From a9b578ec815dd90d076a9f862fa5f97d7c8a869a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Fri, 12 Nov 2021 13:16:59 +0100 Subject: [PATCH 01/47] added doc --- doc/Makefile | 20 + doc/_build/doctrees/environment.pickle | Bin 0 -> 20135 bytes doc/_build/doctrees/index.doctree | Bin 0 -> 4976 bytes .../source/biapol_utilities.data.doctree | Bin 0 -> 3207 bytes .../doctrees/source/biapol_utilities.doctree | Bin 0 -> 7126 bytes .../source/biapol_utilities.label.doctree | Bin 0 -> 3219 bytes doc/_build/doctrees/source/modules.doctree | Bin 0 -> 2717 bytes doc/_build/html/.buildinfo | 4 + doc/_build/html/_sources/index.rst.txt | 20 + .../source/biapol_utilities.data.rst.txt | 10 + .../source/biapol_utilities.label.rst.txt | 10 + .../_sources/source/biapol_utilities.rst.txt | 19 + .../html/_sources/source/modules.rst.txt | 7 + doc/_build/html/_static/alabaster.css | 701 + doc/_build/html/_static/basic.css | 904 ++ doc/_build/html/_static/custom.css | 1 + doc/_build/html/_static/doctools.js | 323 + .../html/_static/documentation_options.js | 12 + doc/_build/html/_static/file.png | Bin 0 -> 286 bytes doc/_build/html/_static/jquery-3.5.1.js | 10872 ++++++++++++++++ doc/_build/html/_static/jquery.js | 2 + doc/_build/html/_static/language_data.js | 297 + doc/_build/html/_static/minus.png | Bin 0 -> 90 bytes doc/_build/html/_static/plus.png | Bin 0 -> 90 bytes doc/_build/html/_static/pygments.css | 82 + doc/_build/html/_static/searchtools.js | 528 + doc/_build/html/_static/underscore-1.13.1.js | 2042 +++ doc/_build/html/_static/underscore.js | 6 + doc/_build/html/genindex.html | 148 + doc/_build/html/index.html | 111 + doc/_build/html/objects.inv | Bin 0 -> 373 bytes doc/_build/html/py-modindex.html | 125 + doc/_build/html/search.html | 119 + doc/_build/html/searchindex.js | 1 + .../html/source/biapol_utilities.data.html | 104 + doc/_build/html/source/biapol_utilities.html | 134 + .../html/source/biapol_utilities.label.html | 104 + doc/_build/html/source/modules.html | 123 + doc/conf.py | 53 + doc/index.rst | 22 + doc/logos/BiaPoL.png | Bin 0 -> 80365 bytes doc/make.bat | 35 + doc/source/biapol_utilities.data.rst | 10 + doc/source/biapol_utilities.label.rst | 10 + doc/source/biapol_utilities.rst | 19 + doc/source/modules.rst | 7 + 46 files changed, 16985 insertions(+) create mode 100644 doc/Makefile create mode 100644 doc/_build/doctrees/environment.pickle create mode 100644 doc/_build/doctrees/index.doctree create mode 100644 doc/_build/doctrees/source/biapol_utilities.data.doctree create mode 100644 doc/_build/doctrees/source/biapol_utilities.doctree create mode 100644 doc/_build/doctrees/source/biapol_utilities.label.doctree create mode 100644 doc/_build/doctrees/source/modules.doctree create mode 100644 doc/_build/html/.buildinfo create mode 100644 doc/_build/html/_sources/index.rst.txt create mode 100644 doc/_build/html/_sources/source/biapol_utilities.data.rst.txt create mode 100644 doc/_build/html/_sources/source/biapol_utilities.label.rst.txt create mode 100644 doc/_build/html/_sources/source/biapol_utilities.rst.txt create mode 100644 doc/_build/html/_sources/source/modules.rst.txt create mode 100644 doc/_build/html/_static/alabaster.css create mode 100644 doc/_build/html/_static/basic.css create mode 100644 doc/_build/html/_static/custom.css create mode 100644 doc/_build/html/_static/doctools.js create mode 100644 doc/_build/html/_static/documentation_options.js create mode 100644 doc/_build/html/_static/file.png create mode 100644 doc/_build/html/_static/jquery-3.5.1.js create mode 100644 doc/_build/html/_static/jquery.js create mode 100644 doc/_build/html/_static/language_data.js create mode 100644 doc/_build/html/_static/minus.png create mode 100644 doc/_build/html/_static/plus.png create mode 100644 doc/_build/html/_static/pygments.css create mode 100644 doc/_build/html/_static/searchtools.js create mode 100644 doc/_build/html/_static/underscore-1.13.1.js create mode 100644 doc/_build/html/_static/underscore.js create mode 100644 doc/_build/html/genindex.html create mode 100644 doc/_build/html/index.html create mode 100644 doc/_build/html/objects.inv create mode 100644 doc/_build/html/py-modindex.html create mode 100644 doc/_build/html/search.html create mode 100644 doc/_build/html/searchindex.js create mode 100644 doc/_build/html/source/biapol_utilities.data.html create mode 100644 doc/_build/html/source/biapol_utilities.html create mode 100644 doc/_build/html/source/biapol_utilities.label.html create mode 100644 doc/_build/html/source/modules.html create mode 100644 doc/conf.py create mode 100644 doc/index.rst create mode 100644 doc/logos/BiaPoL.png create mode 100644 doc/make.bat create mode 100644 doc/source/biapol_utilities.data.rst create mode 100644 doc/source/biapol_utilities.label.rst create mode 100644 doc/source/biapol_utilities.rst create mode 100644 doc/source/modules.rst diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..d4bb2cb --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/_build/doctrees/environment.pickle b/doc/_build/doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..c52137d02840f09bdc1436654e2fb8b22923a814 GIT binary patch literal 20135 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 IWrO~|0euT|K>z>% literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/source/biapol_utilities.data.doctree b/doc/_build/doctrees/source/biapol_utilities.data.doctree new file mode 100644 index 0000000000000000000000000000000000000000..61b302bc575e91985f2a9c0135e685bfdce7a188 GIT binary patch literal 3207 zcmc&$OK%%D5O!=!w)~Loq{*drVg!A-MI|R`4~2Uu(B@`DD4HTYR0%=tQX=c!<(3ay z1{$CR8Xy693;Ub;xB78kvXr>j3J|ay4u><}d^4OsT7Un(wN(7vj?THrrhOX6nT(nC zZatQfO<89ATmRXg{-r;19Yrs+v?^lWEkPsVB8e5t{B!TRLEVT%_p9@3nngy)tU1nG zyv^61`y<|QEh9|Au57uxBSCYS3`sB|j9|JSQ$r7P8lBMz^Wh{8uKvWP!J}G#={o&a zzVMm1YRzjcyLL_ygz(&gNge}i^_&(p_2YiL!bw58o89uI%*Te5hP<~MI zSD>kfj~+aFNJ^w;fe+#Huyl2}xL1JKR~pgXJ6*OTzFFpSmWS> zy2Sj>yYdEG{v|wrSb9F-_X0lr5TNk;NY+RAe}exJ{+}aY{zVaJzf|WvIMjkeORgod zm`$&cq2$T6mfRY=Q(y>SJaVf!70SDVv~d2L!}lWK-F~^>d;d0X4~(b5#cvT&<)XWY zPXe|@73d1uVgBE_ShPP3EFKafGGPem=a(n2sNsG#Ih5mTyahBj?1(i89PxqMsRC%S z!)k=xpL)7o`f4zpYwQmZ4kM%oreuHnkTLRP>#(DtH@v*M3G53wqRzi|-6vXTmb3 zsFBKJff$)KG|jQtEUzK3eTL;mwX`b1YTL+>860xULnbcj?{Dv6Lp0hF#e_z2UY) z)5~m1remp64@o!VIwz4#Lod}Z`C%zx2`ePzLKsf!=7Afl164N}xGlwUsSHWjIZOQM zvfJP^X_hUw$EKhbqA^z2N-ful*~m_CUH5{j3|K)!F`7csF^Wbk1m$15uE=t02+JZF zL(994HRImbJuUFPKfg(sQc@94vp8X>xpr_hGT!Y-Yv!%A3M(kfg`EWx{4dunjm{jX zkM7TJESz+^Api}OIPggjkayb&%_bJF1>lacUdGepZYdT?6_c3d41FexLgN^?HtJ}M z7y*ZfNsg{8rk=N5ms%sqOyrgY7_}YSG$#$~fNCKSXp}0WNieumNC0i7L+)pyTr(R> zGED=YcG)zSnxP%cP8Jl23^^BCl>FQwvCwpsgg`1U*XnBEJ-3BmH26=8_Z5_>)W}#Q zMOSop!WS;lOa&dJH&~02?@hen%@X|F3nc~GWD~G35vef#$?m7Fo3oq%6ox{K3c$94 zWJKY6s0??=jmh=N@$tpQ1-hEyGV4n zE8yBy<7nZUAemjWUteRS#B3p$85h@ZlP0*LW9SG46dUeO*WCf=n3AS48~2GuJ7fNh z+trtup;N-egeUlex~qu{tl!cpMUDMtQPLVP-741Qk|Z*s6|e^pr>GtzuPilSTmXpE zXEw(bVGb&Wo2mu80e561vN0G?_k^3FOK3Zq*V|?3h{Y(=OWeg7Gq83$N+dlaETtkL zn9UR`MvT{Pg=Obq9&zhscR)FUTzE(Y=x&IiYQoTMFpKQrB9O(PNrDJ*m_A;jf6YnD z2?b(U8#jw~C<+WWkgo+{`F+G+@L%{d{?xiokebUJh=oW0#ehE>Sbjfz|AK+$DIU@R zX0~?e&8!_)gJAQ#@j>&<)DIVi0*wdHzYb5rKbVXD*SENy3GB$a?W_DMz}b!jnr}cC zfR&QaL~6Y<3s)tj9&!UdrX!g&lr2<0SP(YaojHr0`qtvm%{lvc43r74&+SE9)y|UJ zK#Pl{4Q2!1A%|=`>a#Lhc XVq-KIISFLkh(j~3`c@ba?5O`Qagy!i literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/source/biapol_utilities.doctree b/doc/_build/doctrees/source/biapol_utilities.doctree new file mode 100644 index 0000000000000000000000000000000000000000..5077ea234e9632231bf98c65feae231e5d09679a GIT binary patch literal 7126 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 .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Georgia, serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: Georgia, serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +div.sphinxsidebar .badge { + border-bottom: none; +} + +div.sphinxsidebar .badge:hover { + border-bottom: none; +} + +/* To address an issue with donation coming after search */ +div.sphinxsidebar h3.donation { + margin-top: 10px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Georgia, serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: Georgia, serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + + +/* relbar */ + +.related { + line-height: 30px; + width: 100%; + font-size: 0.9rem; +} + +.related.top { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.related.bottom { + border-top: 1px solid #EEE; +} + +.related ul { + padding: 0; + margin: 0; + list-style: none; +} + +.related li { + display: inline; +} + +nav#rellinks { + float: right; +} + +nav#rellinks li+li:before { + content: "|"; +} + +nav#breadcrumbs li+li:before { + content: "\00BB"; +} + +/* Hide certain items when printing */ +@media print { + div.related { + display: none; + } +} \ No newline at end of file diff --git a/doc/_build/html/_static/basic.css b/doc/_build/html/_static/basic.css new file mode 100644 index 0000000..912859b --- /dev/null +++ b/doc/_build/html/_static/basic.css @@ -0,0 +1,904 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0.5em; + content: ":"; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/doc/_build/html/_static/custom.css b/doc/_build/html/_static/custom.css new file mode 100644 index 0000000..2a924f1 --- /dev/null +++ b/doc/_build/html/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/doc/_build/html/_static/doctools.js b/doc/_build/html/_static/doctools.js new file mode 100644 index 0000000..8cbf1b1 --- /dev/null +++ b/doc/_build/html/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/doc/_build/html/_static/documentation_options.js b/doc/_build/html/_static/documentation_options.js new file mode 100644 index 0000000..2fa8c97 --- /dev/null +++ b/doc/_build/html/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/doc/_build/html/_static/file.png b/doc/_build/html/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/doc/_build/html/_static/jquery-3.5.1.js b/doc/_build/html/_static/jquery-3.5.1.js new file mode 100644 index 0000000..5093733 --- /dev/null +++ b/doc/_build/html/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Index

+ +
+ B + | M + +
+

B

+ + + +
    +
  • + biapol_utilities + +
  • +
  • + biapol_utilities.data + +
  • +
    +
  • + biapol_utilities.label + +
  • +
+ +

M

+ + +
+ + + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/doc/_build/html/index.html b/doc/_build/html/index.html new file mode 100644 index 0000000..d08cd39 --- /dev/null +++ b/doc/_build/html/index.html @@ -0,0 +1,111 @@ + + + + + + + + + Welcome to BiaPol utilities’s documentation! — BiaPoL utilities documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Welcome to BiaPol utilities’s documentation!

+
+
+
+
+

Indices and tables

+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/doc/_build/html/objects.inv b/doc/_build/html/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..01d227e38c2e77c939cbda96631a5cda1908dbbc GIT binary patch literal 373 zcmV-*0gC=3AX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkHX<<-r zOdxf1X>4h9X=QT?BOq2~a&u{KZaN?eBOp|0Wgv28ZDDC{WMy(7Z)PBLXlZjGW@&6? zAZc?TV{dJ6a%FRKWn>_Ab7^j8AbMxJv1{?kM``=o6B-jhbaoaJoI>@X{U4 z1#@gWs7Jg}uv`%c!?VYn1DtbzzP=M26ir1@P&~&QbI6|vt=sH0P}f&oN#lFd1zFxo z$#JMognL^Kg?gu&t + + + + + + Python Module Index — BiaPoL utilities documentation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Python Module Index

+ +
+ b +
+ + + + + + + + + + + + + +
 
+ b
+ biapol_utilities +
    + biapol_utilities.data +
    + biapol_utilities.label +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/doc/_build/html/search.html b/doc/_build/html/search.html new file mode 100644 index 0000000..d3f9dc1 --- /dev/null +++ b/doc/_build/html/search.html @@ -0,0 +1,119 @@ + + + + + + + + Search — BiaPoL utilities documentation + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/doc/_build/html/searchindex.js b/doc/_build/html/searchindex.js new file mode 100644 index 0000000..6f24459 --- /dev/null +++ b/doc/_build/html/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["index","source/biapol_utilities","source/biapol_utilities.data","source/biapol_utilities.label","source/modules"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,sphinx:56},filenames:["index.rst","source\\biapol_utilities.rst","source\\biapol_utilities.data.rst","source\\biapol_utilities.label.rst","source\\modules.rst"],objects:{"":{biapol_utilities:[1,0,0,"-"]},biapol_utilities:{data:[2,0,0,"-"],label:[3,0,0,"-"]}},objnames:{"0":["py","module","Python module"]},objtypes:{"0":"py:module"},terms:{"function":1,analysi:1,biapol:1,biapolutil:1,bio:1,cluster:1,collect:1,content:4,data:[1,4],develop:1,dfg:1,dresden:1,evalu:1,excel:1,gener:1,group:1,handl:1,imag:1,index:0,k:1,label:[1,4],life:1,maintain:1,manag:1,modul:[0,4],packag:4,page:0,physic:1,point:1,process:1,python:1,represent:1,search:0,subpackag:4,surfac:1,technolog:1,tu:1,util:1,visual:1},titles:["Welcome to BiaPol utilities\u2019s documentation!","biapol_utilities package","biapol_utilities.data package","biapol_utilities.label package","biapol_utilities"],titleterms:{biapol:0,biapol_util:[1,2,3,4],content:[1,2,3],data:2,document:0,indic:0,label:3,modul:[1,2,3],packag:[1,2,3],s:0,subpackag:1,tabl:0,util:0,welcom:0}}) \ No newline at end of file diff --git a/doc/_build/html/source/biapol_utilities.data.html b/doc/_build/html/source/biapol_utilities.data.html new file mode 100644 index 0000000..8506eea --- /dev/null +++ b/doc/_build/html/source/biapol_utilities.data.html @@ -0,0 +1,104 @@ + + + + + + + + + biapol_utilities.data package — BiaPoL utilities documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

biapol_utilities.data package

+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/doc/_build/html/source/biapol_utilities.html b/doc/_build/html/source/biapol_utilities.html new file mode 100644 index 0000000..7f8632a --- /dev/null +++ b/doc/_build/html/source/biapol_utilities.html @@ -0,0 +1,134 @@ + + + + + + + + + biapol_utilities package — BiaPoL utilities documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

biapol_utilities package

+
+

Subpackages

+ +
+
+

Module contents

+

Biapol utilities for Python +biapol-utilities (a.k.a. biapolutils) is a collection of utility functions +for image processing and visualization that is maintained by the Bio-image Analysis +Technology Development Group at DFG Cluster of Excellence “Physics of Life”, TU Dresden

+
+

Subpackages

+
+
label

Label handling and evaluation

+
+
surface

Manage surfaces and point representations

+
+
utilities

Generic utilities.

+
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/doc/_build/html/source/biapol_utilities.label.html b/doc/_build/html/source/biapol_utilities.label.html new file mode 100644 index 0000000..6287635 --- /dev/null +++ b/doc/_build/html/source/biapol_utilities.label.html @@ -0,0 +1,104 @@ + + + + + + + + + biapol_utilities.label package — BiaPoL utilities documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

biapol_utilities.label package

+
+

Module contents

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/doc/_build/html/source/modules.html b/doc/_build/html/source/modules.html new file mode 100644 index 0000000..2509bb9 --- /dev/null +++ b/doc/_build/html/source/modules.html @@ -0,0 +1,123 @@ + + + + + + + + + biapol_utilities — BiaPoL utilities documentation + + + + + + + + + + + + + + + + + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 0000000..0ab9181 --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,53 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'BiaPoL utilities' +copyright = '2021, Robert Haase, Johannes Müller, Marcelo Zoccoler' +author = 'Robert Haase, Johannes Müller, Marcelo Zoccoler' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.napoleon', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] \ No newline at end of file diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000..81b9fcf --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,22 @@ +.. BiaPol utilities documentation master file, created by + sphinx-quickstart on Fri Nov 12 12:12:24 2021. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to BiaPol utilities's documentation! +============================================ + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/logos/BiaPoL.png b/doc/logos/BiaPoL.png new file mode 100644 index 0000000000000000000000000000000000000000..60e8b161d202538113aa82da228eb260e9848544 GIT binary patch literal 80365 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 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/doc/source/biapol_utilities.data.rst b/doc/source/biapol_utilities.data.rst new file mode 100644 index 0000000..6d60e1d --- /dev/null +++ b/doc/source/biapol_utilities.data.rst @@ -0,0 +1,10 @@ +biapol\_utilities.data package +============================== + +Module contents +--------------- + +.. automodule:: biapol_utilities.data + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/biapol_utilities.label.rst b/doc/source/biapol_utilities.label.rst new file mode 100644 index 0000000..329c67a --- /dev/null +++ b/doc/source/biapol_utilities.label.rst @@ -0,0 +1,10 @@ +biapol\_utilities.label package +=============================== + +Module contents +--------------- + +.. automodule:: biapol_utilities.label + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/biapol_utilities.rst b/doc/source/biapol_utilities.rst new file mode 100644 index 0000000..1ee4738 --- /dev/null +++ b/doc/source/biapol_utilities.rst @@ -0,0 +1,19 @@ +biapol\_utilities package +========================= + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + biapol_utilities.data + biapol_utilities.label + +Module contents +--------------- + +.. automodule:: biapol_utilities + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/modules.rst b/doc/source/modules.rst new file mode 100644 index 0000000..a2c59ae --- /dev/null +++ b/doc/source/modules.rst @@ -0,0 +1,7 @@ +biapol_utilities +================ + +.. toctree:: + :maxdepth: 4 + + biapol_utilities From 522395086788c69b43a84623356acbbfc8d5284d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Fri, 12 Nov 2021 14:35:06 +0100 Subject: [PATCH 02/47] updated doc --- doc/_build/doctrees/environment.pickle | Bin 20135 -> 21323 bytes doc/_build/doctrees/index.doctree | Bin 4976 -> 4448 bytes doc/_build/doctrees/source/modules.doctree | Bin 2717 -> 2754 bytes doc/_build/doctrees/source/setup.doctree | Bin 0 -> 2348 bytes doc/_build/html/.buildinfo | 2 +- doc/_build/html/_sources/index.rst.txt | 11 +- .../html/_sources/source/modules.rst.txt | 5 +- doc/_build/html/_sources/source/setup.rst.txt | 7 ++ doc/_build/html/genindex.html | 4 + doc/_build/html/index.html | 25 ++++ doc/_build/html/objects.inv | Bin 373 -> 392 bytes doc/_build/html/py-modindex.html | 4 + doc/_build/html/search.html | 4 + doc/_build/html/searchindex.js | 2 +- .../html/source/biapol_utilities.data.html | 24 ++++ doc/_build/html/source/biapol_utilities.html | 25 ++++ .../html/source/biapol_utilities.label.html | 24 ++++ doc/_build/html/source/modules.html | 17 ++- doc/_build/html/source/setup.html | 113 ++++++++++++++++++ doc/conf.py | 6 +- doc/index.rst | 9 +- doc/source/modules.rst | 5 +- doc/source/setup.rst | 7 ++ 23 files changed, 273 insertions(+), 21 deletions(-) create mode 100644 doc/_build/doctrees/source/setup.doctree create mode 100644 doc/_build/html/_sources/source/setup.rst.txt create mode 100644 doc/_build/html/source/setup.html create mode 100644 doc/source/setup.rst diff --git a/doc/_build/doctrees/environment.pickle b/doc/_build/doctrees/environment.pickle index c52137d02840f09bdc1436654e2fb8b22923a814..ab0d42fea6ca12ad630e4ae95d9e5903d5a35afe 100644 GIT binary patch literal 21323 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 literal 20135 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 literal 4976 zcmds5U5gx98J=X)pYuK0M3zmk_F~Osce*Eudm(e<#|A-y<07()Frjj~>U5toQ(dQ0 z=hRHkg}4hw5Po~r7u?lGN+cZT%P=RNQFdY|Y0 z>Q5S<^Xn__pWV`lknyC?!Z21L*ST$nD#*q>Hu-1y-B0r$ET96#0`%wJfpk|JjILTsfocF_jt8P4nzorRAa8Q9o(-7oGGkH+ z8-h8+lvNpOu)?;2h-nQWzBghvF21$HESU`kEI3X1(CKt0(pkTy(`vv1&Vh#hVgKLS3jz3J*34qea#0`Jog#MI($Jppt z#vz~dQ*Cm4Es`mvil$N2o&Q)u0^8XS)lsc z1!;C{f61c1e)6kJ%Vr>a8K$@|z9d$~og;Dg2snr@!1&@#knt^iZsYSseBOSXXW|`k z0QLPsUF?awk6P}DZSo0~#bNCs#T&&6%wCZF^4!Y~5;twbSrgcU9w}U$uwR#P5M?1J z$997Dm`y^S7?D4^3YNf4$;`I%0sIZ?^dXQKMQV`0uuUPu5JBdJ-6(gN3fgft9`KZh z`J)xvb$DnMM;FlTB39KdK*Q=3@e!Hhp}6DB(1BULzGyqURldA;p0Xt2Y0ehS`PF%I z!u)({e*4~e!GxYsy@GMQDdT#&SCQ8RJ#1Z~W%tWvM4)2XEK*)35UZp6F0Qk>fbM%m z+@6v4UL~-*--<&SApWvA^b8viEG~-e{Ku&o=`_xH`rnZ*u3c-}k#22}MTo>kCOT)*tX}fiZIC1!7#A8RXCso|-AQrI^fD$!r@!Y*<#jYnDZ;eO(1gkGA zbZk?`&gp9xDc0`Tc6C-hvp^FT_~pwjuxGEigY2p{A-n*8dvq{gBv6ihez8crx{_^T z9jKCv?;!Qk*D+F2E`DQM7@3O%L2{M0wrlvyCrKm&X~2D&K4)p1KX>bpFGn1qZT1-A z|IbSP@8TME*)>S{CpG0Cze@Q>*zwaD=I{*hY)ZTm!?6M+2)ZSPKdt7)?;UDCUl@PB zFa|Q!4hzWqX$dmo*RKW2AD2DwWuW}|^+6H8t=+y3#dR3&56cd(LqW>FdzJE1C^iar z(wwD%xCF%C7l0_nGa!ob4wA21zW~F({&yJux$JQ-f#IZiWd&*Lb=?ClX50SiAM)Fxk zsb=eOereu7fL?aBveFWJWP&SpGssdZ1N~BdWY;T+3#mu8t+_FXzUU}+DDAlpVVJr! zkMP+1h(#H4&ouTP9N7+nE>D?JX^ugN9sni(IKg18I0ktmKE<$G4zo1EXagzRr(%+3 zaa@Da|3z+hhp5|QWq57!(G|NvwH@jQe==0*IEQ3Yqh3k;vTf1W@~uL`BTkKs_Rpme zepS-q#BxDd}l}%T$XgX}z9X^q;m0>2+l~ThtLO#ewIBt`IHf1X8 z%h?!`j!97q)1wf}H)Wh;#^-TB!E=OaDKo>~S9)6F`>pv&pQouxeF0KLs9r#Gye&Wy z*ixC9-=*Pp$?ffhnT0J*J|@@NEcTt}Pwl|zUvRZ;?vPi3 zIq?WYjN};U{@dGk>}J9fpK1X3B0>Rfj-n?4-*I*g@FjzQ-B(q~~RmT{m@I!#)X6TL) zW*p&&4#E?BD5R>tZEu5-V}I(L)9d?1|M$Xf>kBmB6JN-Yi12aUnIht^>oI-<@SkSz zY7H}8cjIE{M=D@tmvK7~s0;(ZUU(a9>uqy%9w9vS0%r-1`s#(f5k!ie`W$6i({i;E^B~ z1#bEY!7mCl*B9;JAdtl%PJ#$%n5dt&yK~Z_b%q$b4W|Pt7OCroyhXy|`<^%z;^aPD z_oR(XKu$%b*fvmJGa04Er??Gjm5pn8MK9n4gnfmkN|~ppwM`@ zo*o&Z^+75B3|4!Ve-{i#CjpGD(y IWrO~|0euT|K>z>% diff --git a/doc/_build/doctrees/source/modules.doctree b/doc/_build/doctrees/source/modules.doctree index 48d6ffdb637020de6c46e1bde2f442169ed3d020..b9199a31f96616111f1be34c9e6431a87d0f2c84 100644 GIT binary patch delta 139 zcmbO$dPtO|fpzNki7cILqDBTrhVc{o6rrq*8*&&KH73h2$!hua@D%5l7A2?Z7pIn# z7EEcIlG?+QnU|bXnv$B9nUh*PC3cENhC_x^>SRBrM^OEn4VgWd7#lZNv2J3PiOz^9 g?%~W!%uOw+EC8ynostplSDc{;q$4(aaE3Ah0FeVPmjD0& delta 101 zcmX>kI#-mXfpzMni7cIr0uv`IG74Hq)$ diff --git a/doc/_build/doctrees/source/setup.doctree b/doc/_build/doctrees/source/setup.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a25b2452447011249466eb1c982199f040503ad9 GIT binary patch literal 2348 zcmZ8jO>Y}F5KZjJvTRwllcty0ZGs|5gT_{B^ibs32I#@4Q4~edg9?ILQX*?Ex#fo~ z9|E+8013cb*#Fzd-PPKX0mIA3;mq*Oo1y>d{r7Beul|Yqt`br&PAOyBFz!;^W~K-w z*FJqpFaJ&N(${fd>9sS#7Cgm!uqcF7%yOOnOmURWy;SbBJ>Pe{@Y3k+xaf&3(f>1v zLF{?y6~D6+hmQMDJuM9j*l5ij{KgkK{MzpORHp-fkK$HEk$_L)Fb+tUvDl1TZK4

UJ@u#iix5Y!hPN(|O)X zVqZKFLvbWF#c}-U?VHKlmNhr|LDI^o$uHLY1t#3&?Dg5VWLkqHGbO#`Zi1XAO{$Zc zf>Y~on=j5ckgxa>Ns4Dks-fqkrH6{IK;!ccU(!a!3*ax2p!i1YAhFFRG4X2M;nKnK zKu4E&mCxRfqaxT$Ea_+*E|G@LxQ%qZ)N@GXu&e#d8tu7eDQ^8vRRE7m@reD4IGA(I zE%nAGEEq)@JS{6McAGE+zAv%dX_vt&toFPqNTxsUB3uu7*_#v}&W!Qecz$Q|{C?ca z!qcH7iKdtZlSm#p{P9;%8GQV1FJP4Avmk4$`1Ey1k`GmYkvz>jt6GQqRe_a z;ET#QPVSzpB~o~DC7o>axlfpMbgJ@2+ARCaZV<2H5SMY#KdomRB-5IanN-dA_&k3h zh~qZfpuE`|L%nw~N4q8Td6-)Yve9#>P{~sI^z*@sII4I>Knh1A7BykRj7%wV&z%vU z3hyiTW<0*WzCNvPyfFII*!h_8t1&FyIK{{LM4bpu5YJ1L$)haWz)zmP{tmp3?5tP| zlabpnN6RqY7|eIc{j3fne5nv(;OP_%#Jou7+wmB3EJ@dyUHZgTSsx$cfxFS3E{KqG zq3{doK2RpBe&|Yy9{W3>r5$K`RIi&QQKq0RvB!m==pK~4X*F8QSy)u>|KH-X0gq&`ZKgDiy)|XnFlqe2AM| zU*&ftZa32b?Fey6%_QXRiKlkXF>NrW4-p7r@fiCM0?V(+JIt>Yw0UU&!`rM|Y~`lF zBL%#l!RA|>iLr}=4EUQ0WW7t`?81p>_&XLu7x(TKpgz4IZef%H zvA6>sf&Pyz{t1_VpMHgo@vi_n1CO`E_-O)mqhJNz?clm(yHXb_Fm#}q=W6Y+JgwTs K&M#<~p8gNz*R0h5 literal 0 HcmV?d00001 diff --git a/doc/_build/html/.buildinfo b/doc/_build/html/.buildinfo index 28fa03a..de2a8ce 100644 --- a/doc/_build/html/.buildinfo +++ b/doc/_build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: ce2b8b64d5e7aa76a57958c38370f3da +config: d267cc1b5df3146c7b699d60ba623aed tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/doc/_build/html/_sources/index.rst.txt b/doc/_build/html/_sources/index.rst.txt index 6cd54a1..905ee29 100644 --- a/doc/_build/html/_sources/index.rst.txt +++ b/doc/_build/html/_sources/index.rst.txt @@ -1,15 +1,14 @@ -.. BiaPol utilities documentation master file, created by - sphinx-quickstart on Fri Nov 12 12:12:24 2021. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - Welcome to BiaPol utilities's documentation! ============================================ .. toctree:: - :maxdepth: 2 + :maxdepth: 4 :caption: Contents: + source/modules + + + Indices and tables diff --git a/doc/_build/html/_sources/source/modules.rst.txt b/doc/_build/html/_sources/source/modules.rst.txt index a2c59ae..30021ce 100644 --- a/doc/_build/html/_sources/source/modules.rst.txt +++ b/doc/_build/html/_sources/source/modules.rst.txt @@ -1,7 +1,8 @@ -biapol_utilities -================ +2021_biapol_utilities +===================== .. toctree:: :maxdepth: 4 biapol_utilities + setup diff --git a/doc/_build/html/_sources/source/setup.rst.txt b/doc/_build/html/_sources/source/setup.rst.txt new file mode 100644 index 0000000..552eb49 --- /dev/null +++ b/doc/_build/html/_sources/source/setup.rst.txt @@ -0,0 +1,7 @@ +setup module +============ + +.. automodule:: setup + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/_build/html/genindex.html b/doc/_build/html/genindex.html index e409f53..b54dffa 100644 --- a/doc/_build/html/genindex.html +++ b/doc/_build/html/genindex.html @@ -102,6 +102,10 @@

BiaPoL utilities

Navigation

+

Contents:

+

Related Topics

diff --git a/doc/_build/html/index.html b/doc/_build/html/index.html index d08cd39..8567f2a 100644 --- a/doc/_build/html/index.html +++ b/doc/_build/html/index.html @@ -15,6 +15,7 @@ + @@ -34,6 +35,25 @@

Welcome to BiaPol utilities’s documentation!

@@ -62,11 +82,16 @@

BiaPoL utilities

Navigation

+

Contents:

+ diff --git a/doc/_build/html/objects.inv b/doc/_build/html/objects.inv index 01d227e38c2e77c939cbda96631a5cda1908dbbc..13f8f13f2ed641d05a6bacad326122398f087f23 100644 GIT binary patch delta 273 zcmV+s0q*|w0*C{UfPb-WgD?<=cR$5d=}Mbq%-F3%C8P`;BV(U}RfDbgEQPJF(bwyf zG;k$>0D%qN{r~st%%2(QojpV{){wyfzSSa2{u6hISFJQ4WAdEKRBL41x5HVaW#CX(NaC`cvFw+JC89)KPq*RjxoF2X98E z&cZeK_xmTn#SsfENs@8plepxMg!(FJ7fk)&lQ_P!ow21A<*w|z1Im-i`$nFzXV3do z9#Kp@VE6P#e;)=$FV)urFjry${n`kaXw^&(U%nvdRuz~kTtA8nHTFdR8-{Jy+s)yg X*fIiA^dp33&I*2(FjD*h>7rJ$vucSs delta 253 zcmV)77|77Epd}&}DvL%$1NGKx^m;u> zULAHYXZR|ByRSW9*Td=eJNGARVurK%!~ks zf~%Z5aM>
-
-

Compare-labels: Feature-wise

-

It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops.

-
-
[12]:
-
-
-
-properties = ['label', 'area', 'eccentricity', 'orientation']
-features_gt = measure.regionprops_table(ground_truth, properties=properties)
-features_seg = measure.regionprops_table(segmented, properties=properties)
-
-features_gt = pd.DataFrame(features_gt)
-features_seg = pd.DataFrame(features_seg)
-features_gt
-
-
-
-
-
[12]:
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
-

63 rows × 4 columns

-
-
-

Visualize as histograms

-
-
[13]:
-
-
-
-fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))
-
-ax_idx = 0
-for idx, prop in enumerate(properties):
-    if  prop == 'label':
-        continue
-
-    axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)
-    axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)
-    axes[ax_idx].set_xlabel(prop)
-    ax_idx += 1
-
-axes[0].legend()
-axes[0].set_ylabel('# Occurrences')
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[13]:
-
-
-
-
-Text(0, 0.5, '# Occurrences')
-
-
-
-
[ ]:
-
-
-
-
-
-
-
-
- - - -
- - - - -
- - - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/notebooks/label/Compare_segmentations.ipynb b/doc/_build/html/_include/notebooks/label/Compare_segmentations.ipynb deleted file mode 100644 index b694e2f..0000000 --- a/doc/_build/html/_include/notebooks/label/Compare_segmentations.ipynb +++ /dev/null @@ -1,5614 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "9f0d8ccf", - "metadata": {}, - "source": [ - "# Quantitative segmentation quality estimation\n", - "\n", - "Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "89205b6d", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import biapol_utilities as biau\n", - "from skimage import io, measure, segmentation\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", - "import pandas as pd\n", - "\n", - "%matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "id": "a63045b4", - "metadata": {}, - "source": [ - "## Input data\n", - "First, let's generate some example data!" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "db9c5fe0", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biau.data.blobs()" - ] - }, - { - "cell_type": "markdown", - "id": "2c0c8418", - "metadata": {}, - "source": [ - "Let's segment this and take it as a ground truth image:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "2ae66de8", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Ground truth')" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "threshold = 128\n", - "imageA = (blobs > threshold).astype(np.uint8)\n", - "ground_truth = measure.label(imageA)\n", - "\n", - "plt.imshow(ground_truth)\n", - "plt.title('Ground truth')" - ] - }, - { - "cell_type": "markdown", - "id": "f7f4c0be", - "metadata": {}, - "source": [ - "Next, we shuffle the labels and expand them a bit:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "2b8dc27c", - "metadata": {}, - "outputs": [], - "source": [ - "# First, shuffle randomly\n", - "label_shuffle = np.arange(1, ground_truth.max()+1, 1)\n", - "np.random.shuffle(label_shuffle)\n", - "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", - "segmented = label_shuffle[ground_truth]" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "279f3e2c", - "metadata": {}, - "outputs": [], - "source": [ - "# Second, expand the labels a bit\n", - "segmented = segmentation.expand_labels(segmented, 5)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "eb0b69c2", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Segmentation')" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "\n", - "axes[0].imshow(ground_truth)\n", - "axes[0].set_title('Ground truth')\n", - "\n", - "axes[1].imshow(segmented)\n", - "axes[1].set_title('Segmentation')" - ] - }, - { - "cell_type": "markdown", - "id": "dd726a7c", - "metadata": {}, - "source": [ - "## Re-match labels\n", - "\n", - "Next, use the label-matching from `biapol_utilities` to assign correct labels to both images" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "8007d578", - "metadata": {}, - "outputs": [], - "source": [ - "segmented = biau.label.match_labels(ground_truth, segmented)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "23496dad", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Segmentation')" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "\n", - "axes[0].imshow(ground_truth)\n", - "axes[0].set_title('Ground truth')\n", - "\n", - "axes[1].imshow(segmented)\n", - "axes[1].set_title('Segmentation')" - ] - }, - { - "cell_type": "markdown", - "id": "1e1d39a4", - "metadata": {}, - "source": [ - "## Compare labels: Labelwise Jaccard-index\n", - "\n", - "Lastly, we calculate the *label-wise Jaccard index* to measure the intersection over union (IoU) between corresponding pairs of labels." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "7641d30b", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
\n", - "

68 rows × 3 columns

\n", - "
" - ], - "text/plain": [ - " label jaccard_score dice_score\n", - "0 0 0.496847 0.663858\n", - "1 1 0.518102 0.682566\n", - "2 2 0.470130 0.639576\n", - "3 3 0.623552 0.768133\n", - "4 4 0.602546 0.751986\n", - ".. ... ... ...\n", - "63 63 0.262857 0.416290\n", - "64 64 0.000000 0.000000\n", - "65 65 0.000000 0.000000\n", - "66 66 0.000000 0.000000\n", - "67 67 0.000000 0.000000\n", - "\n", - "[68 rows x 3 columns]" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "result = biau.label.compare_labels(ground_truth, segmented)\n", - "result" - ] - }, - { - "cell_type": "markdown", - "id": "3f218dd4", - "metadata": {}, - "source": [ - "Let's also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "fab77a34", - "metadata": {}, - "outputs": [], - "source": [ - "LUT_jaccard = result['jaccard_score'].to_numpy()\n", - "LUT_dice = result['dice_score'].to_numpy()\n", - "\n", - "# set segmentation quality of background to zero\n", - "LUT_jaccard[0] = np.nan\n", - "LUT_dice[0] = np.nan\n", - "\n", - "# create score map\n", - "JI_map = LUT_jaccard[segmented]\n", - "DI_map = LUT_dice[segmented]" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "ca62489c", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "(-0.5, 255.5, 253.5, -0.5)" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))\n", - "fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)\n", - "\n", - "\n", - "# Plot ground truth\n", - "axes[0, 0].imshow(ground_truth)\n", - "axes[0, 0].set_title('Ground truth')\n", - "\n", - "# Plot segmentation\n", - "axes[0, 1].imshow(segmented)\n", - "axes[0, 1].set_title('Segmentation')\n", - "\n", - "# Plot overlay\n", - "axes[0, 2].imshow(ground_truth)\n", - "axes[0, 2].imshow(segmented, alpha=0.5)\n", - "axes[0, 2].set_title('Overlay')\n", - "\n", - "# Plot Jaccard index map\n", - "im = axes[1, 0].imshow(JI_map, cmap='inferno_r')\n", - "axes[1, 0].set_title('Jaccard score')\n", - "cbar = fig.colorbar(im, ax=axes[1, 0])\n", - "\n", - "# Plot Dice score map\n", - "im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')\n", - "axes[1, 1].set_title('Dice score')\n", - "cbar2 = fig.colorbar(im2, ax=axes[1, 1])\n", - "\n", - "axes[-1, -1].axis('off')" - ] - }, - { - "cell_type": "markdown", - "id": "1dc2ca58", - "metadata": {}, - "source": [ - "## Compare-labels: Feature-wise\n", - "It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "5f6cc904", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
\n", - "

63 rows × 4 columns

\n", - "
" - ], - "text/plain": [ - " label area eccentricity orientation\n", - "0 1 415 0.878888 -0.433915\n", - "1 2 181 0.822705 -1.513862\n", - "2 3 646 0.386542 -0.079653\n", - "3 4 426 0.324798 -0.400592\n", - "4 5 465 0.780472 -0.044317\n", - ".. ... ... ... ...\n", - "58 59 1 0.000000 0.785398\n", - "59 60 87 0.969263 -1.560717\n", - "60 61 73 0.951468 -1.567605\n", - "61 62 49 0.942191 -1.554054\n", - "62 63 46 0.976786 1.538848\n", - "\n", - "[63 rows x 4 columns]" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "properties = ['label', 'area', 'eccentricity', 'orientation']\n", - "features_gt = measure.regionprops_table(ground_truth, properties=properties)\n", - "features_seg = measure.regionprops_table(segmented, properties=properties)\n", - "\n", - "features_gt = pd.DataFrame(features_gt)\n", - "features_seg = pd.DataFrame(features_seg)\n", - "features_gt" - ] - }, - { - "cell_type": "markdown", - "id": "ec29004b", - "metadata": {}, - "source": [ - "Visualize as histograms" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "e9652f8d", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0, 0.5, '# Occurrences')" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))\n", - "\n", - "ax_idx = 0\n", - "for idx, prop in enumerate(properties):\n", - " if prop == 'label':\n", - " continue\n", - " \n", - " axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)\n", - " axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)\n", - " axes[ax_idx].set_xlabel(prop)\n", - " ax_idx += 1\n", - " \n", - "axes[0].legend()\n", - "axes[0].set_ylabel('# Occurrences')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "185d4c1d", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_include/notebooks/label/match_labels.html b/doc/_build/html/_include/notebooks/label/match_labels.html deleted file mode 100644 index 2d63afe..0000000 --- a/doc/_build/html/_include/notebooks/label/match_labels.html +++ /dev/null @@ -1,3472 +0,0 @@ - - - - - - - - - Matching labels — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- - - -
-

Matching labels

-

This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image.

-
-
[3]:
-
-
-
-import os
-import biapol_utilities as biau
-from skimage import io, measure, filters
-import numpy as np
-import matplotlib.pyplot as plt
-from datetime import datetime
-
-%matplotlib notebook
-
-
-
-
-

Load data

-

First, we load the example blobs image and threshold it to create a label map.

-
-
[4]:
-
-
-
-blobs = biau.data.blobs()
-
-
-
-
-
[5]:
-
-
-
-threshold = 128
-imageA = (blobs > threshold).astype(np.uint8)
-imageA_labelled = measure.label(imageA)
-
-plt.imshow(imageA_labelled)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[5]:
-
-
-
-
-<matplotlib.image.AxesImage at 0x29c86bdabe0>
-
-
-

Let’s create a second version of this image in which we shuffle the labels:

-
-
[6]:
-
-
-
-label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)
-np.random.shuffle(label_shuffle)
-label_shuffle = np.append(np.asarray([0]), label_shuffle)  # append 0 at start of array - we don't want to shuffle background
-
-imageB_labelled = label_shuffle[imageA_labelled]
-
-
-
-

Both images are not identical!

-
-
[7]:
-
-
-
-fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
-axes[0].imshow(imageA_labelled)
-axes[0].set_title('Reference image')
-axes[1].imshow(imageB_labelled)
-axes[1].set_title('Shuffled image')
-
-print(f'Number of labels in imageA: {imageA_labelled.max()}')
-print(f'Number of labels in imageB: {imageB_labelled.max()}')
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Number of labels in imageA: 63
-Number of labels in imageB: 63
-
-
-

Match labels and track time

-
-
[8]:
-
-
-
-t0 = datetime.now()
-output = biau.label.match_labels(imageA_labelled, imageB_labelled)
-t1 = datetime.now()
-print(f'Took {(t1-t0).seconds*1000} ms')
-
-
-
-
-
-
-
-
-Took 0 ms
-
-
-

Visualize

-
-
[9]:
-
-
-
-fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
-axes[0].imshow(imageA_labelled)
-axes[0].set_title('Reference image')
-axes[1].imshow(output)
-axes[1].set_title('Relabelled image')
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[9]:
-
-
-
-
-Text(0.5, 1.0, 'Relabelled image')
-
-
-
-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/notebooks/label/match_labels.ipynb b/doc/_build/html/_include/notebooks/label/match_labels.ipynb deleted file mode 100644 index 181425a..0000000 --- a/doc/_build/html/_include/notebooks/label/match_labels.ipynb +++ /dev/null @@ -1,3198 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "e5db44ea", - "metadata": {}, - "source": [ - "## Matching labels\n", - "This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "d1ca8e7a", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import biapol_utilities as biau\n", - "from skimage import io, measure, filters\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from datetime import datetime\n", - "\n", - "%matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "id": "ee62539b", - "metadata": {}, - "source": [ - "### Load data\n", - "First, we load the example blobs image and threshold it to create a label map. " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "7fe70350", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biau.data.blobs()" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "909ce3b2", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "threshold = 128\n", - "imageA = (blobs > threshold).astype(np.uint8)\n", - "imageA_labelled = measure.label(imageA)\n", - "\n", - "plt.imshow(imageA_labelled)" - ] - }, - { - "cell_type": "markdown", - "id": "1cbf5ae3", - "metadata": {}, - "source": [ - "Let's create a second version of this image in which we shuffle the labels:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "29986d79", - "metadata": {}, - "outputs": [], - "source": [ - "label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)\n", - "np.random.shuffle(label_shuffle)\n", - "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", - "\n", - "imageB_labelled = label_shuffle[imageA_labelled]" - ] - }, - { - "cell_type": "markdown", - "id": "1393dfb7", - "metadata": {}, - "source": [ - "Both images are not identical!" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "1ff3c80c", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of labels in imageA: 63\n", - "Number of labels in imageB: 63\n" - ] - } - ], - "source": [ - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "axes[0].imshow(imageA_labelled)\n", - "axes[0].set_title('Reference image')\n", - "axes[1].imshow(imageB_labelled)\n", - "axes[1].set_title('Shuffled image')\n", - "\n", - "print(f'Number of labels in imageA: {imageA_labelled.max()}')\n", - "print(f'Number of labels in imageB: {imageB_labelled.max()}')" - ] - }, - { - "cell_type": "markdown", - "id": "7a38be04", - "metadata": {}, - "source": [ - "Match labels and track time" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "79f0cf74", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Took 0 ms\n" - ] - } - ], - "source": [ - "t0 = datetime.now()\n", - "output = biau.label.match_labels(imageA_labelled, imageB_labelled)\n", - "t1 = datetime.now()\n", - "print(f'Took {(t1-t0).seconds*1000} ms')" - ] - }, - { - "cell_type": "markdown", - "id": "a8710824", - "metadata": {}, - "source": [ - "Visualize" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "84ed2639", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Relabelled image')" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "axes[0].imshow(imageA_labelled)\n", - "axes[0].set_title('Reference image')\n", - "axes[1].imshow(output)\n", - "axes[1].set_title('Relabelled image')" - ] - } - ], - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_include/notebooks/label/visualize_labels.html b/doc/_build/html/_include/notebooks/label/visualize_labels.html deleted file mode 100644 index 6665eb1..0000000 --- a/doc/_build/html/_include/notebooks/label/visualize_labels.html +++ /dev/null @@ -1,414 +0,0 @@ - - - - - - - - - Labels visualized in colours — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- - - -
-
[1]:
-
-
-
-import biapol_utilities as biao
-from skimage.measure import label
-from skimage.io import imshow
-
-
-
-
-
[2]:
-
-
-
-blobs = biao.blobs()
-labels = label(blobs > 128)
-
-
-
-
-

Labels visualized in colours

-

biapol_utilities provided a standardized color map for visualizing labels in:

-
-
[4]:
-
-
-
-imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())
-
-
-
-
-
[4]:
-
-
-
-
-<matplotlib.image.AxesImage at 0x17fe4272220>
-
-
-
-
-
-
-../../../_images/_include_notebooks_label_visualize_labels_3_1.png -
-
-
-
[ ]:
-
-
-
-
-
-
-
-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/notebooks/label/visualize_labels.ipynb b/doc/_build/html/_include/notebooks/label/visualize_labels.ipynb deleted file mode 100644 index 9924ff8..0000000 --- a/doc/_build/html/_include/notebooks/label/visualize_labels.ipynb +++ /dev/null @@ -1,98 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "803a884d", - "metadata": {}, - "outputs": [], - "source": [ - "import biapol_utilities as biao\n", - "from skimage.measure import label\n", - "from skimage.io import imshow" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "af876b71", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biao.blobs()\n", - "labels = label(blobs > 128)" - ] - }, - { - "cell_type": "markdown", - "id": "d9ded05a", - "metadata": {}, - "source": [ - "# Labels visualized in colours\n", - "`biapol_utilities` provided a standardized color map for visualizing labels in:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "5c3f2337", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "867149ee", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_sources/_include/API_reference.rst.txt b/doc/_build/html/_sources/_include/API_reference.rst.txt index 3073ec6..21cf6f0 100644 --- a/doc/_build/html/_sources/_include/API_reference.rst.txt +++ b/doc/_build/html/_sources/_include/API_reference.rst.txt @@ -1,5 +1,5 @@ -API reference -============================= +API Reference +============= The label module @@ -8,6 +8,8 @@ The label module .. currentmodule:: biapol_utilities .. autosummary:: + :recursive: + :toctree: generated label.compare_labels label.intersection_over_union_matrix diff --git a/doc/_build/html/_sources/_include/Examples.rst.txt b/doc/_build/html/_sources/_include/Examples.rst.txt index 1626a5c..de920ec 100644 --- a/doc/_build/html/_sources/_include/Examples.rst.txt +++ b/doc/_build/html/_sources/_include/Examples.rst.txt @@ -8,8 +8,8 @@ Label module :titlesonly: :maxdepth: 0 - Match labels - Compare segmentations + Match labels <../../notebooks/label/match_labels.ipynb> + Compare segmentations <../../notebooks/label/Compare_segmentations.ipynb> Data module ------------------ diff --git a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.compare_labels.rst.txt b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.compare_labels.rst.txt new file mode 100644 index 0000000..286bf6d --- /dev/null +++ b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.compare_labels.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.compare\_labels +======================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: compare_labels \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst.txt b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst.txt new file mode 100644 index 0000000..3b66942 --- /dev/null +++ b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.intersection\_over\_union\_matrix +========================================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: intersection_over_union_matrix \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels_stack.rst.txt b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels_stack.rst.txt new file mode 100644 index 0000000..2f71b54 --- /dev/null +++ b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels_stack.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.match\_labels\_stack +============================================ + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: match_labels_stack \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt b/doc/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt deleted file mode 100644 index b694e2f..0000000 --- a/doc/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt +++ /dev/null @@ -1,5614 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "9f0d8ccf", - "metadata": {}, - "source": [ - "# Quantitative segmentation quality estimation\n", - "\n", - "Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "89205b6d", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import biapol_utilities as biau\n", - "from skimage import io, measure, segmentation\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", - "import pandas as pd\n", - "\n", - "%matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "id": "a63045b4", - "metadata": {}, - "source": [ - "## Input data\n", - "First, let's generate some example data!" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "db9c5fe0", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biau.data.blobs()" - ] - }, - { - "cell_type": "markdown", - "id": "2c0c8418", - "metadata": {}, - "source": [ - "Let's segment this and take it as a ground truth image:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "2ae66de8", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Ground truth')" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "threshold = 128\n", - "imageA = (blobs > threshold).astype(np.uint8)\n", - "ground_truth = measure.label(imageA)\n", - "\n", - "plt.imshow(ground_truth)\n", - "plt.title('Ground truth')" - ] - }, - { - "cell_type": "markdown", - "id": "f7f4c0be", - "metadata": {}, - "source": [ - "Next, we shuffle the labels and expand them a bit:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "2b8dc27c", - "metadata": {}, - "outputs": [], - "source": [ - "# First, shuffle randomly\n", - "label_shuffle = np.arange(1, ground_truth.max()+1, 1)\n", - "np.random.shuffle(label_shuffle)\n", - "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", - "segmented = label_shuffle[ground_truth]" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "279f3e2c", - "metadata": {}, - "outputs": [], - "source": [ - "# Second, expand the labels a bit\n", - "segmented = segmentation.expand_labels(segmented, 5)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "eb0b69c2", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Segmentation')" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "\n", - "axes[0].imshow(ground_truth)\n", - "axes[0].set_title('Ground truth')\n", - "\n", - "axes[1].imshow(segmented)\n", - "axes[1].set_title('Segmentation')" - ] - }, - { - "cell_type": "markdown", - "id": "dd726a7c", - "metadata": {}, - "source": [ - "## Re-match labels\n", - "\n", - "Next, use the label-matching from `biapol_utilities` to assign correct labels to both images" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "8007d578", - "metadata": {}, - "outputs": [], - "source": [ - "segmented = biau.label.match_labels(ground_truth, segmented)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "23496dad", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Segmentation')" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "\n", - "axes[0].imshow(ground_truth)\n", - "axes[0].set_title('Ground truth')\n", - "\n", - "axes[1].imshow(segmented)\n", - "axes[1].set_title('Segmentation')" - ] - }, - { - "cell_type": "markdown", - "id": "1e1d39a4", - "metadata": {}, - "source": [ - "## Compare labels: Labelwise Jaccard-index\n", - "\n", - "Lastly, we calculate the *label-wise Jaccard index* to measure the intersection over union (IoU) between corresponding pairs of labels." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "7641d30b", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
\n", - "

68 rows × 3 columns

\n", - "
" - ], - "text/plain": [ - " label jaccard_score dice_score\n", - "0 0 0.496847 0.663858\n", - "1 1 0.518102 0.682566\n", - "2 2 0.470130 0.639576\n", - "3 3 0.623552 0.768133\n", - "4 4 0.602546 0.751986\n", - ".. ... ... ...\n", - "63 63 0.262857 0.416290\n", - "64 64 0.000000 0.000000\n", - "65 65 0.000000 0.000000\n", - "66 66 0.000000 0.000000\n", - "67 67 0.000000 0.000000\n", - "\n", - "[68 rows x 3 columns]" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "result = biau.label.compare_labels(ground_truth, segmented)\n", - "result" - ] - }, - { - "cell_type": "markdown", - "id": "3f218dd4", - "metadata": {}, - "source": [ - "Let's also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "fab77a34", - "metadata": {}, - "outputs": [], - "source": [ - "LUT_jaccard = result['jaccard_score'].to_numpy()\n", - "LUT_dice = result['dice_score'].to_numpy()\n", - "\n", - "# set segmentation quality of background to zero\n", - "LUT_jaccard[0] = np.nan\n", - "LUT_dice[0] = np.nan\n", - "\n", - "# create score map\n", - "JI_map = LUT_jaccard[segmented]\n", - "DI_map = LUT_dice[segmented]" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "ca62489c", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "(-0.5, 255.5, 253.5, -0.5)" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))\n", - "fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)\n", - "\n", - "\n", - "# Plot ground truth\n", - "axes[0, 0].imshow(ground_truth)\n", - "axes[0, 0].set_title('Ground truth')\n", - "\n", - "# Plot segmentation\n", - "axes[0, 1].imshow(segmented)\n", - "axes[0, 1].set_title('Segmentation')\n", - "\n", - "# Plot overlay\n", - "axes[0, 2].imshow(ground_truth)\n", - "axes[0, 2].imshow(segmented, alpha=0.5)\n", - "axes[0, 2].set_title('Overlay')\n", - "\n", - "# Plot Jaccard index map\n", - "im = axes[1, 0].imshow(JI_map, cmap='inferno_r')\n", - "axes[1, 0].set_title('Jaccard score')\n", - "cbar = fig.colorbar(im, ax=axes[1, 0])\n", - "\n", - "# Plot Dice score map\n", - "im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')\n", - "axes[1, 1].set_title('Dice score')\n", - "cbar2 = fig.colorbar(im2, ax=axes[1, 1])\n", - "\n", - "axes[-1, -1].axis('off')" - ] - }, - { - "cell_type": "markdown", - "id": "1dc2ca58", - "metadata": {}, - "source": [ - "## Compare-labels: Feature-wise\n", - "It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "5f6cc904", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
\n", - "

63 rows × 4 columns

\n", - "
" - ], - "text/plain": [ - " label area eccentricity orientation\n", - "0 1 415 0.878888 -0.433915\n", - "1 2 181 0.822705 -1.513862\n", - "2 3 646 0.386542 -0.079653\n", - "3 4 426 0.324798 -0.400592\n", - "4 5 465 0.780472 -0.044317\n", - ".. ... ... ... ...\n", - "58 59 1 0.000000 0.785398\n", - "59 60 87 0.969263 -1.560717\n", - "60 61 73 0.951468 -1.567605\n", - "61 62 49 0.942191 -1.554054\n", - "62 63 46 0.976786 1.538848\n", - "\n", - "[63 rows x 4 columns]" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "properties = ['label', 'area', 'eccentricity', 'orientation']\n", - "features_gt = measure.regionprops_table(ground_truth, properties=properties)\n", - "features_seg = measure.regionprops_table(segmented, properties=properties)\n", - "\n", - "features_gt = pd.DataFrame(features_gt)\n", - "features_seg = pd.DataFrame(features_seg)\n", - "features_gt" - ] - }, - { - "cell_type": "markdown", - "id": "ec29004b", - "metadata": {}, - "source": [ - "Visualize as histograms" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "e9652f8d", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0, 0.5, '# Occurrences')" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))\n", - "\n", - "ax_idx = 0\n", - "for idx, prop in enumerate(properties):\n", - " if prop == 'label':\n", - " continue\n", - " \n", - " axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)\n", - " axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)\n", - " axes[ax_idx].set_xlabel(prop)\n", - " ax_idx += 1\n", - " \n", - "axes[0].legend()\n", - "axes[0].set_ylabel('# Occurrences')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "185d4c1d", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt b/doc/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt deleted file mode 100644 index 181425a..0000000 --- a/doc/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt +++ /dev/null @@ -1,3198 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "e5db44ea", - "metadata": {}, - "source": [ - "## Matching labels\n", - "This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "d1ca8e7a", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import biapol_utilities as biau\n", - "from skimage import io, measure, filters\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from datetime import datetime\n", - "\n", - "%matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "id": "ee62539b", - "metadata": {}, - "source": [ - "### Load data\n", - "First, we load the example blobs image and threshold it to create a label map. " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "7fe70350", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biau.data.blobs()" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "909ce3b2", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "threshold = 128\n", - "imageA = (blobs > threshold).astype(np.uint8)\n", - "imageA_labelled = measure.label(imageA)\n", - "\n", - "plt.imshow(imageA_labelled)" - ] - }, - { - "cell_type": "markdown", - "id": "1cbf5ae3", - "metadata": {}, - "source": [ - "Let's create a second version of this image in which we shuffle the labels:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "29986d79", - "metadata": {}, - "outputs": [], - "source": [ - "label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)\n", - "np.random.shuffle(label_shuffle)\n", - "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", - "\n", - "imageB_labelled = label_shuffle[imageA_labelled]" - ] - }, - { - "cell_type": "markdown", - "id": "1393dfb7", - "metadata": {}, - "source": [ - "Both images are not identical!" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "1ff3c80c", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of labels in imageA: 63\n", - "Number of labels in imageB: 63\n" - ] - } - ], - "source": [ - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "axes[0].imshow(imageA_labelled)\n", - "axes[0].set_title('Reference image')\n", - "axes[1].imshow(imageB_labelled)\n", - "axes[1].set_title('Shuffled image')\n", - "\n", - "print(f'Number of labels in imageA: {imageA_labelled.max()}')\n", - "print(f'Number of labels in imageB: {imageB_labelled.max()}')" - ] - }, - { - "cell_type": "markdown", - "id": "7a38be04", - "metadata": {}, - "source": [ - "Match labels and track time" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "79f0cf74", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Took 0 ms\n" - ] - } - ], - "source": [ - "t0 = datetime.now()\n", - "output = biau.label.match_labels(imageA_labelled, imageB_labelled)\n", - "t1 = datetime.now()\n", - "print(f'Took {(t1-t0).seconds*1000} ms')" - ] - }, - { - "cell_type": "markdown", - "id": "a8710824", - "metadata": {}, - "source": [ - "Visualize" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "84ed2639", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Relabelled image')" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "axes[0].imshow(imageA_labelled)\n", - "axes[0].set_title('Reference image')\n", - "axes[1].imshow(output)\n", - "axes[1].set_title('Relabelled image')" - ] - } - ], - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt b/doc/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt deleted file mode 100644 index 9924ff8..0000000 --- a/doc/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt +++ /dev/null @@ -1,98 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "803a884d", - "metadata": {}, - "outputs": [], - "source": [ - "import biapol_utilities as biao\n", - "from skimage.measure import label\n", - "from skimage.io import imshow" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "af876b71", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biao.blobs()\n", - "labels = label(blobs > 128)" - ] - }, - { - "cell_type": "markdown", - "id": "d9ded05a", - "metadata": {}, - "source": [ - "# Labels visualized in colours\n", - "`biapol_utilities` provided a standardized color map for visualizing labels in:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "5c3f2337", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "867149ee", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_sources/index.rst.txt b/doc/_build/html/_sources/index.rst.txt index f36003f..217e66a 100644 --- a/doc/_build/html/_sources/index.rst.txt +++ b/doc/_build/html/_sources/index.rst.txt @@ -1,6 +1,8 @@ Welcome to BiAPoL utilities's documentation! ============================================ +On this page, we provide docuemntation pages for our API and provide +comprehensive examples on how to use the functions in our library. .. toctree:: :maxdepth: 3 diff --git a/doc/_build/html/genindex.html b/doc/_build/html/genindex.html index ffd3dd3..060b76e 100644 --- a/doc/_build/html/genindex.html +++ b/doc/_build/html/genindex.html @@ -36,8 +36,35 @@

Index

+ C + | I + | M
+

C

+ + +
+ +

I

+ + +
+ +

M

+ + +
+ @@ -59,7 +86,7 @@

Navigation

Contents:

diff --git a/doc/_build/html/index.html b/doc/_build/html/index.html index 924a1c7..902293d 100644 --- a/doc/_build/html/index.html +++ b/doc/_build/html/index.html @@ -36,20 +36,25 @@

Welcome to BiAPoL utilities’s documentation!

+

On this page, we provide docuemntation pages for our API and provide +comprehensive examples on how to use the functions in our library.

Contents:

  • Examples
      -
    • Label module
    • -
    • API reference
        -
      • The label module
      • +
      • API Reference
      • @@ -85,7 +90,7 @@

        Navigation

        Contents:

        diff --git a/doc/_build/html/objects.inv b/doc/_build/html/objects.inv index 5bc49e50cac83baed9386e638ace33a5eb3c730e..54c0b75faa9674884077ecc0a636e520203ffb05 100644 GIT binary patch delta 619 zcmV-x0+juk2Hpjbet*qZ&5oQf48G4(xS~=|nbBVNwpDu=X)BGom3l-O@GemyAPDWw zt*_D7>ytDjz>tM3;cwL&G4}V_P8>UDMzb{bOTl6$7#91Oo-y7BX_C<#eYGkeyWBpO zJP<79a05Q$L0pD-ctVaj6&N1QE-?E@B(e7%$j+k9xWK$X#ed_cKQZ@9UVSE1L7VSvX<0%41GD_v4DN?hJN1IG@4%d^ z3Y=7zx$9|7(rVVnuGS>=1-xERj)ZR)`dIH-J@hfc)k7cYKMM}6LuZ3ort5}hJ9Ax2 zQdtsZN$P&TT~cN`^#7!C>gcq2DyKTMc`64+tp$Z<8GqcsS$(ua0n@pRoF zClJ4VI$WmpP14~)JRu#7hd9s*v{)Ur?-N6bza5y=`htP7-h5SfNrrfnYd{}X+}-9LuQ F6{_w-E7Sl0 delta 679 zcmV;Y0$Bat1(^nret*4I&2rN)5We>*#Q4BT&2a6l6gm^eok@Wijv3k7CIVSg>;t}T-ZT4B@a^d2xJn&3pzoPWU59bR}LNyXv#NDYycKh(;4uVR^`B!jJjT>?TA&7@G5EIo*5fU}Ko(~DrQUbGHC3h z$DDAc4+xZIiGMXM(-@R{uC&w@egL9#vwmg@&Q2h>X`$aX(Oa9Sx%o=j*xv#Ve$0j&$h2--=YKYPvJAgmFJe`CejBOxjE&%2ebkh>Pn^mBP)swlCau;fBI!S+%@r=i}YhzS%+F7s@@ z68HU6_=skj6E4xtkr{-ifKTUO+hcc*ab|l4-+-If2uMrxo?UNbh;q%$OJ<HyYu zOgXxhGN!%5Kfiu=s?bc6M N{SDc{#b1iNlSz2pSnU7+ diff --git a/doc/_build/html/search.html b/doc/_build/html/search.html index 91908b8..71ab514 100644 --- a/doc/_build/html/search.html +++ b/doc/_build/html/search.html @@ -88,7 +88,7 @@

        Navigation

        Contents:

        diff --git a/doc/_build/html/searchindex.js b/doc/_build/html/searchindex.js index 4cdbf9d..72c9c03 100644 --- a/doc/_build/html/searchindex.js +++ b/doc/_build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["_include/API_reference","_include/Examples","_include/notebooks/label/Compare_segmentations","_include/notebooks/label/match_labels","_include/notebooks/label/visualize_labels","index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,nbsphinx:3,sphinx:56},filenames:["_include\\API_reference.rst","_include\\Examples.rst","_include\\notebooks\\label\\Compare_segmentations.ipynb","_include\\notebooks\\label\\match_labels.ipynb","_include\\notebooks\\label\\visualize_labels.ipynb","index.rst"],objects:{},objnames:{},objtypes:{},terms:{"0":[2,3,4],"000000":2,"044317":2,"05":2,"06":2,"079653":2,"0x17fe4272220":4,"0x29c86bdabe0":3,"1":[2,3,4],"10":2,"1000":3,"11":2,"12":2,"128":[2,3,4],"13":2,"181":2,"2":[2,3,4],"20":2,"253":2,"255":2,"262857":2,"3":[2,3],"324798":2,"386542":2,"39":[2,3],"4":[2,3,4],"400592":2,"415":2,"416290":2,"426":2,"433915":2,"46":2,"465":2,"470130":2,"49":2,"496847":2,"5":[2,3],"513862":2,"518102":2,"538848":2,"554054":2,"560717":2,"567605":2,"58":2,"59":2,"6":[2,3],"60":2,"602546":2,"61":2,"62":2,"623552":2,"63":[2,3],"639576":2,"64":2,"646":2,"65":2,"66":2,"663858":2,"67":2,"68":2,"682566":2,"7":[2,3],"73":2,"751986":2,"768133":2,"780472":2,"785398":2,"8":[2,3],"822705":2,"85":2,"87":2,"878888":2,"9":[2,3],"942191":2,"95":2,"951468":2,"969263":2,"976786":2,"do":2,"import":[2,3,4],"new":2,"true":[2,3],For:2,It:2,The:5,To:2,achiev:2,agreement:2,alpha:2,also:2,an:2,annnoot:2,annnot:2,annot:2,api:5,append:[2,3],approach:2,ar:[2,3],arang:[2,3],area:2,arrai:[2,3],asarrai:[2,3],assign:[2,3],astyp:[2,3],ax:[2,3],ax_idx:2,axes_grid1:2,axesimag:[3,4],axi:2,background:[2,3],between:2,biao:4,biapol_util:[2,3,4],biau:[2,3],bin:2,bit:2,blob:[2,3,4],both:[2,3],bottom:2,calcul:2,cbar2:2,cbar:2,certain:2,check:2,cmap:[2,4],color:4,colorbar:2,column:2,compar:[1,3,5],compare_label:2,continu:2,convert:3,correct:2,correspond:2,creat:[2,3],data:5,datafram:2,datetim:3,depend:2,di_map:2,dice:2,dice_scor:2,don:[2,3],eccentr:2,enumer:2,epyseg:2,estim:[],etc:2,everi:2,exampl:[2,3,5],expand:2,expand_label:2,f:3,face:2,features_gt:2,features_seg:2,fig:[2,3],figsiz:2,filter:3,first:[2,3],from:[2,3,4],gener:2,ground:2,ground_truth:2,gt:[3,4],have:2,hist:2,histogram:2,ident:3,idx:2,im2:2,im:2,imag:[2,3,4],imagea:[2,3],imagea_label:3,imageb:3,imageb_label:3,imshow:[2,3,4],index:5,inferno_r:2,interest:2,intersect:2,io:[2,3,4],iou:2,jaccard_scor:2,ji_map:2,label:5,label_shuffl:[2,3],labels_colormap:4,lastli:2,left:2,legend:2,len:2,let:[2,3],lt:[3,4],lut_dic:2,lut_jaccard:2,mai:2,make_axes_locat:2,map:[2,3,4],match:[1,5],match_label:[2,3],matplotlib:[2,3,4],max:[2,3,4],measur:[2,3,4],method:2,modul:5,mpl_toolkit:2,ms:3,nan:2,ncol:[2,3],next:2,notebook:[2,3],now:3,np:[2,3],nrow:2,number:3,numpi:[2,3],obtain:2,occurr:2,off:2,often:2,one:3,onli:2,orient:2,os:[2,3],output:3,over:2,overlai:2,overlap:2,page:5,pair:2,panda:2,pd:2,pipelin:2,pixel:2,plantseg:2,plot:2,plt:[2,3],preserv:2,print:3,problem:2,prop:2,properti:2,provid:[2,4],pyplot:[2,3],qualiti:[],quantit:[],random:[2,3],randomli:2,refer:[3,5],regionprop:2,regionprops_t:2,relabel:3,resembl:3,result:2,right:2,row:2,s:[2,3],same:2,scikit:2,score:2,script:3,search:5,second:[2,3],segment:[1,5],set:2,set_titl:[2,3],set_xlabel:2,set_ylabel:2,shape:2,sharei:[2,3],sharex:[2,3],shuffl:[2,3],side:2,skimag:[2,3,4],some:2,standard:4,stardist:2,start:[2,3],subplot:[2,3],subplots_adjust:2,t0:3,t1:3,t:[2,3],take:2,text:[2,3],them:2,thi:[2,3],threshold:[2,3],time:3,titl:2,to_numpi:2,took:3,top:2,track:3,truth:2,two:3,uint8:[2,3],union:2,us:2,valu:2,version:[2,3],visual:[2,3],vmax:4,vmin:4,wa:2,want:[2,3],we:[2,3],whether:2,which:[2,3],wspace:2,zero:2},titles:["API reference","Examples","Quantitative segmentation quality estimation","Matching labels","Labels visualized in colours","Welcome to BiAPoL utilities\u2019s documentation!"],titleterms:{The:0,api:0,biapol:5,colour:4,compar:2,content:5,data:[0,1,2,3],document:5,estim:2,exampl:1,featur:2,index:2,indic:5,input:2,jaccard:2,label:[0,1,2,3,4],labelwis:2,load:3,match:[2,3],modul:[0,1],qualiti:2,quantit:2,re:2,refer:0,s:5,segment:2,tabl:5,util:5,visual:4,welcom:5,wise:2}}) \ No newline at end of file +Search.setIndex({docnames:["_include/API_reference","_include/Examples","_include/generated/biapol_utilities.label.compare_labels","_include/generated/biapol_utilities.label.intersection_over_union_matrix","_include/generated/biapol_utilities.label.match_labels_stack","index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,nbsphinx:3,sphinx:56},filenames:["_include\\API_reference.rst","_include\\Examples.rst","_include\\generated\\biapol_utilities.label.compare_labels.rst","_include\\generated\\biapol_utilities.label.intersection_over_union_matrix.rst","_include\\generated\\biapol_utilities.label.match_labels_stack.rst","index.rst"],objects:{"biapol_utilities.label":{compare_labels:[2,0,1,""],intersection_over_union_matrix:[3,0,1,""],match_labels_stack:[4,0,1,""]}},objnames:{"0":["py","function","Python function"]},objtypes:{"0":"py:function"},terms:{"0":[3,4],"1":[2,3],"2":3,"25":4,"2d":[3,4],"2j":2,"3d":4,"default":4,"float":[3,4],"function":[4,5],"int":[2,3,4],"return":[2,3,4],"true":3,On:5,The:[2,3,4,5],_:2,abov:4,ad:3,all:3,along:3,an:3,api:5,ar:[3,4],arbitrari:2,area:3,arrai:[2,3,4],axi:[3,4],background:3,becaus:3,between:[2,3],biapol_util:5,can:2,clij2:3,clij:3,column:[2,3],compar:2,compare_label:5,comprehens:5,consid:4,correspond:2,data:5,datafram:2,defin:2,deriv:2,determin:2,dice:2,dice_scor:2,differ:2,dimens:2,doc:3,docuemnt:5,duplic:3,each:[2,3],equival:3,evalu:2,everi:3,exampl:5,except:3,find:3,follow:2,frac:2,from:[2,4],gener:3,github:3,give:3,guarante:3,have:2,how:[3,5],http:3,ident:4,imag:[2,3,4],includ:3,index:5,intersect:[2,3],intersection_over_union_matrix:[4,5],io:3,iou:[3,4],j:2,jaccard:2,jaccard_scor:2,kwarg:4,label:5,label_image_i:[2,3],label_image_x:[2,3],label_stack:4,librari:5,likewis:3,lookup:3,mask:[3,4],match:4,match_labels_stack:5,matrix:3,max:3,measur:2,method:4,modul:5,must:2,nd:[2,3],option:4,order:4,our:5,over:[2,3],overlap:3,page:5,pair:3,panda:2,paramet:[2,3,4],predict:3,provid:5,quantitii:2,reconstruct:3,refer:[3,5],reference_generatejaccardindexmatrix:3,relat:2,respect:2,row:[2,3],s:2,same:2,score:2,search:5,set:3,size:3,slice:4,so:3,sourc:3,specifi:4,stack:4,stitch:4,stitch_threshold:4,str:4,subsequ:4,subtract:3,sum:3,tabl:3,taken:3,thi:[3,5],threshold:4,through:2,thu:3,togeth:3,total:3,two:[2,4],type:[3,4],union:[2,3],us:[4,5],valu:4,vector:3,we:5,where:3,which:[2,4],wise:2,work:3,x:3,y:3,zyx:4},titles:["API Reference","Examples","biapol_utilities.label.compare_labels","biapol_utilities.label.intersection_over_union_matrix","biapol_utilities.label.match_labels_stack","Welcome to BiAPoL utilities\u2019s documentation!"],titleterms:{The:0,api:0,biapol:5,biapol_util:[2,3,4],compare_label:2,content:5,data:[0,1],document:5,exampl:1,indic:5,intersection_over_union_matrix:3,label:[0,1,2,3,4],match_labels_stack:4,modul:[0,1],refer:0,s:5,tabl:5,util:5,welcom:5}}) \ No newline at end of file diff --git a/doc/_include/API_reference.rst b/doc/_include/API_reference.rst index 3073ec6..21cf6f0 100644 --- a/doc/_include/API_reference.rst +++ b/doc/_include/API_reference.rst @@ -1,5 +1,5 @@ -API reference -============================= +API Reference +============= The label module @@ -8,6 +8,8 @@ The label module .. currentmodule:: biapol_utilities .. autosummary:: + :recursive: + :toctree: generated label.compare_labels label.intersection_over_union_matrix diff --git a/doc/_include/Examples.rst b/doc/_include/Examples.rst index 37708b5..de920ec 100644 --- a/doc/_include/Examples.rst +++ b/doc/_include/Examples.rst @@ -8,8 +8,8 @@ Label module :titlesonly: :maxdepth: 0 - Match labels <../notebooks/label/match_labels.ipynb> - Compare segmentations <../notebooks/label/Compare_segmentations.ipynb> + Match labels <../../notebooks/label/match_labels.ipynb> + Compare segmentations <../../notebooks/label/Compare_segmentations.ipynb> Data module ------------------ diff --git a/doc/_include/generated/biapol_utilities.label.compare_labels.rst b/doc/_include/generated/biapol_utilities.label.compare_labels.rst new file mode 100644 index 0000000..286bf6d --- /dev/null +++ b/doc/_include/generated/biapol_utilities.label.compare_labels.rst @@ -0,0 +1,6 @@ +biapol\_utilities.label.compare\_labels +======================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: compare_labels \ No newline at end of file diff --git a/doc/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst b/doc/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst new file mode 100644 index 0000000..3b66942 --- /dev/null +++ b/doc/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst @@ -0,0 +1,6 @@ +biapol\_utilities.label.intersection\_over\_union\_matrix +========================================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: intersection_over_union_matrix \ No newline at end of file diff --git a/doc/_include/generated/biapol_utilities.label.match_labels_stack.rst b/doc/_include/generated/biapol_utilities.label.match_labels_stack.rst new file mode 100644 index 0000000..2f71b54 --- /dev/null +++ b/doc/_include/generated/biapol_utilities.label.match_labels_stack.rst @@ -0,0 +1,6 @@ +biapol\_utilities.label.match\_labels\_stack +============================================ + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: match_labels_stack \ No newline at end of file diff --git a/doc/_templates/autosummary/base.rst b/doc/_templates/autosummary/base.rst new file mode 100644 index 0000000..6a4040a --- /dev/null +++ b/doc/_templates/autosummary/base.rst @@ -0,0 +1,5 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. auto{{ objtype }}:: {{ objname }} \ No newline at end of file diff --git a/doc/_templates/autosummary/class.rst b/doc/_templates/autosummary/class.rst new file mode 100644 index 0000000..c188ac6 --- /dev/null +++ b/doc/_templates/autosummary/class.rst @@ -0,0 +1,31 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + + {% block methods %} + {% block attributes %} + {% if attributes %} + .. HACK -- the point here is that we don't want this to appear in the output, but the autosummary should still generate the pages. + .. autosummary:: + :toctree: + {% for item in all_attributes %} + {%- if not item.startswith('_') %} + {{ name }}.{{ item }} + {%- endif -%} + {%- endfor %} + {% endif %} + {% endblock %} + + {% if methods %} + .. HACK -- the point here is that we don't want this to appear in the output, but the autosummary should still generate the pages. + .. autosummary:: + :toctree: + {% for item in all_methods %} + {%- if not item.startswith('_') or item in ['__call__'] %} + {{ name }}.{{ item }} + {%- endif -%} + {%- endfor %} + {% endif %} + {% endblock %} \ No newline at end of file diff --git a/doc/_templates/autosummary/module.rst b/doc/_templates/autosummary/module.rst new file mode 100644 index 0000000..76d1c8e --- /dev/null +++ b/doc/_templates/autosummary/module.rst @@ -0,0 +1,29 @@ +{{ fullname | escape | underline }} + +.. rubric:: Description + +.. automodule:: {{ fullname }} + +.. currentmodule:: {{ fullname }} + +{% if classes %} +.. rubric:: Classes + +.. autosummary:: + :toctree: . + {% for class in classes %} + {{ class }} + {% endfor %} + +{% endif %} + +{% if functions %} +.. rubric:: Functions + +.. autosummary:: + :toctree: . + {% for function in functions %} + {{ function }} + {% endfor %} + +{% endif %} \ No newline at end of file From daa33db2d74a6ed4d267a013a4bd9368b2bcac47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 22 Nov 2021 18:17:46 +0100 Subject: [PATCH 08/47] Added documentation --- .../doctrees/_include/API_reference.doctree | Bin 9499 -> 12402 bytes doc/_build/doctrees/_include/Examples.doctree | Bin 3909 -> 4483 bytes ...pol_utilities.label.compare_labels.doctree | Bin 0 -> 11590 bytes ...bel.intersection_over_union_matrix.doctree | Bin 0 -> 12066 bytes ...utilities.label.match_labels_stack.doctree | Bin 0 -> 10655 bytes .../biapol_utilities.data.blobs.doctree | Bin 0 -> 6426 bytes ...iapol_utilities.label.match_labels.doctree | Bin 0 -> 11809 bytes doc/_build/doctrees/environment.pickle | Bin 30096 -> 47486 bytes doc/_build/doctrees/index.doctree | Bin 4841 -> 6858 bytes doc/_build/html/.buildinfo | 2 +- ...e_notebooks_label_visualize_labels_3_1.png | Bin 0 -> 13455 bytes doc/_build/html/_include/API_reference.html | 37 +- doc/_build/html/_include/Examples.html | 33 +- ...biapol_utilities.label.compare_labels.html | 141 + ....label.intersection_over_union_matrix.html | 146 + ...ol_utilities.label.match_labels_stack.html | 131 + .../biapol_utilities.data.blobs.html | 134 + ...biapol_utilities.label.compare_labels.html | 22 +- ....label.intersection_over_union_matrix.html | 26 +- .../biapol_utilities.label.match_labels.html | 147 + ...ol_utilities.label.match_labels_stack.html | 28 +- .../label/Compare_segmentations.html | 5798 +++++++++++++++++ .../label/Compare_segmentations.ipynb | 0 .../notebooks/label/match_labels.html | 3465 ++++++++++ .../notebooks}/label/match_labels.ipynb | 0 .../notebooks/label/visualize_labels.html | 411 ++ .../notebooks}/label/visualize_labels.ipynb | 0 .../_sources/_include/API_reference.rst.txt | 8 +- .../html/_sources/_include/Examples.rst.txt | 16 +- ...pol_utilities.label.compare_labels.rst.txt | 6 + ...bel.intersection_over_union_matrix.rst.txt | 6 + ...utilities.label.match_labels_stack.rst.txt | 6 + .../biapol_utilities.data.blobs.rst.txt | 6 + ...iapol_utilities.label.match_labels.rst.txt | 6 + .../label/Compare_segmentations.ipynb.txt | 5614 ++++++++++++++++ .../notebooks/label/match_labels.ipynb.txt | 3198 +++++++++ .../label/visualize_labels.ipynb.txt | 98 + doc/_build/html/_sources/index.rst.txt | 10 +- doc/_build/html/_static/logos/biapol_logo.png | Bin 0 -> 41688 bytes doc/_build/html/genindex.html | 36 +- doc/_build/html/index.html | 37 +- doc/_build/html/objects.inv | Bin 734 -> 1448 bytes doc/_build/html/search.html | 15 +- doc/_build/html/searchindex.js | 2 +- doc/_include/API_reference.rst | 8 +- doc/_include/Examples.rst | 16 +- .../biapol_utilities.label.compare_labels.rst | 6 + ...s.label.intersection_over_union_matrix.rst | 6 + ...pol_utilities.label.match_labels_stack.rst | 6 + .../generated/biapol_utilities.data.blobs.rst | 6 + .../biapol_utilities.label.match_labels.rst | 6 + .../label/Compare_segmentations.ipynb | 5614 ++++++++++++++++ .../notebooks/label/match_labels.ipynb | 3198 +++++++++ .../notebooks/label/visualize_labels.ipynb | 98 + doc/_static/logos/biapol_logo.png | Bin 0 -> 41688 bytes doc/conf.py | 28 +- doc/index.rst | 10 +- 57 files changed, 28437 insertions(+), 150 deletions(-) create mode 100644 doc/_build/doctrees/_include/biapol_utilities.label.compare_labels.doctree create mode 100644 doc/_build/doctrees/_include/biapol_utilities.label.intersection_over_union_matrix.doctree create mode 100644 doc/_build/doctrees/_include/biapol_utilities.label.match_labels_stack.doctree create mode 100644 doc/_build/doctrees/_include/generated/biapol_utilities.data.blobs.doctree create mode 100644 doc/_build/doctrees/_include/generated/biapol_utilities.label.match_labels.doctree create mode 100644 doc/_build/html/_images/_include_notebooks_label_visualize_labels_3_1.png create mode 100644 doc/_build/html/_include/biapol_utilities.label.compare_labels.html create mode 100644 doc/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html create mode 100644 doc/_build/html/_include/biapol_utilities.label.match_labels_stack.html create mode 100644 doc/_build/html/_include/generated/biapol_utilities.data.blobs.html create mode 100644 doc/_build/html/_include/generated/biapol_utilities.label.match_labels.html create mode 100644 doc/_build/html/_include/notebooks/label/Compare_segmentations.html rename {notebooks => doc/_build/html/_include/notebooks}/label/Compare_segmentations.ipynb (100%) create mode 100644 doc/_build/html/_include/notebooks/label/match_labels.html rename {notebooks => doc/_build/html/_include/notebooks}/label/match_labels.ipynb (100%) create mode 100644 doc/_build/html/_include/notebooks/label/visualize_labels.html rename {notebooks => doc/_build/html/_include/notebooks}/label/visualize_labels.ipynb (100%) create mode 100644 doc/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt create mode 100644 doc/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt create mode 100644 doc/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt create mode 100644 doc/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt create mode 100644 doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt create mode 100644 doc/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt create mode 100644 doc/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt create mode 100644 doc/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt create mode 100644 doc/_build/html/_static/logos/biapol_logo.png create mode 100644 doc/_include/biapol_utilities.label.compare_labels.rst create mode 100644 doc/_include/biapol_utilities.label.intersection_over_union_matrix.rst create mode 100644 doc/_include/biapol_utilities.label.match_labels_stack.rst create mode 100644 doc/_include/generated/biapol_utilities.data.blobs.rst create mode 100644 doc/_include/generated/biapol_utilities.label.match_labels.rst create mode 100644 doc/_include/notebooks/label/Compare_segmentations.ipynb create mode 100644 doc/_include/notebooks/label/match_labels.ipynb create mode 100644 doc/_include/notebooks/label/visualize_labels.ipynb create mode 100644 doc/_static/logos/biapol_logo.png diff --git a/doc/_build/doctrees/_include/API_reference.doctree b/doc/_build/doctrees/_include/API_reference.doctree index 58329dbfdf1dca5efd7d2991e59fe19522d629b6..a87282c83163a34d7d741cfe470db6ebe9714c6f 100644 GIT binary patch literal 12402 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 delta 810 zcmbV}ZEF)j5XXB>_U?k$q-mreiSw=?|`h!Ai+%T}eoZoSK`9O3~Y0`_n(V+Go5L%Q3MBdH#TE~1M)H^bBFd4QHItm7VT_ZyR@ zc6JU6teEU3DYVzykR;755M2B+;0x`tG_hmYgczs?b{g3U(;)=vqEi&)9lWFSPZ&vl*#m<`&K*?N8GBxacyi&0-LvjDH&lk zC@G<1)}AmD!VZMO8E1J#LNMd*+HLoSdrh!>=u;4m!Sp1`Vh;o^$&&>WUo9k zR#24c&nSY*ki_ndTG5X^1x1>SfYMM5hN0AzAfa6S4N9;eQ~$&R I_{FmG1#lP)ivR!s diff --git a/doc/_build/doctrees/_include/biapol_utilities.label.compare_labels.doctree b/doc/_build/doctrees/_include/biapol_utilities.label.compare_labels.doctree new file mode 100644 index 0000000000000000000000000000000000000000..03f306ac698eb92f8de57bedddd55c60bc6f8f42 GIT binary patch literal 11590 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 U3D&83w_%c3NenOrJ5js!Kc5g<1poj5 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/_include/biapol_utilities.label.intersection_over_union_matrix.doctree b/doc/_build/doctrees/_include/biapol_utilities.label.intersection_over_union_matrix.doctree new file mode 100644 index 0000000000000000000000000000000000000000..ad3305a99fd9669b52befb1181f2f8086feac97f GIT binary patch literal 12066 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 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/_include/biapol_utilities.label.match_labels_stack.doctree b/doc/_build/doctrees/_include/biapol_utilities.label.match_labels_stack.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a76903e4d72c0fcb4f4cf48963eb3c00e2b0869c GIT binary patch literal 10655 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 Wd5C&D^bBy?q8&8dY-qu_+4vtUx;l3N literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/_include/generated/biapol_utilities.data.blobs.doctree b/doc/_build/doctrees/_include/generated/biapol_utilities.data.blobs.doctree new file mode 100644 index 0000000000000000000000000000000000000000..f2afac4153510954a46e48899c1cb8883127ea30 GIT binary patch literal 6426 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 AdjJ3c literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/_include/generated/biapol_utilities.label.match_labels.doctree b/doc/_build/doctrees/_include/generated/biapol_utilities.label.match_labels.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9c7a619641a95ddd5f956ac702d565a5a288f16c GIT binary patch literal 11809 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 literal 0 HcmV?d00001 diff --git a/doc/_build/doctrees/environment.pickle b/doc/_build/doctrees/environment.pickle index 265f06baca688392c1c18b20412926901d2015d1..2f8711d2f7ddb1587e8a0c73f378a415ea9bf179 100644 GIT binary patch literal 47486 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

        bIeC-U$%VFwe?;ZRRCfB44f9Qpf;Oi*3aa-SD_x zgiCtiT;aR|4v#erATlLsI3Ol&lS*PmKdkd{=yFRWQSMFs=~(IA{M zEGY#2GX=xEqTi5Rvn@ua}f607T+V~vCCP+?ou(UoCLIj z6H|Yu6lhcvjE{nuuou>P&~`LZc1ShOBDDik8w(xEDx4~u<|4bLNJ2kpBZ#v%E6l`L z`#O!l1Yj`&Vu8bXiavD)0%xd5MQ}669wW6{877g#(V7iQk$d6{EF1h;$SC+-;M+jB zF$AxIX)2RNs~0MJ;;Q7=pp{m^wjhE`#cjzFu!^8{FWkW(6FCSAu_4nH6A~G4hGRbk zRW>wMLA(OY7YKIFxGQc&WyF1q*1qonHOTIbi&20qL@I(UU;#<%PfS#PhgSj&vL6Ff z*$|Lgm<>Y>vjLuk)+QIt^u5-FJM_>VBuMeFk!9iClt?a1JqXFQ0gA(et;X;U3K%Hb zqOWzRthRQxVJbS_lu!N%cK7Ky+k_>SBYWNcwQJTy_dkO`EKtD4zJjq{c?VwyI}cuR z0t$(+Jg_4$b91|Hta&aD>#RgvER%1y&S*K84EixyqCV}^kP){_1MtvEJG7i4d>2(k z8>$~_%CQp{%b$l&reAsRk@qVxJIF;S>;pZ9Ik&#*!G|Cscn9Z^!DmbXvt*@q8MInS z*O>^iR+>XBGkg*uJa9_x59P8>J`2w>oBe1`3;XR9OAM{tDsMQKMN=?$ui5h$=y_&g zv|z<}+{-JU8v@W9-3M@%>XK|e z>@bhIA}oc=?iEZo!hdI+owsMm$HNYg4YrrY^fJZnii@e{wQnN2<8WMTYg|m$R0cqz zookceEBuBqb)sDj=%?khfT=bd14K3UVVS%H$O`t=AS~)fL@k);NAfRXy7E!6t8csK7S}~M=fSm$KyjAsVBkPn3DIzHF$>z zV+iw?JSmvcG5ZpHF~!7@cr}K#JBG!Cz^Xzv1cpYdK?Mg5ywQR~CRAJ{K|2Fi>TEN0 zbVgh&6*mM+nU|mtABZ-6wNq+Z!|u(&)Op+i@9&$V_#Hdv)7jRyP!_Kr7Pq3({z%yb9 z5KGRSoo_6rcL8D}PMW+&!vQRkXz&chu$1JD(ZY@t){hi&7^@iW6=6bh4Q^{>Mg1`h zY38lE8B+*y)ffR;S);%;OMc@9TCli;>;%Kuox-wyw}z+u`VJHhLc_H_yjy2G9(kWSTJtgJc$LPh_zFUI@f+n;Xtz4PIgjHWc91Ior)-s(^%?f1d$Pv20La#A1k1 zaouPwcu!o4c6>@sKvtt_N@>wO`V?Ju+V^2m#>~*{y33S+(F1>y;g&A&7E?fl+W-@A zl@0<>VWV-IieaZ^hAi#QB`E;JfhcP%`Bnpy^thGBh7f!BXfFfylSLMh88QznSD1E; zP05FrD`|GsOz~}X#nC77rtnPIUY7$K2di;4Z|k!vG?8@H&bnI40MwZ=!!S40&OFa< zgU&8fy>51@otT)Nxhj-uNgK*$_a<(DOx7$8E2>B&GdqXPCNyFta#b8AjMmeH)xyDK zQ@9&e(!AZG_IVRK*s3x@38u{|MaZ_xKoDb;#Rv6|2Y=kWUYuQ)jClW@6eO)xU{cJ% zw-v329?;uLF>p{1#~763KiY7Vf_#;(*kdq&04n2@AfjhX!DC0q%DUi?DOkV57^l~7 zM#il>9uB~fJq8@07+%^JTs@&ExZ40#&P-Lx-M9{ZJsw$!z6u*9zQG9LLb-6Ab!DMa z2t;YdO=GKryiQ_^DBXLPX;bGWv=RI3c9;?&9sKmL>f+`&GbR|;7hos$6sznrGoxk) z4H0$nR#dFGZn-;mB{RuvpfQ6ba9KNd3lFJz^Oj^ueVR2(2ZUKvVw&(EsRLL_sz&!$ zV1Nq|?@huI)rlp5==WH}r??cB->}d5WH2p`Xg>+UO`>VkY-g>d+(uFmyGycfr6yk= zj54x&44bOe$!JjAmVBBNmj8u2u(aVr)hb06f-tV4jT|YBnVL9*yjAT)V2JQ;L$v9N z`elw}>+{})eu`3v`hYhZPPNyuQ~EfhH6N+c$6jNP9`|8{4^60EF`c1qKnXAh773P{ z`wRdbbrXzoO>z(C3UI^WFg47M5mQc`uWf9Iy|7rTHCJc^e1`nBC>husv!KRV^q6Tu zkBfY}PBpgmsiJGVx#kue$6-oS(~u|WtliiXwr7FQ8s zr)n40Mt3zP;!Hg@^z4vk&z+5#jzrQ@p1x|pK*PNX7uK8YJe|yoH7dWS0hVjcSYjCy z8v2d`T@BPMQ2MThTHR*iP5r9WA55D~JQ zSzC&>*QN8^KurDzv|(yVJ)8$mBcSW zI2e=r2164uKre0mS#_{@X2T^q!_R0vvZ{Shzca6g6d>_>OcYKdte8^ zr4LVWw42wYa@vEW7!(cmYxC&mj%2urjvzxgBS*Ov)xBW*^ zucA{RJoL;DRw=s$&i>3$g0_v?r?v8wn%3HPu2i2(g`fY)|LaE4Nu^JHVn-`o!I?k( z_OE@-oq(B3Pd~c%Zel54{lrNS%jzd{On@nu4AzZeT^vTash zYxMG~u3M^Brd_R!uH}9Wjky02ALy+6b$p|f?lF zhrS+a*H@PBnqzC!@~^IYs%mrhxTmQDO~P*8^2F*@Hw; z!T3k3#F+G02aIpayji<`b@PVQW`}K9IH0p%1rt?jKrZk6vCukAAL-Q?cxmp^HNjF1!?nVc^avgo+`C zg(EKOm~*JBs=}iatL)K2=N=7RB1b2@D=Fo=tV6mfSMYjrm3Wa!*kSD4dy!qQDPscW z>99Us7ga@YTpg0j7Zr?OSS7}boiXk+j>9_a;$*=jUyn)8Mid(z3HyoGogHX8@@~6` z6(Q~t@l%Zvet-I*PX_fzDjuk(@}Xra?{BIqeVx0ReRaQx9#$u-(Ewe;)?gyDjVd-I z8E|5Sk$K~?jY4LD%etM^t;;%-6qd_chs3$dGMR*;%aVJBwpm2zMYa7+daQeQ%zu;(V|~>>HcC!N6rRy`N(Gd5^nIF&vv#?pb&_ z)mmU1FY<99fVOD))|WPw1(|;1oNQN&ZS97|KypaCUnLr{vHUsozB^-?R!S1v1GnWy z;8LwPHCg2hNTd}n3<|G^RgIO6S*%Et|G4WW6{Hq)5{UnhA-ZqitJT`$fcwjBb3WZB z$NiOd8BE;a=W&@2%iEM3g{_}z&DnzJHv#mPP&?YT7ePm9#we{YQmdLTp-pN1x4Uj# zf%q*0;_D2eEv4O0A|H!GaS*f{o-1FNMO)OWTt}oIScUWTCi+}^cD1h3!;0&l5gNv! z>Q`$AF1vpLa=(VKz`s=A|3iKMkiTtsD)bic(?7#sw0;`fT(p6UD<;^$!L8nKJj5{7 zOfwwB1`ywrfI90r1n9C1rSGDF?gp}gTqj8dmW(O8>-9Pg;u>KqkiNoL-Tc`;M6;dN zeJv+@Q?4L0yrEkXtx&Q?!#vjspSDwdux9wiMbXPWiSXayC36jzX2hGy9W?4 z7NRG601;#Hage2#iSH5?+DX_>QMaABZjWlZC%=jNZDSoxb;YTUG2owA9UST6H~w6D~On>f6^-m#Z-2p+%~56ri=T@ zB4aCT`^Ii9kJkL9UU%Z}P}glW@pntFAY%UZ_X#s&Gnu;HiOFwt-BuHmKh`UVn90A`D+tA8-m&PK z$p?B}A$PZ_S+|LB%5eD`UH7>)m#Ocaxcs%Q+iK$SZ!w6ro~`!V1-%k^;3+z7#U8}^ zeS&0$SUKP8x_c`mWwd!OW05AmVNKB__C9>K>vo&S`kh`u#FOU_g){B8YkH;s(6e@$ zqb^!+kvHZFC+^sEbL`EgK@I<{Zc#RDaJ#JppvCO?yIyG-Z`J&?R}i6$U=lbw^h!3GZuSU>&ASTsz-2CQV#B(<_KZ zuJz!&C&NNWDvGZM5HS{C?p3NN^JW1mzOCkM>;LcBylD!5N{STs8DqixeAoPGJ=myw zoh+CScHLIfaQXm)=$?+fD$xFmzLjrbza-LSgnh2-zO9gs(ZF89p^f$OnXa2{BI&1l z1rg7Uf7C08c!mmNS2aWDSAzw1=r}y8>jg-!BWwB4zq;9a)y&rKcHPC+ql~)RX|{f+ z>$aMP)*to?A|6`b?iGX*yBz7(HB);QyK%^59S5%&4sO83=E-g35^``x!YIakA%>nl^5%}lm<9U1}L&Pp1axabxlTfjx zXk)?2eI;svxJTERO!PS!uQDq0*OVr>M`go37RWr+knQ_cb zbn@JZj6^kO)GZ=GMh;QL2W9a_q+CXy2h8YzZGJfqhwNO~ECcXyG}E1cQ8={-P?M1u zE9K4uOTlUiP`i(@YHQ~9szf)RZ5NwXmm`#!?V2(x6$)GSwuniKWkT3>!%Z^bdaoeL zs3_eR7Ie={*D)YO?)Ly9#^V1r=<}5hDaHau8lM$tr_XPJ;#tkX1NVba;6nW0XyD(g zqTxR*UmuaLkIL5)f3+Ta)cuxf-~B9VNn2m+x-B)_K4n1sDuY;s3R*$`j0)mDB~{Sn zR!5Z)?c4S|bZdeCM>KA~gO55{zc!ZjQU4jaaxyr9yUI91xHqxC)FAfxQEL?Udqhm} zbAFE~OktMM;gyPfb_gcK{3c=YA25gF^RJx=u26Wrfywb~UNMN80r3UK;--uB?N7<= z^8A`^ezQlzxv5qKgf4&EHC(wH7~7v+)zPA3st1^hBM1gVzM{6D>zdqK(hVlfFZc=MwJm3LLzG%$q(n zi3=C$UN7~0+Qyync;3JlW#b2K=)r{+{K{Uu--)gw<0}VoP==%W@#fOtSvy%~DeBKA zuH1+Qaq+0{ory2upnKu;<-3bD_emNjYpPK{F8Ehhzfq4isYmq76zR+93*b;frJ|ln zqV0qvgA(Bc4p+|WOTHRG5cV4UziGyvBXa=Yo zCOK#tKFF6Fc4&*HB?x{`Q&W_ou18d4Ch2N`-wwW#95)UAec&r;6ob&=BpW(Vna3;0 zytj$WoFjKb=<940xk+!C#%|{zB29^@OnX}RB4;_iNLk>EGyyIGszz(^s;x!LIUjQl zI&qWCXi768a6JfANER9_SV7{7UaC%FV~M544W7nJtkIWPp)avMzrpH!iM9C>EAu7R z`t(Kb zwWSa@dqh3T5BHk@c0dldf4&vmE<}QY#nFSm)(Y0Lb6(Zv0|1|HReME4SwZ3W)GxGv zQgy$K)Wn!sM|YFPJTt6ZN0*Z#J=%=B^rquWqV@ROs5Al<>BAX92_$j959qj8YfzoN zmkT!OF0kj-OU`h$5`2zx!p=V>42LicU!FH_L9@YVa~&$Zsm-%1cymp(0gE(T+)d1O z{|xoqKc|oXMj!tjA0Mr~R-43YDf%!k1Q%dFPv{r&5B+~7 zpl?(!LUjK(65D~?{2ad>Fm(m50c(lxPZAL8kZeRb+Hr;7Uz4gs61_ZVZh{-N%1(TX zDlOdiA|;);3xH;PG+3Y5c!L>0-m?ryxpn~kT|YpSjt(tTw)uR#+*vT(bZ$OsKD`gv zk92~a^nD8GAp)IDj+%}N12B;w)j$__9Xiy47=)~B1?W8>ZprPZ;w{l89O{lPONBwI z&rI_{60HAtDot))S+CjDuYu-gZbFv@c?_EUGH7lh8N2NflhJ*X1{HmvgR8kpkPpZx zOXW851h=_%xcxtAS<8xPxuM6Um9$CAZS-tKM#@-f>RO8mx@;3eno*%)^=OY>s4-#~ zN=IZUt&$Wg!IoQeKS4u=K7f3e*E8}Nj9W*_XJS%{aTVGvUZ4=KMq7^rR=0AQKd&A1 zf;PeXL=l~vpkLeo@i(DcR*Y1Q8wPLRDZE`p$6DjX@Le*-`2%QnxTcbg_s4-v$NuJ4 z!~|KZ_HGD}T5}&Hd{*e+K^IT13bPt7(ZG|ZgeNzpp9$`?qKLHV(z1|0(1{Os(TU}C zTIlL zmzLn@bhe95C-ud0%u4E@8ap?%b0{IQgs*i)b*ZLaB^xFY_V!gEEeL@x?-9P-1OhCN zuUz6s9s-v>fWDFt9j`=X*TTDLP_M`#0m#>SBusCH2)kcS5Pn^_Zh+;fRbyFWXBn6{ zDNMX+{a%)p`ch}(c5=!0gbq!{9csL@U2BxO$hi@xJnv2J#qF%--qv)oKw90~noiu? z%8tRP?rdYnI`zdnUJZ+$9P6nkHAW8XaD^QcJwd@PJdPAfIK1>$&Js#Wlss4nOwaY! z2F~u($sB3OoTk$Y`^co|Fhw+ZwYMhgeFi6_2|7TOcI%FY2`c(bn8Kv}NvxHh9s}yn z-W=4YlEAHhQQDb)f2`XTAC^-u{4pDB?bx7vaO@)pX(b52qFFEodaD0N( zFs_F52+@p}q5&0cH7NEg_NwA1!gO`VH$uW*agg24LThT)TH=7GCF zKs!?U9qq?JQo$(b*Tk>|C!*sw{@}lcz)hS zi?%4UlXoI&(H5R~+VPAQA8Z4P7ueY0s21@aGLEd@oJ@-9f|3Cz?h%)Ezd+=w>ziPr zo0d{vq*6^daZB|DzeEKa+dMwX`!7u3S-Dg@9s21ePj--|H@B1!S|K;W^VVYYNHeYTx2IaoR9;zd@|%HkKG|=?*0$AsIvW_X%Q~t|hUT(%+)e_5HwY|0g~D6+Q~D;EDFv)FvCA{*Io0rt{VUxa_Xb?hUdx>IAOZr=NJY z2H9Io0`0~iVb~-n06R};h;`n0FUS=b~7V8O$o+!JwsD5InBeLH{31%^b zgp-tDJXA`#~kRsK^ZL6!I?l)wj4KOrxO_B=k*h7 zSU~)zlt3DXbqErERVQ%yU)N9W7x4?(zhM$cNg(0hm;_QnNcguVK~?#xNl;b(9VHm) zhAO|S6S&Ra(@!j_kp1sX0!bqz{3ny}4N3SfCV`|IN_^WSNEIE~f|p0w6@>R8Vz3%* z#7j%?7TQ|0Sp_-JJGKy{dS1QH`dyxL{j9vQ5Z5-lp8%C8h?A)MMs!&3#H{=cZm-n> zs=t3T>LWTbUz9uA-3O5n4W9L9J+cX@^*}CykGA_2XWH?sVwO?G8(kfs9`#dbBEQ#< zo;G7EJn@3=XuE#NT#OkN+iH@fStPZ2L-+xnN(e2Xk%=$rFojsgFLGC}9H+?D_{Hf~ ebuRDV`Kk;t?sUws$zFl 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 diff --git a/doc/_build/doctrees/index.doctree b/doc/_build/doctrees/index.doctree index 69412bd17b62dc87328a9a56ea407c8afc3e0bba..ffbaab33970c3541a4b6bf21cf8a1ca8e72bfffb 100644 GIT binary patch delta 1934 zcmb7_&ubG=5XZBd=67o=LP~$7DW#hJNFqv6g9-|Y&=N{}5w$cwy5{XO$;MDvRgd}f;T}=22UP(_a6{Ec=w`L5d`PG-M87aX{(o6c6MfVzB8Y<`+ef`tnZ<3 zXLs<8PZTSX5fGokrTJ3S1VL=}bYWlgSf(!B&Ey(VzFtJRu!#c8CQ2FA(8z`D$qjSe zOducn#k@Ov?xVzSrJ0XR9_dFz=#SCs9W;J~62fm|J9yTI1A@n6oDNJi*TPX@0Y#iT zep)wy`nZFH7o|o+(dtF1VRaI1b2;z987PT{@OfH!*O%1sEOiVcFB(BJC^pxx6;Oyo z3T35uZ{@zGsFG=z{56QZ7j3rRC(vW=Am^^iR~D4{c&V;vwK!BMW#YMuNL6c%OgdeV z^EIWMD#--orE;`DxD3)cqLa;Nb zE>(+Ml}^`0#t&=J?vRf)cCZ*4>FVpKNNDknm+qn0dr~J|)qF)V$x%tf4-&MxY~nJc zYG@kYqB1SDOru}T*GrP>S{sQUvH>Q~)ETIwl-jXnlMFGDNo!w8YhOuONz#Ryc{C2F zPe9mF&F0Z5h@6DTeO*_fYZ7+Wky=y;BfrQkyH(h@rt@uIRSxnZ;^EGm_>#g~m|Qd8x!tjbcO6PM5Fv~4bX+A6bt zb$0H_o+r?xLG#!#vtY!x!NF-K=@x+h)E0+vio?jWZXT@0HP3x%hh#zTub|a7NdG4v zS0Ed|1LJ~~PD3kT1uo7EW*kVln7v);uGLr*aDYu%z*?C}*ePe%M%dY@i{4Hutnhs# zKo*cZ-;OfZL{Y};U>L!cG}KNo-h{{P6gUVEg8vyj<_HIEge9XdG!VnnwE7Gf7$4fO zztR-@8+Oh$I@jxP1HRVB+@efE&V=BsIe&=O33j|jIT9E8n@=JGqUaHuZ+kv@^)vL< zX==Vw^M#re*tNxfD`}# delta 220 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 kH3 - + @@ -37,8 +37,11 @@

        API Reference

        +

        This is the class and function reference of biapol-utilities. Please refer to the examples for further details, as the class and function raw specifications may not be enough to give full guidelines on their uses.

        The label module

        +

        The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of +an object is encoded in the pixel value which must be an integer number.

        @@ -51,7 +54,10 @@

        The label module

        - + + + + @@ -59,13 +65,14 @@

        The label module

        The data module

        +

        The data module provides example data to be usedin the examples section.

        label.intersection_over_union_matrix(...)

        Generates a matrix with intersection over union of all mask pairs

        label.match_labels_stack(label_stack[, method])

        label.match_labels(label_image_x, label_image_y)

        Match labels in label_image_y with labels in label_image_x.

        label.match_labels_stack(label_stack[, method])

        Match labels from subsequent slices with specified method

        - + @@ -80,7 +87,12 @@

        The data module - - - - - - - -
        diff --git a/doc/_build/html/_include/Examples.html b/doc/_build/html/_include/Examples.html index 7dcdc39..8b56d58 100644 --- a/doc/_build/html/_include/Examples.html +++ b/doc/_build/html/_include/Examples.html @@ -17,7 +17,7 @@ - + @@ -37,13 +37,23 @@

        Examples

        +

        This is the example library of biapol-utilities. We provide examples for all top-level functions that are listed +in the API reference and comment on their usage here.

        Label module

        +

        The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of +an object is encoded in the pixel value which must be an integer number.

        Data module

        +

        The data module provides example data to be usedin the examples section.

        @@ -54,7 +64,12 @@

        Data module
        -

        BiAPoL utilities

        + @@ -67,9 +82,7 @@

        Navigation

        Contents:

        @@ -95,14 +108,6 @@

        Quick search

        - - - - - - - -
        diff --git a/doc/_build/html/_include/biapol_utilities.label.compare_labels.html b/doc/_build/html/_include/biapol_utilities.label.compare_labels.html new file mode 100644 index 0000000..691388d --- /dev/null +++ b/doc/_build/html/_include/biapol_utilities.label.compare_labels.html @@ -0,0 +1,141 @@ + + + + + + + + + biapol_utilities.label.compare_labels — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + +
        + +
        +

        biapol_utilities.label.compare_labels

        +
        +
        +biapol_utilities.label.compare_labels(label_image_x, label_image_y)
        +

        Evaluate differences between two label images.

        +

        Compares two label images to determine the +label-wise Jaccard- and Dice scores. +The Jaccard-score is defined as the intersection over union of two labelled +images [#]_. The Dice score S can be derived from the Jaccard-score J +through the following relation:

        +
        +\[S = \frac{2J}{1+J}\]
        +
        +

        See also

        +

        +
        +
        +
        Parameters
        +
          +
        • label_image_x (ND-array, int) – label image of arbitrary dimensions.

        • +
        • label_image_y (ND-array, int) – label image which will be compared to label_image_x, must have the +same dimensions.

        • +
        +
        +
        Returns
        +

          +
        • pandas DataFrame with columns [‘label’, ‘jaccard_score’, ‘dice_score’].

        • +
        • Each row corresponds to the measured quantitiy (Jaccard- or Dice score) of

        • +
        • the respective label.

        • +
        +

        +
        +
        +
        + +
        + + +
        + +
        +
        + +
        +
        + + + + + + + \ No newline at end of file diff --git a/doc/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html b/doc/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html new file mode 100644 index 0000000..1f7d03b --- /dev/null +++ b/doc/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html @@ -0,0 +1,146 @@ + + + + + + + + + biapol_utilities.label.intersection_over_union_matrix — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + +
        + +
        +

        biapol_utilities.label.intersection_over_union_matrix

        +
        +
        +biapol_utilities.label.intersection_over_union_matrix(label_image_x, label_image_y)
        +

        Generates a matrix with intersection over union of all mask pairs

        +

        How it works: +The overlap matrix is a lookup table of the area of intersection +between each set of labels (true and predicted). The true labels +are taken to be along axis 0, and the predicted labels are taken +to be along axis 1. The sum of the overlaps along axis 0 is thus +an array giving the total overlap of the true labels with each of +the predicted labels, and likewise the sum over axis 1 is the +total overlap of the predicted labels with each of the true labels. +Because the label 0 (background) is included, this sum is guaranteed +to reconstruct the total area of each label. Adding this row and +column vectors gives a 2D array with the areas of every label pair +added together. This is equivalent to the union of the label areas +except for the duplicated overlap area, so the overlap matrix is +subtracted to find the union matrix.

        +

        Source: 1

        +
        +
        Parameters
        +
          +
        • label_image_x (ND-array, int) – label image, where 0=background; 1,2… are label masks

        • +
        • label_image_y (ND-array, int) – label image, where 0=background; 1,2… are label masks

        • +
        +
        +
        Returns
        +

        iou – matrix of IOU pairs of size [x.max()+1, y.max()+1]

        +
        +
        Return type
        +

        ND-array, float

        +
        +
        +

        References

        +
        +
        1
        +

        https://clij.github.io/clij2-docs/reference_generateJaccardIndexMatrix

        +
        +
        +
        + +
        + + +
        + +
        +
        + +
        +
        + + + + + + + \ No newline at end of file diff --git a/doc/_build/html/_include/biapol_utilities.label.match_labels_stack.html b/doc/_build/html/_include/biapol_utilities.label.match_labels_stack.html new file mode 100644 index 0000000..1815ca2 --- /dev/null +++ b/doc/_build/html/_include/biapol_utilities.label.match_labels_stack.html @@ -0,0 +1,131 @@ + + + + + + + + + biapol_utilities.label.match_labels_stack — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + +
        + +
        +

        biapol_utilities.label.match_labels_stack

        +
        +
        +biapol_utilities.label.match_labels_stack(label_stack, method=<function intersection_over_union_matrix>, **kwargs)
        +

        Match labels from subsequent slices with specified method

        +
        +
        Parameters
        +
          +
        • label_stack (3D-array, int) – Stack of 2D label images to be stitched with axis order ZYX

        • +
        • method (str, optional) –

          Method to be used for stitching the masks. The default is intersection_over_union_matrix with a stitch threshold of 0.25. +stitch_threshold : float

          +
          +

          Threshold value for iou value above which two labels are considered identical. +The default value is 0.25

          +
          +

        • +
        +
        +
        Returns
        +

        Stack of stitched masks

        +
        +
        Return type
        +

        3D-array, int

        +
        +
        +
        + +
        + + +
        + +
        +
        + +
        +
        + + + + + + + \ No newline at end of file diff --git a/doc/_build/html/_include/generated/biapol_utilities.data.blobs.html b/doc/_build/html/_include/generated/biapol_utilities.data.blobs.html new file mode 100644 index 0000000..9f341f1 --- /dev/null +++ b/doc/_build/html/_include/generated/biapol_utilities.data.blobs.html @@ -0,0 +1,134 @@ + + + + + + + + + biapol_utilities.data.blobs — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + +
        + +
        +

        biapol_utilities.data.blobs

        +
        +
        +biapol_utilities.data.blobs()
        +

        Gray-level “blobs” image [1].

        +

        Can be used for segmentation and denoising examples.

        +
        +
        Returns
        +

        blobs – Blobs image.

        +
        +
        Return type
        +

        (256, 254) uint8 ndarray

        +
        +
        +

        References

        +
        +
        1
        +

        https://imagej.nih.gov/ij/images/

        +
        +
        +
        + +
        + + +
        + +
        +
        + +
        +
        + + + + + + + \ No newline at end of file diff --git a/doc/_build/html/_include/generated/biapol_utilities.label.compare_labels.html b/doc/_build/html/_include/generated/biapol_utilities.label.compare_labels.html index 01cb50b..7645d7d 100644 --- a/doc/_build/html/_include/generated/biapol_utilities.label.compare_labels.html +++ b/doc/_build/html/_include/generated/biapol_utilities.label.compare_labels.html @@ -82,7 +82,12 @@

        biapol_utilities.label.compare_labels - - - - - - - -
        diff --git a/doc/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html b/doc/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html index 4e73405..f8ddb1d 100644 --- a/doc/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html +++ b/doc/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html @@ -17,7 +17,7 @@ - + @@ -87,7 +87,12 @@

        biapol_utilities.label.intersection_over_union_matrix - - - - - - - -
        diff --git a/doc/_build/html/_include/generated/biapol_utilities.label.match_labels.html b/doc/_build/html/_include/generated/biapol_utilities.label.match_labels.html new file mode 100644 index 0000000..9636ccc --- /dev/null +++ b/doc/_build/html/_include/generated/biapol_utilities.label.match_labels.html @@ -0,0 +1,147 @@ + + + + + + + + + biapol_utilities.label.match_labels — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + +
        + +
        +

        biapol_utilities.label.match_labels

        +
        +
        +biapol_utilities.label.match_labels(label_image_x, label_image_y, method=<function intersection_over_union_matrix>, **kwargs)
        +

        Match labels in label_image_y with labels in label_image_x.

        +
        +
        Parameters
        +
          +
        • label_image_x (nd-array) – Image that should serve as a reference for label-matching

        • +
        • label_image_y (nd-array) – Image the labels of which should be paired with labels from imageA

        • +
        • method (str, optional) –

          Pairing method to be used. The default is ‘iou’ (intersection over union).

          +
          +
          iou (intersection over union): The intersection over union is used to

          measure the overlap between labels in both images. The label with +highest overlap is chosen as counterpart label

          +
          +
          iou_streshold: float, optional

          Threshold value above which two labels are accepted as overlapping. +The default value is 0.25

          +
          +
          +
          +
          +

        • +
        +
        +
        Returns
        +

        Processed version of imageB with labels corresponding to imageA.

        +
        +
        Return type
        +

        nd-array

        +
        +
        +
        + +
        + + +
        + +
        +
        + +
        +
        + + + + + + + \ No newline at end of file diff --git a/doc/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html b/doc/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html index f3775ab..011bf14 100644 --- a/doc/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html +++ b/doc/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html @@ -17,7 +17,8 @@ - + + @@ -71,7 +72,12 @@

        biapol_utilities.label.match_labels_stack - - - - - - - -
        diff --git a/doc/_build/html/_include/notebooks/label/Compare_segmentations.html b/doc/_build/html/_include/notebooks/label/Compare_segmentations.html new file mode 100644 index 0000000..9f45111 --- /dev/null +++ b/doc/_build/html/_include/notebooks/label/Compare_segmentations.html @@ -0,0 +1,5798 @@ + + + + + + + + + Quantitative segmentation quality estimation — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + + +
        + + + +
        +

        Quantitative segmentation quality estimation

        +

        Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation.

        +
        +
        [1]:
        +
        +
        +
        +import os
        +import biapol_utilities as biau
        +from skimage import io, measure, segmentation
        +import numpy as np
        +import matplotlib.pyplot as plt
        +from mpl_toolkits.axes_grid1 import make_axes_locatable
        +import pandas as pd
        +
        +%matplotlib notebook
        +
        +
        +
        +
        +

        Input data

        +

        First, let’s generate some example data!

        +
        +
        [2]:
        +
        +
        +
        +blobs = biau.data.blobs()
        +
        +
        +
        +

        Let’s segment this and take it as a ground truth image:

        +
        +
        [3]:
        +
        +
        +
        +threshold = 128
        +imageA = (blobs > threshold).astype(np.uint8)
        +ground_truth = measure.label(imageA)
        +
        +plt.imshow(ground_truth)
        +plt.title('Ground truth')
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        [3]:
        +
        +
        +
        +
        +Text(0.5, 1.0, 'Ground truth')
        +
        +
        +

        Next, we shuffle the labels and expand them a bit:

        +
        +
        [4]:
        +
        +
        +
        +# First, shuffle randomly
        +label_shuffle = np.arange(1, ground_truth.max()+1, 1)
        +np.random.shuffle(label_shuffle)
        +label_shuffle = np.append(np.asarray([0]), label_shuffle)  # append 0 at start of array - we don't want to shuffle background
        +segmented = label_shuffle[ground_truth]
        +
        +
        +
        +
        +
        [5]:
        +
        +
        +
        +# Second, expand the labels a bit
        +segmented = segmentation.expand_labels(segmented, 5)
        +
        +
        +
        +
        +
        [6]:
        +
        +
        +
        +# Plot side by side
        +fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
        +
        +axes[0].imshow(ground_truth)
        +axes[0].set_title('Ground truth')
        +
        +axes[1].imshow(segmented)
        +axes[1].set_title('Segmentation')
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        [6]:
        +
        +
        +
        +
        +Text(0.5, 1.0, 'Segmentation')
        +
        +
        +
        +
        +

        Re-match labels

        +

        Next, use the label-matching from biapol_utilities to assign correct labels to both images

        +
        +
        [7]:
        +
        +
        +
        +segmented = biau.label.match_labels(ground_truth, segmented)
        +
        +
        +
        +
        +
        [8]:
        +
        +
        +
        +# Plot side by side
        +fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
        +
        +axes[0].imshow(ground_truth)
        +axes[0].set_title('Ground truth')
        +
        +axes[1].imshow(segmented)
        +axes[1].set_title('Segmentation')
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        [8]:
        +
        +
        +
        +
        +Text(0.5, 1.0, 'Segmentation')
        +
        +
        +
        +
        +

        Compare labels: Labelwise Jaccard-index

        +

        Lastly, we calculate the label-wise Jaccard index to measure the intersection over union (IoU) between corresponding pairs of labels.

        +
        +
        [9]:
        +
        +
        +
        +result = biau.label.compare_labels(ground_truth, segmented)
        +result
        +
        +
        +
        +
        +
        [9]:
        +
        +
        +
        +
        + +

        data.blobs()

        data.blobs()

        Gray-level "blobs" image [1].

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        labeljaccard_scoredice_score
        000.4968470.663858
        110.5181020.682566
        220.4701300.639576
        330.6235520.768133
        440.6025460.751986
        ............
        63630.2628570.416290
        64640.0000000.000000
        65650.0000000.000000
        66660.0000000.000000
        67670.0000000.000000
        +

        68 rows × 3 columns

        +
        +
+

Let’s also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label.

+
+
[10]:
+
+
+
+LUT_jaccard = result['jaccard_score'].to_numpy()
+LUT_dice = result['dice_score'].to_numpy()
+
+# set segmentation quality of background to zero
+LUT_jaccard[0] = np.nan
+LUT_dice[0] = np.nan
+
+# create score map
+JI_map = LUT_jaccard[segmented]
+DI_map = LUT_dice[segmented]
+
+
+
+
+
[11]:
+
+
+
+# Plot side by side
+fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))
+fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)
+
+
+# Plot ground truth
+axes[0, 0].imshow(ground_truth)
+axes[0, 0].set_title('Ground truth')
+
+# Plot segmentation
+axes[0, 1].imshow(segmented)
+axes[0, 1].set_title('Segmentation')
+
+# Plot overlay
+axes[0, 2].imshow(ground_truth)
+axes[0, 2].imshow(segmented, alpha=0.5)
+axes[0, 2].set_title('Overlay')
+
+# Plot Jaccard index map
+im = axes[1, 0].imshow(JI_map, cmap='inferno_r')
+axes[1, 0].set_title('Jaccard score')
+cbar = fig.colorbar(im, ax=axes[1, 0])
+
+# Plot Dice score map
+im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')
+axes[1, 1].set_title('Dice score')
+cbar2 = fig.colorbar(im2, ax=axes[1, 1])
+
+axes[-1, -1].axis('off')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[11]:
+
+
+
+
+(-0.5, 255.5, 253.5, -0.5)
+
+
+
+
+

Compare-labels: Feature-wise

+

It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops.

+
+
[12]:
+
+
+
+properties = ['label', 'area', 'eccentricity', 'orientation']
+features_gt = measure.regionprops_table(ground_truth, properties=properties)
+features_seg = measure.regionprops_table(segmented, properties=properties)
+
+features_gt = pd.DataFrame(features_gt)
+features_seg = pd.DataFrame(features_seg)
+features_gt
+
+
+
+
+
[12]:
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
+

63 rows × 4 columns

+
+
+

Visualize as histograms

+
+
[13]:
+
+
+
+fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))
+
+ax_idx = 0
+for idx, prop in enumerate(properties):
+    if  prop == 'label':
+        continue
+
+    axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)
+    axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)
+    axes[ax_idx].set_xlabel(prop)
+    ax_idx += 1
+
+axes[0].legend()
+axes[0].set_ylabel('# Occurrences')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[13]:
+
+
+
+
+Text(0, 0.5, '# Occurrences')
+
+
+
+
[ ]:
+
+
+
+
+
+
+
+
+ + + +
+ + + + +
+ + + + + + + + \ No newline at end of file diff --git a/notebooks/label/Compare_segmentations.ipynb b/doc/_build/html/_include/notebooks/label/Compare_segmentations.ipynb similarity index 100% rename from notebooks/label/Compare_segmentations.ipynb rename to doc/_build/html/_include/notebooks/label/Compare_segmentations.ipynb diff --git a/doc/_build/html/_include/notebooks/label/match_labels.html b/doc/_build/html/_include/notebooks/label/match_labels.html new file mode 100644 index 0000000..7ec2864 --- /dev/null +++ b/doc/_build/html/_include/notebooks/label/match_labels.html @@ -0,0 +1,3465 @@ + + + + + + + + + Matching labels — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + + +
+

Matching labels

+

This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image.

+
+
[3]:
+
+
+
+import os
+import biapol_utilities as biau
+from skimage import io, measure, filters
+import numpy as np
+import matplotlib.pyplot as plt
+from datetime import datetime
+
+%matplotlib notebook
+
+
+
+
+

Load data

+

First, we load the example blobs image and threshold it to create a label map.

+
+
[4]:
+
+
+
+blobs = biau.data.blobs()
+
+
+
+
+
[5]:
+
+
+
+threshold = 128
+imageA = (blobs > threshold).astype(np.uint8)
+imageA_labelled = measure.label(imageA)
+
+plt.imshow(imageA_labelled)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[5]:
+
+
+
+
+<matplotlib.image.AxesImage at 0x29c86bdabe0>
+
+
+

Let’s create a second version of this image in which we shuffle the labels:

+
+
[6]:
+
+
+
+label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)
+np.random.shuffle(label_shuffle)
+label_shuffle = np.append(np.asarray([0]), label_shuffle)  # append 0 at start of array - we don't want to shuffle background
+
+imageB_labelled = label_shuffle[imageA_labelled]
+
+
+
+

Both images are not identical!

+
+
[7]:
+
+
+
+fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
+axes[0].imshow(imageA_labelled)
+axes[0].set_title('Reference image')
+axes[1].imshow(imageB_labelled)
+axes[1].set_title('Shuffled image')
+
+print(f'Number of labels in imageA: {imageA_labelled.max()}')
+print(f'Number of labels in imageB: {imageB_labelled.max()}')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Number of labels in imageA: 63
+Number of labels in imageB: 63
+
+
+

Match labels and track time

+
+
[8]:
+
+
+
+t0 = datetime.now()
+output = biau.label.match_labels(imageA_labelled, imageB_labelled)
+t1 = datetime.now()
+print(f'Took {(t1-t0).seconds*1000} ms')
+
+
+
+
+
+
+
+
+Took 0 ms
+
+
+

Visualize

+
+
[9]:
+
+
+
+fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
+axes[0].imshow(imageA_labelled)
+axes[0].set_title('Reference image')
+axes[1].imshow(output)
+axes[1].set_title('Relabelled image')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[9]:
+
+
+
+
+Text(0.5, 1.0, 'Relabelled image')
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/notebooks/label/match_labels.ipynb b/doc/_build/html/_include/notebooks/label/match_labels.ipynb similarity index 100% rename from notebooks/label/match_labels.ipynb rename to doc/_build/html/_include/notebooks/label/match_labels.ipynb diff --git a/doc/_build/html/_include/notebooks/label/visualize_labels.html b/doc/_build/html/_include/notebooks/label/visualize_labels.html new file mode 100644 index 0000000..4897c53 --- /dev/null +++ b/doc/_build/html/_include/notebooks/label/visualize_labels.html @@ -0,0 +1,411 @@ + + + + + + + + + Labels visualized in colours — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + + +
+
[1]:
+
+
+
+import biapol_utilities as biao
+from skimage.measure import label
+from skimage.io import imshow
+
+
+
+
+
[2]:
+
+
+
+blobs = biao.blobs()
+labels = label(blobs > 128)
+
+
+
+
+

Labels visualized in colours

+

biapol_utilities provided a standardized color map for visualizing labels in:

+
+
[4]:
+
+
+
+imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())
+
+
+
+
+
[4]:
+
+
+
+
+<matplotlib.image.AxesImage at 0x17fe4272220>
+
+
+
+
+
+
+../../../_images/_include_notebooks_label_visualize_labels_3_1.png +
+
+
+
[ ]:
+
+
+
+
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/notebooks/label/visualize_labels.ipynb b/doc/_build/html/_include/notebooks/label/visualize_labels.ipynb similarity index 100% rename from notebooks/label/visualize_labels.ipynb rename to doc/_build/html/_include/notebooks/label/visualize_labels.ipynb diff --git a/doc/_build/html/_sources/_include/API_reference.rst.txt b/doc/_build/html/_sources/_include/API_reference.rst.txt index 21cf6f0..f94c3ba 100644 --- a/doc/_build/html/_sources/_include/API_reference.rst.txt +++ b/doc/_build/html/_sources/_include/API_reference.rst.txt @@ -1,9 +1,11 @@ API Reference ============= - +This is the class and function reference of biapol-utilities. Please refer to the examples for further details, as the class and function raw specifications may not be enough to give full guidelines on their uses. The label module ------------------ +The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of +an object is encoded in the pixel value which must be an integer number. .. currentmodule:: biapol_utilities @@ -13,13 +15,17 @@ The label module label.compare_labels label.intersection_over_union_matrix + label.match_labels label.match_labels_stack The data module ------------------ +The data module provides example data to be usedin the examples section. .. currentmodule:: biapol_utilities .. autosummary:: + :recursive: + :toctree: generated data.blobs \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/Examples.rst.txt b/doc/_build/html/_sources/_include/Examples.rst.txt index de920ec..792bb14 100644 --- a/doc/_build/html/_sources/_include/Examples.rst.txt +++ b/doc/_build/html/_sources/_include/Examples.rst.txt @@ -1,17 +1,21 @@ Examples -============================= - +============= +This is the example library of biapol-utilities. We provide examples for all top-level functions that are listed +in the API reference and comment on their usage here. Label module ------------------ +The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of +an object is encoded in the pixel value which must be an integer number. + .. toctree:: :titlesonly: :maxdepth: 0 - Match labels <../../notebooks/label/match_labels.ipynb> - Compare segmentations <../../notebooks/label/Compare_segmentations.ipynb> + Match labels + Compare segmentations + Visualize labels Data module ------------------ - - +The data module provides example data to be usedin the examples section. diff --git a/doc/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt b/doc/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt new file mode 100644 index 0000000..286bf6d --- /dev/null +++ b/doc/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.compare\_labels +======================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: compare_labels \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt b/doc/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt new file mode 100644 index 0000000..3b66942 --- /dev/null +++ b/doc/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.intersection\_over\_union\_matrix +========================================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: intersection_over_union_matrix \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt b/doc/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt new file mode 100644 index 0000000..2f71b54 --- /dev/null +++ b/doc/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.match\_labels\_stack +============================================ + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: match_labels_stack \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt b/doc/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt new file mode 100644 index 0000000..16a40fd --- /dev/null +++ b/doc/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.data.blobs +============================ + +.. currentmodule:: biapol_utilities.data + +.. autofunction:: blobs \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt new file mode 100644 index 0000000..ae8b654 --- /dev/null +++ b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.match\_labels +===================================== + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: match_labels \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt b/doc/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt new file mode 100644 index 0000000..b694e2f --- /dev/null +++ b/doc/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt @@ -0,0 +1,5614 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9f0d8ccf", + "metadata": {}, + "source": [ + "# Quantitative segmentation quality estimation\n", + "\n", + "Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "89205b6d", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import biapol_utilities as biau\n", + "from skimage import io, measure, segmentation\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", + "import pandas as pd\n", + "\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "markdown", + "id": "a63045b4", + "metadata": {}, + "source": [ + "## Input data\n", + "First, let's generate some example data!" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "db9c5fe0", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biau.data.blobs()" + ] + }, + { + "cell_type": "markdown", + "id": "2c0c8418", + "metadata": {}, + "source": [ + "Let's segment this and take it as a ground truth image:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2ae66de8", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Ground truth')" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "threshold = 128\n", + "imageA = (blobs > threshold).astype(np.uint8)\n", + "ground_truth = measure.label(imageA)\n", + "\n", + "plt.imshow(ground_truth)\n", + "plt.title('Ground truth')" + ] + }, + { + "cell_type": "markdown", + "id": "f7f4c0be", + "metadata": {}, + "source": [ + "Next, we shuffle the labels and expand them a bit:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2b8dc27c", + "metadata": {}, + "outputs": [], + "source": [ + "# First, shuffle randomly\n", + "label_shuffle = np.arange(1, ground_truth.max()+1, 1)\n", + "np.random.shuffle(label_shuffle)\n", + "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", + "segmented = label_shuffle[ground_truth]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "279f3e2c", + "metadata": {}, + "outputs": [], + "source": [ + "# Second, expand the labels a bit\n", + "segmented = segmentation.expand_labels(segmented, 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "eb0b69c2", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Segmentation')" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "\n", + "axes[0].imshow(ground_truth)\n", + "axes[0].set_title('Ground truth')\n", + "\n", + "axes[1].imshow(segmented)\n", + "axes[1].set_title('Segmentation')" + ] + }, + { + "cell_type": "markdown", + "id": "dd726a7c", + "metadata": {}, + "source": [ + "## Re-match labels\n", + "\n", + "Next, use the label-matching from `biapol_utilities` to assign correct labels to both images" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8007d578", + "metadata": {}, + "outputs": [], + "source": [ + "segmented = biau.label.match_labels(ground_truth, segmented)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "23496dad", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Segmentation')" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "\n", + "axes[0].imshow(ground_truth)\n", + "axes[0].set_title('Ground truth')\n", + "\n", + "axes[1].imshow(segmented)\n", + "axes[1].set_title('Segmentation')" + ] + }, + { + "cell_type": "markdown", + "id": "1e1d39a4", + "metadata": {}, + "source": [ + "## Compare labels: Labelwise Jaccard-index\n", + "\n", + "Lastly, we calculate the *label-wise Jaccard index* to measure the intersection over union (IoU) between corresponding pairs of labels." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "7641d30b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
\n", + "

68 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " label jaccard_score dice_score\n", + "0 0 0.496847 0.663858\n", + "1 1 0.518102 0.682566\n", + "2 2 0.470130 0.639576\n", + "3 3 0.623552 0.768133\n", + "4 4 0.602546 0.751986\n", + ".. ... ... ...\n", + "63 63 0.262857 0.416290\n", + "64 64 0.000000 0.000000\n", + "65 65 0.000000 0.000000\n", + "66 66 0.000000 0.000000\n", + "67 67 0.000000 0.000000\n", + "\n", + "[68 rows x 3 columns]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result = biau.label.compare_labels(ground_truth, segmented)\n", + "result" + ] + }, + { + "cell_type": "markdown", + "id": "3f218dd4", + "metadata": {}, + "source": [ + "Let's also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "fab77a34", + "metadata": {}, + "outputs": [], + "source": [ + "LUT_jaccard = result['jaccard_score'].to_numpy()\n", + "LUT_dice = result['dice_score'].to_numpy()\n", + "\n", + "# set segmentation quality of background to zero\n", + "LUT_jaccard[0] = np.nan\n", + "LUT_dice[0] = np.nan\n", + "\n", + "# create score map\n", + "JI_map = LUT_jaccard[segmented]\n", + "DI_map = LUT_dice[segmented]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ca62489c", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(-0.5, 255.5, 253.5, -0.5)" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))\n", + "fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)\n", + "\n", + "\n", + "# Plot ground truth\n", + "axes[0, 0].imshow(ground_truth)\n", + "axes[0, 0].set_title('Ground truth')\n", + "\n", + "# Plot segmentation\n", + "axes[0, 1].imshow(segmented)\n", + "axes[0, 1].set_title('Segmentation')\n", + "\n", + "# Plot overlay\n", + "axes[0, 2].imshow(ground_truth)\n", + "axes[0, 2].imshow(segmented, alpha=0.5)\n", + "axes[0, 2].set_title('Overlay')\n", + "\n", + "# Plot Jaccard index map\n", + "im = axes[1, 0].imshow(JI_map, cmap='inferno_r')\n", + "axes[1, 0].set_title('Jaccard score')\n", + "cbar = fig.colorbar(im, ax=axes[1, 0])\n", + "\n", + "# Plot Dice score map\n", + "im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')\n", + "axes[1, 1].set_title('Dice score')\n", + "cbar2 = fig.colorbar(im2, ax=axes[1, 1])\n", + "\n", + "axes[-1, -1].axis('off')" + ] + }, + { + "cell_type": "markdown", + "id": "1dc2ca58", + "metadata": {}, + "source": [ + "## Compare-labels: Feature-wise\n", + "It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "5f6cc904", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
\n", + "

63 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " label area eccentricity orientation\n", + "0 1 415 0.878888 -0.433915\n", + "1 2 181 0.822705 -1.513862\n", + "2 3 646 0.386542 -0.079653\n", + "3 4 426 0.324798 -0.400592\n", + "4 5 465 0.780472 -0.044317\n", + ".. ... ... ... ...\n", + "58 59 1 0.000000 0.785398\n", + "59 60 87 0.969263 -1.560717\n", + "60 61 73 0.951468 -1.567605\n", + "61 62 49 0.942191 -1.554054\n", + "62 63 46 0.976786 1.538848\n", + "\n", + "[63 rows x 4 columns]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "properties = ['label', 'area', 'eccentricity', 'orientation']\n", + "features_gt = measure.regionprops_table(ground_truth, properties=properties)\n", + "features_seg = measure.regionprops_table(segmented, properties=properties)\n", + "\n", + "features_gt = pd.DataFrame(features_gt)\n", + "features_seg = pd.DataFrame(features_seg)\n", + "features_gt" + ] + }, + { + "cell_type": "markdown", + "id": "ec29004b", + "metadata": {}, + "source": [ + "Visualize as histograms" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "e9652f8d", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0, 0.5, '# Occurrences')" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))\n", + "\n", + "ax_idx = 0\n", + "for idx, prop in enumerate(properties):\n", + " if prop == 'label':\n", + " continue\n", + " \n", + " axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)\n", + " axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)\n", + " axes[ax_idx].set_xlabel(prop)\n", + " ax_idx += 1\n", + " \n", + "axes[0].legend()\n", + "axes[0].set_ylabel('# Occurrences')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "185d4c1d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt b/doc/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt new file mode 100644 index 0000000..181425a --- /dev/null +++ b/doc/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt @@ -0,0 +1,3198 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e5db44ea", + "metadata": {}, + "source": [ + "## Matching labels\n", + "This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d1ca8e7a", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import biapol_utilities as biau\n", + "from skimage import io, measure, filters\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from datetime import datetime\n", + "\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "markdown", + "id": "ee62539b", + "metadata": {}, + "source": [ + "### Load data\n", + "First, we load the example blobs image and threshold it to create a label map. " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "7fe70350", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biau.data.blobs()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "909ce3b2", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "threshold = 128\n", + "imageA = (blobs > threshold).astype(np.uint8)\n", + "imageA_labelled = measure.label(imageA)\n", + "\n", + "plt.imshow(imageA_labelled)" + ] + }, + { + "cell_type": "markdown", + "id": "1cbf5ae3", + "metadata": {}, + "source": [ + "Let's create a second version of this image in which we shuffle the labels:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "29986d79", + "metadata": {}, + "outputs": [], + "source": [ + "label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)\n", + "np.random.shuffle(label_shuffle)\n", + "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", + "\n", + "imageB_labelled = label_shuffle[imageA_labelled]" + ] + }, + { + "cell_type": "markdown", + "id": "1393dfb7", + "metadata": {}, + "source": [ + "Both images are not identical!" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "1ff3c80c", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of labels in imageA: 63\n", + "Number of labels in imageB: 63\n" + ] + } + ], + "source": [ + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "axes[0].imshow(imageA_labelled)\n", + "axes[0].set_title('Reference image')\n", + "axes[1].imshow(imageB_labelled)\n", + "axes[1].set_title('Shuffled image')\n", + "\n", + "print(f'Number of labels in imageA: {imageA_labelled.max()}')\n", + "print(f'Number of labels in imageB: {imageB_labelled.max()}')" + ] + }, + { + "cell_type": "markdown", + "id": "7a38be04", + "metadata": {}, + "source": [ + "Match labels and track time" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "79f0cf74", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Took 0 ms\n" + ] + } + ], + "source": [ + "t0 = datetime.now()\n", + "output = biau.label.match_labels(imageA_labelled, imageB_labelled)\n", + "t1 = datetime.now()\n", + "print(f'Took {(t1-t0).seconds*1000} ms')" + ] + }, + { + "cell_type": "markdown", + "id": "a8710824", + "metadata": {}, + "source": [ + "Visualize" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "84ed2639", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Relabelled image')" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "axes[0].imshow(imageA_labelled)\n", + "axes[0].set_title('Reference image')\n", + "axes[1].imshow(output)\n", + "axes[1].set_title('Relabelled image')" + ] + } + ], + "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.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt b/doc/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt new file mode 100644 index 0000000..9924ff8 --- /dev/null +++ b/doc/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt @@ -0,0 +1,98 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "803a884d", + "metadata": {}, + "outputs": [], + "source": [ + "import biapol_utilities as biao\n", + "from skimage.measure import label\n", + "from skimage.io import imshow" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "af876b71", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biao.blobs()\n", + "labels = label(blobs > 128)" + ] + }, + { + "cell_type": "markdown", + "id": "d9ded05a", + "metadata": {}, + "source": [ + "# Labels visualized in colours\n", + "`biapol_utilities` provided a standardized color map for visualizing labels in:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "5c3f2337", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "867149ee", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/_build/html/_sources/index.rst.txt b/doc/_build/html/_sources/index.rst.txt index 217e66a..67ee96f 100644 --- a/doc/_build/html/_sources/index.rst.txt +++ b/doc/_build/html/_sources/index.rst.txt @@ -1,11 +1,11 @@ Welcome to BiAPoL utilities's documentation! ============================================ -On this page, we provide docuemntation pages for our API and provide +On this page, we provide documentation pages for our API and provide comprehensive examples on how to use the functions in our library. .. toctree:: - :maxdepth: 3 + :maxdepth: 2 :caption: Contents: _include/Examples @@ -18,3 +18,9 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` + +Ressources +================== + + * BiAPoL group blog: ``_. + * Source code: ``_. \ No newline at end of file diff --git a/doc/_build/html/_static/logos/biapol_logo.png b/doc/_build/html/_static/logos/biapol_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0945d112a0d6994fafdcde2f1a5737fd5061142a GIT binary patch literal 41688 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%0A8QEJHw@N2mVDcG3H0qLCC&NopN85|PG%C^ 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

- C + B + | C | I | M
+

B

+ + +
+

C

@@ -52,7 +61,7 @@

C

I

@@ -60,7 +69,11 @@

I

M

+
@@ -73,7 +86,12 @@

M

- - - - - - - -
diff --git a/doc/_build/html/index.html b/doc/_build/html/index.html index 902293d..8fb7099 100644 --- a/doc/_build/html/index.html +++ b/doc/_build/html/index.html @@ -36,25 +36,18 @@

Welcome to BiAPoL utilities’s documentation!

-

On this page, we provide docuemntation pages for our API and provide +

On this page, we provide documentation pages for our API and provide comprehensive examples on how to use the functions in our library.

+
+

Ressources

+
+
@@ -77,7 +79,12 @@

Indices and tables
-

BiAPoL utilities

+ @@ -111,14 +118,6 @@

Quick search

- - - - - - - -
diff --git a/doc/_build/html/objects.inv b/doc/_build/html/objects.inv index 54c0b75faa9674884077ecc0a636e520203ffb05..c84ecea155641e68a3d15e823aa3713108058dff 100644 GIT binary patch delta 1339 zcmV-B1;qN^1*i*Srw}gH#wh01E}~*$!O?akWF=Y_{eq(4n-jZ2)!F*CRf96( z=lBulI0^73FDNKzc*}bMD4F|se<#URiU4Z@4^7jYN{_X`wnf=Muba9#dc?4bco?T) z8EF{ocl_;$L4S1(#Py<4Zp6rHr)OnW^c>h#n{CsNQGK=oB~cS-o{)sCWbJ(|3G4Z0 z>wuz}wcT7=U>&)+WX6%33k#}t;3+K7z^JPWSEeFJ?g^`&koSc3X61SS3}L+Yu<7pc zD-D}2jFpCMWH;8HEE79AP!>0ZITe9ix?V`3$W~l9q<>-VQm(5cY7SjjF=ygBenW8< z;kgXqb0fk-tGSxc;Vq|G9eo}7pGGsQj{4?8Np~x}1X>|Y>uTVpG}CyK@>@FvG=OWB+8c2S>m>Q+uA8O% z7OuNa{C{mZ6^o#~L^0sNJ*Q=X6AJ5n3IumU>84b0IFy$z8uUm+izzlBBURE!8=xw= zyfbH%j9tdzc`n(p!}G>gba=6nHD#%dsvAS-*43>s6~AtsYd0L`6|d!RtX2CaDaD60 z{Z?$bz_!VN3j7q~graJZE;b}PC5H*e`WilsYJcG2`?W*~B~{Z4D>0?};JHK$^9kUB zl9)G{Vf4Bw?k#-8h?ea7l@!?80q;{!`_HoW-c2CibmR^Ht@Ob^P!OOzWZ6uJ-`qR4 zYYqLZ9;bmR=(B}rCNUJBcLba&Rp|MDX%LtM{N+(KCZ)^Q8ZachtKtB$n` zOn)gB77BTZhJz11h0Qe>Y`cA>ovmJHQ5t4=U#b?8Jee5vq7;QXaXL&os!5y`&ZWSD*S>pg@X*QfE~Xkjp*pm z8prWB5jYMesrSyufG!_ZGjXDzch)_s**W=XckHNxaXqd}|Kv#rw|%{)$GwkYbANPJ zVoJa2VsaLhmJF8}?h8b!R>f%Mg&FZ>Q`6exw47f`dFm+2wF+IOWK9Xta+a%{=qTAU zNa9dNfa8}QMG)*)J>b+osU4!~tYUlrx=;P4;LD5Gp08eev3%|Q|JRAm)Bx}~w)d}< zqgR5x_y04*ZO|i}S_TYUIRn%i5T)#)+|U z9f{%W1e+Um@+F>yh-T^TLbv-9J+e%()B9N?p}b}WI`2}w>vPEp%+-xdSTq$F<*au{ xRytDjz>tM3;cwL&G4}V_P8>UDMzb{bOTl6$7#91Oo-y7BX_C<#eYGkeyWBpO zJP<79a05Q$L0pD-ctVaj6&N1QE-?E@B(e7%$j+k9xWK$X#ed_cKQZ@9UVSE1L7VSvX<0%41GD_v4DN?hJN1IG@4%d^ z3Y=7zx$9|7(rVVnuGS>=1-xERj)ZR)`dIH-J@hfc)k7cYKMM}6LuZ3ort5}hJ9Ax2 zQdtsZN$P&TT~cN`^#7!C>gcq2DyKTMc`64+tp$Z<8GqcsS$(ua0n@pRoF zClJ4VI$WmpP14~)JRu#7hd9s*v{)Ur?-N6bza5y=`htP7-h5SfNrrfnYd{}X+}-9LuQ F6{;SoE9d|K diff --git a/doc/_build/html/search.html b/doc/_build/html/search.html index 71ab514..df21b5d 100644 --- a/doc/_build/html/search.html +++ b/doc/_build/html/search.html @@ -75,7 +75,12 @@

Search

diff --git a/doc/_build/html/searchindex.js b/doc/_build/html/searchindex.js index 72c9c03..8c31e0a 100644 --- a/doc/_build/html/searchindex.js +++ b/doc/_build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["_include/API_reference","_include/Examples","_include/generated/biapol_utilities.label.compare_labels","_include/generated/biapol_utilities.label.intersection_over_union_matrix","_include/generated/biapol_utilities.label.match_labels_stack","index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,nbsphinx:3,sphinx:56},filenames:["_include\\API_reference.rst","_include\\Examples.rst","_include\\generated\\biapol_utilities.label.compare_labels.rst","_include\\generated\\biapol_utilities.label.intersection_over_union_matrix.rst","_include\\generated\\biapol_utilities.label.match_labels_stack.rst","index.rst"],objects:{"biapol_utilities.label":{compare_labels:[2,0,1,""],intersection_over_union_matrix:[3,0,1,""],match_labels_stack:[4,0,1,""]}},objnames:{"0":["py","function","Python function"]},objtypes:{"0":"py:function"},terms:{"0":[3,4],"1":[2,3],"2":3,"25":4,"2d":[3,4],"2j":2,"3d":4,"default":4,"float":[3,4],"function":[4,5],"int":[2,3,4],"return":[2,3,4],"true":3,On:5,The:[2,3,4,5],_:2,abov:4,ad:3,all:3,along:3,an:3,api:5,ar:[3,4],arbitrari:2,area:3,arrai:[2,3,4],axi:[3,4],background:3,becaus:3,between:[2,3],biapol_util:5,can:2,clij2:3,clij:3,column:[2,3],compar:2,compare_label:5,comprehens:5,consid:4,correspond:2,data:5,datafram:2,defin:2,deriv:2,determin:2,dice:2,dice_scor:2,differ:2,dimens:2,doc:3,docuemnt:5,duplic:3,each:[2,3],equival:3,evalu:2,everi:3,exampl:5,except:3,find:3,follow:2,frac:2,from:[2,4],gener:3,github:3,give:3,guarante:3,have:2,how:[3,5],http:3,ident:4,imag:[2,3,4],includ:3,index:5,intersect:[2,3],intersection_over_union_matrix:[4,5],io:3,iou:[3,4],j:2,jaccard:2,jaccard_scor:2,kwarg:4,label:5,label_image_i:[2,3],label_image_x:[2,3],label_stack:4,librari:5,likewis:3,lookup:3,mask:[3,4],match:4,match_labels_stack:5,matrix:3,max:3,measur:2,method:4,modul:5,must:2,nd:[2,3],option:4,order:4,our:5,over:[2,3],overlap:3,page:5,pair:3,panda:2,paramet:[2,3,4],predict:3,provid:5,quantitii:2,reconstruct:3,refer:[3,5],reference_generatejaccardindexmatrix:3,relat:2,respect:2,row:[2,3],s:2,same:2,score:2,search:5,set:3,size:3,slice:4,so:3,sourc:3,specifi:4,stack:4,stitch:4,stitch_threshold:4,str:4,subsequ:4,subtract:3,sum:3,tabl:3,taken:3,thi:[3,5],threshold:4,through:2,thu:3,togeth:3,total:3,two:[2,4],type:[3,4],union:[2,3],us:[4,5],valu:4,vector:3,we:5,where:3,which:[2,4],wise:2,work:3,x:3,y:3,zyx:4},titles:["API Reference","Examples","biapol_utilities.label.compare_labels","biapol_utilities.label.intersection_over_union_matrix","biapol_utilities.label.match_labels_stack","Welcome to BiAPoL utilities\u2019s documentation!"],titleterms:{The:0,api:0,biapol:5,biapol_util:[2,3,4],compare_label:2,content:5,data:[0,1],document:5,exampl:1,indic:5,intersection_over_union_matrix:3,label:[0,1,2,3,4],match_labels_stack:4,modul:[0,1],refer:0,s:5,tabl:5,util:5,welcom:5}}) \ No newline at end of file +Search.setIndex({docnames:["_include/API_reference","_include/Examples","_include/biapol_utilities.label.compare_labels","_include/biapol_utilities.label.intersection_over_union_matrix","_include/biapol_utilities.label.match_labels_stack","_include/generated/biapol_utilities.data.blobs","_include/generated/biapol_utilities.label.compare_labels","_include/generated/biapol_utilities.label.intersection_over_union_matrix","_include/generated/biapol_utilities.label.match_labels","_include/generated/biapol_utilities.label.match_labels_stack","_include/notebooks/label/Compare_segmentations","_include/notebooks/label/match_labels","_include/notebooks/label/visualize_labels","index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,nbsphinx:3,sphinx:56},filenames:["_include\\API_reference.rst","_include\\Examples.rst","_include\\biapol_utilities.label.compare_labels.rst","_include\\biapol_utilities.label.intersection_over_union_matrix.rst","_include\\biapol_utilities.label.match_labels_stack.rst","_include\\generated\\biapol_utilities.data.blobs.rst","_include\\generated\\biapol_utilities.label.compare_labels.rst","_include\\generated\\biapol_utilities.label.intersection_over_union_matrix.rst","_include\\generated\\biapol_utilities.label.match_labels.rst","_include\\generated\\biapol_utilities.label.match_labels_stack.rst","_include\\notebooks\\label\\Compare_segmentations.ipynb","_include\\notebooks\\label\\match_labels.ipynb","_include\\notebooks\\label\\visualize_labels.ipynb","index.rst"],objects:{"biapol_utilities.data":{blobs:[5,0,1,""]},"biapol_utilities.label":{compare_labels:[6,0,1,""],intersection_over_union_matrix:[7,0,1,""],match_labels:[8,0,1,""],match_labels_stack:[9,0,1,""]}},objnames:{"0":["py","function","Python function"]},objtypes:{"0":"py:function"},terms:{"0":[3,4,7,8,9,10,11,12],"000000":10,"044317":10,"05":10,"06":10,"079653":10,"0x17fe4272220":12,"0x29c86bdabe0":11,"1":[2,3,5,6,7,10,11,12],"10":10,"1000":11,"11":10,"12":10,"128":[10,11,12],"13":10,"181":10,"2":[3,7,10,11,12],"20":10,"25":[4,8,9],"253":10,"254":5,"255":10,"256":5,"262857":10,"2d":[3,4,7,9],"2j":[2,6],"3":[10,11],"324798":10,"386542":10,"39":[10,11],"3d":[4,9],"4":[10,11,12],"400592":10,"415":10,"416290":10,"426":10,"433915":10,"46":10,"465":10,"470130":10,"49":10,"496847":10,"5":[10,11],"513862":10,"518102":10,"538848":10,"554054":10,"560717":10,"567605":10,"58":10,"59":10,"6":[10,11],"60":10,"602546":10,"61":10,"62":10,"623552":10,"63":[10,11],"639576":10,"64":10,"646":10,"65":10,"66":10,"663858":10,"67":10,"68":10,"682566":10,"7":[10,11],"73":10,"751986":10,"768133":10,"780472":10,"785398":10,"8":[10,11],"822705":10,"85":10,"87":10,"878888":10,"9":[10,11],"942191":10,"95":10,"951468":10,"969263":10,"976786":10,"class":0,"default":[4,8,9],"do":10,"float":[3,4,7,8,9],"function":[0,1,4,8,9,13],"import":[10,11,12],"int":[2,3,4,6,7,9],"new":10,"return":[2,3,4,5,6,7,8,9],"true":[3,7,10,11],For:10,It:10,On:13,The:[1,2,3,4,6,7,8,9,13],To:10,_:[2,6],abov:[4,8,9],accept:8,achiev:10,ad:[3,7],agreement:10,all:[1,3,7],along:[3,7],alpha:10,also:10,an:[0,1,3,7,10],annnoot:10,annnot:10,annot:[0,1,10],api:[1,13],append:[10,11],approach:10,ar:[1,3,4,7,8,9,10,11],arang:[10,11],arbitrari:[2,6],area:[3,7,10],arrai:[2,3,4,6,7,8,9,10,11],asarrai:[10,11],assign:[10,11],astyp:[10,11],ax:[10,11],ax_idx:10,axes_grid1:10,axesimag:[11,12],axi:[3,4,7,9,10],background:[3,7,10,11],becaus:[3,7],between:[2,3,6,7,8,10],biao:12,biapol:[0,1],biapol_util:[10,11,12],biau:[10,11],bin:10,bit:10,blob:[10,11,12],blog:13,both:[8,10,11],bottom:10,bundl:[0,1],calcul:10,can:[2,5,6],cbar2:10,cbar:10,certain:10,check:10,chosen:8,clij2:[3,7],clij:[3,7],cmap:[10,12],code:13,color:12,colorbar:10,column:[2,3,6,7,10],com:13,comment:1,compar:[1,2,6,11],compare_label:10,comprehens:13,consid:[4,9],continu:10,convert:11,correct:10,correspond:[2,6,8,10],counterpart:8,creat:[10,11],data:13,datafram:[2,6,10],datetim:11,defin:[2,6],denois:5,depend:10,deriv:[2,6],detail:0,determin:[2,6],di_map:10,dice:[2,6,10],dice_scor:[2,6,10],differ:[2,6],dimens:[2,6],doc:[3,7],docuemnt:[],don:[10,11],duplic:[3,7],e:[0,1],each:[2,3,6,7],eccentr:10,encod:[0,1],enough:0,enumer:10,epyseg:10,equival:[3,7],etc:10,evalu:[2,6],everi:[3,7,10],exampl:[0,5,10,11,13],except:[3,7],expand:10,expand_label:10,f:11,face:10,features_gt:10,features_seg:10,fig:[10,11],figsiz:10,filter:11,find:[3,7],first:[10,11],follow:[2,6],frac:[2,6],from:[2,4,6,8,9,10,11,12],full:0,further:0,gener:[3,7,10],github:[3,7,13],give:[0,3,7],gov:5,grai:5,ground:10,ground_truth:10,group:13,gt:[11,12],guarante:[3,7],guidelin:0,have:[2,6,10],here:1,highest:8,hist:10,histogram:10,how:[3,7,13],http:[3,5,7,13],i:[0,1],idend:[0,1],ident:[4,9,11],idx:10,ij:5,im2:10,im:10,imag:[0,1,2,3,4,5,6,7,8,9,10,11,12],imagea:[8,10,11],imagea_label:11,imageb:[8,11],imageb_label:11,imagej:5,imshow:[10,11,12],includ:[3,7],index:13,inferno_r:10,integ:[0,1],interest:10,intersect:[2,3,6,7,8,10],intersection_over_union_matrix:[4,8,9],io:[3,7,10,11,12,13],iou:[3,4,7,8,9,10],iou_streshold:8,j:[2,6],jaccard:[2,6],jaccard_scor:[2,6,10],ji_map:10,kwarg:[4,8,9],label:13,label_image_i:[2,3,6,7,8],label_image_x:[2,3,6,7,8],label_shuffl:[10,11],label_stack:[4,9],labels_colormap:12,lastli:10,left:10,legend:10,len:10,let:[10,11],level:[1,5],librari:[1,13],likewis:[3,7],list:1,lookup:[3,7],lt:[11,12],lut_dic:10,lut_jaccard:10,mai:[0,10],make_axes_locat:10,map:[10,11,12],mask:[3,4,7,9],match:[1,4,8,9],match_label:[10,11],match_labels_stack:[],matplotlib:[10,11,12],matrix:[3,7],max:[3,7,10,11,12],measur:[2,6,8,10,11,12],method:[4,8,9,10],modul:13,mpl_toolkit:10,ms:11,must:[0,1,2,6],nan:10,ncol:[10,11],nd:[2,3,6,7,8],ndarrai:5,next:10,nih:5,notebook:[10,11],now:11,np:[10,11],nrow:10,number:[0,1,11],numpi:[10,11],object:[0,1],obtain:10,occurr:10,off:10,often:10,one:11,onli:10,oper:[0,1],option:[4,8,9],order:[4,9],orient:10,os:[10,11],our:13,output:11,over:[2,3,6,7,8,10],overlai:10,overlap:[3,7,8,10],page:13,pair:[3,7,8,10],panda:[2,6,10],paramet:[2,3,4,6,7,8,9],pd:10,pipelin:10,pixel:[0,1,10],plantseg:10,pleas:0,plot:10,plt:[10,11],predict:[3,7],preserv:10,print:11,problem:10,process:8,prop:10,properti:10,provid:[0,1,10,12,13],pyplot:[10,11],quantitii:[2,6],random:[10,11],randomli:10,raw:0,reconstruct:[3,7],refer:[1,3,5,7,8,11,13],reference_generatejaccardindexmatrix:[3,7],regionprop:10,regionprops_t:10,relabel:11,relat:[2,6],resembl:11,respect:[2,6],result:10,right:10,row:[2,3,6,7,10],s:[2,6,10,11],same:[2,6,10],scikit:10,score:[2,6,10],script:11,search:13,second:[10,11],section:[0,1],segment:[1,5],serv:8,set:[3,7,10],set_titl:[10,11],set_xlabel:10,set_ylabel:10,shape:10,sharei:[10,11],sharex:[10,11],should:8,shuffl:[10,11],side:10,size:[3,7],skimag:[10,11,12],slice:[4,9],so:[3,7],some:10,sourc:[3,7,13],specif:0,specifi:[4,9],stack:[4,9],standard:12,stardist:10,start:[10,11],stitch:[4,9],stitch_threshold:[4,9],str:[4,8,9],subplot:[10,11],subplots_adjust:10,subsequ:[4,9],subtract:[3,7],sum:[3,7],t0:11,t1:11,t:[10,11],tabl:[3,7],take:10,taken:[3,7],text:[10,11],them:10,thi:[0,1,3,7,10,11,13],threshold:[4,8,9,10,11],through:[2,6],thu:[3,7],time:11,titl:10,to_numpi:10,togeth:[3,7],took:11,top:[1,10],total:[3,7],track:11,truth:10,two:[2,4,6,8,9,11],type:[3,4,5,7,8,9],uint8:[5,10,11],union:[2,3,6,7,8,10],us:[0,4,5,8,9,10,13],usag:1,usedin:[0,1],util:[0,1],valu:[0,1,4,8,9,10],vector:[3,7],version:[8,10,11],visual:[1,10,11],vmax:12,vmin:12,wa:10,want:[10,11],we:[1,10,11,13],where:[3,7],whether:10,which:[0,1,2,4,6,8,9,10,11],wise:[2,6],work:[3,7],wspace:10,x:[3,7],y:[3,7],zero:10,zyx:[4,9]},titles:["API Reference","Examples","biapol_utilities.label.compare_labels","biapol_utilities.label.intersection_over_union_matrix","biapol_utilities.label.match_labels_stack","biapol_utilities.data.blobs","biapol_utilities.label.compare_labels","biapol_utilities.label.intersection_over_union_matrix","biapol_utilities.label.match_labels","biapol_utilities.label.match_labels_stack","Quantitative segmentation quality estimation","Matching labels","Labels visualized in colours","Welcome to BiAPoL utilities\u2019s documentation!"],titleterms:{The:0,api:0,biapol:13,biapol_util:[2,3,4,5,6,7,8,9],blob:5,colour:12,compar:10,compare_label:[2,6],content:13,data:[0,1,5,10,11],document:13,estim:10,exampl:1,featur:10,index:10,indic:13,input:10,intersection_over_union_matrix:[3,7],jaccard:10,label:[0,1,2,3,4,6,7,8,9,10,11,12],labelwis:10,load:11,match:[10,11],match_label:8,match_labels_stack:[4,9],modul:[0,1],qualiti:10,quantit:10,re:10,refer:0,ressourc:13,s:13,segment:10,tabl:13,util:13,visual:12,welcom:13,wise:10}}) \ No newline at end of file diff --git a/doc/_include/API_reference.rst b/doc/_include/API_reference.rst index 21cf6f0..f94c3ba 100644 --- a/doc/_include/API_reference.rst +++ b/doc/_include/API_reference.rst @@ -1,9 +1,11 @@ API Reference ============= - +This is the class and function reference of biapol-utilities. Please refer to the examples for further details, as the class and function raw specifications may not be enough to give full guidelines on their uses. The label module ------------------ +The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of +an object is encoded in the pixel value which must be an integer number. .. currentmodule:: biapol_utilities @@ -13,13 +15,17 @@ The label module label.compare_labels label.intersection_over_union_matrix + label.match_labels label.match_labels_stack The data module ------------------ +The data module provides example data to be usedin the examples section. .. currentmodule:: biapol_utilities .. autosummary:: + :recursive: + :toctree: generated data.blobs \ No newline at end of file diff --git a/doc/_include/Examples.rst b/doc/_include/Examples.rst index de920ec..792bb14 100644 --- a/doc/_include/Examples.rst +++ b/doc/_include/Examples.rst @@ -1,17 +1,21 @@ Examples -============================= - +============= +This is the example library of biapol-utilities. We provide examples for all top-level functions that are listed +in the API reference and comment on their usage here. Label module ------------------ +The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of +an object is encoded in the pixel value which must be an integer number. + .. toctree:: :titlesonly: :maxdepth: 0 - Match labels <../../notebooks/label/match_labels.ipynb> - Compare segmentations <../../notebooks/label/Compare_segmentations.ipynb> + Match labels + Compare segmentations + Visualize labels Data module ------------------ - - +The data module provides example data to be usedin the examples section. diff --git a/doc/_include/biapol_utilities.label.compare_labels.rst b/doc/_include/biapol_utilities.label.compare_labels.rst new file mode 100644 index 0000000..286bf6d --- /dev/null +++ b/doc/_include/biapol_utilities.label.compare_labels.rst @@ -0,0 +1,6 @@ +biapol\_utilities.label.compare\_labels +======================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: compare_labels \ No newline at end of file diff --git a/doc/_include/biapol_utilities.label.intersection_over_union_matrix.rst b/doc/_include/biapol_utilities.label.intersection_over_union_matrix.rst new file mode 100644 index 0000000..3b66942 --- /dev/null +++ b/doc/_include/biapol_utilities.label.intersection_over_union_matrix.rst @@ -0,0 +1,6 @@ +biapol\_utilities.label.intersection\_over\_union\_matrix +========================================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: intersection_over_union_matrix \ No newline at end of file diff --git a/doc/_include/biapol_utilities.label.match_labels_stack.rst b/doc/_include/biapol_utilities.label.match_labels_stack.rst new file mode 100644 index 0000000..2f71b54 --- /dev/null +++ b/doc/_include/biapol_utilities.label.match_labels_stack.rst @@ -0,0 +1,6 @@ +biapol\_utilities.label.match\_labels\_stack +============================================ + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: match_labels_stack \ No newline at end of file diff --git a/doc/_include/generated/biapol_utilities.data.blobs.rst b/doc/_include/generated/biapol_utilities.data.blobs.rst new file mode 100644 index 0000000..16a40fd --- /dev/null +++ b/doc/_include/generated/biapol_utilities.data.blobs.rst @@ -0,0 +1,6 @@ +biapol\_utilities.data.blobs +============================ + +.. currentmodule:: biapol_utilities.data + +.. autofunction:: blobs \ No newline at end of file diff --git a/doc/_include/generated/biapol_utilities.label.match_labels.rst b/doc/_include/generated/biapol_utilities.label.match_labels.rst new file mode 100644 index 0000000..ae8b654 --- /dev/null +++ b/doc/_include/generated/biapol_utilities.label.match_labels.rst @@ -0,0 +1,6 @@ +biapol\_utilities.label.match\_labels +===================================== + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: match_labels \ No newline at end of file diff --git a/doc/_include/notebooks/label/Compare_segmentations.ipynb b/doc/_include/notebooks/label/Compare_segmentations.ipynb new file mode 100644 index 0000000..b694e2f --- /dev/null +++ b/doc/_include/notebooks/label/Compare_segmentations.ipynb @@ -0,0 +1,5614 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9f0d8ccf", + "metadata": {}, + "source": [ + "# Quantitative segmentation quality estimation\n", + "\n", + "Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "89205b6d", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import biapol_utilities as biau\n", + "from skimage import io, measure, segmentation\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", + "import pandas as pd\n", + "\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "markdown", + "id": "a63045b4", + "metadata": {}, + "source": [ + "## Input data\n", + "First, let's generate some example data!" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "db9c5fe0", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biau.data.blobs()" + ] + }, + { + "cell_type": "markdown", + "id": "2c0c8418", + "metadata": {}, + "source": [ + "Let's segment this and take it as a ground truth image:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2ae66de8", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Ground truth')" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "threshold = 128\n", + "imageA = (blobs > threshold).astype(np.uint8)\n", + "ground_truth = measure.label(imageA)\n", + "\n", + "plt.imshow(ground_truth)\n", + "plt.title('Ground truth')" + ] + }, + { + "cell_type": "markdown", + "id": "f7f4c0be", + "metadata": {}, + "source": [ + "Next, we shuffle the labels and expand them a bit:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2b8dc27c", + "metadata": {}, + "outputs": [], + "source": [ + "# First, shuffle randomly\n", + "label_shuffle = np.arange(1, ground_truth.max()+1, 1)\n", + "np.random.shuffle(label_shuffle)\n", + "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", + "segmented = label_shuffle[ground_truth]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "279f3e2c", + "metadata": {}, + "outputs": [], + "source": [ + "# Second, expand the labels a bit\n", + "segmented = segmentation.expand_labels(segmented, 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "eb0b69c2", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Segmentation')" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "\n", + "axes[0].imshow(ground_truth)\n", + "axes[0].set_title('Ground truth')\n", + "\n", + "axes[1].imshow(segmented)\n", + "axes[1].set_title('Segmentation')" + ] + }, + { + "cell_type": "markdown", + "id": "dd726a7c", + "metadata": {}, + "source": [ + "## Re-match labels\n", + "\n", + "Next, use the label-matching from `biapol_utilities` to assign correct labels to both images" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8007d578", + "metadata": {}, + "outputs": [], + "source": [ + "segmented = biau.label.match_labels(ground_truth, segmented)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "23496dad", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Segmentation')" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "\n", + "axes[0].imshow(ground_truth)\n", + "axes[0].set_title('Ground truth')\n", + "\n", + "axes[1].imshow(segmented)\n", + "axes[1].set_title('Segmentation')" + ] + }, + { + "cell_type": "markdown", + "id": "1e1d39a4", + "metadata": {}, + "source": [ + "## Compare labels: Labelwise Jaccard-index\n", + "\n", + "Lastly, we calculate the *label-wise Jaccard index* to measure the intersection over union (IoU) between corresponding pairs of labels." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "7641d30b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
\n", + "

68 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " label jaccard_score dice_score\n", + "0 0 0.496847 0.663858\n", + "1 1 0.518102 0.682566\n", + "2 2 0.470130 0.639576\n", + "3 3 0.623552 0.768133\n", + "4 4 0.602546 0.751986\n", + ".. ... ... ...\n", + "63 63 0.262857 0.416290\n", + "64 64 0.000000 0.000000\n", + "65 65 0.000000 0.000000\n", + "66 66 0.000000 0.000000\n", + "67 67 0.000000 0.000000\n", + "\n", + "[68 rows x 3 columns]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result = biau.label.compare_labels(ground_truth, segmented)\n", + "result" + ] + }, + { + "cell_type": "markdown", + "id": "3f218dd4", + "metadata": {}, + "source": [ + "Let's also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "fab77a34", + "metadata": {}, + "outputs": [], + "source": [ + "LUT_jaccard = result['jaccard_score'].to_numpy()\n", + "LUT_dice = result['dice_score'].to_numpy()\n", + "\n", + "# set segmentation quality of background to zero\n", + "LUT_jaccard[0] = np.nan\n", + "LUT_dice[0] = np.nan\n", + "\n", + "# create score map\n", + "JI_map = LUT_jaccard[segmented]\n", + "DI_map = LUT_dice[segmented]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ca62489c", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(-0.5, 255.5, 253.5, -0.5)" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))\n", + "fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)\n", + "\n", + "\n", + "# Plot ground truth\n", + "axes[0, 0].imshow(ground_truth)\n", + "axes[0, 0].set_title('Ground truth')\n", + "\n", + "# Plot segmentation\n", + "axes[0, 1].imshow(segmented)\n", + "axes[0, 1].set_title('Segmentation')\n", + "\n", + "# Plot overlay\n", + "axes[0, 2].imshow(ground_truth)\n", + "axes[0, 2].imshow(segmented, alpha=0.5)\n", + "axes[0, 2].set_title('Overlay')\n", + "\n", + "# Plot Jaccard index map\n", + "im = axes[1, 0].imshow(JI_map, cmap='inferno_r')\n", + "axes[1, 0].set_title('Jaccard score')\n", + "cbar = fig.colorbar(im, ax=axes[1, 0])\n", + "\n", + "# Plot Dice score map\n", + "im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')\n", + "axes[1, 1].set_title('Dice score')\n", + "cbar2 = fig.colorbar(im2, ax=axes[1, 1])\n", + "\n", + "axes[-1, -1].axis('off')" + ] + }, + { + "cell_type": "markdown", + "id": "1dc2ca58", + "metadata": {}, + "source": [ + "## Compare-labels: Feature-wise\n", + "It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "5f6cc904", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
\n", + "

63 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " label area eccentricity orientation\n", + "0 1 415 0.878888 -0.433915\n", + "1 2 181 0.822705 -1.513862\n", + "2 3 646 0.386542 -0.079653\n", + "3 4 426 0.324798 -0.400592\n", + "4 5 465 0.780472 -0.044317\n", + ".. ... ... ... ...\n", + "58 59 1 0.000000 0.785398\n", + "59 60 87 0.969263 -1.560717\n", + "60 61 73 0.951468 -1.567605\n", + "61 62 49 0.942191 -1.554054\n", + "62 63 46 0.976786 1.538848\n", + "\n", + "[63 rows x 4 columns]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "properties = ['label', 'area', 'eccentricity', 'orientation']\n", + "features_gt = measure.regionprops_table(ground_truth, properties=properties)\n", + "features_seg = measure.regionprops_table(segmented, properties=properties)\n", + "\n", + "features_gt = pd.DataFrame(features_gt)\n", + "features_seg = pd.DataFrame(features_seg)\n", + "features_gt" + ] + }, + { + "cell_type": "markdown", + "id": "ec29004b", + "metadata": {}, + "source": [ + "Visualize as histograms" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "e9652f8d", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0, 0.5, '# Occurrences')" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))\n", + "\n", + "ax_idx = 0\n", + "for idx, prop in enumerate(properties):\n", + " if prop == 'label':\n", + " continue\n", + " \n", + " axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)\n", + " axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)\n", + " axes[ax_idx].set_xlabel(prop)\n", + " ax_idx += 1\n", + " \n", + "axes[0].legend()\n", + "axes[0].set_ylabel('# Occurrences')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "185d4c1d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/_include/notebooks/label/match_labels.ipynb b/doc/_include/notebooks/label/match_labels.ipynb new file mode 100644 index 0000000..181425a --- /dev/null +++ b/doc/_include/notebooks/label/match_labels.ipynb @@ -0,0 +1,3198 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e5db44ea", + "metadata": {}, + "source": [ + "## Matching labels\n", + "This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d1ca8e7a", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import biapol_utilities as biau\n", + "from skimage import io, measure, filters\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from datetime import datetime\n", + "\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "markdown", + "id": "ee62539b", + "metadata": {}, + "source": [ + "### Load data\n", + "First, we load the example blobs image and threshold it to create a label map. " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "7fe70350", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biau.data.blobs()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "909ce3b2", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "threshold = 128\n", + "imageA = (blobs > threshold).astype(np.uint8)\n", + "imageA_labelled = measure.label(imageA)\n", + "\n", + "plt.imshow(imageA_labelled)" + ] + }, + { + "cell_type": "markdown", + "id": "1cbf5ae3", + "metadata": {}, + "source": [ + "Let's create a second version of this image in which we shuffle the labels:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "29986d79", + "metadata": {}, + "outputs": [], + "source": [ + "label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)\n", + "np.random.shuffle(label_shuffle)\n", + "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", + "\n", + "imageB_labelled = label_shuffle[imageA_labelled]" + ] + }, + { + "cell_type": "markdown", + "id": "1393dfb7", + "metadata": {}, + "source": [ + "Both images are not identical!" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "1ff3c80c", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of labels in imageA: 63\n", + "Number of labels in imageB: 63\n" + ] + } + ], + "source": [ + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "axes[0].imshow(imageA_labelled)\n", + "axes[0].set_title('Reference image')\n", + "axes[1].imshow(imageB_labelled)\n", + "axes[1].set_title('Shuffled image')\n", + "\n", + "print(f'Number of labels in imageA: {imageA_labelled.max()}')\n", + "print(f'Number of labels in imageB: {imageB_labelled.max()}')" + ] + }, + { + "cell_type": "markdown", + "id": "7a38be04", + "metadata": {}, + "source": [ + "Match labels and track time" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "79f0cf74", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Took 0 ms\n" + ] + } + ], + "source": [ + "t0 = datetime.now()\n", + "output = biau.label.match_labels(imageA_labelled, imageB_labelled)\n", + "t1 = datetime.now()\n", + "print(f'Took {(t1-t0).seconds*1000} ms')" + ] + }, + { + "cell_type": "markdown", + "id": "a8710824", + "metadata": {}, + "source": [ + "Visualize" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "84ed2639", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Relabelled image')" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "axes[0].imshow(imageA_labelled)\n", + "axes[0].set_title('Reference image')\n", + "axes[1].imshow(output)\n", + "axes[1].set_title('Relabelled image')" + ] + } + ], + "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.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/_include/notebooks/label/visualize_labels.ipynb b/doc/_include/notebooks/label/visualize_labels.ipynb new file mode 100644 index 0000000..9924ff8 --- /dev/null +++ b/doc/_include/notebooks/label/visualize_labels.ipynb @@ -0,0 +1,98 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "803a884d", + "metadata": {}, + "outputs": [], + "source": [ + "import biapol_utilities as biao\n", + "from skimage.measure import label\n", + "from skimage.io import imshow" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "af876b71", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biao.blobs()\n", + "labels = label(blobs > 128)" + ] + }, + { + "cell_type": "markdown", + "id": "d9ded05a", + "metadata": {}, + "source": [ + "# Labels visualized in colours\n", + "`biapol_utilities` provided a standardized color map for visualizing labels in:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "5c3f2337", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "867149ee", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/_static/logos/biapol_logo.png b/doc/_static/logos/biapol_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0945d112a0d6994fafdcde2f1a5737fd5061142a GIT binary patch literal 41688 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%0A8QEJHw@N2mVDcG3H0qLCC&NopN85|PG%C^ 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. + * Source code: ``_. \ No newline at end of file From 8d973a09288608297a6c5ff8008d174eca0146f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Tue, 23 Nov 2021 09:46:43 +0100 Subject: [PATCH 09/47] Create index.html --- index.html | 1 + 1 file changed, 1 insertion(+) create mode 100644 index.html diff --git a/index.html b/index.html new file mode 100644 index 0000000..37bb1d2 --- /dev/null +++ b/index.html @@ -0,0 +1 @@ + From 38bd188f6901ff5fd16a69a20b7d01d76995bd71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Tue, 23 Nov 2021 09:47:52 +0100 Subject: [PATCH 10/47] Update and rename index.html to doc/index.html --- doc/index.html | 1 + index.html | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 doc/index.html delete mode 100644 index.html diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..8016e02 --- /dev/null +++ b/doc/index.html @@ -0,0 +1 @@ + diff --git a/index.html b/index.html deleted file mode 100644 index 37bb1d2..0000000 --- a/index.html +++ /dev/null @@ -1 +0,0 @@ - From b2bd8847fe78ab3455f932da49eb4a67b13ee7d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Tue, 23 Nov 2021 09:49:23 +0100 Subject: [PATCH 11/47] rename doc -> docs --- doc/_build/doctrees/API_reference.doctree | Bin 44588 -> 0 bytes doc/_build/doctrees/Examples.doctree | Bin 3612 -> 0 bytes .../doctrees/_include/API_reference.doctree | Bin 12402 -> 0 bytes doc/_build/doctrees/_include/Examples.doctree | Bin 4483 -> 0 bytes ...pol_utilities.label.compare_labels.doctree | Bin 11590 -> 0 bytes ...bel.intersection_over_union_matrix.doctree | Bin 12066 -> 0 bytes ...utilities.label.match_labels_stack.doctree | Bin 10655 -> 0 bytes .../biapol_utilities.data.blobs.doctree | Bin 6426 -> 0 bytes ...pol_utilities.label.compare_labels.doctree | Bin 11610 -> 0 bytes ...bel.intersection_over_union_matrix.doctree | Bin 12086 -> 0 bytes ...iapol_utilities.label.match_labels.doctree | Bin 11809 -> 0 bytes ...utilities.label.match_labels_stack.doctree | Bin 10665 -> 0 bytes .../label/Compare_segmentations.doctree | Bin 1362681 -> 0 bytes .../notebooks/label/match_labels.doctree | Bin 629194 -> 0 bytes .../notebooks/label/visualize_labels.doctree | Bin 7548 -> 0 bytes doc/_build/doctrees/api.doctree | Bin 44612 -> 0 bytes doc/_build/doctrees/environment.pickle | Bin 47486 -> 0 bytes doc/_build/doctrees/index.doctree | Bin 6858 -> 0 bytes ...e_notebooks_label_visualize_labels_3_1.png | Bin 13455 -> 0 bytes doc/_build/html/.buildinfo | 4 - ...e_notebooks_label_visualize_labels_3_1.png | Bin 13455 -> 0 bytes doc/_build/html/_include/API_reference.html | 154 - doc/_build/html/_include/Examples.html | 131 - ...biapol_utilities.label.compare_labels.html | 141 - ....label.intersection_over_union_matrix.html | 146 - ...ol_utilities.label.match_labels_stack.html | 131 - .../biapol_utilities.data.blobs.html | 134 - ...biapol_utilities.label.compare_labels.html | 151 - ....label.intersection_over_union_matrix.html | 156 - .../biapol_utilities.label.match_labels.html | 147 - ...ol_utilities.label.match_labels_stack.html | 141 - .../label/Compare_segmentations.html | 5798 -------- .../label/Compare_segmentations.ipynb | 5614 -------- .../notebooks/label/match_labels.html | 3465 ----- .../notebooks/label/match_labels.ipynb | 3198 ----- .../notebooks/label/visualize_labels.html | 411 - .../notebooks/label/visualize_labels.ipynb | 98 - .../_sources/_include/API_reference.rst.txt | 31 - .../html/_sources/_include/Examples.rst.txt | 21 - ...pol_utilities.label.compare_labels.rst.txt | 6 - ...bel.intersection_over_union_matrix.rst.txt | 6 - ...utilities.label.match_labels_stack.rst.txt | 6 - .../biapol_utilities.data.blobs.rst.txt | 6 - ...pol_utilities.label.compare_labels.rst.txt | 6 - ...bel.intersection_over_union_matrix.rst.txt | 6 - ...iapol_utilities.label.match_labels.rst.txt | 6 - ...utilities.label.match_labels_stack.rst.txt | 6 - .../label/Compare_segmentations.ipynb.txt | 5614 -------- .../notebooks/label/match_labels.ipynb.txt | 3198 ----- .../label/visualize_labels.ipynb.txt | 98 - doc/_build/html/_sources/index.rst.txt | 26 - doc/_build/html/_static/alabaster.css | 701 - doc/_build/html/_static/basic.css | 904 -- doc/_build/html/_static/custom.css | 1 - doc/_build/html/_static/doctools.js | 323 - .../html/_static/documentation_options.js | 12 - doc/_build/html/_static/file.png | Bin 286 -> 0 bytes doc/_build/html/_static/jquery-3.5.1.js | 10872 ---------------- doc/_build/html/_static/jquery.js | 2 - doc/_build/html/_static/language_data.js | 297 - doc/_build/html/_static/minus.png | Bin 90 -> 0 bytes doc/_build/html/_static/plus.png | Bin 90 -> 0 bytes doc/_build/html/_static/pygments.css | 82 - doc/_build/html/_static/searchtools.js | 528 - doc/_build/html/_static/underscore-1.13.1.js | 2042 --- doc/_build/html/_static/underscore.js | 6 - doc/_build/html/genindex.html | 144 - doc/_build/html/index.html | 141 - doc/_build/html/objects.inv | Bin 1448 -> 0 bytes doc/_build/html/search.html | 123 - doc/_build/html/searchindex.js | 1 - .../label/Compare_segmentations.ipynb | 5614 -------- .../notebooks/label/match_labels.ipynb | 3198 ----- .../notebooks/label/visualize_labels.ipynb | 98 - doc/_static/css/hatnotes.css | 15 - doc/_static/logos/biapol_logo.png | Bin 41688 -> 0 bytes {doc => docs}/Makefile | 0 {doc => docs}/_include/API_reference.rst | 0 {doc => docs}/_include/Examples.rst | 0 .../biapol_utilities.label.compare_labels.rst | 0 ...s.label.intersection_over_union_matrix.rst | 0 ...pol_utilities.label.match_labels_stack.rst | 0 .../generated/biapol_utilities.data.blobs.rst | 0 .../biapol_utilities.label.compare_labels.rst | 0 ...s.label.intersection_over_union_matrix.rst | 0 .../biapol_utilities.label.match_labels.rst | 0 ...pol_utilities.label.match_labels_stack.rst | 0 .../label/Compare_segmentations.ipynb | 0 .../notebooks/label/match_labels.ipynb | 0 .../notebooks/label/visualize_labels.ipynb | 0 .../html => docs}/_static/css/hatnotes.css | 0 .../_static/logos/biapol_logo.png | Bin {doc => docs}/_templates/autosummary/base.rst | 0 .../_templates/autosummary/class.rst | 0 .../_templates/autosummary/module.rst | 0 {doc => docs}/_templates/layout.html | 0 {doc => docs}/conf.py | 0 {doc => docs}/index.html | 0 {doc => docs}/index.rst | 0 {doc => docs}/make.bat | 0 100 files changed, 54160 deletions(-) delete mode 100644 doc/_build/doctrees/API_reference.doctree delete mode 100644 doc/_build/doctrees/Examples.doctree delete mode 100644 doc/_build/doctrees/_include/API_reference.doctree delete mode 100644 doc/_build/doctrees/_include/Examples.doctree delete mode 100644 doc/_build/doctrees/_include/biapol_utilities.label.compare_labels.doctree delete mode 100644 doc/_build/doctrees/_include/biapol_utilities.label.intersection_over_union_matrix.doctree delete mode 100644 doc/_build/doctrees/_include/biapol_utilities.label.match_labels_stack.doctree delete mode 100644 doc/_build/doctrees/_include/generated/biapol_utilities.data.blobs.doctree delete mode 100644 doc/_build/doctrees/_include/generated/biapol_utilities.label.compare_labels.doctree delete mode 100644 doc/_build/doctrees/_include/generated/biapol_utilities.label.intersection_over_union_matrix.doctree delete mode 100644 doc/_build/doctrees/_include/generated/biapol_utilities.label.match_labels.doctree delete mode 100644 doc/_build/doctrees/_include/generated/biapol_utilities.label.match_labels_stack.doctree delete mode 100644 doc/_build/doctrees/_include/notebooks/label/Compare_segmentations.doctree delete mode 100644 doc/_build/doctrees/_include/notebooks/label/match_labels.doctree delete mode 100644 doc/_build/doctrees/_include/notebooks/label/visualize_labels.doctree delete mode 100644 doc/_build/doctrees/api.doctree delete mode 100644 doc/_build/doctrees/environment.pickle delete mode 100644 doc/_build/doctrees/index.doctree delete mode 100644 doc/_build/doctrees/nbsphinx/_include_notebooks_label_visualize_labels_3_1.png delete mode 100644 doc/_build/html/.buildinfo delete mode 100644 doc/_build/html/_images/_include_notebooks_label_visualize_labels_3_1.png delete mode 100644 doc/_build/html/_include/API_reference.html delete mode 100644 doc/_build/html/_include/Examples.html delete mode 100644 doc/_build/html/_include/biapol_utilities.label.compare_labels.html delete mode 100644 doc/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html delete mode 100644 doc/_build/html/_include/biapol_utilities.label.match_labels_stack.html delete mode 100644 doc/_build/html/_include/generated/biapol_utilities.data.blobs.html delete mode 100644 doc/_build/html/_include/generated/biapol_utilities.label.compare_labels.html delete mode 100644 doc/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html delete mode 100644 doc/_build/html/_include/generated/biapol_utilities.label.match_labels.html delete mode 100644 doc/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html delete mode 100644 doc/_build/html/_include/notebooks/label/Compare_segmentations.html delete mode 100644 doc/_build/html/_include/notebooks/label/Compare_segmentations.ipynb delete mode 100644 doc/_build/html/_include/notebooks/label/match_labels.html delete mode 100644 doc/_build/html/_include/notebooks/label/match_labels.ipynb delete mode 100644 doc/_build/html/_include/notebooks/label/visualize_labels.html delete mode 100644 doc/_build/html/_include/notebooks/label/visualize_labels.ipynb delete mode 100644 doc/_build/html/_sources/_include/API_reference.rst.txt delete mode 100644 doc/_build/html/_sources/_include/Examples.rst.txt delete mode 100644 doc/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt delete mode 100644 doc/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt delete mode 100644 doc/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt delete mode 100644 doc/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt delete mode 100644 doc/_build/html/_sources/_include/generated/biapol_utilities.label.compare_labels.rst.txt delete mode 100644 doc/_build/html/_sources/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst.txt delete mode 100644 doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt delete mode 100644 doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels_stack.rst.txt delete mode 100644 doc/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt delete mode 100644 doc/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt delete mode 100644 doc/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt delete mode 100644 doc/_build/html/_sources/index.rst.txt delete mode 100644 doc/_build/html/_static/alabaster.css delete mode 100644 doc/_build/html/_static/basic.css delete mode 100644 doc/_build/html/_static/custom.css delete mode 100644 doc/_build/html/_static/doctools.js delete mode 100644 doc/_build/html/_static/documentation_options.js delete mode 100644 doc/_build/html/_static/file.png delete mode 100644 doc/_build/html/_static/jquery-3.5.1.js delete mode 100644 doc/_build/html/_static/jquery.js delete mode 100644 doc/_build/html/_static/language_data.js delete mode 100644 doc/_build/html/_static/minus.png delete mode 100644 doc/_build/html/_static/plus.png delete mode 100644 doc/_build/html/_static/pygments.css delete mode 100644 doc/_build/html/_static/searchtools.js delete mode 100644 doc/_build/html/_static/underscore-1.13.1.js delete mode 100644 doc/_build/html/_static/underscore.js delete mode 100644 doc/_build/html/genindex.html delete mode 100644 doc/_build/html/index.html delete mode 100644 doc/_build/html/objects.inv delete mode 100644 doc/_build/html/search.html delete mode 100644 doc/_build/html/searchindex.js delete mode 100644 doc/_include/notebooks/label/Compare_segmentations.ipynb delete mode 100644 doc/_include/notebooks/label/match_labels.ipynb delete mode 100644 doc/_include/notebooks/label/visualize_labels.ipynb delete mode 100644 doc/_static/css/hatnotes.css delete mode 100644 doc/_static/logos/biapol_logo.png rename {doc => docs}/Makefile (100%) rename {doc => docs}/_include/API_reference.rst (100%) rename {doc => docs}/_include/Examples.rst (100%) rename {doc => docs}/_include/biapol_utilities.label.compare_labels.rst (100%) rename {doc => docs}/_include/biapol_utilities.label.intersection_over_union_matrix.rst (100%) rename {doc => docs}/_include/biapol_utilities.label.match_labels_stack.rst (100%) rename {doc => docs}/_include/generated/biapol_utilities.data.blobs.rst (100%) rename {doc => docs}/_include/generated/biapol_utilities.label.compare_labels.rst (100%) rename {doc => docs}/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst (100%) rename {doc => docs}/_include/generated/biapol_utilities.label.match_labels.rst (100%) rename {doc => docs}/_include/generated/biapol_utilities.label.match_labels_stack.rst (100%) rename {doc/_build/doctrees/nbsphinx => docs}/_include/notebooks/label/Compare_segmentations.ipynb (100%) rename {doc/_build/doctrees/nbsphinx => docs}/_include/notebooks/label/match_labels.ipynb (100%) rename {doc/_build/doctrees/nbsphinx => docs}/_include/notebooks/label/visualize_labels.ipynb (100%) rename {doc/_build/html => docs}/_static/css/hatnotes.css (100%) rename {doc/_build/html => docs}/_static/logos/biapol_logo.png (100%) rename {doc => docs}/_templates/autosummary/base.rst (100%) rename {doc => docs}/_templates/autosummary/class.rst (100%) rename {doc => docs}/_templates/autosummary/module.rst (100%) rename {doc => docs}/_templates/layout.html (100%) rename {doc => docs}/conf.py (100%) rename {doc => docs}/index.html (100%) rename {doc => docs}/index.rst (100%) rename {doc => docs}/make.bat (100%) diff --git a/doc/_build/doctrees/API_reference.doctree b/doc/_build/doctrees/API_reference.doctree deleted file mode 100644 index 26e65f6f9a42a5596ef84f6365965f654dad5ecc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44588 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 I>Eq7-f9bm(vH$=8 diff --git a/doc/_build/doctrees/Examples.doctree b/doc/_build/doctrees/Examples.doctree deleted file mode 100644 index 41070dd6c32e3cce36a4d99c5fa82151a584f28a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3612 zcmdT{O>Z2x8Fno1N~@2RWY@XGa@Q%0I;gdBod7L_A}}i3K%+z{j3R&m1q5e?yJW>7 zrzA&O9Spb!19rfhr?>WR3E_`vs^aFTVd{K}&lO*0A0fd?#Ce#d6PcIW0rQThQz z*L**tu#3NCHH{31*Ms^KldN*jPkz^YC&W@wE!<1}(nToc;QzG-7g;>LdqtB~0&L zAkGoG5BKg>?j7-)0R;YIM9yyk+@Iig8^538_W`2fKP#izt=Rcpc+&3*_;nd9@79)S zqoAfY9?`DC)j2$k!ncIB_K-T-=&2)Hpv?n2gyP@)Z-G7T1U6gURb~iupWwJ!A9Evd z+Hg81p-93l%=O@xIWPRxiPlbO$2ymX@A!?-7gU~-*+iSP0A*-Vn;D698rqG8%J(V? zldPnWGvPRCN);Asfx32&{JLS8HjYSk%4BhP*{^ac+hfmfvzY)^j=J17Og-OASd>p; zZg@tG0#@KKjHaLroS`ubK@~6kP^c_-gsE63;41tecaz;;?plHG8;h5O8KVv1R3(xb z;2d0yUEw!%?iRK5N-c%oxo~qq1^>zqE2VP>8qphz7Z)V`RtUfXB@TQf0xJB5q-vVe zDFfUI&X>`>{WZg4Z4#2O49NjA=uZHlA8R#1jDSNVBts7rvx4{ikmgR4ImurZ$f%7Z zPczbH9Z)R^0tsgnl|kWVNddIVhPR)SGRyKrlUW+_X^YJ=Z5ioGmMIcDaw@E-@^h0U z!qP~FKx!|Sn`+>9{W^lN$bVXnAf!yqMkXT67_|F$!xxNLW&#hMH)u=n-fI|h?GgF8 z9ZCvmqo&A0DN^BzPcD7)&z>JSHvvbF_ z8f!D%OW5fiIPG5HuLp_J6-W@rFauF|n0lb^-oEz{kR6&ye8Ehh%+1_r%s8zvfCY1t z(hPU0go%Np5lSd=yf|F(J4ncsw6)o~Piz)4w<$%H z{UJwDTL5*fJXc2|bxdn$cVbRaKX~}6*nn~gA*4_83?{;|P;LNq6L^K}(Xmhy5J0`k^eaOn|-|h}HKUo^Z+! z_yc~-pXPoLZrphW)WQr-j`+b5KR(L&t#G8+BOdTw{**t?{YLj?O0^rYK;sI2!Bj;F z1=#Ra{&y)AAELrbrjeHIW0$NyxVkeWQsYABzJ5_xeRIjLqCLbq z55-^jwOC6D#1RAL!}38*e+@8R6i<-g*yT_%*uE?}Q!t4AZ)ndg%AujoCsk*S96*px z4b6Dx+JE>c^x%Xb^6jC2+p8bwIllX0_7{i2n9^Zd`X z^qc2@`S0@c1*MP4{*NENp!^-|f5YB4KyMa+i%L?u)Q#xt@px1_v%kMO!ry*b7FH{H zUK3I}L;rSse{`?p_>4O2=W04CcQ-rw)p)!Yrg5b8iQOxSduiYy6~kC$=PLTRls(XC zSg%KxO~U{#v+w&g)ST%19nMBo1M2^)`-^Y-ueWY!0}QYIs)eF=qXjW@%F5OH+wj1A z2di6WRcu!1W@YxhdUsj!S3;w}8ujSOlh08c)qgRE%NKUQzd~zwVIROdf3=;hP1%&y gyVjD+4!9;%Eb{~-O;1DfTTR0FuP0?l+&mip8>^3Qg8%>k diff --git a/doc/_build/doctrees/_include/API_reference.doctree b/doc/_build/doctrees/_include/API_reference.doctree deleted file mode 100644 index a87282c83163a34d7d741cfe470db6ebe9714c6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12402 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 U3D&83w_%c3NenOrJ5js!Kc5g<1poj5 diff --git a/doc/_build/doctrees/_include/biapol_utilities.label.intersection_over_union_matrix.doctree b/doc/_build/doctrees/_include/biapol_utilities.label.intersection_over_union_matrix.doctree deleted file mode 100644 index ad3305a99fd9669b52befb1181f2f8086feac97f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12066 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 diff --git a/doc/_build/doctrees/_include/biapol_utilities.label.match_labels_stack.doctree b/doc/_build/doctrees/_include/biapol_utilities.label.match_labels_stack.doctree deleted file mode 100644 index a76903e4d72c0fcb4f4cf48963eb3c00e2b0869c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10655 zcmd5?>u(%a6?g2cz3X?}#zn$OM-`xTu-Bz6Di{K^w3TRDQ-uJfxE*F^?)uJpc4jgU zdyRxtK2#*=@{l_H6Z#Ld;-P|&_(&@dRHA%DMFJ#*1V}}K3JHGa-kI5%efW`-rje5D z+}AnhcOLiNbMCX17n0R6`9~~-KDXU&!>}yZvsjpjs^yt+hq+Pme6sq@bxc@ksUd#&?VNI zw&8ouwoZ%KkFr5=opd7w{`guZtG!Wn7awBgJn)%VO`=cn>{vs_E#a zBIV(gY~C@cib>yqxKYB-h?<_`!zaXK3d@!_?bt3$w&JECri~~H>}DJRPJ(a3wnBnx z%5;n{L?eDzT%)6YRjt_XeKa9uz*;mW7E_V2LtP19;46HVpW_q!ym;o}&Fu&62cGaA z+kPVO+CV$pRv@nD7;b~fZQXWFC$?DHI~=1FB85;R2qEO1m&W5J9}^YZwOF^HETu=T zK`4F~6!8K4{Sf}v@%I7=2#f+~5X{#BjqUD0*W!Mu$r7FVs#dpMt>am-!!*TwKYOc* zSRLM@Orx}5!Y8+)#EAJCZ}gzr;&(zJkmNKh+Z+(2j-Gky(L)Pqt!LTD)ev5eriD*S$R!=&=h=(6LZpcR#hJUAVBjZv;Exsx)MxKP%~z z_mQ46kAsEYF+z6b0?VWOb0degR`_GeXcQ7gNp*EG1G(3IST@lXbHs`?QTfeEs;zZ9 z&SvNv6auQ460%^AC4~2*pz=s+n%`%esj+SQBTchkux$zIHlbwlRI3gDU=t=B0ylR@ z^I9Wpq*0z!TpsRh&|&ix=S4VytBW?2mDDnn}=25ps~Rk&7(^dO{sn?FtX={@}T zGnv6INp=x+pc&YdW5X{C#__rOJ8p=|5ps$}YBL35nfaC4%D5bi#-(Udnf&{ZKZKWd z)n)_Jzx$+)l`(bliDk~eb+epTGY8K&>NS)py>LU6Sjm5ffq8YnmC6c~Acgp~1D zMLE+$d@P(RiU)%lS>8@y_`GO&AAg);f+p=R)LMbp(O@beyBcF1Ep%*?h1$LyaV_+j zX}4@dq_jKT^N_Mp&F&aGFv-Z%noJ9E z*flv!Qd+3dwL{GdEEZ@_edS4sk34|j(8~hD!G0BZ?oNRnQHrthtm`Ah*imv_OrbwI@NpD>S&ofxjAK#KejgTYSMkrac8y5A z)SkwFgk5`qz9oF^v-p`?)%cp0$w)uT(rwTrdCnhpWE(CWX{fzeAfXU1Q=Nd(W@P2> zGTqPI0NwUQOgb*A?GIz{aZ!B`V~<1?MtN$r3?DDsPIEPW( z)G}l!MZFic?Y>)<+F@4sKMq5l2K^0d{uRFa_ssHAN6h2flfMAW>a3;J5q{P*&!?Na z;mGLrxV+w^u`CV|$68*H1~odBN1SOLBis!e+7Q}6X`YAwezqW9YEV)On@t^V-k%b&lzaqp`3MHle`rzrqM7iTvz z2+YQnT)sWSiJ1h^_F_$a8BN?1wS8{mm=o=L*-;1S1`Wrh(8hK_>(O$yX*iAPBGhUL z08X%_JIcQ^ZHq~z+RW**&)i^P4lC_0OrU6YqeJ9yf219v9bu8-n}qBtu77l#f+1!s zPtfl&zu!4FzlG@kZOPwg(TdUkL~-hSSa>)tY4lH_DTm@iH-Hy!L_np0BeAV!{+$8b zYbc}q!y94Z<^LDTKRzbPLpFo~`@@)Fd&1zjJW7h>)&;@~{gLp3mWIOA+n2@HZyk3% z*Sw`%AOOA5XRo*dREHfhmj(gNTw$>v>Yj8mP`=qmVstd2!1H?=t@x6Gv6|~GcQny! z8zR9``~P|VDsI`8H26}41s%HhIG(wyUyZ$}m`&{8`2~MhcO^L8yGJkwxP59|D&fB; z(HvdgCA3q3_CJ_;#3`%&w$e03;Nm`al>S!QSC3viJHj2l*k5qY`|}ZO@;_qG>v8k& zm41yuzl0tACObnYyQ%XxvIa4AnITW^=J)&jJBM9*%Y6j>aj!8P_xtuoXokui(OKe8 z8N~t9y(2%Z=l5%Q3e6mOWPi?~7&!!dJbWU~U%`wAG2-EK}~8Aybj*UqdqQ& z%Q)mx{oTHaqxXy(7Ee+=j%0^>KH2eAiNI(c=}w6-BJJatc6>O|*AQ-GI+CAP$&SN^ z{{X{fN?C;oRQAf_>+0x^jI=7p^=Gxy^o|-eh0M3~p!UxpHj3V;(G5R$V1VrUAi(imQBG z)oDlTD=$v-b((uh%$spQWo$h!TF+)Js(3A`A&Vm1?ePrYOkUSV+MV+DRw5?9L^s$% z+HPS>)OMJQ{AJ_?2|g@b(jjce$H$B!gCwlGi_huwGY%Yl%|)K6Q?Z+RL9PP60;JuR zTAmlVIK31)FP#!|R8@83j^0HMqLZLy9(P0A*G;cOZxuo;`F_>H941?I%DU=V$sH8a z326;}OUwq$_W~q|*&cI}OXFgi8&3XN5ocJ}23EMn$6+?8A}SVZ#ycQ4k4mmf=}xT6 zj1F3AQGog=35B%kyzTmNq%+s_C@GqVS{$|3KejGwFDvCvodtmx=-hBEhXufySVdVz zEO>ELUZo;eNyNFnp1vj8Z;@5ct95%kWV2Vw9etCN)63z&(Fwr(*>{eleD{@L-c=8ZV=^j?z~w_#Ls zR^0LR-0%RbY>+u5q@rlS1=#|0-H_DZYw|-DTb_>EG)65V{o;iTuO5(4PiIOiF(ZA? z4sB(k3%X^8M$;idQZA=5hv4gC7Q*0Mf!6@Y-C)tVbeP_<9r>_9EYmL#K?R(~K*O|} z1(na>nN0o(6Foy-1W2sK1$(uX5cowU}wW(dm9)TZY1I?&5*2MhK@o86ooTC68Owt|KQ#C0onPW zW%iMwmL8dvj7;Qtc)(+`s3pnpsN;Y{Ei#($A}iv_rK&gwo9yVhd*Q%sXu^1j8 z=hfA@y~7>+h5ep(sH7og!;S$*ledx(K;0(4)u)aNi;+Tm&g3W{A%hkue*?-ALd@Qc zePrS3v5|a1l*WPUupZB}-4<*h3k*vXDo`aXk6UD&CbQtH2cX3nQuo)zSrbXcU7aE8 z@921ffjlI=&bcNgn7c<$c|=u(2>2w-3mbwBgO7BT`6cG{cisXe%pQx|AeAO&9o=cAlb1M^1JZ%M)qSfy2u}i z#avM%a=AHFETs98?o|spUN%ngU2IX~uq{D@ou=pHN|r-!?`zCQ*GenaGOBXYQfYm} z&>*6qeYStCv}a6ABP^I+Os(Ol$b_4(A`#lD#6t zkj%JD63Hul`Pf*jsfk&+$sm$aOi!*6#D1>jQpyE))Z+bCEalr%W`WWXX7XkkL}t<_ Wd5C&D^bBy?q8&8dY-qu_+4vtUx;l3N diff --git a/doc/_build/doctrees/_include/generated/biapol_utilities.data.blobs.doctree b/doc/_build/doctrees/_include/generated/biapol_utilities.data.blobs.doctree deleted file mode 100644 index f2afac4153510954a46e48899c1cb8883127ea30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6426 zcmc&&-ESOM757Kh>-D#j+5*){r{P0uE4wCDiYiMLYD?0cINKh+04#N zX71SQhl*4vZ7i+|B2x(=KExk@Kokjh#xD(9WRPKL}E>7#V}{q()GDI1Y>6bDIU zvs6xj!sf2$M9fd`q;iGGh3m!b?0h|Dwr~T#IL>Q)j@R#`P2P|-;R=tHKFO`FYlVT= zG3gRlxGZivmay7gFX+Z8ox`z9UuPrYC#Rk|o%%tl_~o^n?u=XITxfxPk@9ufFbjG4 ztenflJdl?>*JtTL(zWD*B}C+Q69IS#j#<}YuR@r z)+3rk)`iulPbpvJTYQOM<+J>n{N|f`o!8yh-VNUAyc-1rpci*ED6ImM4w&qiu5WvZ z!#aKDv&a(6$>>f+qaDQ%@P+-Eq|2vd&Gj8NDgm!`!VL(-uLI=I7__9J@%-98vB8es}sh;tsjD~2J6fIdcVV+wvtYhIJC&Q=5Zuu(IHC-nYZ!ETbYsE zV|$shJK>o|QWdL1p42gwKZVD8u%Q?__4`K9J6&sSO`G{%ri_Myv5H}>!j9l7ps`DxA}vkjjm!22?CVbWqAq`J9~ZC7!2benLcxaF}!<{8(Og036x(CRbeTQ~2t zbNha=MD_UoPZZtb`#&vHjurVsF!qD96}>FQruVy<`RBPubC`>(*~G#7;lUuA8!0k2$9R_lJvf{yUKWHnZd@ zSa890H*k)hV2zK}v!RU7Xtj*jDc@@o)c8}mFo$>*`2Erivaz$H&g|^uS~@lM{PW_> z{{zhbtxV20<+}0s{-a5r3UK7wll)e0D8-OUUe!Lb#s7lBVjO5rA^H<={F$y z74ZHfxA$E4zt1=1qE@ycjziQPR8DP9?iF&WtoGkB5a)A9O8>N^^grisY9>lr{!H_w zm%n_&cG1LS{)6H~(kHO;f)Kr-jO6MW-9r&p^LP1qBiR`&e zIg3{+*KAa-Ia?wWxvb{|L(BD3ITIeIauFMB6nd`hiu6R*vD6@bsAz>1^_fWZtBN=d zneFymJAEh{NVi#1;2$8ZAMfc5Z~*-et`JjON<`>xQ_kElDr{G!A3TR66?m1rw<-sB zpGn@q=Wy&PFxbI=r%Sf|Y?3WcTFInoyh)F$()qO7tDKO^I(;e` zEAL-K+VdUtBj|e`d|$-tKfR#Wpa0@7;hidp@M~FFjc^(z-3azsDwGy(!^lym+Nkui z=uqA&kRQZ^`qtpyg~2CF57eQY50%^+Dm~2if8i;ffn?A{0CNxR5kc6?dx`wLWKsc z#KD+gQ(i!lNfv*6VHTl8)=MHcRqqkVKhg|;tQbB!!0F6$O(|gksAvJlMnrAx%~Vyq z@s{q^&sJeEp5QGyJ1tl2B%(ovS&S`~@*O?C zkn=GU0!b5topl;?s7Xx^MHM;=CzW&Gu)GAWUqpn}1KG$F8$>Azh2lSn zbE2B8Ijo!X@!ZOh75P+P;9h18vC|L{`f?HqIeo?T!$g>fl>wC@sca;o*LtO;n!~Nh zk0y(vATl``439;?nOH^NC|83-Ox{vcx1{oFKl z11JuNJT+@r_AI}jpf?2K4rUKCnCHnW5wnBHF&#$57M`IA(1DyoE80U33`AVV#E_!r zj;Nbmu@VuO<1IPk!l;&=WEh%-;Q?5+fx?ePzU9${t7-@6`Z1}0ycNbQaRL)F5m2q6 z{0d@*h%-K^ti%@PA$m5UOmx+B+}P@RBuK_(J$DG+l1mUKh6|{U50@@yWMRrc zqMluOhIYo!Y~|00Aizl0Wum8^;bQ3FiH5Mc@FGX>bbnr6g-s64!aWQ2O+Ae|k!$fW zI^~hc-9Gp51N*(?Q9mY^;-LjcyO$t^#{lYzTI;3h1-6wzd)4NcQ`k_S_BWucAjIjr zNrZ+VoW+3?SWjTPeh)T~2ZqZOD&nL&Nw>y^UFN`7kMR~~D8*0YhV2E`U6Y}T z_e>1_FioTR>_a)r{6iY%%6T0k;FB;f1br6se1>l@V@voBL}0fEB~5^`>ITXx`i&;?LO@~FR&?LPvXgPEDB zsr~8rL3$f5fWa4>3JQo3yY$0F9GTc&EVh-l7qjU(%(G8kzu-`)%c25h;H2CBAG+XF AdjJ3c diff --git a/doc/_build/doctrees/_include/generated/biapol_utilities.label.compare_labels.doctree b/doc/_build/doctrees/_include/generated/biapol_utilities.label.compare_labels.doctree deleted file mode 100644 index cebda2d14182f55bd0be805eca6db86e5dd66429..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11610 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 diff --git a/doc/_build/doctrees/_include/generated/biapol_utilities.label.intersection_over_union_matrix.doctree b/doc/_build/doctrees/_include/generated/biapol_utilities.label.intersection_over_union_matrix.doctree deleted file mode 100644 index 2fd966b2595750bb764403e9cbf6f8bc1c67ca2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12086 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 gpcIDZvtg#9jHF9{EH6eE@WAE@&FX8-^I diff --git a/doc/_build/doctrees/_include/generated/biapol_utilities.label.match_labels.doctree b/doc/_build/doctrees/_include/generated/biapol_utilities.label.match_labels.doctree deleted file mode 100644 index 9c7a619641a95ddd5f956ac702d565a5a288f16c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11809 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 diff --git a/doc/_build/doctrees/_include/generated/biapol_utilities.label.match_labels_stack.doctree b/doc/_build/doctrees/_include/generated/biapol_utilities.label.match_labels_stack.doctree deleted file mode 100644 index b51620befce82ffae7fb59c9cdd8f8cd50a77481..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10665 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 diff --git a/doc/_build/doctrees/_include/notebooks/label/Compare_segmentations.doctree b/doc/_build/doctrees/_include/notebooks/label/Compare_segmentations.doctree deleted file mode 100644 index 39cb2d4ce100477c40fa5a77c57ad8f2de3ccd18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1362681 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 z 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%0A4jvq_))g}F41iqdDqt@z5-P41o~MSASvz|hZI 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�JeLbH8>Uh0b0n)lq3dS6k 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%0D}UR^CAc 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 Bh?`g*dKqn>5xG(l+Da1WP$$nEarPP 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

gf-j3_57F_ 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≀@R^wrKABuIW) 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%0Dy$f4|D>O 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

jJv5X;13XP;P4$6udWeH3h?A;w#w4zB) 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ȋ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�TZIMebs&slEe@25z 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 V2qgBjfj4aJ)lvtb3woj1{vRSl)^`8^ diff --git a/doc/_build/doctrees/api.doctree b/doc/_build/doctrees/api.doctree deleted file mode 100644 index 25a2e9e5f635ef06882f07814f4051b122ccd994..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44612 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

bIeC-U$%VFwe?;ZRRCfB44f9Qpf;Oi*3aa-SD_x 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 ebuRDV-HRkw6`$Fe>6xDInaz%v{jir1vdKaDIS z>)x8_d00py+3d=N7`7saFZ!%c0iP8S1fK=LH~kX?MFhd$xwpQ$XQq3CFAj7~*Zny6 zeEiNi_ndxf;ltlNJ){5BhKRTq4EJo;4MLZRR4uuolMGlO(JB^TdE%0$0AH( zhox!;D;)0mZp?!8`6y%y+^8 zYsj$in)m9R@T(0X=Sh!==R_mt#wLc(*!{P+etK&EyQvllEL~Q$ z$c7Ly#b)PSrAD+iKqT0+zOuj;)q$DPymbNGOSvGUvGh3Q&uVZwrAzd|wFc zf%&%NCQ(ZJ;ElRsbQz_rzSNSTx#^?BT_2L`*herIvJ8{^D3dLc^v!l>& z7V0nkZ(R1;RUG4K}m~krKCDh-H`_*_HrplzBD)HVWw0}6aHIi3ZnNxzz?COoF^|%4)yUR{L?jo}2d%$KGL?oWhu8{y4!h{O1=k${!{Pc%D)I zbaA8bk1E_(O>r5D`~9TDtEQmEzn!*tqAAvm0|{ow4!^fN=09p}WZKM@cKMgKQ)w6T zzJsfZCO2l4|NQS(`S&DQ&#_8>adrkN@1ouU!{qE&&GHm9{m)6KSIt6;|2}Q;X|t5s zA`kz0I9D|j9#b{@f=>ExR~%Od(~(@W4Y#6D-b5&GW}&=HDfw(Q&`(Sp6rm?1j^(>d zn7e6_FsegE(CqKS5d3QYCHklDmlwI-AYJr7SM1P<>=RkW@I&Xm^@AjoXIy07DS}0I z%P*tP=d%laFAkHa(ecCHe&gO3xRjCDZ?#O4-RpUhC!IYnY|(<&EBCDI%2?!<{vF~< zR}eeu@)IHevDHDaMPCid&o|gjs$HC)kzMqNR)E5|NAaAK;-~!wAMlU8DaFrq960 z#eCyw?0g>tF76xW)9v3TZg+_qF2;F&CGY$4^b`7D!Wt|s6P1bQ<#7}$iY!^?;?dDc zRX<+5A?KCEPG1kQ-Vom<=4aKqlf=|Tva<2ETFpmH??^2PCM60Y^wzeh_SC(yZmer< zR4lb`*?xioun55$ZB<9SJ-E2{> ziDq%!0@dIrsoL&_p$w3`E0YJaYKHx4XS5)sj4Tk+kB}hJbb@4I%%;u4r7bsV&iXEs7>WMOB_yJCL$~B1-+gU#Vr;Y8BpC!0#i1e}GNo$G zw}W1S?i@7k;{6gDE$VX2oG^ARG-yyr;}~iHwN=dtgD%8`Mm*O-ORnn;Q(jZ+b|OQo z98#A&fNIT629Z?&4~o?T9{M|RVEaUHLythafgtmjLy=&K8(PBwL246qZYUUfOyy3E z5=UA`p70DrH!Rl^)W?7z8JCN>L-1X-3Sk6Xz;s-InrxYs_odVheZwJw#ng*}g^8LA zldqtaRJ;PBTjW(hPS67oeQ$sY{3|nm{l|h@k62W;zepT(A|fCj+>?8#MxMrwkB|4F z6UoD1FN}LFmmRgRQnXTag?4CGu){(F1ct(uS1n<@`Ru1Z3(c;_U1#hV8Yz#tmLDU- z5KVE9$*w+z%Ylz0>L?Q6MJ_epmeh4%a$ptiS=@0f5fMTjt4(ndNPB2;ug86SfZusP zB0GBf~P`05GH;tWlX$LfmXhxUDop?Bh2_*H>oF#!BX&9UH! zI_YZ3gb4T~;6>#V052_b5!GGvEgS^6NJL6N!KJ?W0|c>=QPW$;FsOBl7wX_pTOQ+! zG-$rx;sf6Ae}g5|8d`I?h7OYU3WAgwA%D)-8Ff@g%sTwk0ALI{ zpQnMSVLna>o)_-J^F2B*`>Icg%G;rqGtRr D{?qGn diff --git a/doc/_build/doctrees/nbsphinx/_include_notebooks_label_visualize_labels_3_1.png b/doc/_build/doctrees/nbsphinx/_include_notebooks_label_visualize_labels_3_1.png deleted file mode 100644 index e143f9c7de2abc3e7d0fd5eeaa5ebe19129751b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13455 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 kH3$0kN^vdjP#lUo#fuavuEpK86xVlp?-=*J zzxR<58T;%cd+)Q>TyxG9p{^>2iB5_R2M33#APstqNR}W)nGdLAvS4Ue1S6eHS*Y0M{E>;fqJnX#eJgl!RU0oerggH3u{x^W#!P$ai zBnLVUOoHYpuj>K_hk^I+0S}jvMGObW^QZuoeCL^UlI_*5soBxpC9&((K3MTpAxN;W z7&E1qLxp*gyUs8)a)X7-CnHkJx>zi%&rzPHPj`|$=eJAg2z9-(BOw92&l6j))1j@+(-O-cOWv85{_?E1LQrtqF+ZX}Mpm%)9J&6#Xx#4f|4eH8a$kdx)4Gk;gds<|)6 z;GWFpD26X8rZL$9IgXh4+v-C-St?7>eUkWDvj;+51De)0ZRps}c!6-)-Vu{?V=Y7k@@)5kpx6JBBjD)l&tQ69it{`-H}( zHNkDEf|HZGOOBYPRPC{jy@9+#mET9pA*RotG58Zd%PChbhTh`G(yVe~;D^Z=T{(3el|2ts=qx%%XofL!=htg?t zpd0T5;T^wlSJNB9Qn3iZ3Q&&3`MNh8!kJ8(Q&_tqO5qYT&~ zCfRtx}ov4Zpo%I4q@hbW^`xn#lV29v!u>MJ^d;zMQ zf!N|;OP&gNk(|R-(3<-KaeG{1nqzI=kkJq~^Nm6Rt7)+Az%EiGX2J+o-13POWv;eF zx>fH04av>mTEnjoiVjhe$FHZkqlK+Z5=$5IjwtssX*}9$Hut>0m<$vrgSs}J3wtdk z&CSxx!LoE%V18f~kC++Wd`Bu@8L!8mzo4#fTDEFX0Uy9Czmi2j7bNi{Ye6AKV1@h1 zSfusNhNhkyq?Bc_{dK`OYvC)NvCHN@Bb}^p*n^fR@52Ad#dF^ z_C0SGcLLmeP97jr6t@sZ$Qvh&b9yidCb=G~JIgt~SE4atnZU+^o<*8WPvnHYgqqay zTrDP9*bVo>wz?6CV}1BB;t0YR+&y!Vq7Pf@IuFN*>HZ+TkNA^PGX)2|t!q5|+&6L2 z<`X%1>*dAQ5FRn2V*KX6DVB)GC|OlW-iA>6xBIvba!f^!O;6^kp&G4&_6jk*@uEj- z-nsJ7sX6w_|Ko*%D@zLyiy{#OBFAb$s^(r&k>LN!}!- zGs)ubZ@AoOr17>wC=4y{IA%lDnjcfg!IafV9rMg+TR$G?)1Mi4*Rf65nFRL{6B_B92HSd&3fZ(O=Vgem?5{eaw*vt@2b|EW9a1bbyV%KUuBK7LT`(l?J{#ifZkDkvD zPx%;-9k@7(yvgUdu6H|P3bTq%s!O=IUX}uEUK<6fas4Y?rFQ|FGH!T%!|i(eQ8Apq zUTV62XeStKj1y!U=0!;T=0>tt@M5^jGPUbqJ(jRwL2}nr@abTyv3dLZiN`&Zz~mj6 zy=A>uJ(1CBW22zt!92`gs$qo1Ov8#3Cs2R%=@)Rz<5X|9z zWgG6-Qi?66v()!a=3Eh*1Dm`{*oPdMhc(jbg7v(e-i`$^>cD_mn~!(kX<4jN8h6pOYHXb5soH z-N-no>I}PreoA7}1M5EBv@UF`Ed(m&mSTX)5$eqOi3!AdYj#O>3~~N4waaVlb&F3l zwVbD3_D_4RxQF|x7j2GG_9bsrnlv9r&VBzU8ii9rXrhhblO@~dQ~%X2qme?XP^+J6 z;Tm;PWDr*aGr7fs-}Pj`ZX7K)S8H+h=9~gvz27Jmu#|#w7=6^9JB2F)TR(N8KgXT z9tf^`x=F9s42nEM|2AhD(w{hSIzU$f)p&Y&p-vqV^=S;k;it?QAiIx{X0 zp)4g&J80F$3n!n3;`brD#V0-7%M>oQzHBYK?aP77)aj>{{poTVMLG^buoW0e2TmER z18ohWuS7dL=A&~RRB$p1Ls*U9gw`j)me#D6&0d~n2KRC%s~&yBszwi&Aj#>*Y~Ykr z3*B(60Ibd%5wwUdIqVMpk(dX~bS_Xa z)N|)?*QMCvOn6kj4Y)1x4yv5zQ-ga&ny1-cifb9>i>pk3KOZM%_^o>GjH1bGGM1zu zZ9z`|^g6?*tku)?6)xzK-r9vFK4K7lxBsjA?*=+F-Jh4iQv43bvf=_$j{S<;kWGOM zHc6_eNkRQPmPMHs$c2Q)G`4GChx|I@ePO;$emDYq2GyBT%!_kji)|_ z(D5HP#C!PjYIjKynleH#0%yCmjG|zNaNvVi%ZMO&Lb#7fFc#OPEFt|n;J!>`XvMA2 zdGCrIgWuj7v3eMI?kC*X%{ok$dDmuWm~m z2~aR`MKMdidi>sEd4Ho=#`NYx(ah%N6WyCNMFJU9QO-`SEqk^+i7VEgiuhRtylD}2 z(*2)IOP6b{f;nqpe(%2av3>(#Ybo+Y4yty4fNry$sT3uBYiKLi_$ox;pXFQU|lS0j?tXCWex<>bX5Wul0r?3_lA@5kK2P)M-+oo^1@w_ z^_YsZhyo-KT8Pu&qhGPJJm0DRwm|wJt7RFLFxVqMsZirTc$9yX^9$K=K1RaQJAXMV;bV*5nqWh(K~P=@OO|Qh1h2NokgV!Y~#k2uY!x#Ay@!jy9;j(B>f6xs5Qc7G*c6}(anbyNP1#A4uK5}o?mV7p|T zSmTe&V$ttD*(#fk*9V+>>!v!NMLpunBWm=7reVJBBP+64t}0uec_$S$?}L(0OLW7J zwA|N2NO}|hJ6(7csvVHcyd)V|F7fi3v+Sr>C+}PcsskKOT==t*y3pg*Wde#xf$&8nuqXD66D!^Q<(7SO2N^;GEgb0RXdb8M}NxK7z_c~ zec5Ao&R|4ivkXns0vB5$FPOUTGjuENl%v%et9YnB4p1-J8N3lK>D!YHWf!?*U|ZQz zM2gSH1V3M9bTzhIXHrp_KMKvBA3?%K(N$2nN>P6uB`ek1bd8d`k8LVyGCNBu%NYO{ z(+_>r0syV|pGfvt4+iaouQ!G`)Wu9JyfQlAIg?*M{dq@)7~aGJsJT(oKH+tR6Ky&vY34^6W`lX7nza4JY7NJ+iH+gxZo5`n(CKyW1-EkfxeF7KbLdC1uj&Vq3p+B46z*G~QI)&&Ey3 z!f2T~8Yt%`wpI+u{Wd)se@TqQvB}mWGDt^3!N!Yqy_~1vLeehl zG8&E*`1{RwYdw#+{^hgQ)QzE!log(SiyZ^9*7H!=G=Azsn2KrgX=>DHwf!j&u8z{p?#&aP%)Ha^_>s(uK(6p3{%1`fI&OP zC`;@r#*IV2N?nTVkQ(&{%C5Gq6WvRS=6~QtFZ;4_Zh-8(_v(3ik7L!<%S38~`GLbv z&{bP#R5y=|CpykLh$Xc!78Smg^>FNygc$7MPL0!`%@!X3%C7~fkr|?Krdg%rgeQ_e z2uTaGZtrfq6dCyMdD17=Gf2xf<5=A28MT+&n(%+81yVt=K`=YZ2>;*3>+P0j$!oGT zV>UvL^dxE|B9pYCMA1zG1H!eqW9a^PVcB!oW{#Jlvjg4nOf!{Fc3HsGRTqal_a)sZ zi3y>68(j8nPytO3?0aFbpydKC{gY}y_J#`K$3F>HB*g?|20PvmRW!qCw}F5p2}1)B z{XZ$Qm3R!TkjoS`sc@F2>z$mqaa8qQvrxU3V@?WD?b}tqt(xPun*;3$!FzS69wN^t*`k?ws3{{S#XjZ;f~vZr-M3lUU9&W;_wK~e zg)+oV?n-+3@XXt}OnY-6{!U4`WjBK*Oj#z;~c0g@qcU#cw9=9?AHEN)<2Fwj+`_#uK(%d z<6>F)h$C={f7S_nhbow|OIN5G%Iy19oq)LP(`C#ws5Y{w8fUA|<<@Y!UX8)G5=z`4 zYcUr!B~hY*E^P{{Ow;g<+eZEswn!u*uJ!#_3T?%dpzrRkUzjl=+|z%(B4O6(f#JTG zmN3Op+<57NK1~m9Py$89F(nFt389QmKJ9lsSOo)kaRjSAg#cl2Lfg_q&fy6?TgPx~ zCSx2?E^3hRD`E&&@6a1;u+`fUEEM<{|G1$L(C0D6RHdr-vG&mupetHYIVH;5ujdkh z4j@Z$=;WW?4ic}WT*QW%>O+d68Lw_Hxc-sz62-C?{CEk30gW^bN(|BMo22)HoXk!` z9BTP4g3KDYMr@?|4kjiycTLhlL}~1hR5*^jTK6UGPzX0B&elCG7!`gF(`LM4$$h^1+-gOm*D^SHV+wYo4ZTNH=|76;Hc}I+yb_Bw z^*SmW*5|(wybR-#GYO-r79TJRGo$s&F$JI$jLx5r zz|n^fx}xJTPz~@I?$fIUy;TX?x%ms}7saC$QHBM>)$5OMyzPjU=M7cdXRZ96*<-5k zIh+-Nz3}x99~o2f8XV%ctk0++W_&J8td&ATQX{e9w+b~{cNLMfly$uc+usx>3z2%= zY34ND9a^4o!L2%rZ)aLv`iZr|n5qffH8_H;Hz) z4*J(tw>c%b-kc67{j)$(o;%t{hFblW+$@((>0!q;gc@~y?dBmG8cG7SR?hzJUuk29 zPMz4mS}d8GOvMpDlNq!+1ZoD@YWp|j(pV=WYJ`3GF4q^{cAkEyk>3m38X9{`-77%E zU$@rc;`OI^vHFLiV&LpyiDY<*s<7X~S(n7$MI@TZf)u!4zls#Xzvj}-MWOb_l2zHw z_er2AH{odT0?{0oZXsD|QYB#<(EwbWuBU6#AwQu+OkMT6CgR19#gA+nsFrb?c8K^` zlv#jz#Tplkry$FF$rKnK9~Soh44%vu+NHoQm2DEZvG}UraL6rj3oiUi9)Gn=mC1 zj$Cy1nx5r!%tTA;A1{;+PrP(EXvKJZC8hx?K*};&sk1A=BFjiY^Mu}53V^E7r$2&$ zm?a%Lh(lVk=`wwscQzeRN}X~8z=$)N=9UFM6^RsDczLNUrk2biAV^OsKo4@yfQ^N8 z2~BiJQo<#}N4eYlLK`*XKFmwEIls`Pwv9~CD#YL&hEM2^HR1m|{P7_GehW3r)s7u0 z#3_iJSdx9OyE(W?7*{uBa>7#NW zsX-+`rVeqMfq;czHP}s)g}m zSP~hV>ZQ(HdQ8I{#GD9y$o(~EA68JtEM}_X=Izgp)5gA40yRKg)DgrYsyRond?EJ@ z23OO)C2Dqw8rsAmCtlv&rs=+;;5U|p~+aLOnR71h?y=8n@^`=GT zS+ea5Mrc>RV|I@E183;VLNA6$Mn!gKdl zzo(*x_#MiIo?MI2UDXeJ{X#GJQXG-kPQL$zaIso%XhPx$8;Sk=I|qa!&?4{}Kg&HA zb|?iVL03lcMywCSOM+#7YfRK5F?2F*Bb*=eYCl|~nY}d&^GY`Q&F=gToH2~`%L&FS z9Wa}X(R4ud@KX3v{#yVcjHzfYTwZ@&7wm;Ei1&Zfw`TMEB3S4@E|F3zlD@w8Ya)Z; zMt|cDyFvo4F`B+qg@Em`RJOMaM5KsWM zE8|m3)nU~BW$h`%a;^*>1x=cTZCHsk&^*~MNq6-;Kg&Q1`9iAB83K7_o8DNP5<`QFQ4{He!CLeO9$A7TACJC<{^&@#SaL8ZGk7ka z)~#x5kY#FwL35DAF)nf9`TLI@an%2^y#s(_w|&C?U$;6a!;izlGMo2ksT83$YlIl7 z-DQa**?Ke(zrax$usc#G=slJw8o8XYtQV`ek1h~tc-57{RfA{C=A${sw?dn+Jx;`0 z5Z5vbyVh>&KAYbW9AGc&kqg+qS}sqzPYfSHE{+sIPkX(V;xzEo%L6O}(teYtNr z?7)zi7K1J6;^zIrx>|}JRzl3kHF+w-?)-i1GQBL;a$5d^I$?66jl@`F_)1)J-JBSUX+DQ&mnO|QI$T<~h0ad28u1?L%XRTc!v$c^SO-GxSM8d)_IZJnX#qE0dx zSlCrz1@myH_<<^CG=n^^BC7(W3YpwEOTR~h`<-gE=WtFzlAp>rU}U;zREn#Rp`mzn z2vQRp)mW=l07(5Kv~&*%h!coNqgcH-9`0#Ze|p--XpeBUg5eOGEB7|ts;yJIcrO!! zHcW|WjO(Q+z!`(+pHZER;`F(N?9=wDoZmyiKvmV7>ezFVc*&w8F;w%W*eq@Kt!)sl zoH;QA0L0lfWKhrl3}1_0cS*J$y~I8$QvloZQ}YLQYZVb#cm$75#1#@fHm35_vhDq} zu>C?icx&S6YsLtf4y=Y(Q7nt^w;_U;fJ-5W%C1iGF7!MTMc)gxd*xq|#Qp4`MktdO z5|Q}zW2kZKu+O1OeL3NpgeDy1BS)RBawtrU61F3HIv6_`^VT>UK5 z_4eCK>z(DTY+;hOEHu=zNq{u1Drph5odx2;WE*x@qG~2VJy(u8EpE8a(8n7&q4XVJ z1-)kPY7|>h*GX@b=ISsgls%K=CdBOdRn#)&w3V60PY^@+;LWG>Ze0L1;$x{jrj|sX zeTv-K*7Q6QX}4%B&*HTr%E2n8)nV_x@X^K1Kd8Vlx(kF??l_kM*uKYAPf#){OD|dA z2Ms~J2kman?jcE1900Q2ei`==gvqg?nS;q7NIDDleApoGMa3lzR62m`(Rfp$Hw#iuZzTv8X>jWRhjDSz&s_GqG?lQPKrD-MD$LVp|< zcQ^uCQu{64zvz-^B^up5u_|ye0m{OjOt3L0S7Q5L-Pu=bT!F&#`3qiQC$!(VWOq+mz^wfI|n=f_BUj$8dhFMQWRD4Ma9msjNW~m4`SZ0Cp>I z=Vt14U&R+~aFw9l*XtHzAo<{cy^nxW(;Am`vXjU6VjBKhSCo+JwF);)FCzqyg6975 zJ}{{fJ*_kgfaD*)jlg+>Njw}Hbvom4S*r?$Ofm3qN0U*2y?^~=gC;^MQk%CHicB&)a+0P1wj{kP{`0^H#uX^jR4SCdbwIMN_ci2l&dFf+aJw<;z3O)yyK(Z8R|a5& ziv5-}l_2$rQ-!dXoP$9IIL#@i| zWzKIroGHOG0@A72-drOlA!HUl$*;0*y8i=8Bowt^Ovs?NIfDK~t7FK{22=LVHs%Yh z((SE$nUZLvA5@Yl_+m|BUKT}8#Ll8z0uXM6GT~N*PPg3t;vXaZLkv!UeVPS~2Ez(% zs2y%9Xn#7&kb6eKZ6CDSzqWaLtwVL)GO#!RJdDjXlkCVmNcuugqp>BMMgR`+CDiGoZKq|reF z;8l@w)D;crA$Xr6-pn@7&&Pn==7=eq8cX!`61fx7xcI519Q0MgM-OV`$U@hazJ4$^ zJz474{=&-s+^Gj$Ej-s6o5WW=KxrZHL}!qen{)hSo*zFqgcq0`6Nxg8>8dXMIeg^O zHwWgM_Z}ni%<~2RTy$doZ&fiJe(R)W83xJjhH`I(N4ye%8|mw%95OZPdlj8osN_I2 z-6&))`}(`TKdqrJ+p`G|6J8&jYkXn;l?+3~g1ZFFdc`XeOm-Td$CF}y_J_;_Rs=7TkZi|cwVnDL1keK=cPO+Tz6F7$szMUnyG;jVyY z(93Nu#*y;@LtJTN78kpJYL+0C{vrFvhck zI8Gx;gVTG5YLJDcl%;}=>!cZ^0_<0AqFd87R1;QNTF*OB#LEqyg`TasGAIN|?!P2g zjK^axUyE9jPDCDY>{oo)5ca9{bmAUiY+W$cG9D8ge%)&a*gku*=M$aUTXM;&&8dBdb z=jdj&q;|68Q{lc7z}jJwG6pu(a7xeX1tYSvEdNklk=PECTP-$trn;A**)ZMb3_Ypf z#Ij{=SN)6{M{!#zzmPZd7bLO#J4S@aU+7KDQjAy|A@E~qwk3ng9$d0!>SS1 zj~QC|+B%iyua|H8^A=BzFI-CpP<{dqq|!hp>SAgZR*i%V`%q#!GS-M1T(VSl^VQid z^pz$yz?T%u>?xzA5S-p4U;LOSW63aqF`27*27n_t)nd;xiF#{^trRL^Hx0Qe{_?K$c6~{ zT^~!2;=GC?mp$R7Ubn&;C7@AZ0ed_-^l$t#qtVUgxMVkGzXafvLY{@Dy?U&Z3LGO7 zxj69hv2MN-$ce#C;P2!H{b{lkosBNClUz;(s@^cN1(fUp_zI9XRw|?T<_y zWRBOKK92*m!%6{*)bv)kQ(fz*dCqY?FQCETSdOUwwYx%uKWlC%^{h+>{Zr$_JqKr* zQjPB182Wcz?{{4^B~S>qfYUZSdqEl|)+!LQKCyOCo$3{C{~QAP%GO)zP|hLu&kY5$ z6-hbqOnu*0f(K!v)2WR9g-^l%+pSm1K42?sac4^-uNZ^~EC={}_x^L_dyulwNpk>R)3lSn(&NZdxp^y*?Mloxk*u0jdSM0Ls*622u1Ns^P9q)kE#$Ikj~gn-H|C$8d3KSZ;z#OvhQe?t;QdEwGH8mH zXpcm82&96+6^_JWtQT2qrXwX6PS4ZlJ%sMoHf%-3bBX@v-zgP|QzsSv#{YpTe`PL3 zf7N-9WR8ZuZLA5ZV=Yp}?$Qyip4t$FqnGn;YbTMa$zqt|-r|m`N1tBmf{uv$5!m72 zF)S7L)B^JmuR_{7PFRH;8l~gY10SH^hEK$e<=Xa33b;*HJJxjQv;(4;Rd)lbT`Wxo zWboFQt~ME?j&eskLQ!huGm=t;K6iL3M;G^-7$3msMMv~86vt0i$lBeKg(VsS&0I0% zu$St`@)AtSldtFM;`edWSfN^!YrBwZ6VrAXQHK`8e?ZJgg3(0HGgH#OJrepp1S)V% zrikTDKt$6r9h9?6bJeCgxgf31?0VG_+jF2tM-RJuo&IfGHdLc@fPx824#s-GoAm3t zi|$QK4&NDbQ4Uj1=6cbhB)6tQ7%1#4df7`H&bsSGQ83LFYcgBk)J?^e__tWS}oB0v%Kf3Ky(&hqkW2yTWWz8vSY3z&5m^Y40t?bTbo4ENj znGNE%nrk-2JHH!Rc;-KN8v$vspn_*cOrGA2o0Xbll~^fdzjZLyyC?zGCYgt>U(7vY z;A4qRG!h{Rr`XKLZxpm|lV^r;Ho+!h_S0**WQdQGh}zlzAf!fzQkSLMk=`Q*Kk6SRmZjOa*#$1aFc<^DuiW6+2stFfXD!)sBW=lfkGerePTK zm|G|uuMQsO{BvN3BAWJ%g7U?LWvSGC0{&?p?>)ZL8OsnCRnit(annRI_lY69u6IU- zTBTC?2kgteg5Yt_^qYk}3sRqU7ovU^7f_`x&a*i-n@ng<^VGff2875wY3ymK5fdUI zCa`xdRTz$41gD~VOXHG}`18d-k5=?vVd%&pC&tGxfYO`t*ZIt5o-^V7aE7wn$@fG4 zSOeF2ae%ZOtQBq}emF8cjabPO9RiF;)d(hbvr^GAPgVh}J@r!6aDZkE1IaG74$v(& zdqo(KUdEkgd;}5`AWPyaXF2F_NJUEr@0eXML&F1DxtN+NUTA-;z78f47}?SiHE0LSe?NIg$VI5lGk0i=4|(93T^k7% zdARAMGj;PY!LmbGiCHqLpU=tf%qH?>9(P5bUf3yXh@(;g%n#)4ywPaRXq+QAp_l^k zw60FEHE+!T6!ga>Jyt_!Hfc-t)syuPb&hL8?`sja&5lYopt~Y03g1V zP+?vIs?xk$@P5C-gmGr&_^F-WhFcm1qqU_4{|7vy_xGjUai}u%rfJCEA|`w!N^vNL zVAu=Ba)%S;G{Sm_bs$af;h*(9)6bJzJ)(Z7-6dP7; zZm1%atw7vU`;A^iQfcC)7&d_T8qlnn8i{q@Kl(L>x1)h7G|YH84VW6ip4!k|7|zFgLc&+;4M&|g_pH6% z=2LkLR>>lN%U)Nv%Mtq>~T3z$`yitbP^{TGvDp8M}fI=D` zR%(br;KQd}z#$wlh}m7u7)|qx-hwWu+bmWzgKwl*dotsZxYf<_LvcQo)qeR|s4^iM z&=W+ga7@&}DTk(#;r_S{G9@eXwJ!~+jlafc1yQu1oe0XvdWdfUa^qEul2RySDkTW@ z4AA@Fz9#7%et-ENm2)N8Zxc)U4%fJn+bSua30xe)2^8Qe^*Eoy&%Y47@GsigH<}Zi z6VZn zy#$^pV9NCA?90_{-o=_RQPI2HDHO0*g^p?}RyXqa9#g+@6U=7-{)2{MHtf+C!SM^s zTIx%;n|WgHtHPd2IqRA4_$}`QP>bGCfzwF_UYD`Ge;i7@>XM$@Lh0!G40!CF`tgvO z5&JhBO(|&p;sYQ*jOM5v?wB1SEmKJ0C>ruT>P_Ln*HETs8CXn|gje0O$DsG)m+m!5 zrbZbkJzU&d9X%curYqSAci0~+e4qhAo^)Qt9q2dsZ|{Npr~kL>Kw+RDDx4K3ejd7Q z22R&)pHqT917>IZm*aHTEIO!ZMmTT8;8BhZ!B#TDJbqWAwv1`lHe`*`rs$RfH~#0Q z$9Y|N^u@ABHSx<5#MzWvLqHCS95t8-;ns();>7br&hz{cn+cbAyC$uf1dDi5CqB+X zIYw_lG=!I>C3ze8n+OimY`zMPo-iO6^?iAob@eVN#4k}rN_>Vo^puIWe6__-uUB<%F)b!v_C#@IV+ZVe465N zj>u2a142pd?Su7KS8_x8&M?wH+BC^)(tHUi8~^RHn0XG%q{lzE0Ha`&iHP9ksEP(1E^_sAvXOG^15C!@rJwydPA=|ExH$5ubOKx9H@r z`#{MY-vElSEr=ikAFzhp{CEw?{zSt_Zp@EJtk23%=*gIl+E_+-23mjUUls!B)@%6?1rpE=T;~T}Tt`6e0 za{TAsqcf(LdXq;7L^(Q&0IuTCOs=0kyfS2ejvgMqQKxxU_QRg_Uv?J-&hhIz`?`N^ kH3 - - - - - - - API Reference — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - -

-
-
- - -
- -
-

API Reference

-

This is the class and function reference of biapol-utilities. Please refer to the examples for further details, as the class and function raw specifications may not be enough to give full guidelines on their uses.

-
-

The label module

-

The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of -an object is encoded in the pixel value which must be an integer number.

- ---- - - - - - - - - - - - - - - -

label.compare_labels(label_image_x, ...)

Evaluate differences between two label images.

label.intersection_over_union_matrix(...)

Generates a matrix with intersection over union of all mask pairs

label.match_labels(label_image_x, label_image_y)

Match labels in label_image_y with labels in label_image_x.

label.match_labels_stack(label_stack[, method])

Match labels from subsequent slices with specified method

-
-
-

The data module

-

The data module provides example data to be usedin the examples section.

- ---- - - - - - -

data.blobs()

Gray-level "blobs" image [1].

-
-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/Examples.html b/doc/_build/html/_include/Examples.html deleted file mode 100644 index 8b56d58..0000000 --- a/doc/_build/html/_include/Examples.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - Examples — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

Examples

-

This is the example library of biapol-utilities. We provide examples for all top-level functions that are listed -in the API reference and comment on their usage here.

-
-

Label module

-

The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of -an object is encoded in the pixel value which must be an integer number.

- -
-
-

Data module

-

The data module provides example data to be usedin the examples section.

-
-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/biapol_utilities.label.compare_labels.html b/doc/_build/html/_include/biapol_utilities.label.compare_labels.html deleted file mode 100644 index 691388d..0000000 --- a/doc/_build/html/_include/biapol_utilities.label.compare_labels.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - biapol_utilities.label.compare_labels — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

biapol_utilities.label.compare_labels

-
-
-biapol_utilities.label.compare_labels(label_image_x, label_image_y)
-

Evaluate differences between two label images.

-

Compares two label images to determine the -label-wise Jaccard- and Dice scores. -The Jaccard-score is defined as the intersection over union of two labelled -images [#]_. The Dice score S can be derived from the Jaccard-score J -through the following relation:

-
-\[S = \frac{2J}{1+J}\]
-
-

See also

-

-
-
-
Parameters
-
    -
  • label_image_x (ND-array, int) – label image of arbitrary dimensions.

  • -
  • label_image_y (ND-array, int) – label image which will be compared to label_image_x, must have the -same dimensions.

  • -
-
-
Returns
-

    -
  • pandas DataFrame with columns [‘label’, ‘jaccard_score’, ‘dice_score’].

  • -
  • Each row corresponds to the measured quantitiy (Jaccard- or Dice score) of

  • -
  • the respective label.

  • -
-

-
-
-
- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html b/doc/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html deleted file mode 100644 index 1f7d03b..0000000 --- a/doc/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - biapol_utilities.label.intersection_over_union_matrix — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

biapol_utilities.label.intersection_over_union_matrix

-
-
-biapol_utilities.label.intersection_over_union_matrix(label_image_x, label_image_y)
-

Generates a matrix with intersection over union of all mask pairs

-

How it works: -The overlap matrix is a lookup table of the area of intersection -between each set of labels (true and predicted). The true labels -are taken to be along axis 0, and the predicted labels are taken -to be along axis 1. The sum of the overlaps along axis 0 is thus -an array giving the total overlap of the true labels with each of -the predicted labels, and likewise the sum over axis 1 is the -total overlap of the predicted labels with each of the true labels. -Because the label 0 (background) is included, this sum is guaranteed -to reconstruct the total area of each label. Adding this row and -column vectors gives a 2D array with the areas of every label pair -added together. This is equivalent to the union of the label areas -except for the duplicated overlap area, so the overlap matrix is -subtracted to find the union matrix.

-

Source: 1

-
-
Parameters
-
    -
  • label_image_x (ND-array, int) – label image, where 0=background; 1,2… are label masks

  • -
  • label_image_y (ND-array, int) – label image, where 0=background; 1,2… are label masks

  • -
-
-
Returns
-

iou – matrix of IOU pairs of size [x.max()+1, y.max()+1]

-
-
Return type
-

ND-array, float

-
-
-

References

-
-
1
-

https://clij.github.io/clij2-docs/reference_generateJaccardIndexMatrix

-
-
-
- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/biapol_utilities.label.match_labels_stack.html b/doc/_build/html/_include/biapol_utilities.label.match_labels_stack.html deleted file mode 100644 index 1815ca2..0000000 --- a/doc/_build/html/_include/biapol_utilities.label.match_labels_stack.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - biapol_utilities.label.match_labels_stack — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

biapol_utilities.label.match_labels_stack

-
-
-biapol_utilities.label.match_labels_stack(label_stack, method=<function intersection_over_union_matrix>, **kwargs)
-

Match labels from subsequent slices with specified method

-
-
Parameters
-
    -
  • label_stack (3D-array, int) – Stack of 2D label images to be stitched with axis order ZYX

  • -
  • method (str, optional) –

    Method to be used for stitching the masks. The default is intersection_over_union_matrix with a stitch threshold of 0.25. -stitch_threshold : float

    -
    -

    Threshold value for iou value above which two labels are considered identical. -The default value is 0.25

    -
    -

  • -
-
-
Returns
-

Stack of stitched masks

-
-
Return type
-

3D-array, int

-
-
-
- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/generated/biapol_utilities.data.blobs.html b/doc/_build/html/_include/generated/biapol_utilities.data.blobs.html deleted file mode 100644 index 9f341f1..0000000 --- a/doc/_build/html/_include/generated/biapol_utilities.data.blobs.html +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - biapol_utilities.data.blobs — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

biapol_utilities.data.blobs

-
-
-biapol_utilities.data.blobs()
-

Gray-level “blobs” image [1].

-

Can be used for segmentation and denoising examples.

-
-
Returns
-

blobs – Blobs image.

-
-
Return type
-

(256, 254) uint8 ndarray

-
-
-

References

-
-
1
-

https://imagej.nih.gov/ij/images/

-
-
-
- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/generated/biapol_utilities.label.compare_labels.html b/doc/_build/html/_include/generated/biapol_utilities.label.compare_labels.html deleted file mode 100644 index 7645d7d..0000000 --- a/doc/_build/html/_include/generated/biapol_utilities.label.compare_labels.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - biapol_utilities.label.compare_labels — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

biapol_utilities.label.compare_labels

-
-
-biapol_utilities.label.compare_labels(label_image_x, label_image_y)
-

Evaluate differences between two label images.

-

Compares two label images to determine the -label-wise Jaccard- and Dice scores. -The Jaccard-score is defined as the intersection over union of two labelled -images [#]_. The Dice score S can be derived from the Jaccard-score J -through the following relation:

-
-\[S = \frac{2J}{1+J}\]
-
-

See also

-

-
-
-
Parameters
-
    -
  • label_image_x (ND-array, int) – label image of arbitrary dimensions.

  • -
  • label_image_y (ND-array, int) – label image which will be compared to label_image_x, must have the -same dimensions.

  • -
-
-
Returns
-

    -
  • pandas DataFrame with columns [‘label’, ‘jaccard_score’, ‘dice_score’].

  • -
  • Each row corresponds to the measured quantitiy (Jaccard- or Dice score) of

  • -
  • the respective label.

  • -
-

-
-
-
- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html b/doc/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html deleted file mode 100644 index f8ddb1d..0000000 --- a/doc/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - - biapol_utilities.label.intersection_over_union_matrix — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

biapol_utilities.label.intersection_over_union_matrix

-
-
-biapol_utilities.label.intersection_over_union_matrix(label_image_x, label_image_y)
-

Generates a matrix with intersection over union of all mask pairs

-

How it works: -The overlap matrix is a lookup table of the area of intersection -between each set of labels (true and predicted). The true labels -are taken to be along axis 0, and the predicted labels are taken -to be along axis 1. The sum of the overlaps along axis 0 is thus -an array giving the total overlap of the true labels with each of -the predicted labels, and likewise the sum over axis 1 is the -total overlap of the predicted labels with each of the true labels. -Because the label 0 (background) is included, this sum is guaranteed -to reconstruct the total area of each label. Adding this row and -column vectors gives a 2D array with the areas of every label pair -added together. This is equivalent to the union of the label areas -except for the duplicated overlap area, so the overlap matrix is -subtracted to find the union matrix.

-

Source: 1

-
-
Parameters
-
    -
  • label_image_x (ND-array, int) – label image, where 0=background; 1,2… are label masks

  • -
  • label_image_y (ND-array, int) – label image, where 0=background; 1,2… are label masks

  • -
-
-
Returns
-

iou – matrix of IOU pairs of size [x.max()+1, y.max()+1]

-
-
Return type
-

ND-array, float

-
-
-

References

-
-
1
-

https://clij.github.io/clij2-docs/reference_generateJaccardIndexMatrix

-
-
-
- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/generated/biapol_utilities.label.match_labels.html b/doc/_build/html/_include/generated/biapol_utilities.label.match_labels.html deleted file mode 100644 index 9636ccc..0000000 --- a/doc/_build/html/_include/generated/biapol_utilities.label.match_labels.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - biapol_utilities.label.match_labels — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

biapol_utilities.label.match_labels

-
-
-biapol_utilities.label.match_labels(label_image_x, label_image_y, method=<function intersection_over_union_matrix>, **kwargs)
-

Match labels in label_image_y with labels in label_image_x.

-
-
Parameters
-
    -
  • label_image_x (nd-array) – Image that should serve as a reference for label-matching

  • -
  • label_image_y (nd-array) – Image the labels of which should be paired with labels from imageA

  • -
  • method (str, optional) –

    Pairing method to be used. The default is ‘iou’ (intersection over union).

    -
    -
    iou (intersection over union): The intersection over union is used to

    measure the overlap between labels in both images. The label with -highest overlap is chosen as counterpart label

    -
    -
    iou_streshold: float, optional

    Threshold value above which two labels are accepted as overlapping. -The default value is 0.25

    -
    -
    -
    -
    -

  • -
-
-
Returns
-

Processed version of imageB with labels corresponding to imageA.

-
-
Return type
-

nd-array

-
-
-
- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html b/doc/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html deleted file mode 100644 index 011bf14..0000000 --- a/doc/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - biapol_utilities.label.match_labels_stack — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

biapol_utilities.label.match_labels_stack

-
-
-biapol_utilities.label.match_labels_stack(label_stack, method=<function intersection_over_union_matrix>, **kwargs)
-

Match labels from subsequent slices with specified method

-
-
Parameters
-
    -
  • label_stack (3D-array, int) – Stack of 2D label images to be stitched with axis order ZYX

  • -
  • method (str, optional) –

    Method to be used for stitching the masks. The default is intersection_over_union_matrix with a stitch threshold of 0.25. -stitch_threshold : float

    -
    -

    Threshold value for iou value above which two labels are considered identical. -The default value is 0.25

    -
    -

  • -
-
-
Returns
-

Stack of stitched masks

-
-
Return type
-

3D-array, int

-
-
-
- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/notebooks/label/Compare_segmentations.html b/doc/_build/html/_include/notebooks/label/Compare_segmentations.html deleted file mode 100644 index 9f45111..0000000 --- a/doc/_build/html/_include/notebooks/label/Compare_segmentations.html +++ /dev/null @@ -1,5798 +0,0 @@ - - - - - - - - - Quantitative segmentation quality estimation — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- - - -
-

Quantitative segmentation quality estimation

-

Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation.

-
-
[1]:
-
-
-
-import os
-import biapol_utilities as biau
-from skimage import io, measure, segmentation
-import numpy as np
-import matplotlib.pyplot as plt
-from mpl_toolkits.axes_grid1 import make_axes_locatable
-import pandas as pd
-
-%matplotlib notebook
-
-
-
-
-

Input data

-

First, let’s generate some example data!

-
-
[2]:
-
-
-
-blobs = biau.data.blobs()
-
-
-
-

Let’s segment this and take it as a ground truth image:

-
-
[3]:
-
-
-
-threshold = 128
-imageA = (blobs > threshold).astype(np.uint8)
-ground_truth = measure.label(imageA)
-
-plt.imshow(ground_truth)
-plt.title('Ground truth')
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[3]:
-
-
-
-
-Text(0.5, 1.0, 'Ground truth')
-
-
-

Next, we shuffle the labels and expand them a bit:

-
-
[4]:
-
-
-
-# First, shuffle randomly
-label_shuffle = np.arange(1, ground_truth.max()+1, 1)
-np.random.shuffle(label_shuffle)
-label_shuffle = np.append(np.asarray([0]), label_shuffle)  # append 0 at start of array - we don't want to shuffle background
-segmented = label_shuffle[ground_truth]
-
-
-
-
-
[5]:
-
-
-
-# Second, expand the labels a bit
-segmented = segmentation.expand_labels(segmented, 5)
-
-
-
-
-
[6]:
-
-
-
-# Plot side by side
-fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
-
-axes[0].imshow(ground_truth)
-axes[0].set_title('Ground truth')
-
-axes[1].imshow(segmented)
-axes[1].set_title('Segmentation')
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[6]:
-
-
-
-
-Text(0.5, 1.0, 'Segmentation')
-
-
-
-
-

Re-match labels

-

Next, use the label-matching from biapol_utilities to assign correct labels to both images

-
-
[7]:
-
-
-
-segmented = biau.label.match_labels(ground_truth, segmented)
-
-
-
-
-
[8]:
-
-
-
-# Plot side by side
-fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
-
-axes[0].imshow(ground_truth)
-axes[0].set_title('Ground truth')
-
-axes[1].imshow(segmented)
-axes[1].set_title('Segmentation')
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[8]:
-
-
-
-
-Text(0.5, 1.0, 'Segmentation')
-
-
-
-
-

Compare labels: Labelwise Jaccard-index

-

Lastly, we calculate the label-wise Jaccard index to measure the intersection over union (IoU) between corresponding pairs of labels.

-
-
[9]:
-
-
-
-result = biau.label.compare_labels(ground_truth, segmented)
-result
-
-
-
-
-
[9]:
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
-

68 rows × 3 columns

-
-
-

Let’s also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label.

-
-
[10]:
-
-
-
-LUT_jaccard = result['jaccard_score'].to_numpy()
-LUT_dice = result['dice_score'].to_numpy()
-
-# set segmentation quality of background to zero
-LUT_jaccard[0] = np.nan
-LUT_dice[0] = np.nan
-
-# create score map
-JI_map = LUT_jaccard[segmented]
-DI_map = LUT_dice[segmented]
-
-
-
-
-
[11]:
-
-
-
-# Plot side by side
-fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))
-fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)
-
-
-# Plot ground truth
-axes[0, 0].imshow(ground_truth)
-axes[0, 0].set_title('Ground truth')
-
-# Plot segmentation
-axes[0, 1].imshow(segmented)
-axes[0, 1].set_title('Segmentation')
-
-# Plot overlay
-axes[0, 2].imshow(ground_truth)
-axes[0, 2].imshow(segmented, alpha=0.5)
-axes[0, 2].set_title('Overlay')
-
-# Plot Jaccard index map
-im = axes[1, 0].imshow(JI_map, cmap='inferno_r')
-axes[1, 0].set_title('Jaccard score')
-cbar = fig.colorbar(im, ax=axes[1, 0])
-
-# Plot Dice score map
-im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')
-axes[1, 1].set_title('Dice score')
-cbar2 = fig.colorbar(im2, ax=axes[1, 1])
-
-axes[-1, -1].axis('off')
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[11]:
-
-
-
-
-(-0.5, 255.5, 253.5, -0.5)
-
-
-
-
-

Compare-labels: Feature-wise

-

It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops.

-
-
[12]:
-
-
-
-properties = ['label', 'area', 'eccentricity', 'orientation']
-features_gt = measure.regionprops_table(ground_truth, properties=properties)
-features_seg = measure.regionprops_table(segmented, properties=properties)
-
-features_gt = pd.DataFrame(features_gt)
-features_seg = pd.DataFrame(features_seg)
-features_gt
-
-
-
-
-
[12]:
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
-

63 rows × 4 columns

-
-
-

Visualize as histograms

-
-
[13]:
-
-
-
-fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))
-
-ax_idx = 0
-for idx, prop in enumerate(properties):
-    if  prop == 'label':
-        continue
-
-    axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)
-    axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)
-    axes[ax_idx].set_xlabel(prop)
-    ax_idx += 1
-
-axes[0].legend()
-axes[0].set_ylabel('# Occurrences')
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[13]:
-
-
-
-
-Text(0, 0.5, '# Occurrences')
-
-
-
-
[ ]:
-
-
-
-
-
-
-
-
-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/notebooks/label/Compare_segmentations.ipynb b/doc/_build/html/_include/notebooks/label/Compare_segmentations.ipynb deleted file mode 100644 index b694e2f..0000000 --- a/doc/_build/html/_include/notebooks/label/Compare_segmentations.ipynb +++ /dev/null @@ -1,5614 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "9f0d8ccf", - "metadata": {}, - "source": [ - "# Quantitative segmentation quality estimation\n", - "\n", - "Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "89205b6d", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import biapol_utilities as biau\n", - "from skimage import io, measure, segmentation\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", - "import pandas as pd\n", - "\n", - "%matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "id": "a63045b4", - "metadata": {}, - "source": [ - "## Input data\n", - "First, let's generate some example data!" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "db9c5fe0", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biau.data.blobs()" - ] - }, - { - "cell_type": "markdown", - "id": "2c0c8418", - "metadata": {}, - "source": [ - "Let's segment this and take it as a ground truth image:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "2ae66de8", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Ground truth')" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "threshold = 128\n", - "imageA = (blobs > threshold).astype(np.uint8)\n", - "ground_truth = measure.label(imageA)\n", - "\n", - "plt.imshow(ground_truth)\n", - "plt.title('Ground truth')" - ] - }, - { - "cell_type": "markdown", - "id": "f7f4c0be", - "metadata": {}, - "source": [ - "Next, we shuffle the labels and expand them a bit:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "2b8dc27c", - "metadata": {}, - "outputs": [], - "source": [ - "# First, shuffle randomly\n", - "label_shuffle = np.arange(1, ground_truth.max()+1, 1)\n", - "np.random.shuffle(label_shuffle)\n", - "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", - "segmented = label_shuffle[ground_truth]" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "279f3e2c", - "metadata": {}, - "outputs": [], - "source": [ - "# Second, expand the labels a bit\n", - "segmented = segmentation.expand_labels(segmented, 5)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "eb0b69c2", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Segmentation')" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "\n", - "axes[0].imshow(ground_truth)\n", - "axes[0].set_title('Ground truth')\n", - "\n", - "axes[1].imshow(segmented)\n", - "axes[1].set_title('Segmentation')" - ] - }, - { - "cell_type": "markdown", - "id": "dd726a7c", - "metadata": {}, - "source": [ - "## Re-match labels\n", - "\n", - "Next, use the label-matching from `biapol_utilities` to assign correct labels to both images" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "8007d578", - "metadata": {}, - "outputs": [], - "source": [ - "segmented = biau.label.match_labels(ground_truth, segmented)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "23496dad", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Segmentation')" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "\n", - "axes[0].imshow(ground_truth)\n", - "axes[0].set_title('Ground truth')\n", - "\n", - "axes[1].imshow(segmented)\n", - "axes[1].set_title('Segmentation')" - ] - }, - { - "cell_type": "markdown", - "id": "1e1d39a4", - "metadata": {}, - "source": [ - "## Compare labels: Labelwise Jaccard-index\n", - "\n", - "Lastly, we calculate the *label-wise Jaccard index* to measure the intersection over union (IoU) between corresponding pairs of labels." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "7641d30b", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
\n", - "

68 rows × 3 columns

\n", - "
" - ], - "text/plain": [ - " label jaccard_score dice_score\n", - "0 0 0.496847 0.663858\n", - "1 1 0.518102 0.682566\n", - "2 2 0.470130 0.639576\n", - "3 3 0.623552 0.768133\n", - "4 4 0.602546 0.751986\n", - ".. ... ... ...\n", - "63 63 0.262857 0.416290\n", - "64 64 0.000000 0.000000\n", - "65 65 0.000000 0.000000\n", - "66 66 0.000000 0.000000\n", - "67 67 0.000000 0.000000\n", - "\n", - "[68 rows x 3 columns]" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "result = biau.label.compare_labels(ground_truth, segmented)\n", - "result" - ] - }, - { - "cell_type": "markdown", - "id": "3f218dd4", - "metadata": {}, - "source": [ - "Let's also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "fab77a34", - "metadata": {}, - "outputs": [], - "source": [ - "LUT_jaccard = result['jaccard_score'].to_numpy()\n", - "LUT_dice = result['dice_score'].to_numpy()\n", - "\n", - "# set segmentation quality of background to zero\n", - "LUT_jaccard[0] = np.nan\n", - "LUT_dice[0] = np.nan\n", - "\n", - "# create score map\n", - "JI_map = LUT_jaccard[segmented]\n", - "DI_map = LUT_dice[segmented]" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "ca62489c", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "(-0.5, 255.5, 253.5, -0.5)" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))\n", - "fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)\n", - "\n", - "\n", - "# Plot ground truth\n", - "axes[0, 0].imshow(ground_truth)\n", - "axes[0, 0].set_title('Ground truth')\n", - "\n", - "# Plot segmentation\n", - "axes[0, 1].imshow(segmented)\n", - "axes[0, 1].set_title('Segmentation')\n", - "\n", - "# Plot overlay\n", - "axes[0, 2].imshow(ground_truth)\n", - "axes[0, 2].imshow(segmented, alpha=0.5)\n", - "axes[0, 2].set_title('Overlay')\n", - "\n", - "# Plot Jaccard index map\n", - "im = axes[1, 0].imshow(JI_map, cmap='inferno_r')\n", - "axes[1, 0].set_title('Jaccard score')\n", - "cbar = fig.colorbar(im, ax=axes[1, 0])\n", - "\n", - "# Plot Dice score map\n", - "im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')\n", - "axes[1, 1].set_title('Dice score')\n", - "cbar2 = fig.colorbar(im2, ax=axes[1, 1])\n", - "\n", - "axes[-1, -1].axis('off')" - ] - }, - { - "cell_type": "markdown", - "id": "1dc2ca58", - "metadata": {}, - "source": [ - "## Compare-labels: Feature-wise\n", - "It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "5f6cc904", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
\n", - "

63 rows × 4 columns

\n", - "
" - ], - "text/plain": [ - " label area eccentricity orientation\n", - "0 1 415 0.878888 -0.433915\n", - "1 2 181 0.822705 -1.513862\n", - "2 3 646 0.386542 -0.079653\n", - "3 4 426 0.324798 -0.400592\n", - "4 5 465 0.780472 -0.044317\n", - ".. ... ... ... ...\n", - "58 59 1 0.000000 0.785398\n", - "59 60 87 0.969263 -1.560717\n", - "60 61 73 0.951468 -1.567605\n", - "61 62 49 0.942191 -1.554054\n", - "62 63 46 0.976786 1.538848\n", - "\n", - "[63 rows x 4 columns]" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "properties = ['label', 'area', 'eccentricity', 'orientation']\n", - "features_gt = measure.regionprops_table(ground_truth, properties=properties)\n", - "features_seg = measure.regionprops_table(segmented, properties=properties)\n", - "\n", - "features_gt = pd.DataFrame(features_gt)\n", - "features_seg = pd.DataFrame(features_seg)\n", - "features_gt" - ] - }, - { - "cell_type": "markdown", - "id": "ec29004b", - "metadata": {}, - "source": [ - "Visualize as histograms" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "e9652f8d", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0, 0.5, '# Occurrences')" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))\n", - "\n", - "ax_idx = 0\n", - "for idx, prop in enumerate(properties):\n", - " if prop == 'label':\n", - " continue\n", - " \n", - " axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)\n", - " axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)\n", - " axes[ax_idx].set_xlabel(prop)\n", - " ax_idx += 1\n", - " \n", - "axes[0].legend()\n", - "axes[0].set_ylabel('# Occurrences')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "185d4c1d", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_include/notebooks/label/match_labels.html b/doc/_build/html/_include/notebooks/label/match_labels.html deleted file mode 100644 index 7ec2864..0000000 --- a/doc/_build/html/_include/notebooks/label/match_labels.html +++ /dev/null @@ -1,3465 +0,0 @@ - - - - - - - - - Matching labels — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- - - -
-

Matching labels

-

This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image.

-
-
[3]:
-
-
-
-import os
-import biapol_utilities as biau
-from skimage import io, measure, filters
-import numpy as np
-import matplotlib.pyplot as plt
-from datetime import datetime
-
-%matplotlib notebook
-
-
-
-
-

Load data

-

First, we load the example blobs image and threshold it to create a label map.

-
-
[4]:
-
-
-
-blobs = biau.data.blobs()
-
-
-
-
-
[5]:
-
-
-
-threshold = 128
-imageA = (blobs > threshold).astype(np.uint8)
-imageA_labelled = measure.label(imageA)
-
-plt.imshow(imageA_labelled)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[5]:
-
-
-
-
-<matplotlib.image.AxesImage at 0x29c86bdabe0>
-
-
-

Let’s create a second version of this image in which we shuffle the labels:

-
-
[6]:
-
-
-
-label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)
-np.random.shuffle(label_shuffle)
-label_shuffle = np.append(np.asarray([0]), label_shuffle)  # append 0 at start of array - we don't want to shuffle background
-
-imageB_labelled = label_shuffle[imageA_labelled]
-
-
-
-

Both images are not identical!

-
-
[7]:
-
-
-
-fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
-axes[0].imshow(imageA_labelled)
-axes[0].set_title('Reference image')
-axes[1].imshow(imageB_labelled)
-axes[1].set_title('Shuffled image')
-
-print(f'Number of labels in imageA: {imageA_labelled.max()}')
-print(f'Number of labels in imageB: {imageB_labelled.max()}')
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Number of labels in imageA: 63
-Number of labels in imageB: 63
-
-
-

Match labels and track time

-
-
[8]:
-
-
-
-t0 = datetime.now()
-output = biau.label.match_labels(imageA_labelled, imageB_labelled)
-t1 = datetime.now()
-print(f'Took {(t1-t0).seconds*1000} ms')
-
-
-
-
-
-
-
-
-Took 0 ms
-
-
-

Visualize

-
-
[9]:
-
-
-
-fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
-axes[0].imshow(imageA_labelled)
-axes[0].set_title('Reference image')
-axes[1].imshow(output)
-axes[1].set_title('Relabelled image')
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[9]:
-
-
-
-
-Text(0.5, 1.0, 'Relabelled image')
-
-
-
-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/notebooks/label/match_labels.ipynb b/doc/_build/html/_include/notebooks/label/match_labels.ipynb deleted file mode 100644 index 181425a..0000000 --- a/doc/_build/html/_include/notebooks/label/match_labels.ipynb +++ /dev/null @@ -1,3198 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "e5db44ea", - "metadata": {}, - "source": [ - "## Matching labels\n", - "This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "d1ca8e7a", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import biapol_utilities as biau\n", - "from skimage import io, measure, filters\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from datetime import datetime\n", - "\n", - "%matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "id": "ee62539b", - "metadata": {}, - "source": [ - "### Load data\n", - "First, we load the example blobs image and threshold it to create a label map. " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "7fe70350", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biau.data.blobs()" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "909ce3b2", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "threshold = 128\n", - "imageA = (blobs > threshold).astype(np.uint8)\n", - "imageA_labelled = measure.label(imageA)\n", - "\n", - "plt.imshow(imageA_labelled)" - ] - }, - { - "cell_type": "markdown", - "id": "1cbf5ae3", - "metadata": {}, - "source": [ - "Let's create a second version of this image in which we shuffle the labels:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "29986d79", - "metadata": {}, - "outputs": [], - "source": [ - "label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)\n", - "np.random.shuffle(label_shuffle)\n", - "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", - "\n", - "imageB_labelled = label_shuffle[imageA_labelled]" - ] - }, - { - "cell_type": "markdown", - "id": "1393dfb7", - "metadata": {}, - "source": [ - "Both images are not identical!" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "1ff3c80c", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of labels in imageA: 63\n", - "Number of labels in imageB: 63\n" - ] - } - ], - "source": [ - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "axes[0].imshow(imageA_labelled)\n", - "axes[0].set_title('Reference image')\n", - "axes[1].imshow(imageB_labelled)\n", - "axes[1].set_title('Shuffled image')\n", - "\n", - "print(f'Number of labels in imageA: {imageA_labelled.max()}')\n", - "print(f'Number of labels in imageB: {imageB_labelled.max()}')" - ] - }, - { - "cell_type": "markdown", - "id": "7a38be04", - "metadata": {}, - "source": [ - "Match labels and track time" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "79f0cf74", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Took 0 ms\n" - ] - } - ], - "source": [ - "t0 = datetime.now()\n", - "output = biau.label.match_labels(imageA_labelled, imageB_labelled)\n", - "t1 = datetime.now()\n", - "print(f'Took {(t1-t0).seconds*1000} ms')" - ] - }, - { - "cell_type": "markdown", - "id": "a8710824", - "metadata": {}, - "source": [ - "Visualize" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "84ed2639", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Relabelled image')" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "axes[0].imshow(imageA_labelled)\n", - "axes[0].set_title('Reference image')\n", - "axes[1].imshow(output)\n", - "axes[1].set_title('Relabelled image')" - ] - } - ], - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_include/notebooks/label/visualize_labels.html b/doc/_build/html/_include/notebooks/label/visualize_labels.html deleted file mode 100644 index 4897c53..0000000 --- a/doc/_build/html/_include/notebooks/label/visualize_labels.html +++ /dev/null @@ -1,411 +0,0 @@ - - - - - - - - - Labels visualized in colours — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- - - -
-
[1]:
-
-
-
-import biapol_utilities as biao
-from skimage.measure import label
-from skimage.io import imshow
-
-
-
-
-
[2]:
-
-
-
-blobs = biao.blobs()
-labels = label(blobs > 128)
-
-
-
-
-

Labels visualized in colours

-

biapol_utilities provided a standardized color map for visualizing labels in:

-
-
[4]:
-
-
-
-imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())
-
-
-
-
-
[4]:
-
-
-
-
-<matplotlib.image.AxesImage at 0x17fe4272220>
-
-
-
-
-
-
-../../../_images/_include_notebooks_label_visualize_labels_3_1.png -
-
-
-
[ ]:
-
-
-
-
-
-
-
-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/_include/notebooks/label/visualize_labels.ipynb b/doc/_build/html/_include/notebooks/label/visualize_labels.ipynb deleted file mode 100644 index 9924ff8..0000000 --- a/doc/_build/html/_include/notebooks/label/visualize_labels.ipynb +++ /dev/null @@ -1,98 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "803a884d", - "metadata": {}, - "outputs": [], - "source": [ - "import biapol_utilities as biao\n", - "from skimage.measure import label\n", - "from skimage.io import imshow" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "af876b71", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biao.blobs()\n", - "labels = label(blobs > 128)" - ] - }, - { - "cell_type": "markdown", - "id": "d9ded05a", - "metadata": {}, - "source": [ - "# Labels visualized in colours\n", - "`biapol_utilities` provided a standardized color map for visualizing labels in:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "5c3f2337", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAUMAAAEYCAYAAADGepQzAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAz/ElEQVR4nO2debxVVb3Avz/mebzIrKBJgjikpg2Wpi9NKtEysl6GiuErMXuailZqpj2HxHBII8RZ0Rye2HOozCGzTHAWFQFBuQIXFGSe1/vjnAP7nnvO2Wvvvdaezvp+PvfDPXuvtfYPj379rXGLUgqHw+God1olHYDD4XCkASdDh8PhwMnQ4XA4ACdDh8PhAJwMHQ6HA3AydDgcDsCiDEXkKyLytojMFZGJtp7jcDgcJhAb6wxFpDUwB/gysAh4AfiOUmq28Yc5HA6HAWxlhgcCc5VS85VSm4DpwGhLz3I4HI7ItLHU7kDgfc/nRcBB3gIiMh4YX/y4v4mH9uyya6T6K9bMjxzDJ3baLXIb5cxtmme8zRL7yDAr7b6i5lhpt8SeXfoba+uNNYuNtZVnBo8YGKre+7Mblyul+pQ+77d3J7VqzTbt+vPe3fi4UuoroR4eAFsy9EUpNQWYAiAiRvrqR+7/60j1pz99fOQY5jbN45H/fihyO15GXW0nqV7e7kkr7QI0bPqStbbfOORCo+3t+fQvjbaXV86958eh6k3Y69yF3s/rmwZw1wm/0a5/0G+ObQj14IDYkmEjMNjzeVDxmjWOP2R6pPomROhw5JXrXrvcWFvv9lnOCadO1a+g781I2JLhC8DuIjKUggSPB75r6VmRcSI0z/J2T1rJDk1nhQ5/TIoQoOfKjXxjhv6Q1GVGn14dKzJUSm0RkQnA40BrYJpS6g0bz4LwWWEWJGiri+zYwRuHXOi6yjGyfHEfpl5yWoAaE6zF4sXamKFS6hHgEVvtl0ijCEddPdrIuKFNEdocL3Q4ajLyA+TPP9Mv39deKF4Sm0BJkixkhFnH5gSKDZLMDo/c7UIen1c/mWnDxyMZ98jftMtfSm+L0ewg0zKMOmlik6jZoese55sjd7uw4ud6kGLHppUMv+H+pMNoQWZlmGYRRiUOETZs+pLrKidAuQSr3c+zFNfyIbO23Gm0TRHpAUwFRgIKOBl4G7gHGAIsAMYopVZUayOzMgxLnF3koNlhnNmgE2Fz4ugi+4mwUtmkpWh6JhlgVYcePLbn0foVXnxap9Rk4DGl1HEi0g7oBJwPPKGUuqx4PsJE4NxqDWRShlnKCkuCqyVF1yXOP0FEWF4vaSGapudOqzluwlPa5X91e+37ItId+CJwIkBxC/AmERkNHFosdivwFHmTYRapN+HZWmeYRcKK0Fs/T0Lc1rENG4f3MtnkUGAZcLOI7APMAs4A+iqlSnstl+AzL+1k6MgUez79S7cdLyZsdJEB1qo+PLftRwFq3NogIjM9F6YUt/OWaAPsB5yulHpeRCZT6BJvRyml/Lb9Zk6GUbrIbkmNw5E86996n9c/999BqixXSh1Q4/4iYJFS6vni5/soyHCpiPRXSi0Wkf5AU62HZE6Gjui4yZP4iNpFTpIJe51rJTvs0aorX++iP4RyC8/VvK+UWiIi74vIJ5VSbwOHA7OLP2Mp7OgbC9SczXQydGQOk11l10WOn9btO9F1yL76Ff6tVep04M7iTPJ84CQK57XeKyLjgIXAmFoNOBnWIXGsMYw6eTLk4h27DhZc8GGL+yaEmBURBpk8+fX4zi2unT9lrclwIiMDt9HxsjX6Fe71L6KUehmo1JU+XPcxdSNDE+OFHV5o+S/Vhk+3/JfPER6vBL3XKgkxClkRoS6VJOi9F1aINrrK7RcuZMip4/0LxkzdyDAslQRY6X7WpJjGHSiVROi9Z0qI9SRCb5m0ZIiNW/bk/CUPBKhh5zT2clIhwy677saa+faOtg+bFfqJ0FGZMF3kWiKsRpiuctwifHzeLyNNovh1kXVEmDaGt9rCjK4rtctHe5mHPqmQYRoJKsIOL6x12WECBBFiEBE+fHTLJVxfn+GWZplgo5rHnA3HJB1GC1Ijw0On389Tx38z6TAcEUli14lXcuViDJoJVpJgrXs6ggybHeZp14mX9e168uYuAf5bf/Fae8F4SI0MbRGmixy2e+yyw+SJ0g2uJUK/OqazRh0RZrGLDLB08zquWvJS0mG0IPcydPhjSog2s0LTs8nlhBFhEIJkh3kWIUD3QcM48sq/aJe/6eCOFqPZQeZkOP3p47W35Lntd/pEFWJUES644MNQkyhp4eGjp/tmh35CtN0tDjujbHp5zcb1S3n39WuMtWeKVMlQd9wwiBDzwjtnzKh6b/fJAc6Gq0FYIdoeJ8xKVqgrxCSJa4nNhL2qnpTFluXr+fAPr1mPISipkqFJ8pAV1hKgLcrFVkuOpiVoW3qVMN091hFiVJLoIutmh7UkWKLn4I18c/I72s9+5WDtopHIrAyrZYcmJLjh051DTaKYmjwJKsF3zphhLDssx51J6ChREl0lKepIsEQXtvLFrauMxWWKVMkw6NIarxBdJugIiu1Jk7wSRHyVaDevNQPHdDcUjTlSJcMwpEWCUbPCqCK0mR06gmG7q3z+lLWZnk1e13UbLx+yXr+CxkENJkiNDNO24DpsVzkMpjJCJ0RHFljWfT03jnpVv0K9yTDLZG2htcN1kZNkaNch3H6Y/qz6AMZajGYHqZChzUMaohBHdujGCR1xkoaTa179aC2D7n7ev2DMpEKGacZPiFGyQhsidF1lR9rp2LMbnzj2SO3yr537O4vR7MDJUAOv8NJ+fqETYfLEcbpNmEmUNGSFAF3nKA7/8mbt8nEtz3YyDEhSawkdjnKCCDEtIgT4uF8bHjmvQb/Cf9mLxYuToaMu+fqM461MosR95qGOENMkQoB+W5cyccVV2uVPthiLFydDhyPjlGTnlWLaBOjlw6aN3HL9u0mH0YJMyPCAEbL995mzVYKRmMF1kdOB6eww6ZOwwwrwHwtbVb33+V22hQ2nOju3RV3VT7/8Ma+bj6ECqZahV4Lea3kQoiMd2OouZ4FaEvSWMS3EnVZt5PTH9JfT/d3o06sjSiUvFhFpEUQlEZbIsgzjyArdjHJwogox6awwKDoiLGFAhrOUUtvfadxl//3UyOee0a78fIeuzerbIpWZYS0Rlu5nWYgOfw6+9zstrj075m5rz4uSIeZZhDbYShOrWl2XaAyVSKUM84obK/SnkgS992wKMQymRHjl/OZzpmfvOs1Iu+WEEaHprnLXl4TDO7fTLv+msSfXpq5k2P7sk5p93njlzQlF4iinlgTjIu7xw3IBlt+zJcSk2Vka+G2Hk/wLFrlu81kWo9lB6mTo10UOSrkAK91zUkyOoBK0nR0GEWKUrLCWCPPOnB6bOWLUMv0Kd9iLxUvqZGiSWiKsVM6mFF0X2RxxCLFEuRhNdIuTEmHSY4UlNuy0kXd+NFe/QhZkKCILgNXAVmCLUuoAEekF3AMMARYAY5RSK3TbnDlb+WaHfpMnuhKsVS+L2WKWZpGjdovjGj80PTmSZEb4+V22pUKIO7+9kUmH678DZbTFWLyYyAy/pJRa7vk8EXhCKXWZiEwsfo52TngCtD/7JKNC3H3y0VazwyyJ0BRpnFBx+LOsR3euP2KUfoV7fuJbxERiZqObPBo4tPj7rcBTBJRhKfOrlCHaygqrtZWFDLEeRVgiz0K0MYmShuyw54olHHef/t7kP+s3HSkxiypDBfy5uGj690qpKUBfpdTi4v0lQN9KFUVkPDC+VuNuLaE/9SzCrJHVSRPTO1Aa6MYp2/Tfujie34d9VKDELKoMD1ZKNYrITsBfROQt702llKq0u6R4bwowBSrvQAmDyazQ26ap7NB0V9mJ0BGGktySyhBXDOrJA2ccp1/hbK1SoROzEpFkqJRqLP7ZJCIPAgcCS0Wkv1JqsYj0B5qiPCNvmBKiE+EO8txVziPvdZvHhCO/rV/hbBpEZKbnypSi7LyETsxKhJahiHQGWimlVhd/PwK4GJgBjAUuK/75UNhnBMFGVmiLksjCSNFJsH7I66LrnssGcMzvf6Fd/kbuX+63N9lEYhYlM+wLPCgipXbuUko9JiIvAPeKyDhgITAmwjNyTVApOhFmlzSOF/pNplg5vgvo/WEj37/t59rlb/S5byoxCy1DpdR8YJ8K1z8EDg/bbj3iJ0UnQYctKo0f2pLgdnYaSOuTf61f/td/8ithJDHLxQ6ULHWRa+Gkl0/CZIVxd5GtC9DDx+0388gnlhhrz1RilgsZOuqbNE+eZEGEcbOsm/C7LyW/E6YcJ0MfsrDo2pFO0jhOmAaGrOjMpPs+o10+rv6Sk6GDWX2/3uzz/ksfTiiS/BC3CJ8+YwSHTJ4d6zPD0kotoevmy5IOowVOhnVMuQQrXXdijJcgXeSnzxhR8XPapdjERq5rvSDpMFrgZFiDPHeRq4mwWjnTUnx2zN1GDnRN43ih7aywXIKV7qdZiOtWduCFGcOTDqMFToZ1iK4IbWNKiHlBJyv0E6G3nG0h3tH5cxWvf2/tczXrbVu7mk3PP2UhomjkQoYbr7w5N8trbBNWhLP6fj11XeY0ZoU20RWhbapJ0Hu/lhBb9V1Np7FP6j/wCv2iUciFDG2Q5y5ymigJLWiGmFYRpmkG2WR26CfASuWrCbFhTXdO/Mch2m1dQDynxOdGhi479Cct3eNKBJGiDRH+9Jq/tbj2mx8fZvw51fDrIofNCk0IMagIy+uVS7Frv80cds7iSlUqckFMR13nRoYmyWNWmGYRevGKLo53J1eSoPdeECGmKSs0RVgR1mLLxn40zTknQI1vGY+hErmSYUliUTLEPIrQBEmMF9ruCtcSobdMnBlimrAhQgBp3YZ2PXpaaTsKuZJhFPIsQRNZYRonUOKiHoVoS4QATes78rtXW2wlTpxcyjBIhphnCUJ2usdxo5MVlpf3E+LZu05ze5E16NLwOp85ZQ/t8o9cazEYD7mUYYm8i86RPsIK0RZhJk9sZoUA6+a34+XvDAhQ40NrsXjJtQwdjiQIIsR6ywoBemwdyNErLtcu/wABXisaASfDmBnx0RDfMrN7LbAehyMYQccMdYRYjyIE6LFbK465uZ1+hc/ai8WLk2EM6AiwvLwTYvapJcR6FSHAu6znBNK3d9rJ0DJBRZhHjrq5MAb16Em196z61Y/SRlIkKb20HtbQ491eHH3id7XLP8yPLUazAydDi0QRYdqywzDLarwS837WEVp5Xe/1uIWY9LKatOxJNsVm5rF46zFJh9GCupfhyWMerHh92r3HRmrXREaYNiHqUk1kle6Xi82vbtwkLUIoZHhBhRglK/ze2ueMzChX25u8ZecGll0zTr+ho56NHIsOdSnDagIsLxNViCbImhCDyiyM/JLIDrNEWrvHJT7qtoS7j4zpKJoAiFI1XzIfTxA+b7o3iY4IvYQRoo1xwrBCNLHoWreLHHdWZ1KIpUXYacgEa1EtQ7QhwLDZYYWMcJb3JfA99txNfeEe/VeF/mmv42f5vUTeBHWVGQYVYalOGjLEpKiXLXhpl2CJOLM+U93lcjYt6sR75+5vvN2opEqGL95UeyHmfuPOjSmS5gQRYr3OHqdtrM9hhqBC9DvlGmDDgEbeuuAX+kE8ol80CqmQ4fBdBnLnBf7T5y/edHliQswq+y99OHRXOc1ZoRszjI9qgiuXpI4IAbos6s6BPz1S+/lPMF27bBRSIcMgOCEGJ4wQ0yxCRzrQlV85Qzos5Obh/6Vdfud4JpOzJ0NItxBn91pgvKtsYja5JDcdKaZdhC4rzDbz2vbkuP5B9hvfYS0WL5mUIQQXYpjJkzziFV0W34/sROjPpKn+h+KeeUpybyXs1Lcfe52pf9L1vy92MvQlzRliFki7AJ34gqMjwlK5pIQ4aNkSJv1Of53hTRZj8ZJpGaYVG13leiJOCV7Tdcd/lD9eXTtb8ZbVrRMnuiL0lk9CiCu29uWej88IUMNlhlq47DAdPHrSc5GX18QlwUpSK79eLjmdOl7SJMlaJCHEzb1WsOy79+lX0Dj6UERaAzOBRqXU10RkKDAd6A3MAk5QSm2q1UbmZZhWXHYYjKRFGLZcrfpZEWLcNHywmrEX/V27/M/0ip0BvAl0K36+HLhaKTVdRG4ExgE31GqglXZEGSfKLpIkd6BkaV9yWKGlTYRZfF7QLrKpumEQ6U3bNmO1f/zbk0HAV4Gpxc8CHAaU0s9bgWP82qmrzHDavcfGsje5RElkLkOsTl5F6H2u7QwxbplFZVEf4ZwftdWv8EffEr8FzgG6Fj/3BlYqpbaUHgkM9GukrmSYFGG7zFnKCksEGTt0s8X1SbumHgy5dnSQKg0iMtPzeYpSagqAiHwNaFJKzRKRQ6PEVXcyDJIdmuweBxViFkVYoiS5WlKsJxHazA6zlhUCyNBXaHdHb/0KnVhe49SazwNHi8gooAOFMcPJQA8RaVPMDgcBjX6PyYUMg84ol0uuXI5ujNAM9SQ8R0se+KDwP4BvDGg+RNHxw70ZedufA7TUr+odpdR5wHkAxczwp0qp/xSRPwLHUZhRHgs85PeUXMgwKnHJL0+iczgqURJgLRpbb2Ji9/m2QzkXmC4ilwAvobF221eGIjINKPXLRxav9QLuAYYAC4AxSqkVxVmcycAoYB1wolLqxVB/FYfDkSl0RAjQccFC9jn5R9rtvqlZTin1FPBU8ff5wIHaD0EvM7wFuA64zXNtIvCEUuoyEZlY/HwucBSwe/HnIArreg4KElBY3OJrhyMcJhZd64oQoEefnoz+tn5vbPq1L4eIKDi+MlRKPSMiQ8oujwYOLf5+KwUbn1u8fpsqvEvgXyLSQ0T6K6UWG4vY4XBs58xTvpP4JEoQEQJ0aNrEsBvesxRNeMKOGfb1CG4J0Lf4+0DgfU+50vqeFjIUkfHAeIB+vXuEDMPh8CepNYZZIGpWGFSEAFtar2F5lwCTaysDPyIUkSdQlFIqzAudiuuEpgCMGDIo+bdSORwZJWx2mIQIAdYNa8+s23bXr/Bp3VHDaISV4dJS91dE+gNNxeuNwGBPOa31PY5keeupyls29zj0hzFHYocfrz7HZYdlJHmeYd9NAznzvUu0y5/PDIvR7CCsDGdQWLtzGc3X8MwAJojIdAoTJx/HNV7oJk+CU02C5ffzIsU8EyQ7TFKEALNbz+FTvY5INIZK6CytuZvCZEmDiCwCLqQgwXtFZBywEBhTLP4IhWU1cyksrTnJQsyOiPhJsFb5rIqxHrLDkuSqSdGkBMN2kQH2WDeUp2Zep12+B/ovj4qCzmxytX+Ch1coq4DTogblsEdQEVaq74QY/LlxknTm54es2EibB6wvug5MLnaguC5yvGRdiF7K5VgPGWTSvLytDQ1rG5IOowWZl6EToT5Rs8LytrIqRC+VsjaTQszrAa/fGHBF6K5yh0+24xNPDtIu/1rPUI8JTOZlaItNL07d/nu7/U5JMBJHEpQk5rJE82xZt5aVs2YlHUYLnAyLeOVX615WxWgyK/S2mYfssBZRssS8ZoVRUUs3sWlyfnagJI7J7nEtEVYrm1UpponGlSdWvTewxy2xxeFHmCzRibA6ezX04NlTvu5fsEjnh+PJzlMhwzcXNrLfuHN58abar8FKSoDV6qdBiKdOOn37778/89oEI9GjlgDLy6VJiKCfJdaLCMOOG65t18Q/B0y2EFE0UiHDEiXZlUvRTZLkA10RpplaWWK9SNBLGCGu2LCJ/30rfRvTUiXDErblFzUrTCunTjo9tdlh0iLc55UdC3df2efxyO3Vo/iq4T3JWkeMa5a34elbetkMKRRSWCedcBAhDnoIi0kRBu0mD+v0eotrc9aNNBWOLzYmUXQmUKKIMEpX2SvASpiQYpqY02FhoPLDNuxiKZIWzPK+w2Tvnr3UjENb7NmoytD/vW9WjXegGCOVmWEeqSRC7/U4pWiKOGaSw44d+onQWybrUgwqQW+9GIW4nSWbe3Ll4m8HqHGffxED1FVmaKN7rJMdVhOhl7hkaCo7DCLCqF3koDLUEWE5WRZiWBmWiEGIzTK7fYa1VY9f10O7cv8jl7vM0CRJjRPqiNBbzrYU9zj0h5GFmGYRhmWfV47MpBCjitDbRlxZ4tI1wtV/7xDLs4JQNzJ07CCKENO+yDpMVphVTIiwUnu2pdip1Uj27vxMgBpdrcXixckwZQzr9HosXeaS1HSlmHYJQn2J0Ca2xxKlw1za7HGMtfbD4mRoEd0ucpKkXXJpXHydBkxnhZXatyXExq1wwcpWVtqOgpOhw+GIlT4fDOUHF9+uXf5s+lmMZgd1IcO8LrJ2mCUrkyi2s0Lvc8Jkh289cRZ7HH5V1fvdB85n1K+P127v7JjOqq0LGTqyi+siZ4u3njir2Z9ACzG2+mgInadPCdDqMBOh+eJk6HA4qmJj7PDjXTbw6I1z9Ss85F/EBE6GEUjDqTUOs2Slq5xGvNlgLZZLI39ofZ7laIJTNztQ0rz7xEsWt+XVIu59yaaW16RZiHGNGZYIkhlW6R4320GyV4ed1IxBY9Bl13nXux0oeWDOupGZWGKTF17Z53EjQjR9yk29UGvipMScnftz2LUBMsOvXB8hIn3qRobt9jsl9bPKecsKo5CmiZO8HOiQFtqvWsnQP+sPBC7wuS8iHYBngPYUnHafUupCERkKTAd6A7OAE5RSm6q1k1oZXnFkuxbXznm86t8j1fhlh3mVYNguclQRmsoOy3FSNEN/1Z0Ltukf+/+k/6vYNwKHKaXWiEhb4FkReRQ4E7haKTVdRG4ExgFVt1ylUoaVROi9HlaKJrPDoJMnXuHFteUuSZISYQlbQqw3bOxCkVUf0eYv0421pwoTH2uKH9sWfxRwGPDd4vVbgYvIkgyribC8TBQhQrILsfMswqQOcq2EzQzRZYfhaTu0I/1u20O/wv7+RUSkNYWu8CeA64F5wEql1JZikUXAwFptpEqGOiIsL5tEluiW1FQm6WywEnnMEIdt2CX2GWWTvLNkLaOufDFIlQYRmen5PEUp1WzVtlJqK7CviPQAHgQC2LZAamQYRISmCJMlOhFWJul3nDjMY+ughsG9lvLbb12pXf6r01muu7RGKbVSRJ4EPgv0EJE2xexwEFDzLVSpkOHAbpLo83WyRCfB6qSpa1wJlx2Ga98WC5fAqZPMnVojIn2AzUURdgS+DFwOPAkcR2FGeSw+e1lSIcM0UEuIToTVqdeMMM/jhrYPd+09uAPfm6S/3/iyg2b5FekP3FocN2wF3KuU+pOIzAami8glwEvATbUacTL0UC7EPEjwl//6uOq9Cz/TPVLbWRKhyw7124zKSwOan2L9qQ++2Oxz09w9uO6r/wjQYu1XBCilXgU+VeH6fOBA3ac4GZaRhAA7bti5xbX1Hd6L1GYtCXrLRBViFNK0sDqrmBJiVAmWC7AW/Tpt5Yf7r9Uu/4uYEnAnw4SoJMBK98NIUUeE3rJhhJilrDDvRBVinCIEYHUj6plzIz3TBk6GCeAnwvKyQYQYRITeOklmiHGRx65yCV2heaVpo0usRZ+PaH38Xfrlrwn+iDA4GcZMEBEGJYwIHfWFycmRUCIEti0fzrppfwxQY0So5wTFyTADBM0OwxB3dpj18cK8ziTrElaEAAO3refida9ql7809JOC4WQYI2GzQh0RmsgKgwhxYI9bMjlumOeuclxEESHAu8OXcMLtk/QrWD/JsECmZZjVU2yCEkdmGCcuK8wuUUUI8PHK9jz2v0G66/+O/EwdUiHDxlXBD7quFxE6zBMlO3QijM7OTf245Hr92eT/JMj4Ynh8ZSgi04CvAU1KqZHFaxcBPwCWFYudr5R6pHjvPArnhm0FfqyUMv5vTxZFmIWJk6BjhmG6ymnJCoMKsZ4lCOZECLCg5wrGHXOffoWYDpjSyQxvAa4Dbiu7frVS6jfeCyIyAjge2BMYAPxVRIYVT5SoyTmPb9I6rCGLIswzukJMiwS9lARXS4r1LkEwK0KAnquEr/5Fv1Oq/7r5aPhGpJR6RkSGaLY3GpiulNoIvCsicylsh/mnTmU/IdarCNM+XugnxDSK0Eu5FE0KsOf1zQ9KWXFazSP16oKGLpsZ94Vl/gWL3B7TaWVRxgwniMj3gZnAWUqpFRQOT/yXp4zvgYrl5FV46zu8Z7WrnDRpF54OpiRYLsDye1kSoumsEGD5gAFMvfBC/Qp3/N54DJUIK8MbgF9ROFr7V8BVwMlBGhCR8cD4kM93OFJHLQlmERsiBFjZbjUPDHraSttRCCVDpdTS0u8i8gfgT8WPjcBgT9GqByoWT6qdUmwj+Zc3x0CY7DDtXeS4mLFH4dWSR7/1PwlHEp0sZIe2RAgw7IO23PzLnbTLf9ZaJM0JJUMR6a+UWlz8eCxQevXbDOAuEZlEYQJld+JaJJQR8t5djkpJen730ybFPGWFNkUI8P7ALZx1yYf6FS6zF4sXnaU1dwOHUngPwSLgQuBQEdmXQjd5AXAqgFLqDRG5F5gNbAFO05lJrjd0hVhPWaGfBCuVT5sQ84BtEQJ0nLWGEe31zzN8zmIsXnRmk79T4XLVE2OVUpcS33bCzOInxLhFmOSpNUFF6Mg23dqu4Ig+92uXn/qBxWA8pGIHSr1SEl6UswuzThQRuuwwm7zfqRVn7t9Zv4KToR43vFp52v2He58acyThqUcJQn4ywryMF8bRRQbo3W84/znxb9rlL3+4l8VodpBZGVaTYPn9LEkxKZLoIudFhGEwMZO881nVBfzeVemeqe72zgaOOOot7fKXW4zFS+Zk6CdBR/qpZxGaoJYIS/fDCPFTH3wxluxwY4+lLBx1tX6FO+zF4iVzMgzKDa/+3lh2+LfWK5p9PmxrTyPtRiFrp1s7EYbHT4LlZZPOEMvfildi48eKtx9N3yKTTMkwiaywXIDl99IgxKyQVxGuOG2g9rhh2C5yEBF66yQhxGoSLNG+M3zy0wH2WTwWMSBNMiPDKCIMmx3WEqG3TFJCzFpWmGeCCDHP+IkQQA0YyoaL7tRv9LFOESLSJzMyjBsdEXrLxi1EkyKsl7fj2aaWENO+/a5ElHFDHRECdJm/kYPHzAv1DJtkQoYmusdBssMgIvTWcV3m6uS1i1xOuRBtzxynBV0RAqzouJgH9vqVfuMxrTzLhAzjJIwIHf4c/db/1JUQs0zQ7DCICAH69d3GWWeu0y5/0f8Faj40qZdhlpbSuOwwXtzuE3t4BVdJjEEF6GVjh57MGzEmQI0/+RcxQOpl6GiJmzhJhrEvT655/9Z9z4gpkniJIr5KvLewPT85ZYjRNk3gZOjBRBc5i9lhFidP4swK/SRYXi4tUkx6nWE1hq5Zw63/0j+1JshLRaOQahlmqYscFy4rTKcIy+ukRYhppHH4Mn4+Y4p+hV3txeIl1TJ0OMpJuwi9dU0J8b2rBmZiRlmXzY1dWHzu5wLUeLfmXREZTOHtnX0pnLE6RSk1WUR6AfcAQyicuzqm+K6mijgZZggbWWGcXeSoM8pZEaG3DZchtqTPx50Y/3/7apf/K74LtLdQeCndiyLSFZglIn8BTgSeUEpdJiITgYlA1bfX140MddYYHra1p1takzKSmDE2IUJvW06IzemwRxuG39ugX2Fk7dvFV5AsLv6+WkTepPBWztEUTukHuBV4CidDR9Zwy2aikdbJE4CVjYoHzw10UEODiMz0fJ5SfKFcC4rveP8U8DzQ1/OupiUUutFVqQsZ5uFMw6x3kUukXXIms0Jvm1Gzw0pyKx9HDCPABxv/6Fvm2IHfCtxuLTrKFvbp8FGQKsuVUgf4FRKRLsD9wE+UUqtEZPs9pZTyewtn7mWYBxE6so+N7nKU7E9Hgt6yJoW4pk03/tHwH8baAxCRthREeKdS6oHi5aWlN3mKSH+gqVYbqZbhD/c+NdLymiREaGuN4YWf6e6W1VjGRlaYRoKI0FvHlBB79d3K8WfoZ4ZX+ChACingTcCbSqlJnlszgLEUXjY6FnioVjupliGEF2JYEbpJFEeeCSNC08yfs4FvHfGOySY/D5wAvCYiLxevnU9BgveKyDhgIVBzD2DqZQjBhZhU19j2zhOT2WEWd504ohFVhKayw97923HSRP/3hpf4+Y9q31dKPQtIlduH6z4nEzKEyoIrF6QpCeY9O3QirD/SkBGWaNV9NZ2+9qR+BR8ZmiIzMqxEmiZH4tqPHDU7dCJ0JI3a2sDGVacEqPEba7F4ybQMbRIkO8zKwQxOhMmS1AJsk1mhia7yyi3v8XDTBEMRmcPJsAY6QkxChGGyQydCf27d94y6mVFOkt4ruvC9Bz6rXf45/moxmh04GfqQlazPkQ3c9jxoGtCK6y/orF/hOnuxeHEyzCi62WFaM8LbVz/f4toJXQ9KIBJH3PRd1pefTDlTu/wPmGgxmh04GWYYr+jS/Ia7SuLzK5eEGF0XOR6WNc3lxmtHJx1GC5wMc0IaRagrQb+6ecoY672LDNBOtWXnDTtpl59lMRYvToYO40SRYLX28iTELGNkS97w1vBQL/3yu0V/pA5Oho5MkAchuqywwOA1nfjts3trl3/QYixeRKmap9rEE4TP0TqO7GA6KyzHthBtjhsmKUMTaw0jZIWzvEdwdWnbT+3be6x25X8svWKWzhFeUXGZocMRAy4r3MFO3T/kh0fepl3+H/pFI+Fk6DCG7awwDmwsvE6DCI8d+K1I2aHJ8ww/3NiNOxd+OUCN2409uxZOhg4j5EGEJdxOlOaEFeGVh68C4OwnujW7vkvX9tz4xaHa7ezydKjHB8bJ0OGogCkhpiErLFGSmm6GGCUbLImwEhuXLmbe1b8K3bYtnAwdjip4RVZJjJVEVypnUoIzTxvMAde/b6y9alI0/a6TaizvthdTD39Ev8L9g+0F48HJ0OHQQFdupiVY/rsNKZqmVlYI0KPVOkZ3fEG7vbuiBqSJrwyDvq2++D6CycAoYB1wolLqRTvhOxz5xCvCStdNSjFuFvRawEnfHqdf4Q57sXjRyQyDvq3+KGD34s9BwA3FPx0OhwbVRJgF/LJCgM4bO/LpeXtqt/k3no0Skja+MgzxtvrRwG2qsJr7XyLSo/S6PvPhV+aSa5v/g/756W/E9ejM0umbz7Hu/s8lHUbdoytC0+OIcbK6zWae7LM06TBaEGjMUPNt9QMB77e0qHitmQxFZDwwPnjI1SmXYPl1J8XmdPrmc1U/BxXjCV0PytXyGoc9ujeN4NDf6a+XeYhu/oUMoC3DqG+rL0cpNQWYUmw7lu14l1y7pxMiLSVYrYzLFB022HXDQm5/44fa5eNRoaYMA76tvhHw5vqDitesUi0rrFSuHoWoI8BqdXSl6LLD+MhqFxlgcceduHzf0/UrPHWnvWA86MwmB31b/QxggohMpzBx8nGc44U6JCnEL0w7Z/vvfz/5ikRiCEpQKTrCkeWJkyB069uZw8/QP3fh0qfsxeJFJzMM+rb6Rygsq5lLYWnNSSYDroRuVpgEXvlVu2dbimGywmrt+AnRZnaY9SO8HAVaL5xN91M/nXQYLdCZTQ70tvriLPJpEeOyju3ssJYEK5W1JURTIvS25zJERzXOfqKb7/KaTX0aeO8HJ+o3evFL0YLSJBfnGUbJDE0LMYgEK2FaiqZlWEJHiCYzxHrJCnW7ymkfM/QK8ewnujU7j1AaOqo2Xx+i3daWW95y5xnWIya7zrZEWGo7ri5zvYhQl7SLEFqeVOPlkx+2Z8od+mf5H8JbJkLyJRcy/Pnpb4TODk12l6NmhXmkJLIwUqxHCR5w/fs1s8MsiNCPzp9sxUE3ddGvcLC9WLzkQoZpwLQIbY4jmiLI+GElsZULsh7lV4lKQsyDBEusWzKIly+/MkCNe6zF4iUXY4YQfUY5anZoKyuMIkSb3WQvbkLFDnk4lKFIszG/Nnt1Ud0f2ke78ke7PVdzzFBEpgFfA5qUUiOL1yoeJFPrObnJDKN0lR2ONJIDCVZkyEdtmHRXH+3yGq+bvwW4jsLpWiUmUvkgmarkRoZRqMcdKQ5HUizpNJTL9r8lQI2eNe8qpZ4pnpvgpdpBMlVJhwyH74zceT4Aar//SjiYdBFl7HDd/Z+Lpavs1h7mh9YHv8rWAO80DkPPdkv5xmD9Vyr8ExpEZKbn0pTi2Qa1qHaQTFXSIUMP8uKNQHApui5yZeISoiObtD74Vd9rpuXYtLgz1196YJAqy6OsM9Q9SCZ1MiwhL94YS5bousiOeqWSCGuVMyXFPXaax2Ona4wEFhkwPdRjqh0kU5XUyhDiEWI9HATrskN9Tnn9lKr3po6cGmMk9tCVYKV6JoT49tttOPRg316rh0VhHlPtIJmqpFqGSRB2EfbfT76irhddZ33csJYEq5XJohzDitAkAwcoLv3RBu3y3/p57fsicjeFyZIGEVkEXEj1g2SqknoZ6maHbmlNbWxnh3kXoU69tMvRhAhNZIcL1w3jBy8F6fvWfp5S6jtVbrU4SKYWqZchxDd+mHdcd7klYUUYpa0kpGkyI4wqxD0GdOC+i4Zplx9+f+hHBSITMtTFZYf+OCHuwKQIgz43TiGmoWvsZdGSt5h4Wfp6ErmSoUMP00LMYhc5KRF6nx+HEG2JMEp2uLXbYD7+8jX6Fe6M56SGzMgwC2OHNiZR0n5Ygy1mntB6++8H3L41wUjsURJy2scaqxFWiGs+6szT0wOtM4yFzMgwCFGEGHVpTVZmlU1lhyazQq8AK113UgxG2rrHJdq3eYldGvSP8JpjMRYvuZRhFEycb1gvQoxDhOVl8ipEiH8sMSm2rP8ky9+4OUCNz1qLxYuTYZ0TVohxi9AkSY8X5okwXeUOuy5i97vO1i7//PCgUYUjUzKMY4mNqR0oJrLDuMYLgwoxSRHmPTusB/rP6c2Fh39fu/wonrUYzQ4yJcMghBk3zONWPF28gqslxjTMHDshZpvlI2HqMwEqdLUWSjMyJUObWaENEUbJDpOcRU6D8Bz5ZdCiRfzmPP3/Lh6wGIuXTMkwKLrZoc2MMIwQ63U5jaM+mL++Pd96VX8HCvzbWixeci1DaC66pE6oCSJEJ0I9onSVp46cmspJlHqYSQaQbRtouy59Q1KZkaGJLrIJ+V0/4e8trp123Rd865VLzuT7kR3BSasQ64HdNw3hsff+R7t8D75tMZodZEKGaTmkoZIIS9d1hOjFSdBhm63P7m194XWYHShqaGc2XxNgXPqowI8IRSZkmAaqidB7P6gQHclSD9lhHEIMyoeyitvbPZZ0GC1IvQzTkBX6idBbzgkxHvK2tCaL44VhD2potXI5Hf40zXA00Um1DNMgQke+qZfsENKzV/m9gRs5/dL5+hWutheLl1TKMMsSdNmhIyhxZYUmu8xRDndt/0pbduk3QLv8HJaGflYQRCnfN+jZD0LjNX5JodtF9uJkGIygW/JsdJGTyA7T0jX2E6SBl0DN8r7qc9CAvmrCD47XrnzexdfMivKqUF1SmRk66osDbt+qLURbY4UlMcUlxbSIEMy/F9mPjpt7s9cS/b3JEOAg2Ag4GTocHmxLMU0STIrGNWv4xXP/TDqMFjgZGsZmF7ndvkez6eUZ1tpPkiDZYRxUk1YYSToBNqdrxzZ8YUQv7fIvvW4xGA9OhhkiryIsUeoCV5NiGpbTVBJbJUE6AVZn7YbO/Pudg5IOowVOhgZxEydmqCTFNIiwGk58wWiz6wL63n2ifoU9rIXSDCdDR2pJswAd4Wm7dQg7rbolQI1P2AqlGa1ieUqG0c32XFbocGgiW1Btlmv/xIVvZigig4HbgL6AAqYopSaLyEXAD4BlxaLnK6UeKdY5DxgHbAV+rJR63ELsDocjg6zZMJ9/zNZfZxgXvouuRaQ/0F8p9aKIdAVmAccAY4A1SqnflJUfAdwNHAgMAP4KDFNKVe3zpHnRdYlai69dVuhw1KTZoukenbuqQ0bsr115xsyn07HoWim1GFhc/H21iLwJDKxRZTQwXSm1EXhXROZSEGP6FhYF4LTrvhD6LMN6ZtKhJ2mVO/OpIK+OjJ++4zv6llk6ZX0MkdjlkBWFU6Wf7mnvJe89+m/l6J+v0C4/4xhroTQj0HY8ERkCPAOMBM4ETgRWATOBs5RSK0TkOuBfSqk7inVuAh5VSt1X1tZ4YHzxo/7/JuqABf13/L9myOLGBCMJj64Eq5EmOeqI0EvWpFgSYDUMiLFZZtehzSfV4K6/0648d+V/pCMzLCEiXYD7gZ8opVaJyA3AryiMI/4KuAo4Wbc9pdQUYEqx7dR3k+PAK8FK14Ysbtz+Oa2SjCpBbztpEGJQEZbqZEGIfhK0Rafd17H/tJe1y8/VOAdWRL4CTAZaA1OVUpcFjUtLhiLSloII71RKPQCglFrquf8H4E/Fj43AYE/1QcVrjhpUEmGtMmmUoikRpoUwIvTWTbMQg4jwkBX/NtptbrVmFe2f/5ux9kSkNXA98GVgEfCCiMxQSs0O0o7ObLIANwFvKqUmea73L44nAhwLlDbNzADuEpFJFCZQdieu11tlFB0R1qqbBiHaEGGS2WEUEaadMBmhSSFu2rqeDz5+yUhbRQ4E5iql5gOIyHQKcxeBZKgzm3ww8HfgNWBb8fL5wHeAfSl0kxcAp5bkKCI/o9Bl3kKhW/2ozzOWAWuB+BYVmacBF3/SZP3vkPX4ofLfYRelVJ/SBxF5rFhOlw7ABs/nKcVhtlJ7xwFfUUqdUvx8AnCQUmpCkMB1ZpOfBaTCrUdq1LkUuFQ3CKVUHxGZGccgqS1c/MmT9b9D1uMHvb+DUuorccUTBLcDxeFwZB0j8xROhg6HI+u8AOwuIkNFpB1wPIW5i0Ck6aCGKf5FUo2LP3my/nfIevyQwN9BKbVFRCYAj1NYWjNNKfVG0HZS8Q4Uh8PhSBrXTXY4HA6cDB0OhwNIgQxF5Csi8raIzBWRiUnHo4uILBCR10TkZRGZWbzWS0T+IiLvFP/smXScJURkmog0icjrnmsV45UC1xS/k1dFZL/kIt8ea6X4LxKRxuJ38LKIjPLcO68Y/9sicmQyUTdHRAaLyJMiMltE3hCRM4rXM/E91Ig/U99DVZRSif1QGOycB+wKtANeAUYkGVOA2BcADWXXrgAmFn+fCFyedJye2L4I7Ae87hcvMAp4lML60s8Az6c0/ouAn1YoO6L471J7YGjx37HWKfg79Af2K/7eFZhTjDUT30ON+DP1PVT7SToz3L6NRim1CShto8kqo4Fbi7/fSuHcx1SglHoG+KjscrV4RwO3qQL/AnoUz7VMjCrxV2P7MXJKqXeB0jFyiaKUWqyUerH4+2qgdBxeJr6HGvFXI5XfQzWSluFA4H3P50XU/oebJhTwZxGZVTyODKCv2rFfewmF08HTTLV4s/S9TCh2Iad5hiVSH3/xOLxPAc+Twe+hLH7I6PfgJWkZZpmDlVL7AUcBp4nIF703VaGfkJl1S1mLt8gNwG4U9sgvpnCMXOopPw7Pey8L30OF+DP5PZSTtAwze9yXUqqx+GcT8CCF9H9pqRtT/LMpuQi1qBZvJr4XpdRSpdRWpdQ24A/s6IKlNv5Kx+GRoe+h2nF+WfseKpG0DI1so4kbEekshffBICKdgSMoHGE2AxhbLDYWeCiZCLWpFu8M4PvF2czPAB97unGpoWz8rPwYueNFpL2IDCUlx8iJVD4Oj4x8D9Xiz9r3UJWkZ3AozJjNoTDT9LOk49GMeVcKs2SvAG+U4gZ6A08A71B4EVavpGP1xHw3hS7MZgpjN+OqxUth9vL64nfyGnBASuO/vRjfqxT+w+vvKf+zYvxvA0clHX8xpoMpdIFfBV4u/ozKyvdQI/5MfQ/Vftx2PIfD4SD5brLD4XCkAidDh8PhwMnQ4XA4ACdDh8PhAJwMHQ6HA3AydDgcDsDJ0OFwOAD4fwt0eX/NFHx6AAAAAElFTkSuQmCC\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "867149ee", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_sources/_include/API_reference.rst.txt b/doc/_build/html/_sources/_include/API_reference.rst.txt deleted file mode 100644 index f94c3ba..0000000 --- a/doc/_build/html/_sources/_include/API_reference.rst.txt +++ /dev/null @@ -1,31 +0,0 @@ -API Reference -============= -This is the class and function reference of biapol-utilities. Please refer to the examples for further details, as the class and function raw specifications may not be enough to give full guidelines on their uses. - -The label module ------------------- -The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of -an object is encoded in the pixel value which must be an integer number. - -.. currentmodule:: biapol_utilities - -.. autosummary:: - :recursive: - :toctree: generated - - label.compare_labels - label.intersection_over_union_matrix - label.match_labels - label.match_labels_stack - -The data module ------------------- -The data module provides example data to be usedin the examples section. - -.. currentmodule:: biapol_utilities - -.. autosummary:: - :recursive: - :toctree: generated - - data.blobs \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/Examples.rst.txt b/doc/_build/html/_sources/_include/Examples.rst.txt deleted file mode 100644 index 792bb14..0000000 --- a/doc/_build/html/_sources/_include/Examples.rst.txt +++ /dev/null @@ -1,21 +0,0 @@ -Examples -============= -This is the example library of biapol-utilities. We provide examples for all top-level functions that are listed -in the API reference and comment on their usage here. - -Label module ------------------- -The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of -an object is encoded in the pixel value which must be an integer number. - -.. toctree:: - :titlesonly: - :maxdepth: 0 - - Match labels - Compare segmentations - Visualize labels - -Data module ------------------- -The data module provides example data to be usedin the examples section. diff --git a/doc/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt b/doc/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt deleted file mode 100644 index 286bf6d..0000000 --- a/doc/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -biapol\_utilities.label.compare\_labels -======================================= - -.. currentmodule:: biapol_utilities.label - -.. autofunction:: compare_labels \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt b/doc/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt deleted file mode 100644 index 3b66942..0000000 --- a/doc/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -biapol\_utilities.label.intersection\_over\_union\_matrix -========================================================= - -.. currentmodule:: biapol_utilities.label - -.. autofunction:: intersection_over_union_matrix \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt b/doc/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt deleted file mode 100644 index 2f71b54..0000000 --- a/doc/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -biapol\_utilities.label.match\_labels\_stack -============================================ - -.. currentmodule:: biapol_utilities.label - -.. autofunction:: match_labels_stack \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt b/doc/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt deleted file mode 100644 index 16a40fd..0000000 --- a/doc/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -biapol\_utilities.data.blobs -============================ - -.. currentmodule:: biapol_utilities.data - -.. autofunction:: blobs \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.compare_labels.rst.txt b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.compare_labels.rst.txt deleted file mode 100644 index 286bf6d..0000000 --- a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.compare_labels.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -biapol\_utilities.label.compare\_labels -======================================= - -.. currentmodule:: biapol_utilities.label - -.. autofunction:: compare_labels \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst.txt b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst.txt deleted file mode 100644 index 3b66942..0000000 --- a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -biapol\_utilities.label.intersection\_over\_union\_matrix -========================================================= - -.. currentmodule:: biapol_utilities.label - -.. autofunction:: intersection_over_union_matrix \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt deleted file mode 100644 index ae8b654..0000000 --- a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -biapol\_utilities.label.match\_labels -===================================== - -.. currentmodule:: biapol_utilities.label - -.. autofunction:: match_labels \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels_stack.rst.txt b/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels_stack.rst.txt deleted file mode 100644 index 2f71b54..0000000 --- a/doc/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels_stack.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -biapol\_utilities.label.match\_labels\_stack -============================================ - -.. currentmodule:: biapol_utilities.label - -.. autofunction:: match_labels_stack \ No newline at end of file diff --git a/doc/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt b/doc/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt deleted file mode 100644 index b694e2f..0000000 --- a/doc/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt +++ /dev/null @@ -1,5614 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "9f0d8ccf", - "metadata": {}, - "source": [ - "# Quantitative segmentation quality estimation\n", - "\n", - "Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "89205b6d", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import biapol_utilities as biau\n", - "from skimage import io, measure, segmentation\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", - "import pandas as pd\n", - "\n", - "%matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "id": "a63045b4", - "metadata": {}, - "source": [ - "## Input data\n", - "First, let's generate some example data!" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "db9c5fe0", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biau.data.blobs()" - ] - }, - { - "cell_type": "markdown", - "id": "2c0c8418", - "metadata": {}, - "source": [ - "Let's segment this and take it as a ground truth image:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "2ae66de8", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Ground truth')" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "threshold = 128\n", - "imageA = (blobs > threshold).astype(np.uint8)\n", - "ground_truth = measure.label(imageA)\n", - "\n", - "plt.imshow(ground_truth)\n", - "plt.title('Ground truth')" - ] - }, - { - "cell_type": "markdown", - "id": "f7f4c0be", - "metadata": {}, - "source": [ - "Next, we shuffle the labels and expand them a bit:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "2b8dc27c", - "metadata": {}, - "outputs": [], - "source": [ - "# First, shuffle randomly\n", - "label_shuffle = np.arange(1, ground_truth.max()+1, 1)\n", - "np.random.shuffle(label_shuffle)\n", - "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", - "segmented = label_shuffle[ground_truth]" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "279f3e2c", - "metadata": {}, - "outputs": [], - "source": [ - "# Second, expand the labels a bit\n", - "segmented = segmentation.expand_labels(segmented, 5)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "eb0b69c2", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Segmentation')" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "\n", - "axes[0].imshow(ground_truth)\n", - "axes[0].set_title('Ground truth')\n", - "\n", - "axes[1].imshow(segmented)\n", - "axes[1].set_title('Segmentation')" - ] - }, - { - "cell_type": "markdown", - "id": "dd726a7c", - "metadata": {}, - "source": [ - "## Re-match labels\n", - "\n", - "Next, use the label-matching from `biapol_utilities` to assign correct labels to both images" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "8007d578", - "metadata": {}, - "outputs": [], - "source": [ - "segmented = biau.label.match_labels(ground_truth, segmented)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "23496dad", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Segmentation')" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "\n", - "axes[0].imshow(ground_truth)\n", - "axes[0].set_title('Ground truth')\n", - "\n", - "axes[1].imshow(segmented)\n", - "axes[1].set_title('Segmentation')" - ] - }, - { - "cell_type": "markdown", - "id": "1e1d39a4", - "metadata": {}, - "source": [ - "## Compare labels: Labelwise Jaccard-index\n", - "\n", - "Lastly, we calculate the *label-wise Jaccard index* to measure the intersection over union (IoU) between corresponding pairs of labels." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "7641d30b", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
\n", - "

68 rows × 3 columns

\n", - "
" - ], - "text/plain": [ - " label jaccard_score dice_score\n", - "0 0 0.496847 0.663858\n", - "1 1 0.518102 0.682566\n", - "2 2 0.470130 0.639576\n", - "3 3 0.623552 0.768133\n", - "4 4 0.602546 0.751986\n", - ".. ... ... ...\n", - "63 63 0.262857 0.416290\n", - "64 64 0.000000 0.000000\n", - "65 65 0.000000 0.000000\n", - "66 66 0.000000 0.000000\n", - "67 67 0.000000 0.000000\n", - "\n", - "[68 rows x 3 columns]" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "result = biau.label.compare_labels(ground_truth, segmented)\n", - "result" - ] - }, - { - "cell_type": "markdown", - "id": "3f218dd4", - "metadata": {}, - "source": [ - "Let's also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "fab77a34", - "metadata": {}, - "outputs": [], - "source": [ - "LUT_jaccard = result['jaccard_score'].to_numpy()\n", - "LUT_dice = result['dice_score'].to_numpy()\n", - "\n", - "# set segmentation quality of background to zero\n", - "LUT_jaccard[0] = np.nan\n", - "LUT_dice[0] = np.nan\n", - "\n", - "# create score map\n", - "JI_map = LUT_jaccard[segmented]\n", - "DI_map = LUT_dice[segmented]" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "ca62489c", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "(-0.5, 255.5, 253.5, -0.5)" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))\n", - "fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)\n", - "\n", - "\n", - "# Plot ground truth\n", - "axes[0, 0].imshow(ground_truth)\n", - "axes[0, 0].set_title('Ground truth')\n", - "\n", - "# Plot segmentation\n", - "axes[0, 1].imshow(segmented)\n", - "axes[0, 1].set_title('Segmentation')\n", - "\n", - "# Plot overlay\n", - "axes[0, 2].imshow(ground_truth)\n", - "axes[0, 2].imshow(segmented, alpha=0.5)\n", - "axes[0, 2].set_title('Overlay')\n", - "\n", - "# Plot Jaccard index map\n", - "im = axes[1, 0].imshow(JI_map, cmap='inferno_r')\n", - "axes[1, 0].set_title('Jaccard score')\n", - "cbar = fig.colorbar(im, ax=axes[1, 0])\n", - "\n", - "# Plot Dice score map\n", - "im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')\n", - "axes[1, 1].set_title('Dice score')\n", - "cbar2 = fig.colorbar(im2, ax=axes[1, 1])\n", - "\n", - "axes[-1, -1].axis('off')" - ] - }, - { - "cell_type": "markdown", - "id": "1dc2ca58", - "metadata": {}, - "source": [ - "## Compare-labels: Feature-wise\n", - "It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "5f6cc904", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
\n", - "

63 rows × 4 columns

\n", - "
" - ], - "text/plain": [ - " label area eccentricity orientation\n", - "0 1 415 0.878888 -0.433915\n", - "1 2 181 0.822705 -1.513862\n", - "2 3 646 0.386542 -0.079653\n", - "3 4 426 0.324798 -0.400592\n", - "4 5 465 0.780472 -0.044317\n", - ".. ... ... ... ...\n", - "58 59 1 0.000000 0.785398\n", - "59 60 87 0.969263 -1.560717\n", - "60 61 73 0.951468 -1.567605\n", - "61 62 49 0.942191 -1.554054\n", - "62 63 46 0.976786 1.538848\n", - "\n", - "[63 rows x 4 columns]" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "properties = ['label', 'area', 'eccentricity', 'orientation']\n", - "features_gt = measure.regionprops_table(ground_truth, properties=properties)\n", - "features_seg = measure.regionprops_table(segmented, properties=properties)\n", - "\n", - "features_gt = pd.DataFrame(features_gt)\n", - "features_seg = pd.DataFrame(features_seg)\n", - "features_gt" - ] - }, - { - "cell_type": "markdown", - "id": "ec29004b", - "metadata": {}, - "source": [ - "Visualize as histograms" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "e9652f8d", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0, 0.5, '# Occurrences')" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))\n", - "\n", - "ax_idx = 0\n", - "for idx, prop in enumerate(properties):\n", - " if prop == 'label':\n", - " continue\n", - " \n", - " axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)\n", - " axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)\n", - " axes[ax_idx].set_xlabel(prop)\n", - " ax_idx += 1\n", - " \n", - "axes[0].legend()\n", - "axes[0].set_ylabel('# Occurrences')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "185d4c1d", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt b/doc/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt deleted file mode 100644 index 181425a..0000000 --- a/doc/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt +++ /dev/null @@ -1,3198 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "e5db44ea", - "metadata": {}, - "source": [ - "## Matching labels\n", - "This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "d1ca8e7a", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import biapol_utilities as biau\n", - "from skimage import io, measure, filters\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from datetime import datetime\n", - "\n", - "%matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "id": "ee62539b", - "metadata": {}, - "source": [ - "### Load data\n", - "First, we load the example blobs image and threshold it to create a label map. " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "7fe70350", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biau.data.blobs()" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "909ce3b2", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "threshold = 128\n", - "imageA = (blobs > threshold).astype(np.uint8)\n", - "imageA_labelled = measure.label(imageA)\n", - "\n", - "plt.imshow(imageA_labelled)" - ] - }, - { - "cell_type": "markdown", - "id": "1cbf5ae3", - "metadata": {}, - "source": [ - "Let's create a second version of this image in which we shuffle the labels:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "29986d79", - "metadata": {}, - "outputs": [], - "source": [ - "label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)\n", - "np.random.shuffle(label_shuffle)\n", - "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", - "\n", - "imageB_labelled = label_shuffle[imageA_labelled]" - ] - }, - { - "cell_type": "markdown", - "id": "1393dfb7", - "metadata": {}, - "source": [ - "Both images are not identical!" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "1ff3c80c", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of labels in imageA: 63\n", - "Number of labels in imageB: 63\n" - ] - } - ], - "source": [ - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "axes[0].imshow(imageA_labelled)\n", - "axes[0].set_title('Reference image')\n", - "axes[1].imshow(imageB_labelled)\n", - "axes[1].set_title('Shuffled image')\n", - "\n", - "print(f'Number of labels in imageA: {imageA_labelled.max()}')\n", - "print(f'Number of labels in imageB: {imageB_labelled.max()}')" - ] - }, - { - "cell_type": "markdown", - "id": "7a38be04", - "metadata": {}, - "source": [ - "Match labels and track time" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "79f0cf74", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Took 0 ms\n" - ] - } - ], - "source": [ - "t0 = datetime.now()\n", - "output = biau.label.match_labels(imageA_labelled, imageB_labelled)\n", - "t1 = datetime.now()\n", - "print(f'Took {(t1-t0).seconds*1000} ms')" - ] - }, - { - "cell_type": "markdown", - "id": "a8710824", - "metadata": {}, - "source": [ - "Visualize" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "84ed2639", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Relabelled image')" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "axes[0].imshow(imageA_labelled)\n", - "axes[0].set_title('Reference image')\n", - "axes[1].imshow(output)\n", - "axes[1].set_title('Relabelled image')" - ] - } - ], - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt b/doc/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt deleted file mode 100644 index 9924ff8..0000000 --- a/doc/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt +++ /dev/null @@ -1,98 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "803a884d", - "metadata": {}, - "outputs": [], - "source": [ - "import biapol_utilities as biao\n", - "from skimage.measure import label\n", - "from skimage.io import imshow" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "af876b71", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biao.blobs()\n", - "labels = label(blobs > 128)" - ] - }, - { - "cell_type": "markdown", - "id": "d9ded05a", - "metadata": {}, - "source": [ - "# Labels visualized in colours\n", - "`biapol_utilities` provided a standardized color map for visualizing labels in:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "5c3f2337", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "867149ee", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_build/html/_sources/index.rst.txt b/doc/_build/html/_sources/index.rst.txt deleted file mode 100644 index 67ee96f..0000000 --- a/doc/_build/html/_sources/index.rst.txt +++ /dev/null @@ -1,26 +0,0 @@ -Welcome to BiAPoL utilities's documentation! -============================================ - -On this page, we provide documentation pages for our API and provide -comprehensive examples on how to use the functions in our library. - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - _include/Examples - _include/API_reference - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - -Ressources -================== - - * BiAPoL group blog: ``_. - * Source code: ``_. \ No newline at end of file diff --git a/doc/_build/html/_static/alabaster.css b/doc/_build/html/_static/alabaster.css deleted file mode 100644 index 0eddaeb..0000000 --- a/doc/_build/html/_static/alabaster.css +++ /dev/null @@ -1,701 +0,0 @@ -@import url("basic.css"); - -/* -- page layout ----------------------------------------------------------- */ - -body { - font-family: Georgia, serif; - font-size: 17px; - background-color: #fff; - color: #000; - margin: 0; - padding: 0; -} - - -div.document { - width: 940px; - margin: 30px auto 0 auto; -} - -div.documentwrapper { - float: left; - width: 100%; -} - -div.bodywrapper { - margin: 0 0 0 220px; -} - -div.sphinxsidebar { - width: 220px; - font-size: 14px; - line-height: 1.5; -} - -hr { - border: 1px solid #B1B4B6; -} - -div.body { - background-color: #fff; - color: #3E4349; - padding: 0 30px 0 30px; -} - -div.body > .section { - text-align: left; -} - -div.footer { - width: 940px; - margin: 20px auto 30px auto; - font-size: 14px; - color: #888; - text-align: right; -} - -div.footer a { - color: #888; -} - -p.caption { - font-family: inherit; - font-size: inherit; -} - - -div.relations { - display: none; -} - - -div.sphinxsidebar a { - color: #444; - text-decoration: none; - border-bottom: 1px dotted #999; -} - -div.sphinxsidebar a:hover { - border-bottom: 1px solid #999; -} - -div.sphinxsidebarwrapper { - padding: 18px 10px; -} - -div.sphinxsidebarwrapper p.logo { - padding: 0; - margin: -10px 0 0 0px; - text-align: center; -} - -div.sphinxsidebarwrapper h1.logo { - margin-top: -10px; - text-align: center; - margin-bottom: 5px; - text-align: left; -} - -div.sphinxsidebarwrapper h1.logo-name { - margin-top: 0px; -} - -div.sphinxsidebarwrapper p.blurb { - margin-top: 0; - font-style: normal; -} - -div.sphinxsidebar h3, -div.sphinxsidebar h4 { - font-family: Georgia, serif; - color: #444; - font-size: 24px; - font-weight: normal; - margin: 0 0 5px 0; - padding: 0; -} - -div.sphinxsidebar h4 { - font-size: 20px; -} - -div.sphinxsidebar h3 a { - color: #444; -} - -div.sphinxsidebar p.logo a, -div.sphinxsidebar h3 a, -div.sphinxsidebar p.logo a:hover, -div.sphinxsidebar h3 a:hover { - border: none; -} - -div.sphinxsidebar p { - color: #555; - margin: 10px 0; -} - -div.sphinxsidebar ul { - margin: 10px 0; - padding: 0; - color: #000; -} - -div.sphinxsidebar ul li.toctree-l1 > a { - font-size: 120%; -} - -div.sphinxsidebar ul li.toctree-l2 > a { - font-size: 110%; -} - -div.sphinxsidebar input { - border: 1px solid #CCC; - font-family: Georgia, serif; - font-size: 1em; -} - -div.sphinxsidebar hr { - border: none; - height: 1px; - color: #AAA; - background: #AAA; - - text-align: left; - margin-left: 0; - width: 50%; -} - -div.sphinxsidebar .badge { - border-bottom: none; -} - -div.sphinxsidebar .badge:hover { - border-bottom: none; -} - -/* To address an issue with donation coming after search */ -div.sphinxsidebar h3.donation { - margin-top: 10px; -} - -/* -- body styles ----------------------------------------------------------- */ - -a { - color: #004B6B; - text-decoration: underline; -} - -a:hover { - color: #6D4100; - text-decoration: underline; -} - -div.body h1, -div.body h2, -div.body h3, -div.body h4, -div.body h5, -div.body h6 { - font-family: Georgia, serif; - font-weight: normal; - margin: 30px 0px 10px 0px; - padding: 0; -} - -div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } -div.body h2 { font-size: 180%; } -div.body h3 { font-size: 150%; } -div.body h4 { font-size: 130%; } -div.body h5 { font-size: 100%; } -div.body h6 { font-size: 100%; } - -a.headerlink { - color: #DDD; - padding: 0 4px; - text-decoration: none; -} - -a.headerlink:hover { - color: #444; - background: #EAEAEA; -} - -div.body p, div.body dd, div.body li { - line-height: 1.4em; -} - -div.admonition { - margin: 20px 0px; - padding: 10px 30px; - background-color: #EEE; - border: 1px solid #CCC; -} - -div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { - background-color: #FBFBFB; - border-bottom: 1px solid #fafafa; -} - -div.admonition p.admonition-title { - font-family: Georgia, serif; - font-weight: normal; - font-size: 24px; - margin: 0 0 10px 0; - padding: 0; - line-height: 1; -} - -div.admonition p.last { - margin-bottom: 0; -} - -div.highlight { - background-color: #fff; -} - -dt:target, .highlight { - background: #FAF3E8; -} - -div.warning { - background-color: #FCC; - border: 1px solid #FAA; -} - -div.danger { - background-color: #FCC; - border: 1px solid #FAA; - -moz-box-shadow: 2px 2px 4px #D52C2C; - -webkit-box-shadow: 2px 2px 4px #D52C2C; - box-shadow: 2px 2px 4px #D52C2C; -} - -div.error { - background-color: #FCC; - border: 1px solid #FAA; - -moz-box-shadow: 2px 2px 4px #D52C2C; - -webkit-box-shadow: 2px 2px 4px #D52C2C; - box-shadow: 2px 2px 4px #D52C2C; -} - -div.caution { - background-color: #FCC; - border: 1px solid #FAA; -} - -div.attention { - background-color: #FCC; - border: 1px solid #FAA; -} - -div.important { - background-color: #EEE; - border: 1px solid #CCC; -} - -div.note { - background-color: #EEE; - border: 1px solid #CCC; -} - -div.tip { - background-color: #EEE; - border: 1px solid #CCC; -} - -div.hint { - background-color: #EEE; - border: 1px solid #CCC; -} - -div.seealso { - background-color: #EEE; - border: 1px solid #CCC; -} - -div.topic { - background-color: #EEE; -} - -p.admonition-title { - display: inline; -} - -p.admonition-title:after { - content: ":"; -} - -pre, tt, code { - font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; - font-size: 0.9em; -} - -.hll { - background-color: #FFC; - margin: 0 -12px; - padding: 0 12px; - display: block; -} - -img.screenshot { -} - -tt.descname, tt.descclassname, code.descname, code.descclassname { - font-size: 0.95em; -} - -tt.descname, code.descname { - padding-right: 0.08em; -} - -img.screenshot { - -moz-box-shadow: 2px 2px 4px #EEE; - -webkit-box-shadow: 2px 2px 4px #EEE; - box-shadow: 2px 2px 4px #EEE; -} - -table.docutils { - border: 1px solid #888; - -moz-box-shadow: 2px 2px 4px #EEE; - -webkit-box-shadow: 2px 2px 4px #EEE; - box-shadow: 2px 2px 4px #EEE; -} - -table.docutils td, table.docutils th { - border: 1px solid #888; - padding: 0.25em 0.7em; -} - -table.field-list, table.footnote { - border: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - -table.footnote { - margin: 15px 0; - width: 100%; - border: 1px solid #EEE; - background: #FDFDFD; - font-size: 0.9em; -} - -table.footnote + table.footnote { - margin-top: -15px; - border-top: none; -} - -table.field-list th { - padding: 0 0.8em 0 0; -} - -table.field-list td { - padding: 0; -} - -table.field-list p { - margin-bottom: 0.8em; -} - -/* Cloned from - * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 - */ -.field-name { - -moz-hyphens: manual; - -ms-hyphens: manual; - -webkit-hyphens: manual; - hyphens: manual; -} - -table.footnote td.label { - width: .1px; - padding: 0.3em 0 0.3em 0.5em; -} - -table.footnote td { - padding: 0.3em 0.5em; -} - -dl { - margin: 0; - padding: 0; -} - -dl dd { - margin-left: 30px; -} - -blockquote { - margin: 0 0 0 30px; - padding: 0; -} - -ul, ol { - /* Matches the 30px from the narrow-screen "li > ul" selector below */ - margin: 10px 0 10px 30px; - padding: 0; -} - -pre { - background: #EEE; - padding: 7px 30px; - margin: 15px 0px; - line-height: 1.3em; -} - -div.viewcode-block:target { - background: #ffd; -} - -dl pre, blockquote pre, li pre { - margin-left: 0; - padding-left: 30px; -} - -tt, code { - background-color: #ecf0f3; - color: #222; - /* padding: 1px 2px; */ -} - -tt.xref, code.xref, a tt { - background-color: #FBFBFB; - border-bottom: 1px solid #fff; -} - -a.reference { - text-decoration: none; - border-bottom: 1px dotted #004B6B; -} - -/* Don't put an underline on images */ -a.image-reference, a.image-reference:hover { - border-bottom: none; -} - -a.reference:hover { - border-bottom: 1px solid #6D4100; -} - -a.footnote-reference { - text-decoration: none; - font-size: 0.7em; - vertical-align: top; - border-bottom: 1px dotted #004B6B; -} - -a.footnote-reference:hover { - border-bottom: 1px solid #6D4100; -} - -a:hover tt, a:hover code { - background: #EEE; -} - - -@media screen and (max-width: 870px) { - - div.sphinxsidebar { - display: none; - } - - div.document { - width: 100%; - - } - - div.documentwrapper { - margin-left: 0; - margin-top: 0; - margin-right: 0; - margin-bottom: 0; - } - - div.bodywrapper { - margin-top: 0; - margin-right: 0; - margin-bottom: 0; - margin-left: 0; - } - - ul { - margin-left: 0; - } - - li > ul { - /* Matches the 30px from the "ul, ol" selector above */ - margin-left: 30px; - } - - .document { - width: auto; - } - - .footer { - width: auto; - } - - .bodywrapper { - margin: 0; - } - - .footer { - width: auto; - } - - .github { - display: none; - } - - - -} - - - -@media screen and (max-width: 875px) { - - body { - margin: 0; - padding: 20px 30px; - } - - div.documentwrapper { - float: none; - background: #fff; - } - - div.sphinxsidebar { - display: block; - float: none; - width: 102.5%; - margin: 50px -30px -20px -30px; - padding: 10px 20px; - background: #333; - color: #FFF; - } - - div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, - div.sphinxsidebar h3 a { - color: #fff; - } - - div.sphinxsidebar a { - color: #AAA; - } - - div.sphinxsidebar p.logo { - display: none; - } - - div.document { - width: 100%; - margin: 0; - } - - div.footer { - display: none; - } - - div.bodywrapper { - margin: 0; - } - - div.body { - min-height: 0; - padding: 0; - } - - .rtd_doc_footer { - display: none; - } - - .document { - width: auto; - } - - .footer { - width: auto; - } - - .footer { - width: auto; - } - - .github { - display: none; - } -} - - -/* misc. */ - -.revsys-inline { - display: none!important; -} - -/* Make nested-list/multi-paragraph items look better in Releases changelog - * pages. Without this, docutils' magical list fuckery causes inconsistent - * formatting between different release sub-lists. - */ -div#changelog > div.section > ul > li > p:only-child { - margin-bottom: 0; -} - -/* Hide fugly table cell borders in ..bibliography:: directive output */ -table.docutils.citation, table.docutils.citation td, table.docutils.citation th { - border: none; - /* Below needed in some edge cases; if not applied, bottom shadows appear */ - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - - -/* relbar */ - -.related { - line-height: 30px; - width: 100%; - font-size: 0.9rem; -} - -.related.top { - border-bottom: 1px solid #EEE; - margin-bottom: 20px; -} - -.related.bottom { - border-top: 1px solid #EEE; -} - -.related ul { - padding: 0; - margin: 0; - list-style: none; -} - -.related li { - display: inline; -} - -nav#rellinks { - float: right; -} - -nav#rellinks li+li:before { - content: "|"; -} - -nav#breadcrumbs li+li:before { - content: "\00BB"; -} - -/* Hide certain items when printing */ -@media print { - div.related { - display: none; - } -} \ No newline at end of file diff --git a/doc/_build/html/_static/basic.css b/doc/_build/html/_static/basic.css deleted file mode 100644 index 912859b..0000000 --- a/doc/_build/html/_static/basic.css +++ /dev/null @@ -1,904 +0,0 @@ -/* - * basic.css - * ~~~~~~~~~ - * - * Sphinx stylesheet -- basic theme. - * - * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/* -- main layout ----------------------------------------------------------- */ - -div.clearer { - clear: both; -} - -div.section::after { - display: block; - content: ''; - clear: left; -} - -/* -- relbar ---------------------------------------------------------------- */ - -div.related { - width: 100%; - font-size: 90%; -} - -div.related h3 { - display: none; -} - -div.related ul { - margin: 0; - padding: 0 0 0 10px; - list-style: none; -} - -div.related li { - display: inline; -} - -div.related li.right { - float: right; - margin-right: 5px; -} - -/* -- sidebar --------------------------------------------------------------- */ - -div.sphinxsidebarwrapper { - padding: 10px 5px 0 10px; -} - -div.sphinxsidebar { - float: left; - width: 230px; - margin-left: -100%; - font-size: 90%; - word-wrap: break-word; - overflow-wrap : break-word; -} - -div.sphinxsidebar ul { - list-style: none; -} - -div.sphinxsidebar ul ul, -div.sphinxsidebar ul.want-points { - margin-left: 20px; - list-style: square; -} - -div.sphinxsidebar ul ul { - margin-top: 0; - margin-bottom: 0; -} - -div.sphinxsidebar form { - margin-top: 10px; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -div.sphinxsidebar #searchbox form.search { - overflow: hidden; -} - -div.sphinxsidebar #searchbox input[type="text"] { - float: left; - width: 80%; - padding: 0.25em; - box-sizing: border-box; -} - -div.sphinxsidebar #searchbox input[type="submit"] { - float: left; - width: 20%; - border-left: none; - padding: 0.25em; - box-sizing: border-box; -} - - -img { - border: 0; - max-width: 100%; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin: 10px 0 0 20px; - padding: 0; -} - -ul.search li { - padding: 5px 0 5px 20px; - background-image: url(file.png); - background-repeat: no-repeat; - background-position: 0 7px; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li p.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} - -/* -- index page ------------------------------------------------------------ */ - -table.contentstable { - width: 90%; - margin-left: auto; - margin-right: auto; -} - -table.contentstable p.biglink { - line-height: 150%; -} - -a.biglink { - font-size: 1.3em; -} - -span.linkdescr { - font-style: italic; - padding-top: 5px; - font-size: 90%; -} - -/* -- general index --------------------------------------------------------- */ - -table.indextable { - width: 100%; -} - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable ul { - margin-top: 0; - margin-bottom: 0; - list-style-type: none; -} - -table.indextable > tbody > tr > td > ul { - padding-left: 0em; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -div.modindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -div.genindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -/* -- domain module index --------------------------------------------------- */ - -table.modindextable td { - padding: 2px; - border-collapse: collapse; -} - -/* -- general body styles --------------------------------------------------- */ - -div.body { - min-width: 450px; - max-width: 800px; -} - -div.body p, div.body dd, div.body li, div.body blockquote { - -moz-hyphens: auto; - -ms-hyphens: auto; - -webkit-hyphens: auto; - hyphens: auto; -} - -a.headerlink { - visibility: hidden; -} - -a.brackets:before, -span.brackets > a:before{ - content: "["; -} - -a.brackets:after, -span.brackets > a:after { - content: "]"; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink, -caption:hover > a.headerlink, -p.caption:hover > a.headerlink, -div.code-block-caption:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -img.align-left, figure.align-left, .figure.align-left, object.align-left { - clear: left; - float: left; - margin-right: 1em; -} - -img.align-right, figure.align-right, .figure.align-right, object.align-right { - clear: right; - float: right; - margin-left: 1em; -} - -img.align-center, figure.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -img.align-default, figure.align-default, .figure.align-default { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left; -} - -.align-center { - text-align: center; -} - -.align-default { - text-align: center; -} - -.align-right { - text-align: right; -} - -/* -- sidebars -------------------------------------------------------------- */ - -div.sidebar, -aside.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px; - background-color: #ffe; - width: 40%; - float: right; - clear: right; - overflow-x: auto; -} - -p.sidebar-title { - font-weight: bold; -} - -div.admonition, div.topic, blockquote { - clear: left; -} - -/* -- topics ---------------------------------------------------------------- */ - -div.topic { - border: 1px solid #ccc; - padding: 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- content of sidebars/topics/admonitions -------------------------------- */ - -div.sidebar > :last-child, -aside.sidebar > :last-child, -div.topic > :last-child, -div.admonition > :last-child { - margin-bottom: 0; -} - -div.sidebar::after, -aside.sidebar::after, -div.topic::after, -div.admonition::after, -blockquote::after { - display: block; - content: ''; - clear: both; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - margin-top: 10px; - margin-bottom: 10px; - border: 0; - border-collapse: collapse; -} - -table.align-center { - margin-left: auto; - margin-right: auto; -} - -table.align-default { - margin-left: auto; - margin-right: auto; -} - -table caption span.caption-number { - font-style: italic; -} - -table caption span.caption-text { -} - -table.docutils td, table.docutils th { - padding: 1px 8px 1px 5px; - border-top: 0; - border-left: 0; - border-right: 0; - border-bottom: 1px solid #aaa; -} - -table.footnote td, table.footnote th { - border: 0 !important; -} - -th { - text-align: left; - padding-right: 5px; -} - -table.citation { - border-left: solid 1px gray; - margin-left: 1px; -} - -table.citation td { - border-bottom: none; -} - -th > :first-child, -td > :first-child { - margin-top: 0px; -} - -th > :last-child, -td > :last-child { - margin-bottom: 0px; -} - -/* -- figures --------------------------------------------------------------- */ - -div.figure, figure { - margin: 0.5em; - padding: 0.5em; -} - -div.figure p.caption, figcaption { - padding: 0.3em; -} - -div.figure p.caption span.caption-number, -figcaption span.caption-number { - font-style: italic; -} - -div.figure p.caption span.caption-text, -figcaption span.caption-text { -} - -/* -- field list styles ----------------------------------------------------- */ - -table.field-list td, table.field-list th { - border: 0 !important; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - -.field-name { - -moz-hyphens: manual; - -ms-hyphens: manual; - -webkit-hyphens: manual; - hyphens: manual; -} - -/* -- hlist styles ---------------------------------------------------------- */ - -table.hlist { - margin: 1em 0; -} - -table.hlist td { - vertical-align: top; -} - -/* -- object description styles --------------------------------------------- */ - -.sig { - font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; -} - -.sig-name, code.descname { - background-color: transparent; - font-weight: bold; -} - -.sig-name { - font-size: 1.1em; -} - -code.descname { - font-size: 1.2em; -} - -.sig-prename, code.descclassname { - background-color: transparent; -} - -.optional { - font-size: 1.3em; -} - -.sig-paren { - font-size: larger; -} - -.sig-param.n { - font-style: italic; -} - -/* C++ specific styling */ - -.sig-inline.c-texpr, -.sig-inline.cpp-texpr { - font-family: unset; -} - -.sig.c .k, .sig.c .kt, -.sig.cpp .k, .sig.cpp .kt { - color: #0033B3; -} - -.sig.c .m, -.sig.cpp .m { - color: #1750EB; -} - -.sig.c .s, .sig.c .sc, -.sig.cpp .s, .sig.cpp .sc { - color: #067D17; -} - - -/* -- other body styles ----------------------------------------------------- */ - -ol.arabic { - list-style: decimal; -} - -ol.loweralpha { - list-style: lower-alpha; -} - -ol.upperalpha { - list-style: upper-alpha; -} - -ol.lowerroman { - list-style: lower-roman; -} - -ol.upperroman { - list-style: upper-roman; -} - -:not(li) > ol > li:first-child > :first-child, -:not(li) > ul > li:first-child > :first-child { - margin-top: 0px; -} - -:not(li) > ol > li:last-child > :last-child, -:not(li) > ul > li:last-child > :last-child { - margin-bottom: 0px; -} - -ol.simple ol p, -ol.simple ul p, -ul.simple ol p, -ul.simple ul p { - margin-top: 0; -} - -ol.simple > li:not(:first-child) > p, -ul.simple > li:not(:first-child) > p { - margin-top: 0; -} - -ol.simple p, -ul.simple p { - margin-bottom: 0; -} - -dl.footnote > dt, -dl.citation > dt { - float: left; - margin-right: 0.5em; -} - -dl.footnote > dd, -dl.citation > dd { - margin-bottom: 0em; -} - -dl.footnote > dd:after, -dl.citation > dd:after { - content: ""; - clear: both; -} - -dl.field-list { - display: grid; - grid-template-columns: fit-content(30%) auto; -} - -dl.field-list > dt { - font-weight: bold; - word-break: break-word; - padding-left: 0.5em; - padding-right: 5px; -} - -dl.field-list > dt:after { - content: ":"; -} - -dl.field-list > dd { - padding-left: 0.5em; - margin-top: 0em; - margin-left: 0em; - margin-bottom: 0em; -} - -dl { - margin-bottom: 15px; -} - -dd > :first-child { - margin-top: 0px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; -} - -dl > dd:last-child, -dl > dd:last-child > :last-child { - margin-bottom: 0; -} - -dt:target, span.highlighted { - background-color: #fbe54e; -} - -rect.highlighted { - fill: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa; -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -.guilabel, .menuselection { - font-family: sans-serif; -} - -.accelerator { - text-decoration: underline; -} - -.classifier { - font-style: oblique; -} - -.classifier:before { - font-style: normal; - margin: 0.5em; - content: ":"; -} - -abbr, acronym { - border-bottom: dotted 1px; - cursor: help; -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; - overflow-y: hidden; /* fixes display issues on Chrome browsers */ -} - -pre, div[class*="highlight-"] { - clear: both; -} - -span.pre { - -moz-hyphens: none; - -ms-hyphens: none; - -webkit-hyphens: none; - hyphens: none; -} - -div[class*="highlight-"] { - margin: 1em 0; -} - -td.linenos pre { - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - display: block; -} - -table.highlighttable tbody { - display: block; -} - -table.highlighttable tr { - display: flex; -} - -table.highlighttable td { - margin: 0; - padding: 0; -} - -table.highlighttable td.linenos { - padding-right: 0.5em; -} - -table.highlighttable td.code { - flex: 1; - overflow: hidden; -} - -.highlight .hll { - display: block; -} - -div.highlight pre, -table.highlighttable pre { - margin: 0; -} - -div.code-block-caption + div { - margin-top: 0; -} - -div.code-block-caption { - margin-top: 1em; - padding: 2px 5px; - font-size: small; -} - -div.code-block-caption code { - background-color: transparent; -} - -table.highlighttable td.linenos, -span.linenos, -div.highlight span.gp { /* gp: Generic.Prompt */ - user-select: none; - -webkit-user-select: text; /* Safari fallback only */ - -webkit-user-select: none; /* Chrome/Safari */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* IE10+ */ -} - -div.code-block-caption span.caption-number { - padding: 0.1em 0.3em; - font-style: italic; -} - -div.code-block-caption span.caption-text { -} - -div.literal-block-wrapper { - margin: 1em 0; -} - -code.xref, a code { - background-color: transparent; - font-weight: bold; -} - -h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { - background-color: transparent; -} - -.viewcode-link { - float: right; -} - -.viewcode-back { - float: right; - font-family: sans-serif; -} - -div.viewcode-block:target { - margin: -1px -10px; - padding: 0 10px; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -span.eqno a.headerlink { - position: absolute; - z-index: 1; -} - -div.math:hover a.headerlink { - visibility: visible; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0 !important; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} \ No newline at end of file diff --git a/doc/_build/html/_static/custom.css b/doc/_build/html/_static/custom.css deleted file mode 100644 index 2a924f1..0000000 --- a/doc/_build/html/_static/custom.css +++ /dev/null @@ -1 +0,0 @@ -/* This file intentionally left blank. */ diff --git a/doc/_build/html/_static/doctools.js b/doc/_build/html/_static/doctools.js deleted file mode 100644 index 8cbf1b1..0000000 --- a/doc/_build/html/_static/doctools.js +++ /dev/null @@ -1,323 +0,0 @@ -/* - * doctools.js - * ~~~~~~~~~~~ - * - * Sphinx JavaScript utilities for all documentation. - * - * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/** - * select a different prefix for underscore - */ -$u = _.noConflict(); - -/** - * make the code below compatible with browsers without - * an installed firebug like debugger -if (!window.console || !console.firebug) { - var names = ["log", "debug", "info", "warn", "error", "assert", "dir", - "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", - "profile", "profileEnd"]; - window.console = {}; - for (var i = 0; i < names.length; ++i) - window.console[names[i]] = function() {}; -} - */ - -/** - * small helper function to urldecode strings - * - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL - */ -jQuery.urldecode = function(x) { - if (!x) { - return x - } - return decodeURIComponent(x.replace(/\+/g, ' ')); -}; - -/** - * small helper function to urlencode strings - */ -jQuery.urlencode = encodeURIComponent; - -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s === 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; - } - return result; -}; - -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node, addItems) { - if (node.nodeType === 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && - !jQuery(node.parentNode).hasClass(className) && - !jQuery(node.parentNode).hasClass("nohighlight")) { - var span; - var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.className = className; - } - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - if (isInSVG) { - var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); - var bbox = node.parentElement.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute('class', className); - addItems.push({ - "parent": node.parentNode, - "target": rect}); - } - } - } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this, addItems); - }); - } - } - var addItems = []; - var result = this.each(function() { - highlight(this, addItems); - }); - for (var i = 0; i < addItems.length; ++i) { - jQuery(addItems[i].parent).before(addItems[i].target); - } - return result; -}; - -/* - * backward compatibility for jQuery.browser - * This will be supported until firefox bug is fixed. - */ -if (!jQuery.browser) { - jQuery.uaMatch = function(ua) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(webkit)[ \/]([\w.]+)/.exec(ua) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - /(msie) ([\w.]+)/.exec(ua) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; - }; - jQuery.browser = {}; - jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; -} - -/** - * Small JavaScript module for the documentation. - */ -var Documentation = { - - init : function() { - this.fixFirefoxAnchorBug(); - this.highlightSearchWords(); - this.initIndexTable(); - if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { - this.initOnKeyListeners(); - } - }, - - /** - * i18n support - */ - TRANSLATIONS : {}, - PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, - LOCALE : 'unknown', - - // gettext and ngettext don't access this so that the functions - // can safely bound to a different name (_ = Documentation.gettext) - gettext : function(string) { - var translated = Documentation.TRANSLATIONS[string]; - if (typeof translated === 'undefined') - return string; - return (typeof translated === 'string') ? translated : translated[0]; - }, - - ngettext : function(singular, plural, n) { - var translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated === 'undefined') - return (n == 1) ? singular : plural; - return translated[Documentation.PLURALEXPR(n)]; - }, - - addTranslations : function(catalog) { - for (var key in catalog.messages) - this.TRANSLATIONS[key] = catalog.messages[key]; - this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); - this.LOCALE = catalog.locale; - }, - - /** - * add context elements like header anchor links - */ - addContextElements : function() { - $('div[id] > :header:first').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this headline')). - appendTo(this); - }); - $('dt[id]').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this definition')). - appendTo(this); - }); - }, - - /** - * workaround a firefox stupidity - * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 - */ - fixFirefoxAnchorBug : function() { - if (document.location.hash && $.browser.mozilla) - window.setTimeout(function() { - document.location.href += ''; - }, 10); - }, - - /** - * highlight the search words provided in the url in the text - */ - highlightSearchWords : function() { - var params = $.getQueryParameters(); - var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; - if (terms.length) { - var body = $('div.body'); - if (!body.length) { - body = $('body'); - } - window.setTimeout(function() { - $.each(terms, function() { - body.highlightText(this.toLowerCase(), 'highlighted'); - }); - }, 10); - $('') - .appendTo($('#searchbox')); - } - }, - - /** - * init the domain index toggle buttons - */ - initIndexTable : function() { - var togglers = $('img.toggler').click(function() { - var src = $(this).attr('src'); - var idnum = $(this).attr('id').substr(7); - $('tr.cg-' + idnum).toggle(); - if (src.substr(-9) === 'minus.png') - $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); - else - $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); - }).css('display', ''); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { - togglers.click(); - } - }, - - /** - * helper function to hide the search marks again - */ - hideSearchWords : function() { - $('#searchbox .highlight-link').fadeOut(300); - $('span.highlighted').removeClass('highlighted'); - }, - - /** - * make the url absolute - */ - makeURL : function(relativeURL) { - return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; - }, - - /** - * get the current relative url - */ - getCurrentURL : function() { - var path = document.location.pathname; - var parts = path.split(/\//); - $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { - if (this === '..') - parts.pop(); - }); - var url = parts.join('/'); - return path.substring(url.lastIndexOf('/') + 1, path.length - 1); - }, - - initOnKeyListeners: function() { - $(document).keydown(function(event) { - var activeElementType = document.activeElement.tagName; - // don't navigate when in search box, textarea, dropdown or button - if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' - && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey - && !event.shiftKey) { - switch (event.keyCode) { - case 37: // left - var prevHref = $('link[rel="prev"]').prop('href'); - if (prevHref) { - window.location.href = prevHref; - return false; - } - break; - case 39: // right - var nextHref = $('link[rel="next"]').prop('href'); - if (nextHref) { - window.location.href = nextHref; - return false; - } - break; - } - } - }); - } -}; - -// quick alias for translations -_ = Documentation.gettext; - -$(document).ready(function() { - Documentation.init(); -}); diff --git a/doc/_build/html/_static/documentation_options.js b/doc/_build/html/_static/documentation_options.js deleted file mode 100644 index 23fc755..0000000 --- a/doc/_build/html/_static/documentation_options.js +++ /dev/null @@ -1,12 +0,0 @@ -var DOCUMENTATION_OPTIONS = { - URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), - VERSION: '0.0.1', - LANGUAGE: 'None', - COLLAPSE_INDEX: false, - BUILDER: 'html', - FILE_SUFFIX: '.html', - LINK_SUFFIX: '.html', - HAS_SOURCE: true, - SOURCELINK_SUFFIX: '.txt', - NAVIGATION_WITH_KEYS: false -}; \ No newline at end of file diff --git a/doc/_build/html/_static/file.png b/doc/_build/html/_static/file.png deleted file mode 100644 index a858a410e4faa62ce324d814e4b816fff83a6fb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( diff --git a/doc/_build/html/_static/jquery-3.5.1.js b/doc/_build/html/_static/jquery-3.5.1.js deleted file mode 100644 index 5093733..0000000 --- a/doc/_build/html/_static/jquery-3.5.1.js +++ /dev/null @@ -1,10872 +0,0 @@ -/*! - * jQuery JavaScript Library v3.5.1 - * https://jquery.com/ - * - * Includes Sizzle.js - * https://sizzlejs.com/ - * - * Copyright JS Foundation and other contributors - * Released under the MIT license - * https://jquery.org/license - * - * Date: 2020-05-04T22:49Z - */ -( function( global, factory ) { - - "use strict"; - - if ( typeof module === "object" && typeof module.exports === "object" ) { - - // For CommonJS and CommonJS-like environments where a proper `window` - // is present, execute the factory and get jQuery. - // For environments that do not have a `window` with a `document` - // (such as Node.js), expose a factory as module.exports. - // This accentuates the need for the creation of a real `window`. - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info. - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } - -// Pass this if window is not defined yet -} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - -// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 -// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode -// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common -// enough that all such attempts are guarded in a try block. -"use strict"; - -var arr = []; - -var getProto = Object.getPrototypeOf; - -var slice = arr.slice; - -var flat = arr.flat ? function( array ) { - return arr.flat.call( array ); -} : function( array ) { - return arr.concat.apply( [], array ); -}; - - -var push = arr.push; - -var indexOf = arr.indexOf; - -var class2type = {}; - -var toString = class2type.toString; - -var hasOwn = class2type.hasOwnProperty; - -var fnToString = hasOwn.toString; - -var ObjectFunctionString = fnToString.call( Object ); - -var support = {}; - -var isFunction = function isFunction( obj ) { - - // Support: Chrome <=57, Firefox <=52 - // In some browsers, typeof returns "function" for HTML elements - // (i.e., `typeof document.createElement( "object" ) === "function"`). - // We don't want to classify *any* DOM node as a function. - return typeof obj === "function" && typeof obj.nodeType !== "number"; - }; - - -var isWindow = function isWindow( obj ) { - return obj != null && obj === obj.window; - }; - - -var document = window.document; - - - - var preservedScriptAttributes = { - type: true, - src: true, - nonce: true, - noModule: true - }; - - function DOMEval( code, node, doc ) { - doc = doc || document; - - var i, val, - script = doc.createElement( "script" ); - - script.text = code; - if ( node ) { - for ( i in preservedScriptAttributes ) { - - // Support: Firefox 64+, Edge 18+ - // Some browsers don't support the "nonce" property on scripts. - // On the other hand, just using `getAttribute` is not enough as - // the `nonce` attribute is reset to an empty string whenever it - // becomes browsing-context connected. - // See https://github.com/whatwg/html/issues/2369 - // See https://html.spec.whatwg.org/#nonce-attributes - // The `node.getAttribute` check was added for the sake of - // `jQuery.globalEval` so that it can fake a nonce-containing node - // via an object. - val = node[ i ] || node.getAttribute && node.getAttribute( i ); - if ( val ) { - script.setAttribute( i, val ); - } - } - } - doc.head.appendChild( script ).parentNode.removeChild( script ); - } - - -function toType( obj ) { - if ( obj == null ) { - return obj + ""; - } - - // Support: Android <=2.3 only (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call( obj ) ] || "object" : - typeof obj; -} -/* global Symbol */ -// Defining this global in .eslintrc.json would create a danger of using the global -// unguarded in another place, it seems safer to define global only for this module - - - -var - version = "3.5.1", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }; - -jQuery.fn = jQuery.prototype = { - - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - - // Return all the elements in a clean array - if ( num == null ) { - return slice.call( this ); - } - - // Return just the one element from the set - return num < 0 ? this[ num + this.length ] : this[ num ]; - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - each: function( callback ) { - return jQuery.each( this, callback ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map( this, function( elem, i ) { - return callback.call( elem, i, elem ); - } ) ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - even: function() { - return this.pushStack( jQuery.grep( this, function( _elem, i ) { - return ( i + 1 ) % 2; - } ) ); - }, - - odd: function() { - return this.pushStack( jQuery.grep( this, function( _elem, i ) { - return i % 2; - } ) ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[ 0 ] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // Skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !isFunction( target ) ) { - target = {}; - } - - // Extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - - // Only deal with non-null/undefined values - if ( ( options = arguments[ i ] ) != null ) { - - // Extend the base object - for ( name in options ) { - copy = options[ name ]; - - // Prevent Object.prototype pollution - // Prevent never-ending loop - if ( name === "__proto__" || target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject( copy ) || - ( copyIsArray = Array.isArray( copy ) ) ) ) { - src = target[ name ]; - - // Ensure proper type for the source value - if ( copyIsArray && !Array.isArray( src ) ) { - clone = []; - } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { - clone = {}; - } else { - clone = src; - } - copyIsArray = false; - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend( { - - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - isPlainObject: function( obj ) { - var proto, Ctor; - - // Detect obvious negatives - // Use toString instead of jQuery.type to catch host objects - if ( !obj || toString.call( obj ) !== "[object Object]" ) { - return false; - } - - proto = getProto( obj ); - - // Objects with no prototype (e.g., `Object.create( null )`) are plain - if ( !proto ) { - return true; - } - - // Objects with prototype are plain iff they were constructed by a global Object function - Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; - return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; - }, - - isEmptyObject: function( obj ) { - var name; - - for ( name in obj ) { - return false; - } - return true; - }, - - // Evaluates a script in a provided context; falls back to the global one - // if not specified. - globalEval: function( code, options, doc ) { - DOMEval( code, { nonce: options && options.nonce }, doc ); - }, - - each: function( obj, callback ) { - var length, i = 0; - - if ( isArrayLike( obj ) ) { - length = obj.length; - for ( ; i < length; i++ ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } else { - for ( i in obj ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } - - return obj; - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArrayLike( Object( arr ) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var length, value, - i = 0, - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArrayLike( elems ) ) { - length = elems.length; - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return flat( ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -} ); - -if ( typeof Symbol === "function" ) { - jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; -} - -// Populate the class2type map -jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), -function( _i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -} ); - -function isArrayLike( obj ) { - - // Support: real iOS 8.2 only (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, - type = toType( obj ); - - if ( isFunction( obj ) || isWindow( obj ) ) { - return false; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.3.5 - * https://sizzlejs.com/ - * - * Copyright JS Foundation and other contributors - * Released under the MIT license - * https://js.foundation/ - * - * Date: 2020-03-14 - */ -( function( window ) { -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - nonnativeSelectorCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // Instance methods - hasOwn = ( {} ).hasOwnProperty, - arr = [], - pop = arr.pop, - pushNative = arr.push, - push = arr.push, - slice = arr.slice, - - // Use a stripped-down indexOf as it's faster than native - // https://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[ i ] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + - "ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - - // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram - identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + - "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - - // "Attribute values must be CSS identifiers [capture 5] - // or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + - whitespace + "*\\]", - - pseudos = ":(" + identifier + ")(?:\\((" + - - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + - whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + - "*" ), - rdescend = new RegExp( whitespace + "|>" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + - whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + - whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + - "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + - "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rhtml = /HTML$/i, - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - - // CSS escapes - // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), - funescape = function( escape, nonHex ) { - var high = "0x" + escape.slice( 1 ) - 0x10000; - - return nonHex ? - - // Strip the backslash prefix from a non-hex escape sequence - nonHex : - - // Replace a hexadecimal escape sequence with the encoded Unicode code point - // Support: IE <=11+ - // For values outside the Basic Multilingual Plane (BMP), manually construct a - // surrogate pair - high < 0 ? - String.fromCharCode( high + 0x10000 ) : - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, - fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { - - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + - ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; - } - - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }, - - inDisabledFieldset = addCombinator( - function( elem ) { - return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; - }, - { dir: "parentNode", next: "legend" } - ); - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - ( arr = slice.call( preferredDoc.childNodes ) ), - preferredDoc.childNodes - ); - - // Support: Android<4.0 - // Detect silently failing push.apply - // eslint-disable-next-line no-unused-expressions - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - pushNative.apply( target, slice.call( els ) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - - // Can't trust NodeList.length - while ( ( target[ j++ ] = els[ i++ ] ) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, match, groups, newSelector, - newContext = context && context.ownerDocument, - - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; - - results = results || []; - - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { - setDocument( context ); - context = context || document; - - if ( documentIsHTML ) { - - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { - - // ID selector - if ( ( m = match[ 1 ] ) ) { - - // Document context - if ( nodeType === 9 ) { - if ( ( elem = context.getElementById( m ) ) ) { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - - // Element context - } else { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && ( elem = newContext.getElementById( m ) ) && - contains( context, elem ) && - elem.id === m ) { - - results.push( elem ); - return results; - } - } - - // Type selector - } else if ( match[ 2 ] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Class selector - } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && - context.getElementsByClassName ) { - - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // Take advantage of querySelectorAll - if ( support.qsa && - !nonnativeSelectorCache[ selector + " " ] && - ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && - - // Support: IE 8 only - // Exclude object elements - ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { - - newSelector = selector; - newContext = context; - - // qSA considers elements outside a scoping root when evaluating child or - // descendant combinators, which is not what we want. - // In such cases, we work around the behavior by prefixing every selector in the - // list with an ID selector referencing the scope context. - // The technique has to be used as well when a leading combinator is used - // as such selectors are not recognized by querySelectorAll. - // Thanks to Andrew Dupont for this technique. - if ( nodeType === 1 && - ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - - // We can use :scope instead of the ID hack if the browser - // supports it & if we're not changing the context. - if ( newContext !== context || !support.scope ) { - - // Capture the context ID, setting it first if necessary - if ( ( nid = context.getAttribute( "id" ) ) ) { - nid = nid.replace( rcssescape, fcssescape ); - } else { - context.setAttribute( "id", ( nid = expando ) ); - } - } - - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - while ( i-- ) { - groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + - toSelector( groups[ i ] ); - } - newSelector = groups.join( "," ); - } - - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - nonnativeSelectorCache( selector, true ); - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return ( cache[ key + " " ] = value ); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created element and returns a boolean result - */ -function assert( fn ) { - var el = document.createElement( "fieldset" ); - - try { - return !!fn( el ); - } catch ( e ) { - return false; - } finally { - - // Remove from its parent by default - if ( el.parentNode ) { - el.parentNode.removeChild( el ); - } - - // release memory in IE - el = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split( "|" ), - i = arr.length; - - while ( i-- ) { - Expr.attrHandle[ arr[ i ] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - a.sourceIndex - b.sourceIndex; - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( ( cur = cur.nextSibling ) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return ( name === "input" || name === "button" ) && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for :enabled/:disabled - * @param {Boolean} disabled true for :disabled; false for :enabled - */ -function createDisabledPseudo( disabled ) { - - // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable - return function( elem ) { - - // Only certain elements can match :enabled or :disabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled - if ( "form" in elem ) { - - // Check for inherited disabledness on relevant non-disabled elements: - // * listed form-associated elements in a disabled fieldset - // https://html.spec.whatwg.org/multipage/forms.html#category-listed - // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled - // * option elements in a disabled optgroup - // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled - // All such elements have a "form" property. - if ( elem.parentNode && elem.disabled === false ) { - - // Option elements defer to a parent optgroup if present - if ( "label" in elem ) { - if ( "label" in elem.parentNode ) { - return elem.parentNode.disabled === disabled; - } else { - return elem.disabled === disabled; - } - } - - // Support: IE 6 - 11 - // Use the isDisabled shortcut property to check for disabled fieldset ancestors - return elem.isDisabled === disabled || - - // Where there is no isDisabled, check manually - /* jshint -W018 */ - elem.isDisabled !== !disabled && - inDisabledFieldset( elem ) === disabled; - } - - return elem.disabled === disabled; - - // Try to winnow out elements that can't be disabled before trusting the disabled property. - // Some victims get caught in our net (label, legend, menu, track), but it shouldn't - // even exist on them, let alone have a boolean value. - } else if ( "label" in elem ) { - return elem.disabled === disabled; - } - - // Remaining elements are neither :enabled nor :disabled - return false; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction( function( argument ) { - argument = +argument; - return markFunction( function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ ( j = matchIndexes[ i ] ) ] ) { - seed[ j ] = !( matches[ j ] = seed[ j ] ); - } - } - } ); - } ); -} - -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - var namespace = elem.namespaceURI, - docElem = ( elem.ownerDocument || elem ).documentElement; - - // Support: IE <=8 - // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes - // https://bugs.jquery.com/ticket/4833 - return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); -}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, subWindow, - doc = node ? node.ownerDocument || node : preferredDoc; - - // Return early if doc is invalid or already selected - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Update global variables - document = doc; - docElem = document.documentElement; - documentIsHTML = !isXML( document ); - - // Support: IE 9 - 11+, Edge 12 - 18+ - // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( preferredDoc != document && - ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { - - // Support: IE 11, Edge - if ( subWindow.addEventListener ) { - subWindow.addEventListener( "unload", unloadHandler, false ); - - // Support: IE 9 - 10 only - } else if ( subWindow.attachEvent ) { - subWindow.attachEvent( "onunload", unloadHandler ); - } - } - - // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, - // Safari 4 - 5 only, Opera <=11.6 - 12.x only - // IE/Edge & older browsers don't support the :scope pseudo-class. - // Support: Safari 6.0 only - // Safari 6.0 supports :scope but it's an alias of :root there. - support.scope = assert( function( el ) { - docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); - return typeof el.querySelectorAll !== "undefined" && - !el.querySelectorAll( ":scope fieldset div" ).length; - } ); - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert( function( el ) { - el.className = "i"; - return !el.getAttribute( "className" ); - } ); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert( function( el ) { - el.appendChild( document.createComment( "" ) ); - return !el.getElementsByTagName( "*" ).length; - } ); - - // Support: IE<9 - support.getElementsByClassName = rnative.test( document.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programmatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert( function( el ) { - docElem.appendChild( el ).id = expando; - return !document.getElementsByName || !document.getElementsByName( expando ).length; - } ); - - // ID filter and find - if ( support.getById ) { - Expr.filter[ "ID" ] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute( "id" ) === attrId; - }; - }; - Expr.find[ "ID" ] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var elem = context.getElementById( id ); - return elem ? [ elem ] : []; - } - }; - } else { - Expr.filter[ "ID" ] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode( "id" ); - return node && node.value === attrId; - }; - }; - - // Support: IE 6 - 7 only - // getElementById is not reliable as a find shortcut - Expr.find[ "ID" ] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var node, i, elems, - elem = context.getElementById( id ); - - if ( elem ) { - - // Verify the id attribute - node = elem.getAttributeNode( "id" ); - if ( node && node.value === id ) { - return [ elem ]; - } - - // Fall back on getElementsByName - elems = context.getElementsByName( id ); - i = 0; - while ( ( elem = elems[ i++ ] ) ) { - node = elem.getAttributeNode( "id" ); - if ( node && node.value === id ) { - return [ elem ]; - } - } - } - - return []; - } - }; - } - - // Tag - Expr.find[ "TAG" ] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); - - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( ( elem = results[ i++ ] ) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See https://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert( function( el ) { - - var input; - - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // https://bugs.jquery.com/ticket/12359 - docElem.appendChild( el ).innerHTML = "" + - ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !el.querySelectorAll( "[selected]" ).length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ - if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push( "~=" ); - } - - // Support: IE 11+, Edge 15 - 18+ - // IE 11/Edge don't find elements on a `[name='']` query in some cases. - // Adding a temporary attribute to the document before the selection works - // around the issue. - // Interestingly, IE 10 & older don't seem to have the issue. - input = document.createElement( "input" ); - input.setAttribute( "name", "" ); - el.appendChild( input ); - if ( !el.querySelectorAll( "[name='']" ).length ) { - rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + - whitespace + "*(?:''|\"\")" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !el.querySelectorAll( ":checked" ).length ) { - rbuggyQSA.push( ":checked" ); - } - - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibling-combinator selector` fails - if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push( ".#.+[+~]" ); - } - - // Support: Firefox <=3.6 - 5 only - // Old Firefox doesn't throw on a badly-escaped identifier. - el.querySelectorAll( "\\\f" ); - rbuggyQSA.push( "[\\r\\n\\f]" ); - } ); - - assert( function( el ) { - el.innerHTML = "" + - ""; - - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement( "input" ); - input.setAttribute( "type", "hidden" ); - el.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( el.querySelectorAll( "[name=d]" ).length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Support: IE9-11+ - // IE's :disabled selector does not pick up the children of disabled fieldsets - docElem.appendChild( el ).disabled = true; - if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Support: Opera 10 - 11 only - // Opera 10-11 does not throw on post-comma invalid pseudos - el.querySelectorAll( "*,:x" ); - rbuggyQSA.push( ",.*:" ); - } ); - } - - if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector ) ) ) ) { - - assert( function( el ) { - - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( el, "*" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( el, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - } ); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully self-exclusive - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - ) ); - } : - function( a, b ) { - if ( b ) { - while ( ( b = b.parentNode ) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { - - // Choose the first element that is related to our preferred document - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( a == document || a.ownerDocument == preferredDoc && - contains( preferredDoc, a ) ) { - return -1; - } - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( b == document || b.ownerDocument == preferredDoc && - contains( preferredDoc, b ) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - /* eslint-disable eqeqeq */ - return a == document ? -1 : - b == document ? 1 : - /* eslint-enable eqeqeq */ - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( ( cur = cur.parentNode ) ) { - ap.unshift( cur ); - } - cur = b; - while ( ( cur = cur.parentNode ) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[ i ] === bp[ i ] ) { - i++; - } - - return i ? - - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[ i ], bp[ i ] ) : - - // Otherwise nodes in our document sort first - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - /* eslint-disable eqeqeq */ - ap[ i ] == preferredDoc ? -1 : - bp[ i ] == preferredDoc ? 1 : - /* eslint-enable eqeqeq */ - 0; - }; - - return document; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - setDocument( elem ); - - if ( support.matchesSelector && documentIsHTML && - !nonnativeSelectorCache[ expr + " " ] && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch ( e ) { - nonnativeSelectorCache( expr, true ); - } - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; - -Sizzle.contains = function( context, elem ) { - - // Set document vars if needed - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( ( context.ownerDocument || context ) != document ) { - setDocument( context ); - } - return contains( context, elem ); -}; - -Sizzle.attr = function( elem, name ) { - - // Set document vars if needed - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( ( elem.ownerDocument || elem ) != document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - ( val = elem.getAttributeNode( name ) ) && val.specified ? - val.value : - null; -}; - -Sizzle.escape = function( sel ) { - return ( sel + "" ).replace( rcssescape, fcssescape ); -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( ( elem = results[ i++ ] ) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; -}; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - - // If no nodeType, this is expected to be an array - while ( ( node = elem[ i++ ] ) ) { - - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - - // Do not include comment or processing instruction nodes - - return ret; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[ 1 ] = match[ 1 ].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[ 3 ] = ( match[ 3 ] || match[ 4 ] || - match[ 5 ] || "" ).replace( runescape, funescape ); - - if ( match[ 2 ] === "~=" ) { - match[ 3 ] = " " + match[ 3 ] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[ 1 ] = match[ 1 ].toLowerCase(); - - if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { - - // nth-* requires argument - if ( !match[ 3 ] ) { - Sizzle.error( match[ 0 ] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[ 4 ] = +( match[ 4 ] ? - match[ 5 ] + ( match[ 6 ] || 1 ) : - 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); - match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); - - // other types prohibit arguments - } else if ( match[ 3 ] ) { - Sizzle.error( match[ 0 ] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[ 6 ] && match[ 2 ]; - - if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[ 3 ] ) { - match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - - // Get excess from tokenize (recursively) - ( excess = tokenize( unquoted, true ) ) && - - // advance to the next closing parenthesis - ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { - - // excess is a negative index - match[ 0 ] = match[ 0 ].slice( 0, excess ); - match[ 2 ] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { - return true; - } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - ( pattern = new RegExp( "(^|" + whitespace + - ")" + className + "(" + whitespace + "|$)" ) ) && classCache( - className, function( elem ) { - return pattern.test( - typeof elem.className === "string" && elem.className || - typeof elem.getAttribute !== "undefined" && - elem.getAttribute( "class" ) || - "" - ); - } ); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - /* eslint-disable max-len */ - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - /* eslint-enable max-len */ - - }; - }, - - "CHILD": function( type, what, _argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, _context, xml ) { - var cache, uniqueCache, outerCache, node, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType, - diff = false; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( ( node = node[ dir ] ) ) { - if ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) { - - return false; - } - } - - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - - // Seek `elem` from a previously-cached index - - // ...in a gzip-friendly way - node = parent; - outerCache = node[ expando ] || ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex && cache[ 2 ]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( ( node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - ( diff = nodeIndex = 0 ) || start.pop() ) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - } else { - - // Use previously-cached element index if available - if ( useCache ) { - - // ...in a gzip-friendly way - node = elem; - outerCache = node[ expando ] || ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex; - } - - // xml :nth-child(...) - // or :nth-last-child(...) or :nth(-last)?-of-type(...) - if ( diff === false ) { - - // Use the same loop as above to seek `elem` from the start - while ( ( node = ++nodeIndex && node && node[ dir ] || - ( diff = nodeIndex = 0 ) || start.pop() ) ) { - - if ( ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) && - ++diff ) { - - // Cache the index of each encountered element - if ( useCache ) { - outerCache = node[ expando ] || - ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - uniqueCache[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction( function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf( seed, matched[ i ] ); - seed[ idx ] = !( matches[ idx ] = matched[ i ] ); - } - } ) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - - // Potentially complex pseudos - "not": markFunction( function( selector ) { - - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction( function( seed, matches, _context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( ( elem = unmatched[ i ] ) ) { - seed[ i ] = !( matches[ i ] = elem ); - } - } - } ) : - function( elem, _context, xml ) { - input[ 0 ] = elem; - matcher( input, null, xml, results ); - - // Don't keep the element (issue #299) - input[ 0 ] = null; - return !results.pop(); - }; - } ), - - "has": markFunction( function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - } ), - - "contains": markFunction( function( text ) { - text = text.replace( runescape, funescape ); - return function( elem ) { - return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; - }; - } ), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - - // lang value must be a valid identifier - if ( !ridentifier.test( lang || "" ) ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( ( elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); - return false; - }; - } ), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && - ( !document.hasFocus || document.hasFocus() ) && - !!( elem.type || elem.href || ~elem.tabIndex ); - }, - - // Boolean properties - "enabled": createDisabledPseudo( false ), - "disabled": createDisabledPseudo( true ), - - "checked": function( elem ) { - - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return ( nodeName === "input" && !!elem.checked ) || - ( nodeName === "option" && !!elem.selected ); - }, - - "selected": function( elem ) { - - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - // eslint-disable-next-line no-unused-expressions - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos[ "empty" ]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( ( attr = elem.getAttribute( "type" ) ) == null || - attr.toLowerCase() === "text" ); - }, - - // Position-in-collection - "first": createPositionalPseudo( function() { - return [ 0 ]; - } ), - - "last": createPositionalPseudo( function( _matchIndexes, length ) { - return [ length - 1 ]; - } ), - - "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - } ), - - "even": createPositionalPseudo( function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - } ), - - "odd": createPositionalPseudo( function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - } ), - - "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { - var i = argument < 0 ? - argument + length : - argument > length ? - length : - argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - } ), - - "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - } ) - } -}; - -Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; - -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} - -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); - -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || ( match = rcomma.exec( soFar ) ) ) { - if ( match ) { - - // Don't consume trailing commas as valid - soFar = soFar.slice( match[ 0 ].length ) || soFar; - } - groups.push( ( tokens = [] ) ); - } - - matched = false; - - // Combinators - if ( ( match = rcombinators.exec( soFar ) ) ) { - matched = match.shift(); - tokens.push( { - value: matched, - - // Cast descendant combinators to space - type: match[ 0 ].replace( rtrim, " " ) - } ); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || - ( match = preFilters[ type ]( match ) ) ) ) { - matched = match.shift(); - tokens.push( { - value: matched, - type: type, - matches: match - } ); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; - -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[ i ].value; - } - return selector; -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - skip = combinator.next, - key = skip || dir, - checkNonElements = base && key === "parentNode", - doneName = done++; - - return combinator.first ? - - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( ( elem = elem[ dir ] ) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - return false; - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, uniqueCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching - if ( xml ) { - while ( ( elem = elem[ dir ] ) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( ( elem = elem[ dir ] ) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || ( elem[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || - ( outerCache[ elem.uniqueID ] = {} ); - - if ( skip && skip === elem.nodeName.toLowerCase() ) { - elem = elem[ dir ] || elem; - } else if ( ( oldCache = uniqueCache[ key ] ) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return ( newCache[ 2 ] = oldCache[ 2 ] ); - } else { - - // Reuse newcache so results back-propagate to previous elements - uniqueCache[ key ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { - return true; - } - } - } - } - } - return false; - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[ i ]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[ 0 ]; -} - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[ i ], results ); - } - return results; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( ( elem = unmatched[ i ] ) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction( function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( - selector || "*", - context.nodeType ? [ context ] : context, - [] - ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( ( elem = temp[ i ] ) ) { - matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( ( elem = matcherOut[ i ] ) ) { - - // Restore matcherIn since elem is not yet a final match - temp.push( ( matcherIn[ i ] = elem ) ); - } - } - postFinder( null, ( matcherOut = [] ), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( ( elem = matcherOut[ i ] ) && - ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { - - seed[ temp ] = !( results[ temp ] = elem ); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - } ); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[ 0 ].type ], - implicitRelative = leadingRelative || Expr.relative[ " " ], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - ( checkContext = context ).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - - // Avoid hanging onto element (issue #299) - checkContext = null; - return ret; - } ]; - - for ( ; i < len; i++ ) { - if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { - matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; - } else { - matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[ j ].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens - .slice( 0, i - 1 ) - .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), - - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), - len = elems.length; - - if ( outermost ) { - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - outermostContext = context == document || context || outermost; - } - - // Add elements passing elementMatchers directly to results - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( !context && elem.ownerDocument != document ) { - setDocument( elem ); - xml = !documentIsHTML; - } - while ( ( matcher = elementMatchers[ j++ ] ) ) { - if ( matcher( elem, context || document, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - - // They will have gone through all possible matchers - if ( ( elem = !matcher && elem ) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // `i` is now the count of elements visited above, and adding it to `matchedCount` - // makes the latter nonnegative. - matchedCount += i; - - // Apply set filters to unmatched elements - // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` - // equals `i`), unless we didn't visit _any_ elements in the above loop because we have - // no element matchers and no seed. - // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that - // case, which will result in a "00" `matchedCount` that differs from `i` but is also - // numerically zero. - if ( bySet && i !== matchedCount ) { - j = 0; - while ( ( matcher = setMatchers[ j++ ] ) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !( unmatched[ i ] || setMatched[ i ] ) ) { - setMatched[ i ] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[ i ] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( - selector, - matcherFromGroupMatchers( elementMatchers, setMatchers ) - ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( ( selector = compiled.selector || selector ) ); - - results = results || []; - - // Try to minimize operations if there is only one selector in the list and no seed - // (the latter of which guarantees us context) - if ( match.length === 1 ) { - - // Reduce context if the leading compound selector is an ID - tokens = match[ 0 ] = match[ 0 ].slice( 0 ); - if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && - context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { - - context = ( Expr.find[ "ID" ]( token.matches[ 0 ] - .replace( runescape, funescape ), context ) || [] )[ 0 ]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[ i ]; - - // Abort if we hit a combinator - if ( Expr.relative[ ( type = token.type ) ] ) { - break; - } - if ( ( find = Expr.find[ type ] ) ) { - - // Search, expanding context for leading sibling combinators - if ( ( seed = find( - token.matches[ 0 ].replace( runescape, funescape ), - rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || - context - ) ) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - !context || rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; - -// One-time assignments - -// Sort stability -support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; - -// Support: Chrome 14-35+ -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert( function( el ) { - - // Should return 1, but returns 4 (following) - return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; -} ); - -// Support: IE<8 -// Prevent attribute/property "interpolation" -// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert( function( el ) { - el.innerHTML = ""; - return el.firstChild.getAttribute( "href" ) === "#"; -} ) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - } ); -} - -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert( function( el ) { - el.innerHTML = ""; - el.firstChild.setAttribute( "value", "" ); - return el.firstChild.getAttribute( "value" ) === ""; -} ) ) { - addHandle( "value", function( elem, _name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - } ); -} - -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert( function( el ) { - return el.getAttribute( "disabled" ) == null; -} ) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - ( val = elem.getAttributeNode( name ) ) && val.specified ? - val.value : - null; - } - } ); -} - -return Sizzle; - -} )( window ); - - - -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; - -// Deprecated -jQuery.expr[ ":" ] = jQuery.expr.pseudos; -jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; -jQuery.escapeSelector = Sizzle.escape; - - - - -var dir = function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; -}; - - -var siblings = function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; -}; - - -var rneedsContext = jQuery.expr.match.needsContext; - - - -function nodeName( elem, name ) { - - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - -}; -var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); - - - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - return !!qualifier.call( elem, i, elem ) !== not; - } ); - } - - // Single element - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - } ); - } - - // Arraylike of elements (jQuery, arguments, Array) - if ( typeof qualifier !== "string" ) { - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) > -1 ) !== not; - } ); - } - - // Filtered directly for both simple and complex selectors - return jQuery.filter( qualifier, elements, not ); -} - -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - if ( elems.length === 1 && elem.nodeType === 1 ) { - return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; - } - - return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - } ) ); -}; - -jQuery.fn.extend( { - find: function( selector ) { - var i, ret, - len = this.length, - self = this; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter( function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - } ) ); - } - - ret = this.pushStack( [] ); - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - return len > 1 ? jQuery.uniqueSort( ret ) : ret; - }, - filter: function( selector ) { - return this.pushStack( winnow( this, selector || [], false ) ); - }, - not: function( selector ) { - return this.pushStack( winnow( this, selector || [], true ) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -} ); - - -// Initialize a jQuery object - - -// A central reference to the root jQuery(document) -var rootjQuery, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - // Shortcut simple #id case for speed - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, - - init = jQuery.fn.init = function( selector, context, root ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Method init() accepts an alternate rootjQuery - // so migrate can support jQuery.sub (gh-2101) - root = root || rootjQuery; - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[ 0 ] === "<" && - selector[ selector.length - 1 ] === ">" && - selector.length >= 3 ) { - - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && ( match[ 1 ] || !context ) ) { - - // HANDLE: $(html) -> $(array) - if ( match[ 1 ] ) { - context = context instanceof jQuery ? context[ 0 ] : context; - - // Option to run scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[ 1 ], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - - // Properties of context are called as methods if possible - if ( isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[ 2 ] ); - - if ( elem ) { - - // Inject the element directly into the jQuery object - this[ 0 ] = elem; - this.length = 1; - } - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || root ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this[ 0 ] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( isFunction( selector ) ) { - return root.ready !== undefined ? - root.ready( selector ) : - - // Execute immediately if ready is not present - selector( jQuery ); - } - - return jQuery.makeArray( selector, this ); - }; - -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; - -// Initialize central reference -rootjQuery = jQuery( document ); - - -var rparentsprev = /^(?:parents|prev(?:Until|All))/, - - // Methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend( { - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; - - return this.filter( function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[ i ] ) ) { - return true; - } - } - } ); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - targets = typeof selectors !== "string" && jQuery( selectors ); - - // Positional selectors never match, since there's no _selection_ context - if ( !rneedsContext.test( selectors ) ) { - for ( ; i < l; i++ ) { - for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { - - // Always skip document fragments - if ( cur.nodeType < 11 && ( targets ? - targets.index( cur ) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector( cur, selectors ) ) ) { - - matched.push( cur ); - break; - } - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); - }, - - // Determine the position of an element within the set - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // Index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); - } - - // Locate the position of the desired element - return indexOf.call( this, - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.uniqueSort( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - } -} ); - -function sibling( cur, dir ) { - while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} - return cur; -} - -jQuery.each( { - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, _i, until ) { - return dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, _i, until ) { - return dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, _i, until ) { - return dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return siblings( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return siblings( elem.firstChild ); - }, - contents: function( elem ) { - if ( elem.contentDocument != null && - - // Support: IE 11+ - // elements with no `data` attribute has an object - // `contentDocument` with a `null` prototype. - getProto( elem.contentDocument ) ) { - - return elem.contentDocument; - } - - // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only - // Treat the template element as a regular one in browsers that - // don't support it. - if ( nodeName( elem, "template" ) ) { - elem = elem.content || elem; - } - - return jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); - } - - if ( this.length > 1 ) { - - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.uniqueSort( matched ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); - } - } - - return this.pushStack( matched ); - }; -} ); -var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); - - - -// Convert String-formatted options into Object-formatted ones -function createOptions( options ) { - var object = {}; - jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { - object[ flag ] = true; - } ); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - createOptions( options ) : - jQuery.extend( {}, options ); - - var // Flag to know if list is currently firing - firing, - - // Last fire value for non-forgettable lists - memory, - - // Flag to know if list was already fired - fired, - - // Flag to prevent firing - locked, - - // Actual callback list - list = [], - - // Queue of execution data for repeatable lists - queue = [], - - // Index of currently firing callback (modified by add/remove as needed) - firingIndex = -1, - - // Fire callbacks - fire = function() { - - // Enforce single-firing - locked = locked || options.once; - - // Execute callbacks for all pending executions, - // respecting firingIndex overrides and runtime changes - fired = firing = true; - for ( ; queue.length; firingIndex = -1 ) { - memory = queue.shift(); - while ( ++firingIndex < list.length ) { - - // Run callback and check for early termination - if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && - options.stopOnFalse ) { - - // Jump to end and forget the data so .add doesn't re-fire - firingIndex = list.length; - memory = false; - } - } - } - - // Forget the data if we're done with it - if ( !options.memory ) { - memory = false; - } - - firing = false; - - // Clean up if we're done firing for good - if ( locked ) { - - // Keep an empty list if we have data for future add calls - if ( memory ) { - list = []; - - // Otherwise, this object is spent - } else { - list = ""; - } - } - }, - - // Actual Callbacks object - self = { - - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - - // If we have memory from a past run, we should fire after adding - if ( memory && !firing ) { - firingIndex = list.length - 1; - queue.push( memory ); - } - - ( function add( args ) { - jQuery.each( args, function( _, arg ) { - if ( isFunction( arg ) ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && toType( arg ) !== "string" ) { - - // Inspect recursively - add( arg ); - } - } ); - } )( arguments ); - - if ( memory && !firing ) { - fire(); - } - } - return this; - }, - - // Remove a callback from the list - remove: function() { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - - // Handle firing indexes - if ( index <= firingIndex ) { - firingIndex--; - } - } - } ); - return this; - }, - - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? - jQuery.inArray( fn, list ) > -1 : - list.length > 0; - }, - - // Remove all callbacks from the list - empty: function() { - if ( list ) { - list = []; - } - return this; - }, - - // Disable .fire and .add - // Abort any current/pending executions - // Clear all callbacks and values - disable: function() { - locked = queue = []; - list = memory = ""; - return this; - }, - disabled: function() { - return !list; - }, - - // Disable .fire - // Also disable .add unless we have memory (since it would have no effect) - // Abort any pending executions - lock: function() { - locked = queue = []; - if ( !memory && !firing ) { - list = memory = ""; - } - return this; - }, - locked: function() { - return !!locked; - }, - - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( !locked ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - queue.push( args ); - if ( !firing ) { - fire(); - } - } - return this; - }, - - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; - - -function Identity( v ) { - return v; -} -function Thrower( ex ) { - throw ex; -} - -function adoptValue( value, resolve, reject, noValue ) { - var method; - - try { - - // Check for promise aspect first to privilege synchronous behavior - if ( value && isFunction( ( method = value.promise ) ) ) { - method.call( value ).done( resolve ).fail( reject ); - - // Other thenables - } else if ( value && isFunction( ( method = value.then ) ) ) { - method.call( value, resolve, reject ); - - // Other non-thenables - } else { - - // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: - // * false: [ value ].slice( 0 ) => resolve( value ) - // * true: [ value ].slice( 1 ) => resolve() - resolve.apply( undefined, [ value ].slice( noValue ) ); - } - - // For Promises/A+, convert exceptions into rejections - // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in - // Deferred#then to conditionally suppress rejection. - } catch ( value ) { - - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - reject.apply( undefined, [ value ] ); - } -} - -jQuery.extend( { - - Deferred: function( func ) { - var tuples = [ - - // action, add listener, callbacks, - // ... .then handlers, argument index, [final state] - [ "notify", "progress", jQuery.Callbacks( "memory" ), - jQuery.Callbacks( "memory" ), 2 ], - [ "resolve", "done", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 0, "resolved" ], - [ "reject", "fail", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 1, "rejected" ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - "catch": function( fn ) { - return promise.then( null, fn ); - }, - - // Keep pipe for back-compat - pipe: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - - return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( _i, tuple ) { - - // Map tuples (progress, done, fail) to arguments (done, fail, progress) - var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; - - // deferred.progress(function() { bind to newDefer or newDefer.notify }) - // deferred.done(function() { bind to newDefer or newDefer.resolve }) - // deferred.fail(function() { bind to newDefer or newDefer.reject }) - deferred[ tuple[ 1 ] ]( function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && isFunction( returned.promise ) ) { - returned.promise() - .progress( newDefer.notify ) - .done( newDefer.resolve ) - .fail( newDefer.reject ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( - this, - fn ? [ returned ] : arguments - ); - } - } ); - } ); - fns = null; - } ).promise(); - }, - then: function( onFulfilled, onRejected, onProgress ) { - var maxDepth = 0; - function resolve( depth, deferred, handler, special ) { - return function() { - var that = this, - args = arguments, - mightThrow = function() { - var returned, then; - - // Support: Promises/A+ section 2.3.3.3.3 - // https://promisesaplus.com/#point-59 - // Ignore double-resolution attempts - if ( depth < maxDepth ) { - return; - } - - returned = handler.apply( that, args ); - - // Support: Promises/A+ section 2.3.1 - // https://promisesaplus.com/#point-48 - if ( returned === deferred.promise() ) { - throw new TypeError( "Thenable self-resolution" ); - } - - // Support: Promises/A+ sections 2.3.3.1, 3.5 - // https://promisesaplus.com/#point-54 - // https://promisesaplus.com/#point-75 - // Retrieve `then` only once - then = returned && - - // Support: Promises/A+ section 2.3.4 - // https://promisesaplus.com/#point-64 - // Only check objects and functions for thenability - ( typeof returned === "object" || - typeof returned === "function" ) && - returned.then; - - // Handle a returned thenable - if ( isFunction( then ) ) { - - // Special processors (notify) just wait for resolution - if ( special ) { - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ) - ); - - // Normal processors (resolve) also hook into progress - } else { - - // ...and disregard older resolution values - maxDepth++; - - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ), - resolve( maxDepth, deferred, Identity, - deferred.notifyWith ) - ); - } - - // Handle all other returned values - } else { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Identity ) { - that = undefined; - args = [ returned ]; - } - - // Process the value(s) - // Default process is resolve - ( special || deferred.resolveWith )( that, args ); - } - }, - - // Only normal processors (resolve) catch and reject exceptions - process = special ? - mightThrow : - function() { - try { - mightThrow(); - } catch ( e ) { - - if ( jQuery.Deferred.exceptionHook ) { - jQuery.Deferred.exceptionHook( e, - process.stackTrace ); - } - - // Support: Promises/A+ section 2.3.3.3.4.1 - // https://promisesaplus.com/#point-61 - // Ignore post-resolution exceptions - if ( depth + 1 >= maxDepth ) { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Thrower ) { - that = undefined; - args = [ e ]; - } - - deferred.rejectWith( that, args ); - } - } - }; - - // Support: Promises/A+ section 2.3.3.3.1 - // https://promisesaplus.com/#point-57 - // Re-resolve promises immediately to dodge false rejection from - // subsequent errors - if ( depth ) { - process(); - } else { - - // Call an optional hook to record the stack, in case of exception - // since it's otherwise lost when execution goes async - if ( jQuery.Deferred.getStackHook ) { - process.stackTrace = jQuery.Deferred.getStackHook(); - } - window.setTimeout( process ); - } - }; - } - - return jQuery.Deferred( function( newDefer ) { - - // progress_handlers.add( ... ) - tuples[ 0 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onProgress ) ? - onProgress : - Identity, - newDefer.notifyWith - ) - ); - - // fulfilled_handlers.add( ... ) - tuples[ 1 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onFulfilled ) ? - onFulfilled : - Identity - ) - ); - - // rejected_handlers.add( ... ) - tuples[ 2 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onRejected ) ? - onRejected : - Thrower - ) - ); - } ).promise(); - }, - - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 5 ]; - - // promise.progress = list.add - // promise.done = list.add - // promise.fail = list.add - promise[ tuple[ 1 ] ] = list.add; - - // Handle state - if ( stateString ) { - list.add( - function() { - - // state = "resolved" (i.e., fulfilled) - // state = "rejected" - state = stateString; - }, - - // rejected_callbacks.disable - // fulfilled_callbacks.disable - tuples[ 3 - i ][ 2 ].disable, - - // rejected_handlers.disable - // fulfilled_handlers.disable - tuples[ 3 - i ][ 3 ].disable, - - // progress_callbacks.lock - tuples[ 0 ][ 2 ].lock, - - // progress_handlers.lock - tuples[ 0 ][ 3 ].lock - ); - } - - // progress_handlers.fire - // fulfilled_handlers.fire - // rejected_handlers.fire - list.add( tuple[ 3 ].fire ); - - // deferred.notify = function() { deferred.notifyWith(...) } - // deferred.resolve = function() { deferred.resolveWith(...) } - // deferred.reject = function() { deferred.rejectWith(...) } - deferred[ tuple[ 0 ] ] = function() { - deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); - return this; - }; - - // deferred.notifyWith = list.fireWith - // deferred.resolveWith = list.fireWith - // deferred.rejectWith = list.fireWith - deferred[ tuple[ 0 ] + "With" ] = list.fireWith; - } ); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( singleValue ) { - var - - // count of uncompleted subordinates - remaining = arguments.length, - - // count of unprocessed arguments - i = remaining, - - // subordinate fulfillment data - resolveContexts = Array( i ), - resolveValues = slice.call( arguments ), - - // the master Deferred - master = jQuery.Deferred(), - - // subordinate callback factory - updateFunc = function( i ) { - return function( value ) { - resolveContexts[ i ] = this; - resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( !( --remaining ) ) { - master.resolveWith( resolveContexts, resolveValues ); - } - }; - }; - - // Single- and empty arguments are adopted like Promise.resolve - if ( remaining <= 1 ) { - adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, - !remaining ); - - // Use .then() to unwrap secondary thenables (cf. gh-3000) - if ( master.state() === "pending" || - isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { - - return master.then(); - } - } - - // Multiple arguments are aggregated like Promise.all array elements - while ( i-- ) { - adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); - } - - return master.promise(); - } -} ); - - -// These usually indicate a programmer mistake during development, -// warn about them ASAP rather than swallowing them by default. -var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; - -jQuery.Deferred.exceptionHook = function( error, stack ) { - - // Support: IE 8 - 9 only - // Console exists when dev tools are open, which can happen at any time - if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { - window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); - } -}; - - - - -jQuery.readyException = function( error ) { - window.setTimeout( function() { - throw error; - } ); -}; - - - - -// The deferred used on DOM ready -var readyList = jQuery.Deferred(); - -jQuery.fn.ready = function( fn ) { - - readyList - .then( fn ) - - // Wrap jQuery.readyException in a function so that the lookup - // happens at the time of error handling instead of callback - // registration. - .catch( function( error ) { - jQuery.readyException( error ); - } ); - - return this; -}; - -jQuery.extend( { - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - } -} ); - -jQuery.ready.then = readyList.then; - -// The ready event handler and self cleanup method -function completed() { - document.removeEventListener( "DOMContentLoaded", completed ); - window.removeEventListener( "load", completed ); - jQuery.ready(); -} - -// Catch cases where $(document).ready() is called -// after the browser event has already occurred. -// Support: IE <=9 - 10 only -// Older IE sometimes signals "interactive" too soon -if ( document.readyState === "complete" || - ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { - - // Handle it asynchronously to allow scripts the opportunity to delay ready - window.setTimeout( jQuery.ready ); - -} else { - - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed ); -} - - - - -// Multifunctional method to get and set values of a collection -// The value/s can optionally be executed if it's a function -var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; - - // Sets many values - if ( toType( key ) === "object" ) { - chainable = true; - for ( i in key ) { - access( elems, fn, i, key[ i ], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, _key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < len; i++ ) { - fn( - elems[ i ], key, raw ? - value : - value.call( elems[ i ], i, fn( elems[ i ], key ) ) - ); - } - } - } - - if ( chainable ) { - return elems; - } - - // Gets - if ( bulk ) { - return fn.call( elems ); - } - - return len ? fn( elems[ 0 ], key ) : emptyGet; -}; - - -// Matches dashed string for camelizing -var rmsPrefix = /^-ms-/, - rdashAlpha = /-([a-z])/g; - -// Used by camelCase as callback to replace() -function fcamelCase( _all, letter ) { - return letter.toUpperCase(); -} - -// Convert dashed to camelCase; used by the css and data modules -// Support: IE <=9 - 11, Edge 12 - 15 -// Microsoft forgot to hump their vendor prefix (#9572) -function camelCase( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); -} -var acceptData = function( owner ) { - - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); -}; - - - - -function Data() { - this.expando = jQuery.expando + Data.uid++; -} - -Data.uid = 1; - -Data.prototype = { - - cache: function( owner ) { - - // Check if the owner object already has a cache - var value = owner[ this.expando ]; - - // If not, create one - if ( !value ) { - value = {}; - - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return an empty object. - if ( acceptData( owner ) ) { - - // If it is a node unlikely to be stringify-ed or looped over - // use plain assignment - if ( owner.nodeType ) { - owner[ this.expando ] = value; - - // Otherwise secure it in a non-enumerable property - // configurable must be true to allow the property to be - // deleted when data is removed - } else { - Object.defineProperty( owner, this.expando, { - value: value, - configurable: true - } ); - } - } - } - - return value; - }, - set: function( owner, data, value ) { - var prop, - cache = this.cache( owner ); - - // Handle: [ owner, key, value ] args - // Always use camelCase key (gh-2257) - if ( typeof data === "string" ) { - cache[ camelCase( data ) ] = value; - - // Handle: [ owner, { properties } ] args - } else { - - // Copy the properties one-by-one to the cache object - for ( prop in data ) { - cache[ camelCase( prop ) ] = data[ prop ]; - } - } - return cache; - }, - get: function( owner, key ) { - return key === undefined ? - this.cache( owner ) : - - // Always use camelCase key (gh-2257) - owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; - }, - access: function( owner, key, value ) { - - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ( ( key && typeof key === "string" ) && value === undefined ) ) { - - return this.get( owner, key ); - } - - // When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); - - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, - cache = owner[ this.expando ]; - - if ( cache === undefined ) { - return; - } - - if ( key !== undefined ) { - - // Support array or space separated string of keys - if ( Array.isArray( key ) ) { - - // If key is an array of keys... - // We always set camelCase keys, so remove that. - key = key.map( camelCase ); - } else { - key = camelCase( key ); - - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - key = key in cache ? - [ key ] : - ( key.match( rnothtmlwhite ) || [] ); - } - - i = key.length; - - while ( i-- ) { - delete cache[ key[ i ] ]; - } - } - - // Remove the expando if there's no more data - if ( key === undefined || jQuery.isEmptyObject( cache ) ) { - - // Support: Chrome <=35 - 45 - // Webkit & Blink performance suffers when deleting properties - // from DOM nodes, so set to undefined instead - // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) - if ( owner.nodeType ) { - owner[ this.expando ] = undefined; - } else { - delete owner[ this.expando ]; - } - } - }, - hasData: function( owner ) { - var cache = owner[ this.expando ]; - return cache !== undefined && !jQuery.isEmptyObject( cache ); - } -}; -var dataPriv = new Data(); - -var dataUser = new Data(); - - - -// Implementation Summary -// -// 1. Enforce API surface and semantic compatibility with 1.9.x branch -// 2. Improve the module's maintainability by reducing the storage -// paths to a single mechanism. -// 3. Use the same single mechanism to support "private" and "user" data. -// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) -// 5. Avoid exposing implementation details on user objects (eg. expando properties) -// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 - -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /[A-Z]/g; - -function getData( data ) { - if ( data === "true" ) { - return true; - } - - if ( data === "false" ) { - return false; - } - - if ( data === "null" ) { - return null; - } - - // Only convert to a number if it doesn't change the string - if ( data === +data + "" ) { - return +data; - } - - if ( rbrace.test( data ) ) { - return JSON.parse( data ); - } - - return data; -} - -function dataAttr( elem, key, data ) { - var name; - - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = getData( data ); - } catch ( e ) {} - - // Make sure we set the data so it isn't changed later - dataUser.set( elem, key, data ); - } else { - data = undefined; - } - } - return data; -} - -jQuery.extend( { - hasData: function( elem ) { - return dataUser.hasData( elem ) || dataPriv.hasData( elem ); - }, - - data: function( elem, name, data ) { - return dataUser.access( elem, name, data ); - }, - - removeData: function( elem, name ) { - dataUser.remove( elem, name ); - }, - - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to dataPriv methods, these can be deprecated. - _data: function( elem, name, data ) { - return dataPriv.access( elem, name, data ); - }, - - _removeData: function( elem, name ) { - dataPriv.remove( elem, name ); - } -} ); - -jQuery.fn.extend( { - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = dataUser.get( elem ); - - if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE 11 only - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = camelCase( name.slice( 5 ) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - dataPriv.set( elem, "hasDataAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each( function() { - dataUser.set( this, key ); - } ); - } - - return access( this, function( value ) { - var data; - - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { - - // Attempt to get data from the cache - // The key will always be camelCased in Data - data = dataUser.get( elem, key ); - if ( data !== undefined ) { - return data; - } - - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, key ); - if ( data !== undefined ) { - return data; - } - - // We tried really hard, but the data doesn't exist. - return; - } - - // Set the data... - this.each( function() { - - // We always store the camelCased key - dataUser.set( this, key, value ); - } ); - }, null, value, arguments.length > 1, null, true ); - }, - - removeData: function( key ) { - return this.each( function() { - dataUser.remove( this, key ); - } ); - } -} ); - - -jQuery.extend( { - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = dataPriv.get( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || Array.isArray( data ) ) { - queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // Clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // Not public - generate a queueHooks object, or return the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { - empty: jQuery.Callbacks( "once memory" ).add( function() { - dataPriv.remove( elem, [ type + "queue", key ] ); - } ) - } ); - } -} ); - -jQuery.fn.extend( { - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[ 0 ], type ); - } - - return data === undefined ? - this : - this.each( function() { - var queue = jQuery.queue( this, type, data ); - - // Ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - } ); - }, - dequeue: function( type ) { - return this.each( function() { - jQuery.dequeue( this, type ); - } ); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -} ); -var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; - -var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); - - -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - -var documentElement = document.documentElement; - - - - var isAttached = function( elem ) { - return jQuery.contains( elem.ownerDocument, elem ); - }, - composed = { composed: true }; - - // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only - // Check attachment across shadow DOM boundaries when possible (gh-3504) - // Support: iOS 10.0-10.2 only - // Early iOS 10 versions support `attachShadow` but not `getRootNode`, - // leading to errors. We need to check for `getRootNode`. - if ( documentElement.getRootNode ) { - isAttached = function( elem ) { - return jQuery.contains( elem.ownerDocument, elem ) || - elem.getRootNode( composed ) === elem.ownerDocument; - }; - } -var isHiddenWithinTree = function( elem, el ) { - - // isHiddenWithinTree might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - - // Inline style trumps all - return elem.style.display === "none" || - elem.style.display === "" && - - // Otherwise, check computed style - // Support: Firefox <=43 - 45 - // Disconnected elements can have computed display: none, so first confirm that elem is - // in the document. - isAttached( elem ) && - - jQuery.css( elem, "display" ) === "none"; - }; - - - -function adjustCSS( elem, prop, valueParts, tween ) { - var adjusted, scale, - maxIterations = 20, - currentValue = tween ? - function() { - return tween.cur(); - } : - function() { - return jQuery.css( elem, prop, "" ); - }, - initial = currentValue(), - unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - - // Starting value computation is required for potential unit mismatches - initialInUnit = elem.nodeType && - ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && - rcssNum.exec( jQuery.css( elem, prop ) ); - - if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { - - // Support: Firefox <=54 - // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) - initial = initial / 2; - - // Trust units reported by jQuery.css - unit = unit || initialInUnit[ 3 ]; - - // Iteratively approximate from a nonzero starting point - initialInUnit = +initial || 1; - - while ( maxIterations-- ) { - - // Evaluate and update our best guess (doubling guesses that zero out). - // Finish if the scale equals or crosses 1 (making the old*new product non-positive). - jQuery.style( elem, prop, initialInUnit + unit ); - if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { - maxIterations = 0; - } - initialInUnit = initialInUnit / scale; - - } - - initialInUnit = initialInUnit * 2; - jQuery.style( elem, prop, initialInUnit + unit ); - - // Make sure we update the tween properties later on - valueParts = valueParts || []; - } - - if ( valueParts ) { - initialInUnit = +initialInUnit || +initial || 0; - - // Apply relative offset (+=/-=) if specified - adjusted = valueParts[ 1 ] ? - initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : - +valueParts[ 2 ]; - if ( tween ) { - tween.unit = unit; - tween.start = initialInUnit; - tween.end = adjusted; - } - } - return adjusted; -} - - -var defaultDisplayMap = {}; - -function getDefaultDisplay( elem ) { - var temp, - doc = elem.ownerDocument, - nodeName = elem.nodeName, - display = defaultDisplayMap[ nodeName ]; - - if ( display ) { - return display; - } - - temp = doc.body.appendChild( doc.createElement( nodeName ) ); - display = jQuery.css( temp, "display" ); - - temp.parentNode.removeChild( temp ); - - if ( display === "none" ) { - display = "block"; - } - defaultDisplayMap[ nodeName ] = display; - - return display; -} - -function showHide( elements, show ) { - var display, elem, - values = [], - index = 0, - length = elements.length; - - // Determine new display value for elements that need to change - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - - display = elem.style.display; - if ( show ) { - - // Since we force visibility upon cascade-hidden elements, an immediate (and slow) - // check is required in this first loop unless we have a nonempty display value (either - // inline or about-to-be-restored) - if ( display === "none" ) { - values[ index ] = dataPriv.get( elem, "display" ) || null; - if ( !values[ index ] ) { - elem.style.display = ""; - } - } - if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { - values[ index ] = getDefaultDisplay( elem ); - } - } else { - if ( display !== "none" ) { - values[ index ] = "none"; - - // Remember what we're overwriting - dataPriv.set( elem, "display", display ); - } - } - } - - // Set the display of the elements in a second loop to avoid constant reflow - for ( index = 0; index < length; index++ ) { - if ( values[ index ] != null ) { - elements[ index ].style.display = values[ index ]; - } - } - - return elements; -} - -jQuery.fn.extend( { - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state ) { - if ( typeof state === "boolean" ) { - return state ? this.show() : this.hide(); - } - - return this.each( function() { - if ( isHiddenWithinTree( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - } ); - } -} ); -var rcheckableType = ( /^(?:checkbox|radio)$/i ); - -var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); - -var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); - - - -( function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // Support: Android 4.0 - 4.3 only - // Check state lost if the name is set (#11217) - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Android <=4.1 only - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE <=11 only - // Make sure textarea (and checkbox) defaultValue is properly cloned - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; - - // Support: IE <=9 only - // IE <=9 replaces "; - support.option = !!div.lastChild; -} )(); - - -// We have to close these tags to support XHTML (#13200) -var wrapMap = { - - // XHTML parsers do not magically insert elements in the - // same way that tag soup parsers do. So we cannot shorten - // this by omitting or other required elements. - thead: [ 1, "", "
" ], - col: [ 2, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], - - _default: [ 0, "", "" ] -}; - -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// Support: IE <=9 only -if ( !support.option ) { - wrapMap.optgroup = wrapMap.option = [ 1, "" ]; -} - - -function getAll( context, tag ) { - - // Support: IE <=9 - 11 only - // Use typeof to avoid zero-argument method invocation on host objects (#15151) - var ret; - - if ( typeof context.getElementsByTagName !== "undefined" ) { - ret = context.getElementsByTagName( tag || "*" ); - - } else if ( typeof context.querySelectorAll !== "undefined" ) { - ret = context.querySelectorAll( tag || "*" ); - - } else { - ret = []; - } - - if ( tag === undefined || tag && nodeName( context, tag ) ) { - return jQuery.merge( [ context ], ret ); - } - - return ret; -} - - -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - dataPriv.set( - elems[ i ], - "globalEval", - !refElements || dataPriv.get( refElements[ i ], "globalEval" ) - ); - } -} - - -var rhtml = /<|&#?\w+;/; - -function buildFragment( elems, context, scripts, selection, ignored ) { - var elem, tmp, tag, wrap, attached, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( toType( elem ) === "object" ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Ensure the created nodes are orphaned (#12392) - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( ( elem = nodes[ i++ ] ) ) { - - // Skip elements already in the context collection (trac-4087) - if ( selection && jQuery.inArray( elem, selection ) > -1 ) { - if ( ignored ) { - ignored.push( elem ); - } - continue; - } - - attached = isAttached( elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( attached ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( ( elem = tmp[ j++ ] ) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; -} - - -var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)/; - -function returnTrue() { - return true; -} - -function returnFalse() { - return false; -} - -// Support: IE <=9 - 11+ -// focus() and blur() are asynchronous, except when they are no-op. -// So expect focus to be synchronous when the element is already active, -// and blur to be synchronous when the element is not already active. -// (focus and blur are always synchronous in other supported browsers, -// this just defines when we can count on it). -function expectSync( elem, type ) { - return ( elem === safeActiveElement() ) === ( type === "focus" ); -} - -// Support: IE <=9 only -// Accessing document.activeElement can throw unexpectedly -// https://bugs.jquery.com/ticket/13393 -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - -function on( elem, types, selector, data, fn, one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - on( elem, type, selector, data, types[ type ], one ); - } - return elem; - } - - if ( data == null && fn == null ) { - - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return elem; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return elem.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - } ); -} - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.get( elem ); - - // Only attach events to objects that accept data - if ( !acceptData( elem ) ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Ensure that invalid selectors throw exceptions at attach time - // Evaluate against documentElement in case elem is a non-element node (e.g., document) - if ( selector ) { - jQuery.find.matchesSelector( documentElement, selector ); - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !( events = elemData.events ) ) { - events = elemData.events = Object.create( null ); - } - if ( !( eventHandle = elemData.handle ) ) { - eventHandle = elemData.handle = function( e ) { - - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend( { - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join( "." ) - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !( handlers = events[ type ] ) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener if the special events handler returns false - if ( !special.setup || - special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); - - if ( !elemData || !( events = elemData.events ) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[ 2 ] && - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || - selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || - special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove data and the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - dataPriv.remove( elem, "handle events" ); - } - }, - - dispatch: function( nativeEvent ) { - - var i, j, ret, matched, handleObj, handlerQueue, - args = new Array( arguments.length ), - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( nativeEvent ), - - handlers = ( - dataPriv.get( this, "events" ) || Object.create( null ) - )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[ 0 ] = event; - - for ( i = 1; i < arguments.length; i++ ) { - args[ i ] = arguments[ i ]; - } - - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( ( handleObj = matched.handlers[ j++ ] ) && - !event.isImmediatePropagationStopped() ) { - - // If the event is namespaced, then each handler is only invoked if it is - // specially universal or its namespaces are a superset of the event's. - if ( !event.rnamespace || handleObj.namespace === false || - event.rnamespace.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || - handleObj.handler ).apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( ( event.result = ret ) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, handleObj, sel, matchedHandlers, matchedSelectors, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - if ( delegateCount && - - // Support: IE <=9 - // Black-hole SVG instance trees (trac-13180) - cur.nodeType && - - // Support: Firefox <=42 - // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) - // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click - // Support: IE 11 only - // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) - !( event.type === "click" && event.button >= 1 ) ) { - - for ( ; cur !== this; cur = cur.parentNode || this ) { - - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { - matchedHandlers = []; - matchedSelectors = {}; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matchedSelectors[ sel ] === undefined ) { - matchedSelectors[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) > -1 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matchedSelectors[ sel ] ) { - matchedHandlers.push( handleObj ); - } - } - if ( matchedHandlers.length ) { - handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); - } - } - } - } - - // Add the remaining (directly-bound) handlers - cur = this; - if ( delegateCount < handlers.length ) { - handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); - } - - return handlerQueue; - }, - - addProp: function( name, hook ) { - Object.defineProperty( jQuery.Event.prototype, name, { - enumerable: true, - configurable: true, - - get: isFunction( hook ) ? - function() { - if ( this.originalEvent ) { - return hook( this.originalEvent ); - } - } : - function() { - if ( this.originalEvent ) { - return this.originalEvent[ name ]; - } - }, - - set: function( value ) { - Object.defineProperty( this, name, { - enumerable: true, - configurable: true, - writable: true, - value: value - } ); - } - } ); - }, - - fix: function( originalEvent ) { - return originalEvent[ jQuery.expando ] ? - originalEvent : - new jQuery.Event( originalEvent ); - }, - - special: { - load: { - - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - click: { - - // Utilize native event to ensure correct state for checkable inputs - setup: function( data ) { - - // For mutual compressibility with _default, replace `this` access with a local var. - // `|| data` is dead code meant only to preserve the variable through minification. - var el = this || data; - - // Claim the first handler - if ( rcheckableType.test( el.type ) && - el.click && nodeName( el, "input" ) ) { - - // dataPriv.set( el, "click", ... ) - leverageNative( el, "click", returnTrue ); - } - - // Return false to allow normal processing in the caller - return false; - }, - trigger: function( data ) { - - // For mutual compressibility with _default, replace `this` access with a local var. - // `|| data` is dead code meant only to preserve the variable through minification. - var el = this || data; - - // Force setup before triggering a click - if ( rcheckableType.test( el.type ) && - el.click && nodeName( el, "input" ) ) { - - leverageNative( el, "click" ); - } - - // Return non-false to allow normal event-path propagation - return true; - }, - - // For cross-browser consistency, suppress native .click() on links - // Also prevent it if we're currently inside a leveraged native-event stack - _default: function( event ) { - var target = event.target; - return rcheckableType.test( target.type ) && - target.click && nodeName( target, "input" ) && - dataPriv.get( target, "click" ) || - nodeName( target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } - } - } -}; - -// Ensure the presence of an event listener that handles manually-triggered -// synthetic events by interrupting progress until reinvoked in response to -// *native* events that it fires directly, ensuring that state changes have -// already occurred before other listeners are invoked. -function leverageNative( el, type, expectSync ) { - - // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add - if ( !expectSync ) { - if ( dataPriv.get( el, type ) === undefined ) { - jQuery.event.add( el, type, returnTrue ); - } - return; - } - - // Register the controller as a special universal handler for all event namespaces - dataPriv.set( el, type, false ); - jQuery.event.add( el, type, { - namespace: false, - handler: function( event ) { - var notAsync, result, - saved = dataPriv.get( this, type ); - - if ( ( event.isTrigger & 1 ) && this[ type ] ) { - - // Interrupt processing of the outer synthetic .trigger()ed event - // Saved data should be false in such cases, but might be a leftover capture object - // from an async native handler (gh-4350) - if ( !saved.length ) { - - // Store arguments for use when handling the inner native event - // There will always be at least one argument (an event object), so this array - // will not be confused with a leftover capture object. - saved = slice.call( arguments ); - dataPriv.set( this, type, saved ); - - // Trigger the native event and capture its result - // Support: IE <=9 - 11+ - // focus() and blur() are asynchronous - notAsync = expectSync( this, type ); - this[ type ](); - result = dataPriv.get( this, type ); - if ( saved !== result || notAsync ) { - dataPriv.set( this, type, false ); - } else { - result = {}; - } - if ( saved !== result ) { - - // Cancel the outer synthetic event - event.stopImmediatePropagation(); - event.preventDefault(); - return result.value; - } - - // If this is an inner synthetic event for an event with a bubbling surrogate - // (focus or blur), assume that the surrogate already propagated from triggering the - // native event and prevent that from happening again here. - // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the - // bubbling surrogate propagates *after* the non-bubbling base), but that seems - // less bad than duplication. - } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { - event.stopPropagation(); - } - - // If this is a native event triggered above, everything is now in order - // Fire an inner synthetic event with the original arguments - } else if ( saved.length ) { - - // ...and capture the result - dataPriv.set( this, type, { - value: jQuery.event.trigger( - - // Support: IE <=9 - 11+ - // Extend with the prototype to reset the above stopImmediatePropagation() - jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), - saved.slice( 1 ), - this - ) - } ); - - // Abort handling of the native event - event.stopImmediatePropagation(); - } - } - } ); -} - -jQuery.removeEvent = function( elem, type, handle ) { - - // This "if" is needed for plain objects - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle ); - } -}; - -jQuery.Event = function( src, props ) { - - // Allow instantiation without the 'new' keyword - if ( !( this instanceof jQuery.Event ) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - - // Support: Android <=2.3 only - src.returnValue === false ? - returnTrue : - returnFalse; - - // Create target properties - // Support: Safari <=6 - 7 only - // Target should not be a text node (#504, #13143) - this.target = ( src.target && src.target.nodeType === 3 ) ? - src.target.parentNode : - src.target; - - this.currentTarget = src.currentTarget; - this.relatedTarget = src.relatedTarget; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || Date.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - constructor: jQuery.Event, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - isSimulated: false, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - - if ( e && !this.isSimulated ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } -}; - -// Includes all common event props including KeyEvent and MouseEvent specific props -jQuery.each( { - altKey: true, - bubbles: true, - cancelable: true, - changedTouches: true, - ctrlKey: true, - detail: true, - eventPhase: true, - metaKey: true, - pageX: true, - pageY: true, - shiftKey: true, - view: true, - "char": true, - code: true, - charCode: true, - key: true, - keyCode: true, - button: true, - buttons: true, - clientX: true, - clientY: true, - offsetX: true, - offsetY: true, - pointerId: true, - pointerType: true, - screenX: true, - screenY: true, - targetTouches: true, - toElement: true, - touches: true, - - which: function( event ) { - var button = event.button; - - // Add which for key events - if ( event.which == null && rkeyEvent.test( event.type ) ) { - return event.charCode != null ? event.charCode : event.keyCode; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { - if ( button & 1 ) { - return 1; - } - - if ( button & 2 ) { - return 3; - } - - if ( button & 4 ) { - return 2; - } - - return 0; - } - - return event.which; - } -}, jQuery.event.addProp ); - -jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { - jQuery.event.special[ type ] = { - - // Utilize native event if possible so blur/focus sequence is correct - setup: function() { - - // Claim the first handler - // dataPriv.set( this, "focus", ... ) - // dataPriv.set( this, "blur", ... ) - leverageNative( this, type, expectSync ); - - // Return false to allow normal processing in the caller - return false; - }, - trigger: function() { - - // Force setup before trigger - leverageNative( this, type ); - - // Return non-false to allow normal event-path propagation - return true; - }, - - delegateType: delegateType - }; -} ); - -// Create mouseenter/leave events using mouseover/out and event-time checks -// so that event delegation works in jQuery. -// Do the same for pointerenter/pointerleave and pointerover/pointerout -// -// Support: Safari 7 only -// Safari sends mouseenter too often; see: -// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 -// for the description of the bug (it existed in older Chrome versions as well). -jQuery.each( { - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mouseenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -} ); - -jQuery.fn.extend( { - - on: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn ); - }, - one: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? - handleObj.origType + "." + handleObj.namespace : - handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each( function() { - jQuery.event.remove( this, types, fn, selector ); - } ); - } -} ); - - -var - - // Support: IE <=10 - 11, Edge 12 - 13 only - // In IE/Edge using regex groups here causes severe slowdowns. - // See https://connect.microsoft.com/IE/feedback/details/1736512/ - rnoInnerhtml = /\s*$/g; - -// Prefer a tbody over its parent table for containing new rows -function manipulationTarget( elem, content ) { - if ( nodeName( elem, "table" ) && - nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { - - return jQuery( elem ).children( "tbody" )[ 0 ] || elem; - } - - return elem; -} - -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { - elem.type = elem.type.slice( 5 ); - } else { - elem.removeAttribute( "type" ); - } - - return elem; -} - -function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, udataOld, udataCur, events; - - if ( dest.nodeType !== 1 ) { - return; - } - - // 1. Copy private data: events, handlers, etc. - if ( dataPriv.hasData( src ) ) { - pdataOld = dataPriv.get( src ); - events = pdataOld.events; - - if ( events ) { - dataPriv.remove( dest, "handle events" ); - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - } - - // 2. Copy user data - if ( dataUser.hasData( src ) ) { - udataOld = dataUser.access( src ); - udataCur = jQuery.extend( {}, udataOld ); - - dataUser.set( dest, udataCur ); - } -} - -// Fix IE bugs, see support tests -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - -function domManip( collection, args, callback, ignored ) { - - // Flatten any nested arrays - args = flat( args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = collection.length, - iNoClone = l - 1, - value = args[ 0 ], - valueIsFunction = isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( valueIsFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return collection.each( function( index ) { - var self = collection.eq( index ); - if ( valueIsFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - domManip( self, args, callback, ignored ); - } ); - } - - if ( l ) { - fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - // Require either new content or an interest in ignored elements to invoke the callback - if ( first || ignored ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item - // instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( collection[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !dataPriv.access( node, "globalEval" ) && - jQuery.contains( doc, node ) ) { - - if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { - - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl && !node.noModule ) { - jQuery._evalUrl( node.src, { - nonce: node.nonce || node.getAttribute( "nonce" ) - }, doc ); - } - } else { - DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); - } - } - } - } - } - } - - return collection; -} - -function remove( elem, selector, keepData ) { - var node, - nodes = selector ? jQuery.filter( selector, elem ) : elem, - i = 0; - - for ( ; ( node = nodes[ i ] ) != null; i++ ) { - if ( !keepData && node.nodeType === 1 ) { - jQuery.cleanData( getAll( node ) ); - } - - if ( node.parentNode ) { - if ( keepData && isAttached( node ) ) { - setGlobalEval( getAll( node, "script" ) ); - } - node.parentNode.removeChild( node ); - } - } - - return elem; -} - -jQuery.extend( { - htmlPrefilter: function( html ) { - return html; - }, - - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = isAttached( elem ); - - // Fix IE cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - // Return the cloned set - return clone; - }, - - cleanData: function( elems ) { - var data, elem, type, - special = jQuery.event.special, - i = 0; - - for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { - if ( acceptData( elem ) ) { - if ( ( data = elem[ dataPriv.expando ] ) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataPriv.expando ] = undefined; - } - if ( elem[ dataUser.expando ] ) { - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataUser.expando ] = undefined; - } - } - } - } -} ); - -jQuery.fn.extend( { - detach: function( selector ) { - return remove( this, selector, true ); - }, - - remove: function( selector ) { - return remove( this, selector ); - }, - - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each( function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - } ); - }, null, value, arguments.length ); - }, - - append: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - } ); - }, - - prepend: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - } ); - }, - - before: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - } ); - }, - - after: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - } ); - }, - - empty: function() { - var elem, - i = 0; - - for ( ; ( elem = this[ i ] ) != null; i++ ) { - if ( elem.nodeType === 1 ) { - - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); - - // Remove any remaining nodes - elem.textContent = ""; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map( function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - } ); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = jQuery.htmlPrefilter( value ); - - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch ( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var ignored = []; - - // Make the changes, replacing each non-ignored context element with the new content - return domManip( this, arguments, function( elem ) { - var parent = this.parentNode; - - if ( jQuery.inArray( this, ignored ) < 0 ) { - jQuery.cleanData( getAll( this ) ); - if ( parent ) { - parent.replaceChild( elem, this ); - } - } - - // Force callback invocation - }, ignored ); - } -} ); - -jQuery.each( { - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Support: Android <=4.0 only, PhantomJS 1 only - // .get() because push.apply(_, arraylike) throws on ancient WebKit - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -} ); -var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); - -var getStyles = function( elem ) { - - // Support: IE <=11 only, Firefox <=30 (#15098, #14150) - // IE throws on elements created in popups - // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" - var view = elem.ownerDocument.defaultView; - - if ( !view || !view.opener ) { - view = window; - } - - return view.getComputedStyle( elem ); - }; - -var swap = function( elem, options, callback ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.call( elem ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}; - - -var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); - - - -( function() { - - // Executing both pixelPosition & boxSizingReliable tests require only one layout - // so they're executed at the same time to save the second computation. - function computeStyleTests() { - - // This is a singleton, we need to execute it only once - if ( !div ) { - return; - } - - container.style.cssText = "position:absolute;left:-11111px;width:60px;" + - "margin-top:1px;padding:0;border:0"; - div.style.cssText = - "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + - "margin:auto;border:1px;padding:1px;" + - "width:60%;top:1%"; - documentElement.appendChild( container ).appendChild( div ); - - var divStyle = window.getComputedStyle( div ); - pixelPositionVal = divStyle.top !== "1%"; - - // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 - reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; - - // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 - // Some styles come back with percentage values, even though they shouldn't - div.style.right = "60%"; - pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; - - // Support: IE 9 - 11 only - // Detect misreporting of content dimensions for box-sizing:border-box elements - boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; - - // Support: IE 9 only - // Detect overflow:scroll screwiness (gh-3699) - // Support: Chrome <=64 - // Don't get tricked when zoom affects offsetWidth (gh-4029) - div.style.position = "absolute"; - scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; - - documentElement.removeChild( container ); - - // Nullify the div so it wouldn't be stored in the memory and - // it will also be a sign that checks already performed - div = null; - } - - function roundPixelMeasures( measure ) { - return Math.round( parseFloat( measure ) ); - } - - var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, - reliableTrDimensionsVal, reliableMarginLeftVal, - container = document.createElement( "div" ), - div = document.createElement( "div" ); - - // Finish early in limited (non-browser) environments - if ( !div.style ) { - return; - } - - // Support: IE <=9 - 11 only - // Style of cloned element affects source element cloned (#8908) - div.style.backgroundClip = "content-box"; - div.cloneNode( true ).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; - - jQuery.extend( support, { - boxSizingReliable: function() { - computeStyleTests(); - return boxSizingReliableVal; - }, - pixelBoxStyles: function() { - computeStyleTests(); - return pixelBoxStylesVal; - }, - pixelPosition: function() { - computeStyleTests(); - return pixelPositionVal; - }, - reliableMarginLeft: function() { - computeStyleTests(); - return reliableMarginLeftVal; - }, - scrollboxSize: function() { - computeStyleTests(); - return scrollboxSizeVal; - }, - - // Support: IE 9 - 11+, Edge 15 - 18+ - // IE/Edge misreport `getComputedStyle` of table rows with width/height - // set in CSS while `offset*` properties report correct values. - // Behavior in IE 9 is more subtle than in newer versions & it passes - // some versions of this test; make sure not to make it pass there! - reliableTrDimensions: function() { - var table, tr, trChild, trStyle; - if ( reliableTrDimensionsVal == null ) { - table = document.createElement( "table" ); - tr = document.createElement( "tr" ); - trChild = document.createElement( "div" ); - - table.style.cssText = "position:absolute;left:-11111px"; - tr.style.height = "1px"; - trChild.style.height = "9px"; - - documentElement - .appendChild( table ) - .appendChild( tr ) - .appendChild( trChild ); - - trStyle = window.getComputedStyle( tr ); - reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; - - documentElement.removeChild( table ); - } - return reliableTrDimensionsVal; - } - } ); -} )(); - - -function curCSS( elem, name, computed ) { - var width, minWidth, maxWidth, ret, - - // Support: Firefox 51+ - // Retrieving style before computed somehow - // fixes an issue with getting wrong values - // on detached elements - style = elem.style; - - computed = computed || getStyles( elem ); - - // getPropertyValue is needed for: - // .css('filter') (IE 9 only, #12537) - // .css('--customProperty) (#3144) - if ( computed ) { - ret = computed.getPropertyValue( name ) || computed[ name ]; - - if ( ret === "" && !isAttached( elem ) ) { - ret = jQuery.style( elem, name ); - } - - // A tribute to the "awesome hack by Dean Edwards" - // Android Browser returns percentage for some values, - // but width seems to be reliably pixels. - // This is against the CSSOM draft spec: - // https://drafts.csswg.org/cssom/#resolved-values - if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { - - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - return ret !== undefined ? - - // Support: IE <=9 - 11 only - // IE returns zIndex value as an integer. - ret + "" : - ret; -} - - -function addGetHookIf( conditionFn, hookFn ) { - - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function() { - if ( conditionFn() ) { - - // Hook not needed (or it's not possible to use it due - // to missing dependency), remove it. - delete this.get; - return; - } - - // Hook needed; redefine it so that the support test is not executed again. - return ( this.get = hookFn ).apply( this, arguments ); - } - }; -} - - -var cssPrefixes = [ "Webkit", "Moz", "ms" ], - emptyStyle = document.createElement( "div" ).style, - vendorProps = {}; - -// Return a vendor-prefixed property or undefined -function vendorPropName( name ) { - - // Check for vendor prefixed names - var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in emptyStyle ) { - return name; - } - } -} - -// Return a potentially-mapped jQuery.cssProps or vendor prefixed property -function finalPropName( name ) { - var final = jQuery.cssProps[ name ] || vendorProps[ name ]; - - if ( final ) { - return final; - } - if ( name in emptyStyle ) { - return name; - } - return vendorProps[ name ] = vendorPropName( name ) || name; -} - - -var - - // Swappable if display is none or starts with table - // except "table", "table-cell", or "table-caption" - // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rcustomProp = /^--/, - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }; - -function setPositiveNumber( _elem, value, subtract ) { - - // Any relative (+/-) values have already been - // normalized at this point - var matches = rcssNum.exec( value ); - return matches ? - - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : - value; -} - -function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { - var i = dimension === "width" ? 1 : 0, - extra = 0, - delta = 0; - - // Adjustment may not be necessary - if ( box === ( isBorderBox ? "border" : "content" ) ) { - return 0; - } - - for ( ; i < 4; i += 2 ) { - - // Both box models exclude margin - if ( box === "margin" ) { - delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); - } - - // If we get here with a content-box, we're seeking "padding" or "border" or "margin" - if ( !isBorderBox ) { - - // Add padding - delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - - // For "border" or "margin", add border - if ( box !== "padding" ) { - delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - - // But still keep track of it otherwise - } else { - extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - - // If we get here with a border-box (content + padding + border), we're seeking "content" or - // "padding" or "margin" - } else { - - // For "content", subtract padding - if ( box === "content" ) { - delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - } - - // For "content" or "padding", subtract border - if ( box !== "margin" ) { - delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } - } - - // Account for positive content-box scroll gutter when requested by providing computedVal - if ( !isBorderBox && computedVal >= 0 ) { - - // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border - // Assuming integer scroll gutter, subtract the rest and round down - delta += Math.max( 0, Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - computedVal - - delta - - extra - - 0.5 - - // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter - // Use an explicit zero to avoid NaN (gh-3964) - ) ) || 0; - } - - return delta; -} - -function getWidthOrHeight( elem, dimension, extra ) { - - // Start with computed style - var styles = getStyles( elem ), - - // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). - // Fake content-box until we know it's needed to know the true value. - boxSizingNeeded = !support.boxSizingReliable() || extra, - isBorderBox = boxSizingNeeded && - jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - valueIsBorderBox = isBorderBox, - - val = curCSS( elem, dimension, styles ), - offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); - - // Support: Firefox <=54 - // Return a confounding non-pixel value or feign ignorance, as appropriate. - if ( rnumnonpx.test( val ) ) { - if ( !extra ) { - return val; - } - val = "auto"; - } - - - // Support: IE 9 - 11 only - // Use offsetWidth/offsetHeight for when box sizing is unreliable. - // In those cases, the computed value can be trusted to be border-box. - if ( ( !support.boxSizingReliable() && isBorderBox || - - // Support: IE 10 - 11+, Edge 15 - 18+ - // IE/Edge misreport `getComputedStyle` of table rows with width/height - // set in CSS while `offset*` properties report correct values. - // Interestingly, in some cases IE 9 doesn't suffer from this issue. - !support.reliableTrDimensions() && nodeName( elem, "tr" ) || - - // Fall back to offsetWidth/offsetHeight when value is "auto" - // This happens for inline elements with no explicit setting (gh-3571) - val === "auto" || - - // Support: Android <=4.1 - 4.3 only - // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) - !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && - - // Make sure the element is visible & connected - elem.getClientRects().length ) { - - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; - - // Where available, offsetWidth/offsetHeight approximate border box dimensions. - // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the - // retrieved value as a content box dimension. - valueIsBorderBox = offsetProp in elem; - if ( valueIsBorderBox ) { - val = elem[ offsetProp ]; - } - } - - // Normalize "" and auto - val = parseFloat( val ) || 0; - - // Adjust for the element's box model - return ( val + - boxModelAdjustment( - elem, - dimension, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox, - styles, - - // Provide the current computed size to request scroll gutter calculation (gh-3589) - val - ) - ) + "px"; -} - -jQuery.extend( { - - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { - - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - } - } - } - }, - - // Don't automatically add "px" to these possibly-unitless properties - cssNumber: { - "animationIterationCount": true, - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "gridArea": true, - "gridColumn": true, - "gridColumnEnd": true, - "gridColumnStart": true, - "gridRow": true, - "gridRowEnd": true, - "gridRowStart": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: {}, - - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { - - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = camelCase( name ), - isCustomProp = rcustomProp.test( name ), - style = elem.style; - - // Make sure that we're working with the right name. We don't - // want to query the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Gets hook for the prefixed version, then unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // Convert "+=" or "-=" to relative numbers (#7345) - if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { - value = adjustCSS( elem, name, ret ); - - // Fixes bug #9237 - type = "number"; - } - - // Make sure that null and NaN values aren't set (#7116) - if ( value == null || value !== value ) { - return; - } - - // If a number was passed in, add the unit (except for certain CSS properties) - // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append - // "px" to a few hardcoded values. - if ( type === "number" && !isCustomProp ) { - value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); - } - - // background-* props affect original clone's values - if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { - style[ name ] = "inherit"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !( "set" in hooks ) || - ( value = hooks.set( elem, value, extra ) ) !== undefined ) { - - if ( isCustomProp ) { - style.setProperty( name, value ); - } else { - style[ name ] = value; - } - } - - } else { - - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && - ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { - - return ret; - } - - // Otherwise just get the value from the style object - return style[ name ]; - } - }, - - css: function( elem, name, extra, styles ) { - var val, num, hooks, - origName = camelCase( name ), - isCustomProp = rcustomProp.test( name ); - - // Make sure that we're working with the right name. We don't - // want to modify the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Try prefixed name followed by the unprefixed name - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } - - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name, styles ); - } - - // Convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } - - // Make numeric if forced or a qualifier was provided and val looks numeric - if ( extra === "" || extra ) { - num = parseFloat( val ); - return extra === true || isFinite( num ) ? num || 0 : val; - } - - return val; - } -} ); - -jQuery.each( [ "height", "width" ], function( _i, dimension ) { - jQuery.cssHooks[ dimension ] = { - get: function( elem, computed, extra ) { - if ( computed ) { - - // Certain elements can have dimension info if we invisibly show them - // but it must have a current display style that would benefit - return rdisplayswap.test( jQuery.css( elem, "display" ) ) && - - // Support: Safari 8+ - // Table columns in Safari have non-zero offsetWidth & zero - // getBoundingClientRect().width unless display is changed. - // Support: IE <=11 only - // Running getBoundingClientRect on a disconnected node - // in IE throws an error. - ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? - swap( elem, cssShow, function() { - return getWidthOrHeight( elem, dimension, extra ); - } ) : - getWidthOrHeight( elem, dimension, extra ); - } - }, - - set: function( elem, value, extra ) { - var matches, - styles = getStyles( elem ), - - // Only read styles.position if the test has a chance to fail - // to avoid forcing a reflow. - scrollboxSizeBuggy = !support.scrollboxSize() && - styles.position === "absolute", - - // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) - boxSizingNeeded = scrollboxSizeBuggy || extra, - isBorderBox = boxSizingNeeded && - jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - subtract = extra ? - boxModelAdjustment( - elem, - dimension, - extra, - isBorderBox, - styles - ) : - 0; - - // Account for unreliable border-box dimensions by comparing offset* to computed and - // faking a content-box to get border and padding (gh-3699) - if ( isBorderBox && scrollboxSizeBuggy ) { - subtract -= Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - parseFloat( styles[ dimension ] ) - - boxModelAdjustment( elem, dimension, "border", false, styles ) - - 0.5 - ); - } - - // Convert to pixels if value adjustment is needed - if ( subtract && ( matches = rcssNum.exec( value ) ) && - ( matches[ 3 ] || "px" ) !== "px" ) { - - elem.style[ dimension ] = value; - value = jQuery.css( elem, dimension ); - } - - return setPositiveNumber( elem, value, subtract ); - } - }; -} ); - -jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, - function( elem, computed ) { - if ( computed ) { - return ( parseFloat( curCSS( elem, "marginLeft" ) ) || - elem.getBoundingClientRect().left - - swap( elem, { marginLeft: 0 }, function() { - return elem.getBoundingClientRect().left; - } ) - ) + "px"; - } - } -); - -// These hooks are used by animate to expand properties -jQuery.each( { - margin: "", - padding: "", - border: "Width" -}, function( prefix, suffix ) { - jQuery.cssHooks[ prefix + suffix ] = { - expand: function( value ) { - var i = 0, - expanded = {}, - - // Assumes a single number if not a string - parts = typeof value === "string" ? value.split( " " ) : [ value ]; - - for ( ; i < 4; i++ ) { - expanded[ prefix + cssExpand[ i ] + suffix ] = - parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; - } - - return expanded; - } - }; - - if ( prefix !== "margin" ) { - jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; - } -} ); - -jQuery.fn.extend( { - css: function( name, value ) { - return access( this, function( elem, name, value ) { - var styles, len, - map = {}, - i = 0; - - if ( Array.isArray( name ) ) { - styles = getStyles( elem ); - len = name.length; - - for ( ; i < len; i++ ) { - map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); - } - - return map; - } - - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - } -} ); - - -function Tween( elem, options, prop, end, easing ) { - return new Tween.prototype.init( elem, options, prop, end, easing ); -} -jQuery.Tween = Tween; - -Tween.prototype = { - constructor: Tween, - init: function( elem, options, prop, end, easing, unit ) { - this.elem = elem; - this.prop = prop; - this.easing = easing || jQuery.easing._default; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - }, - cur: function() { - var hooks = Tween.propHooks[ this.prop ]; - - return hooks && hooks.get ? - hooks.get( this ) : - Tween.propHooks._default.get( this ); - }, - run: function( percent ) { - var eased, - hooks = Tween.propHooks[ this.prop ]; - - if ( this.options.duration ) { - this.pos = eased = jQuery.easing[ this.easing ]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = ( this.end - this.start ) * eased + this.start; - - if ( this.options.step ) { - this.options.step.call( this.elem, this.now, this ); - } - - if ( hooks && hooks.set ) { - hooks.set( this ); - } else { - Tween.propHooks._default.set( this ); - } - return this; - } -}; - -Tween.prototype.init.prototype = Tween.prototype; - -Tween.propHooks = { - _default: { - get: function( tween ) { - var result; - - // Use a property on the element directly when it is not a DOM element, - // or when there is no matching style property that exists. - if ( tween.elem.nodeType !== 1 || - tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { - return tween.elem[ tween.prop ]; - } - - // Passing an empty string as a 3rd parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails. - // Simple values such as "10px" are parsed to Float; - // complex values such as "rotate(1rad)" are returned as-is. - result = jQuery.css( tween.elem, tween.prop, "" ); - - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function( tween ) { - - // Use step hook for back compat. - // Use cssHook if its there. - // Use .style if available and use plain properties where available. - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.nodeType === 1 && ( - jQuery.cssHooks[ tween.prop ] || - tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; - -// Support: IE <=9 only -// Panic based approach to setting things on disconnected nodes -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; - -jQuery.easing = { - linear: function( p ) { - return p; - }, - swing: function( p ) { - return 0.5 - Math.cos( p * Math.PI ) / 2; - }, - _default: "swing" -}; - -jQuery.fx = Tween.prototype.init; - -// Back compat <1.8 extension point -jQuery.fx.step = {}; - - - - -var - fxNow, inProgress, - rfxtypes = /^(?:toggle|show|hide)$/, - rrun = /queueHooks$/; - -function schedule() { - if ( inProgress ) { - if ( document.hidden === false && window.requestAnimationFrame ) { - window.requestAnimationFrame( schedule ); - } else { - window.setTimeout( schedule, jQuery.fx.interval ); - } - - jQuery.fx.tick(); - } -} - -// Animations created synchronously will run synchronously -function createFxNow() { - window.setTimeout( function() { - fxNow = undefined; - } ); - return ( fxNow = Date.now() ); -} - -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - i = 0, - attrs = { height: type }; - - // If we include width, step value is 1 to do all cssExpand values, - // otherwise step value is 2 to skip over Left and Right - includeWidth = includeWidth ? 1 : 0; - for ( ; i < 4; i += 2 - includeWidth ) { - which = cssExpand[ i ]; - attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; - } - - if ( includeWidth ) { - attrs.opacity = attrs.width = type; - } - - return attrs; -} - -function createTween( value, prop, animation ) { - var tween, - collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { - - // We're done with this property - return tween; - } - } -} - -function defaultPrefilter( elem, props, opts ) { - var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, - isBox = "width" in props || "height" in props, - anim = this, - orig = {}, - style = elem.style, - hidden = elem.nodeType && isHiddenWithinTree( elem ), - dataShow = dataPriv.get( elem, "fxshow" ); - - // Queue-skipping animations hijack the fx hooks - if ( !opts.queue ) { - hooks = jQuery._queueHooks( elem, "fx" ); - if ( hooks.unqueued == null ) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function() { - if ( !hooks.unqueued ) { - oldfire(); - } - }; - } - hooks.unqueued++; - - anim.always( function() { - - // Ensure the complete handler is called before this completes - anim.always( function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - } ); - } ); - } - - // Detect show/hide animations - for ( prop in props ) { - value = props[ prop ]; - if ( rfxtypes.test( value ) ) { - delete props[ prop ]; - toggle = toggle || value === "toggle"; - if ( value === ( hidden ? "hide" : "show" ) ) { - - // Pretend to be hidden if this is a "show" and - // there is still data from a stopped show/hide - if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { - hidden = true; - - // Ignore all other no-op show/hide data - } else { - continue; - } - } - orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); - } - } - - // Bail out if this is a no-op like .hide().hide() - propTween = !jQuery.isEmptyObject( props ); - if ( !propTween && jQuery.isEmptyObject( orig ) ) { - return; - } - - // Restrict "overflow" and "display" styles during box animations - if ( isBox && elem.nodeType === 1 ) { - - // Support: IE <=9 - 11, Edge 12 - 15 - // Record all 3 overflow attributes because IE does not infer the shorthand - // from identically-valued overflowX and overflowY and Edge just mirrors - // the overflowX value there. - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - - // Identify a display type, preferring old show/hide data over the CSS cascade - restoreDisplay = dataShow && dataShow.display; - if ( restoreDisplay == null ) { - restoreDisplay = dataPriv.get( elem, "display" ); - } - display = jQuery.css( elem, "display" ); - if ( display === "none" ) { - if ( restoreDisplay ) { - display = restoreDisplay; - } else { - - // Get nonempty value(s) by temporarily forcing visibility - showHide( [ elem ], true ); - restoreDisplay = elem.style.display || restoreDisplay; - display = jQuery.css( elem, "display" ); - showHide( [ elem ] ); - } - } - - // Animate inline elements as inline-block - if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { - if ( jQuery.css( elem, "float" ) === "none" ) { - - // Restore the original display value at the end of pure show/hide animations - if ( !propTween ) { - anim.done( function() { - style.display = restoreDisplay; - } ); - if ( restoreDisplay == null ) { - display = style.display; - restoreDisplay = display === "none" ? "" : display; - } - } - style.display = "inline-block"; - } - } - } - - if ( opts.overflow ) { - style.overflow = "hidden"; - anim.always( function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - } ); - } - - // Implement show/hide animations - propTween = false; - for ( prop in orig ) { - - // General show/hide setup for this element animation - if ( !propTween ) { - if ( dataShow ) { - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; - } - } else { - dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); - } - - // Store hidden/visible for toggle so `.stop().toggle()` "reverses" - if ( toggle ) { - dataShow.hidden = !hidden; - } - - // Show elements before animating them - if ( hidden ) { - showHide( [ elem ], true ); - } - - /* eslint-disable no-loop-func */ - - anim.done( function() { - - /* eslint-enable no-loop-func */ - - // The final step of a "hide" animation is actually hiding the element - if ( !hidden ) { - showHide( [ elem ] ); - } - dataPriv.remove( elem, "fxshow" ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - } ); - } - - // Per-property setup - propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = propTween.start; - if ( hidden ) { - propTween.end = propTween.start; - propTween.start = 0; - } - } - } -} - -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( Array.isArray( value ) ) { - easing = value[ 1 ]; - value = props[ index ] = value[ 0 ]; - } - - if ( index !== name ) { - props[ name ] = value; - delete props[ index ]; - } - - hooks = jQuery.cssHooks[ name ]; - if ( hooks && "expand" in hooks ) { - value = hooks.expand( value ); - delete props[ name ]; - - // Not quite $.extend, this won't overwrite existing keys. - // Reusing 'index' because we have the correct "name" - for ( index in value ) { - if ( !( index in props ) ) { - props[ index ] = value[ index ]; - specialEasing[ index ] = easing; - } - } - } else { - specialEasing[ name ] = easing; - } - } -} - -function Animation( elem, properties, options ) { - var result, - stopped, - index = 0, - length = Animation.prefilters.length, - deferred = jQuery.Deferred().always( function() { - - // Don't match elem in the :animated selector - delete tick.elem; - } ), - tick = function() { - if ( stopped ) { - return false; - } - var currentTime = fxNow || createFxNow(), - remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - - // Support: Android 2.3 only - // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) - temp = remaining / animation.duration || 0, - percent = 1 - temp, - index = 0, - length = animation.tweens.length; - - for ( ; index < length; index++ ) { - animation.tweens[ index ].run( percent ); - } - - deferred.notifyWith( elem, [ animation, percent, remaining ] ); - - // If there's more to do, yield - if ( percent < 1 && length ) { - return remaining; - } - - // If this was an empty animation, synthesize a final progress notification - if ( !length ) { - deferred.notifyWith( elem, [ animation, 1, 0 ] ); - } - - // Resolve the animation and report its conclusion - deferred.resolveWith( elem, [ animation ] ); - return false; - }, - animation = deferred.promise( { - elem: elem, - props: jQuery.extend( {}, properties ), - opts: jQuery.extend( true, { - specialEasing: {}, - easing: jQuery.easing._default - }, options ), - originalProperties: properties, - originalOptions: options, - startTime: fxNow || createFxNow(), - duration: options.duration, - tweens: [], - createTween: function( prop, end ) { - var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); - animation.tweens.push( tween ); - return tween; - }, - stop: function( gotoEnd ) { - var index = 0, - - // If we are going to the end, we want to run all the tweens - // otherwise we skip this part - length = gotoEnd ? animation.tweens.length : 0; - if ( stopped ) { - return this; - } - stopped = true; - for ( ; index < length; index++ ) { - animation.tweens[ index ].run( 1 ); - } - - // Resolve when we played the last frame; otherwise, reject - if ( gotoEnd ) { - deferred.notifyWith( elem, [ animation, 1, 0 ] ); - deferred.resolveWith( elem, [ animation, gotoEnd ] ); - } else { - deferred.rejectWith( elem, [ animation, gotoEnd ] ); - } - return this; - } - } ), - props = animation.props; - - propFilter( props, animation.opts.specialEasing ); - - for ( ; index < length; index++ ) { - result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); - if ( result ) { - if ( isFunction( result.stop ) ) { - jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = - result.stop.bind( result ); - } - return result; - } - } - - jQuery.map( props, createTween, animation ); - - if ( isFunction( animation.opts.start ) ) { - animation.opts.start.call( elem, animation ); - } - - // Attach callbacks from options - animation - .progress( animation.opts.progress ) - .done( animation.opts.done, animation.opts.complete ) - .fail( animation.opts.fail ) - .always( animation.opts.always ); - - jQuery.fx.timer( - jQuery.extend( tick, { - elem: elem, - anim: animation, - queue: animation.opts.queue - } ) - ); - - return animation; -} - -jQuery.Animation = jQuery.extend( Animation, { - - tweeners: { - "*": [ function( prop, value ) { - var tween = this.createTween( prop, value ); - adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); - return tween; - } ] - }, - - tweener: function( props, callback ) { - if ( isFunction( props ) ) { - callback = props; - props = [ "*" ]; - } else { - props = props.match( rnothtmlwhite ); - } - - var prop, - index = 0, - length = props.length; - - for ( ; index < length; index++ ) { - prop = props[ index ]; - Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; - Animation.tweeners[ prop ].unshift( callback ); - } - }, - - prefilters: [ defaultPrefilter ], - - prefilter: function( callback, prepend ) { - if ( prepend ) { - Animation.prefilters.unshift( callback ); - } else { - Animation.prefilters.push( callback ); - } - } -} ); - -jQuery.speed = function( speed, easing, fn ) { - var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { - complete: fn || !fn && easing || - isFunction( speed ) && speed, - duration: speed, - easing: fn && easing || easing && !isFunction( easing ) && easing - }; - - // Go to the end state if fx are off - if ( jQuery.fx.off ) { - opt.duration = 0; - - } else { - if ( typeof opt.duration !== "number" ) { - if ( opt.duration in jQuery.fx.speeds ) { - opt.duration = jQuery.fx.speeds[ opt.duration ]; - - } else { - opt.duration = jQuery.fx.speeds._default; - } - } - } - - // Normalize opt.queue - true/undefined/null -> "fx" - if ( opt.queue == null || opt.queue === true ) { - opt.queue = "fx"; - } - - // Queueing - opt.old = opt.complete; - - opt.complete = function() { - if ( isFunction( opt.old ) ) { - opt.old.call( this ); - } - - if ( opt.queue ) { - jQuery.dequeue( this, opt.queue ); - } - }; - - return opt; -}; - -jQuery.fn.extend( { - fadeTo: function( speed, to, easing, callback ) { - - // Show any hidden elements after setting opacity to 0 - return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() - - // Animate to the value specified - .end().animate( { opacity: to }, speed, easing, callback ); - }, - animate: function( prop, speed, easing, callback ) { - var empty = jQuery.isEmptyObject( prop ), - optall = jQuery.speed( speed, easing, callback ), - doAnimation = function() { - - // Operate on a copy of prop so per-property easing won't be lost - var anim = Animation( this, jQuery.extend( {}, prop ), optall ); - - // Empty animations, or finishing resolves immediately - if ( empty || dataPriv.get( this, "finish" ) ) { - anim.stop( true ); - } - }; - doAnimation.finish = doAnimation; - - return empty || optall.queue === false ? - this.each( doAnimation ) : - this.queue( optall.queue, doAnimation ); - }, - stop: function( type, clearQueue, gotoEnd ) { - var stopQueue = function( hooks ) { - var stop = hooks.stop; - delete hooks.stop; - stop( gotoEnd ); - }; - - if ( typeof type !== "string" ) { - gotoEnd = clearQueue; - clearQueue = type; - type = undefined; - } - if ( clearQueue ) { - this.queue( type || "fx", [] ); - } - - return this.each( function() { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = dataPriv.get( this ); - - if ( index ) { - if ( data[ index ] && data[ index ].stop ) { - stopQueue( data[ index ] ); - } - } else { - for ( index in data ) { - if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { - stopQueue( data[ index ] ); - } - } - } - - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && - ( type == null || timers[ index ].queue === type ) ) { - - timers[ index ].anim.stop( gotoEnd ); - dequeue = false; - timers.splice( index, 1 ); - } - } - - // Start the next in the queue if the last step wasn't forced. - // Timers currently will call their complete callbacks, which - // will dequeue but only if they were gotoEnd. - if ( dequeue || !gotoEnd ) { - jQuery.dequeue( this, type ); - } - } ); - }, - finish: function( type ) { - if ( type !== false ) { - type = type || "fx"; - } - return this.each( function() { - var index, - data = dataPriv.get( this ), - queue = data[ type + "queue" ], - hooks = data[ type + "queueHooks" ], - timers = jQuery.timers, - length = queue ? queue.length : 0; - - // Enable finishing flag on private data - data.finish = true; - - // Empty the queue first - jQuery.queue( this, type, [] ); - - if ( hooks && hooks.stop ) { - hooks.stop.call( this, true ); - } - - // Look for any active animations, and finish them - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && timers[ index ].queue === type ) { - timers[ index ].anim.stop( true ); - timers.splice( index, 1 ); - } - } - - // Look for any animations in the old queue and finish them - for ( index = 0; index < length; index++ ) { - if ( queue[ index ] && queue[ index ].finish ) { - queue[ index ].finish.call( this ); - } - } - - // Turn off finishing flag - delete data.finish; - } ); - } -} ); - -jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { - var cssFn = jQuery.fn[ name ]; - jQuery.fn[ name ] = function( speed, easing, callback ) { - return speed == null || typeof speed === "boolean" ? - cssFn.apply( this, arguments ) : - this.animate( genFx( name, true ), speed, easing, callback ); - }; -} ); - -// Generate shortcuts for custom animations -jQuery.each( { - slideDown: genFx( "show" ), - slideUp: genFx( "hide" ), - slideToggle: genFx( "toggle" ), - fadeIn: { opacity: "show" }, - fadeOut: { opacity: "hide" }, - fadeToggle: { opacity: "toggle" } -}, function( name, props ) { - jQuery.fn[ name ] = function( speed, easing, callback ) { - return this.animate( props, speed, easing, callback ); - }; -} ); - -jQuery.timers = []; -jQuery.fx.tick = function() { - var timer, - i = 0, - timers = jQuery.timers; - - fxNow = Date.now(); - - for ( ; i < timers.length; i++ ) { - timer = timers[ i ]; - - // Run the timer and safely remove it when done (allowing for external removal) - if ( !timer() && timers[ i ] === timer ) { - timers.splice( i--, 1 ); - } - } - - if ( !timers.length ) { - jQuery.fx.stop(); - } - fxNow = undefined; -}; - -jQuery.fx.timer = function( timer ) { - jQuery.timers.push( timer ); - jQuery.fx.start(); -}; - -jQuery.fx.interval = 13; -jQuery.fx.start = function() { - if ( inProgress ) { - return; - } - - inProgress = true; - schedule(); -}; - -jQuery.fx.stop = function() { - inProgress = null; -}; - -jQuery.fx.speeds = { - slow: 600, - fast: 200, - - // Default speed - _default: 400 -}; - - -// Based off of the plugin by Clint Helfers, with permission. -// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ -jQuery.fn.delay = function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = window.setTimeout( next, time ); - hooks.stop = function() { - window.clearTimeout( timeout ); - }; - } ); -}; - - -( function() { - var input = document.createElement( "input" ), - select = document.createElement( "select" ), - opt = select.appendChild( document.createElement( "option" ) ); - - input.type = "checkbox"; - - // Support: Android <=4.3 only - // Default value for a checkbox should be "on" - support.checkOn = input.value !== ""; - - // Support: IE <=11 only - // Must access selectedIndex to make default options select - support.optSelected = opt.selected; - - // Support: IE <=11 only - // An input loses its value after becoming a radio - input = document.createElement( "input" ); - input.value = "t"; - input.type = "radio"; - support.radioValue = input.value === "t"; -} )(); - - -var boolHook, - attrHandle = jQuery.expr.attrHandle; - -jQuery.fn.extend( { - attr: function( name, value ) { - return access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each( function() { - jQuery.removeAttr( this, name ); - } ); - } -} ); - -jQuery.extend( { - attr: function( elem, name, value ) { - var ret, hooks, - nType = elem.nodeType; - - // Don't get/set attributes on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { - return jQuery.prop( elem, name, value ); - } - - // Attribute hooks are determined by the lowercase version - // Grab necessary hook if one is defined - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - hooks = jQuery.attrHooks[ name.toLowerCase() ] || - ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); - } - - if ( value !== undefined ) { - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return; - } - - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - elem.setAttribute( name, value + "" ); - return value; - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - ret = jQuery.find.attr( elem, name ); - - // Non-existent attributes return null, we normalize to undefined - return ret == null ? undefined : ret; - }, - - attrHooks: { - type: { - set: function( elem, value ) { - if ( !support.radioValue && value === "radio" && - nodeName( elem, "input" ) ) { - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - } - }, - - removeAttr: function( elem, value ) { - var name, - i = 0, - - // Attribute names can contain non-HTML whitespace characters - // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 - attrNames = value && value.match( rnothtmlwhite ); - - if ( attrNames && elem.nodeType === 1 ) { - while ( ( name = attrNames[ i++ ] ) ) { - elem.removeAttribute( name ); - } - } - } -} ); - -// Hooks for boolean attributes -boolHook = { - set: function( elem, value, name ) { - if ( value === false ) { - - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - elem.setAttribute( name, name ); - } - return name; - } -}; - -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { - var getter = attrHandle[ name ] || jQuery.find.attr; - - attrHandle[ name ] = function( elem, name, isXML ) { - var ret, handle, - lowercaseName = name.toLowerCase(); - - if ( !isXML ) { - - // Avoid an infinite loop by temporarily removing this function from the getter - handle = attrHandle[ lowercaseName ]; - attrHandle[ lowercaseName ] = ret; - ret = getter( elem, name, isXML ) != null ? - lowercaseName : - null; - attrHandle[ lowercaseName ] = handle; - } - return ret; - }; -} ); - - - - -var rfocusable = /^(?:input|select|textarea|button)$/i, - rclickable = /^(?:a|area)$/i; - -jQuery.fn.extend( { - prop: function( name, value ) { - return access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - return this.each( function() { - delete this[ jQuery.propFix[ name ] || name ]; - } ); - } -} ); - -jQuery.extend( { - prop: function( elem, name, value ) { - var ret, hooks, - nType = elem.nodeType; - - // Don't get/set properties on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - return ( elem[ name ] = value ); - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - return elem[ name ]; - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - - // Support: IE <=9 - 11 only - // elem.tabIndex doesn't always return the - // correct value when it hasn't been explicitly set - // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - // Use proper attribute retrieval(#12072) - var tabindex = jQuery.find.attr( elem, "tabindex" ); - - if ( tabindex ) { - return parseInt( tabindex, 10 ); - } - - if ( - rfocusable.test( elem.nodeName ) || - rclickable.test( elem.nodeName ) && - elem.href - ) { - return 0; - } - - return -1; - } - } - }, - - propFix: { - "for": "htmlFor", - "class": "className" - } -} ); - -// Support: IE <=11 only -// Accessing the selectedIndex property -// forces the browser to respect setting selected -// on the option -// The getter ensures a default option is selected -// when in an optgroup -// eslint rule "no-unused-expressions" is disabled for this code -// since it considers such accessions noop -if ( !support.optSelected ) { - jQuery.propHooks.selected = { - get: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent && parent.parentNode ) { - parent.parentNode.selectedIndex; - } - return null; - }, - set: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent ) { - parent.selectedIndex; - - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - } - }; -} - -jQuery.each( [ - "tabIndex", - "readOnly", - "maxLength", - "cellSpacing", - "cellPadding", - "rowSpan", - "colSpan", - "useMap", - "frameBorder", - "contentEditable" -], function() { - jQuery.propFix[ this.toLowerCase() ] = this; -} ); - - - - - // Strip and collapse whitespace according to HTML spec - // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace - function stripAndCollapse( value ) { - var tokens = value.match( rnothtmlwhite ) || []; - return tokens.join( " " ); - } - - -function getClass( elem ) { - return elem.getAttribute && elem.getAttribute( "class" ) || ""; -} - -function classesToArray( value ) { - if ( Array.isArray( value ) ) { - return value; - } - if ( typeof value === "string" ) { - return value.match( rnothtmlwhite ) || []; - } - return []; -} - -jQuery.fn.extend( { - addClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - if ( cur.indexOf( " " + clazz + " " ) < 0 ) { - cur += clazz + " "; - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - if ( !arguments.length ) { - return this.attr( "class", "" ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - - // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - - // Remove *all* instances - while ( cur.indexOf( " " + clazz + " " ) > -1 ) { - cur = cur.replace( " " + clazz + " ", " " ); - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isValidValue = type === "string" || Array.isArray( value ); - - if ( typeof stateVal === "boolean" && isValidValue ) { - return stateVal ? this.addClass( value ) : this.removeClass( value ); - } - - if ( isFunction( value ) ) { - return this.each( function( i ) { - jQuery( this ).toggleClass( - value.call( this, i, getClass( this ), stateVal ), - stateVal - ); - } ); - } - - return this.each( function() { - var className, i, self, classNames; - - if ( isValidValue ) { - - // Toggle individual class names - i = 0; - self = jQuery( this ); - classNames = classesToArray( value ); - - while ( ( className = classNames[ i++ ] ) ) { - - // Check each className given, space separated list - if ( self.hasClass( className ) ) { - self.removeClass( className ); - } else { - self.addClass( className ); - } - } - - // Toggle whole class name - } else if ( value === undefined || type === "boolean" ) { - className = getClass( this ); - if ( className ) { - - // Store className if set - dataPriv.set( this, "__className__", className ); - } - - // If the element has a class name or if we're passed `false`, - // then remove the whole classname (if there was one, the above saved it). - // Otherwise bring back whatever was previously saved (if anything), - // falling back to the empty string if nothing was stored. - if ( this.setAttribute ) { - this.setAttribute( "class", - className || value === false ? - "" : - dataPriv.get( this, "__className__" ) || "" - ); - } - } - } ); - }, - - hasClass: function( selector ) { - var className, elem, - i = 0; - - className = " " + selector + " "; - while ( ( elem = this[ i++ ] ) ) { - if ( elem.nodeType === 1 && - ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { - return true; - } - } - - return false; - } -} ); - - - - -var rreturn = /\r/g; - -jQuery.fn.extend( { - val: function( value ) { - var hooks, ret, valueIsFunction, - elem = this[ 0 ]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || - jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && - "get" in hooks && - ( ret = hooks.get( elem, "value" ) ) !== undefined - ) { - return ret; - } - - ret = elem.value; - - // Handle most common string cases - if ( typeof ret === "string" ) { - return ret.replace( rreturn, "" ); - } - - // Handle cases where value is null/undef or number - return ret == null ? "" : ret; - } - - return; - } - - valueIsFunction = isFunction( value ); - - return this.each( function( i ) { - var val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( valueIsFunction ) { - val = value.call( this, i, jQuery( this ).val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - - } else if ( typeof val === "number" ) { - val += ""; - - } else if ( Array.isArray( val ) ) { - val = jQuery.map( val, function( value ) { - return value == null ? "" : value + ""; - } ); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - } ); - } -} ); - -jQuery.extend( { - valHooks: { - option: { - get: function( elem ) { - - var val = jQuery.find.attr( elem, "value" ); - return val != null ? - val : - - // Support: IE <=10 - 11 only - // option.text throws exceptions (#14686, #14858) - // Strip and collapse whitespace - // https://html.spec.whatwg.org/#strip-and-collapse-whitespace - stripAndCollapse( jQuery.text( elem ) ); - } - }, - select: { - get: function( elem ) { - var value, option, i, - options = elem.options, - index = elem.selectedIndex, - one = elem.type === "select-one", - values = one ? null : [], - max = one ? index + 1 : options.length; - - if ( index < 0 ) { - i = max; - - } else { - i = one ? index : 0; - } - - // Loop through all the selected options - for ( ; i < max; i++ ) { - option = options[ i ]; - - // Support: IE <=9 only - // IE8-9 doesn't update selected after form reset (#2551) - if ( ( option.selected || i === index ) && - - // Don't return options that are disabled or in a disabled optgroup - !option.disabled && - ( !option.parentNode.disabled || - !nodeName( option.parentNode, "optgroup" ) ) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - }, - - set: function( elem, value ) { - var optionSet, option, - options = elem.options, - values = jQuery.makeArray( value ), - i = options.length; - - while ( i-- ) { - option = options[ i ]; - - /* eslint-disable no-cond-assign */ - - if ( option.selected = - jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 - ) { - optionSet = true; - } - - /* eslint-enable no-cond-assign */ - } - - // Force browsers to behave consistently when non-matching value is set - if ( !optionSet ) { - elem.selectedIndex = -1; - } - return values; - } - } - } -} ); - -// Radios and checkboxes getter/setter -jQuery.each( [ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - set: function( elem, value ) { - if ( Array.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); - } - } - }; - if ( !support.checkOn ) { - jQuery.valHooks[ this ].get = function( elem ) { - return elem.getAttribute( "value" ) === null ? "on" : elem.value; - }; - } -} ); - - - - -// Return jQuery for attributes-only inclusion - - -support.focusin = "onfocusin" in window; - - -var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - stopPropagationCallback = function( e ) { - e.stopPropagation(); - }; - -jQuery.extend( jQuery.event, { - - trigger: function( event, data, elem, onlyHandlers ) { - - var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; - - cur = lastElement = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf( "." ) > -1 ) { - - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split( "." ); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf( ":" ) < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join( "." ); - event.rnamespace = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === ( elem.ownerDocument || document ) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { - lastElement = cur; - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( - dataPriv.get( cur, "events" ) || Object.create( null ) - )[ event.type ] && - dataPriv.get( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === false ) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( ( !special._default || - special._default.apply( eventPath.pop(), data ) === false ) && - acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name as the event. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - - if ( event.isPropagationStopped() ) { - lastElement.addEventListener( type, stopPropagationCallback ); - } - - elem[ type ](); - - if ( event.isPropagationStopped() ) { - lastElement.removeEventListener( type, stopPropagationCallback ); - } - - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - // Piggyback on a donor event to simulate a different one - // Used only for `focus(in | out)` events - simulate: function( type, elem, event ) { - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true - } - ); - - jQuery.event.trigger( e, null, elem ); - } - -} ); - -jQuery.fn.extend( { - - trigger: function( type, data ) { - return this.each( function() { - jQuery.event.trigger( type, data, this ); - } ); - }, - triggerHandler: function( type, data ) { - var elem = this[ 0 ]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } - } -} ); - - -// Support: Firefox <=44 -// Firefox doesn't have focus(in | out) events -// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 -// -// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 -// focus(in | out) events fire after focus & blur events, -// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order -// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 -if ( !support.focusin ) { - jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - - // Handle: regular nodes (via `this.ownerDocument`), window - // (via `this.document`) & document (via `this`). - var doc = this.ownerDocument || this.document || this, - attaches = dataPriv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this.document || this, - attaches = dataPriv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - dataPriv.remove( doc, fix ); - - } else { - dataPriv.access( doc, fix, attaches ); - } - } - }; - } ); -} -var location = window.location; - -var nonce = { guid: Date.now() }; - -var rquery = ( /\?/ ); - - - -// Cross-browser xml parsing -jQuery.parseXML = function( data ) { - var xml; - if ( !data || typeof data !== "string" ) { - return null; - } - - // Support: IE 9 - 11 only - // IE throws on parseFromString with invalid input. - try { - xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); - } catch ( e ) { - xml = undefined; - } - - if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; -}; - - -var - rbracket = /\[\]$/, - rCRLF = /\r?\n/g, - rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, - rsubmittable = /^(?:input|select|textarea|keygen)/i; - -function buildParams( prefix, obj, traditional, add ) { - var name; - - if ( Array.isArray( obj ) ) { - - // Serialize array item. - jQuery.each( obj, function( i, v ) { - if ( traditional || rbracket.test( prefix ) ) { - - // Treat each array item as a scalar. - add( prefix, v ); - - } else { - - // Item is non-scalar (array or object), encode its numeric index. - buildParams( - prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", - v, - traditional, - add - ); - } - } ); - - } else if ( !traditional && toType( obj ) === "object" ) { - - // Serialize object item. - for ( name in obj ) { - buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); - } - - } else { - - // Serialize scalar item. - add( prefix, obj ); - } -} - -// Serialize an array of form elements or a set of -// key/values into a query string -jQuery.param = function( a, traditional ) { - var prefix, - s = [], - add = function( key, valueOrFunction ) { - - // If value is a function, invoke it and use its return value - var value = isFunction( valueOrFunction ) ? - valueOrFunction() : - valueOrFunction; - - s[ s.length ] = encodeURIComponent( key ) + "=" + - encodeURIComponent( value == null ? "" : value ); - }; - - if ( a == null ) { - return ""; - } - - // If an array was passed in, assume that it is an array of form elements. - if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { - - // Serialize the form elements - jQuery.each( a, function() { - add( this.name, this.value ); - } ); - - } else { - - // If traditional, encode the "old" way (the way 1.3.2 or older - // did it), otherwise encode params recursively. - for ( prefix in a ) { - buildParams( prefix, a[ prefix ], traditional, add ); - } - } - - // Return the resulting serialization - return s.join( "&" ); -}; - -jQuery.fn.extend( { - serialize: function() { - return jQuery.param( this.serializeArray() ); - }, - serializeArray: function() { - return this.map( function() { - - // Can add propHook for "elements" to filter or add form elements - var elements = jQuery.prop( this, "elements" ); - return elements ? jQuery.makeArray( elements ) : this; - } ) - .filter( function() { - var type = this.type; - - // Use .is( ":disabled" ) so that fieldset[disabled] works - return this.name && !jQuery( this ).is( ":disabled" ) && - rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && - ( this.checked || !rcheckableType.test( type ) ); - } ) - .map( function( _i, elem ) { - var val = jQuery( this ).val(); - - if ( val == null ) { - return null; - } - - if ( Array.isArray( val ) ) { - return jQuery.map( val, function( val ) { - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ); - } - - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ).get(); - } -} ); - - -var - r20 = /%20/g, - rhash = /#.*$/, - rantiCache = /([?&])_=[^&]*/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, - - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = "*/".concat( "*" ), - - // Anchor tag for parsing the document origin - originAnchor = document.createElement( "a" ); - originAnchor.href = location.href; - -// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport -function addToPrefiltersOrTransports( structure ) { - - // dataTypeExpression is optional and defaults to "*" - return function( dataTypeExpression, func ) { - - if ( typeof dataTypeExpression !== "string" ) { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, - i = 0, - dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; - - if ( isFunction( func ) ) { - - // For each dataType in the dataTypeExpression - while ( ( dataType = dataTypes[ i++ ] ) ) { - - // Prepend if requested - if ( dataType[ 0 ] === "+" ) { - dataType = dataType.slice( 1 ) || "*"; - ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); - - // Otherwise append - } else { - ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); - } - } - } - }; -} - -// Base inspection function for prefilters and transports -function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { - - var inspected = {}, - seekingTransport = ( structure === transports ); - - function inspect( dataType ) { - var selected; - inspected[ dataType ] = true; - jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { - var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); - if ( typeof dataTypeOrTransport === "string" && - !seekingTransport && !inspected[ dataTypeOrTransport ] ) { - - options.dataTypes.unshift( dataTypeOrTransport ); - inspect( dataTypeOrTransport ); - return false; - } else if ( seekingTransport ) { - return !( selected = dataTypeOrTransport ); - } - } ); - return selected; - } - - return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); -} - -// A special extend for ajax options -// that takes "flat" options (not to be deep extended) -// Fixes #9887 -function ajaxExtend( target, src ) { - var key, deep, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - - for ( key in src ) { - if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; - } - } - if ( deep ) { - jQuery.extend( true, target, deep ); - } - - return target; -} - -/* Handles responses to an ajax request: - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ -function ajaxHandleResponses( s, jqXHR, responses ) { - - var ct, type, finalDataType, firstDataType, - contents = s.contents, - dataTypes = s.dataTypes; - - // Remove auto dataType and get content-type in the process - while ( dataTypes[ 0 ] === "*" ) { - dataTypes.shift(); - if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); - } - } - - // Check if we're dealing with a known content-type - if ( ct ) { - for ( type in contents ) { - if ( contents[ type ] && contents[ type ].test( ct ) ) { - dataTypes.unshift( type ); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if ( dataTypes[ 0 ] in responses ) { - finalDataType = dataTypes[ 0 ]; - } else { - - // Try convertible dataTypes - for ( type in responses ) { - if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { - finalDataType = type; - break; - } - if ( !firstDataType ) { - firstDataType = type; - } - } - - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if ( finalDataType ) { - if ( finalDataType !== dataTypes[ 0 ] ) { - dataTypes.unshift( finalDataType ); - } - return responses[ finalDataType ]; - } -} - -/* Chain conversions given the request and the original response - * Also sets the responseXXX fields on the jqXHR instance - */ -function ajaxConvert( s, response, jqXHR, isSuccess ) { - var conv2, current, conv, tmp, prev, - converters = {}, - - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(); - - // Create converters map with lowercased keys - if ( dataTypes[ 1 ] ) { - for ( conv in s.converters ) { - converters[ conv.toLowerCase() ] = s.converters[ conv ]; - } - } - - current = dataTypes.shift(); - - // Convert to each sequential dataType - while ( current ) { - - if ( s.responseFields[ current ] ) { - jqXHR[ s.responseFields[ current ] ] = response; - } - - // Apply the dataFilter if provided - if ( !prev && isSuccess && s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } - - prev = current; - current = dataTypes.shift(); - - if ( current ) { - - // There's only work to do if current dataType is non-auto - if ( current === "*" ) { - - current = prev; - - // Convert response if prev dataType is non-auto and differs from current - } else if ( prev !== "*" && prev !== current ) { - - // Seek a direct converter - conv = converters[ prev + " " + current ] || converters[ "* " + current ]; - - // If none found, seek a pair - if ( !conv ) { - for ( conv2 in converters ) { - - // If conv2 outputs current - tmp = conv2.split( " " ); - if ( tmp[ 1 ] === current ) { - - // If prev can be converted to accepted input - conv = converters[ prev + " " + tmp[ 0 ] ] || - converters[ "* " + tmp[ 0 ] ]; - if ( conv ) { - - // Condense equivalence converters - if ( conv === true ) { - conv = converters[ conv2 ]; - - // Otherwise, insert the intermediate dataType - } else if ( converters[ conv2 ] !== true ) { - current = tmp[ 0 ]; - dataTypes.unshift( tmp[ 1 ] ); - } - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if ( conv !== true ) { - - // Unless errors are allowed to bubble, catch and return them - if ( conv && s.throws ) { - response = conv( response ); - } else { - try { - response = conv( response ); - } catch ( e ) { - return { - state: "parsererror", - error: conv ? e : "No conversion from " + prev + " to " + current - }; - } - } - } - } - } - } - - return { state: "success", data: response }; -} - -jQuery.extend( { - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {}, - - ajaxSettings: { - url: location.href, - type: "GET", - isLocal: rlocalProtocol.test( location.protocol ), - global: true, - processData: true, - async: true, - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - "*": allTypes, - text: "text/plain", - html: "text/html", - xml: "application/xml, text/xml", - json: "application/json, text/javascript" - }, - - contents: { - xml: /\bxml\b/, - html: /\bhtml/, - json: /\bjson\b/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText", - json: "responseJSON" - }, - - // Data converters - // Keys separate source (or catchall "*") and destination types with a single space - converters: { - - // Convert anything to text - "* text": String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": JSON.parse, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - url: true, - context: true - } - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - return settings ? - - // Building a settings object - ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : - - // Extending ajaxSettings - ajaxExtend( jQuery.ajaxSettings, target ); - }, - - ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), - ajaxTransport: addToPrefiltersOrTransports( transports ), - - // Main method - ajax: function( url, options ) { - - // If url is an object, simulate pre-1.5 signature - if ( typeof url === "object" ) { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var transport, - - // URL without anti-cache param - cacheURL, - - // Response headers - responseHeadersString, - responseHeaders, - - // timeout handle - timeoutTimer, - - // Url cleanup var - urlAnchor, - - // Request state (becomes false upon send and true upon completion) - completed, - - // To know if global events are to be dispatched - fireGlobals, - - // Loop variable - i, - - // uncached part of the url - uncached, - - // Create the final options object - s = jQuery.ajaxSetup( {}, options ), - - // Callbacks context - callbackContext = s.context || s, - - // Context for global events is callbackContext if it is a DOM node or jQuery collection - globalEventContext = s.context && - ( callbackContext.nodeType || callbackContext.jquery ) ? - jQuery( callbackContext ) : - jQuery.event, - - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks( "once memory" ), - - // Status-dependent callbacks - statusCode = s.statusCode || {}, - - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - - // Default abort message - strAbort = "canceled", - - // Fake xhr - jqXHR = { - readyState: 0, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( completed ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while ( ( match = rheaders.exec( responseHeadersString ) ) ) { - responseHeaders[ match[ 1 ].toLowerCase() + " " ] = - ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) - .concat( match[ 2 ] ); - } - } - match = responseHeaders[ key.toLowerCase() + " " ]; - } - return match == null ? null : match.join( ", " ); - }, - - // Raw string - getAllResponseHeaders: function() { - return completed ? responseHeadersString : null; - }, - - // Caches the header - setRequestHeader: function( name, value ) { - if ( completed == null ) { - name = requestHeadersNames[ name.toLowerCase() ] = - requestHeadersNames[ name.toLowerCase() ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( completed == null ) { - s.mimeType = type; - } - return this; - }, - - // Status-dependent callbacks - statusCode: function( map ) { - var code; - if ( map ) { - if ( completed ) { - - // Execute the appropriate callbacks - jqXHR.always( map[ jqXHR.status ] ); - } else { - - // Lazy-add the new callbacks in a way that preserves old ones - for ( code in map ) { - statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; - } - } - } - return this; - }, - - // Cancel the request - abort: function( statusText ) { - var finalText = statusText || strAbort; - if ( transport ) { - transport.abort( finalText ); - } - done( 0, finalText ); - return this; - } - }; - - // Attach deferreds - deferred.promise( jqXHR ); - - // Add protocol if not provided (prefilters might expect it) - // Handle falsy url in the settings object (#10093: consistency with old signature) - // We also use the url parameter if available - s.url = ( ( url || s.url || location.href ) + "" ) - .replace( rprotocol, location.protocol + "//" ); - - // Alias method option to type as per ticket #12004 - s.type = options.method || options.type || s.method || s.type; - - // Extract dataTypes list - s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; - - // A cross-domain request is in order when the origin doesn't match the current origin. - if ( s.crossDomain == null ) { - urlAnchor = document.createElement( "a" ); - - // Support: IE <=8 - 11, Edge 12 - 15 - // IE throws exception on accessing the href property if url is malformed, - // e.g. http://example.com:80x/ - try { - urlAnchor.href = s.url; - - // Support: IE <=8 - 11 only - // Anchor's host property isn't correctly set when s.url is relative - urlAnchor.href = urlAnchor.href; - s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== - urlAnchor.protocol + "//" + urlAnchor.host; - } catch ( e ) { - - // If there is an error parsing the URL, assume it is crossDomain, - // it can be rejected by the transport if it is invalid - s.crossDomain = true; - } - } - - // Convert data if not already a string - if ( s.data && s.processData && typeof s.data !== "string" ) { - s.data = jQuery.param( s.data, s.traditional ); - } - - // Apply prefilters - inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); - - // If request was aborted inside a prefilter, stop there - if ( completed ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) - fireGlobals = jQuery.event && s.global; - - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger( "ajaxStart" ); - } - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test( s.type ); - - // Save the URL in case we're toying with the If-Modified-Since - // and/or If-None-Match header later on - // Remove hash to simplify url manipulation - cacheURL = s.url.replace( rhash, "" ); - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // Remember the hash so we can put it back - uncached = s.url.slice( cacheURL.length ); - - // If data is available and should be processed, append data to url - if ( s.data && ( s.processData || typeof s.data === "string" ) ) { - cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; - - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Add or update anti-cache param if needed - if ( s.cache === false ) { - cacheURL = cacheURL.replace( rantiCache, "$1" ); - uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + - uncached; - } - - // Put hash and anti-cache on the URL that will be requested (gh-1732) - s.url = cacheURL + uncached; - - // Change '%20' to '+' if this is encoded form body content (gh-2658) - } else if ( s.data && s.processData && - ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { - s.data = s.data.replace( r20, "+" ); - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - if ( jQuery.lastModified[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); - } - if ( jQuery.etag[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); - } - } - - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? - s.accepts[ s.dataTypes[ 0 ] ] + - ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : - s.accepts[ "*" ] - ); - - // Check for headers option - for ( i in s.headers ) { - jqXHR.setRequestHeader( i, s.headers[ i ] ); - } - - // Allow custom headers/mimetypes and early abort - if ( s.beforeSend && - ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { - - // Abort if not done already and return - return jqXHR.abort(); - } - - // Aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - completeDeferred.add( s.complete ); - jqXHR.done( s.success ); - jqXHR.fail( s.error ); - - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - jqXHR.readyState = 1; - - // Send global event - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - - // If request was aborted inside ajaxSend, stop there - if ( completed ) { - return jqXHR; - } - - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = window.setTimeout( function() { - jqXHR.abort( "timeout" ); - }, s.timeout ); - } - - try { - completed = false; - transport.send( requestHeaders, done ); - } catch ( e ) { - - // Rethrow post-completion exceptions - if ( completed ) { - throw e; - } - - // Propagate others as results - done( -1, e ); - } - } - - // Callback for when everything is done - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Ignore repeat invocations - if ( completed ) { - return; - } - - completed = true; - - // Clear timeout if it exists - if ( timeoutTimer ) { - window.clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Determine if successful - isSuccess = status >= 200 && status < 300 || status === 304; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // Use a noop converter for missing script - if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { - s.converters[ "text script" ] = function() {}; - } - - // Convert no matter what (that way responseXXX fields are always set) - response = ajaxConvert( s, response, jqXHR, isSuccess ); - - // If successful, handle type chaining - if ( isSuccess ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - modified = jqXHR.getResponseHeader( "Last-Modified" ); - if ( modified ) { - jQuery.lastModified[ cacheURL ] = modified; - } - modified = jqXHR.getResponseHeader( "etag" ); - if ( modified ) { - jQuery.etag[ cacheURL ] = modified; - } - } - - // if no content - if ( status === 204 || s.type === "HEAD" ) { - statusText = "nocontent"; - - // if not modified - } else if ( status === 304 ) { - statusText = "notmodified"; - - // If we have data, let's convert it - } else { - statusText = response.state; - success = response.data; - error = response.error; - isSuccess = !error; - } - } else { - - // Extract error from statusText and normalize for non-aborts - error = statusText; - if ( status || !statusText ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger( "ajaxStop" ); - } - } - } - - return jqXHR; - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, - - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - } -} ); - -jQuery.each( [ "get", "post" ], function( _i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - - // Shift arguments if data argument was omitted - if ( isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - // The url can be an options object (which then must have .url) - return jQuery.ajax( jQuery.extend( { - url: url, - type: method, - dataType: type, - data: data, - success: callback - }, jQuery.isPlainObject( url ) && url ) ); - }; -} ); - -jQuery.ajaxPrefilter( function( s ) { - var i; - for ( i in s.headers ) { - if ( i.toLowerCase() === "content-type" ) { - s.contentType = s.headers[ i ] || ""; - } - } -} ); - - -jQuery._evalUrl = function( url, options, doc ) { - return jQuery.ajax( { - url: url, - - // Make this explicit, since user can override this through ajaxSetup (#11264) - type: "GET", - dataType: "script", - cache: true, - async: false, - global: false, - - // Only evaluate the response if it is successful (gh-4126) - // dataFilter is not invoked for failure responses, so using it instead - // of the default converter is kludgy but it works. - converters: { - "text script": function() {} - }, - dataFilter: function( response ) { - jQuery.globalEval( response, options, doc ); - } - } ); -}; - - -jQuery.fn.extend( { - wrapAll: function( html ) { - var wrap; - - if ( this[ 0 ] ) { - if ( isFunction( html ) ) { - html = html.call( this[ 0 ] ); - } - - // The elements to wrap the target around - wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); - - if ( this[ 0 ].parentNode ) { - wrap.insertBefore( this[ 0 ] ); - } - - wrap.map( function() { - var elem = this; - - while ( elem.firstElementChild ) { - elem = elem.firstElementChild; - } - - return elem; - } ).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( isFunction( html ) ) { - return this.each( function( i ) { - jQuery( this ).wrapInner( html.call( this, i ) ); - } ); - } - - return this.each( function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - } ); - }, - - wrap: function( html ) { - var htmlIsFunction = isFunction( html ); - - return this.each( function( i ) { - jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); - } ); - }, - - unwrap: function( selector ) { - this.parent( selector ).not( "body" ).each( function() { - jQuery( this ).replaceWith( this.childNodes ); - } ); - return this; - } -} ); - - -jQuery.expr.pseudos.hidden = function( elem ) { - return !jQuery.expr.pseudos.visible( elem ); -}; -jQuery.expr.pseudos.visible = function( elem ) { - return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); -}; - - - - -jQuery.ajaxSettings.xhr = function() { - try { - return new window.XMLHttpRequest(); - } catch ( e ) {} -}; - -var xhrSuccessStatus = { - - // File protocol always yields status code 0, assume 200 - 0: 200, - - // Support: IE <=9 only - // #1450: sometimes IE returns 1223 when it should be 204 - 1223: 204 - }, - xhrSupported = jQuery.ajaxSettings.xhr(); - -support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); -support.ajax = xhrSupported = !!xhrSupported; - -jQuery.ajaxTransport( function( options ) { - var callback, errorCallback; - - // Cross domain only allowed if supported through XMLHttpRequest - if ( support.cors || xhrSupported && !options.crossDomain ) { - return { - send: function( headers, complete ) { - var i, - xhr = options.xhr(); - - xhr.open( - options.type, - options.url, - options.async, - options.username, - options.password - ); - - // Apply custom fields if provided - if ( options.xhrFields ) { - for ( i in options.xhrFields ) { - xhr[ i ] = options.xhrFields[ i ]; - } - } - - // Override mime type if needed - if ( options.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( options.mimeType ); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { - headers[ "X-Requested-With" ] = "XMLHttpRequest"; - } - - // Set headers - for ( i in headers ) { - xhr.setRequestHeader( i, headers[ i ] ); - } - - // Callback - callback = function( type ) { - return function() { - if ( callback ) { - callback = errorCallback = xhr.onload = - xhr.onerror = xhr.onabort = xhr.ontimeout = - xhr.onreadystatechange = null; - - if ( type === "abort" ) { - xhr.abort(); - } else if ( type === "error" ) { - - // Support: IE <=9 only - // On a manual native abort, IE9 throws - // errors on any property access that is not readyState - if ( typeof xhr.status !== "number" ) { - complete( 0, "error" ); - } else { - complete( - - // File: protocol always yields status 0; see #8605, #14207 - xhr.status, - xhr.statusText - ); - } - } else { - complete( - xhrSuccessStatus[ xhr.status ] || xhr.status, - xhr.statusText, - - // Support: IE <=9 only - // IE9 has no XHR2 but throws on binary (trac-11426) - // For XHR2 non-text, let the caller handle it (gh-2498) - ( xhr.responseType || "text" ) !== "text" || - typeof xhr.responseText !== "string" ? - { binary: xhr.response } : - { text: xhr.responseText }, - xhr.getAllResponseHeaders() - ); - } - } - }; - }; - - // Listen to events - xhr.onload = callback(); - errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); - - // Support: IE 9 only - // Use onreadystatechange to replace onabort - // to handle uncaught aborts - if ( xhr.onabort !== undefined ) { - xhr.onabort = errorCallback; - } else { - xhr.onreadystatechange = function() { - - // Check readyState before timeout as it changes - if ( xhr.readyState === 4 ) { - - // Allow onerror to be called first, - // but that will not handle a native abort - // Also, save errorCallback to a variable - // as xhr.onerror cannot be accessed - window.setTimeout( function() { - if ( callback ) { - errorCallback(); - } - } ); - } - }; - } - - // Create the abort callback - callback = callback( "abort" ); - - try { - - // Do send the request (this may raise an exception) - xhr.send( options.hasContent && options.data || null ); - } catch ( e ) { - - // #14683: Only rethrow if this hasn't been notified as an error yet - if ( callback ) { - throw e; - } - } - }, - - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -} ); - - - - -// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) -jQuery.ajaxPrefilter( function( s ) { - if ( s.crossDomain ) { - s.contents.script = false; - } -} ); - -// Install script dataType -jQuery.ajaxSetup( { - accepts: { - script: "text/javascript, application/javascript, " + - "application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /\b(?:java|ecma)script\b/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } -} ); - -// Handle cache's special case and crossDomain -jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - } -} ); - -// Bind script tag hack transport -jQuery.ajaxTransport( "script", function( s ) { - - // This transport only deals with cross domain or forced-by-attrs requests - if ( s.crossDomain || s.scriptAttrs ) { - var script, callback; - return { - send: function( _, complete ) { - script = jQuery( " - - - - - - - - - - - - - - - -
- - -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/index.html b/doc/_build/html/index.html deleted file mode 100644 index 8fb7099..0000000 --- a/doc/_build/html/index.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - Welcome to BiAPoL utilities’s documentation! — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

Welcome to BiAPoL utilities’s documentation!

-

On this page, we provide documentation pages for our API and provide -comprehensive examples on how to use the functions in our library.

- -
-
-

Indices and tables

- -
-
-

Ressources

-
-
-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/objects.inv b/doc/_build/html/objects.inv deleted file mode 100644 index c84ecea155641e68a3d15e823aa3713108058dff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1448 zcmV;Z1y}kbAX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkHX+cnL zOdxf1X>4h9X=QT?BOq2~a&u{KZaN?eBOp|0Wgv28ZDDC{WMy(7Z)PBLXlZjGW@&6? zAZc?TV{dJ6a%FRKWn>_Ab7^j8AbM7fAG>GrWq0!q>Z`~ZBC1W_5{?GsLLjwlYdhw09nBaI{P2EY#kp$Hvt zvOm5Hq}HH%hBLUCSTZpTkwaPF5$^*2T|CvV0m=G88uVq(G3b|hpaS{D6+ zqTrhoyF%63`nFYrGUDg>5$8Aw@Fp)PC}?=gdjTk!`*?pR$yJH~YXT2V)0|3=wZOJT z*+8$Gx;c8pu!?vXr(qds80>fa?TA5j4aD`LQEtS@YNuyqR`eX$Rhwpx3s|Y>uTVpG}CyK@>@FvG=OWB z+8c2S>m>Q+uA8O%7OuNa{B1cEi=e$kG2p;Gr)7Z?3hR9e1b0K}rc`h^l$S0V^hiXD zDK;P@RnkZspenh%GiQ{HUB=;gF4?ie^Tt+mc(IZ-WvPv-8$;;U)vYlVziyptHyq{_ zujO#8Rr@9>#fLQgR&2Szw#k4B{1oGaqH2*YHY7VGhY82}8a|C`;NknVLfcgujzEZO{CZDi2;@sokNUX0kfI8)Ke5RJ8Fc0kWhXGSH$y-Y5TsFB=K4sy zI#)PrV~Z24wb{V*c5{m7ec;REFf|m-d<=fa5u1$|&=mYgKHjH0&~E787a&Z7vYk)g zN&4908IpiyODG8;MTY@Dd^RyAdMBCyYXYK4)}7;`VEBU>os!5y`&ZWSD*S>pg@X*Q zfE~Xkjp*pm8prWB5jYMesrSyufG!_ZGjXDzch)_s**W=XckHNxaXqd}|Kv#rw|%{) z$GwkYb97c>O26u2au$`A43`=13q-0`#c1Y*8S!OP)7s;-oL@?L>L|*!3SFgSO$pI* zmaClTDA_Ye;!s9_nxeC_@J*NM*5 z0Ps1s_pg?>zi11kYmiKBQJ8|MS=1gYu3Hs$0w2n6#AQT1=(Fz?e`x8B~OtI7ZStFsmW(GR%QoZYQ$qLNXjZ9b- z80D;YM^?0nhx4nre~+H<2ipA*#@!b+wD+lt%dci$&nu_cg=c87wRyO)rTSl)+C3~x CIL5vJ diff --git a/doc/_build/html/search.html b/doc/_build/html/search.html deleted file mode 100644 index df21b5d..0000000 --- a/doc/_build/html/search.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - Search — BiAPoL utilities 0.0.1 documentation - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -

Search

- - - - -

- Searching for multiple words only shows matches that contain - all words. -

- - -
- - - -
- - - -
- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/doc/_build/html/searchindex.js b/doc/_build/html/searchindex.js deleted file mode 100644 index 8c31e0a..0000000 --- a/doc/_build/html/searchindex.js +++ /dev/null @@ -1 +0,0 @@ -Search.setIndex({docnames:["_include/API_reference","_include/Examples","_include/biapol_utilities.label.compare_labels","_include/biapol_utilities.label.intersection_over_union_matrix","_include/biapol_utilities.label.match_labels_stack","_include/generated/biapol_utilities.data.blobs","_include/generated/biapol_utilities.label.compare_labels","_include/generated/biapol_utilities.label.intersection_over_union_matrix","_include/generated/biapol_utilities.label.match_labels","_include/generated/biapol_utilities.label.match_labels_stack","_include/notebooks/label/Compare_segmentations","_include/notebooks/label/match_labels","_include/notebooks/label/visualize_labels","index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,nbsphinx:3,sphinx:56},filenames:["_include\\API_reference.rst","_include\\Examples.rst","_include\\biapol_utilities.label.compare_labels.rst","_include\\biapol_utilities.label.intersection_over_union_matrix.rst","_include\\biapol_utilities.label.match_labels_stack.rst","_include\\generated\\biapol_utilities.data.blobs.rst","_include\\generated\\biapol_utilities.label.compare_labels.rst","_include\\generated\\biapol_utilities.label.intersection_over_union_matrix.rst","_include\\generated\\biapol_utilities.label.match_labels.rst","_include\\generated\\biapol_utilities.label.match_labels_stack.rst","_include\\notebooks\\label\\Compare_segmentations.ipynb","_include\\notebooks\\label\\match_labels.ipynb","_include\\notebooks\\label\\visualize_labels.ipynb","index.rst"],objects:{"biapol_utilities.data":{blobs:[5,0,1,""]},"biapol_utilities.label":{compare_labels:[6,0,1,""],intersection_over_union_matrix:[7,0,1,""],match_labels:[8,0,1,""],match_labels_stack:[9,0,1,""]}},objnames:{"0":["py","function","Python function"]},objtypes:{"0":"py:function"},terms:{"0":[3,4,7,8,9,10,11,12],"000000":10,"044317":10,"05":10,"06":10,"079653":10,"0x17fe4272220":12,"0x29c86bdabe0":11,"1":[2,3,5,6,7,10,11,12],"10":10,"1000":11,"11":10,"12":10,"128":[10,11,12],"13":10,"181":10,"2":[3,7,10,11,12],"20":10,"25":[4,8,9],"253":10,"254":5,"255":10,"256":5,"262857":10,"2d":[3,4,7,9],"2j":[2,6],"3":[10,11],"324798":10,"386542":10,"39":[10,11],"3d":[4,9],"4":[10,11,12],"400592":10,"415":10,"416290":10,"426":10,"433915":10,"46":10,"465":10,"470130":10,"49":10,"496847":10,"5":[10,11],"513862":10,"518102":10,"538848":10,"554054":10,"560717":10,"567605":10,"58":10,"59":10,"6":[10,11],"60":10,"602546":10,"61":10,"62":10,"623552":10,"63":[10,11],"639576":10,"64":10,"646":10,"65":10,"66":10,"663858":10,"67":10,"68":10,"682566":10,"7":[10,11],"73":10,"751986":10,"768133":10,"780472":10,"785398":10,"8":[10,11],"822705":10,"85":10,"87":10,"878888":10,"9":[10,11],"942191":10,"95":10,"951468":10,"969263":10,"976786":10,"class":0,"default":[4,8,9],"do":10,"float":[3,4,7,8,9],"function":[0,1,4,8,9,13],"import":[10,11,12],"int":[2,3,4,6,7,9],"new":10,"return":[2,3,4,5,6,7,8,9],"true":[3,7,10,11],For:10,It:10,On:13,The:[1,2,3,4,6,7,8,9,13],To:10,_:[2,6],abov:[4,8,9],accept:8,achiev:10,ad:[3,7],agreement:10,all:[1,3,7],along:[3,7],alpha:10,also:10,an:[0,1,3,7,10],annnoot:10,annnot:10,annot:[0,1,10],api:[1,13],append:[10,11],approach:10,ar:[1,3,4,7,8,9,10,11],arang:[10,11],arbitrari:[2,6],area:[3,7,10],arrai:[2,3,4,6,7,8,9,10,11],asarrai:[10,11],assign:[10,11],astyp:[10,11],ax:[10,11],ax_idx:10,axes_grid1:10,axesimag:[11,12],axi:[3,4,7,9,10],background:[3,7,10,11],becaus:[3,7],between:[2,3,6,7,8,10],biao:12,biapol:[0,1],biapol_util:[10,11,12],biau:[10,11],bin:10,bit:10,blob:[10,11,12],blog:13,both:[8,10,11],bottom:10,bundl:[0,1],calcul:10,can:[2,5,6],cbar2:10,cbar:10,certain:10,check:10,chosen:8,clij2:[3,7],clij:[3,7],cmap:[10,12],code:13,color:12,colorbar:10,column:[2,3,6,7,10],com:13,comment:1,compar:[1,2,6,11],compare_label:10,comprehens:13,consid:[4,9],continu:10,convert:11,correct:10,correspond:[2,6,8,10],counterpart:8,creat:[10,11],data:13,datafram:[2,6,10],datetim:11,defin:[2,6],denois:5,depend:10,deriv:[2,6],detail:0,determin:[2,6],di_map:10,dice:[2,6,10],dice_scor:[2,6,10],differ:[2,6],dimens:[2,6],doc:[3,7],docuemnt:[],don:[10,11],duplic:[3,7],e:[0,1],each:[2,3,6,7],eccentr:10,encod:[0,1],enough:0,enumer:10,epyseg:10,equival:[3,7],etc:10,evalu:[2,6],everi:[3,7,10],exampl:[0,5,10,11,13],except:[3,7],expand:10,expand_label:10,f:11,face:10,features_gt:10,features_seg:10,fig:[10,11],figsiz:10,filter:11,find:[3,7],first:[10,11],follow:[2,6],frac:[2,6],from:[2,4,6,8,9,10,11,12],full:0,further:0,gener:[3,7,10],github:[3,7,13],give:[0,3,7],gov:5,grai:5,ground:10,ground_truth:10,group:13,gt:[11,12],guarante:[3,7],guidelin:0,have:[2,6,10],here:1,highest:8,hist:10,histogram:10,how:[3,7,13],http:[3,5,7,13],i:[0,1],idend:[0,1],ident:[4,9,11],idx:10,ij:5,im2:10,im:10,imag:[0,1,2,3,4,5,6,7,8,9,10,11,12],imagea:[8,10,11],imagea_label:11,imageb:[8,11],imageb_label:11,imagej:5,imshow:[10,11,12],includ:[3,7],index:13,inferno_r:10,integ:[0,1],interest:10,intersect:[2,3,6,7,8,10],intersection_over_union_matrix:[4,8,9],io:[3,7,10,11,12,13],iou:[3,4,7,8,9,10],iou_streshold:8,j:[2,6],jaccard:[2,6],jaccard_scor:[2,6,10],ji_map:10,kwarg:[4,8,9],label:13,label_image_i:[2,3,6,7,8],label_image_x:[2,3,6,7,8],label_shuffl:[10,11],label_stack:[4,9],labels_colormap:12,lastli:10,left:10,legend:10,len:10,let:[10,11],level:[1,5],librari:[1,13],likewis:[3,7],list:1,lookup:[3,7],lt:[11,12],lut_dic:10,lut_jaccard:10,mai:[0,10],make_axes_locat:10,map:[10,11,12],mask:[3,4,7,9],match:[1,4,8,9],match_label:[10,11],match_labels_stack:[],matplotlib:[10,11,12],matrix:[3,7],max:[3,7,10,11,12],measur:[2,6,8,10,11,12],method:[4,8,9,10],modul:13,mpl_toolkit:10,ms:11,must:[0,1,2,6],nan:10,ncol:[10,11],nd:[2,3,6,7,8],ndarrai:5,next:10,nih:5,notebook:[10,11],now:11,np:[10,11],nrow:10,number:[0,1,11],numpi:[10,11],object:[0,1],obtain:10,occurr:10,off:10,often:10,one:11,onli:10,oper:[0,1],option:[4,8,9],order:[4,9],orient:10,os:[10,11],our:13,output:11,over:[2,3,6,7,8,10],overlai:10,overlap:[3,7,8,10],page:13,pair:[3,7,8,10],panda:[2,6,10],paramet:[2,3,4,6,7,8,9],pd:10,pipelin:10,pixel:[0,1,10],plantseg:10,pleas:0,plot:10,plt:[10,11],predict:[3,7],preserv:10,print:11,problem:10,process:8,prop:10,properti:10,provid:[0,1,10,12,13],pyplot:[10,11],quantitii:[2,6],random:[10,11],randomli:10,raw:0,reconstruct:[3,7],refer:[1,3,5,7,8,11,13],reference_generatejaccardindexmatrix:[3,7],regionprop:10,regionprops_t:10,relabel:11,relat:[2,6],resembl:11,respect:[2,6],result:10,right:10,row:[2,3,6,7,10],s:[2,6,10,11],same:[2,6,10],scikit:10,score:[2,6,10],script:11,search:13,second:[10,11],section:[0,1],segment:[1,5],serv:8,set:[3,7,10],set_titl:[10,11],set_xlabel:10,set_ylabel:10,shape:10,sharei:[10,11],sharex:[10,11],should:8,shuffl:[10,11],side:10,size:[3,7],skimag:[10,11,12],slice:[4,9],so:[3,7],some:10,sourc:[3,7,13],specif:0,specifi:[4,9],stack:[4,9],standard:12,stardist:10,start:[10,11],stitch:[4,9],stitch_threshold:[4,9],str:[4,8,9],subplot:[10,11],subplots_adjust:10,subsequ:[4,9],subtract:[3,7],sum:[3,7],t0:11,t1:11,t:[10,11],tabl:[3,7],take:10,taken:[3,7],text:[10,11],them:10,thi:[0,1,3,7,10,11,13],threshold:[4,8,9,10,11],through:[2,6],thu:[3,7],time:11,titl:10,to_numpi:10,togeth:[3,7],took:11,top:[1,10],total:[3,7],track:11,truth:10,two:[2,4,6,8,9,11],type:[3,4,5,7,8,9],uint8:[5,10,11],union:[2,3,6,7,8,10],us:[0,4,5,8,9,10,13],usag:1,usedin:[0,1],util:[0,1],valu:[0,1,4,8,9,10],vector:[3,7],version:[8,10,11],visual:[1,10,11],vmax:12,vmin:12,wa:10,want:[10,11],we:[1,10,11,13],where:[3,7],whether:10,which:[0,1,2,4,6,8,9,10,11],wise:[2,6],work:[3,7],wspace:10,x:[3,7],y:[3,7],zero:10,zyx:[4,9]},titles:["API Reference","Examples","biapol_utilities.label.compare_labels","biapol_utilities.label.intersection_over_union_matrix","biapol_utilities.label.match_labels_stack","biapol_utilities.data.blobs","biapol_utilities.label.compare_labels","biapol_utilities.label.intersection_over_union_matrix","biapol_utilities.label.match_labels","biapol_utilities.label.match_labels_stack","Quantitative segmentation quality estimation","Matching labels","Labels visualized in colours","Welcome to BiAPoL utilities\u2019s documentation!"],titleterms:{The:0,api:0,biapol:13,biapol_util:[2,3,4,5,6,7,8,9],blob:5,colour:12,compar:10,compare_label:[2,6],content:13,data:[0,1,5,10,11],document:13,estim:10,exampl:1,featur:10,index:10,indic:13,input:10,intersection_over_union_matrix:[3,7],jaccard:10,label:[0,1,2,3,4,6,7,8,9,10,11,12],labelwis:10,load:11,match:[10,11],match_label:8,match_labels_stack:[4,9],modul:[0,1],qualiti:10,quantit:10,re:10,refer:0,ressourc:13,s:13,segment:10,tabl:13,util:13,visual:12,welcom:13,wise:10}}) \ No newline at end of file diff --git a/doc/_include/notebooks/label/Compare_segmentations.ipynb b/doc/_include/notebooks/label/Compare_segmentations.ipynb deleted file mode 100644 index b694e2f..0000000 --- a/doc/_include/notebooks/label/Compare_segmentations.ipynb +++ /dev/null @@ -1,5614 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "9f0d8ccf", - "metadata": {}, - "source": [ - "# Quantitative segmentation quality estimation\n", - "\n", - "Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "89205b6d", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import biapol_utilities as biau\n", - "from skimage import io, measure, segmentation\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", - "import pandas as pd\n", - "\n", - "%matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "id": "a63045b4", - "metadata": {}, - "source": [ - "## Input data\n", - "First, let's generate some example data!" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "db9c5fe0", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biau.data.blobs()" - ] - }, - { - "cell_type": "markdown", - "id": "2c0c8418", - "metadata": {}, - "source": [ - "Let's segment this and take it as a ground truth image:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "2ae66de8", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Ground truth')" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "threshold = 128\n", - "imageA = (blobs > threshold).astype(np.uint8)\n", - "ground_truth = measure.label(imageA)\n", - "\n", - "plt.imshow(ground_truth)\n", - "plt.title('Ground truth')" - ] - }, - { - "cell_type": "markdown", - "id": "f7f4c0be", - "metadata": {}, - "source": [ - "Next, we shuffle the labels and expand them a bit:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "2b8dc27c", - "metadata": {}, - "outputs": [], - "source": [ - "# First, shuffle randomly\n", - "label_shuffle = np.arange(1, ground_truth.max()+1, 1)\n", - "np.random.shuffle(label_shuffle)\n", - "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", - "segmented = label_shuffle[ground_truth]" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "279f3e2c", - "metadata": {}, - "outputs": [], - "source": [ - "# Second, expand the labels a bit\n", - "segmented = segmentation.expand_labels(segmented, 5)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "eb0b69c2", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Segmentation')" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "\n", - "axes[0].imshow(ground_truth)\n", - "axes[0].set_title('Ground truth')\n", - "\n", - "axes[1].imshow(segmented)\n", - "axes[1].set_title('Segmentation')" - ] - }, - { - "cell_type": "markdown", - "id": "dd726a7c", - "metadata": {}, - "source": [ - "## Re-match labels\n", - "\n", - "Next, use the label-matching from `biapol_utilities` to assign correct labels to both images" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "8007d578", - "metadata": {}, - "outputs": [], - "source": [ - "segmented = biau.label.match_labels(ground_truth, segmented)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "23496dad", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Segmentation')" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "\n", - "axes[0].imshow(ground_truth)\n", - "axes[0].set_title('Ground truth')\n", - "\n", - "axes[1].imshow(segmented)\n", - "axes[1].set_title('Segmentation')" - ] - }, - { - "cell_type": "markdown", - "id": "1e1d39a4", - "metadata": {}, - "source": [ - "## Compare labels: Labelwise Jaccard-index\n", - "\n", - "Lastly, we calculate the *label-wise Jaccard index* to measure the intersection over union (IoU) between corresponding pairs of labels." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "7641d30b", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
\n", - "

68 rows × 3 columns

\n", - "
" - ], - "text/plain": [ - " label jaccard_score dice_score\n", - "0 0 0.496847 0.663858\n", - "1 1 0.518102 0.682566\n", - "2 2 0.470130 0.639576\n", - "3 3 0.623552 0.768133\n", - "4 4 0.602546 0.751986\n", - ".. ... ... ...\n", - "63 63 0.262857 0.416290\n", - "64 64 0.000000 0.000000\n", - "65 65 0.000000 0.000000\n", - "66 66 0.000000 0.000000\n", - "67 67 0.000000 0.000000\n", - "\n", - "[68 rows x 3 columns]" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "result = biau.label.compare_labels(ground_truth, segmented)\n", - "result" - ] - }, - { - "cell_type": "markdown", - "id": "3f218dd4", - "metadata": {}, - "source": [ - "Let's also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "fab77a34", - "metadata": {}, - "outputs": [], - "source": [ - "LUT_jaccard = result['jaccard_score'].to_numpy()\n", - "LUT_dice = result['dice_score'].to_numpy()\n", - "\n", - "# set segmentation quality of background to zero\n", - "LUT_jaccard[0] = np.nan\n", - "LUT_dice[0] = np.nan\n", - "\n", - "# create score map\n", - "JI_map = LUT_jaccard[segmented]\n", - "DI_map = LUT_dice[segmented]" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "ca62489c", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "(-0.5, 255.5, 253.5, -0.5)" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Plot side by side\n", - "fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))\n", - "fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)\n", - "\n", - "\n", - "# Plot ground truth\n", - "axes[0, 0].imshow(ground_truth)\n", - "axes[0, 0].set_title('Ground truth')\n", - "\n", - "# Plot segmentation\n", - "axes[0, 1].imshow(segmented)\n", - "axes[0, 1].set_title('Segmentation')\n", - "\n", - "# Plot overlay\n", - "axes[0, 2].imshow(ground_truth)\n", - "axes[0, 2].imshow(segmented, alpha=0.5)\n", - "axes[0, 2].set_title('Overlay')\n", - "\n", - "# Plot Jaccard index map\n", - "im = axes[1, 0].imshow(JI_map, cmap='inferno_r')\n", - "axes[1, 0].set_title('Jaccard score')\n", - "cbar = fig.colorbar(im, ax=axes[1, 0])\n", - "\n", - "# Plot Dice score map\n", - "im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')\n", - "axes[1, 1].set_title('Dice score')\n", - "cbar2 = fig.colorbar(im2, ax=axes[1, 1])\n", - "\n", - "axes[-1, -1].axis('off')" - ] - }, - { - "cell_type": "markdown", - "id": "1dc2ca58", - "metadata": {}, - "source": [ - "## Compare-labels: Feature-wise\n", - "It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "5f6cc904", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
\n", - "

63 rows × 4 columns

\n", - "
" - ], - "text/plain": [ - " label area eccentricity orientation\n", - "0 1 415 0.878888 -0.433915\n", - "1 2 181 0.822705 -1.513862\n", - "2 3 646 0.386542 -0.079653\n", - "3 4 426 0.324798 -0.400592\n", - "4 5 465 0.780472 -0.044317\n", - ".. ... ... ... ...\n", - "58 59 1 0.000000 0.785398\n", - "59 60 87 0.969263 -1.560717\n", - "60 61 73 0.951468 -1.567605\n", - "61 62 49 0.942191 -1.554054\n", - "62 63 46 0.976786 1.538848\n", - "\n", - "[63 rows x 4 columns]" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "properties = ['label', 'area', 'eccentricity', 'orientation']\n", - "features_gt = measure.regionprops_table(ground_truth, properties=properties)\n", - "features_seg = measure.regionprops_table(segmented, properties=properties)\n", - "\n", - "features_gt = pd.DataFrame(features_gt)\n", - "features_seg = pd.DataFrame(features_seg)\n", - "features_gt" - ] - }, - { - "cell_type": "markdown", - "id": "ec29004b", - "metadata": {}, - "source": [ - "Visualize as histograms" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "e9652f8d", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0, 0.5, '# Occurrences')" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))\n", - "\n", - "ax_idx = 0\n", - "for idx, prop in enumerate(properties):\n", - " if prop == 'label':\n", - " continue\n", - " \n", - " axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)\n", - " axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)\n", - " axes[ax_idx].set_xlabel(prop)\n", - " ax_idx += 1\n", - " \n", - "axes[0].legend()\n", - "axes[0].set_ylabel('# Occurrences')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "185d4c1d", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_include/notebooks/label/match_labels.ipynb b/doc/_include/notebooks/label/match_labels.ipynb deleted file mode 100644 index 181425a..0000000 --- a/doc/_include/notebooks/label/match_labels.ipynb +++ /dev/null @@ -1,3198 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "e5db44ea", - "metadata": {}, - "source": [ - "## Matching labels\n", - "This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "d1ca8e7a", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import biapol_utilities as biau\n", - "from skimage import io, measure, filters\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "from datetime import datetime\n", - "\n", - "%matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "id": "ee62539b", - "metadata": {}, - "source": [ - "### Load data\n", - "First, we load the example blobs image and threshold it to create a label map. " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "7fe70350", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biau.data.blobs()" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "909ce3b2", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "threshold = 128\n", - "imageA = (blobs > threshold).astype(np.uint8)\n", - "imageA_labelled = measure.label(imageA)\n", - "\n", - "plt.imshow(imageA_labelled)" - ] - }, - { - "cell_type": "markdown", - "id": "1cbf5ae3", - "metadata": {}, - "source": [ - "Let's create a second version of this image in which we shuffle the labels:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "29986d79", - "metadata": {}, - "outputs": [], - "source": [ - "label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)\n", - "np.random.shuffle(label_shuffle)\n", - "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", - "\n", - "imageB_labelled = label_shuffle[imageA_labelled]" - ] - }, - { - "cell_type": "markdown", - "id": "1393dfb7", - "metadata": {}, - "source": [ - "Both images are not identical!" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "1ff3c80c", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Number of labels in imageA: 63\n", - "Number of labels in imageB: 63\n" - ] - } - ], - "source": [ - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "axes[0].imshow(imageA_labelled)\n", - "axes[0].set_title('Reference image')\n", - "axes[1].imshow(imageB_labelled)\n", - "axes[1].set_title('Shuffled image')\n", - "\n", - "print(f'Number of labels in imageA: {imageA_labelled.max()}')\n", - "print(f'Number of labels in imageB: {imageB_labelled.max()}')" - ] - }, - { - "cell_type": "markdown", - "id": "7a38be04", - "metadata": {}, - "source": [ - "Match labels and track time" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "79f0cf74", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Took 0 ms\n" - ] - } - ], - "source": [ - "t0 = datetime.now()\n", - "output = biau.label.match_labels(imageA_labelled, imageB_labelled)\n", - "t1 = datetime.now()\n", - "print(f'Took {(t1-t0).seconds*1000} ms')" - ] - }, - { - "cell_type": "markdown", - "id": "a8710824", - "metadata": {}, - "source": [ - "Visualize" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "84ed2639", - "metadata": {}, - "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(\"
\");\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", - " '';\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", - " '';\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 = '';\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 = '';\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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Relabelled image')" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", - "axes[0].imshow(imageA_labelled)\n", - "axes[0].set_title('Reference image')\n", - "axes[1].imshow(output)\n", - "axes[1].set_title('Relabelled image')" - ] - } - ], - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_include/notebooks/label/visualize_labels.ipynb b/doc/_include/notebooks/label/visualize_labels.ipynb deleted file mode 100644 index 9924ff8..0000000 --- a/doc/_include/notebooks/label/visualize_labels.ipynb +++ /dev/null @@ -1,98 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "803a884d", - "metadata": {}, - "outputs": [], - "source": [ - "import biapol_utilities as biao\n", - "from skimage.measure import label\n", - "from skimage.io import imshow" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "af876b71", - "metadata": {}, - "outputs": [], - "source": [ - "blobs = biao.blobs()\n", - "labels = label(blobs > 128)" - ] - }, - { - "cell_type": "markdown", - "id": "d9ded05a", - "metadata": {}, - "source": [ - "# Labels visualized in colours\n", - "`biapol_utilities` provided a standardized color map for visualizing labels in:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "5c3f2337", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "867149ee", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/doc/_static/css/hatnotes.css b/doc/_static/css/hatnotes.css deleted file mode 100644 index 8f32061..0000000 --- a/doc/_static/css/hatnotes.css +++ /dev/null @@ -1,15 +0,0 @@ -.hatnote -{ - border-color: #c8c8c8 ; - border-style: solid ; - border-width: 1px ; - font-size: x-small ; - font-style: italic ; - margin-left: auto ; - margin-right: auto ; - padding: 3px 2em ; -} -.hatnote-gray { background-color: #e8e8e8 ; color: #000000 ; } -.hatnote-yellow { background-color: #ffffe8 ; color: #000000 ; } -.hatnote-red { background-color: #ffe8e8 ; color: #000000 ; } -.hatnote-icon { height: 16px ; width: 16px ; } \ No newline at end of file diff --git a/doc/_static/logos/biapol_logo.png b/doc/_static/logos/biapol_logo.png deleted file mode 100644 index 0945d112a0d6994fafdcde2f1a5737fd5061142a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41688 zcmV(=K-s^EP)!oh-l^_-^_F{Y#*O$Q;)_TvBJkhjzscnm{Zb#mnP z6g7Mu48LiONcaXh?<-$P^2$-H3k)ls_jLR%DT@YJRTWwD?xaOgkpzRJKgXxogAfo6 zUQIas=%_s?7aakv{xvC(7bHX(s1dM(OsC%ngYFFvIO%=TEs^*vo_`Olo?z517@iuw zqEriCfv#}vZG6G=_*{SY!^h~(4+_LA?1e}ZDlZ;Mt$s>S8-6Zj4yqv0k`SSczLMiB zDX0vwi%)45U=oCq!iP15ya1sLG$|e1;3H_Q!E#A4hsTMl)(_~4T+S;auOP+pGQ79r zmA>FA)4+6%R(oJ&BzQ3ytWmH|42YC07a)Of)Dz+GjKlZ=9;^y)5FUC|8E6irZ@_5N zWZ>8&YM}wp8fpWj3Rbh}*f4;io(_L4JZPVeGFTo)u<=7obe#^s0%Y;HhdwtPmKyk3 zS>s+`A@WLbh0Los2rq&h!TqedrSld5LBcum2(pmpu!>&7!+Esbs@?7`E>~wN-)Hg8 z+it(p>2{dIYdm{k3AbNxo)ok)_&gMWvDVnw*tjCCL~Avk>+y+}o*ZlD)FRjbw820V zI1_P5wL*uG1yv48;^Q%^@GmASRYldL@bkPoUDn(yuOy50N>MC|-T^Lf8?cImcz{@N zxGZbbi^I}+2FKt_X?N>|rS`c~XO5nkIp(24@_pA9)8k;xn1b?v^)@JL{I=lrf=wHu zBn(c|d#_533qj?TQX~zwXb5s@5VtZle%;k~T)pMaEzKPoGLW-?6+sJR5;%|c&IDAK z3{$ju3I?`VMvgMTd>;-U6ViVrDb_2-6<%FQ9}Qaq$xN4mfH}_!e=OjMjB%8j~s~&x{VS zCSmd|;5-HqYLf2w>v#X?gw9!>u=SIfZYkOeuoJKq{!SS{0jL;Vj3<%6ctHsW`71u|U^ zr3f>yC?9Mb38P-GYknOo6$7dhCg4k1K>8`Yr#(;DE6Rq_!tF2r$P)6-6RET7Ye{Nefb*;+ca^qHI(3(AJ*3~8X3;h{v-5V;8j zpfmWJpvbC`451y$#n72ok0~f7v1pR;LWd5>F}kjtJ$mk;8?WA6Vq5ez^IQmRS~A}yil^>}shWE334Fit2~ zw^dDABf;7Qy+ctP%#C97LN2^RnoPav_JLyyH{G!5=CRgwu6xMajv_E-4)mhP;}xr_ zvs3Zy3h&4_yavpk;3#D?a<0PBDF}h82TA}-UFmCl8Rg}vSZmYfYVZWQxP&U22ai;G zsJeFL?99nC=T4nm*|#Dm1y~wR&;g1U7u=VKvn&<}RZK{T!eL55+yFY`FiRxK5hAW; zBPrz+f+9XA79IG@fWD(^RDe|gZJaST6nZP={=1;IWl{OV`&abyu$6fcjMc+W{IeRFsR;@@p~p0&bwwVbOIrgzI1!gkhzIbB`VS+7tU9R7xvscKk9lys!nf2uzsLo5Vnllmz?4 zBz)diUZ5%RoDgR1lh0+b*8UmOi(SxAQ6SnN`Pw)2=C|MR-WxY>s#boZ1^+o1S&Ne8 zo+?72aL&QnC9E#e61Uk90PX_04zTG*2-8QfHAuOHfH7u%jYJEfM&2Ca4Y}rw z0zdS5fa5G_9Vp4(Q9oh(p+Jhz)Z%C{qQ=$Sk);Qf>{>HaIKhuAP8(s0WctyGP zKKL@yDp(H(gcM!W#bv|cSIYCb)Za&$Ml!@;gA_uD>BNZ`Ql?!ko$4IkyZLYE?ACf^ zDw72WaiZhkK!>|Ji z1RqcstHIrpOfvdm_KRM8^QC^_7k=SI|I!QPyx=Na6%tkowMH$7PPr~&2lYaQ=a#@3 zpk`y^j;XTlt+eMI)89EDj&b|UII4DlXz>h#A2VbBl!R1D4#`=Bz?o(1v8!FMHYE_9!K?plz zel@^ERKW|EH~?Y897VV#Y<%zq)$SKZUKWZK7M|H7_2Oj+O5%X5c!U+g8CC~6@?RdE z{(}b&eeJ}lr_ZerW_u=gUbk`Y_SRPKeA(+eaZYRoS_^s>(W*qTS_DN48y|twl|G4B zA&UQJ9C{zmzGxI>ubiCNxn*pRDoemeQG4b(>Y<9UYIt$H2ON@9=oO08qCqn1q8xMe zLu{W!oJO4iZeVT^=FwaM1$1x0n;2t+uop*=ap1@4CCS>qJTMld6th_+ltdR~5so2z z;>p=R`PQMlac!?I)tE5#H*2}A)%^Rf-+N;NTDpB?=8^lK`m-*~urTG&=h7K;F+-pk zGLOm=(?#@w%PeUjQ(`RE`&g9H>?AX}t6+O^%lqE&qhoxeYX8Groo0!(YBop~W4UQi zcE(|j7S>ce37oWgcC*Q^Z*2HMz;}V%I)E`aDoNB5?2~552M4q^MKZ$oFP6M4EEd3k z(Sj0v7UBxRw1>|foco=x9(-cDa>X_aEhw@I*z2rs^|>}YdT{p4O5NHpzH9UDJzK8T zp68Z2B?)VfQs!(6$3}=nS<-kBw17DFo;Y%yZL+rM_(t2c~oboE~_AJ-(p zVd(`qRkl$=z>8~%K9GnOibV$<)P3ODx_1=(ap8F~IbaT=8OX=rHp0rp<`|qV%G$v3 zMGX~SO2uMk@54nGcE~Xegj6A|2;6(9{fTcK`Lk!27Mfc-l_^xKA_r)VxZH{6tWS-V zyt!|&{qX+dRBXO+$5l6MyJ>9GwtYtrY9l#1RacD=LTRsZ8<|$mort<@vYG@-zYX|a zLw=v2oow#hwee~v2gUDKVo8jU6QrnB7&9EQ%8?l;hT#A-a|B0NDP|=zCFK>2EvdEhVmkl1z%!|MMRM_AP$^ky#(r8XZxQ$F#Cypr=GRC zR4wNWV&)9=O~*jL;cU(v6h!OFT5Ym6`NtQgkI%1+w>Dihb@eTKZ}aV5dtn~6E=g=m zR2arsYq`=EOU~mR!Z2GA%gjX1S$*Tq+YFShd{{#}2CY75l+ZwnM(jl)k%BQ}L{^pP zD*PL{V8oiFLY%Mt!MZ-oaym2H379xXA3-`vz-r(GeB?9AP{&_X=FLl{SgCl7h}K$A zrjKTp==UEv_j?Z8^}lsf#698w*ArVrv+1y>Bp4+2i`Xy$Bvpsr5mdLDHXs2Oh_1!$tFaxrlq z(G}~92t`*`UNXfBHiUyEQA(|N_{MDcoA(`fbf(*FZ0s^QACR{p#ojq|T9bB4z&Ol& zWpocN7btO+|t*ydU ztr{S56!FZc)#TNaKala$R38HBOVpO2SZtE@8qi~6iD~dl%=0F9%F*r!rWiqxoqa@zXw6~4@c+@I&}DFxDCa8{$iNj!us_Z#W0q#C*IxHm zwV8LlCrB?uj%YZ!;J}E76#F&R%0UK|qJBj}4+Rs)7+|B8Tsb7ah%T ze#?$6ySMIb=4NhT+L90M#51vgc%gKu6XqofM&UUK3@=13Cbh~iKNYnEb40OqZ_l>t zHxyU(s&8v^h(cJQL^uMY(St_;EW!wS4>%n$b{-l-@gX8i$V&CZpK{eHg@AejU?RA` zfYl-$M22DUu%0wS6?F(OC;fc1|U0fYIgtWr5kSCvukSi z_U6VDM-L)9Euu51*y^HS))=ZR6bZHwVtJAK#xhIQL_@! zr7_dq?LTpL=hRg;=ZA5Tz=XCF@T+e?ny*)pp?)DCNN+S{z_Fi(r9Oe88aogK&An z#>?ejW9ocBeO%3%j1WisrU)n$odNhaU*GqM1Iy1W`J%ZEi-~?_cztzJCh_qRnV|?^ zxH)yK)Zghhf9Vt7eE7IbZFs}oKky;(QwqkU;&GE}a7^r!7m_QVI|X4&;n4hi=S&5d z>D?f^gp>^P5$pYeV682QZHUTY0r)HJ_OJW$^Qg`cID#y8B1L2YO-P1nkkCaCvxb6p zdE|0gtbxkA;la^>w;{=UOVBzaNC$iMuRrwcgY)&Y%Zf&`SC!5y!W@~`b6SisfelQ9 zGB8=o&Bi#hV$*u&^peV8_f^-t>e^eni*x;z1us2O7O)N&L`Vh!!4?}!gV1UAPmvbV&xBp`&sQKo&YKs6e5Q}G@u0pViUK7@d4u5AwX7km z0wY4ep2Wp#rK0h4nids4ark(aA)ZOx!gYSSVCtAekbs|bK=BK;Jwbkj^flnNgcypt z9xB2->XQl{lnAcCU3Iw>D;S9s5Jor7;HyERfdVjZGk&{Uf8%omzJg%``rpL$2@cB z>B=e=f}lb{C7f5C-W}K7m65BeubH3^R)RBM*XIXY9n6&q;V}lqiiy_{^0HrIIqZE~ zXOoDVz!wsXfRFb*ChAx;cbDs2;c~jdVV4~Y%Dsd@W(Be~z=Nl||L*JiPWKJscweM6 z9!V6V09i$X4kaaqFa69?hC4()D#WA&ka^GpV5~{dh*SjKOr4ouo}264xMSCiJ8xa- zcbD5s!hNL5KUX8pf{j-rMi~bG-4{~kO9j4$~FoK7i6O+u)y|IPbtZQz3kF zrt@3(JvO5!Yb-pYDH?TI7MT|BB94tzUQsNUp|L64a`CfBgi$;Ne-JMh3;14X4Qi^K zE*jIUzJ7G!<6oclxc#0t{r#;IuM%jMq#bI-I`=x7RAKZ!wg-lAJqBFCcgyG=NO`){ z0`HS)j6D=;xJYZJ-Uxv=C>oGiwIM4PyCuMs;C3hE<{uzjVd=i!9FCmuR{ zQnHn->A)F6v7jjjAMTf&oes!Cc?!|-y7PnK12UGJLrh?mlsee3NT2frUh7;0f;nUF zlv&9q?>}Ar@uLe}v*%5>{GBa$J&Phm;=B%U%wq_bLVy`7eJQaRYe<9Uuv8C_wNtBb zFkDRr9QO2pfsaD3l_;g1sGis5O5Xx(Ms<|~HR!2cpU9d)JcHvw!Px4Z*2TuMRc@xC z{sNSr0D6j{fXkMrp|d zD-~{mrk8?Kp%I-&A7?!z-O(&2J~9b*s|Q#DR){t-qBxGy;z)~)qux@JA_v^l?k$G+ zl_n#7NY;r2zONuihP})=;sVrcZ9miN-DjXpNWF0Xc!Y2#>TnY}5If>lK*IN^Uue7R zFK(qx+wJ z=;+*d>!!Ee@WH0r>1@GSUXo_WkXy=4Ah$pok>65_ssJsM3y+{-ERnvG8tcOgD0()G zag3xSaSoEjzEd1@AjRZyuUrzSl-g?j&{tkbNgX`IaY}`8hK_>UN3aOsYf0JJjFOR( zI8KZQ4ZWkH$_w?@m#43gg(*|Ok{f-n^uPO!gOANsXtr4KT$o`W%1b8#%C#bt?F;pl z)ZtpH!Xf*~tsnc=$;oZo?%MMDyYB2i^vu1Yo%1V@SiOnntLk8Jd}F{5kkRCj)$SJo z#c}4tkUfwFl8T^>ZaOlqQmNZ6<&Dj~_hJX9ftB z`syj2qWtvKTNL#)z$)=2}T#aZhuXu%oDh z)B)%Pm_^~b1m`2lGcjuxPV*=^j^ARcXWO#?8@wM2LGcwfR|$JNWlBd31a_R%wa{;l zFPwbhqrcoe@OALc`*6e-pbt<5%dCe5NTwIAD3|C8l~RdVobt5&M4+P^bN#wkR$XiRwd;5L%Zp3%i;L%0mY3NqsYW+Mf25uF z)>)Hhwytz;jM4pm89WT3f@lhXom8EEm&Y4QPoXOSx>xiHB<=9%F|+7I)E?BEV5Miy z9oxAwGjs26?7iiB^t+Va5PSH83v{c>;V*&LeCZe~X;o^OsfcD6{^0TBi)Ml;BXNnL z;eu*G#`dKh&MJUbnVL`+%GZwU%B1xhz;D@9Y~S42G1b~Wv3paawE=t!p#kH!-S9>R zssn7&aUy~jj@}$$GK&s14xS8%>l*K%vRrq{`F8)@N_T0wvpBnWcG;eDWnXLMZQr_H zuF$!NL?)-J<+R*bg7-L>r$+d(V7SN_g_DDr0bz*I4c|>NQfp>K&_c)M_0CD^1Ve6 zDlHjeqwZzhr5iVmzy0QGUbACtcLN&3@uq!|95r!Gq?~hzVn9d%fd(FSKNwFlXw|<29^&&? ztn)rR62>C9BGb0=#X~FKJk!gI=6tmbX53HsNypr0N2cX!PK@ck>KE!xT%cp+}M1}maVVZbyI5`ELeg%1JR%zC=}S> z!oMu!nE-Q@dhu8W!*6gkHVW7qQ)!eEiyx8L$5aAoP}+ykee6|R-f_d0H+So$)8|f} zo`3fE^5YdRvJXLGz*_{px{9+#o6JVhDppuKq4#pd(l}__C$NA;6SBR~&ihB6&9N@U zD?7f^Odk8ET=%&^^PIBRsk+(>r=4ckNpH8w<|(EyI%G8KU`kTEoiY;x1CYi`~31`9vD z@6=y>=ip!T+?>_36|h6!ht5P}vs)R1EO^#5(Q8mU9}E_e;cU2d=~ys8xeAxtdBc-6 z-3qgdF#D(o)R<`_s+^vhS$g8v{@2(1!hfP|JCOshk~n*QL?V1a@;ntQtSqH{8PXhm z=aFT^Op0B#9h+vtHh$sylXVe9QH>-@3iE0bo4lC`XJo z;z(U0EhHSmA<qEG7D%j3Q?MM7T(!=ckEB2zS(E{_ zBZE!l%z?}I%6+jBtWe!%?J)DqBmt zP@jDAKi&;E? z649b?uy1MD7zS6z9>tM>pW4vm`O|mr+48}=ZhBP{v=d*uJkuBMV-b`&$XewH>f)TW z);ZVdbW$?KM@cWHC`u_rY_(cSsXPx+UwUSA{><#0%d%M9l_AlIZAN1R%{^N;?Am(! ze5d=JeFy5=L6(ym2L^ILsk1fSV2~Q#V#^`PdXo_dF$_WRrs=aANZj(X&uI1$pioMT zI43!p>2G{?^DVEY*M5j3kE-Pb9Ep0NAnSQ!tl`iSmHH;@iu3&O)74`qma5DHX!6B* zji9o2P$7WRtEg&Fu|_xK??)?@4SOnM9$E$+25OK6CS=USDX?DEmcUD{#3&{qR~x60 z$DEsh{vG4^&ez^}$JXX#>=__%KpeXi&0zC^wAV=#8>KAEx~`pbNs~r@O=65mDw5ut z-Yz0Z^VTYy);iDgMx&8MS(}a#;Ye)EkX25Th99-_?<8BTWD?UNL$6ZE(6pl(F%#IL7+ZZtksjG z;qeZiL9f83H$)&#gTax4K216l*1l8_%vHR-GBmep!~@d!>}tI_ZZoW@MJuo_$idkU*%$vP@R^aFn?HW=y57e;3rFN2Ks&)*{k8d=c<%Nx%bF*Lm_>LdF*+Zcc zA?gY$)7Z>ZgPTG@YnNlkKe=zzc8l;5A*E+bke~yfd*60O16cKUGCD+N!Cr_RnA0OYa zVZ+$iSkSFe4?eQeq#}S(x&b~{jUO1_S=VzNKqX*FR!D}yN(5aT*@5e=`4AH1ER)Jl zLiZGR=F({fbOTC63X?4?%r!F&u7X340k0r50ClV|!V6`XKF^7M?7bD0gSA@uiqtb; ze(^I;9ch#HG>!(j%g{B(XoXrSqjZ*HElDs%yf==;3s=rtFAjl;oG@wyq&yf=6Lsxa zoYn!cqze(bb}_XhaPB?RepJ#+ILOR&%Nj7Ex-+^AOQE_=sxsbYS3E1 z^lDz2ondd&h?@~AO3IY|vso+^M zr9qs4+qeHzQO?~yF}b@K-`SeFYRj(44bo~giVSlD#hP}awD(>!g229ol^(P!SnAuk zPJe#6yV&l}Ew9XUx^w65O`G0!* zn>PtG23e&zHzI8fzyVvcxK4L|aiwERt4Sr_q_w8=WpMS^sMq(t6(19=s+=S&fwj~Y{iCl_TF#`4q`OM>nFrV zvSQ}^6u>pG(w;f=%s8a|^a2h^v3`gYBookaM-1l@s z>c4&a&0B#puq=dd*gh z&vmzn%27?c(6KbnOR*9Yx2afafh_j`H(#~&#IrW@eE(yQ?SJ~6P1?r%XP#lBX(0(D)yxKX zEN?Y6u`VFEKD8E0Jx>#Lfh$aEH?nhU^=y>INY6OuhUgx0Y!!J`xqh!#&CGTi%X;JF z)cDvKP!*wT5og~3a0~q1sDUyyFqyLjcHfYV1eU3P0glEZftGaHo0f_ zwr$&*d#~R-KGE8B^|r}PSuId`IC`!;xU~GtTptTvcrN=j1lI3^$16N)Gm9+k(k&hokO z>u&qs|1)j9o>hJc;9Z8JcGa5JlC+)Lh#}ecURlU~=x_bsC(ly2W1)vwJIFn3AZCRX zoS(WHoGM-r2?CtAzX&E;OXPj0W$*%?rSG}iFrMFb>rL;v=N)f;)2^-Cz{fp3Fm5pu zt63cNlLlcV!qU>>;=&>VHk!FMT4}AdAv7qYO<1_3Jr~3C=c7Q+M=pS0YlWQ%gm}U` z^xk^!>)Lg@eednot=pzHZGyoNv6{hSMC<@dKu`8MztgjSI+6EviNwQds0XhKrW)ez zP&Ak-g5W1aby+zk@C+JE8fe2jwq)0GA{eZ8fzKcov-mWkW!b{6QptG-i_2Be$ z$JLWc8732321N64wA$Kr8vPs?#P6o=k}866QbmLU0X&Kal{Yr^`sITU9eVJa2R3fN zom;Da_+x+jo%g&>>0q;!igWOySwR6?l}pP@olYmqvPPqk(v{Ke1&lYSO2hNAK+~D%(}{KMVSB9-?zMWOa_J_Hi6MdC=9cpN<)f z@^yG27hGJGo15YE^6aDk^#;v--w@G-RVtRc!(~T@oRL80DGdw+7Sd$I%^lsp=c$M2 zHTSU6gei9&6y$rC4@Zi%%3>MHn%&G|sqpCG_QQXwQJzy(KgqX}|&ks2y_C!d>nLVdKCc2%-g-0}^Lr zVBQ9GtNrMM6VmqH8`aPZhGUOp9FrNxcZQprL>sSEoHFJ}P|Fzf>BPR}ryq)AdmyEe zf&xlR;C`2xack!YuSsi0NjQx|{0@&jdHmr=4v-$}_Nvuo5*lv7z0PujL|htNgm5lg zxLTIx=Znl;w|DZVf9Cy!18TE~H#%HtTf6z$#ZISFL`e&l=Xo+z7vw)*4vMwbc8*eL zqq0)7(K05}Av(@`z24a~vypEYusoSj<0T2HZSkd;X0QCx5bX?8Aq^sE6ClIv~L z<=i7*gWf#)ieh3npb_Eku@B;NW2~6j8x%j&B$zLM{*3eZKzfmWQ@SECx=Iz=Sd zL9L3oU6**<&$PS!j$Oa^yFVUWEi40!D4}ts1?24AsSQ zK{7VMMWeYk8q~;i*)7kWp6&NM!kEaI_(lX=2KaSZ>+dQ3PAe0l z5;59Pcs`jb0^~Hl9TEBpe0Dq3ud7cyd-CDWHOW@2#k)oZ4y~h@=t(TyNXrr=AB ziIY_z#fE;()_9jL;)N(EtI0%odGFrFuYTkoU$c87i9<&ySz3Uqa%a!X)U|K5#v6@B z3IL7KG;}T(Amx{>jA({Kx2S?QFgnXjkrj=+v3b)}uhTty`fOR+l#2=AM3-^+*E<>$ zKMQnguix^lh5FtrNnQLR9H-!iE6K*%t(e^fcGtqg_f6VP4hkG*=$z(K84r2pX)qF; zDjo2CEMZ3fs97SRJaS2ZCZt~xJ$(o<(e@Li7z&co3>VNLf zzC>!wdGTU{PNRazz>Cy;Ppn{_bBKfpl`s={S1;?V`z!zFf4}=`5bk9P;`T!gU~<;a z&CV;*&E{CdzbeZDP9G#<*T{<*1FlC#kPC^GW~IDR+UO!PEfCqbsZrU5>6v4-wIeo> zMPX?H|3H@g2+_4dMg)9Jt0v}_A5d$7%Y0nl-7q&pccp&h{+49Eq5{xh-9hN-oWbM{ zi4CIz>T7Y7a?U}Ky=Ep)$U5M9BwhEmtNQG|$AGO`!~Gv}g)ii|UbG3wa3(=jR{_BZ z?0e?K$7#7x2PedFU_x;U7nx8Scp2L4vXZ?5qr7|L?P4De*z4eCcrwA%V zOe%mUw&0vQH*>D+mqwdB%Nvb`*2);2lDEc~mouokSk@kGGPO!GDNI2~rn5%FXvLd0 zj&-^V)6=IwdmtOHVC>bf<7ED3qxDt`yF?`lBd0;I2~Wpr+9m^UL$#;#mtVxQCv(XZ zWhiW&^`Hf_SRx$kxe&BbMhR^m?lKjJ#Kp9hMrpcU|KMXFm8<&k94OU2zDHCz+5nA* z6GtSXET;@S@X#@!T`Xc$hSo?Wal&yGX&*uBW4hsck+LOVQzz&+HJr%sy9S&Zj^x0+ zay3%_{qK9@Fa3*uprq0wMw%eR#Mtoji*xO6r)V~^A`gJwfYOmXuM`F^pk8Q+#zh%1 zsGM^tYDv#Le-*g|x%k)+Q9P351Q`)fW>Irqj3Z8rHMW*zed^RH4r^ZrD9_+X18s+~ zzneFIxMU;P7;OEkg#Ea-nXsywH$dxdf4bWLG&h|?EXSWOMnzYhQ|MtB|P~GLD$^bz$l|Zr}5>KlA>v7HA}Pj07&W7|bs$ zEG#TGo6VvqQf@um;={ap1ZOYURwbK}*vToYl+u+|RlU%Ux-1e;W`q@Cklr#yo;S4C zi;FAEixol381h^x!=N&Nn^faHVDIR39qQN(D_A&%fF(}m=JlY>xhKDroqNV)Hf{nH zo5|wVo3YtR(u__VFb2+VS~&lbN`m-x_dB2YBj6HJha3e>jBxwHPWQD~WHmub8eIq` z^%GA_pFOka?0T^oCx->YIiYg+~YPE>ST03GGH=E6u1pBW|ZjJJ&sg)y2aq{@N&awq?O0kzR z1a58;`1VHe0aSZ!+~qKC;@e^06nL%5-U9Py<{td?lATT{WgS#Sgsa8(-gDQR z-*|mSU=WB*v}~S;&z_w&c{9uM#41j3>H_lT3zfCyJZ3h=c<-yK8Z}3(?|d&^)}~K~ zF>lbVB5xFVZ|zOD_dk(1Iv$)1*iaWP#KjBaVnULwhhxWkuku(1E!Nw?f^wDo? znnYF9Ze9D{rftuLn@z@s%m`~F*ilhXBlQ3OKl1kNTeV`&^I`ujK&RbVUS4h#h1NPV zSxSLwty2rv1>ceoccRy&pGlt6{18!9RjE#=luAH8@eY#BNLc>j&wSv42VV86SLJz* zS4@(jO17#fiiwGdsi~=}ckjG*@9uZq^Y-8Vt>5c*dK9DKp6fX&!Q}vVWyN1r`f95i zi*~Obe<%1Y?XTWD?z-fCuJbA~uGY1Pikx=^V&PU6_CE?-GFmkp;lb|0^2>8;ad1~2 z4jo*!);K3w2m>xd*#^=+m;g!}XIUYz?-BKP?r7cft~+CnG)^arDYB}nmzO&xE3^sL zDu&{#lIQt=KsSuwQZ%QON=)}M1jehXN;-##X#~Ss9{NZ|X{2NY>$*?MLq$zvb1D+rpA)(&uZ)`HGd)FGis4 z6*zuu*16o17w;5YN=U!vkOnlM)vQJSF7b^DH2?|#dhCr9)o0P?PypPOs9dx{F9 znp!)PMV-8e=QPro zT6^!u#>P6GPBMgA>%DvT9yo9y{py^Xo}PY@(_IYgJ^$u!{MN7i>t9o-ZE5fO@;Bb~ zuJ?ErW3m9-S$Wz;*(Nx4fA<@IoK*{4WJP8StEwuMY6+Duba#ohfh98U zo}N+H@9@AOj!<%e%^E3|le9lNV46Mmg)iODlmkToE9)9g8*G*8A!q0ti2YzJzzQkw zxMg$p);Hc*#N8Q_xnu@sp&(TlY-XO612Wzljk(j{&>E23``9fG9_ifN+}A$;h0lKG zGhh7T7rXtg2PAD`{}~uo49a4i1_RJwg<_i(X+UwVRscpBZ)3ZuChvV5=ZBq6XL54# z?z`{);0HhWp7*@xcYpVHfAJT8F>W5hq;;n(fBhpL2|yc>y;qUgD+uQehf5TI#19!x z<@laUmuPwz8|`Bocnr8?*q!s!KmF65;|$Jt^S4)4`rU4$kpo~jD$?QVIXeBPA9X9! zW7>EpmVH=sodG+Rb*Yx7jmW`Q04`M(8Ba{`dEG_4G zp%f}@Rc1sHL7_d^cz_Q2IVh;0$MwJe*nj+2|Kbxc;^8jaqrDrq`mb?ILhp%Pnp}hBdUx6ka1}f_uPLvxac}FHr@?ng zPdd^%5=$>uEErUkQ=O3U=#i7{m7daLq>0mfm-R^6bvQ^ZG8pXWoZWd<>#zOb&EOq~ zwQP;byhyvhJhyyqe0&0owpp%JW=JyVgK$=uUBy!SE_$tOHYwRb`2g#f4AA+u?}= zdC1ebf1lCO0)u&|=%amb!+jSxjo`U>p*x+<^z`)R&6{;C3PU;YeFABrPY zIF|V?!}hT_9BZf&{STx%brPyBW|NUn%8B(fl7V6=&>Z*q3qLg+K77 z=OOD?N)=%Hu<-Of*Hp*t(zydqbvo^v6wB;NqsY4bypXBgoA%za>-OyRHv??|HwI{W z2DCsH(^5b+2uaCLKl2^$*lQH@ggQ98DE)q4Yt78PUa!$;dTETG&T4A_R9hQUlexLhO#pSR791L=BBRV!v_TrzOL$O+|*74)V zw{PD*c)yN25H@#D-0-^c^uZ8Crx~d*oVB@s_MTzBsVvVX8 zMCbvIK0B{XvvM9FIwD!uW`2>YZU8)^O_imXQtQ3p^*hJMf`tTStSH0I_v@{Vypicx zVAl$=IPN|TD})A>fQzs^``Dj;{J^*VyqQ(wlM@>^Z@%UBH%*MU?97o9hre_4Ti#q% zJah8MXaCbLSD*ZiU0YxEs@J}2>P_z?vjrswM?fS>0eZ{{`!1Lnsa@P>CdHM(6~+9% zh%}qc6b3qsa4ePOfkc|W^V=W&!;k&pFa7c_MFKA)Ip_Nnhh3&Yq#jiCV=h+7zAtW$ z!~CNDDu4!X74HCC+beaxq=ZNcQ$ox^1g_#N1KKop%Uf0+yjS@S4+q(asF)PEblplM zDF&s|FiR9!S%m3l;p$BY&5I{H3=}JNZWxdNPAf;JPAwSI>Q!7cv%0L*C5_%XPsBtn zwi7Wi5pN4)UwhYW5{^`*k)+`KzOUU^FP`4HbLXDdycuXb9&WG>h zBR9SK{|B%g%v5aW%skhbB2t(+cA7k~cu7fwlr0-ojZ%>y4wg$!3BendZ0~h@|Iz>O zlmF^p{;CT)5CR+^n{ajN%8S=Fjf@$r%=a)EiTWWJv@i!~#i8EO#@SKx`~`1G2LPEs zX1}SFnwgo|v113Y10n~?AvAAz-HO>%a4$L`uf;N&b*>;u8cr57p|Rjw*lK0};}g4X zLu$fBXelWc8a>E!AdyipJ-yWL3u$FtMU*%d>oTNqoLwAwf{GAHs=xVxcWjzu1LPcQ z1nn&NrS74J>gj#^AL}3Z>c_WUdn4_|&YBFT#fEt^+YU1bq z#n1f9fB8!TV-!L}kyMjq7O{~imc^z6zG#=pi$x&L`UQp$|Fbv#)UP}gUmy2)5_hrD zBBC^qa(a4t+qP{nPZJzV1<;(>w)d^?Tl~uJY6W0xgHW!Y134f&nM7X(ktVv?!{3>B zXBDoKzmPz+O7s&MO-YB@*$zkc+-N-ZI)%U@{(scH2b^7HnLqx#<&@i|m&{BieP+@d z2{j=FNPqy*00QEIx`1U_ad+JnR9tbRxNBKgQBkQ15h9}WB(y*%>Ag=TeKM0|>YaP< zX>a*|&imdunM^{W=J)&k-Isham&q;Xp7WgNeaiRwex+g90>T}K8s43E%rz9&fl|x> z`KASSZ02pZ&H3UNul)QSH6yCG?%7aMfQK~T4`mOGMgAU z3F*ZUi6KfAK{S_Pbmgl)sdZMFs&LOzXgMljSWOR(t`E{#z-fXJ+qR>+niB6rf^!Q% z&}6}7H@G+klyarr^M3|gs{kn?&+f;G@VXB*g7gE(&xQ7V?n&ev8gOu=MP{;0p1=f3 z#jbZQMf67V@Wor-d%$bi6|-`T2f$VPRAGe3nKvqh5Fx-#OiPQ(o_OrHf*F{{ zqz_b}FW!EKEr`hj8#5DQ98mBLgpE9UBYb~PlU$trJmLIbgUZP%2+Y%Tbt4c_YilbD zBp^z$PQM8h4m1Z0=gc=K_@UjO6O15VX$gPO0O_iuAQ1TNE#PKc5T|jdy{}Vc3bnRw z*{4RF4cV(_aPCV8N70!WQpLgzqXr3{$I5dS9-;|d6njCKl*Yg+*w@loP*MemK)__c z+^maZc4t?sI#jEmxN_>W^9NUoNwpd8;5&22m(7_x8YHrZSCn5`w1zEt@$i!)J~b5z zyhBH}Tzvj`;3_)O1 zVi`EV;@H1_W=56ZrHG}ln?TtlVpw9^D1hD@RU)A{^3IwQVojz~Spg+U(raV7hISf< zs#{EY^4s&gjN{1Av-$?GF!85xW6)^kXAO)Pq9hvh`KuQaDuN_T>0*;Gt7DdMp}XU> zK;qsyRz5roul4#3Tk-`J8EG*@`RYjn5wg#VqmkHX&O7=n36fgG54b@M&&%1SsIRLs z2!{aYIo-fFSejs;hoP?xL9k=@q4OtC1dhS;Ei1t>Npn$_L;wzm1O&2RSiQOD&F|ec zzlF`LN} zelY&7ukm=?r&v#^pY@arB0WW|`>D^~9@+?UK(x5&ZEa0UP1*GB8{@h>)Y!~_``hNX z-|I4w?K+-PEC~9Xvomi-io#dn$j6U1+gm!-ixjFT&oI^h<+|yv2dOEgnOrWBOof?| zP)s!vqneS4c!E0_4hA|ky8a87P!b~%=Yo`oNoE6gI@(a}X}(&o$5K#q4vYh=S>L4O zVRCA~)e;B^%w?FC69fVyPpP^i8M-usVPG^6LNr_EZ_)b5k-U| zr=!A1-!O0F{CSsfuDXQ*Ac8qiiERgnN03mWAKC7%%DVdS8^lc>CiDR!PPgv>l`_Z$ zb{t|ARl`TV{mSC1cp9t#2iwI$=)Qb>G&Ndf`I3XOH3|~ESri~F`5g_}~r{22#p2x2H%uAQt zvgNj~Y(8?#`}}9hxgzdLKwtr}hzSx|mZdx*reF~OQ-$<;cwOsWV8vU(6okYSFmL*K zhnjke_-a-`d_>@{3Fx)o%B3@*RpFSb5pf{6XvCBwj!7`3oJDMXfAx}xOA;W!@c>al z1572Aw%3z8)?uFR;QDy1FiR4S105YXMYZRva=DJZn40rZgCJ75LMbp}ipyPw#-=zl z5tUpzfs{xW<|G$^uni<+rnHz&pEPRbq=xe+*Od;y5R({$@By3Dmy9F(;V0I2rH{|Q zV&eEAaU66Et||wF8A@VW#F%S=OF1&lV#g``VAIhpEyu>xRnHhX`N+oAod-4-51YWT zK?^OB%N3+d;dY6XK_x&}8Zl}b#kMeQf}M5`Xc?xZ6d8?cR@GHc!I*|lAwN=Z#?z`Q z;%Zh(ggLjw6vf-x@rqR)Ac08e>VW5-+VkW8XizTRPe`z0P*@&@)Q1mv2*AUP8(4Zo zhAFlHj5ID@i1E4WDx6vaksEXVJi5wv2v|wn$hIE@=uzws3MAa$ur$I6NKd*`2t+6q zvhUEeR1``GNh+ltDr0JFKTH!q&@j)HzV^zTy9hX@{sreXTr+#jWz#1VC&6p=H@v=M z$J*`Nnl_HReB9`XlNDJTWO(_`oUI2tbce=dpyw&TD{&LwdS~l03vMpM^~@_CIsedG>#PJ2%i6T`%?q!+*>LxL@XVu--3@|SV0zMH6ssuUqwPv%MObZ6 zs*Oz;!2)AI#24H*5C}NV<$jxL5i_oZsqObkirzeakL=2!4Ui_cs zt6qJd_sF%Zq9}TA4cA%;3;<2skw&$2gnS{pS zz>&R|G}LybkBpf#_IGc7z=JGw9Go<4{)Wf@`@oJZhn8-gdgYD96=TYs*zQ#y>|FkO zb!A0QVa>qvMv*as3xOnlCe+QQEqTIYkBcsSX5l4w-~T=< zKu3C5A_k=~`1Ex!|FY`3p_OjNeDEi$o_yuVq~xgi{OV)hsae3szA1m0VJ%_o1#t=) zak{)UFQ%dg#Y}qicxzF4DVLIHdQgPyx-s6HR=~0Zoin*c7y=^7;~a^A3d9{LST zaqYzu=3jN*MH2^0N9=xk|HgN=>{z=y*X72UmBfah$U?)=d|xz*U(bC?bcY8y&M4ywx@>0GyR_bV?o(j@-UKizB| z-6A)UR4T<25Q_~EkT7^mfT!YieA*c6q)|kIGMS!U;$&@i2&#wXkX5XJ+UK|#qHtGY z6as_;iJ=3TJ;e<*7hF>`ex9$0Rr}4Xo-iz|!~?UL97w9lzfsRJ+ySvL3raS>qKXYiu_;?Cz0PKk4O^7?-cO>Hco1Z!qWeotJ;&^JNp~fJ}j5tF($Cl7N&|bH!~aQU2y@zq@Qed8)|X|MvSF6&2M^+uya; zE}pontLe3syRI8D%6RK7_rL)YBuCJn!1|PhRT)SSt)LiY#SUkTNM`1FRw%}S@E{gg zj>W;SATh0I!knrZ@2p=TVs>3}?)#5#9X7n;+IbCa{?6y$UGe2tH#BvFr(B?cp}r7* zX2>F`vB`Dko>#{Dc`mlJu*IL|I`T%C) z%a!9sZ+_~jjKc|^F%Si@hp`oo!2q4dFudR)tz3l!rOlg+BjsZpkhkl zWc2D(S>cF@%jA@@pFOkchya%wj0IR9f3faYW%=da22E!ms zgh5QeIVC1wNEQ?+%O(HeE4NOV|juDlH5$(#(v zSIU39rQwH9{{Gt8vo9T2-m!6`Bo;{KYJF>QmJWlWnMG957YGhE1Ji{XCv|m@oc%dIhkRd=5*xK2(>o|0GLZ%b%I^5OzqFho0bXL&?*VWINcqlKd#lyB3TE&e@3>WxX4! z;;*FK3pijLvy*P7t-J^?xO&=cH(gm#LYj9pfAEJ@JKx)z?Qv@2g@Q}Z4~P}#ObE~v zN(dk(CE<+Ob^!#yEg?WM1k}Lk&YWu{j~InD6R#bHJ;OqyW^`>|x6(p^;bo}sv1xjk z+J)uib(6jF;lxaYArZxd2q}DuRe#KvU^0n);NkrWmQggM&Nl5#%dy1B^0?2yZJRdC z9D2`nU2WdVKl~;xU6HIfcBnCo3rrBqKU=*)GR=yEA`AIRV#Bq!mKE8W#DWEe=GBq!2RN)H>)cfGZ8_0|SFe4tU4jHlXI*Pcw%UfJ}y z+S>LjTvb0goe4dB`&yv?K*VudtYgJ{k;K#Lm~#*9Ex#7PMY|lC(aw92oc6Yf6ujO zGHB&y-6s+POVcFn?T0U!Quo8}e12eA7>K>`hIZ3ts*qjSWd3kb~_>W^o}LP@cv*JILjJ4u5k1PLu)-^ z1^lRuvzeS+w&(R+=tcno43b-zcma0+b-~f?q78fkzOoxCIb$8%W-z7)vy$QQFW-O9 zJ>R7boBdtlvN>w5g~{w@oLCxWXo{(Ce$V*kFm~c*FwHSlmAv4 zl&-UVsfo3KE3$R9X%QcpKC$8rQ>*XzH?W7mo{snL`by=_9ThU5*d&3W6yW>g5qr17 z-g$Dz4}bzg0$(+U;nWyCs!82rZ+ae``q%QJG#pK;Rs`n z14VX9!!yqm<*yL9_Y{c0BM3OUi*9esmEtuH~TB!`ih>` z47Vx|Aj>mdS>MZzeQBz9L_tc$youp9Bcy8HxD1oXQ#b9CZK&6ObR$wvP3cw;N%0s<`a!3*)B?v)q z0BYhZv@J%|CJS0vRv`n_b(a(rPpU*5TV095F>|k?rDGwNgH+=1(MDM^KF6F?;ecbu zgIp&bd(GvN+{=m2&kh}qzDWKH-f`z05giieoB#>$7uEGbYUo@+`*?WFh(o^){^{0z z_uaQ};X(?8D-TX@bzRLZbL7a8>#n=*zWeUe zo=Mx8=XvpXTwB#?#$`1|SJ{;~QGt}8I8;EX0r2pY3q3{_7!n=`#Tuz@ z5u~)x2?t3?;AVI4*!#v(tKm2`p`d!ml{3b5r?>YUKQ#B6`E>)z_edI0nuuAH1OLmZ z?irU5!Zgk0%a{N5x4(V)<(J#q+M+pZO$BrLCBaGoEY2Vjct-QH(Wzwx(4(rB_I?P|zVl zX#S8BtV}HLYB}53JLu}58mUm%R`jOXqL;1wY+LRA{rhjZ<(3y;d@*8Z(y-%LET(w?v}=q+ z^ZUOZ<^S%3{*rkDY>Wl-lK~1a3J7p4>@f95o*_I-NJK1#O)g?G;bh!4s}xPXZ0INc z*-Q?GuI_#R_75#Dyfg?W!E?A29yW++2P_P0s80+@O=w^xk{EF{-ZU@W#WhKJw=74UL7QFmPQ9n_L1D9Mc#_9uf{E#u-kWlK(-0 z29N5oO(DWhRQ>FPbba1s__7ca8!Q5Zm;_;lkPkc!f@5acMgb546f*#dOd)ZA2}sja z4PizFMw0j}Fs&f`N*FWm$bmia@{04W`8X%3vib|JsH;ca-MMYM_HB5tGhkMVSYFHK zrAw_`=n_qA_-EYBwYsyOzSkFZ_wL=AUdvVM=MVql)z@BYYTToqqglW}-w2A*|LkDG zXPi3(<4*q?dlI5u}mSxnl3hD@Dls6kzBrv3d!X$QFvO z0EgMQqUYcujJp^jj8X1mBa6xl#?BcseZD<;7Ib?D7A-pd+uxB*n`$v)K^M1x7*;Oe z0HGJ5zAywBl7tRXiL~}ZPxqD^I1Te*gK`lR7bmk$ZrVj7zI)#-rAgTQ#-=C!>$fRh zRU}J*Gf9~*)MT?XA+%MQ*UvxGWr5JDs0rXRSE~w1gc#ysvQ2r9)qS|D>4R;JyV_bh zCQiMieBj_WR=*pttPMF^2+9q|5k^t`s!!c4%{Z+ZjzuBoHa0CMfVd$%l(U7zgd)xn zAs`uGuk%QwEma+Y3yut8)NJ_0vMs-Vcj|33CV%x~ZJU>^+r0L*?OVEz9iw2eFsVD! zSE#6{&{n0#M60W-BL)%eR2;|Y{jMjqHgrTuPQ*QDUtL{YYu2o}{r21So9i4<8+0VT z9|S=%nbgj#m-j}^&|%a&$f+VJ&avkS#!ZYIpT!i(w-b1d2#|yr3h&@9;dhw0r?_mw z$G(!7`Y~XIucj7^di8^XAZe(w8xP|(U||r0kPK63Bx8idB;sf0 z^%9a(MG5R>74%*Ys9^~rINEafy+1rP5ZcNMQ^V_O4sCn$;12SMFWwE*Vpg07!oXPe zbhNB`>z(g>!vvi1WzCdnLuY@iV8l4EQl1bA6-t0WmPy>e#n^@P{=*->X7_Y9zw=tA zbYQ~;b31;&C;glBJaX68ht~|hDw`7V0!E7K>YR1Ee4;wbXJqNT`s%BTi;KIvy8$4R z$>`Kf&){Q>U001)^?Iq3YdVpo{rRQ^(LSiDZ?xfBmcH>GjuN-`(9EF{UaJ z*YG6ce6*Qw^>WW83O*XdsmHR0&ndw%5=L7tBQ7eIwRPo}&KNi4Vn~hfw(i>hn`gRT zdcF8qHWf%rV-gF4b1R4;PjCVr0fs}XLW()kMbb#d0TV1KI(akfH7o;y0Ae;RP1xW2 z`dwGg84m(}`rT(*w;VT|m>CAAo&ZyVp$2_#>8@#IxoTf2Pu@~Km&GRETZcrKUI7hby) zN@8>(1+6Hso%arssLuO*)RFvqJ5+Ow)Y+`R4}?9H`kYySlnWXl_EP zBO$%0O|=bU&R7f+$vvAG9zuQq(wC;BS+nR!LD8`JpQ^a*X2>QWh_x^L{<=lKE$ns% zcsLbaXrFQE3J)l?Xq*Ot#R4RW8dL~F^#CJB3Zp0qCqw*B7?xC^4`eZ)XQoc7Gkmjk z%kf`*?=k0?4{4LqH~5pV_3!R8qdKaxm+B*%aP&(%pwAPL8qAe=0( zHpjSxWas2`OaFx*O&K-*!bW#^`s{%G|a9yR%PU`cKij-EDW|BBUZR!8@s zy>B!hsGdFuCfBqrJ~ryYX`9;y{28ReW5Z)q6OBX-+_WH&GSu|$xTk9u`9X=vPm>oO#LgT*gd{`MTYiCF2{b0d{ z-EZ!G}e3@Ctj z+o5!J-eotSSGP(@5#izt7)@;_YE@KJeE<93f9RoyqPRzA{+x4+dO3MepT8sD^_N3~ z^==y#+4X*>bHkdN8l5@ja=C(nf{u=k(039l5JrX(UZ!w|QFs9nAjiSnaB)0CVm-{N z96o8t)t`Xz7XgVuPjKv^XEy!x*A?v@0|^nFF~KB8I6*RA&NO4v$3z;O1(F8Bq&}A% zFp-ETax+6!f*@&wshNsSQ+W?JIgU&Q*pT+Zul^V60mHKdVw`YERL@D~Nx?MS4|)S7 zkS1cr*;ynFL-^ESq`l=hDDAL-K{Cu~m`~!bZ|yW|X2fIe@(=dic=4FJ;o|_(yujx& zBZ8QeLEN?}6V$?)O@}5XW|E-FW2iGQC*6Jf+NU2MG^pGv9T>Ew)7xe7$T4-(7C^j= z!_lW7d1%zQ$(`A<_4^JM6^u%bFZgixnn~po?RF|W8;_pNU)iN2M^i$766RBu4%OGJ zS)+5YD9qAq$_OLD^8`P6Yfw59LTXQ@@FECD+T)S>SKq>cX_}fmLdQ}Om{`Ar5TYZh z)vH&J9z9xDId{ zpV>2^;aYIJjhYdo=Pm$D!yxheSxcV#{RoI5Vv?MgHgxFr%}qaEy1FTyEO2{1^Rc=a zlP=k^GHTHU>2j9HeYEzB^CTrOu>mhb!eBPgZ2cI`4vGndOnywRZ*@}Srt zafL(lvFU-4!ZzgGgQWE0yY8_rx+qNdd<#}>Y5duf&2N8L=mo_F#Z)>xi!^Ut{xbK| zB+6$bs(_(VHdSnt02I*xkX=y@gq&I)?=wuHTKt&es(}NJG#?k7M-c;(NS+h4Rf*Jr zIt77jIe5IXq&)nE>Q@tlzwmeS-dg%5Pl;QuorHN7h&b4^wRrg8ul~ywnBh3~0c8c@ zKKF*)GK~}z_8iUKIQ;>r!Ed~{_~NT?0$dKl;lQL_;0HOd0uCNAlfxRuKl1v{Jsozu zY)s6ho3n+Y>VZrC^wt%3d=n7u9mIm*bj)UbSEMbtWy_YxGC1dR=gu8Gc<`@& z^{a-4hMR7>skyoN(MKPxudn~)CqH@k@Zl$(cw+G2!Jqonr<$9aA9>`Fkt0Xmc;k&N zEiF$x@kDuf`QQKj-|yYK_t|Hk)o$;`8*dyvdi3hmtCucax?sVA`uh6E9((N2p+mRc zdh3W0BlKhK!&a|etwl5rg|1EIUqqX9{vYg znP;Mi>e*+Xjkdz4pME;(An6L$x^?TcOFLmzocoNG4JcQ+IWnXMz(}wS)ZEql`xm?a zwANd@vIs<_VfvnjDWbNi2rMM>0xD6`j&}=o##0d9gL!%pr4q*xc1%)SJ%DjWPcg`o zz*)Kl(J;E<4g9vy1lo!K;;*ozek%x=fi0;}SdClv%;uL6B0!1fNlFFJ;#`M}5rixu z0W*%WJUEsnR?N^eawJShoPY_CvimqOJ+NX&+K!$-{fa~Fet9v*wnYQzIoeh#Ik0u(#_iXC>0XGHhHuL-A^@zvz|co6&+|5I z+LS-fN*zPTJ^Fe_oJaaf>!<0oF(L-nL3dx8cun-pdbL0L4ryt>sI5&uLGQet=e_;* z+mk0x)*qy0HGF`A0aXGc4AK?MM-!g*f2miwF4>+Y}`I#&?v}pusBFZ z+OaU=4q}S%SnOE#nnd-t{>N(v)48i>jrh{7(@W*iOeXilTV0zDtcEN+c+b44Q!C1C zd*mRv@X`yZ?Dh}u_~Y+>Gw$*Q#S<=2cxE61OJDc%&JG9{LM&ObB%96l4ZR~~Hcb=H z7)vA)nM_7UPMS3y`s<3zei{f7Ree6eRKJPdK|eE^^wJjg!yo?e>8GELtTPPG3`^QE z4|oiRn~Vv}2r}Cqd2~>BcMOH5?}aHC7;4BJ2;r3Y7z+eM0%3?E&0}>2pM^BC4)-=A z1B9JK3ntBt z3`*fdp|en6+T7=c6r5#<;Z~FubhTw5CxF;e=8%Ql?!yDhTmIrJlP>#s z{RLNxFuMs%j4)!RLX%5$_9isO__4tBx?IdZ{*1?}za zzx?GdM~@zT zfxh+DTRP10eP7p63rfmB4_0&2VxeDgw>4Uf8;o#)Jw$xPY$XvU3LZu{wq)K9$-G12 zXK)^}ceqleIchs3Mrzm~h}nv+qW|-0-P^C}vSdM<&%t6uv>n;Ap>D(lfIaA8 zZQB|zyZ+;iFSMBf1wrM)~z}nHSgNB>wyOz(1J=kckX=f!3T9D zw0G}b{d*xqV`Jk34?Lh%Sa$8&_27dK>eAQIqes8Nzkq{m6~ht$Pfh z6vZS1WEoOnyoDO*p%Pn47MH7ecFkRZ&v*ia${ICcB$i>4&m|r>ZY-GewB_Fu!MmQ7 z)ifXFmF0)G9U+KPOf*5+IWky=;ezCvu7-kfwCSkAe5w%vDS$J-?fClNEy}hxXLGH{ z&zPBR><8=jZE;LQBtikRN(y%FS>Ar28&#CDTo=S9&zoA2ZQb9Lb*9fBGI?YY(R4*Z z-hcO%e|mpUs=DNsIp-n28Io+*mNiG(yBjXNs$urWAzmeAQAc7b|o<_L*88^?f z&psOk*BU!@=bd+!mX<#E+;iKvZ@=@-JFBXy7B61Bd-v`kLx$XP%Pofv9eVun$4879 zaqF$OwzRZ7_Sj>LvCA&IY|4}=YuBz_wrtthv18}Ypa0rxudQCanh>&J!Ge(^NABOh z|LLcnuB@!QC!c8*679##(3q*m6|VEZ;plWxT%Sn zu>?a=L+#jIh0y7T*vAy(0L$C?jw(aNwf5=$KQSH>GvcDi<*cL$|=L_uigr!Qj3t>vk?g25H>Cv zYk%=4cQ7+NK2vg#UbeI4m0$d9$k4&V#*K*^2|E?TF#<6JaSO5*kP@Ii1hQrId%L%< z;BA|xef(Opco>wA0vQLx3o@-nF1_!=HA81z1*vlA?Bp$*JNACC@q-WiplH@V{AYYv z1Ay&t(=agjQenH`-@mi)+u!~+65$r?_Xf+S{R*7(^UgbO$BrF3eAcBYUCq)do6gQO zlqKrG=(1Daz+6ZAwryv#S<^Iq-`6~%k;Yh5aM!Q(eLs2!t=6e6+ceGFZ@>NCd+&7| zr?s_}F*b9?EQ6Yu=5jy?SXPhQc>MyrdPUp^DNIJd2$0Uh1QLwoh2jAuRpy8#Fg57& zQ5TUzc!Oi`O&+={hOKm>coH5 z&aK=anDh|{7Ji{HMLK%uIP?H14nLQJL>MQ^YR{j4Ye#2iI#%7qaDiQFP-J4@!m#5h zA~2(1V5pilx9Z}HnwCHN{Bz5R|3*nHZYB$AYRU^MijMEv6=eOL*{+VR%z=FeOyJc+ zss>(o!>Eg{k);g+QGu|Dv8vSO;c!w7x`sPZul4Awm?yODbC%oN+jTw|$%#dcJiU=c zTEJ0Y9_b$HpuTU-BAd-dP%3RzQLUA8Zriq2Bhx8l^xD3%P`>YP+_=$k9M^Sy->;~s zu)?HAct8R`7H81i?QGj$=%E}Hj0SNpv__4Z;y54mKNX5W!f2pA9y? zyA3IZd?uMtgXR?@M&*c|&iT?HoH5Qoa@%6IhHVjzpT;K8;^CLxdh@+Mz42>5yzJT= zhgVi~Htt#ZhZjVaQNv6hIfepx%jfU8e&H`J`oi}|U3ZVD94pKiLIw?QW%UhdXwW%7 zhmo*IcrV$BMC4s`={%~E>&v-n)hdLLZQGIh*N=bvW6$$`{p(-rcx&a#m5i|~ue_2m zwtDqyA;c9|T){cN;f5QI9zD8l-MYfU!nt$jN-0;aT&ZpD=9_PpQhxf=pVoMo=bn2` z2=V&suWJy_4L95%rToW#{70>&_`(Y>1VM1=rI%`Vg%H}YV~1`RB7{bc92rIwSa<>( zKnV-Pi%YCd-wxtJ8UZGTq?&R0>W^OD?s^Ocz z_!=of3<9JWzcIq=)~(~57Zw)A<8i|1aSB|>LmmpkK9U3YM) zLAf*p?~YsMSMDD1FJI<%9Qz~yQjNL5g!xafpY51rdTqjBx!V=SV4aJhL+0xIF1v6GY!M|*0;VD{i~Gnx#ym{ z{`%{+>8xG5R!iRN0W56_I>6F)5WO%G9}q&=w#^vRg>}8tX(Q7x`6v{N!X}Ms*B(pj zaYofwjIqXn=}1e5Vh=z3@b|v=z0h5$wi#!_G{S6)Z{9}t9H8J!%uNQS;uSu(rW{C& znPgIi#w~r6L%3#i0~iXOKu^Q4+BXw8>EAAyeF4~#BPP^UKPPL?ADaG4Vu>-QF`U@8 zb|DAMigpl&`a^Lq|*A03XV@%zw;dcsDEQA#ChAAXv@YOHewRh{bMUOsy!_`+N zi75!37!%#X0wV-*KF%Al}o{qs!v1>*{|^r_-;!_F68N6GB{i z>7~B!&zUnvOSWn=%1;rhD5|QeigW(>CzHvtva*hjj_CC1GZ=0?N_a$(3CYk9 zi3H&RCS|4eEw@~E%O~dx&%NueyPjI~`$XIS?mrbUYu>4LjHPD<(f@4p}M=&e|>BAHC;%?tVny7tZQqV3PN?OZOW ztLiIOtkB~a+R%00r$G(+9a>siVzF4?`g#ljj2=B&`v!gY=RFn|m`f}~=z0(rNJWq)2oeZ` z3xoNH`-#NQe*5&c{Y?-2;71qCxZI2<1vd~kA+UfMaB{~p!c=Li(xSZ)%v?K+zM{a9 zW7C0G6cXtNx(FUUK|j!!UmH#IeC_k}o9ka{N2On)6NP9LN8fDG55_~ zzu#039e}L7c+@!_7Sf~r8r_J(5Zf}Xz+;^)-I|Rq`Ut}?MvopHZHW5JiqN(g2qpwq zW71dx5nwZj2jQO-hq#xM1RFzYhkfyL|M0}GpLBY9B=d#uO3#tLBL$azmfi}#`OR-? z52UYXzMJd&*=$yWef4P9q)C(hA4`j$y0ou~c53YiEz4TGcyZpuK_K6yIcN3#-%U7f z7%qg@5i^3>DMNpM%>gLtLIU7((P9VIpsWxy{Rq*FGX0-?vZ3YU>%8Fo$gv~iskra^20eFWeYKF(`%?VPPR-%yAqYze|vTQXLUWA_z&L=0x%(V=RGU>^fOO1ff7E^0+67 zRCTW~U*xzyrag*&VzF4HfUipcx_PHVB}(ar4IB6w$^QPYu6|xtJ1xDp>MZhvo<3$E zf@6zcDRBc^4gCov&8V|3D$g+~1TFK~pMDgc zXkgSbaEeTuF>U>;o4l;23T!91cl6=PKD07t+r-tSMH>7K0&!ou6K0I#9DefC|M}

~ZHKOF%$PAdcI?PxGL%xKLqrgmC_m%N2@#46BG0#>!bf4pOrh#n7*m_X zr2a<%fDC~Cq9J-uky7gLNL!Vjrqap0HZ{)qym|BVMLkD4>%VmANQ-lxPmet>o6TlD zH{G31r_;$qV#?I1hGnXvGx9voq70gv((kP)3OE*03aRinO2Qok5fU&u6M7-)_4T#C zXh>4&4f>o5O1cP4xM(VvI7;&ssbc@LqyIPb0791;MR?gMP%aq|xbBX*Ih5fRSLHRV zSe3Y9Ak$73YYEG<-42q24_FFLsj!6~_|P-&mj{dA{!k%oUPx5hyTEn52LtSdleA=&($+Nm7C}XEtaar2L(9iWE(RKhbx; z?yH!lsmWe+xgp}_?}xwpf3UPw>BL3XDP%53Jg>{owPm^mplQ>lnWpK1bQIvnvMlJ# zZn^(kEOVSm7VcWYzyb@T+Iotc`pogW?&=7IaiHptYA1$&FbFCI7QSVG2l2+zvcx5q zxGK~Qvu(gciMI61I3x8k8Eu3L`KGv12tXVfCe;VXmk~!$?+wq5uK_s;jGYD9t%{-JIt+LE!h+p&9bB}Re!T9O8p|haa7OC`kuo)mdS#YgKGyXsT4#&sn>BPb8gSuD{^Z$Tg+Ge zDlC`+^lKP!cs0-R(MY42d%2*v7Cl!kglnxtB$>}VYR&xn&x%CcBo;uvo1ucakKo5b z(dp0sR2|STeu3d*hv1mfp^}=FTD6$8Afm2N$+JLtB!C|<%Zv%n#aOt~t)DciaA3i@ zb!%Ij4;dECG56VL7wh`9=7`c+*x_10x(M4lk5X{m*(o05O0mnsg#s(nlxG8V@GCwQO0!w0!1C1Fze# zZpo4*y0;(Af>KJSPMs=*(3L=aiuE0=Z|J_9KL2}dOPf)@sT+L@so=_UUDx&4vCgz4 zWahN#2FCepEP&9y{M_+JpXmNzZJ9JJm&G&_DL#Q&kbg#Dv=93zFbqtGJGvL7awJSF z7aOUm6Ch=Ss#oV<_z`c|*JGX7HB|gU7;rG5rhdS{`YMT;;>uQ~&@XlSxEDR5tw=UDW^IS9Hu#uPNFD^CsoGxm+&OouSwq(okPm zR0vo~BMgJooFRfgy}a?EpH;iQEr4*LljJ~AiKdw#HzJU_8tT$a$7)vX3v!V->6hYSU{TH4yFDoj5=J#-gL z?5Q0$y=EHe-V_$-J~$#vZwaY!W=_~PrrYfO)csANh%+V?HJuibYWfgSP;QiH7#54G z05#o$&yc_e)<7(79GuvIilX7Jg4GagEZ%_;ZPBe2PCm^iN2i~o~~uZ!{K^1srMnd^77%g)Um9iq8YN~~6wOM_^;E{>G}SYv+c;qLB~2Dik^ z^Fp9}II8>cZwSyJ5JZOg_(Fe(&8|&$T$8oFF@P@Fg4WTUdjQUi4*a9+H@91@p&$}B z*0o$|R$XPbnpEmjjrNa&4c9b1Wxe-sxKWoMhHa7uG(*ww^D3Wcn%pYkZ0!;nWvGu) zQxrCDM%1ZMdHi7Od)X@QH3z>jM8jdY>8}6m0+KVJUG$!ao8ObfN-W^UUPgf_)xpVW zLC~A}B;ufh`4!8E=w`0#u;bB4*V=f6np)IHWq?k`H+@PipH~{66Fxc-3tO&%^di5R zIr#3Z=QU83H~H*97R(JI#iPIwFD|_)x$0Xe@RI*Up_U)bx+XsGS0iiC5(xq7MFjb2 zeqYmMX;fG;Mob4D; z(dvB&L9 z;jlg;(L!_J_J))R!)Kz+Htqi18TjuKcUeE6yC5QsqmY>UOzlzd02QN3fI_spHLT0G zR)H({atgeTN`13{qKDaF+&o3Riv3E6>KaD*F%p{i#4gwJqqij zcuvoz-Co=at%+yCsJWSN1!SzWdf6$MAVn^6F;tSP{LmwVfMJ;y1tA$>P&?Wkx>fq3 z89a{^l-{hW3m=xvO_Vyx>bA65uTfy3ENPuX3GPoX$S3298PaYJHab`MuiIko4Kori zD|(4K8lsp7y8p#b#`Uxi6%vk?p<=Y8#bQP#q5V&nj$)$GW}^G`U)_IcxtiCtRaK5_ ztsdDbOp6`GVd10S9@SdkPHTcAYghR-4W$uPf7Z>je^m?27xdT}Tv;*NydxTD!5ijR zp_^_Fd0D+Za`D*`mL5j=yJr#?5Qx?8&-O&KRXkXe>54nHAg1>hX0UJ#!N&FqBP|}} zk1KR_w|s=;8Idl8?lJ4B^WCdu_Iw4?Ou2@C6r2l@*tm&sxbv>r)Y!UWh)Iq2xKcgR-e%=fd5vNt9DCblRWmVYH&}XRy z(Pr6@kw)M;uebC6uceW8k;H`*`^cuNt4qMF_KVz-DRs>D$4c`}EnaD=Cgo2z-ZxGC zmpA#5vVtFRvuAJAf#wJd`u^YVxb8MKG7lZ%ZOizL6Zz=D#7GKO$~02R^_9%@QJn!e zn2HLTI$BvI=vs1shok%FEKUGTLY*1Ztz+pL6r!<0W%J;cwj3#h)5DBTMw*Yy$Or1W z|6Jb+jsk5HYTN(G&e#(d&9na2sV;|Ytls6nJ=;A@`%0B+6yW-zM^FTwQMofi_O-h6`J|Q!K%7;bKHspzV!eOj+3-qb1RDF}4$O`N8 z+&Y3Yq?mA-u$UC3d)hFU9iXxjJF*M(BxD`26kPfF_+(4w?lwatQ^$Il5yL_kkB5jQ z8AwrB2YfR6H23-2j{fX7);u~$;Mfs>L6jAQu+HjgcH&stfRStw#}v!p`$N0Lw?z{C zhhm$*ATE#M56VO`1XMV{;xmqkZI-_ZKSCvluS$T&oOX2(VfE$Ap7e@ZNv(F6KJNah zd1~^}xilR6%0%l_DcwgA*^*;>D&&^qBm2^1af)YOxxB0@vtrq;gkq&d&d0rT=lkN% zHrLRfr?yBu8A98C(dHTFE)oCR{nteKdZF(3$5&I6HH zg}S7aA1wX9_g}ufJn0v_poUC0bI|=v>B9$CGyPVfZ$HiUZVDgbPvGC=-5PPRB3^ZXabcA{v{i~ z{==p!CH6H41Zy=~-SDlTSzxPZL0EJ=hqHF{J@sz6&L1)O2MZoo-_p2jDUEs4g_4^P z<`6RX7&c>vEV)U8jw;JvZ^|X5c@b)`JELXkfI&VHOxX<$JQ^T(*hJ&?k~Y*3O|ZeP z6uw&iZ}v{`56}y|5hRzU{m8yTssVW3|K#O6&CYL6S4-w90-*`Jj2Oe|8B>eTu{}@z z#|e~&2?=#{b5v*I4y?l49QC1Ne6h>TbQMaabXcFbZ9h1A*nY5OUE9Ahd84>xuf?xb z9Af8_3(!5BcsJzrFy8)sF-fZMF-D5!cNOhtc>@e4`z+JI>wUqu)sCD)4>nlBu_>=g zP>#xkCYf@D89$fz0`H2RpkQqxwM4*Q9O|xed#H<{8W$M6?a;emP-d*bKA6x63~s#N z2z)yQYJ1|L&D*b*s{nKVa(Z@lmYkgIErKLJ=HU-m-E1jRQi)<0gO>Xd47{__7pj(-+HZK`E1=yXBjSmVx| zQ_VKH)K7PGTXtzWBmcaOsoG~l(M z>#5oEP}35L0=JjPf0a5%KvI&LnyNJ}Q-q5h)fb~lh)gre{daVo9w#6M{O(L|emoz- zOX>OaWa9`X}l?nQyuvCmN_f9VmCRcazipU*QgyjS2fF9IXpRxvDl`zL$KgQKPf2deZM$|Cz! zmYJz+0Kr$a`SZPS{G;bX%_5Ab%sQoykY5ow*+gmQGT_Q566J4>lOD;x{$sap+njd& z-#2+hY*inbM6pg&Zt~L1kz5A})Wvvsc|Cz9WH>CWI-BRu>@4m(r1p-EsHmuyV9CPU z@ID$1HU!Mi?Ik$~K{zKF!r~OT@Z+KM;!&2LM8?1C`X!%Pr*}M;AB*tWOBK8mGDtG7 zsH@xT^!H*RL@*t><5wSo+q=4)*c_^%cuSbfho#JRaIM(Go2eqx9TPy2I|t~EI< zTwGiL$_v1W2vG=N4*dVRvCtiwuNVe+3cZ$yG+M&I{;{Qy^^?Fer%;mCz;ra2z?HPFH$;a^D1%Wen_dX zUYFnx$Nxyt)gz0#eerW~agci;QvX#_A>BtXE#EJ^x4=_GsCNA|DSSBv1~vQ?2OH5f zjW-fAF)j(@Q{r<|#Ndef>4_4!jrj%R0z$F11#=6zoGj@vs1gY9rv6z`*l(F(Es(C# zKm@tU8#Uw~LVevemlOF2%m=Om`b|oVsREZ3RjeR{3Ubs%lScg;CvwZ8KsCo4pG`mt z26Uq9A@HAmmN`g0B0lYJbOn-Gg-OwnVj@)jTs%hZfN*BItXllGI0myaX(V7GA=sSq zq(gO^%Ui$RH1<(ErppTn@M1TX$#i zr>7umVl5X&>X|l7`%JzgXg2k%Co4e1Z($osnU-~vt0?!Pj*Bk#^PP$6d3);G4#FaU zT4WR*B-CmQ=_#}KIhlFv?rnznjj%rjUkfI_VG*d%QgOBs4$_rryAnzX8^l}klo7_t z!F^L^eF=W6HSMVFyizL6^7JJifH5;MVN(cki--UrsH!Sf=yG34l#8a);q}9Fu;ip9 zLKNmRH@6#14|Fp&eleIX%!XUxnNudr!!x(G*6Fb;pE$CcKM3x`0ViEvUUKz30$e;v#Q&4BdZwS{Z56 zTraU#OM}&eL>)k7<4ybx4+Wq3oB#A&J-!JA{dHIL1<8PQ_qitKU`g9 zrdQj_)3hWaQ34&Tgfr;o{CDXR4Y_Q^jcV0D(f(OQ-?fOJFdts_rm>;{q0(H zrm&v$LQ?_}dw3D2FgL#k3FD>p^$QAr6<1&ZWs>H+Odh?ur)@}hT^s#mnlq_z&gzIr5cr^02VWQg*(HRxN`!xz$Z$&<0*j^$c85ME-d zsu~Pxii(PAYo}q?Vcjx217G-rf+Y&h&(Eo;sZqCB8ndQPDW8mzwT5>ut$Aa#@up$+ zx@}gT?Q^Ig9-_hRuOucME(sfq&s@Q+*OF@;)l-?)DCOY2*tUtq8b)x?^P2=4Y1=q! z42-M2Hn7Xg4=%$dK0f}-{dUym%bBlsr4C&(9A$r1^s1VlSUyogFM;^}=+>46Hz^n= zg60c;*~xb2yNNzTx<`r3iHD$WfEs5`RjgY)-k9jcs#8gnwp*Q@oxQ&o8fJ_w)&(bN zu>9KCNGN+0OVs;JHQ|tqq9CTCmO4%0A8QEJHw@N2mVDcG3H0qLCC&NopN85|PG%C^ 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 rtcg~QGB1~>Vgu(`=ja;_9NgO*!J{GnCM#|i9Pp Date: Tue, 23 Nov 2021 09:49:45 +0100 Subject: [PATCH 12/47] Set theme jekyll-theme-minimal --- docs/_config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/_config.yml diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000..2f7efbe --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-minimal \ No newline at end of file From 2384d9122a7cc20a6a33ea240610e4ed65e4ccbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Tue, 23 Nov 2021 09:51:40 +0100 Subject: [PATCH 13/47] Removed docs/_build from gitignore --- .gitignore | 2 +- docs/_build/doctrees/API_reference.doctree | Bin 0 -> 44588 bytes docs/_build/doctrees/Examples.doctree | Bin 0 -> 3612 bytes .../doctrees/_include/API_reference.doctree | Bin 0 -> 12402 bytes .../_build/doctrees/_include/Examples.doctree | Bin 0 -> 4483 bytes ...pol_utilities.label.compare_labels.doctree | Bin 0 -> 11590 bytes ...bel.intersection_over_union_matrix.doctree | Bin 0 -> 12066 bytes ...utilities.label.match_labels_stack.doctree | Bin 0 -> 10655 bytes .../biapol_utilities.data.blobs.doctree | Bin 0 -> 6426 bytes ...pol_utilities.label.compare_labels.doctree | Bin 0 -> 11610 bytes ...bel.intersection_over_union_matrix.doctree | Bin 0 -> 12086 bytes ...iapol_utilities.label.match_labels.doctree | Bin 0 -> 11809 bytes ...utilities.label.match_labels_stack.doctree | Bin 0 -> 10665 bytes .../label/Compare_segmentations.doctree | Bin 0 -> 1362681 bytes .../notebooks/label/match_labels.doctree | Bin 0 -> 629194 bytes .../notebooks/label/visualize_labels.doctree | Bin 0 -> 7548 bytes docs/_build/doctrees/api.doctree | Bin 0 -> 44612 bytes docs/_build/doctrees/environment.pickle | Bin 0 -> 47486 bytes docs/_build/doctrees/index.doctree | Bin 0 -> 6858 bytes .../label/Compare_segmentations.ipynb | 5614 ++++++++ .../notebooks/label/match_labels.ipynb | 3198 +++++ .../notebooks/label/visualize_labels.ipynb | 98 + ...e_notebooks_label_visualize_labels_3_1.png | Bin 0 -> 13455 bytes docs/_build/html/.buildinfo | 4 + ...e_notebooks_label_visualize_labels_3_1.png | Bin 0 -> 13455 bytes docs/_build/html/_include/API_reference.html | 154 + docs/_build/html/_include/Examples.html | 131 + ...biapol_utilities.label.compare_labels.html | 141 + ....label.intersection_over_union_matrix.html | 146 + ...ol_utilities.label.match_labels_stack.html | 131 + .../biapol_utilities.data.blobs.html | 134 + ...biapol_utilities.label.compare_labels.html | 151 + ....label.intersection_over_union_matrix.html | 156 + .../biapol_utilities.label.match_labels.html | 147 + ...ol_utilities.label.match_labels_stack.html | 141 + .../label/Compare_segmentations.html | 5798 ++++++++ .../label/Compare_segmentations.ipynb | 5614 ++++++++ .../notebooks/label/match_labels.html | 3465 +++++ .../notebooks/label/match_labels.ipynb | 3198 +++++ .../notebooks/label/visualize_labels.html | 411 + .../notebooks/label/visualize_labels.ipynb | 98 + .../_sources/_include/API_reference.rst.txt | 31 + .../html/_sources/_include/Examples.rst.txt | 21 + ...pol_utilities.label.compare_labels.rst.txt | 6 + ...bel.intersection_over_union_matrix.rst.txt | 6 + ...utilities.label.match_labels_stack.rst.txt | 6 + .../biapol_utilities.data.blobs.rst.txt | 6 + ...pol_utilities.label.compare_labels.rst.txt | 6 + ...bel.intersection_over_union_matrix.rst.txt | 6 + ...iapol_utilities.label.match_labels.rst.txt | 6 + ...utilities.label.match_labels_stack.rst.txt | 6 + .../label/Compare_segmentations.ipynb.txt | 5614 ++++++++ .../notebooks/label/match_labels.ipynb.txt | 3198 +++++ .../label/visualize_labels.ipynb.txt | 98 + docs/_build/html/_sources/index.rst.txt | 26 + docs/_build/html/_static/alabaster.css | 701 + docs/_build/html/_static/basic.css | 904 ++ docs/_build/html/_static/css/hatnotes.css | 15 + docs/_build/html/_static/custom.css | 1 + docs/_build/html/_static/doctools.js | 323 + .../html/_static/documentation_options.js | 12 + docs/_build/html/_static/file.png | Bin 0 -> 286 bytes docs/_build/html/_static/jquery-3.5.1.js | 10872 ++++++++++++++++ docs/_build/html/_static/jquery.js | 2 + docs/_build/html/_static/language_data.js | 297 + .../_build/html/_static/logos/biapol_logo.png | Bin 0 -> 41688 bytes docs/_build/html/_static/minus.png | Bin 0 -> 90 bytes docs/_build/html/_static/plus.png | Bin 0 -> 90 bytes docs/_build/html/_static/pygments.css | 82 + docs/_build/html/_static/searchtools.js | 528 + docs/_build/html/_static/underscore-1.13.1.js | 2042 +++ docs/_build/html/_static/underscore.js | 6 + docs/_build/html/genindex.html | 144 + docs/_build/html/index.html | 141 + docs/_build/html/objects.inv | Bin 0 -> 1448 bytes docs/_build/html/search.html | 123 + docs/_build/html/searchindex.js | 1 + 77 files changed, 54161 insertions(+), 1 deletion(-) create mode 100644 docs/_build/doctrees/API_reference.doctree create mode 100644 docs/_build/doctrees/Examples.doctree create mode 100644 docs/_build/doctrees/_include/API_reference.doctree create mode 100644 docs/_build/doctrees/_include/Examples.doctree create mode 100644 docs/_build/doctrees/_include/biapol_utilities.label.compare_labels.doctree create mode 100644 docs/_build/doctrees/_include/biapol_utilities.label.intersection_over_union_matrix.doctree create mode 100644 docs/_build/doctrees/_include/biapol_utilities.label.match_labels_stack.doctree create mode 100644 docs/_build/doctrees/_include/generated/biapol_utilities.data.blobs.doctree create mode 100644 docs/_build/doctrees/_include/generated/biapol_utilities.label.compare_labels.doctree create mode 100644 docs/_build/doctrees/_include/generated/biapol_utilities.label.intersection_over_union_matrix.doctree create mode 100644 docs/_build/doctrees/_include/generated/biapol_utilities.label.match_labels.doctree create mode 100644 docs/_build/doctrees/_include/generated/biapol_utilities.label.match_labels_stack.doctree create mode 100644 docs/_build/doctrees/_include/notebooks/label/Compare_segmentations.doctree create mode 100644 docs/_build/doctrees/_include/notebooks/label/match_labels.doctree create mode 100644 docs/_build/doctrees/_include/notebooks/label/visualize_labels.doctree create mode 100644 docs/_build/doctrees/api.doctree create mode 100644 docs/_build/doctrees/environment.pickle create mode 100644 docs/_build/doctrees/index.doctree create mode 100644 docs/_build/doctrees/nbsphinx/_include/notebooks/label/Compare_segmentations.ipynb create mode 100644 docs/_build/doctrees/nbsphinx/_include/notebooks/label/match_labels.ipynb create mode 100644 docs/_build/doctrees/nbsphinx/_include/notebooks/label/visualize_labels.ipynb create mode 100644 docs/_build/doctrees/nbsphinx/_include_notebooks_label_visualize_labels_3_1.png create mode 100644 docs/_build/html/.buildinfo create mode 100644 docs/_build/html/_images/_include_notebooks_label_visualize_labels_3_1.png create mode 100644 docs/_build/html/_include/API_reference.html create mode 100644 docs/_build/html/_include/Examples.html create mode 100644 docs/_build/html/_include/biapol_utilities.label.compare_labels.html create mode 100644 docs/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html create mode 100644 docs/_build/html/_include/biapol_utilities.label.match_labels_stack.html create mode 100644 docs/_build/html/_include/generated/biapol_utilities.data.blobs.html create mode 100644 docs/_build/html/_include/generated/biapol_utilities.label.compare_labels.html create mode 100644 docs/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html create mode 100644 docs/_build/html/_include/generated/biapol_utilities.label.match_labels.html create mode 100644 docs/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html create mode 100644 docs/_build/html/_include/notebooks/label/Compare_segmentations.html create mode 100644 docs/_build/html/_include/notebooks/label/Compare_segmentations.ipynb create mode 100644 docs/_build/html/_include/notebooks/label/match_labels.html create mode 100644 docs/_build/html/_include/notebooks/label/match_labels.ipynb create mode 100644 docs/_build/html/_include/notebooks/label/visualize_labels.html create mode 100644 docs/_build/html/_include/notebooks/label/visualize_labels.ipynb create mode 100644 docs/_build/html/_sources/_include/API_reference.rst.txt create mode 100644 docs/_build/html/_sources/_include/Examples.rst.txt create mode 100644 docs/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt create mode 100644 docs/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt create mode 100644 docs/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt create mode 100644 docs/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt create mode 100644 docs/_build/html/_sources/_include/generated/biapol_utilities.label.compare_labels.rst.txt create mode 100644 docs/_build/html/_sources/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst.txt create mode 100644 docs/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt create mode 100644 docs/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels_stack.rst.txt create mode 100644 docs/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt create mode 100644 docs/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt create mode 100644 docs/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt create mode 100644 docs/_build/html/_sources/index.rst.txt create mode 100644 docs/_build/html/_static/alabaster.css create mode 100644 docs/_build/html/_static/basic.css create mode 100644 docs/_build/html/_static/css/hatnotes.css create mode 100644 docs/_build/html/_static/custom.css create mode 100644 docs/_build/html/_static/doctools.js create mode 100644 docs/_build/html/_static/documentation_options.js create mode 100644 docs/_build/html/_static/file.png create mode 100644 docs/_build/html/_static/jquery-3.5.1.js create mode 100644 docs/_build/html/_static/jquery.js create mode 100644 docs/_build/html/_static/language_data.js create mode 100644 docs/_build/html/_static/logos/biapol_logo.png create mode 100644 docs/_build/html/_static/minus.png create mode 100644 docs/_build/html/_static/plus.png create mode 100644 docs/_build/html/_static/pygments.css create mode 100644 docs/_build/html/_static/searchtools.js create mode 100644 docs/_build/html/_static/underscore-1.13.1.js create mode 100644 docs/_build/html/_static/underscore.js create mode 100644 docs/_build/html/genindex.html create mode 100644 docs/_build/html/index.html create mode 100644 docs/_build/html/objects.inv create mode 100644 docs/_build/html/search.html create mode 100644 docs/_build/html/searchindex.js diff --git a/.gitignore b/.gitignore index 01008fe..4dd0563 100644 --- a/.gitignore +++ b/.gitignore @@ -69,7 +69,7 @@ instance/ .scrapy # Sphinx documentation -docs/_build/ +# docs/_build/ # PyBuilder target/ diff --git a/docs/_build/doctrees/API_reference.doctree b/docs/_build/doctrees/API_reference.doctree new file mode 100644 index 0000000000000000000000000000000000000000..26e65f6f9a42a5596ef84f6365965f654dad5ecc GIT binary patch literal 44588 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 I>Eq7-f9bm(vH$=8 literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/Examples.doctree b/docs/_build/doctrees/Examples.doctree new file mode 100644 index 0000000000000000000000000000000000000000..41070dd6c32e3cce36a4d99c5fa82151a584f28a GIT binary patch literal 3612 zcmdT{O>Z2x8Fno1N~@2RWY@XGa@Q%0I;gdBod7L_A}}i3K%+z{j3R&m1q5e?yJW>7 zrzA&O9Spb!19rfhr?>WR3E_`vs^aFTVd{K}&lO*0A0fd?#Ce#d6PcIW0rQThQz z*L**tu#3NCHH{31*Ms^KldN*jPkz^YC&W@wE!<1}(nToc;QzG-7g;>LdqtB~0&L zAkGoG5BKg>?j7-)0R;YIM9yyk+@Iig8^538_W`2fKP#izt=Rcpc+&3*_;nd9@79)S zqoAfY9?`DC)j2$k!ncIB_K-T-=&2)Hpv?n2gyP@)Z-G7T1U6gURb~iupWwJ!A9Evd z+Hg81p-93l%=O@xIWPRxiPlbO$2ymX@A!?-7gU~-*+iSP0A*-Vn;D698rqG8%J(V? zldPnWGvPRCN);Asfx32&{JLS8HjYSk%4BhP*{^ac+hfmfvzY)^j=J17Og-OASd>p; zZg@tG0#@KKjHaLroS`ubK@~6kP^c_-gsE63;41tecaz;;?plHG8;h5O8KVv1R3(xb z;2d0yUEw!%?iRK5N-c%oxo~qq1^>zqE2VP>8qphz7Z)V`RtUfXB@TQf0xJB5q-vVe zDFfUI&X>`>{WZg4Z4#2O49NjA=uZHlA8R#1jDSNVBts7rvx4{ikmgR4ImurZ$f%7Z zPczbH9Z)R^0tsgnl|kWVNddIVhPR)SGRyKrlUW+_X^YJ=Z5ioGmMIcDaw@E-@^h0U z!qP~FKx!|Sn`+>9{W^lN$bVXnAf!yqMkXT67_|F$!xxNLW&#hMH)u=n-fI|h?GgF8 z9ZCvmqo&A0DN^BzPcD7)&z>JSHvvbF_ z8f!D%OW5fiIPG5HuLp_J6-W@rFauF|n0lb^-oEz{kR6&ye8Ehh%+1_r%s8zvfCY1t z(hPU0go%Np5lSd=yf|F(J4ncsw6)o~Piz)4w<$%H z{UJwDTL5*fJXc2|bxdn$cVbRaKX~}6*nn~gA*4_83?{;|P;LNq6L^K}(Xmhy5J0`k^eaOn|-|h}HKUo^Z+! z_yc~-pXPoLZrphW)WQr-j`+b5KR(L&t#G8+BOdTw{**t?{YLj?O0^rYK;sI2!Bj;F z1=#Ra{&y)AAELrbrjeHIW0$NyxVkeWQsYABzJ5_xeRIjLqCLbq z55-^jwOC6D#1RAL!}38*e+@8R6i<-g*yT_%*uE?}Q!t4AZ)ndg%AujoCsk*S96*px z4b6Dx+JE>c^x%Xb^6jC2+p8bwIllX0_7{i2n9^Zd`X z^qc2@`S0@c1*MP4{*NENp!^-|f5YB4KyMa+i%L?u)Q#xt@px1_v%kMO!ry*b7FH{H zUK3I}L;rSse{`?p_>4O2=W04CcQ-rw)p)!Yrg5b8iQOxSduiYy6~kC$=PLTRls(XC zSg%KxO~U{#v+w&g)ST%19nMBo1M2^)`-^Y-ueWY!0}QYIs)eF=qXjW@%F5OH+wj1A z2di6WRcu!1W@YxhdUsj!S3;w}8ujSOlh08c)qgRE%NKUQzd~zwVIROdf3=;hP1%&y gyVjD+4!9;%Eb{~-O;1DfTTR0FuP0?l+&mip8>^3Qg8%>k literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/_include/API_reference.doctree b/docs/_build/doctrees/_include/API_reference.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a87282c83163a34d7d741cfe470db6ebe9714c6f GIT binary patch literal 12402 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 U3D&83w_%c3NenOrJ5js!Kc5g<1poj5 literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/_include/biapol_utilities.label.intersection_over_union_matrix.doctree b/docs/_build/doctrees/_include/biapol_utilities.label.intersection_over_union_matrix.doctree new file mode 100644 index 0000000000000000000000000000000000000000..ad3305a99fd9669b52befb1181f2f8086feac97f GIT binary patch literal 12066 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 literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/_include/biapol_utilities.label.match_labels_stack.doctree b/docs/_build/doctrees/_include/biapol_utilities.label.match_labels_stack.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a76903e4d72c0fcb4f4cf48963eb3c00e2b0869c GIT binary patch literal 10655 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 Wd5C&D^bBy?q8&8dY-qu_+4vtUx;l3N literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/_include/generated/biapol_utilities.data.blobs.doctree b/docs/_build/doctrees/_include/generated/biapol_utilities.data.blobs.doctree new file mode 100644 index 0000000000000000000000000000000000000000..f2afac4153510954a46e48899c1cb8883127ea30 GIT binary patch literal 6426 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 AdjJ3c literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/_include/generated/biapol_utilities.label.compare_labels.doctree b/docs/_build/doctrees/_include/generated/biapol_utilities.label.compare_labels.doctree new file mode 100644 index 0000000000000000000000000000000000000000..cebda2d14182f55bd0be805eca6db86e5dd66429 GIT binary patch literal 11610 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 literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/_include/generated/biapol_utilities.label.intersection_over_union_matrix.doctree b/docs/_build/doctrees/_include/generated/biapol_utilities.label.intersection_over_union_matrix.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2fd966b2595750bb764403e9cbf6f8bc1c67ca2b GIT binary patch literal 12086 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 gpcIDZvtg#9jHF9{EH6eE@WAE@&FX8-^I literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/_include/generated/biapol_utilities.label.match_labels.doctree b/docs/_build/doctrees/_include/generated/biapol_utilities.label.match_labels.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9c7a619641a95ddd5f956ac702d565a5a288f16c GIT binary patch literal 11809 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 literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/_include/generated/biapol_utilities.label.match_labels_stack.doctree b/docs/_build/doctrees/_include/generated/biapol_utilities.label.match_labels_stack.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b51620befce82ffae7fb59c9cdd8f8cd50a77481 GIT binary patch literal 10665 zcmd5?>u(%a6?g2cz3X?}#zn$OM-`xT@UBZ+R4@c+X)DpRrV0T{aT#W3?)uJpc4jgU zdyRxtK2#*=@{l_H+Hd>=t$3&)BtFs#1eGWsQIP-%Apug6phAM*xp!uEX1(i2Qkq6e zvU6YOp5J-gbI-ZYRGxofbxi&d3!%?#x7Rc*%k?Z4CZcM2X53|NlsuQLek1vMQWv$r z*bBWlFj*qTFv8@vV+G7jo=(I(4UcRmY^L+4LS{y`=jPLSg-`OSr;|FbiArQg4l8tt zwU%x8p0lOXB6ei6u;~~r<}|xTWb!RteuP_k7#ZeHLhE3e(^puJ_Lt2b8$Nq1ojsP$ zem0T(@JcrCm{i52Z-Ct>;b%lm&+*|CVlstgQ=E2emnEBV%MjB>6a{uGjsPdYH(^^L zK{aJMMi`$lF zdu;28!0Q0*a7%&M$T8f)Cbx9kHJ#XETieWKfe|q)9XA}U6fA{RGYG-%otMVr79SH8 z+qGD)AT}jYu7N#%7ew+t{QUs_*75fOu?n;T$P#SS0g~-*L+avwDbo_2`l?p9U9Ia` zvBNaQ#^Cl=6R|qHM=42Z!Guq4Mu`#gHQwxlw#n~=Xu!#7=(u@+kve+jsYefOARfg* zNk_jtWZzOR6;^9nmqpyOE`GcnyHfWx+l^R|8iMZavOter*o2OS0=xH#HSNNMojoJi z4p*g06a869pX`t%p4lFB^^Os|D`Qw5-Jh#Fq_x5yQ|hCTFiN7Uiy83U@S)>GTg=f` zq_WCyRuXNk*L5~R-ymmD#gvc*yDTBR9|e_1QYHN!+enpd%O9zvgN$uSP`3yrlc!Q` z`uiJD<`B5K+nU!Np(D-mq~Z#h>qs@ACUG7Fd1=@TayH9iSXUWZ<1lEe1g*lgN~8}$ z%D4E_grDBWkAEdo*d@7L_#a3HI_21~%Yt%zrvA1oqB4Y>Vv*WRfmo(~rM5CI`=fCw zs#M1R9{3Mor9E}*K=toFsbOWCI{C!%&cAuHJFjL2p6#gLP^R?!4N+nx`yB@6)dR{@ zm~+t}kByTFx|xV+(onBOCrMJa^-1NI6R|vKs_Kx&IVRl%oUW+0W53@}%Gd=jnLWEHa5o)A)+kxTpqUL?{aqH|tA)9;QC=x;InwN$ajpiueVTb{LlV1wwM zX+bMlG@7>>ajn}C>mHo`liU$KRd9S-{oaQfMi3bLYjn=9YK?~WIf_o{bh_surK6hN zHMXIWk*Bqo79#95IaE?=sL``S%?m6RXit6VNr{gPKoI^SOmlEv1)jTI*p4XqSQ!H^ zm)pvKzI8l6#SBH7%3RFknyBHZO%0yEh_iivLmBrbsq(*o{F^|0S&VD-q)hM4B0UOa zeCAp>uJs-W6!=J^#xb#&vC6tWH$pos3=-80-b{1)4JERjAVLE zcdGd3TBk;&UhGWcKf1vQBMEgD3nUcc zWvUZU+KjCHU8eh~8=%{{h)Ksqwevv?J}#;cV(gKqLMczJmf_=Nom>_b?GMj9H-Pbh zK_9yrJI-MgH?<5YN>T2GV|(D1rB0X?{*S|ur$K+intz4u{yo#Y)DUz3_T(=Bvx>E} zI^55i=J|AoHyr8R9+%gf)R)B}{8-xyQl~~ydBmC4HNu^+sa?TOi?xl|i8Oe*!|y?< zJ4{!?GPq4}&#}mn-rcWDuCmD>;9=h7&UhqV2_+`Z8L$Cu)1#Mwk=rd0D7~#Dj)#DYS81(0a6- zZ5mE5201Oxj{ni8eF(>@!zbsKZL92Nfvl-Dnp%+#czK=tNj#_#q*? zit8Wkr=W=0mM7?UdB5L2_I?ZA|66i@qgg9@{}cJC?_%NMxTM}cg{JI^4?O_Be^ZXUuvMZ_cB@YWabn$UKb4R}#dr>i)IC%04{*InXFuHe+ zU=DES)VLJFe@`Mgy1YwhrvUALF!P8gtMitUG^^kXy-3u#)Ft~4EQC7Z-WG8 zlms+&8&%2bQd`cal!SRAen=8uJ+36?vMamHh^P~3NDKn&A9a`S9eZ;(8ln|Q9}%cY zDPpe&@8r?IE{F3tA_P zzNcJI6+f>N*PoQGjB2q5Hk#Ea`$gD>Od2+1Wl8-G8=)*?%k(>?aI#5*CC_1nO(UzW z(nh8M!G!XwyrJr}qve&Csdp#} zyuFo($uH0iwve`4*c7$2%VMV_fs*_(Pn zu7Z69NV_eyJuh+*y%ahxof30YRdwU8-a`(eo1kSLcSGCPO|MI@7D6ofUe&@JCR=pM zy6Rc+9Td|EX*GUR%m&Q&0wjsqE_0Gg<6@c{PX1XDXIRe$R=CE;VK%5DDi&+S+aNcO zO0G-kPOQs}E?R0)fchvgg|zCt?fP+~GuQMeDVm5{9JL!CX~^2kO1V>KLEr^CH(bkM z0dS_RqAVj8yf`YaQjx19;@m*bz!IG|Nvr48y8S(5vscO;1Czxf@el$iq%M3%)_mt2 z!`+UN+y>$nYQW=o2O@3@n2C(GZZS&zf(+IEH^n3}7j2Z7fQW7BC>FQv9@UEGjX3i3 zev=rtp;U8L-1YTb@c^uBkU1ozqG-Vd*#dOkki_3_@mo zsDRTLNSIc$Ao3YJn8`n(qG!mepgHa~6w$G}NF+Zx_QpReV%}%I4p@-eaZ$kn8RX7= zXgqdL<{>m5MSi%kzP`7&hf+A68MsX^*j~5T?m9+>>xno^Gvrngph(kHW$k%>GHPkC$>wIvxIbsdnXMMeu&WJNr=R2Ao-lU+SG&wTs3 zdKGY8EQb5YdG&N|Z*vEKp}(gcDrtz>uxr53abZYo!%y z8C5xHskA9niR6{O95xnfYGPI%GVrA2)01liv7bx1lyboxwRpc3OZoAXX`nQO enY>v#k(u;y9=zT*JqVn(=mbp<8(J`KHU9^7gFco3 literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/_include/notebooks/label/Compare_segmentations.doctree b/docs/_build/doctrees/_include/notebooks/label/Compare_segmentations.doctree new file mode 100644 index 0000000000000000000000000000000000000000..39cb2d4ce100477c40fa5a77c57ad8f2de3ccd18 GIT binary patch literal 1362681 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 z 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%0A4jvq_))g}F41iqdDqt@z5-P41o~MSASvz|hZI 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�JeLbH8>Uh0b0n)lq3dS6k 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%0D}UR^CAc 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 Bh?`g*dKqn>5xG(l+Da1WP$$nEarPP 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

gf-j3_57F_ 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≀@R^wrKABuIW) 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%0Dy$f4|D>O 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

jJv5X;13XP;P4$6udWeH3h?A;w#w4zB) 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ȋ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�TZIMebs&slEe@25z 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 V2qgBjfj4aJ)lvtb3woj1{vRSl)^`8^ literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/api.doctree b/docs/_build/doctrees/api.doctree new file mode 100644 index 0000000000000000000000000000000000000000..25a2e9e5f635ef06882f07814f4051b122ccd994 GIT binary patch literal 44612 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

bIeC-U$%VFwe?;ZRRCfB44f9Qpf;Oi*3aa-SD_x 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 ebuRDV-HRkw6`$Fe>6xDInaz%v{jir1vdKaDIS z>)x8_d00py+3d=N7`7saFZ!%c0iP8S1fK=LH~kX?MFhd$xwpQ$XQq3CFAj7~*Zny6 zeEiNi_ndxf;ltlNJ){5BhKRTq4EJo;4MLZRR4uuolMGlO(JB^TdE%0$0AH( zhox!;D;)0mZp?!8`6y%y+^8 zYsj$in)m9R@T(0X=Sh!==R_mt#wLc(*!{P+etK&EyQvllEL~Q$ z$c7Ly#b)PSrAD+iKqT0+zOuj;)q$DPymbNGOSvGUvGh3Q&uVZwrAzd|wFc zf%&%NCQ(ZJ;ElRsbQz_rzSNSTx#^?BT_2L`*herIvJ8{^D3dLc^v!l>& z7V0nkZ(R1;RUG4K}m~krKCDh-H`_*_HrplzBD)HVWw0}6aHIi3ZnNxzz?COoF^|%4)yUR{L?jo}2d%$KGL?oWhu8{y4!h{O1=k${!{Pc%D)I zbaA8bk1E_(O>r5D`~9TDtEQmEzn!*tqAAvm0|{ow4!^fN=09p}WZKM@cKMgKQ)w6T zzJsfZCO2l4|NQS(`S&DQ&#_8>adrkN@1ouU!{qE&&GHm9{m)6KSIt6;|2}Q;X|t5s zA`kz0I9D|j9#b{@f=>ExR~%Od(~(@W4Y#6D-b5&GW}&=HDfw(Q&`(Sp6rm?1j^(>d zn7e6_FsegE(CqKS5d3QYCHklDmlwI-AYJr7SM1P<>=RkW@I&Xm^@AjoXIy07DS}0I z%P*tP=d%laFAkHa(ecCHe&gO3xRjCDZ?#O4-RpUhC!IYnY|(<&EBCDI%2?!<{vF~< zR}eeu@)IHevDHDaMPCid&o|gjs$HC)kzMqNR)E5|NAaAK;-~!wAMlU8DaFrq960 z#eCyw?0g>tF76xW)9v3TZg+_qF2;F&CGY$4^b`7D!Wt|s6P1bQ<#7}$iY!^?;?dDc zRX<+5A?KCEPG1kQ-Vom<=4aKqlf=|Tva<2ETFpmH??^2PCM60Y^wzeh_SC(yZmer< zR4lb`*?xioun55$ZB<9SJ-E2{> ziDq%!0@dIrsoL&_p$w3`E0YJaYKHx4XS5)sj4Tk+kB}hJbb@4I%%;u4r7bsV&iXEs7>WMOB_yJCL$~B1-+gU#Vr;Y8BpC!0#i1e}GNo$G zw}W1S?i@7k;{6gDE$VX2oG^ARG-yyr;}~iHwN=dtgD%8`Mm*O-ORnn;Q(jZ+b|OQo z98#A&fNIT629Z?&4~o?T9{M|RVEaUHLythafgtmjLy=&K8(PBwL246qZYUUfOyy3E z5=UA`p70DrH!Rl^)W?7z8JCN>L-1X-3Sk6Xz;s-InrxYs_odVheZwJw#ng*}g^8LA zldqtaRJ;PBTjW(hPS67oeQ$sY{3|nm{l|h@k62W;zepT(A|fCj+>?8#MxMrwkB|4F z6UoD1FN}LFmmRgRQnXTag?4CGu){(F1ct(uS1n<@`Ru1Z3(c;_U1#hV8Yz#tmLDU- z5KVE9$*w+z%Ylz0>L?Q6MJ_epmeh4%a$ptiS=@0f5fMTjt4(ndNPB2;ug86SfZusP zB0GBf~P`05GH;tWlX$LfmXhxUDop?Bh2_*H>oF#!BX&9UH! zI_YZ3gb4T~;6>#V052_b5!GGvEgS^6NJL6N!KJ?W0|c>=QPW$;FsOBl7wX_pTOQ+! zG-$rx;sf6Ae}g5|8d`I?h7OYU3WAgwA%D)-8Ff@g%sTwk0ALI{ zpQnMSVLna>o)_-J^F2B*`>Icg%G;rqGtRr D{?qGn literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/nbsphinx/_include/notebooks/label/Compare_segmentations.ipynb b/docs/_build/doctrees/nbsphinx/_include/notebooks/label/Compare_segmentations.ipynb new file mode 100644 index 0000000..b694e2f --- /dev/null +++ b/docs/_build/doctrees/nbsphinx/_include/notebooks/label/Compare_segmentations.ipynb @@ -0,0 +1,5614 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9f0d8ccf", + "metadata": {}, + "source": [ + "# Quantitative segmentation quality estimation\n", + "\n", + "Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "89205b6d", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import biapol_utilities as biau\n", + "from skimage import io, measure, segmentation\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", + "import pandas as pd\n", + "\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "markdown", + "id": "a63045b4", + "metadata": {}, + "source": [ + "## Input data\n", + "First, let's generate some example data!" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "db9c5fe0", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biau.data.blobs()" + ] + }, + { + "cell_type": "markdown", + "id": "2c0c8418", + "metadata": {}, + "source": [ + "Let's segment this and take it as a ground truth image:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2ae66de8", + "metadata": {}, + "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(\"

\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Ground truth')" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "threshold = 128\n", + "imageA = (blobs > threshold).astype(np.uint8)\n", + "ground_truth = measure.label(imageA)\n", + "\n", + "plt.imshow(ground_truth)\n", + "plt.title('Ground truth')" + ] + }, + { + "cell_type": "markdown", + "id": "f7f4c0be", + "metadata": {}, + "source": [ + "Next, we shuffle the labels and expand them a bit:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2b8dc27c", + "metadata": {}, + "outputs": [], + "source": [ + "# First, shuffle randomly\n", + "label_shuffle = np.arange(1, ground_truth.max()+1, 1)\n", + "np.random.shuffle(label_shuffle)\n", + "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", + "segmented = label_shuffle[ground_truth]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "279f3e2c", + "metadata": {}, + "outputs": [], + "source": [ + "# Second, expand the labels a bit\n", + "segmented = segmentation.expand_labels(segmented, 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "eb0b69c2", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Segmentation')" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "\n", + "axes[0].imshow(ground_truth)\n", + "axes[0].set_title('Ground truth')\n", + "\n", + "axes[1].imshow(segmented)\n", + "axes[1].set_title('Segmentation')" + ] + }, + { + "cell_type": "markdown", + "id": "dd726a7c", + "metadata": {}, + "source": [ + "## Re-match labels\n", + "\n", + "Next, use the label-matching from `biapol_utilities` to assign correct labels to both images" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8007d578", + "metadata": {}, + "outputs": [], + "source": [ + "segmented = biau.label.match_labels(ground_truth, segmented)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "23496dad", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Segmentation')" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "\n", + "axes[0].imshow(ground_truth)\n", + "axes[0].set_title('Ground truth')\n", + "\n", + "axes[1].imshow(segmented)\n", + "axes[1].set_title('Segmentation')" + ] + }, + { + "cell_type": "markdown", + "id": "1e1d39a4", + "metadata": {}, + "source": [ + "## Compare labels: Labelwise Jaccard-index\n", + "\n", + "Lastly, we calculate the *label-wise Jaccard index* to measure the intersection over union (IoU) between corresponding pairs of labels." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "7641d30b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
\n", + "

68 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " label jaccard_score dice_score\n", + "0 0 0.496847 0.663858\n", + "1 1 0.518102 0.682566\n", + "2 2 0.470130 0.639576\n", + "3 3 0.623552 0.768133\n", + "4 4 0.602546 0.751986\n", + ".. ... ... ...\n", + "63 63 0.262857 0.416290\n", + "64 64 0.000000 0.000000\n", + "65 65 0.000000 0.000000\n", + "66 66 0.000000 0.000000\n", + "67 67 0.000000 0.000000\n", + "\n", + "[68 rows x 3 columns]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result = biau.label.compare_labels(ground_truth, segmented)\n", + "result" + ] + }, + { + "cell_type": "markdown", + "id": "3f218dd4", + "metadata": {}, + "source": [ + "Let's also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "fab77a34", + "metadata": {}, + "outputs": [], + "source": [ + "LUT_jaccard = result['jaccard_score'].to_numpy()\n", + "LUT_dice = result['dice_score'].to_numpy()\n", + "\n", + "# set segmentation quality of background to zero\n", + "LUT_jaccard[0] = np.nan\n", + "LUT_dice[0] = np.nan\n", + "\n", + "# create score map\n", + "JI_map = LUT_jaccard[segmented]\n", + "DI_map = LUT_dice[segmented]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ca62489c", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(-0.5, 255.5, 253.5, -0.5)" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))\n", + "fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)\n", + "\n", + "\n", + "# Plot ground truth\n", + "axes[0, 0].imshow(ground_truth)\n", + "axes[0, 0].set_title('Ground truth')\n", + "\n", + "# Plot segmentation\n", + "axes[0, 1].imshow(segmented)\n", + "axes[0, 1].set_title('Segmentation')\n", + "\n", + "# Plot overlay\n", + "axes[0, 2].imshow(ground_truth)\n", + "axes[0, 2].imshow(segmented, alpha=0.5)\n", + "axes[0, 2].set_title('Overlay')\n", + "\n", + "# Plot Jaccard index map\n", + "im = axes[1, 0].imshow(JI_map, cmap='inferno_r')\n", + "axes[1, 0].set_title('Jaccard score')\n", + "cbar = fig.colorbar(im, ax=axes[1, 0])\n", + "\n", + "# Plot Dice score map\n", + "im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')\n", + "axes[1, 1].set_title('Dice score')\n", + "cbar2 = fig.colorbar(im2, ax=axes[1, 1])\n", + "\n", + "axes[-1, -1].axis('off')" + ] + }, + { + "cell_type": "markdown", + "id": "1dc2ca58", + "metadata": {}, + "source": [ + "## Compare-labels: Feature-wise\n", + "It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "5f6cc904", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
\n", + "

63 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " label area eccentricity orientation\n", + "0 1 415 0.878888 -0.433915\n", + "1 2 181 0.822705 -1.513862\n", + "2 3 646 0.386542 -0.079653\n", + "3 4 426 0.324798 -0.400592\n", + "4 5 465 0.780472 -0.044317\n", + ".. ... ... ... ...\n", + "58 59 1 0.000000 0.785398\n", + "59 60 87 0.969263 -1.560717\n", + "60 61 73 0.951468 -1.567605\n", + "61 62 49 0.942191 -1.554054\n", + "62 63 46 0.976786 1.538848\n", + "\n", + "[63 rows x 4 columns]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "properties = ['label', 'area', 'eccentricity', 'orientation']\n", + "features_gt = measure.regionprops_table(ground_truth, properties=properties)\n", + "features_seg = measure.regionprops_table(segmented, properties=properties)\n", + "\n", + "features_gt = pd.DataFrame(features_gt)\n", + "features_seg = pd.DataFrame(features_seg)\n", + "features_gt" + ] + }, + { + "cell_type": "markdown", + "id": "ec29004b", + "metadata": {}, + "source": [ + "Visualize as histograms" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "e9652f8d", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0, 0.5, '# Occurrences')" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))\n", + "\n", + "ax_idx = 0\n", + "for idx, prop in enumerate(properties):\n", + " if prop == 'label':\n", + " continue\n", + " \n", + " axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)\n", + " axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)\n", + " axes[ax_idx].set_xlabel(prop)\n", + " ax_idx += 1\n", + " \n", + "axes[0].legend()\n", + "axes[0].set_ylabel('# Occurrences')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "185d4c1d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/_build/doctrees/nbsphinx/_include/notebooks/label/match_labels.ipynb b/docs/_build/doctrees/nbsphinx/_include/notebooks/label/match_labels.ipynb new file mode 100644 index 0000000..181425a --- /dev/null +++ b/docs/_build/doctrees/nbsphinx/_include/notebooks/label/match_labels.ipynb @@ -0,0 +1,3198 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e5db44ea", + "metadata": {}, + "source": [ + "## Matching labels\n", + "This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d1ca8e7a", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import biapol_utilities as biau\n", + "from skimage import io, measure, filters\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from datetime import datetime\n", + "\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "markdown", + "id": "ee62539b", + "metadata": {}, + "source": [ + "### Load data\n", + "First, we load the example blobs image and threshold it to create a label map. " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "7fe70350", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biau.data.blobs()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "909ce3b2", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "threshold = 128\n", + "imageA = (blobs > threshold).astype(np.uint8)\n", + "imageA_labelled = measure.label(imageA)\n", + "\n", + "plt.imshow(imageA_labelled)" + ] + }, + { + "cell_type": "markdown", + "id": "1cbf5ae3", + "metadata": {}, + "source": [ + "Let's create a second version of this image in which we shuffle the labels:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "29986d79", + "metadata": {}, + "outputs": [], + "source": [ + "label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)\n", + "np.random.shuffle(label_shuffle)\n", + "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", + "\n", + "imageB_labelled = label_shuffle[imageA_labelled]" + ] + }, + { + "cell_type": "markdown", + "id": "1393dfb7", + "metadata": {}, + "source": [ + "Both images are not identical!" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "1ff3c80c", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of labels in imageA: 63\n", + "Number of labels in imageB: 63\n" + ] + } + ], + "source": [ + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "axes[0].imshow(imageA_labelled)\n", + "axes[0].set_title('Reference image')\n", + "axes[1].imshow(imageB_labelled)\n", + "axes[1].set_title('Shuffled image')\n", + "\n", + "print(f'Number of labels in imageA: {imageA_labelled.max()}')\n", + "print(f'Number of labels in imageB: {imageB_labelled.max()}')" + ] + }, + { + "cell_type": "markdown", + "id": "7a38be04", + "metadata": {}, + "source": [ + "Match labels and track time" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "79f0cf74", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Took 0 ms\n" + ] + } + ], + "source": [ + "t0 = datetime.now()\n", + "output = biau.label.match_labels(imageA_labelled, imageB_labelled)\n", + "t1 = datetime.now()\n", + "print(f'Took {(t1-t0).seconds*1000} ms')" + ] + }, + { + "cell_type": "markdown", + "id": "a8710824", + "metadata": {}, + "source": [ + "Visualize" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "84ed2639", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Relabelled image')" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "axes[0].imshow(imageA_labelled)\n", + "axes[0].set_title('Reference image')\n", + "axes[1].imshow(output)\n", + "axes[1].set_title('Relabelled image')" + ] + } + ], + "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.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/_build/doctrees/nbsphinx/_include/notebooks/label/visualize_labels.ipynb b/docs/_build/doctrees/nbsphinx/_include/notebooks/label/visualize_labels.ipynb new file mode 100644 index 0000000..9924ff8 --- /dev/null +++ b/docs/_build/doctrees/nbsphinx/_include/notebooks/label/visualize_labels.ipynb @@ -0,0 +1,98 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "803a884d", + "metadata": {}, + "outputs": [], + "source": [ + "import biapol_utilities as biao\n", + "from skimage.measure import label\n", + "from skimage.io import imshow" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "af876b71", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biao.blobs()\n", + "labels = label(blobs > 128)" + ] + }, + { + "cell_type": "markdown", + "id": "d9ded05a", + "metadata": {}, + "source": [ + "# Labels visualized in colours\n", + "`biapol_utilities` provided a standardized color map for visualizing labels in:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "5c3f2337", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAUMAAAEYCAYAAADGepQzAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAz/ElEQVR4nO2debxVVb3Avz/mebzIrKBJgjikpg2Wpi9NKtEysl6GiuErMXuailZqpj2HxHBII8RZ0Rye2HOozCGzTHAWFQFBuQIXFGSe1/vjnAP7nnvO2Wvvvdaezvp+PvfDPXuvtfYPj379rXGLUgqHw+God1olHYDD4XCkASdDh8PhwMnQ4XA4ACdDh8PhAJwMHQ6HA3AydDgcDsCiDEXkKyLytojMFZGJtp7jcDgcJhAb6wxFpDUwB/gysAh4AfiOUmq28Yc5HA6HAWxlhgcCc5VS85VSm4DpwGhLz3I4HI7ItLHU7kDgfc/nRcBB3gIiMh4YX/y4v4mH9uyya6T6K9bMjxzDJ3baLXIb5cxtmme8zRL7yDAr7b6i5lhpt8SeXfoba+uNNYuNtZVnBo8YGKre+7Mblyul+pQ+77d3J7VqzTbt+vPe3fi4UuoroR4eAFsy9EUpNQWYAiAiRvrqR+7/60j1pz99fOQY5jbN45H/fihyO15GXW0nqV7e7kkr7QI0bPqStbbfOORCo+3t+fQvjbaXV86958eh6k3Y69yF3s/rmwZw1wm/0a5/0G+ObQj14IDYkmEjMNjzeVDxmjWOP2R6pPomROhw5JXrXrvcWFvv9lnOCadO1a+g781I2JLhC8DuIjKUggSPB75r6VmRcSI0z/J2T1rJDk1nhQ5/TIoQoOfKjXxjhv6Q1GVGn14dKzJUSm0RkQnA40BrYJpS6g0bz4LwWWEWJGiri+zYwRuHXOi6yjGyfHEfpl5yWoAaE6zF4sXamKFS6hHgEVvtl0ijCEddPdrIuKFNEdocL3Q4ajLyA+TPP9Mv39deKF4Sm0BJkixkhFnH5gSKDZLMDo/c7UIen1c/mWnDxyMZ98jftMtfSm+L0ewg0zKMOmlik6jZoese55sjd7uw4ud6kGLHppUMv+H+pMNoQWZlmGYRRiUOETZs+pLrKidAuQSr3c+zFNfyIbO23Gm0TRHpAUwFRgIKOBl4G7gHGAIsAMYopVZUayOzMgxLnF3koNlhnNmgE2Fz4ugi+4mwUtmkpWh6JhlgVYcePLbn0foVXnxap9Rk4DGl1HEi0g7oBJwPPKGUuqx4PsJE4NxqDWRShlnKCkuCqyVF1yXOP0FEWF4vaSGapudOqzluwlPa5X91e+37ItId+CJwIkBxC/AmERkNHFosdivwFHmTYRapN+HZWmeYRcKK0Fs/T0Lc1rENG4f3MtnkUGAZcLOI7APMAs4A+iqlSnstl+AzL+1k6MgUez79S7cdLyZsdJEB1qo+PLftRwFq3NogIjM9F6YUt/OWaAPsB5yulHpeRCZT6BJvRyml/Lb9Zk6GUbrIbkmNw5E86996n9c/999BqixXSh1Q4/4iYJFS6vni5/soyHCpiPRXSi0Wkf5AU62HZE6Gjui4yZP4iNpFTpIJe51rJTvs0aorX++iP4RyC8/VvK+UWiIi74vIJ5VSbwOHA7OLP2Mp7OgbC9SczXQydGQOk11l10WOn9btO9F1yL76Ff6tVep04M7iTPJ84CQK57XeKyLjgIXAmFoNOBnWIXGsMYw6eTLk4h27DhZc8GGL+yaEmBURBpk8+fX4zi2unT9lrclwIiMDt9HxsjX6Fe71L6KUehmo1JU+XPcxdSNDE+OFHV5o+S/Vhk+3/JfPER6vBL3XKgkxClkRoS6VJOi9F1aINrrK7RcuZMip4/0LxkzdyDAslQRY6X7WpJjGHSiVROi9Z0qI9SRCb5m0ZIiNW/bk/CUPBKhh5zT2clIhwy677saa+faOtg+bFfqJ0FGZMF3kWiKsRpiuctwifHzeLyNNovh1kXVEmDaGt9rCjK4rtctHe5mHPqmQYRoJKsIOL6x12WECBBFiEBE+fHTLJVxfn+GWZplgo5rHnA3HJB1GC1Ijw0On389Tx38z6TAcEUli14lXcuViDJoJVpJgrXs6ggybHeZp14mX9e168uYuAf5bf/Fae8F4SI0MbRGmixy2e+yyw+SJ0g2uJUK/OqazRh0RZrGLDLB08zquWvJS0mG0IPcydPhjSog2s0LTs8nlhBFhEIJkh3kWIUD3QcM48sq/aJe/6eCOFqPZQeZkOP3p47W35Lntd/pEFWJUES644MNQkyhp4eGjp/tmh35CtN0tDjujbHp5zcb1S3n39WuMtWeKVMlQd9wwiBDzwjtnzKh6b/fJAc6Gq0FYIdoeJ8xKVqgrxCSJa4nNhL2qnpTFluXr+fAPr1mPISipkqFJ8pAV1hKgLcrFVkuOpiVoW3qVMN091hFiVJLoIutmh7UkWKLn4I18c/I72s9+5WDtopHIrAyrZYcmJLjh051DTaKYmjwJKsF3zphhLDssx51J6ChREl0lKepIsEQXtvLFrauMxWWKVMkw6NIarxBdJugIiu1Jk7wSRHyVaDevNQPHdDcUjTlSJcMwpEWCUbPCqCK0mR06gmG7q3z+lLWZnk1e13UbLx+yXr+CxkENJkiNDNO24DpsVzkMpjJCJ0RHFljWfT03jnpVv0K9yTDLZG2htcN1kZNkaNch3H6Y/qz6AMZajGYHqZChzUMaohBHdujGCR1xkoaTa179aC2D7n7ev2DMpEKGacZPiFGyQhsidF1lR9rp2LMbnzj2SO3yr537O4vR7MDJUAOv8NJ+fqETYfLEcbpNmEmUNGSFAF3nKA7/8mbt8nEtz3YyDEhSawkdjnKCCDEtIgT4uF8bHjmvQb/Cf9mLxYuToaMu+fqM461MosR95qGOENMkQoB+W5cyccVV2uVPthiLFydDhyPjlGTnlWLaBOjlw6aN3HL9u0mH0YJMyPCAEbL995mzVYKRmMF1kdOB6eww6ZOwwwrwHwtbVb33+V22hQ2nOju3RV3VT7/8Ma+bj6ECqZahV4Lea3kQoiMd2OouZ4FaEvSWMS3EnVZt5PTH9JfT/d3o06sjSiUvFhFpEUQlEZbIsgzjyArdjHJwogox6awwKDoiLGFAhrOUUtvfadxl//3UyOee0a78fIeuzerbIpWZYS0Rlu5nWYgOfw6+9zstrj075m5rz4uSIeZZhDbYShOrWl2XaAyVSKUM84obK/SnkgS992wKMQymRHjl/OZzpmfvOs1Iu+WEEaHprnLXl4TDO7fTLv+msSfXpq5k2P7sk5p93njlzQlF4iinlgTjIu7xw3IBlt+zJcSk2Vka+G2Hk/wLFrlu81kWo9lB6mTo10UOSrkAK91zUkyOoBK0nR0GEWKUrLCWCPPOnB6bOWLUMv0Kd9iLxUvqZGiSWiKsVM6mFF0X2RxxCLFEuRhNdIuTEmHSY4UlNuy0kXd+NFe/QhZkKCILgNXAVmCLUuoAEekF3AMMARYAY5RSK3TbnDlb+WaHfpMnuhKsVS+L2WKWZpGjdovjGj80PTmSZEb4+V22pUKIO7+9kUmH678DZbTFWLyYyAy/pJRa7vk8EXhCKXWZiEwsfo52TngCtD/7JKNC3H3y0VazwyyJ0BRpnFBx+LOsR3euP2KUfoV7fuJbxERiZqObPBo4tPj7rcBTBJRhKfOrlCHaygqrtZWFDLEeRVgiz0K0MYmShuyw54olHHef/t7kP+s3HSkxiypDBfy5uGj690qpKUBfpdTi4v0lQN9KFUVkPDC+VuNuLaE/9SzCrJHVSRPTO1Aa6MYp2/Tfujie34d9VKDELKoMD1ZKNYrITsBfROQt702llKq0u6R4bwowBSrvQAmDyazQ26ap7NB0V9mJ0BGGktySyhBXDOrJA2ccp1/hbK1SoROzEpFkqJRqLP7ZJCIPAgcCS0Wkv1JqsYj0B5qiPCNvmBKiE+EO8txVziPvdZvHhCO/rV/hbBpEZKbnypSi7LyETsxKhJahiHQGWimlVhd/PwK4GJgBjAUuK/75UNhnBMFGVmiLksjCSNFJsH7I66LrnssGcMzvf6Fd/kbuX+63N9lEYhYlM+wLPCgipXbuUko9JiIvAPeKyDhgITAmwjNyTVApOhFmlzSOF/pNplg5vgvo/WEj37/t59rlb/S5byoxCy1DpdR8YJ8K1z8EDg/bbj3iJ0UnQYctKo0f2pLgdnYaSOuTf61f/td/8ithJDHLxQ6ULHWRa+Gkl0/CZIVxd5GtC9DDx+0388gnlhhrz1RilgsZOuqbNE+eZEGEcbOsm/C7LyW/E6YcJ0MfsrDo2pFO0jhOmAaGrOjMpPs+o10+rv6Sk6GDWX2/3uzz/ksfTiiS/BC3CJ8+YwSHTJ4d6zPD0kotoevmy5IOowVOhnVMuQQrXXdijJcgXeSnzxhR8XPapdjERq5rvSDpMFrgZFiDPHeRq4mwWjnTUnx2zN1GDnRN43ih7aywXIKV7qdZiOtWduCFGcOTDqMFToZ1iK4IbWNKiHlBJyv0E6G3nG0h3tH5cxWvf2/tczXrbVu7mk3PP2UhomjkQoYbr7w5N8trbBNWhLP6fj11XeY0ZoU20RWhbapJ0Hu/lhBb9V1Np7FP6j/wCv2iUciFDG2Q5y5ymigJLWiGmFYRpmkG2WR26CfASuWrCbFhTXdO/Mch2m1dQDynxOdGhi479Cct3eNKBJGiDRH+9Jq/tbj2mx8fZvw51fDrIofNCk0IMagIy+uVS7Frv80cds7iSlUqckFMR13nRoYmyWNWmGYRevGKLo53J1eSoPdeECGmKSs0RVgR1mLLxn40zTknQI1vGY+hErmSYUliUTLEPIrQBEmMF9ruCtcSobdMnBlimrAhQgBp3YZ2PXpaaTsKuZJhFPIsQRNZYRonUOKiHoVoS4QATes78rtXW2wlTpxcyjBIhphnCUJ2usdxo5MVlpf3E+LZu05ze5E16NLwOp85ZQ/t8o9cazEYD7mUYYm8i86RPsIK0RZhJk9sZoUA6+a34+XvDAhQ40NrsXjJtQwdjiQIIsR6ywoBemwdyNErLtcu/wABXisaASfDmBnx0RDfMrN7LbAehyMYQccMdYRYjyIE6LFbK465uZ1+hc/ai8WLk2EM6AiwvLwTYvapJcR6FSHAu6znBNK3d9rJ0DJBRZhHjrq5MAb16Em196z61Y/SRlIkKb20HtbQ491eHH3id7XLP8yPLUazAydDi0QRYdqywzDLarwS837WEVp5Xe/1uIWY9LKatOxJNsVm5rF46zFJh9GCupfhyWMerHh92r3HRmrXREaYNiHqUk1kle6Xi82vbtwkLUIoZHhBhRglK/ze2ueMzChX25u8ZecGll0zTr+ho56NHIsOdSnDagIsLxNViCbImhCDyiyM/JLIDrNEWrvHJT7qtoS7j4zpKJoAiFI1XzIfTxA+b7o3iY4IvYQRoo1xwrBCNLHoWreLHHdWZ1KIpUXYacgEa1EtQ7QhwLDZYYWMcJb3JfA99txNfeEe/VeF/mmv42f5vUTeBHWVGQYVYalOGjLEpKiXLXhpl2CJOLM+U93lcjYt6sR75+5vvN2opEqGL95UeyHmfuPOjSmS5gQRYr3OHqdtrM9hhqBC9DvlGmDDgEbeuuAX+kE8ol80CqmQ4fBdBnLnBf7T5y/edHliQswq+y99OHRXOc1ZoRszjI9qgiuXpI4IAbos6s6BPz1S+/lPMF27bBRSIcMgOCEGJ4wQ0yxCRzrQlV85Qzos5Obh/6Vdfud4JpOzJ0NItxBn91pgvKtsYja5JDcdKaZdhC4rzDbz2vbkuP5B9hvfYS0WL5mUIQQXYpjJkzziFV0W34/sROjPpKn+h+KeeUpybyXs1Lcfe52pf9L1vy92MvQlzRliFki7AJ34gqMjwlK5pIQ4aNkSJv1Of53hTRZj8ZJpGaYVG13leiJOCV7Tdcd/lD9eXTtb8ZbVrRMnuiL0lk9CiCu29uWej88IUMNlhlq47DAdPHrSc5GX18QlwUpSK79eLjmdOl7SJMlaJCHEzb1WsOy79+lX0Dj6UERaAzOBRqXU10RkKDAd6A3MAk5QSm2q1UbmZZhWXHYYjKRFGLZcrfpZEWLcNHywmrEX/V27/M/0ip0BvAl0K36+HLhaKTVdRG4ExgE31GqglXZEGSfKLpIkd6BkaV9yWKGlTYRZfF7QLrKpumEQ6U3bNmO1f/zbk0HAV4Gpxc8CHAaU0s9bgWP82qmrzHDavcfGsje5RElkLkOsTl5F6H2u7QwxbplFZVEf4ZwftdWv8EffEr8FzgG6Fj/3BlYqpbaUHgkM9GukrmSYFGG7zFnKCksEGTt0s8X1SbumHgy5dnSQKg0iMtPzeYpSagqAiHwNaFJKzRKRQ6PEVXcyDJIdmuweBxViFkVYoiS5WlKsJxHazA6zlhUCyNBXaHdHb/0KnVhe49SazwNHi8gooAOFMcPJQA8RaVPMDgcBjX6PyYUMg84ol0uuXI5ujNAM9SQ8R0se+KDwP4BvDGg+RNHxw70ZedufA7TUr+odpdR5wHkAxczwp0qp/xSRPwLHUZhRHgs85PeUXMgwKnHJL0+iczgqURJgLRpbb2Ji9/m2QzkXmC4ilwAvobF221eGIjINKPXLRxav9QLuAYYAC4AxSqkVxVmcycAoYB1wolLqxVB/FYfDkSl0RAjQccFC9jn5R9rtvqlZTin1FPBU8ff5wIHaD0EvM7wFuA64zXNtIvCEUuoyEZlY/HwucBSwe/HnIArreg4KElBY3OJrhyMcJhZd64oQoEefnoz+tn5vbPq1L4eIKDi+MlRKPSMiQ8oujwYOLf5+KwUbn1u8fpsqvEvgXyLSQ0T6K6UWG4vY4XBs58xTvpP4JEoQEQJ0aNrEsBvesxRNeMKOGfb1CG4J0Lf4+0DgfU+50vqeFjIUkfHAeIB+vXuEDMPh8CepNYZZIGpWGFSEAFtar2F5lwCTaysDPyIUkSdQlFIqzAudiuuEpgCMGDIo+bdSORwZJWx2mIQIAdYNa8+s23bXr/Bp3VHDaISV4dJS91dE+gNNxeuNwGBPOa31PY5keeupyls29zj0hzFHYocfrz7HZYdlJHmeYd9NAznzvUu0y5/PDIvR7CCsDGdQWLtzGc3X8MwAJojIdAoTJx/HNV7oJk+CU02C5ffzIsU8EyQ7TFKEALNbz+FTvY5INIZK6CytuZvCZEmDiCwCLqQgwXtFZBywEBhTLP4IhWU1cyksrTnJQsyOiPhJsFb5rIqxHrLDkuSqSdGkBMN2kQH2WDeUp2Zep12+B/ovj4qCzmxytX+Ch1coq4DTogblsEdQEVaq74QY/LlxknTm54es2EibB6wvug5MLnaguC5yvGRdiF7K5VgPGWTSvLytDQ1rG5IOowWZl6EToT5Rs8LytrIqRC+VsjaTQszrAa/fGHBF6K5yh0+24xNPDtIu/1rPUI8JTOZlaItNL07d/nu7/U5JMBJHEpQk5rJE82xZt5aVs2YlHUYLnAyLeOVX615WxWgyK/S2mYfssBZRssS8ZoVRUUs3sWlyfnagJI7J7nEtEVYrm1UpponGlSdWvTewxy2xxeFHmCzRibA6ezX04NlTvu5fsEjnh+PJzlMhwzcXNrLfuHN58abar8FKSoDV6qdBiKdOOn37778/89oEI9GjlgDLy6VJiKCfJdaLCMOOG65t18Q/B0y2EFE0UiHDEiXZlUvRTZLkA10RpplaWWK9SNBLGCGu2LCJ/30rfRvTUiXDErblFzUrTCunTjo9tdlh0iLc55UdC3df2efxyO3Vo/iq4T3JWkeMa5a34elbetkMKRRSWCedcBAhDnoIi0kRBu0mD+v0eotrc9aNNBWOLzYmUXQmUKKIMEpX2SvASpiQYpqY02FhoPLDNuxiKZIWzPK+w2Tvnr3UjENb7NmoytD/vW9WjXegGCOVmWEeqSRC7/U4pWiKOGaSw44d+onQWybrUgwqQW+9GIW4nSWbe3Ll4m8HqHGffxED1FVmaKN7rJMdVhOhl7hkaCo7DCLCqF3koDLUEWE5WRZiWBmWiEGIzTK7fYa1VY9f10O7cv8jl7vM0CRJjRPqiNBbzrYU9zj0h5GFmGYRhmWfV47MpBCjitDbRlxZ4tI1wtV/7xDLs4JQNzJ07CCKENO+yDpMVphVTIiwUnu2pdip1Uj27vxMgBpdrcXixckwZQzr9HosXeaS1HSlmHYJQn2J0Ca2xxKlw1za7HGMtfbD4mRoEd0ucpKkXXJpXHydBkxnhZXatyXExq1wwcpWVtqOgpOhw+GIlT4fDOUHF9+uXf5s+lmMZgd1IcO8LrJ2mCUrkyi2s0Lvc8Jkh289cRZ7HH5V1fvdB85n1K+P127v7JjOqq0LGTqyi+siZ4u3njir2Z9ACzG2+mgInadPCdDqMBOh+eJk6HA4qmJj7PDjXTbw6I1z9Ss85F/EBE6GEUjDqTUOs2Slq5xGvNlgLZZLI39ofZ7laIJTNztQ0rz7xEsWt+XVIu59yaaW16RZiHGNGZYIkhlW6R4320GyV4ed1IxBY9Bl13nXux0oeWDOupGZWGKTF17Z53EjQjR9yk29UGvipMScnftz2LUBMsOvXB8hIn3qRobt9jsl9bPKecsKo5CmiZO8HOiQFtqvWsnQP+sPBC7wuS8iHYBngPYUnHafUupCERkKTAd6A7OAE5RSm6q1k1oZXnFkuxbXznm86t8j1fhlh3mVYNguclQRmsoOy3FSNEN/1Z0Ltukf+/+k/6vYNwKHKaXWiEhb4FkReRQ4E7haKTVdRG4ExgFVt1ylUoaVROi9HlaKJrPDoJMnXuHFteUuSZISYQlbQqw3bOxCkVUf0eYv0421pwoTH2uKH9sWfxRwGPDd4vVbgYvIkgyribC8TBQhQrILsfMswqQOcq2EzQzRZYfhaTu0I/1u20O/wv7+RUSkNYWu8CeA64F5wEql1JZikUXAwFptpEqGOiIsL5tEluiW1FQm6WywEnnMEIdt2CX2GWWTvLNkLaOufDFIlQYRmen5PEUp1WzVtlJqK7CviPQAHgQC2LZAamQYRISmCJMlOhFWJul3nDjMY+ughsG9lvLbb12pXf6r01muu7RGKbVSRJ4EPgv0EJE2xexwEFDzLVSpkOHAbpLo83WyRCfB6qSpa1wJlx2Ga98WC5fAqZPMnVojIn2AzUURdgS+DFwOPAkcR2FGeSw+e1lSIcM0UEuIToTVqdeMMM/jhrYPd+09uAPfm6S/3/iyg2b5FekP3FocN2wF3KuU+pOIzAami8glwEvATbUacTL0UC7EPEjwl//6uOq9Cz/TPVLbWRKhyw7124zKSwOan2L9qQ++2Oxz09w9uO6r/wjQYu1XBCilXgU+VeH6fOBA3ac4GZaRhAA7bti5xbX1Hd6L1GYtCXrLRBViFNK0sDqrmBJiVAmWC7AW/Tpt5Yf7r9Uu/4uYEnAnw4SoJMBK98NIUUeE3rJhhJilrDDvRBVinCIEYHUj6plzIz3TBk6GCeAnwvKyQYQYRITeOklmiHGRx65yCV2heaVpo0usRZ+PaH38Xfrlrwn+iDA4GcZMEBEGJYwIHfWFycmRUCIEti0fzrppfwxQY0So5wTFyTADBM0OwxB3dpj18cK8ziTrElaEAAO3refida9ql7809JOC4WQYI2GzQh0RmsgKgwhxYI9bMjlumOeuclxEESHAu8OXcMLtk/QrWD/JsECmZZjVU2yCEkdmGCcuK8wuUUUI8PHK9jz2v0G66/+O/EwdUiHDxlXBD7quFxE6zBMlO3QijM7OTf245Hr92eT/JMj4Ynh8ZSgi04CvAU1KqZHFaxcBPwCWFYudr5R6pHjvPArnhm0FfqyUMv5vTxZFmIWJk6BjhmG6ymnJCoMKsZ4lCOZECLCg5wrGHXOffoWYDpjSyQxvAa4Dbiu7frVS6jfeCyIyAjge2BMYAPxVRIYVT5SoyTmPb9I6rCGLIswzukJMiwS9lARXS4r1LkEwK0KAnquEr/5Fv1Oq/7r5aPhGpJR6RkSGaLY3GpiulNoIvCsicylsh/mnTmU/IdarCNM+XugnxDSK0Eu5FE0KsOf1zQ9KWXFazSP16oKGLpsZ94Vl/gWL3B7TaWVRxgwniMj3gZnAWUqpFRQOT/yXp4zvgYrl5FV46zu8Z7WrnDRpF54OpiRYLsDye1kSoumsEGD5gAFMvfBC/Qp3/N54DJUIK8MbgF9ROFr7V8BVwMlBGhCR8cD4kM93OFJHLQlmERsiBFjZbjUPDHraSttRCCVDpdTS0u8i8gfgT8WPjcBgT9GqByoWT6qdUmwj+Zc3x0CY7DDtXeS4mLFH4dWSR7/1PwlHEp0sZIe2RAgw7IO23PzLnbTLf9ZaJM0JJUMR6a+UWlz8eCxQevXbDOAuEZlEYQJld+JaJJQR8t5djkpJen730ybFPGWFNkUI8P7ALZx1yYf6FS6zF4sXnaU1dwOHUngPwSLgQuBQEdmXQjd5AXAqgFLqDRG5F5gNbAFO05lJrjd0hVhPWaGfBCuVT5sQ84BtEQJ0nLWGEe31zzN8zmIsXnRmk79T4XLVE2OVUpcS33bCzOInxLhFmOSpNUFF6Mg23dqu4Ig+92uXn/qBxWA8pGIHSr1SEl6UswuzThQRuuwwm7zfqRVn7t9Zv4KToR43vFp52v2He58acyThqUcJQn4ywryMF8bRRQbo3W84/znxb9rlL3+4l8VodpBZGVaTYPn9LEkxKZLoIudFhGEwMZO881nVBfzeVemeqe72zgaOOOot7fKXW4zFS+Zk6CdBR/qpZxGaoJYIS/fDCPFTH3wxluxwY4+lLBx1tX6FO+zF4iVzMgzKDa/+3lh2+LfWK5p9PmxrTyPtRiFrp1s7EYbHT4LlZZPOEMvfildi48eKtx9N3yKTTMkwiaywXIDl99IgxKyQVxGuOG2g9rhh2C5yEBF66yQhxGoSLNG+M3zy0wH2WTwWMSBNMiPDKCIMmx3WEqG3TFJCzFpWmGeCCDHP+IkQQA0YyoaL7tRv9LFOESLSJzMyjBsdEXrLxi1EkyKsl7fj2aaWENO+/a5ElHFDHRECdJm/kYPHzAv1DJtkQoYmusdBssMgIvTWcV3m6uS1i1xOuRBtzxynBV0RAqzouJgH9vqVfuMxrTzLhAzjJIwIHf4c/db/1JUQs0zQ7DCICAH69d3GWWeu0y5/0f8Faj40qZdhlpbSuOwwXtzuE3t4BVdJjEEF6GVjh57MGzEmQI0/+RcxQOpl6GiJmzhJhrEvT655/9Z9z4gpkniJIr5KvLewPT85ZYjRNk3gZOjBRBc5i9lhFidP4swK/SRYXi4tUkx6nWE1hq5Zw63/0j+1JshLRaOQahlmqYscFy4rTKcIy+ukRYhppHH4Mn4+Y4p+hV3txeIl1TJ0OMpJuwi9dU0J8b2rBmZiRlmXzY1dWHzu5wLUeLfmXREZTOHtnX0pnLE6RSk1WUR6AfcAQyicuzqm+K6mijgZZggbWWGcXeSoM8pZEaG3DZchtqTPx50Y/3/7apf/K74LtLdQeCndiyLSFZglIn8BTgSeUEpdJiITgYlA1bfX140MddYYHra1p1takzKSmDE2IUJvW06IzemwRxuG39ugX2Fk7dvFV5AsLv6+WkTepPBWztEUTukHuBV4CidDR9Zwy2aikdbJE4CVjYoHzw10UEODiMz0fJ5SfKFcC4rveP8U8DzQ1/OupiUUutFVqQsZ5uFMw6x3kUukXXIms0Jvm1Gzw0pyKx9HDCPABxv/6Fvm2IHfCtxuLTrKFvbp8FGQKsuVUgf4FRKRLsD9wE+UUqtEZPs9pZTyewtn7mWYBxE6so+N7nKU7E9Hgt6yJoW4pk03/tHwH8baAxCRthREeKdS6oHi5aWlN3mKSH+gqVYbqZbhD/c+NdLymiREaGuN4YWf6e6W1VjGRlaYRoKI0FvHlBB79d3K8WfoZ4ZX+ChACingTcCbSqlJnlszgLEUXjY6FnioVjupliGEF2JYEbpJFEeeCSNC08yfs4FvHfGOySY/D5wAvCYiLxevnU9BgveKyDhgIVBzD2DqZQjBhZhU19j2zhOT2WEWd504ohFVhKayw97923HSRP/3hpf4+Y9q31dKPQtIlduH6z4nEzKEyoIrF6QpCeY9O3QirD/SkBGWaNV9NZ2+9qR+BR8ZmiIzMqxEmiZH4tqPHDU7dCJ0JI3a2sDGVacEqPEba7F4ybQMbRIkO8zKwQxOhMmS1AJsk1mhia7yyi3v8XDTBEMRmcPJsAY6QkxChGGyQydCf27d94y6mVFOkt4ruvC9Bz6rXf45/moxmh04GfqQlazPkQ3c9jxoGtCK6y/orF/hOnuxeHEyzCi62WFaM8LbVz/f4toJXQ9KIBJH3PRd1pefTDlTu/wPmGgxmh04GWYYr+jS/Ia7SuLzK5eEGF0XOR6WNc3lxmtHJx1GC5wMc0IaRagrQb+6ecoY672LDNBOtWXnDTtpl59lMRYvToYO40SRYLX28iTELGNkS97w1vBQL/3yu0V/pA5Oho5MkAchuqywwOA1nfjts3trl3/QYixeRKmap9rEE4TP0TqO7GA6KyzHthBtjhsmKUMTaw0jZIWzvEdwdWnbT+3be6x25X8svWKWzhFeUXGZocMRAy4r3MFO3T/kh0fepl3+H/pFI+Fk6DCG7awwDmwsvE6DCI8d+K1I2aHJ8ww/3NiNOxd+OUCN2409uxZOhg4j5EGEJdxOlOaEFeGVh68C4OwnujW7vkvX9tz4xaHa7ezydKjHB8bJ0OGogCkhpiErLFGSmm6GGCUbLImwEhuXLmbe1b8K3bYtnAwdjip4RVZJjJVEVypnUoIzTxvMAde/b6y9alI0/a6TaizvthdTD39Ev8L9g+0F48HJ0OHQQFdupiVY/rsNKZqmVlYI0KPVOkZ3fEG7vbuiBqSJrwyDvq2++D6CycAoYB1wolLqRTvhOxz5xCvCStdNSjFuFvRawEnfHqdf4Q57sXjRyQyDvq3+KGD34s9BwA3FPx0OhwbVRJgF/LJCgM4bO/LpeXtqt/k3no0Skja+MgzxtvrRwG2qsJr7XyLSo/S6PvPhV+aSa5v/g/756W/E9ejM0umbz7Hu/s8lHUbdoytC0+OIcbK6zWae7LM06TBaEGjMUPNt9QMB77e0qHitmQxFZDwwPnjI1SmXYPl1J8XmdPrmc1U/BxXjCV0PytXyGoc9ujeN4NDf6a+XeYhu/oUMoC3DqG+rL0cpNQWYUmw7lu14l1y7pxMiLSVYrYzLFB022HXDQm5/44fa5eNRoaYMA76tvhHw5vqDitesUi0rrFSuHoWoI8BqdXSl6LLD+MhqFxlgcceduHzf0/UrPHWnvWA86MwmB31b/QxggohMpzBx8nGc44U6JCnEL0w7Z/vvfz/5ikRiCEpQKTrCkeWJkyB069uZw8/QP3fh0qfsxeJFJzMM+rb6Rygsq5lLYWnNSSYDroRuVpgEXvlVu2dbimGywmrt+AnRZnaY9SO8HAVaL5xN91M/nXQYLdCZTQ70tvriLPJpEeOyju3ssJYEK5W1JURTIvS25zJERzXOfqKb7/KaTX0aeO8HJ+o3evFL0YLSJBfnGUbJDE0LMYgEK2FaiqZlWEJHiCYzxHrJCnW7ymkfM/QK8ewnujU7j1AaOqo2Xx+i3daWW95y5xnWIya7zrZEWGo7ri5zvYhQl7SLEFqeVOPlkx+2Z8od+mf5H8JbJkLyJRcy/Pnpb4TODk12l6NmhXmkJLIwUqxHCR5w/fs1s8MsiNCPzp9sxUE3ddGvcLC9WLzkQoZpwLQIbY4jmiLI+GElsZULsh7lV4lKQsyDBEusWzKIly+/MkCNe6zF4iUXY4YQfUY5anZoKyuMIkSb3WQvbkLFDnk4lKFIszG/Nnt1Ud0f2ke78ke7PVdzzFBEpgFfA5qUUiOL1yoeJFPrObnJDKN0lR2ONJIDCVZkyEdtmHRXH+3yGq+bvwW4jsLpWiUmUvkgmarkRoZRqMcdKQ5HUizpNJTL9r8lQI2eNe8qpZ4pnpvgpdpBMlVJhwyH74zceT4Aar//SjiYdBFl7HDd/Z+Lpavs1h7mh9YHv8rWAO80DkPPdkv5xmD9Vyr8ExpEZKbn0pTi2Qa1qHaQTFXSIUMP8uKNQHApui5yZeISoiObtD74Vd9rpuXYtLgz1196YJAqy6OsM9Q9SCZ1MiwhL94YS5bousiOeqWSCGuVMyXFPXaax2Ona4wEFhkwPdRjqh0kU5XUyhDiEWI9HATrskN9Tnn9lKr3po6cGmMk9tCVYKV6JoT49tttOPRg316rh0VhHlPtIJmqpFqGSRB2EfbfT76irhddZ33csJYEq5XJohzDitAkAwcoLv3RBu3y3/p57fsicjeFyZIGEVkEXEj1g2SqknoZ6maHbmlNbWxnh3kXoU69tMvRhAhNZIcL1w3jBy8F6fvWfp5S6jtVbrU4SKYWqZchxDd+mHdcd7klYUUYpa0kpGkyI4wqxD0GdOC+i4Zplx9+f+hHBSITMtTFZYf+OCHuwKQIgz43TiGmoWvsZdGSt5h4Wfp6ErmSoUMP00LMYhc5KRF6nx+HEG2JMEp2uLXbYD7+8jX6Fe6M56SGzMgwC2OHNiZR0n5Ygy1mntB6++8H3L41wUjsURJy2scaqxFWiGs+6szT0wOtM4yFzMgwCFGEGHVpTVZmlU1lhyazQq8AK113UgxG2rrHJdq3eYldGvSP8JpjMRYvuZRhFEycb1gvQoxDhOVl8ipEiH8sMSm2rP8ky9+4OUCNz1qLxYuTYZ0TVohxi9AkSY8X5okwXeUOuy5i97vO1i7//PCgUYUjUzKMY4mNqR0oJrLDuMYLgwoxSRHmPTusB/rP6c2Fh39fu/wonrUYzQ4yJcMghBk3zONWPF28gqslxjTMHDshZpvlI2HqMwEqdLUWSjMyJUObWaENEUbJDpOcRU6D8Bz5ZdCiRfzmPP3/Lh6wGIuXTMkwKLrZoc2MMIwQ63U5jaM+mL++Pd96VX8HCvzbWixeci1DaC66pE6oCSJEJ0I9onSVp46cmspJlHqYSQaQbRtouy59Q1KZkaGJLrIJ+V0/4e8trp123Rd865VLzuT7kR3BSasQ64HdNw3hsff+R7t8D75tMZodZEKGaTmkoZIIS9d1hOjFSdBhm63P7m194XWYHShqaGc2XxNgXPqowI8IRSZkmAaqidB7P6gQHclSD9lhHEIMyoeyitvbPZZ0GC1IvQzTkBX6idBbzgkxHvK2tCaL44VhD2potXI5Hf40zXA00Um1DNMgQke+qZfsENKzV/m9gRs5/dL5+hWutheLl1TKMMsSdNmhIyhxZYUmu8xRDndt/0pbduk3QLv8HJaGflYQRCnfN+jZD0LjNX5JodtF9uJkGIygW/JsdJGTyA7T0jX2E6SBl0DN8r7qc9CAvmrCD47XrnzexdfMivKqUF1SmRk66osDbt+qLURbY4UlMcUlxbSIEMy/F9mPjpt7s9cS/b3JEOAg2Ag4GTocHmxLMU0STIrGNWv4xXP/TDqMFjgZGsZmF7ndvkez6eUZ1tpPkiDZYRxUk1YYSToBNqdrxzZ8YUQv7fIvvW4xGA9OhhkiryIsUeoCV5NiGpbTVBJbJUE6AVZn7YbO/Pudg5IOowVOhgZxEydmqCTFNIiwGk58wWiz6wL63n2ifoU9rIXSDCdDR2pJswAd4Wm7dQg7rbolQI1P2AqlGa1ieUqG0c32XFbocGgiW1Btlmv/xIVvZigig4HbgL6AAqYopSaLyEXAD4BlxaLnK6UeKdY5DxgHbAV+rJR63ELsDocjg6zZMJ9/zNZfZxgXvouuRaQ/0F8p9aKIdAVmAccAY4A1SqnflJUfAdwNHAgMAP4KDFNKVe3zpHnRdYlai69dVuhw1KTZoukenbuqQ0bsr115xsyn07HoWim1GFhc/H21iLwJDKxRZTQwXSm1EXhXROZSEGP6FhYF4LTrvhD6LMN6ZtKhJ2mVO/OpIK+OjJ++4zv6llk6ZX0MkdjlkBWFU6Wf7mnvJe89+m/l6J+v0C4/4xhroTQj0HY8ERkCPAOMBM4ETgRWATOBs5RSK0TkOuBfSqk7inVuAh5VSt1X1tZ4YHzxo/7/JuqABf13/L9myOLGBCMJj64Eq5EmOeqI0EvWpFgSYDUMiLFZZtehzSfV4K6/0648d+V/pCMzLCEiXYD7gZ8opVaJyA3AryiMI/4KuAo4Wbc9pdQUYEqx7dR3k+PAK8FK14Ysbtz+Oa2SjCpBbztpEGJQEZbqZEGIfhK0Rafd17H/tJe1y8/VOAdWRL4CTAZaA1OVUpcFjUtLhiLSloII71RKPQCglFrquf8H4E/Fj43AYE/1QcVrjhpUEmGtMmmUoikRpoUwIvTWTbMQg4jwkBX/NtptbrVmFe2f/5ux9kSkNXA98GVgEfCCiMxQSs0O0o7ObLIANwFvKqUmea73L44nAhwLlDbNzADuEpFJFCZQdieu11tlFB0R1qqbBiHaEGGS2WEUEaadMBmhSSFu2rqeDz5+yUhbRQ4E5iql5gOIyHQKcxeBZKgzm3ww8HfgNWBb8fL5wHeAfSl0kxcAp5bkKCI/o9Bl3kKhW/2ozzOWAWuB+BYVmacBF3/SZP3vkPX4ofLfYRelVJ/SBxF5rFhOlw7ABs/nKcVhtlJ7xwFfUUqdUvx8AnCQUmpCkMB1ZpOfBaTCrUdq1LkUuFQ3CKVUHxGZGccgqS1c/MmT9b9D1uMHvb+DUuorccUTBLcDxeFwZB0j8xROhg6HI+u8AOwuIkNFpB1wPIW5i0Ck6aCGKf5FUo2LP3my/nfIevyQwN9BKbVFRCYAj1NYWjNNKfVG0HZS8Q4Uh8PhSBrXTXY4HA6cDB0OhwNIgQxF5Csi8raIzBWRiUnHo4uILBCR10TkZRGZWbzWS0T+IiLvFP/smXScJURkmog0icjrnmsV45UC1xS/k1dFZL/kIt8ea6X4LxKRxuJ38LKIjPLcO68Y/9sicmQyUTdHRAaLyJMiMltE3hCRM4rXM/E91Ig/U99DVZRSif1QGOycB+wKtANeAUYkGVOA2BcADWXXrgAmFn+fCFyedJye2L4I7Ae87hcvMAp4lML60s8Az6c0/ouAn1YoO6L471J7YGjx37HWKfg79Af2K/7eFZhTjDUT30ON+DP1PVT7SToz3L6NRim1CShto8kqo4Fbi7/fSuHcx1SglHoG+KjscrV4RwO3qQL/AnoUz7VMjCrxV2P7MXJKqXeB0jFyiaKUWqyUerH4+2qgdBxeJr6HGvFXI5XfQzWSluFA4H3P50XU/oebJhTwZxGZVTyODKCv2rFfewmF08HTTLV4s/S9TCh2Iad5hiVSH3/xOLxPAc+Twe+hLH7I6PfgJWkZZpmDlVL7AUcBp4nIF703VaGfkJl1S1mLt8gNwG4U9sgvpnCMXOopPw7Pey8L30OF+DP5PZSTtAwze9yXUqqx+GcT8CCF9H9pqRtT/LMpuQi1qBZvJr4XpdRSpdRWpdQ24A/s6IKlNv5Kx+GRoe+h2nF+WfseKpG0DI1so4kbEekshffBICKdgSMoHGE2AxhbLDYWeCiZCLWpFu8M4PvF2czPAB97unGpoWz8rPwYueNFpL2IDCUlx8iJVD4Oj4x8D9Xiz9r3UJWkZ3AozJjNoTDT9LOk49GMeVcKs2SvAG+U4gZ6A08A71B4EVavpGP1xHw3hS7MZgpjN+OqxUth9vL64nfyGnBASuO/vRjfqxT+w+vvKf+zYvxvA0clHX8xpoMpdIFfBV4u/ozKyvdQI/5MfQ/Vftx2PIfD4SD5brLD4XCkAidDh8PhwMnQ4XA4ACdDh8PhAJwMHQ6HA3AydDgcDsDJ0OFwOAD4fwt0eX/NFHx6AAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "867149ee", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/_build/doctrees/nbsphinx/_include_notebooks_label_visualize_labels_3_1.png b/docs/_build/doctrees/nbsphinx/_include_notebooks_label_visualize_labels_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..e143f9c7de2abc3e7d0fd5eeaa5ebe19129751b7 GIT binary patch literal 13455 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 kH3$0kN^vdjP#lUo#fuavuEpK86xVlp?-=*J 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 kH3 + + + + + + + API Reference — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

API Reference

+

This is the class and function reference of biapol-utilities. Please refer to the examples for further details, as the class and function raw specifications may not be enough to give full guidelines on their uses.

+
+

The label module

+

The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of +an object is encoded in the pixel value which must be an integer number.

+ ++++ + + + + + + + + + + + + + + +

label.compare_labels(label_image_x, ...)

Evaluate differences between two label images.

label.intersection_over_union_matrix(...)

Generates a matrix with intersection over union of all mask pairs

label.match_labels(label_image_x, label_image_y)

Match labels in label_image_y with labels in label_image_x.

label.match_labels_stack(label_stack[, method])

Match labels from subsequent slices with specified method

+
+
+

The data module

+

The data module provides example data to be usedin the examples section.

+ ++++ + + + + + +

data.blobs()

Gray-level "blobs" image [1].

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/Examples.html b/docs/_build/html/_include/Examples.html new file mode 100644 index 0000000..8b56d58 --- /dev/null +++ b/docs/_build/html/_include/Examples.html @@ -0,0 +1,131 @@ + + + + + + + + + Examples — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Examples

+

This is the example library of biapol-utilities. We provide examples for all top-level functions that are listed +in the API reference and comment on their usage here.

+
+

Label module

+

The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of +an object is encoded in the pixel value which must be an integer number.

+ +
+
+

Data module

+

The data module provides example data to be usedin the examples section.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/biapol_utilities.label.compare_labels.html b/docs/_build/html/_include/biapol_utilities.label.compare_labels.html new file mode 100644 index 0000000..691388d --- /dev/null +++ b/docs/_build/html/_include/biapol_utilities.label.compare_labels.html @@ -0,0 +1,141 @@ + + + + + + + + + biapol_utilities.label.compare_labels — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

biapol_utilities.label.compare_labels

+
+
+biapol_utilities.label.compare_labels(label_image_x, label_image_y)
+

Evaluate differences between two label images.

+

Compares two label images to determine the +label-wise Jaccard- and Dice scores. +The Jaccard-score is defined as the intersection over union of two labelled +images [#]_. The Dice score S can be derived from the Jaccard-score J +through the following relation:

+
+\[S = \frac{2J}{1+J}\]
+
+

See also

+

+
+
+
Parameters
+
    +
  • label_image_x (ND-array, int) – label image of arbitrary dimensions.

  • +
  • label_image_y (ND-array, int) – label image which will be compared to label_image_x, must have the +same dimensions.

  • +
+
+
Returns
+

    +
  • pandas DataFrame with columns [‘label’, ‘jaccard_score’, ‘dice_score’].

  • +
  • Each row corresponds to the measured quantitiy (Jaccard- or Dice score) of

  • +
  • the respective label.

  • +
+

+
+
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html b/docs/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html new file mode 100644 index 0000000..1f7d03b --- /dev/null +++ b/docs/_build/html/_include/biapol_utilities.label.intersection_over_union_matrix.html @@ -0,0 +1,146 @@ + + + + + + + + + biapol_utilities.label.intersection_over_union_matrix — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

biapol_utilities.label.intersection_over_union_matrix

+
+
+biapol_utilities.label.intersection_over_union_matrix(label_image_x, label_image_y)
+

Generates a matrix with intersection over union of all mask pairs

+

How it works: +The overlap matrix is a lookup table of the area of intersection +between each set of labels (true and predicted). The true labels +are taken to be along axis 0, and the predicted labels are taken +to be along axis 1. The sum of the overlaps along axis 0 is thus +an array giving the total overlap of the true labels with each of +the predicted labels, and likewise the sum over axis 1 is the +total overlap of the predicted labels with each of the true labels. +Because the label 0 (background) is included, this sum is guaranteed +to reconstruct the total area of each label. Adding this row and +column vectors gives a 2D array with the areas of every label pair +added together. This is equivalent to the union of the label areas +except for the duplicated overlap area, so the overlap matrix is +subtracted to find the union matrix.

+

Source: 1

+
+
Parameters
+
    +
  • label_image_x (ND-array, int) – label image, where 0=background; 1,2… are label masks

  • +
  • label_image_y (ND-array, int) – label image, where 0=background; 1,2… are label masks

  • +
+
+
Returns
+

iou – matrix of IOU pairs of size [x.max()+1, y.max()+1]

+
+
Return type
+

ND-array, float

+
+
+

References

+
+
1
+

https://clij.github.io/clij2-docs/reference_generateJaccardIndexMatrix

+
+
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/biapol_utilities.label.match_labels_stack.html b/docs/_build/html/_include/biapol_utilities.label.match_labels_stack.html new file mode 100644 index 0000000..1815ca2 --- /dev/null +++ b/docs/_build/html/_include/biapol_utilities.label.match_labels_stack.html @@ -0,0 +1,131 @@ + + + + + + + + + biapol_utilities.label.match_labels_stack — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

biapol_utilities.label.match_labels_stack

+
+
+biapol_utilities.label.match_labels_stack(label_stack, method=<function intersection_over_union_matrix>, **kwargs)
+

Match labels from subsequent slices with specified method

+
+
Parameters
+
    +
  • label_stack (3D-array, int) – Stack of 2D label images to be stitched with axis order ZYX

  • +
  • method (str, optional) –

    Method to be used for stitching the masks. The default is intersection_over_union_matrix with a stitch threshold of 0.25. +stitch_threshold : float

    +
    +

    Threshold value for iou value above which two labels are considered identical. +The default value is 0.25

    +
    +

  • +
+
+
Returns
+

Stack of stitched masks

+
+
Return type
+

3D-array, int

+
+
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/generated/biapol_utilities.data.blobs.html b/docs/_build/html/_include/generated/biapol_utilities.data.blobs.html new file mode 100644 index 0000000..9f341f1 --- /dev/null +++ b/docs/_build/html/_include/generated/biapol_utilities.data.blobs.html @@ -0,0 +1,134 @@ + + + + + + + + + biapol_utilities.data.blobs — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

biapol_utilities.data.blobs

+
+
+biapol_utilities.data.blobs()
+

Gray-level “blobs” image [1].

+

Can be used for segmentation and denoising examples.

+
+
Returns
+

blobs – Blobs image.

+
+
Return type
+

(256, 254) uint8 ndarray

+
+
+

References

+
+
1
+

https://imagej.nih.gov/ij/images/

+
+
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/generated/biapol_utilities.label.compare_labels.html b/docs/_build/html/_include/generated/biapol_utilities.label.compare_labels.html new file mode 100644 index 0000000..7645d7d --- /dev/null +++ b/docs/_build/html/_include/generated/biapol_utilities.label.compare_labels.html @@ -0,0 +1,151 @@ + + + + + + + + + biapol_utilities.label.compare_labels — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

biapol_utilities.label.compare_labels

+
+
+biapol_utilities.label.compare_labels(label_image_x, label_image_y)
+

Evaluate differences between two label images.

+

Compares two label images to determine the +label-wise Jaccard- and Dice scores. +The Jaccard-score is defined as the intersection over union of two labelled +images [#]_. The Dice score S can be derived from the Jaccard-score J +through the following relation:

+
+\[S = \frac{2J}{1+J}\]
+
+

See also

+

+
+
+
Parameters
+
    +
  • label_image_x (ND-array, int) – label image of arbitrary dimensions.

  • +
  • label_image_y (ND-array, int) – label image which will be compared to label_image_x, must have the +same dimensions.

  • +
+
+
Returns
+

    +
  • pandas DataFrame with columns [‘label’, ‘jaccard_score’, ‘dice_score’].

  • +
  • Each row corresponds to the measured quantitiy (Jaccard- or Dice score) of

  • +
  • the respective label.

  • +
+

+
+
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html b/docs/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html new file mode 100644 index 0000000..f8ddb1d --- /dev/null +++ b/docs/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html @@ -0,0 +1,156 @@ + + + + + + + + + biapol_utilities.label.intersection_over_union_matrix — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

biapol_utilities.label.intersection_over_union_matrix

+
+
+biapol_utilities.label.intersection_over_union_matrix(label_image_x, label_image_y)
+

Generates a matrix with intersection over union of all mask pairs

+

How it works: +The overlap matrix is a lookup table of the area of intersection +between each set of labels (true and predicted). The true labels +are taken to be along axis 0, and the predicted labels are taken +to be along axis 1. The sum of the overlaps along axis 0 is thus +an array giving the total overlap of the true labels with each of +the predicted labels, and likewise the sum over axis 1 is the +total overlap of the predicted labels with each of the true labels. +Because the label 0 (background) is included, this sum is guaranteed +to reconstruct the total area of each label. Adding this row and +column vectors gives a 2D array with the areas of every label pair +added together. This is equivalent to the union of the label areas +except for the duplicated overlap area, so the overlap matrix is +subtracted to find the union matrix.

+

Source: 1

+
+
Parameters
+
    +
  • label_image_x (ND-array, int) – label image, where 0=background; 1,2… are label masks

  • +
  • label_image_y (ND-array, int) – label image, where 0=background; 1,2… are label masks

  • +
+
+
Returns
+

iou – matrix of IOU pairs of size [x.max()+1, y.max()+1]

+
+
Return type
+

ND-array, float

+
+
+

References

+
+
1
+

https://clij.github.io/clij2-docs/reference_generateJaccardIndexMatrix

+
+
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/generated/biapol_utilities.label.match_labels.html b/docs/_build/html/_include/generated/biapol_utilities.label.match_labels.html new file mode 100644 index 0000000..9636ccc --- /dev/null +++ b/docs/_build/html/_include/generated/biapol_utilities.label.match_labels.html @@ -0,0 +1,147 @@ + + + + + + + + + biapol_utilities.label.match_labels — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

biapol_utilities.label.match_labels

+
+
+biapol_utilities.label.match_labels(label_image_x, label_image_y, method=<function intersection_over_union_matrix>, **kwargs)
+

Match labels in label_image_y with labels in label_image_x.

+
+
Parameters
+
    +
  • label_image_x (nd-array) – Image that should serve as a reference for label-matching

  • +
  • label_image_y (nd-array) – Image the labels of which should be paired with labels from imageA

  • +
  • method (str, optional) –

    Pairing method to be used. The default is ‘iou’ (intersection over union).

    +
    +
    iou (intersection over union): The intersection over union is used to

    measure the overlap between labels in both images. The label with +highest overlap is chosen as counterpart label

    +
    +
    iou_streshold: float, optional

    Threshold value above which two labels are accepted as overlapping. +The default value is 0.25

    +
    +
    +
    +
    +

  • +
+
+
Returns
+

Processed version of imageB with labels corresponding to imageA.

+
+
Return type
+

nd-array

+
+
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html b/docs/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html new file mode 100644 index 0000000..011bf14 --- /dev/null +++ b/docs/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html @@ -0,0 +1,141 @@ + + + + + + + + + biapol_utilities.label.match_labels_stack — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

biapol_utilities.label.match_labels_stack

+
+
+biapol_utilities.label.match_labels_stack(label_stack, method=<function intersection_over_union_matrix>, **kwargs)
+

Match labels from subsequent slices with specified method

+
+
Parameters
+
    +
  • label_stack (3D-array, int) – Stack of 2D label images to be stitched with axis order ZYX

  • +
  • method (str, optional) –

    Method to be used for stitching the masks. The default is intersection_over_union_matrix with a stitch threshold of 0.25. +stitch_threshold : float

    +
    +

    Threshold value for iou value above which two labels are considered identical. +The default value is 0.25

    +
    +

  • +
+
+
Returns
+

Stack of stitched masks

+
+
Return type
+

3D-array, int

+
+
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/notebooks/label/Compare_segmentations.html b/docs/_build/html/_include/notebooks/label/Compare_segmentations.html new file mode 100644 index 0000000..9f45111 --- /dev/null +++ b/docs/_build/html/_include/notebooks/label/Compare_segmentations.html @@ -0,0 +1,5798 @@ + + + + + + + + + Quantitative segmentation quality estimation — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + + +
+

Quantitative segmentation quality estimation

+

Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation.

+
+
[1]:
+
+
+
+import os
+import biapol_utilities as biau
+from skimage import io, measure, segmentation
+import numpy as np
+import matplotlib.pyplot as plt
+from mpl_toolkits.axes_grid1 import make_axes_locatable
+import pandas as pd
+
+%matplotlib notebook
+
+
+
+
+

Input data

+

First, let’s generate some example data!

+
+
[2]:
+
+
+
+blobs = biau.data.blobs()
+
+
+
+

Let’s segment this and take it as a ground truth image:

+
+
[3]:
+
+
+
+threshold = 128
+imageA = (blobs > threshold).astype(np.uint8)
+ground_truth = measure.label(imageA)
+
+plt.imshow(ground_truth)
+plt.title('Ground truth')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[3]:
+
+
+
+
+Text(0.5, 1.0, 'Ground truth')
+
+
+

Next, we shuffle the labels and expand them a bit:

+
+
[4]:
+
+
+
+# First, shuffle randomly
+label_shuffle = np.arange(1, ground_truth.max()+1, 1)
+np.random.shuffle(label_shuffle)
+label_shuffle = np.append(np.asarray([0]), label_shuffle)  # append 0 at start of array - we don't want to shuffle background
+segmented = label_shuffle[ground_truth]
+
+
+
+
+
[5]:
+
+
+
+# Second, expand the labels a bit
+segmented = segmentation.expand_labels(segmented, 5)
+
+
+
+
+
[6]:
+
+
+
+# Plot side by side
+fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
+
+axes[0].imshow(ground_truth)
+axes[0].set_title('Ground truth')
+
+axes[1].imshow(segmented)
+axes[1].set_title('Segmentation')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[6]:
+
+
+
+
+Text(0.5, 1.0, 'Segmentation')
+
+
+
+
+

Re-match labels

+

Next, use the label-matching from biapol_utilities to assign correct labels to both images

+
+
[7]:
+
+
+
+segmented = biau.label.match_labels(ground_truth, segmented)
+
+
+
+
+
[8]:
+
+
+
+# Plot side by side
+fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
+
+axes[0].imshow(ground_truth)
+axes[0].set_title('Ground truth')
+
+axes[1].imshow(segmented)
+axes[1].set_title('Segmentation')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[8]:
+
+
+
+
+Text(0.5, 1.0, 'Segmentation')
+
+
+
+
+

Compare labels: Labelwise Jaccard-index

+

Lastly, we calculate the label-wise Jaccard index to measure the intersection over union (IoU) between corresponding pairs of labels.

+
+
[9]:
+
+
+
+result = biau.label.compare_labels(ground_truth, segmented)
+result
+
+
+
+
+
[9]:
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
+

68 rows × 3 columns

+
+
+

Let’s also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label.

+
+
[10]:
+
+
+
+LUT_jaccard = result['jaccard_score'].to_numpy()
+LUT_dice = result['dice_score'].to_numpy()
+
+# set segmentation quality of background to zero
+LUT_jaccard[0] = np.nan
+LUT_dice[0] = np.nan
+
+# create score map
+JI_map = LUT_jaccard[segmented]
+DI_map = LUT_dice[segmented]
+
+
+
+
+
[11]:
+
+
+
+# Plot side by side
+fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))
+fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)
+
+
+# Plot ground truth
+axes[0, 0].imshow(ground_truth)
+axes[0, 0].set_title('Ground truth')
+
+# Plot segmentation
+axes[0, 1].imshow(segmented)
+axes[0, 1].set_title('Segmentation')
+
+# Plot overlay
+axes[0, 2].imshow(ground_truth)
+axes[0, 2].imshow(segmented, alpha=0.5)
+axes[0, 2].set_title('Overlay')
+
+# Plot Jaccard index map
+im = axes[1, 0].imshow(JI_map, cmap='inferno_r')
+axes[1, 0].set_title('Jaccard score')
+cbar = fig.colorbar(im, ax=axes[1, 0])
+
+# Plot Dice score map
+im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')
+axes[1, 1].set_title('Dice score')
+cbar2 = fig.colorbar(im2, ax=axes[1, 1])
+
+axes[-1, -1].axis('off')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[11]:
+
+
+
+
+(-0.5, 255.5, 253.5, -0.5)
+
+
+
+
+

Compare-labels: Feature-wise

+

It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops.

+
+
[12]:
+
+
+
+properties = ['label', 'area', 'eccentricity', 'orientation']
+features_gt = measure.regionprops_table(ground_truth, properties=properties)
+features_seg = measure.regionprops_table(segmented, properties=properties)
+
+features_gt = pd.DataFrame(features_gt)
+features_seg = pd.DataFrame(features_seg)
+features_gt
+
+
+
+
+
[12]:
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
+

63 rows × 4 columns

+
+
+

Visualize as histograms

+
+
[13]:
+
+
+
+fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))
+
+ax_idx = 0
+for idx, prop in enumerate(properties):
+    if  prop == 'label':
+        continue
+
+    axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)
+    axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)
+    axes[ax_idx].set_xlabel(prop)
+    ax_idx += 1
+
+axes[0].legend()
+axes[0].set_ylabel('# Occurrences')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[13]:
+
+
+
+
+Text(0, 0.5, '# Occurrences')
+
+
+
+
[ ]:
+
+
+
+
+
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/notebooks/label/Compare_segmentations.ipynb b/docs/_build/html/_include/notebooks/label/Compare_segmentations.ipynb new file mode 100644 index 0000000..b694e2f --- /dev/null +++ b/docs/_build/html/_include/notebooks/label/Compare_segmentations.ipynb @@ -0,0 +1,5614 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9f0d8ccf", + "metadata": {}, + "source": [ + "# Quantitative segmentation quality estimation\n", + "\n", + "Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "89205b6d", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import biapol_utilities as biau\n", + "from skimage import io, measure, segmentation\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", + "import pandas as pd\n", + "\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "markdown", + "id": "a63045b4", + "metadata": {}, + "source": [ + "## Input data\n", + "First, let's generate some example data!" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "db9c5fe0", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biau.data.blobs()" + ] + }, + { + "cell_type": "markdown", + "id": "2c0c8418", + "metadata": {}, + "source": [ + "Let's segment this and take it as a ground truth image:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2ae66de8", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Ground truth')" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "threshold = 128\n", + "imageA = (blobs > threshold).astype(np.uint8)\n", + "ground_truth = measure.label(imageA)\n", + "\n", + "plt.imshow(ground_truth)\n", + "plt.title('Ground truth')" + ] + }, + { + "cell_type": "markdown", + "id": "f7f4c0be", + "metadata": {}, + "source": [ + "Next, we shuffle the labels and expand them a bit:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2b8dc27c", + "metadata": {}, + "outputs": [], + "source": [ + "# First, shuffle randomly\n", + "label_shuffle = np.arange(1, ground_truth.max()+1, 1)\n", + "np.random.shuffle(label_shuffle)\n", + "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", + "segmented = label_shuffle[ground_truth]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "279f3e2c", + "metadata": {}, + "outputs": [], + "source": [ + "# Second, expand the labels a bit\n", + "segmented = segmentation.expand_labels(segmented, 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "eb0b69c2", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Segmentation')" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "\n", + "axes[0].imshow(ground_truth)\n", + "axes[0].set_title('Ground truth')\n", + "\n", + "axes[1].imshow(segmented)\n", + "axes[1].set_title('Segmentation')" + ] + }, + { + "cell_type": "markdown", + "id": "dd726a7c", + "metadata": {}, + "source": [ + "## Re-match labels\n", + "\n", + "Next, use the label-matching from `biapol_utilities` to assign correct labels to both images" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8007d578", + "metadata": {}, + "outputs": [], + "source": [ + "segmented = biau.label.match_labels(ground_truth, segmented)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "23496dad", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Segmentation')" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "\n", + "axes[0].imshow(ground_truth)\n", + "axes[0].set_title('Ground truth')\n", + "\n", + "axes[1].imshow(segmented)\n", + "axes[1].set_title('Segmentation')" + ] + }, + { + "cell_type": "markdown", + "id": "1e1d39a4", + "metadata": {}, + "source": [ + "## Compare labels: Labelwise Jaccard-index\n", + "\n", + "Lastly, we calculate the *label-wise Jaccard index* to measure the intersection over union (IoU) between corresponding pairs of labels." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "7641d30b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
\n", + "

68 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " label jaccard_score dice_score\n", + "0 0 0.496847 0.663858\n", + "1 1 0.518102 0.682566\n", + "2 2 0.470130 0.639576\n", + "3 3 0.623552 0.768133\n", + "4 4 0.602546 0.751986\n", + ".. ... ... ...\n", + "63 63 0.262857 0.416290\n", + "64 64 0.000000 0.000000\n", + "65 65 0.000000 0.000000\n", + "66 66 0.000000 0.000000\n", + "67 67 0.000000 0.000000\n", + "\n", + "[68 rows x 3 columns]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result = biau.label.compare_labels(ground_truth, segmented)\n", + "result" + ] + }, + { + "cell_type": "markdown", + "id": "3f218dd4", + "metadata": {}, + "source": [ + "Let's also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "fab77a34", + "metadata": {}, + "outputs": [], + "source": [ + "LUT_jaccard = result['jaccard_score'].to_numpy()\n", + "LUT_dice = result['dice_score'].to_numpy()\n", + "\n", + "# set segmentation quality of background to zero\n", + "LUT_jaccard[0] = np.nan\n", + "LUT_dice[0] = np.nan\n", + "\n", + "# create score map\n", + "JI_map = LUT_jaccard[segmented]\n", + "DI_map = LUT_dice[segmented]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ca62489c", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(-0.5, 255.5, 253.5, -0.5)" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))\n", + "fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)\n", + "\n", + "\n", + "# Plot ground truth\n", + "axes[0, 0].imshow(ground_truth)\n", + "axes[0, 0].set_title('Ground truth')\n", + "\n", + "# Plot segmentation\n", + "axes[0, 1].imshow(segmented)\n", + "axes[0, 1].set_title('Segmentation')\n", + "\n", + "# Plot overlay\n", + "axes[0, 2].imshow(ground_truth)\n", + "axes[0, 2].imshow(segmented, alpha=0.5)\n", + "axes[0, 2].set_title('Overlay')\n", + "\n", + "# Plot Jaccard index map\n", + "im = axes[1, 0].imshow(JI_map, cmap='inferno_r')\n", + "axes[1, 0].set_title('Jaccard score')\n", + "cbar = fig.colorbar(im, ax=axes[1, 0])\n", + "\n", + "# Plot Dice score map\n", + "im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')\n", + "axes[1, 1].set_title('Dice score')\n", + "cbar2 = fig.colorbar(im2, ax=axes[1, 1])\n", + "\n", + "axes[-1, -1].axis('off')" + ] + }, + { + "cell_type": "markdown", + "id": "1dc2ca58", + "metadata": {}, + "source": [ + "## Compare-labels: Feature-wise\n", + "It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "5f6cc904", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
\n", + "

63 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " label area eccentricity orientation\n", + "0 1 415 0.878888 -0.433915\n", + "1 2 181 0.822705 -1.513862\n", + "2 3 646 0.386542 -0.079653\n", + "3 4 426 0.324798 -0.400592\n", + "4 5 465 0.780472 -0.044317\n", + ".. ... ... ... ...\n", + "58 59 1 0.000000 0.785398\n", + "59 60 87 0.969263 -1.560717\n", + "60 61 73 0.951468 -1.567605\n", + "61 62 49 0.942191 -1.554054\n", + "62 63 46 0.976786 1.538848\n", + "\n", + "[63 rows x 4 columns]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "properties = ['label', 'area', 'eccentricity', 'orientation']\n", + "features_gt = measure.regionprops_table(ground_truth, properties=properties)\n", + "features_seg = measure.regionprops_table(segmented, properties=properties)\n", + "\n", + "features_gt = pd.DataFrame(features_gt)\n", + "features_seg = pd.DataFrame(features_seg)\n", + "features_gt" + ] + }, + { + "cell_type": "markdown", + "id": "ec29004b", + "metadata": {}, + "source": [ + "Visualize as histograms" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "e9652f8d", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0, 0.5, '# Occurrences')" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))\n", + "\n", + "ax_idx = 0\n", + "for idx, prop in enumerate(properties):\n", + " if prop == 'label':\n", + " continue\n", + " \n", + " axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)\n", + " axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)\n", + " axes[ax_idx].set_xlabel(prop)\n", + " ax_idx += 1\n", + " \n", + "axes[0].legend()\n", + "axes[0].set_ylabel('# Occurrences')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "185d4c1d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/_build/html/_include/notebooks/label/match_labels.html b/docs/_build/html/_include/notebooks/label/match_labels.html new file mode 100644 index 0000000..7ec2864 --- /dev/null +++ b/docs/_build/html/_include/notebooks/label/match_labels.html @@ -0,0 +1,3465 @@ + + + + + + + + + Matching labels — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + + +
+

Matching labels

+

This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image.

+
+
[3]:
+
+
+
+import os
+import biapol_utilities as biau
+from skimage import io, measure, filters
+import numpy as np
+import matplotlib.pyplot as plt
+from datetime import datetime
+
+%matplotlib notebook
+
+
+
+
+

Load data

+

First, we load the example blobs image and threshold it to create a label map.

+
+
[4]:
+
+
+
+blobs = biau.data.blobs()
+
+
+
+
+
[5]:
+
+
+
+threshold = 128
+imageA = (blobs > threshold).astype(np.uint8)
+imageA_labelled = measure.label(imageA)
+
+plt.imshow(imageA_labelled)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[5]:
+
+
+
+
+<matplotlib.image.AxesImage at 0x29c86bdabe0>
+
+
+

Let’s create a second version of this image in which we shuffle the labels:

+
+
[6]:
+
+
+
+label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)
+np.random.shuffle(label_shuffle)
+label_shuffle = np.append(np.asarray([0]), label_shuffle)  # append 0 at start of array - we don't want to shuffle background
+
+imageB_labelled = label_shuffle[imageA_labelled]
+
+
+
+

Both images are not identical!

+
+
[7]:
+
+
+
+fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
+axes[0].imshow(imageA_labelled)
+axes[0].set_title('Reference image')
+axes[1].imshow(imageB_labelled)
+axes[1].set_title('Shuffled image')
+
+print(f'Number of labels in imageA: {imageA_labelled.max()}')
+print(f'Number of labels in imageB: {imageB_labelled.max()}')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Number of labels in imageA: 63
+Number of labels in imageB: 63
+
+
+

Match labels and track time

+
+
[8]:
+
+
+
+t0 = datetime.now()
+output = biau.label.match_labels(imageA_labelled, imageB_labelled)
+t1 = datetime.now()
+print(f'Took {(t1-t0).seconds*1000} ms')
+
+
+
+
+
+
+
+
+Took 0 ms
+
+
+

Visualize

+
+
[9]:
+
+
+
+fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
+axes[0].imshow(imageA_labelled)
+axes[0].set_title('Reference image')
+axes[1].imshow(output)
+axes[1].set_title('Relabelled image')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[9]:
+
+
+
+
+Text(0.5, 1.0, 'Relabelled image')
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/notebooks/label/match_labels.ipynb b/docs/_build/html/_include/notebooks/label/match_labels.ipynb new file mode 100644 index 0000000..181425a --- /dev/null +++ b/docs/_build/html/_include/notebooks/label/match_labels.ipynb @@ -0,0 +1,3198 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e5db44ea", + "metadata": {}, + "source": [ + "## Matching labels\n", + "This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d1ca8e7a", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import biapol_utilities as biau\n", + "from skimage import io, measure, filters\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from datetime import datetime\n", + "\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "markdown", + "id": "ee62539b", + "metadata": {}, + "source": [ + "### Load data\n", + "First, we load the example blobs image and threshold it to create a label map. " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "7fe70350", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biau.data.blobs()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "909ce3b2", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "threshold = 128\n", + "imageA = (blobs > threshold).astype(np.uint8)\n", + "imageA_labelled = measure.label(imageA)\n", + "\n", + "plt.imshow(imageA_labelled)" + ] + }, + { + "cell_type": "markdown", + "id": "1cbf5ae3", + "metadata": {}, + "source": [ + "Let's create a second version of this image in which we shuffle the labels:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "29986d79", + "metadata": {}, + "outputs": [], + "source": [ + "label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)\n", + "np.random.shuffle(label_shuffle)\n", + "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", + "\n", + "imageB_labelled = label_shuffle[imageA_labelled]" + ] + }, + { + "cell_type": "markdown", + "id": "1393dfb7", + "metadata": {}, + "source": [ + "Both images are not identical!" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "1ff3c80c", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of labels in imageA: 63\n", + "Number of labels in imageB: 63\n" + ] + } + ], + "source": [ + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "axes[0].imshow(imageA_labelled)\n", + "axes[0].set_title('Reference image')\n", + "axes[1].imshow(imageB_labelled)\n", + "axes[1].set_title('Shuffled image')\n", + "\n", + "print(f'Number of labels in imageA: {imageA_labelled.max()}')\n", + "print(f'Number of labels in imageB: {imageB_labelled.max()}')" + ] + }, + { + "cell_type": "markdown", + "id": "7a38be04", + "metadata": {}, + "source": [ + "Match labels and track time" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "79f0cf74", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Took 0 ms\n" + ] + } + ], + "source": [ + "t0 = datetime.now()\n", + "output = biau.label.match_labels(imageA_labelled, imageB_labelled)\n", + "t1 = datetime.now()\n", + "print(f'Took {(t1-t0).seconds*1000} ms')" + ] + }, + { + "cell_type": "markdown", + "id": "a8710824", + "metadata": {}, + "source": [ + "Visualize" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "84ed2639", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Relabelled image')" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "axes[0].imshow(imageA_labelled)\n", + "axes[0].set_title('Reference image')\n", + "axes[1].imshow(output)\n", + "axes[1].set_title('Relabelled image')" + ] + } + ], + "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.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/_build/html/_include/notebooks/label/visualize_labels.html b/docs/_build/html/_include/notebooks/label/visualize_labels.html new file mode 100644 index 0000000..4897c53 --- /dev/null +++ b/docs/_build/html/_include/notebooks/label/visualize_labels.html @@ -0,0 +1,411 @@ + + + + + + + + + Labels visualized in colours — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + + +
+
[1]:
+
+
+
+import biapol_utilities as biao
+from skimage.measure import label
+from skimage.io import imshow
+
+
+
+
+
[2]:
+
+
+
+blobs = biao.blobs()
+labels = label(blobs > 128)
+
+
+
+
+

Labels visualized in colours

+

biapol_utilities provided a standardized color map for visualizing labels in:

+
+
[4]:
+
+
+
+imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())
+
+
+
+
+
[4]:
+
+
+
+
+<matplotlib.image.AxesImage at 0x17fe4272220>
+
+
+
+
+
+
+../../../_images/_include_notebooks_label_visualize_labels_3_1.png +
+
+
+
[ ]:
+
+
+
+
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/notebooks/label/visualize_labels.ipynb b/docs/_build/html/_include/notebooks/label/visualize_labels.ipynb new file mode 100644 index 0000000..9924ff8 --- /dev/null +++ b/docs/_build/html/_include/notebooks/label/visualize_labels.ipynb @@ -0,0 +1,98 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "803a884d", + "metadata": {}, + "outputs": [], + "source": [ + "import biapol_utilities as biao\n", + "from skimage.measure import label\n", + "from skimage.io import imshow" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "af876b71", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biao.blobs()\n", + "labels = label(blobs > 128)" + ] + }, + { + "cell_type": "markdown", + "id": "d9ded05a", + "metadata": {}, + "source": [ + "# Labels visualized in colours\n", + "`biapol_utilities` provided a standardized color map for visualizing labels in:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "5c3f2337", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "867149ee", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/_build/html/_sources/_include/API_reference.rst.txt b/docs/_build/html/_sources/_include/API_reference.rst.txt new file mode 100644 index 0000000..f94c3ba --- /dev/null +++ b/docs/_build/html/_sources/_include/API_reference.rst.txt @@ -0,0 +1,31 @@ +API Reference +============= +This is the class and function reference of biapol-utilities. Please refer to the examples for further details, as the class and function raw specifications may not be enough to give full guidelines on their uses. + +The label module +------------------ +The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of +an object is encoded in the pixel value which must be an integer number. + +.. currentmodule:: biapol_utilities + +.. autosummary:: + :recursive: + :toctree: generated + + label.compare_labels + label.intersection_over_union_matrix + label.match_labels + label.match_labels_stack + +The data module +------------------ +The data module provides example data to be usedin the examples section. + +.. currentmodule:: biapol_utilities + +.. autosummary:: + :recursive: + :toctree: generated + + data.blobs \ No newline at end of file diff --git a/docs/_build/html/_sources/_include/Examples.rst.txt b/docs/_build/html/_sources/_include/Examples.rst.txt new file mode 100644 index 0000000..792bb14 --- /dev/null +++ b/docs/_build/html/_sources/_include/Examples.rst.txt @@ -0,0 +1,21 @@ +Examples +============= +This is the example library of biapol-utilities. We provide examples for all top-level functions that are listed +in the API reference and comment on their usage here. + +Label module +------------------ +The label module bundles functions that operate on label images, i.e. images with annotated objects. The idendity of +an object is encoded in the pixel value which must be an integer number. + +.. toctree:: + :titlesonly: + :maxdepth: 0 + + Match labels + Compare segmentations + Visualize labels + +Data module +------------------ +The data module provides example data to be usedin the examples section. diff --git a/docs/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt b/docs/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt new file mode 100644 index 0000000..286bf6d --- /dev/null +++ b/docs/_build/html/_sources/_include/biapol_utilities.label.compare_labels.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.compare\_labels +======================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: compare_labels \ No newline at end of file diff --git a/docs/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt b/docs/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt new file mode 100644 index 0000000..3b66942 --- /dev/null +++ b/docs/_build/html/_sources/_include/biapol_utilities.label.intersection_over_union_matrix.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.intersection\_over\_union\_matrix +========================================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: intersection_over_union_matrix \ No newline at end of file diff --git a/docs/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt b/docs/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt new file mode 100644 index 0000000..2f71b54 --- /dev/null +++ b/docs/_build/html/_sources/_include/biapol_utilities.label.match_labels_stack.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.match\_labels\_stack +============================================ + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: match_labels_stack \ No newline at end of file diff --git a/docs/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt b/docs/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt new file mode 100644 index 0000000..16a40fd --- /dev/null +++ b/docs/_build/html/_sources/_include/generated/biapol_utilities.data.blobs.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.data.blobs +============================ + +.. currentmodule:: biapol_utilities.data + +.. autofunction:: blobs \ No newline at end of file diff --git a/docs/_build/html/_sources/_include/generated/biapol_utilities.label.compare_labels.rst.txt b/docs/_build/html/_sources/_include/generated/biapol_utilities.label.compare_labels.rst.txt new file mode 100644 index 0000000..286bf6d --- /dev/null +++ b/docs/_build/html/_sources/_include/generated/biapol_utilities.label.compare_labels.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.compare\_labels +======================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: compare_labels \ No newline at end of file diff --git a/docs/_build/html/_sources/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst.txt b/docs/_build/html/_sources/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst.txt new file mode 100644 index 0000000..3b66942 --- /dev/null +++ b/docs/_build/html/_sources/_include/generated/biapol_utilities.label.intersection_over_union_matrix.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.intersection\_over\_union\_matrix +========================================================= + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: intersection_over_union_matrix \ No newline at end of file diff --git a/docs/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt b/docs/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt new file mode 100644 index 0000000..ae8b654 --- /dev/null +++ b/docs/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.match\_labels +===================================== + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: match_labels \ No newline at end of file diff --git a/docs/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels_stack.rst.txt b/docs/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels_stack.rst.txt new file mode 100644 index 0000000..2f71b54 --- /dev/null +++ b/docs/_build/html/_sources/_include/generated/biapol_utilities.label.match_labels_stack.rst.txt @@ -0,0 +1,6 @@ +biapol\_utilities.label.match\_labels\_stack +============================================ + +.. currentmodule:: biapol_utilities.label + +.. autofunction:: match_labels_stack \ No newline at end of file diff --git a/docs/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt b/docs/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt new file mode 100644 index 0000000..b694e2f --- /dev/null +++ b/docs/_build/html/_sources/_include/notebooks/label/Compare_segmentations.ipynb.txt @@ -0,0 +1,5614 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9f0d8ccf", + "metadata": {}, + "source": [ + "# Quantitative segmentation quality estimation\n", + "\n", + "Often we face the problem, that we have an annnotated image of some data and a segmented version of the same image, which was obtained with some segmentation pipeline (StarDist, EPySeg, PlantSeg, etc). This notebook provides a method to compare the overlap of both ground truth image and achieved segmentation." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "89205b6d", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import biapol_utilities as biau\n", + "from skimage import io, measure, segmentation\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", + "import pandas as pd\n", + "\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "markdown", + "id": "a63045b4", + "metadata": {}, + "source": [ + "## Input data\n", + "First, let's generate some example data!" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "db9c5fe0", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biau.data.blobs()" + ] + }, + { + "cell_type": "markdown", + "id": "2c0c8418", + "metadata": {}, + "source": [ + "Let's segment this and take it as a ground truth image:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2ae66de8", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Ground truth')" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "threshold = 128\n", + "imageA = (blobs > threshold).astype(np.uint8)\n", + "ground_truth = measure.label(imageA)\n", + "\n", + "plt.imshow(ground_truth)\n", + "plt.title('Ground truth')" + ] + }, + { + "cell_type": "markdown", + "id": "f7f4c0be", + "metadata": {}, + "source": [ + "Next, we shuffle the labels and expand them a bit:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2b8dc27c", + "metadata": {}, + "outputs": [], + "source": [ + "# First, shuffle randomly\n", + "label_shuffle = np.arange(1, ground_truth.max()+1, 1)\n", + "np.random.shuffle(label_shuffle)\n", + "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", + "segmented = label_shuffle[ground_truth]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "279f3e2c", + "metadata": {}, + "outputs": [], + "source": [ + "# Second, expand the labels a bit\n", + "segmented = segmentation.expand_labels(segmented, 5)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "eb0b69c2", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Segmentation')" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "\n", + "axes[0].imshow(ground_truth)\n", + "axes[0].set_title('Ground truth')\n", + "\n", + "axes[1].imshow(segmented)\n", + "axes[1].set_title('Segmentation')" + ] + }, + { + "cell_type": "markdown", + "id": "dd726a7c", + "metadata": {}, + "source": [ + "## Re-match labels\n", + "\n", + "Next, use the label-matching from `biapol_utilities` to assign correct labels to both images" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8007d578", + "metadata": {}, + "outputs": [], + "source": [ + "segmented = biau.label.match_labels(ground_truth, segmented)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "23496dad", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Segmentation')" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "\n", + "axes[0].imshow(ground_truth)\n", + "axes[0].set_title('Ground truth')\n", + "\n", + "axes[1].imshow(segmented)\n", + "axes[1].set_title('Segmentation')" + ] + }, + { + "cell_type": "markdown", + "id": "1e1d39a4", + "metadata": {}, + "source": [ + "## Compare labels: Labelwise Jaccard-index\n", + "\n", + "Lastly, we calculate the *label-wise Jaccard index* to measure the intersection over union (IoU) between corresponding pairs of labels." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "7641d30b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
labeljaccard_scoredice_score
000.4968470.663858
110.5181020.682566
220.4701300.639576
330.6235520.768133
440.6025460.751986
............
63630.2628570.416290
64640.0000000.000000
65650.0000000.000000
66660.0000000.000000
67670.0000000.000000
\n", + "

68 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " label jaccard_score dice_score\n", + "0 0 0.496847 0.663858\n", + "1 1 0.518102 0.682566\n", + "2 2 0.470130 0.639576\n", + "3 3 0.623552 0.768133\n", + "4 4 0.602546 0.751986\n", + ".. ... ... ...\n", + "63 63 0.262857 0.416290\n", + "64 64 0.000000 0.000000\n", + "65 65 0.000000 0.000000\n", + "66 66 0.000000 0.000000\n", + "67 67 0.000000 0.000000\n", + "\n", + "[68 rows x 3 columns]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result = biau.label.compare_labels(ground_truth, segmented)\n", + "result" + ] + }, + { + "cell_type": "markdown", + "id": "3f218dd4", + "metadata": {}, + "source": [ + "Let's also visualize this: To do this, we create a new image and assign the jaccard-index result value to every pixel depending on the label." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "fab77a34", + "metadata": {}, + "outputs": [], + "source": [ + "LUT_jaccard = result['jaccard_score'].to_numpy()\n", + "LUT_dice = result['dice_score'].to_numpy()\n", + "\n", + "# set segmentation quality of background to zero\n", + "LUT_jaccard[0] = np.nan\n", + "LUT_dice[0] = np.nan\n", + "\n", + "# create score map\n", + "JI_map = LUT_jaccard[segmented]\n", + "DI_map = LUT_dice[segmented]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ca62489c", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(-0.5, 255.5, 253.5, -0.5)" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot side by side\n", + "fig, axes = plt.subplots(nrows=2, ncols=3, sharex=True, sharey=True, figsize=(10,5))\n", + "fig.subplots_adjust(left=0.05, bottom=0.06, right=0.85, top=0.95, wspace=0.05)\n", + "\n", + "\n", + "# Plot ground truth\n", + "axes[0, 0].imshow(ground_truth)\n", + "axes[0, 0].set_title('Ground truth')\n", + "\n", + "# Plot segmentation\n", + "axes[0, 1].imshow(segmented)\n", + "axes[0, 1].set_title('Segmentation')\n", + "\n", + "# Plot overlay\n", + "axes[0, 2].imshow(ground_truth)\n", + "axes[0, 2].imshow(segmented, alpha=0.5)\n", + "axes[0, 2].set_title('Overlay')\n", + "\n", + "# Plot Jaccard index map\n", + "im = axes[1, 0].imshow(JI_map, cmap='inferno_r')\n", + "axes[1, 0].set_title('Jaccard score')\n", + "cbar = fig.colorbar(im, ax=axes[1, 0])\n", + "\n", + "# Plot Dice score map\n", + "im2 = axes[1, 1].imshow(DI_map, cmap='inferno_r')\n", + "axes[1, 1].set_title('Dice score')\n", + "cbar2 = fig.colorbar(im2, ax=axes[1, 1])\n", + "\n", + "axes[-1, -1].axis('off')" + ] + }, + { + "cell_type": "markdown", + "id": "1dc2ca58", + "metadata": {}, + "source": [ + "## Compare-labels: Feature-wise\n", + "It may be an interesting approach to not only check the pixel-wise agreement between segmentation and annnootation but to also check whether certain features are preserved in the segmentation. For this, the (shape-) features are calculated in both ground_truth annotation and segmented image with scikit-image regionprops." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "5f6cc904", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
labelareaeccentricityorientation
014150.878888-0.433915
121810.822705-1.513862
236460.386542-0.079653
344260.324798-0.400592
454650.780472-0.044317
...............
585910.0000000.785398
5960870.969263-1.560717
6061730.951468-1.567605
6162490.942191-1.554054
6263460.9767861.538848
\n", + "

63 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " label area eccentricity orientation\n", + "0 1 415 0.878888 -0.433915\n", + "1 2 181 0.822705 -1.513862\n", + "2 3 646 0.386542 -0.079653\n", + "3 4 426 0.324798 -0.400592\n", + "4 5 465 0.780472 -0.044317\n", + ".. ... ... ... ...\n", + "58 59 1 0.000000 0.785398\n", + "59 60 87 0.969263 -1.560717\n", + "60 61 73 0.951468 -1.567605\n", + "61 62 49 0.942191 -1.554054\n", + "62 63 46 0.976786 1.538848\n", + "\n", + "[63 rows x 4 columns]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "properties = ['label', 'area', 'eccentricity', 'orientation']\n", + "features_gt = measure.regionprops_table(ground_truth, properties=properties)\n", + "features_seg = measure.regionprops_table(segmented, properties=properties)\n", + "\n", + "features_gt = pd.DataFrame(features_gt)\n", + "features_seg = pd.DataFrame(features_seg)\n", + "features_gt" + ] + }, + { + "cell_type": "markdown", + "id": "ec29004b", + "metadata": {}, + "source": [ + "Visualize as histograms" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "e9652f8d", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0, 0.5, '# Occurrences')" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig, axes = plt.subplots(nrows=1, ncols=len(properties)-1, figsize=(9,6))\n", + "\n", + "ax_idx = 0\n", + "for idx, prop in enumerate(properties):\n", + " if prop == 'label':\n", + " continue\n", + " \n", + " axes[ax_idx].hist(features_gt[prop], label='ground_truth', bins=20, alpha=0.5)\n", + " axes[ax_idx].hist(features_seg[prop], label='segmentation', bins=20, alpha=0.5)\n", + " axes[ax_idx].set_xlabel(prop)\n", + " ax_idx += 1\n", + " \n", + "axes[0].legend()\n", + "axes[0].set_ylabel('# Occurrences')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "185d4c1d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt b/docs/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt new file mode 100644 index 0000000..181425a --- /dev/null +++ b/docs/_build/html/_sources/_include/notebooks/label/match_labels.ipynb.txt @@ -0,0 +1,3198 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e5db44ea", + "metadata": {}, + "source": [ + "## Matching labels\n", + "This script will compare two labelled images and convert the assigned labels in one image to resemble the labels in the first image." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d1ca8e7a", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import biapol_utilities as biau\n", + "from skimage import io, measure, filters\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from datetime import datetime\n", + "\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "markdown", + "id": "ee62539b", + "metadata": {}, + "source": [ + "### Load data\n", + "First, we load the example blobs image and threshold it to create a label map. " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "7fe70350", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biau.data.blobs()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "909ce3b2", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "threshold = 128\n", + "imageA = (blobs > threshold).astype(np.uint8)\n", + "imageA_labelled = measure.label(imageA)\n", + "\n", + "plt.imshow(imageA_labelled)" + ] + }, + { + "cell_type": "markdown", + "id": "1cbf5ae3", + "metadata": {}, + "source": [ + "Let's create a second version of this image in which we shuffle the labels:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "29986d79", + "metadata": {}, + "outputs": [], + "source": [ + "label_shuffle = np.arange(1, imageA_labelled.max()+1, 1)\n", + "np.random.shuffle(label_shuffle)\n", + "label_shuffle = np.append(np.asarray([0]), label_shuffle) # append 0 at start of array - we don't want to shuffle background\n", + "\n", + "imageB_labelled = label_shuffle[imageA_labelled]" + ] + }, + { + "cell_type": "markdown", + "id": "1393dfb7", + "metadata": {}, + "source": [ + "Both images are not identical!" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "1ff3c80c", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of labels in imageA: 63\n", + "Number of labels in imageB: 63\n" + ] + } + ], + "source": [ + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "axes[0].imshow(imageA_labelled)\n", + "axes[0].set_title('Reference image')\n", + "axes[1].imshow(imageB_labelled)\n", + "axes[1].set_title('Shuffled image')\n", + "\n", + "print(f'Number of labels in imageA: {imageA_labelled.max()}')\n", + "print(f'Number of labels in imageB: {imageB_labelled.max()}')" + ] + }, + { + "cell_type": "markdown", + "id": "7a38be04", + "metadata": {}, + "source": [ + "Match labels and track time" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "79f0cf74", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Took 0 ms\n" + ] + } + ], + "source": [ + "t0 = datetime.now()\n", + "output = biau.label.match_labels(imageA_labelled, imageB_labelled)\n", + "t1 = datetime.now()\n", + "print(f'Took {(t1-t0).seconds*1000} ms')" + ] + }, + { + "cell_type": "markdown", + "id": "a8710824", + "metadata": {}, + "source": [ + "Visualize" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "84ed2639", + "metadata": {}, + "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(\"
\");\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", + " '';\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", + " '';\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 = '';\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 = '';\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": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Relabelled image')" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)\n", + "axes[0].imshow(imageA_labelled)\n", + "axes[0].set_title('Reference image')\n", + "axes[1].imshow(output)\n", + "axes[1].set_title('Relabelled image')" + ] + } + ], + "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.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt b/docs/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt new file mode 100644 index 0000000..9924ff8 --- /dev/null +++ b/docs/_build/html/_sources/_include/notebooks/label/visualize_labels.ipynb.txt @@ -0,0 +1,98 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "803a884d", + "metadata": {}, + "outputs": [], + "source": [ + "import biapol_utilities as biao\n", + "from skimage.measure import label\n", + "from skimage.io import imshow" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "af876b71", + "metadata": {}, + "outputs": [], + "source": [ + "blobs = biao.blobs()\n", + "labels = label(blobs > 128)" + ] + }, + { + "cell_type": "markdown", + "id": "d9ded05a", + "metadata": {}, + "source": [ + "# Labels visualized in colours\n", + "`biapol_utilities` provided a standardized color map for visualizing labels in:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "5c3f2337", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "imshow(labels, cmap=biao.labels_colormap(), vmin=0, vmax=labels.max())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "867149ee", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt new file mode 100644 index 0000000..67ee96f --- /dev/null +++ b/docs/_build/html/_sources/index.rst.txt @@ -0,0 +1,26 @@ +Welcome to BiAPoL utilities's documentation! +============================================ + +On this page, we provide documentation pages for our API and provide +comprehensive examples on how to use the functions in our library. + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + _include/Examples + _include/API_reference + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + +Ressources +================== + + * BiAPoL group blog: ``_. + * Source code: ``_. \ No newline at end of file diff --git a/docs/_build/html/_static/alabaster.css b/docs/_build/html/_static/alabaster.css new file mode 100644 index 0000000..0eddaeb --- /dev/null +++ b/docs/_build/html/_static/alabaster.css @@ -0,0 +1,701 @@ +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Georgia, serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 940px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 220px; +} + +div.sphinxsidebar { + width: 220px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Georgia, serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: Georgia, serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +div.sphinxsidebar .badge { + border-bottom: none; +} + +div.sphinxsidebar .badge:hover { + border-bottom: none; +} + +/* To address an issue with donation coming after search */ +div.sphinxsidebar h3.donation { + margin-top: 10px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Georgia, serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: Georgia, serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + + +/* relbar */ + +.related { + line-height: 30px; + width: 100%; + font-size: 0.9rem; +} + +.related.top { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.related.bottom { + border-top: 1px solid #EEE; +} + +.related ul { + padding: 0; + margin: 0; + list-style: none; +} + +.related li { + display: inline; +} + +nav#rellinks { + float: right; +} + +nav#rellinks li+li:before { + content: "|"; +} + +nav#breadcrumbs li+li:before { + content: "\00BB"; +} + +/* Hide certain items when printing */ +@media print { + div.related { + display: none; + } +} \ No newline at end of file diff --git a/docs/_build/html/_static/basic.css b/docs/_build/html/_static/basic.css new file mode 100644 index 0000000..912859b --- /dev/null +++ b/docs/_build/html/_static/basic.css @@ -0,0 +1,904 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0.5em; + content: ":"; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs/_build/html/_static/css/hatnotes.css b/docs/_build/html/_static/css/hatnotes.css new file mode 100644 index 0000000..8f32061 --- /dev/null +++ b/docs/_build/html/_static/css/hatnotes.css @@ -0,0 +1,15 @@ +.hatnote +{ + border-color: #c8c8c8 ; + border-style: solid ; + border-width: 1px ; + font-size: x-small ; + font-style: italic ; + margin-left: auto ; + margin-right: auto ; + padding: 3px 2em ; +} +.hatnote-gray { background-color: #e8e8e8 ; color: #000000 ; } +.hatnote-yellow { background-color: #ffffe8 ; color: #000000 ; } +.hatnote-red { background-color: #ffe8e8 ; color: #000000 ; } +.hatnote-icon { height: 16px ; width: 16px ; } \ No newline at end of file diff --git a/docs/_build/html/_static/custom.css b/docs/_build/html/_static/custom.css new file mode 100644 index 0000000..2a924f1 --- /dev/null +++ b/docs/_build/html/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/docs/_build/html/_static/doctools.js b/docs/_build/html/_static/doctools.js new file mode 100644 index 0000000..8cbf1b1 --- /dev/null +++ b/docs/_build/html/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/docs/_build/html/_static/documentation_options.js b/docs/_build/html/_static/documentation_options.js new file mode 100644 index 0000000..23fc755 --- /dev/null +++ b/docs/_build/html/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '0.0.1', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/docs/_build/html/_static/file.png b/docs/_build/html/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/docs/_build/html/_static/jquery-3.5.1.js b/docs/_build/html/_static/jquery-3.5.1.js new file mode 100644 index 0000000..5093733 --- /dev/null +++ b/docs/_build/html/_static/jquery-3.5.1.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + + + + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/index.html b/docs/_build/html/index.html new file mode 100644 index 0000000..8fb7099 --- /dev/null +++ b/docs/_build/html/index.html @@ -0,0 +1,141 @@ + + + + + + + + + Welcome to BiAPoL utilities’s documentation! — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Welcome to BiAPoL utilities’s documentation!

+

On this page, we provide documentation pages for our API and provide +comprehensive examples on how to use the functions in our library.

+ +
+
+

Indices and tables

+ +
+
+

Ressources

+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/objects.inv b/docs/_build/html/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..c84ecea155641e68a3d15e823aa3713108058dff GIT binary patch literal 1448 zcmV;Z1y}kbAX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkHX+cnL zOdxf1X>4h9X=QT?BOq2~a&u{KZaN?eBOp|0Wgv28ZDDC{WMy(7Z)PBLXlZjGW@&6? zAZc?TV{dJ6a%FRKWn>_Ab7^j8AbM7fAG>GrWq0!q>Z`~ZBC1W_5{?GsLLjwlYdhw09nBaI{P2EY#kp$Hvt zvOm5Hq}HH%hBLUCSTZpTkwaPF5$^*2T|CvV0m=G88uVq(G3b|hpaS{D6+ zqTrhoyF%63`nFYrGUDg>5$8Aw@Fp)PC}?=gdjTk!`*?pR$yJH~YXT2V)0|3=wZOJT z*+8$Gx;c8pu!?vXr(qds80>fa?TA5j4aD`LQEtS@YNuyqR`eX$Rhwpx3s|Y>uTVpG}CyK@>@FvG=OWB z+8c2S>m>Q+uA8O%7OuNa{B1cEi=e$kG2p;Gr)7Z?3hR9e1b0K}rc`h^l$S0V^hiXD zDK;P@RnkZspenh%GiQ{HUB=;gF4?ie^Tt+mc(IZ-WvPv-8$;;U)vYlVziyptHyq{_ zujO#8Rr@9>#fLQgR&2Szw#k4B{1oGaqH2*YHY7VGhY82}8a|C`;NknVLfcgujzEZO{CZDi2;@sokNUX0kfI8)Ke5RJ8Fc0kWhXGSH$y-Y5TsFB=K4sy zI#)PrV~Z24wb{V*c5{m7ec;REFf|m-d<=fa5u1$|&=mYgKHjH0&~E787a&Z7vYk)g zN&4908IpiyODG8;MTY@Dd^RyAdMBCyYXYK4)}7;`VEBU>os!5y`&ZWSD*S>pg@X*Q zfE~Xkjp*pm8prWB5jYMesrSyufG!_ZGjXDzch)_s**W=XckHNxaXqd}|Kv#rw|%{) z$GwkYb97c>O26u2au$`A43`=13q-0`#c1Y*8S!OP)7s;-oL@?L>L|*!3SFgSO$pI* zmaClTDA_Ye;!s9_nxeC_@J*NM*5 z0Ps1s_pg?>zi11kYmiKBQJ8|MS=1gYu3Hs$0w2n6#AQT1=(Fz?e`x8B~OtI7ZStFsmW(GR%QoZYQ$qLNXjZ9b- z80D;YM^?0nhx4nre~+H<2ipA*#@!b+wD+lt%dci$&nu_cg=c87wRyO)rTSl)+C3~x CIL5vJ literal 0 HcmV?d00001 diff --git a/docs/_build/html/search.html b/docs/_build/html/search.html new file mode 100644 index 0000000..df21b5d --- /dev/null +++ b/docs/_build/html/search.html @@ -0,0 +1,123 @@ + + + + + + + + Search — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/searchindex.js b/docs/_build/html/searchindex.js new file mode 100644 index 0000000..8c31e0a --- /dev/null +++ b/docs/_build/html/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["_include/API_reference","_include/Examples","_include/biapol_utilities.label.compare_labels","_include/biapol_utilities.label.intersection_over_union_matrix","_include/biapol_utilities.label.match_labels_stack","_include/generated/biapol_utilities.data.blobs","_include/generated/biapol_utilities.label.compare_labels","_include/generated/biapol_utilities.label.intersection_over_union_matrix","_include/generated/biapol_utilities.label.match_labels","_include/generated/biapol_utilities.label.match_labels_stack","_include/notebooks/label/Compare_segmentations","_include/notebooks/label/match_labels","_include/notebooks/label/visualize_labels","index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,nbsphinx:3,sphinx:56},filenames:["_include\\API_reference.rst","_include\\Examples.rst","_include\\biapol_utilities.label.compare_labels.rst","_include\\biapol_utilities.label.intersection_over_union_matrix.rst","_include\\biapol_utilities.label.match_labels_stack.rst","_include\\generated\\biapol_utilities.data.blobs.rst","_include\\generated\\biapol_utilities.label.compare_labels.rst","_include\\generated\\biapol_utilities.label.intersection_over_union_matrix.rst","_include\\generated\\biapol_utilities.label.match_labels.rst","_include\\generated\\biapol_utilities.label.match_labels_stack.rst","_include\\notebooks\\label\\Compare_segmentations.ipynb","_include\\notebooks\\label\\match_labels.ipynb","_include\\notebooks\\label\\visualize_labels.ipynb","index.rst"],objects:{"biapol_utilities.data":{blobs:[5,0,1,""]},"biapol_utilities.label":{compare_labels:[6,0,1,""],intersection_over_union_matrix:[7,0,1,""],match_labels:[8,0,1,""],match_labels_stack:[9,0,1,""]}},objnames:{"0":["py","function","Python function"]},objtypes:{"0":"py:function"},terms:{"0":[3,4,7,8,9,10,11,12],"000000":10,"044317":10,"05":10,"06":10,"079653":10,"0x17fe4272220":12,"0x29c86bdabe0":11,"1":[2,3,5,6,7,10,11,12],"10":10,"1000":11,"11":10,"12":10,"128":[10,11,12],"13":10,"181":10,"2":[3,7,10,11,12],"20":10,"25":[4,8,9],"253":10,"254":5,"255":10,"256":5,"262857":10,"2d":[3,4,7,9],"2j":[2,6],"3":[10,11],"324798":10,"386542":10,"39":[10,11],"3d":[4,9],"4":[10,11,12],"400592":10,"415":10,"416290":10,"426":10,"433915":10,"46":10,"465":10,"470130":10,"49":10,"496847":10,"5":[10,11],"513862":10,"518102":10,"538848":10,"554054":10,"560717":10,"567605":10,"58":10,"59":10,"6":[10,11],"60":10,"602546":10,"61":10,"62":10,"623552":10,"63":[10,11],"639576":10,"64":10,"646":10,"65":10,"66":10,"663858":10,"67":10,"68":10,"682566":10,"7":[10,11],"73":10,"751986":10,"768133":10,"780472":10,"785398":10,"8":[10,11],"822705":10,"85":10,"87":10,"878888":10,"9":[10,11],"942191":10,"95":10,"951468":10,"969263":10,"976786":10,"class":0,"default":[4,8,9],"do":10,"float":[3,4,7,8,9],"function":[0,1,4,8,9,13],"import":[10,11,12],"int":[2,3,4,6,7,9],"new":10,"return":[2,3,4,5,6,7,8,9],"true":[3,7,10,11],For:10,It:10,On:13,The:[1,2,3,4,6,7,8,9,13],To:10,_:[2,6],abov:[4,8,9],accept:8,achiev:10,ad:[3,7],agreement:10,all:[1,3,7],along:[3,7],alpha:10,also:10,an:[0,1,3,7,10],annnoot:10,annnot:10,annot:[0,1,10],api:[1,13],append:[10,11],approach:10,ar:[1,3,4,7,8,9,10,11],arang:[10,11],arbitrari:[2,6],area:[3,7,10],arrai:[2,3,4,6,7,8,9,10,11],asarrai:[10,11],assign:[10,11],astyp:[10,11],ax:[10,11],ax_idx:10,axes_grid1:10,axesimag:[11,12],axi:[3,4,7,9,10],background:[3,7,10,11],becaus:[3,7],between:[2,3,6,7,8,10],biao:12,biapol:[0,1],biapol_util:[10,11,12],biau:[10,11],bin:10,bit:10,blob:[10,11,12],blog:13,both:[8,10,11],bottom:10,bundl:[0,1],calcul:10,can:[2,5,6],cbar2:10,cbar:10,certain:10,check:10,chosen:8,clij2:[3,7],clij:[3,7],cmap:[10,12],code:13,color:12,colorbar:10,column:[2,3,6,7,10],com:13,comment:1,compar:[1,2,6,11],compare_label:10,comprehens:13,consid:[4,9],continu:10,convert:11,correct:10,correspond:[2,6,8,10],counterpart:8,creat:[10,11],data:13,datafram:[2,6,10],datetim:11,defin:[2,6],denois:5,depend:10,deriv:[2,6],detail:0,determin:[2,6],di_map:10,dice:[2,6,10],dice_scor:[2,6,10],differ:[2,6],dimens:[2,6],doc:[3,7],docuemnt:[],don:[10,11],duplic:[3,7],e:[0,1],each:[2,3,6,7],eccentr:10,encod:[0,1],enough:0,enumer:10,epyseg:10,equival:[3,7],etc:10,evalu:[2,6],everi:[3,7,10],exampl:[0,5,10,11,13],except:[3,7],expand:10,expand_label:10,f:11,face:10,features_gt:10,features_seg:10,fig:[10,11],figsiz:10,filter:11,find:[3,7],first:[10,11],follow:[2,6],frac:[2,6],from:[2,4,6,8,9,10,11,12],full:0,further:0,gener:[3,7,10],github:[3,7,13],give:[0,3,7],gov:5,grai:5,ground:10,ground_truth:10,group:13,gt:[11,12],guarante:[3,7],guidelin:0,have:[2,6,10],here:1,highest:8,hist:10,histogram:10,how:[3,7,13],http:[3,5,7,13],i:[0,1],idend:[0,1],ident:[4,9,11],idx:10,ij:5,im2:10,im:10,imag:[0,1,2,3,4,5,6,7,8,9,10,11,12],imagea:[8,10,11],imagea_label:11,imageb:[8,11],imageb_label:11,imagej:5,imshow:[10,11,12],includ:[3,7],index:13,inferno_r:10,integ:[0,1],interest:10,intersect:[2,3,6,7,8,10],intersection_over_union_matrix:[4,8,9],io:[3,7,10,11,12,13],iou:[3,4,7,8,9,10],iou_streshold:8,j:[2,6],jaccard:[2,6],jaccard_scor:[2,6,10],ji_map:10,kwarg:[4,8,9],label:13,label_image_i:[2,3,6,7,8],label_image_x:[2,3,6,7,8],label_shuffl:[10,11],label_stack:[4,9],labels_colormap:12,lastli:10,left:10,legend:10,len:10,let:[10,11],level:[1,5],librari:[1,13],likewis:[3,7],list:1,lookup:[3,7],lt:[11,12],lut_dic:10,lut_jaccard:10,mai:[0,10],make_axes_locat:10,map:[10,11,12],mask:[3,4,7,9],match:[1,4,8,9],match_label:[10,11],match_labels_stack:[],matplotlib:[10,11,12],matrix:[3,7],max:[3,7,10,11,12],measur:[2,6,8,10,11,12],method:[4,8,9,10],modul:13,mpl_toolkit:10,ms:11,must:[0,1,2,6],nan:10,ncol:[10,11],nd:[2,3,6,7,8],ndarrai:5,next:10,nih:5,notebook:[10,11],now:11,np:[10,11],nrow:10,number:[0,1,11],numpi:[10,11],object:[0,1],obtain:10,occurr:10,off:10,often:10,one:11,onli:10,oper:[0,1],option:[4,8,9],order:[4,9],orient:10,os:[10,11],our:13,output:11,over:[2,3,6,7,8,10],overlai:10,overlap:[3,7,8,10],page:13,pair:[3,7,8,10],panda:[2,6,10],paramet:[2,3,4,6,7,8,9],pd:10,pipelin:10,pixel:[0,1,10],plantseg:10,pleas:0,plot:10,plt:[10,11],predict:[3,7],preserv:10,print:11,problem:10,process:8,prop:10,properti:10,provid:[0,1,10,12,13],pyplot:[10,11],quantitii:[2,6],random:[10,11],randomli:10,raw:0,reconstruct:[3,7],refer:[1,3,5,7,8,11,13],reference_generatejaccardindexmatrix:[3,7],regionprop:10,regionprops_t:10,relabel:11,relat:[2,6],resembl:11,respect:[2,6],result:10,right:10,row:[2,3,6,7,10],s:[2,6,10,11],same:[2,6,10],scikit:10,score:[2,6,10],script:11,search:13,second:[10,11],section:[0,1],segment:[1,5],serv:8,set:[3,7,10],set_titl:[10,11],set_xlabel:10,set_ylabel:10,shape:10,sharei:[10,11],sharex:[10,11],should:8,shuffl:[10,11],side:10,size:[3,7],skimag:[10,11,12],slice:[4,9],so:[3,7],some:10,sourc:[3,7,13],specif:0,specifi:[4,9],stack:[4,9],standard:12,stardist:10,start:[10,11],stitch:[4,9],stitch_threshold:[4,9],str:[4,8,9],subplot:[10,11],subplots_adjust:10,subsequ:[4,9],subtract:[3,7],sum:[3,7],t0:11,t1:11,t:[10,11],tabl:[3,7],take:10,taken:[3,7],text:[10,11],them:10,thi:[0,1,3,7,10,11,13],threshold:[4,8,9,10,11],through:[2,6],thu:[3,7],time:11,titl:10,to_numpi:10,togeth:[3,7],took:11,top:[1,10],total:[3,7],track:11,truth:10,two:[2,4,6,8,9,11],type:[3,4,5,7,8,9],uint8:[5,10,11],union:[2,3,6,7,8,10],us:[0,4,5,8,9,10,13],usag:1,usedin:[0,1],util:[0,1],valu:[0,1,4,8,9,10],vector:[3,7],version:[8,10,11],visual:[1,10,11],vmax:12,vmin:12,wa:10,want:[10,11],we:[1,10,11,13],where:[3,7],whether:10,which:[0,1,2,4,6,8,9,10,11],wise:[2,6],work:[3,7],wspace:10,x:[3,7],y:[3,7],zero:10,zyx:[4,9]},titles:["API Reference","Examples","biapol_utilities.label.compare_labels","biapol_utilities.label.intersection_over_union_matrix","biapol_utilities.label.match_labels_stack","biapol_utilities.data.blobs","biapol_utilities.label.compare_labels","biapol_utilities.label.intersection_over_union_matrix","biapol_utilities.label.match_labels","biapol_utilities.label.match_labels_stack","Quantitative segmentation quality estimation","Matching labels","Labels visualized in colours","Welcome to BiAPoL utilities\u2019s documentation!"],titleterms:{The:0,api:0,biapol:13,biapol_util:[2,3,4,5,6,7,8,9],blob:5,colour:12,compar:10,compare_label:[2,6],content:13,data:[0,1,5,10,11],document:13,estim:10,exampl:1,featur:10,index:10,indic:13,input:10,intersection_over_union_matrix:[3,7],jaccard:10,label:[0,1,2,3,4,6,7,8,9,10,11,12],labelwis:10,load:11,match:[10,11],match_label:8,match_labels_stack:[4,9],modul:[0,1],qualiti:10,quantit:10,re:10,refer:0,ressourc:13,s:13,segment:10,tabl:13,util:13,visual:12,welcom:13,wise:10}}) \ No newline at end of file From 82c0213b997da336596f54ffafb6ed734cc76c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Tue, 23 Nov 2021 10:02:08 +0100 Subject: [PATCH 14/47] Create .nojekyll --- docs/.nojekyll | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/.nojekyll diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/docs/.nojekyll @@ -0,0 +1 @@ + From 9d18bd315724af28f22da1624f4cf87300120bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Fri, 26 Nov 2021 13:40:02 +0100 Subject: [PATCH 15/47] Added github action to push to doc page --- .github/workflows/build_doc_sphinx.yml | 0 docs/conf.py | 3 +++ 2 files changed, 3 insertions(+) create mode 100644 .github/workflows/build_doc_sphinx.yml diff --git a/.github/workflows/build_doc_sphinx.yml b/.github/workflows/build_doc_sphinx.yml new file mode 100644 index 0000000..e69de29 diff --git a/docs/conf.py b/docs/conf.py index 2ab4f9f..2ef7e28 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -43,6 +43,9 @@ 'sphinx.ext.extlinks' # Link external pages ] +# Autosummary uses a customized module template that was taken from here: +# https://stackoverflow.com/questions/48074094/use-sphinx-autosummary-recursively-to-generate-api-documentation + autosummary_generate = True # Turn on sphinx.ext.autosummary # Add any paths that contain templates here, relative to this directory. From 1fa377f8e2eb5366b5348251b2a699de7f54ef6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 16:47:54 +0100 Subject: [PATCH 16/47] Added automatic build workflow --- .github/workflows/build_doc_sphinx.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/build_doc_sphinx.yml b/.github/workflows/build_doc_sphinx.yml index e69de29..4adbcea 100644 --- a/.github/workflows/build_doc_sphinx.yml +++ b/.github/workflows/build_doc_sphinx.yml @@ -0,0 +1,12 @@ +name: "Pull Request Docs Check" +on: +- pull_request + +jobs: + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: ammaraskar/sphinx-action@master + with: + docs-folder: "docs/" From 4035a9c7e717e585f55fd5b9d1081b8d778e9ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:07:51 +0100 Subject: [PATCH 17/47] Push documentation to separate branch --- .github/workflows/build_doc_sphinx.yml | 29 +++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build_doc_sphinx.yml b/.github/workflows/build_doc_sphinx.yml index 4adbcea..1c2f242 100644 --- a/.github/workflows/build_doc_sphinx.yml +++ b/.github/workflows/build_doc_sphinx.yml @@ -1,12 +1,17 @@ -name: "Pull Request Docs Check" -on: -- pull_request - -jobs: - docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: ammaraskar/sphinx-action@master - with: - docs-folder: "docs/" +- name: Commit documentation changes + run: | + git clone https://github.com/ammaraskar/sphinx-action-test.git --branch gh-pages --single-branch gh-pages + cp -r docs/_build/html/* gh-pages/ + cd gh-pages + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add . + git commit -m "Update documentation" -a || true + # The above command will fail if no changes were present, so we ignore + # the return code. +- name: Push changes + uses: ad-m/github-push-action@master + with: + branch: gh-pages + directory: gh-pages + github_token: ${{ secrets.GITHUB_TOKEN }} From d33672a128362bece591a4ea5a78e56e84341055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:12:26 +0100 Subject: [PATCH 18/47] Update build_doc_sphinx.yml --- .github/workflows/build_doc_sphinx.yml | 29 +++++++++++--------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build_doc_sphinx.yml b/.github/workflows/build_doc_sphinx.yml index 1c2f242..4adbcea 100644 --- a/.github/workflows/build_doc_sphinx.yml +++ b/.github/workflows/build_doc_sphinx.yml @@ -1,17 +1,12 @@ -- name: Commit documentation changes - run: | - git clone https://github.com/ammaraskar/sphinx-action-test.git --branch gh-pages --single-branch gh-pages - cp -r docs/_build/html/* gh-pages/ - cd gh-pages - git config --local user.email "action@github.com" - git config --local user.name "GitHub Action" - git add . - git commit -m "Update documentation" -a || true - # The above command will fail if no changes were present, so we ignore - # the return code. -- name: Push changes - uses: ad-m/github-push-action@master - with: - branch: gh-pages - directory: gh-pages - github_token: ${{ secrets.GITHUB_TOKEN }} +name: "Pull Request Docs Check" +on: +- pull_request + +jobs: + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: ammaraskar/sphinx-action@master + with: + docs-folder: "docs/" From 87481f3de14fa1a539aa24d6c9629d75ea4706d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:25:55 +0100 Subject: [PATCH 19/47] correct test status badge link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7640195..200fbf9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # biapol-utilities [![Python Version](https://img.shields.io/pypi/pyversions/biapol-utilities.svg?color=green)](https://python.org) -[![tests](https://github.com/BiAPoL/biapol-utilities/workflows/tests/badge.svg)](https://github.com/BiAPoL/biapol-utilities/actions) +[![test](https://github.com/BiAPoL/biapol-utilities/actions/workflows/test.yml/badge.svg)](https://github.com/BiAPoL/biapol-utilities/actions/workflows/test.yml) [![Contributors](https://img.shields.io/github/contributors-anon/BiAPoL/biapol-utilities)](https://github.com/BiAPoL/biapol-utilities/graphs/contributors) [![codecov](https://codecov.io/gh/BiAPoL/biapol-utilities/branch/master/graph/badge.svg)](https://codecov.io/gh/BiAPoL/biapol-utilities) [![GitHub stars](https://img.shields.io/github/stars/BiAPoL/biapol-utilities?style=social)](https://github.com/BiAPoL/biapol-utilities/) From a406d8c0eef5233a0c269c68854cf811a79873f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:28:57 +0100 Subject: [PATCH 20/47] added doc badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 200fbf9..3be1899 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![test](https://github.com/BiAPoL/biapol-utilities/actions/workflows/test.yml/badge.svg)](https://github.com/BiAPoL/biapol-utilities/actions/workflows/test.yml) [![Contributors](https://img.shields.io/github/contributors-anon/BiAPoL/biapol-utilities)](https://github.com/BiAPoL/biapol-utilities/graphs/contributors) [![codecov](https://codecov.io/gh/BiAPoL/biapol-utilities/branch/master/graph/badge.svg)](https://codecov.io/gh/BiAPoL/biapol-utilities) -[![GitHub stars](https://img.shields.io/github/stars/BiAPoL/biapol-utilities?style=social)](https://github.com/BiAPoL/biapol-utilities/) +[![Doc build](https://github.com/BiAPoL/biapol-utilities/actions/workflows/build_doc_sphinx.yml/badge.svg)](https://github.com/BiAPoL/biapol-utilities/actions/workflows/build_doc_sphinx.yml) Collection of utility functions from the biapol group at DFG cluster of excellence "Physics of Life" (POL) @ TU Dresden, Dresden, Germany From 7bb7c502891a093c53cac728fd35b51d2b7af57f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:34:00 +0100 Subject: [PATCH 21/47] Create codecov.yml --- .github/workflows/codecov.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/workflows/codecov.yml diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml new file mode 100644 index 0000000..fec72a9 --- /dev/null +++ b/.github/workflows/codecov.yml @@ -0,0 +1,10 @@ +steps: +- uses: actions/checkout@master +- uses: codecov/codecov-action@v2 + with: + token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos + files: ./coverage1.xml,./coverage2.xml # optional + flags: unittests # optional + name: codecov-umbrella # optional + fail_ci_if_error: true # optional (default = false) + verbose: true # optional (default = false) From db31cbaeb8d37fb3ade44aee695bd3afedcece9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:35:47 +0100 Subject: [PATCH 22/47] Update codecov.yml --- .github/workflows/codecov.yml | 44 +++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index fec72a9..f3d853a 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -1,10 +1,34 @@ -steps: -- uses: actions/checkout@master -- uses: codecov/codecov-action@v2 - with: - token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos - files: ./coverage1.xml,./coverage2.xml # optional - flags: unittests # optional - name: codecov-umbrella # optional - fail_ci_if_error: true # optional (default = false) - verbose: true # optional (default = false) +name: Example workflow for Codecov +on: [push] +jobs: + run: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + env: + OS: ${{ matrix.os }} + PYTHON: '3.7' + steps: + - uses: actions/checkout@master + - name: Setup Python + uses: actions/setup-python@master + with: + python-version: 3.7 + - name: Generate coverage report + run: | + pip install pytest + pip install pytest-cov + pytest --cov=./ --cov-report=xml + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + directory: ./coverage/reports/ + env_vars: OS,PYTHON + fail_ci_if_error: true + files: ./coverage1.xml,./coverage2.xml + flags: unittests + name: codecov-umbrella + path_to_write_report: ./coverage/codecov_report.txt + verbose: true From d90d7eec4969725b41a2dd878ceb8ba5514b0e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:36:09 +0100 Subject: [PATCH 23/47] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 3be1899..21f3793 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ [![test](https://github.com/BiAPoL/biapol-utilities/actions/workflows/test.yml/badge.svg)](https://github.com/BiAPoL/biapol-utilities/actions/workflows/test.yml) [![Contributors](https://img.shields.io/github/contributors-anon/BiAPoL/biapol-utilities)](https://github.com/BiAPoL/biapol-utilities/graphs/contributors) [![codecov](https://codecov.io/gh/BiAPoL/biapol-utilities/branch/master/graph/badge.svg)](https://codecov.io/gh/BiAPoL/biapol-utilities) -[![Doc build](https://github.com/BiAPoL/biapol-utilities/actions/workflows/build_doc_sphinx.yml/badge.svg)](https://github.com/BiAPoL/biapol-utilities/actions/workflows/build_doc_sphinx.yml) Collection of utility functions from the biapol group at DFG cluster of excellence "Physics of Life" (POL) @ TU Dresden, Dresden, Germany From 8df54e89b2dea30510668d2d99024d4f581f5bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:38:14 +0100 Subject: [PATCH 24/47] Update codecov.yml --- .github/workflows/codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index f3d853a..f09dcd3 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -1,4 +1,4 @@ -name: Example workflow for Codecov +name: Code coverage on: [push] jobs: run: From 6fb9249320a6dee7ddd2445a850bf8e894c77d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:45:24 +0100 Subject: [PATCH 25/47] Delete codecov.yml --- .github/workflows/codecov.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 .github/workflows/codecov.yml diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml deleted file mode 100644 index f09dcd3..0000000 --- a/.github/workflows/codecov.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Code coverage -on: [push] -jobs: - run: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - env: - OS: ${{ matrix.os }} - PYTHON: '3.7' - steps: - - uses: actions/checkout@master - - name: Setup Python - uses: actions/setup-python@master - with: - python-version: 3.7 - - name: Generate coverage report - run: | - pip install pytest - pip install pytest-cov - pytest --cov=./ --cov-report=xml - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 - with: - token: ${{ secrets.CODECOV_TOKEN }} - directory: ./coverage/reports/ - env_vars: OS,PYTHON - fail_ci_if_error: true - files: ./coverage1.xml,./coverage2.xml - flags: unittests - name: codecov-umbrella - path_to_write_report: ./coverage/codecov_report.txt - verbose: true From b8913495d82e673c976b00083eba283b85a29e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 17:49:11 +0100 Subject: [PATCH 26/47] Update README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 21f3793..f8b0b16 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,14 @@ Collection of utility functions from the biapol group at DFG cluster of excellence "Physics of Life" (POL) @ TU Dresden, Dresden, Germany +## Ressources: + +* Documentation page: https://biapol.github.io/biapol-utilities +* Blog page: https://biapol.github.io/blog/ +* Github: https://github.com/BiAPoL +* Homepage: https://physics-of-life.tu-dresden.de/en/research/core-groups/bio-image-analysis +* Report bugs:https://github.com/BiAPoL/biapol-utilities/issues + ## Acknowledgements Developing biapol-utilities is a community effort. We would like to thank everybody who helped developing and testing. In particular, thanks goes to the contributions of - the developers of cellpose for label-matching functions From b5055f3c435b8c93a168b872d5fc7fc8bb2a991a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 29 Nov 2021 19:23:54 +0100 Subject: [PATCH 27/47] Added nbsphinx to core dependency --- setup.cfg | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 76e5568..75f7e57 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,7 @@ long_description = file: README.md long_description_content_type = text/markdown url = https://github.com/BiAPoL/biapol-utilities.git classifiers = - Development Status :: 2 - Pre-Alpha + Development Status :: 2 - Pre-Alpha Intended Audience :: Developers Topic :: Software Development :: Testing Programming Language :: Python @@ -33,4 +33,5 @@ install_requires = scikit-learn pandas matplotlib - + nbsphinx + From 61a795d2b9ad940dcbd2ac673d4fcfb91cac5deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 29 Nov 2021 19:27:03 +0100 Subject: [PATCH 28/47] added nbsphinx to build command --- .github/workflows/build_doc_sphinx.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_doc_sphinx.yml b/.github/workflows/build_doc_sphinx.yml index 4adbcea..4fa6731 100644 --- a/.github/workflows/build_doc_sphinx.yml +++ b/.github/workflows/build_doc_sphinx.yml @@ -1,5 +1,5 @@ name: "Pull Request Docs Check" -on: +on: - pull_request jobs: @@ -10,3 +10,4 @@ jobs: - uses: ammaraskar/sphinx-action@master with: docs-folder: "docs/" + pre-build-command: "pip install nbsphinx" From c983c77cd46146b2c16f909eebfa886f3042f661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 29 Nov 2021 19:29:02 +0100 Subject: [PATCH 29/47] added pandoc installation to workflow --- .github/workflows/build_doc_sphinx.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_doc_sphinx.yml b/.github/workflows/build_doc_sphinx.yml index 4fa6731..589ec15 100644 --- a/.github/workflows/build_doc_sphinx.yml +++ b/.github/workflows/build_doc_sphinx.yml @@ -10,4 +10,4 @@ jobs: - uses: ammaraskar/sphinx-action@master with: docs-folder: "docs/" - pre-build-command: "pip install nbsphinx" + pre-build-command: "pip install nbsphinx && conda install pandoc" From 5530f9259d2e14f4f6c8c95053e87f28af116be7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 29 Nov 2021 19:30:45 +0100 Subject: [PATCH 30/47] Update build_doc_sphinx.yml --- .github/workflows/build_doc_sphinx.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_doc_sphinx.yml b/.github/workflows/build_doc_sphinx.yml index 589ec15..e101b77 100644 --- a/.github/workflows/build_doc_sphinx.yml +++ b/.github/workflows/build_doc_sphinx.yml @@ -10,4 +10,4 @@ jobs: - uses: ammaraskar/sphinx-action@master with: docs-folder: "docs/" - pre-build-command: "pip install nbsphinx && conda install pandoc" + pre-build-command: "pip install nbsphinx && conda install -c conda-forge pandoc" From 341498df5c78f245c65dc8dc9a07932d595f4422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 29 Nov 2021 19:30:57 +0100 Subject: [PATCH 31/47] Revert "Added nbsphinx to core dependency" This reverts commit b5055f3c435b8c93a168b872d5fc7fc8bb2a991a. --- setup.cfg | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index 75f7e57..76e5568 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,7 @@ long_description = file: README.md long_description_content_type = text/markdown url = https://github.com/BiAPoL/biapol-utilities.git classifiers = - Development Status :: 2 - Pre-Alpha + Development Status :: 2 - Pre-Alpha Intended Audience :: Developers Topic :: Software Development :: Testing Programming Language :: Python @@ -33,5 +33,4 @@ install_requires = scikit-learn pandas matplotlib - nbsphinx - + From 98ce7b9302aa64c2059f4079e0a8dc45b8d0496b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 29 Nov 2021 19:33:17 +0100 Subject: [PATCH 32/47] Delete build_doc_sphinx.yml --- .github/workflows/build_doc_sphinx.yml | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 .github/workflows/build_doc_sphinx.yml diff --git a/.github/workflows/build_doc_sphinx.yml b/.github/workflows/build_doc_sphinx.yml deleted file mode 100644 index e101b77..0000000 --- a/.github/workflows/build_doc_sphinx.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: "Pull Request Docs Check" -on: -- pull_request - -jobs: - docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: ammaraskar/sphinx-action@master - with: - docs-folder: "docs/" - pre-build-command: "pip install nbsphinx && conda install -c conda-forge pandoc" From f32311ac1c360256b2689b2b60440e952db077ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 29 Nov 2021 19:34:40 +0100 Subject: [PATCH 33/47] Create sphinx_build.yml --- .github/workflows/sphinx_build.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/sphinx_build.yml diff --git a/.github/workflows/sphinx_build.yml b/.github/workflows/sphinx_build.yml new file mode 100644 index 0000000..75be680 --- /dev/null +++ b/.github/workflows/sphinx_build.yml @@ -0,0 +1,13 @@ +name: "Pull Request Docs Check" +on: +- pull_request + +jobs: + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: ammaraskar/sphinx-action@master + with: + docs-folder: "docs/" + pre-build-command: "pip install nbsphinx pandoc" From d067a5caa5d5b35a843fad750d556baf588e2535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 29 Nov 2021 19:36:26 +0100 Subject: [PATCH 34/47] added nbsphinx and pandoc to setup --- .github/workflows/sphinx_build.yml | 2 +- setup.cfg | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sphinx_build.yml b/.github/workflows/sphinx_build.yml index 75be680..cfa6065 100644 --- a/.github/workflows/sphinx_build.yml +++ b/.github/workflows/sphinx_build.yml @@ -1,4 +1,4 @@ -name: "Pull Request Docs Check" +name: "Sphinx build" on: - pull_request diff --git a/setup.cfg b/setup.cfg index 76e5568..6a4232c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,7 @@ long_description = file: README.md long_description_content_type = text/markdown url = https://github.com/BiAPoL/biapol-utilities.git classifiers = - Development Status :: 2 - Pre-Alpha + Development Status :: 2 - Pre-Alpha Intended Audience :: Developers Topic :: Software Development :: Testing Programming Language :: Python @@ -33,4 +33,6 @@ install_requires = scikit-learn pandas matplotlib - + pandoc + nbsphinx + From ca24b1f904b8767ee82c314d8cb5529c8d7d010c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 29 Nov 2021 19:39:36 +0100 Subject: [PATCH 35/47] Create requirements.txt --- docs/requirements.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docs/requirements.txt diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..5e6dd28 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,2 @@ +nbsphinx +pandoc \ No newline at end of file From 778521f72b7441b08ced58e69938ad682a7aa46a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 29 Nov 2021 19:49:44 +0100 Subject: [PATCH 36/47] Revert "added nbsphinx and pandoc to setup" This reverts commit d067a5caa5d5b35a843fad750d556baf588e2535. --- .github/workflows/sphinx_build.yml | 2 +- setup.cfg | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/sphinx_build.yml b/.github/workflows/sphinx_build.yml index cfa6065..75be680 100644 --- a/.github/workflows/sphinx_build.yml +++ b/.github/workflows/sphinx_build.yml @@ -1,4 +1,4 @@ -name: "Sphinx build" +name: "Pull Request Docs Check" on: - pull_request diff --git a/setup.cfg b/setup.cfg index 6a4232c..76e5568 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,7 @@ long_description = file: README.md long_description_content_type = text/markdown url = https://github.com/BiAPoL/biapol-utilities.git classifiers = - Development Status :: 2 - Pre-Alpha + Development Status :: 2 - Pre-Alpha Intended Audience :: Developers Topic :: Software Development :: Testing Programming Language :: Python @@ -33,6 +33,4 @@ install_requires = scikit-learn pandas matplotlib - pandoc - nbsphinx - + From e45ad96e234c6d5dbf3ea0b5fe0ae2c96770255e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Mon, 29 Nov 2021 19:49:54 +0100 Subject: [PATCH 37/47] Revert "Create requirements.txt" This reverts commit ca24b1f904b8767ee82c314d8cb5529c8d7d010c. --- docs/requirements.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 docs/requirements.txt diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index 5e6dd28..0000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -nbsphinx -pandoc \ No newline at end of file From 40a6ab929a887343792e6ae2900a4b9d7e1b5332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Mon, 29 Nov 2021 19:50:16 +0100 Subject: [PATCH 38/47] Delete sphinx_build.yml --- .github/workflows/sphinx_build.yml | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 .github/workflows/sphinx_build.yml diff --git a/.github/workflows/sphinx_build.yml b/.github/workflows/sphinx_build.yml deleted file mode 100644 index 75be680..0000000 --- a/.github/workflows/sphinx_build.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: "Pull Request Docs Check" -on: -- pull_request - -jobs: - docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: ammaraskar/sphinx-action@master - with: - docs-folder: "docs/" - pre-build-command: "pip install nbsphinx pandoc" From d450fbcebe4d0be1f1705b2e751dbbf8f08d81a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Tue, 30 Nov 2021 15:06:02 +0100 Subject: [PATCH 39/47] added workflow to push docs to separate branch --- .github/workflows/compile_docs.yml | 37 ++++++++++++++++++++++++++++++ docs/build_environment.yml | 16 +++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 .github/workflows/compile_docs.yml create mode 100644 docs/build_environment.yml diff --git a/.github/workflows/compile_docs.yml b/.github/workflows/compile_docs.yml new file mode 100644 index 0000000..bdbfc89 --- /dev/null +++ b/.github/workflows/compile_docs.yml @@ -0,0 +1,37 @@ +name: Sphinx docs to gh-pages + +# Workflow from: https://github.com/uibcdf/action-sphinx-docs-to-gh-pages + +on: + push: + branches: + - main + +# workflow_dispatch: # Un comment line if you also want to trigger action manually + +jobs: + sphinx_docs_to_gh-pages: + runs-on: ubuntu-latest + name: Sphinx docs to gh-pages + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Make conda environment + uses: conda-incubator/setup-miniconda@v2 + with: + python-version: 3.7 # Python version to build the html sphinx documentation + environment-file: docs/build_environment.yaml # Path to the documentation conda environment + auto-update-conda: false + auto-activate-base: false + show-channel-urls: true + - name: Installing the library + shell: bash -l {0} + run: | + python setup.py install + - name: Running the Sphinx to gh-pages Action + uses: uibcdf/action-sphinx-docs-to-gh-pages@v1.0-beta.2 + with: + branch: main + dir_docs: docs + sphinxopts: '' \ No newline at end of file diff --git a/docs/build_environment.yml b/docs/build_environment.yml new file mode 100644 index 0000000..ba4cf42 --- /dev/null +++ b/docs/build_environment.yml @@ -0,0 +1,16 @@ +name: build_docs + +channels: + + - conda-forge + - defaults + +dependencies: + + - python=3.7 + - sphinx + - sphinx_rtd_theme + - sphinxcontrib-bibtex + - nbsphinx + - pandoc + - sphinx-markdown-tables \ No newline at end of file From 22bd5df7911a678b463234ede4a9dd1c03f7fafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Tue, 30 Nov 2021 15:10:21 +0100 Subject: [PATCH 40/47] Update compile_docs.yml --- .github/workflows/compile_docs.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile_docs.yml b/.github/workflows/compile_docs.yml index bdbfc89..745be70 100644 --- a/.github/workflows/compile_docs.yml +++ b/.github/workflows/compile_docs.yml @@ -3,11 +3,14 @@ name: Sphinx docs to gh-pages # Workflow from: https://github.com/uibcdf/action-sphinx-docs-to-gh-pages on: + pull_request: + branches: + - master push: branches: - main -# workflow_dispatch: # Un comment line if you also want to trigger action manually +workflow_dispatch: # Un comment line if you also want to trigger action manually jobs: sphinx_docs_to_gh-pages: @@ -34,4 +37,4 @@ jobs: with: branch: main dir_docs: docs - sphinxopts: '' \ No newline at end of file + sphinxopts: '' From f7f1da74711049a658851816507367362a10b1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Tue, 30 Nov 2021 15:11:13 +0100 Subject: [PATCH 41/47] Update compile_docs.yml --- .github/workflows/compile_docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile_docs.yml b/.github/workflows/compile_docs.yml index 745be70..34f5eb8 100644 --- a/.github/workflows/compile_docs.yml +++ b/.github/workflows/compile_docs.yml @@ -5,7 +5,7 @@ name: Sphinx docs to gh-pages on: pull_request: branches: - - master + - main push: branches: - main From c2af38c7ceab9ff877695f3f0cc16f8dbf14bd90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Tue, 30 Nov 2021 15:12:34 +0100 Subject: [PATCH 42/47] Update compile_docs.yml --- .github/workflows/compile_docs.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/compile_docs.yml b/.github/workflows/compile_docs.yml index 34f5eb8..eff60c0 100644 --- a/.github/workflows/compile_docs.yml +++ b/.github/workflows/compile_docs.yml @@ -2,13 +2,7 @@ name: Sphinx docs to gh-pages # Workflow from: https://github.com/uibcdf/action-sphinx-docs-to-gh-pages -on: - pull_request: - branches: - - main - push: - branches: - - main +on: [push, pull_request] workflow_dispatch: # Un comment line if you also want to trigger action manually From b427a8466a044e8fd28e4028e609baca49424cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Tue, 30 Nov 2021 15:22:18 +0100 Subject: [PATCH 43/47] removed workflow --- .github/workflows/compile_docs.yml | 34 ------------------------------ docs/build_environment.yml | 16 -------------- 2 files changed, 50 deletions(-) delete mode 100644 .github/workflows/compile_docs.yml delete mode 100644 docs/build_environment.yml diff --git a/.github/workflows/compile_docs.yml b/.github/workflows/compile_docs.yml deleted file mode 100644 index eff60c0..0000000 --- a/.github/workflows/compile_docs.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Sphinx docs to gh-pages - -# Workflow from: https://github.com/uibcdf/action-sphinx-docs-to-gh-pages - -on: [push, pull_request] - -workflow_dispatch: # Un comment line if you also want to trigger action manually - -jobs: - sphinx_docs_to_gh-pages: - runs-on: ubuntu-latest - name: Sphinx docs to gh-pages - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Make conda environment - uses: conda-incubator/setup-miniconda@v2 - with: - python-version: 3.7 # Python version to build the html sphinx documentation - environment-file: docs/build_environment.yaml # Path to the documentation conda environment - auto-update-conda: false - auto-activate-base: false - show-channel-urls: true - - name: Installing the library - shell: bash -l {0} - run: | - python setup.py install - - name: Running the Sphinx to gh-pages Action - uses: uibcdf/action-sphinx-docs-to-gh-pages@v1.0-beta.2 - with: - branch: main - dir_docs: docs - sphinxopts: '' diff --git a/docs/build_environment.yml b/docs/build_environment.yml deleted file mode 100644 index ba4cf42..0000000 --- a/docs/build_environment.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: build_docs - -channels: - - - conda-forge - - defaults - -dependencies: - - - python=3.7 - - sphinx - - sphinx_rtd_theme - - sphinxcontrib-bibtex - - nbsphinx - - pandoc - - sphinx-markdown-tables \ No newline at end of file From d5073b0d2c37637ea5a0abcfba1b32c73ba9af4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Tue, 30 Nov 2021 16:03:01 +0100 Subject: [PATCH 44/47] Added contribution sub-page to documentation pages --- docs/_include/Contribute.rst | 40 ++++++++++++++++++++++++++++++++++++ docs/conf.py | 3 ++- docs/index.rst | 3 ++- 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 docs/_include/Contribute.rst diff --git a/docs/_include/Contribute.rst b/docs/_include/Contribute.rst new file mode 100644 index 0000000..8bff4a3 --- /dev/null +++ b/docs/_include/Contribute.rst @@ -0,0 +1,40 @@ +Contribute +========== + +If you consider contributing to biapol-utilities (thanks in advance!), please follow these guidelines. + +Docstring formatting +----------------------- + +In general, biapol-utilites abides to the numpy docstring standards, as described `here `_. This style is implemented as a docstring template in most Python IDEs (e.g., Spyder, PyCharm, etc.). + +Re-using code +----------------------- + +Biapol-utilities is intented to be a wrapper/collection library for useful image-processing utility functions, that may span several repositories. If you re-use code from third-party libraries (e.g., scikit-image or scikit-learn), please copy the license of the respective (`directory in the repository `_). Feel free to also add sources as footnotes to the docstrings as described `here `_ . + + +Build the documentation +----------------------- + +Prior to submitting pull requests to biapol-utils, make sure to (re-)build the documentation. To do so, you need to install additional packages: + +.. prompt:: bash $ + + pip install sphinx nbsphinx sphinx-prompt + conda install pandoc + +To build the documentation, you need to be in the ``docs/`` folder: + +.. prompt:: bash $ + + cd docs/ + +Generate the html files for the page by running + +.. prompt:: bash $ + + make html + +The documentation will then be generated in the ``_build/html`` directory. This will run all the examples, which may take a while. Upon submitting the pull request, the page will then automatically be built and hosted on github pages once the PR is accepted. + diff --git a/docs/conf.py b/docs/conf.py index 2ef7e28..99000e4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -40,7 +40,8 @@ 'nbsphinx', # link notebooks 'sphinx.ext.autosummary', # Make module lists in table 'sphinx.ext.autosectionlabel', - 'sphinx.ext.extlinks' # Link external pages + 'sphinx.ext.extlinks', # Link external pages + 'sphinx-prompt' ] # Autosummary uses a customized module template that was taken from here: diff --git a/docs/index.rst b/docs/index.rst index 67ee96f..a7df54c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,11 +5,12 @@ On this page, we provide documentation pages for our API and provide comprehensive examples on how to use the functions in our library. .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :caption: Contents: _include/Examples _include/API_reference + _include/Contribute Indices and tables From 121996efc34a1c1b99e23468a01094c8cada6e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Tue, 30 Nov 2021 16:03:11 +0100 Subject: [PATCH 45/47] Rebuilt docs --- .../doctrees/_include/API_reference.doctree | Bin 12402 -> 12578 bytes .../doctrees/_include/Contribute.doctree | Bin 0 -> 11176 bytes .../_build/doctrees/_include/Examples.doctree | Bin 4483 -> 4499 bytes .../biapol_utilities.data.blobs.doctree | Bin 6426 -> 6472 bytes ...pol_utilities.label.compare_labels.doctree | Bin 11610 -> 11656 bytes ...bel.intersection_over_union_matrix.doctree | Bin 12086 -> 12132 bytes ...iapol_utilities.label.match_labels.doctree | Bin 11809 -> 11855 bytes ...utilities.label.match_labels_stack.doctree | Bin 10665 -> 10726 bytes .../label/Compare_segmentations.doctree | Bin 1362681 -> 1362697 bytes .../notebooks/label/match_labels.doctree | Bin 629194 -> 629210 bytes .../notebooks/label/visualize_labels.doctree | Bin 7548 -> 7564 bytes docs/_build/doctrees/environment.pickle | Bin 47486 -> 45848 bytes docs/_build/doctrees/index.doctree | Bin 6858 -> 6901 bytes docs/_build/html/_include/API_reference.html | 11 +- docs/_build/html/_include/Contribute.html | 132 ++++++++++++++++++ docs/_build/html/_include/Examples.html | 7 +- .../biapol_utilities.data.blobs.html | 9 +- ...biapol_utilities.label.compare_labels.html | 7 +- ....label.intersection_over_union_matrix.html | 7 +- .../biapol_utilities.label.match_labels.html | 7 +- ...ol_utilities.label.match_labels_stack.html | 7 +- .../label/Compare_segmentations.html | 11 +- .../notebooks/label/match_labels.html | 7 +- .../notebooks/label/visualize_labels.html | 11 +- .../html/_sources/_include/Contribute.rst.txt | 40 ++++++ docs/_build/html/_sources/index.rst.txt | 3 +- docs/_build/html/genindex.html | 7 +- docs/_build/html/index.html | 14 +- docs/_build/html/objects.inv | Bin 1448 -> 1466 bytes docs/_build/html/search.html | 1 + docs/_build/html/searchindex.js | 2 +- .../biapol_utilities.label.compare_labels.rst | 6 - ...s.label.intersection_over_union_matrix.rst | 6 - ...pol_utilities.label.match_labels_stack.rst | 6 - 34 files changed, 217 insertions(+), 84 deletions(-) create mode 100644 docs/_build/doctrees/_include/Contribute.doctree create mode 100644 docs/_build/html/_include/Contribute.html create mode 100644 docs/_build/html/_sources/_include/Contribute.rst.txt delete mode 100644 docs/_include/biapol_utilities.label.compare_labels.rst delete mode 100644 docs/_include/biapol_utilities.label.intersection_over_union_matrix.rst delete mode 100644 docs/_include/biapol_utilities.label.match_labels_stack.rst diff --git a/docs/_build/doctrees/_include/API_reference.doctree b/docs/_build/doctrees/_include/API_reference.doctree index a87282c83163a34d7d741cfe470db6ebe9714c6f..b6273cf5f32699aa63bb9424e61a39e867204ed7 100644 GIT binary patch delta 740 zcmeyAuqcVOfpx05;YL<}MvEX9s~DI3IRut&U*LN|0uF|(5$ia=k;Y`&m)ks>$9 OOunEfy!nSp6*mA8s2p(s delta 564 zcmZ3K^eKV0fpu!S!A4epMhz!ds~D$D$AEmFn1G`EtkmR^;+Uk&#De@B-O`fGoXnEU z)Z&K{$@6Ib5>Gx7;j#|lgdb%jtahcOhoJ0>?gRMB=b!+ zX9@=qZ$2=bOg5{Ftt8P78;L>^?U0maW+&R$Kv&6ZE>OBik{vRW3zUR6uTZVx1^`xe B%<%vK diff --git a/docs/_build/doctrees/_include/Contribute.doctree b/docs/_build/doctrees/_include/Contribute.doctree new file mode 100644 index 0000000000000000000000000000000000000000..ae32e7c51101f13783be0cf5f7e41effe5d3d5ae GIT binary patch literal 11176 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 a7K|?~$;`xPE delta 59 zcmbQN+^o#fz&f>JBa0iOhOMhrj8mp#K)z2*Kv8~HYH~?&Oj2fIL4J;IX-Q^IW=Uph OaZE~n^5!N+K>+|zq0Uq-El6e|!9svDv(rU0An&F7gXGLfKu@_FW{%~#o6 Fg#ghNLl6J} delta 129 zcmX?MG|PykfpseXMwV_yjVM>E7^h6ffP9~rfTH}Y)Z~)ln54|ag8Ura(vr-a%#zI1 q;+T~DHZ!xk3IPB&4KT+5 diff --git a/docs/_build/doctrees/_include/generated/biapol_utilities.label.compare_labels.doctree b/docs/_build/doctrees/_include/generated/biapol_utilities.label.compare_labels.doctree index cebda2d14182f55bd0be805eca6db86e5dd66429..ab0329883ebb4c7f94493bd0538367f26bc1c6ae 100644 GIT binary patch delta 175 zcmcZ=)e+6oz&f>dBg+~_ixL;B7?=Fy(%jU%lHwSr%*2BHoS1;3{H)YuAm7Nq$S^($ zEEr!}l9`iPl9^f@lailYy!i&B6O-2b6e|!9svDv(rU0An$uBr6H?L!nXCXn)<`*1A FDgYhRLvjEB delta 129 zcmeB(z7@sNz&h1`Bg+~_jTBd_7^h6ffP9~rfTH}Y)Z~)ln54|ag8Ura(vr-a%#zI1 p;+T~D+icfy>DVEur`?;>F002txG1344 diff --git a/docs/_build/doctrees/_include/generated/biapol_utilities.label.match_labels.doctree b/docs/_build/doctrees/_include/generated/biapol_utilities.label.match_labels.doctree index 9c7a619641a95ddd5f956ac702d565a5a288f16c..44130339c2a462cac0bfeb5d40549620f3218139 100644 GIT binary patch delta 175 zcmZ1&b3TTpfpx0OMwVra7DX;rF)sPZrManjCB-pLnTZAYIWYl6`B|ySK)#WIkzsri zSTMe{Br_+oBr~-*CM7?)c=IL3GA6B=DOMmJR5wInOaV6ClV5NaZ@$LzorMHFn_qBR GssI2!Mnoq7 delta 129 zcmX>fvoMCGfpx0bMwVra8cD8JF;1C|0r@^L0Y&*)smUe9F-e(;1^GF;r6rj;nI)O2 p#W5-Q$(tWBmN7|prCLE{V+znzPZr}U-u#v2I}1KVo5i>+RRChSFzx^V diff --git a/docs/_build/doctrees/_include/generated/biapol_utilities.label.match_labels_stack.doctree b/docs/_build/doctrees/_include/generated/biapol_utilities.label.match_labels_stack.doctree index b51620befce82ffae7fb59c9cdd8f8cd50a77481..80f00c5f27d5be527b5c0219feeb23ff3a9d5177 100644 GIT binary patch delta 232 zcmZ1({4AKIfpzNbjV!wvEh=2BVqEf*OLJ56N{VBgG7}5(b7BID^0QKtfqWwaBg6P4 zuwZ;?NoG!FNoHzsOiF%o@#g1@wM<&`Q>;KdsBVbDm;!9NH`lYgXCXoTYQ1iwLaOB-$dN#|Ik=a delta 171 zcmaDByfT=jfpzM#277dT&!YT@{>z*Q}arSW1KP*3-WVf0*dmpQj>vvBLgGD z_$07kd}&E$PG(7FYH>_TesXcM6Jxs*BM37AF*6Xe05K~NvjH(X5OV-AClGT1F*gwN c05LBR^8qnG5DNgYAP@@yvG8^$Mv?6&0a4{H_y7O^ delta 141 zcmeC27W{K+FiQjL)LR=_#27VVT&-f9G93f*ePRNN^0QKtONwKXG7}5(b975fGIKIZ zGE<9VQu33VgBaU`7(ti`h?#+y1&CRJm<@>8ftUk`If0l9h`E872Z(urm=B2gfmi^D R1%X%yh=sQYF^X(I2>{T9DdGSC diff --git a/docs/_build/doctrees/_include/notebooks/label/match_labels.doctree b/docs/_build/doctrees/_include/notebooks/label/match_labels.doctree index e0937f9bc00e963475ecd71ebeb4e87d47f3c411..bffb6881fe8904e98fd1ead45e64b90c0b6bac7b 100644 GIT binary patch delta 113 zcmX@LS?$(lHI@d}sn<8Mh%s6uyI94zh&Am-Ta#K_q(0{|@X BB`g2{ delta 97 zcmcb$S?$zjHI@d}smC|6h%sseyIRFKWjY4r`@{qkF@i7?5HkZY3lOscF&hxG12M<;AV$uP833DvA7%gm diff --git a/docs/_build/doctrees/_include/notebooks/label/visualize_labels.doctree b/docs/_build/doctrees/_include/notebooks/label/visualize_labels.doctree index b01fa40bbad4ff2755d8042712cd37f0c59fca8e..bac2e2753d5307880f2d20ecdf6114a2d890304f 100644 GIT binary patch delta 75 zcmexk)nm=lz&f>YBa0ZLMY@Ysj7xrUX>Mv>NpXx*W@15pPE0^iepYHSkZ)vQWEh_W a7K|?~$;`XBa0ZLM!2h0j8mp#K)z2*Kv8~HYH~?&Oj2fIL4J;IX-Q^IW=Uph OaZE~n^5!5$D;WT8d=(l1 diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle index 2f8711d2f7ddb1587e8a0c73f378a415ea9bf179..6dfaef9ba8f77e6a29330fb3dcde6159e7a287ef 100644 GIT binary patch literal 45848 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

bIeC-U$%VFwe?;ZRRCfB44f9Qpf;Oi*3aa-SD_x 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 ynd1xc- - + @@ -105,18 +105,15 @@

Navigation

Contents:

Related Topics

diff --git a/docs/_build/html/_include/Contribute.html b/docs/_build/html/_include/Contribute.html new file mode 100644 index 0000000..c4f3255 --- /dev/null +++ b/docs/_build/html/_include/Contribute.html @@ -0,0 +1,132 @@ + + + + + + + + + Contribute — BiAPoL utilities 0.0.1 documentation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Contribute

+

If you consider contributing to biapol-utilities (thanks in advance!), please follow these guidelines.

+
+

Docstring formatting

+

In general, biapol-utilites abides to the numpy docstring standards, as described here. This style is implemented as a docstring template in most Python IDEs (e.g., Spyder, PyCharm, etc.).

+
+
+

Re-using code

+

Biapol-utilities is intented to be a wrapper/collection library for useful image-processing utility functions, that may span several repositories. If you re-use code from third-party libraries (e.g., scikit-image or scikit-learn), please copy the license of the respective (directory in the repository). Feel free to also add sources as footnotes to the docstrings as described here .

+
+
+

Build the documentation

+

Prior to submitting pull requests to biapol-utils, make sure to (re-)build the documentation. To do so, you need to install additional packages:

+
pip install sphinx nbsphinx sphinx-prompt
+conda install pandoc
+

To build the documentation, you need to be in the docs/ folder:

+
cd docs/
+

Generate the html files for the page by running

+
make html
+

The documentation will then be generated in the _build/html directory. This will run all the examples, which may take a while. Upon submitting the pull request, the page will then automatically be built and hosted on github pages once the PR is accepted.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_include/Examples.html b/docs/_build/html/_include/Examples.html index 8b56d58..f0950c4 100644 --- a/docs/_build/html/_include/Examples.html +++ b/docs/_build/html/_include/Examples.html @@ -81,12 +81,9 @@

Data moduleContents:

diff --git a/docs/_build/html/_include/generated/biapol_utilities.data.blobs.html b/docs/_build/html/_include/generated/biapol_utilities.data.blobs.html index 9f341f1..f7e92b4 100644 --- a/docs/_build/html/_include/generated/biapol_utilities.data.blobs.html +++ b/docs/_build/html/_include/generated/biapol_utilities.data.blobs.html @@ -17,6 +17,7 @@ + @@ -84,11 +85,8 @@

Navigation

Contents:

@@ -97,6 +95,7 @@

Related Topics

  • Documentation overview
  • diff --git a/docs/_build/html/_include/generated/biapol_utilities.label.compare_labels.html b/docs/_build/html/_include/generated/biapol_utilities.label.compare_labels.html index 7645d7d..2fb1a00 100644 --- a/docs/_build/html/_include/generated/biapol_utilities.label.compare_labels.html +++ b/docs/_build/html/_include/generated/biapol_utilities.label.compare_labels.html @@ -100,11 +100,8 @@

    Navigation

    Contents:

    diff --git a/docs/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html b/docs/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html index f8ddb1d..a98d090 100644 --- a/docs/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html +++ b/docs/_build/html/_include/generated/biapol_utilities.label.intersection_over_union_matrix.html @@ -105,11 +105,8 @@

    Navigation

    Contents:

    diff --git a/docs/_build/html/_include/generated/biapol_utilities.label.match_labels.html b/docs/_build/html/_include/generated/biapol_utilities.label.match_labels.html index 9636ccc..0a0cc43 100644 --- a/docs/_build/html/_include/generated/biapol_utilities.label.match_labels.html +++ b/docs/_build/html/_include/generated/biapol_utilities.label.match_labels.html @@ -96,11 +96,8 @@

    Navigation

    Contents:

    diff --git a/docs/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html b/docs/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html index 011bf14..7b5a46f 100644 --- a/docs/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html +++ b/docs/_build/html/_include/generated/biapol_utilities.label.match_labels_stack.html @@ -90,11 +90,8 @@

    Navigation

    Contents:

    diff --git a/docs/_build/html/_include/notebooks/label/Compare_segmentations.html b/docs/_build/html/_include/notebooks/label/Compare_segmentations.html index 9f45111..66d12fd 100644 --- a/docs/_build/html/_include/notebooks/label/Compare_segmentations.html +++ b/docs/_build/html/_include/notebooks/label/Compare_segmentations.html @@ -19,7 +19,7 @@ - + @@ -5746,12 +5746,9 @@

    Compare-labels: Feature-wiseContents:

    @@ -5760,7 +5757,7 @@

    Related Topics

  • Documentation overview
  • diff --git a/docs/_build/html/_include/notebooks/label/match_labels.html b/docs/_build/html/_include/notebooks/label/match_labels.html index 7ec2864..5fcfd37 100644 --- a/docs/_build/html/_include/notebooks/label/match_labels.html +++ b/docs/_build/html/_include/notebooks/label/match_labels.html @@ -3413,12 +3413,9 @@

    Load dataContents:

    diff --git a/docs/_build/html/_include/notebooks/label/visualize_labels.html b/docs/_build/html/_include/notebooks/label/visualize_labels.html index 4897c53..2603fd2 100644 --- a/docs/_build/html/_include/notebooks/label/visualize_labels.html +++ b/docs/_build/html/_include/notebooks/label/visualize_labels.html @@ -19,6 +19,8 @@ + + @@ -366,15 +368,20 @@

    Labels visualized in coloursContents:

    -
      -
    • Examples
    • + diff --git a/docs/_build/html/_sources/_include/Contribute.rst.txt b/docs/_build/html/_sources/_include/Contribute.rst.txt new file mode 100644 index 0000000..8bff4a3 --- /dev/null +++ b/docs/_build/html/_sources/_include/Contribute.rst.txt @@ -0,0 +1,40 @@ +Contribute +========== + +If you consider contributing to biapol-utilities (thanks in advance!), please follow these guidelines. + +Docstring formatting +----------------------- + +In general, biapol-utilites abides to the numpy docstring standards, as described `here `_. This style is implemented as a docstring template in most Python IDEs (e.g., Spyder, PyCharm, etc.). + +Re-using code +----------------------- + +Biapol-utilities is intented to be a wrapper/collection library for useful image-processing utility functions, that may span several repositories. If you re-use code from third-party libraries (e.g., scikit-image or scikit-learn), please copy the license of the respective (`directory in the repository `_). Feel free to also add sources as footnotes to the docstrings as described `here `_ . + + +Build the documentation +----------------------- + +Prior to submitting pull requests to biapol-utils, make sure to (re-)build the documentation. To do so, you need to install additional packages: + +.. prompt:: bash $ + + pip install sphinx nbsphinx sphinx-prompt + conda install pandoc + +To build the documentation, you need to be in the ``docs/`` folder: + +.. prompt:: bash $ + + cd docs/ + +Generate the html files for the page by running + +.. prompt:: bash $ + + make html + +The documentation will then be generated in the ``_build/html`` directory. This will run all the examples, which may take a while. Upon submitting the pull request, the page will then automatically be built and hosted on github pages once the PR is accepted. + diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt index 67ee96f..a7df54c 100644 --- a/docs/_build/html/_sources/index.rst.txt +++ b/docs/_build/html/_sources/index.rst.txt @@ -5,11 +5,12 @@ On this page, we provide documentation pages for our API and provide comprehensive examples on how to use the functions in our library. .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :caption: Contents: _include/Examples _include/API_reference + _include/Contribute Indices and tables diff --git a/docs/_build/html/genindex.html b/docs/_build/html/genindex.html index 3ffad8f..6428af3 100644 --- a/docs/_build/html/genindex.html +++ b/docs/_build/html/genindex.html @@ -53,7 +53,7 @@

      B

      C

      @@ -61,7 +61,7 @@

      C

      I

      @@ -73,7 +73,7 @@

      M

    @@ -105,6 +105,7 @@

    Navigation

    diff --git a/docs/_build/html/index.html b/docs/_build/html/index.html index 8fb7099..27c3239 100644 --- a/docs/_build/html/index.html +++ b/docs/_build/html/index.html @@ -41,16 +41,9 @@

    Welcome to BiAPoL utilities’s documentation!

    Contents:

    @@ -98,6 +91,7 @@

    Navigation

    diff --git a/docs/_build/html/objects.inv b/docs/_build/html/objects.inv index c84ecea155641e68a3d15e823aa3713108058dff..fb3712d7ad57ec77d2964dd4aee3aa913a89d989 100644 GIT binary patch delta 1356 zcmV-S1+)673%U!Ce}7udj^ri~zVA~Id8C}^)?VkfJDW%o^-8m|E9KIXg>7bghp@LXx^fQLS?@shes7Cv?hCwId zr}zPJXT(&II-t}#~7>1M8u9WX2+9v*3w z#}*2^9lsqgD1XX8mM4`8C9|})dKPMB&z|0pCOmS3oQ-{}n?^`{sHQxKcuo+F!P_xp(#7%BS#>>ege4r_xA&mbu)THhDsj37` z<*@b?!#pbxLK>Mm*zR**mOxQb6yaBNJjHzO4@bo>m4AqciK;Y!;Z4t<7G6vKlXl9q z;H!cWb}c+*w88vqBey#2^i$4kTOA&E^KBW72+T3alkKo>my4TBB9h4A-6U$DBw5@#X`%S-hr@(( zT4gv)6weusgfbjZ`aRnUfo+umW%#jX9I_2Loqv;Hz_BjEjTS+K@0T1Uj1*PR{D`Tv zgQpyEo6i7ej2yc(hlPz^JH@?*4;ZnWmtRPR7dznHbkKiQ(L0SmZFJ;~_$~0@A1Dk_ z8u4rgC2U>D7-6hE>XW}Tl+@sqDOZ*jFbe04(Dc zHh*!u-109r+TLJF@vtz+ODr6`?*LY1(A##qpslUmW>M;Ac%O@!f()FY)Qc&KY~r+^ zqU>sf;@?zoYD_qm_S=1xz9FAGIOgN>OtK=x{={=WNUyW_C_8CG-53FqfRM&CPwg%7 z%3PsA1D6tZG_Dre5$!&g$+NX-DZA^6EPt72 z_j&~1yu-&lFXnM5OO8j&?VNYCwo7@mR<3nsGTQfzESgT3jQ30@WTLR<%~Ky?@ykNJHkUi`QPPUVFKG?foC?a$slx#2nlEmrC~xNz#G!#ROVVSmu9UpHN;8MX2fZPAmQNb_dN`5P#!2R>I#=Fg{_ zCa9`fxuxEUkKBlr8?)H~^q;@}?j4;-@8r1f+(~M>ZY>s2eIK~+sZ%_Xq5MZ2LtGI` zPRXfbJN;XYZ{p*siQ&^3Rt;q~D!+w{W~Fta+ufNR_@dqF{bZ40UoyL!wnb^w^?BM< zeNXA&MWzAEbfuC@8Ad6$rX?%u7fAG>GrWq z0!q>Z`~ZBC1W_5{?GsLLjwlYdhw09nBaI{P2EY#kp$Hvtw0{ZGI72!1`IU*SF*S=; zNkVa6U~b1xUvTc1N%c2IG$(JyDCX5JqGDpf(RL(cC0Z8!f}-G?6T3py+4{CsgEHdh z_z~wg3GgN_C@5%n%Xx=XJuCO9N1NxZPSlYeYOH6Q4?sMkc6#d?R_l?>-lEu zfTEeT-CSB=9l5z=#*v!~3#xYDDJ;;ysH+QCrXoo039Fuv_k{Ik<$3@NVZ8US>F)6> z4Vx~Em4+gxth@7EvH!>eI5CqMl-99`sPAOcPqRES|LsAYVLH{jb~Cp9o2B~} zuDeeBZGSlxi=e$kG2p;Gr)7Z?3hR9e1b0K}rc`h^l$S0V^hiXDDK;P@RnkZspenh% zGiQ{HUB=;gF4?ie^Tt+mc(IZ-WvPv-8$;;U)vYlVziyptHyq{_ujO#8Rr@9>#fLQg zR&2Szw#k4B{1oGaqH2*YHY7VGhY82}8a|C`;D6!!wL}ReRnrSAF{S(9xkL=}3E+Z~ zm^YbW^tvhTEqug?mhAeK6xiAU?^93v&$9O3O(5TN_MPh|+?OHYsbxV(^}3b8-2$paa5<_~2jFtj&AKoSt7QCjBuNW3~%IBR2z6Rfq_ z!1Q)=isyac%i}OL6wQ1Le#a4;jTq1r{C`M3-lsdzZs^|^AWVa@oloCM`q<(bl7MAP zCL|*!3SFgSO$pI*maClTDA_Ye z;!s9_nxeC_@J*NM*50Ps1s_pg(f*--Ggw460kp+L*MI;#y3l{HnX<>sZmuhWt)ENYs#CP6@QQo9(Q|iLr4V ziQ()7n;UiVC7y+dX6f!ixBC-4vP`kl`&lEQyk-VE?^3<%bIA(K)s0M86*Cy+tanFN ww26oFtGIuUp700S{Se087d5o^sf)|6W?s)Lr`UyOXtA|Navigation

    diff --git a/docs/_build/html/searchindex.js b/docs/_build/html/searchindex.js index 8c31e0a..444ca94 100644 --- a/docs/_build/html/searchindex.js +++ b/docs/_build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["_include/API_reference","_include/Examples","_include/biapol_utilities.label.compare_labels","_include/biapol_utilities.label.intersection_over_union_matrix","_include/biapol_utilities.label.match_labels_stack","_include/generated/biapol_utilities.data.blobs","_include/generated/biapol_utilities.label.compare_labels","_include/generated/biapol_utilities.label.intersection_over_union_matrix","_include/generated/biapol_utilities.label.match_labels","_include/generated/biapol_utilities.label.match_labels_stack","_include/notebooks/label/Compare_segmentations","_include/notebooks/label/match_labels","_include/notebooks/label/visualize_labels","index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,nbsphinx:3,sphinx:56},filenames:["_include\\API_reference.rst","_include\\Examples.rst","_include\\biapol_utilities.label.compare_labels.rst","_include\\biapol_utilities.label.intersection_over_union_matrix.rst","_include\\biapol_utilities.label.match_labels_stack.rst","_include\\generated\\biapol_utilities.data.blobs.rst","_include\\generated\\biapol_utilities.label.compare_labels.rst","_include\\generated\\biapol_utilities.label.intersection_over_union_matrix.rst","_include\\generated\\biapol_utilities.label.match_labels.rst","_include\\generated\\biapol_utilities.label.match_labels_stack.rst","_include\\notebooks\\label\\Compare_segmentations.ipynb","_include\\notebooks\\label\\match_labels.ipynb","_include\\notebooks\\label\\visualize_labels.ipynb","index.rst"],objects:{"biapol_utilities.data":{blobs:[5,0,1,""]},"biapol_utilities.label":{compare_labels:[6,0,1,""],intersection_over_union_matrix:[7,0,1,""],match_labels:[8,0,1,""],match_labels_stack:[9,0,1,""]}},objnames:{"0":["py","function","Python function"]},objtypes:{"0":"py:function"},terms:{"0":[3,4,7,8,9,10,11,12],"000000":10,"044317":10,"05":10,"06":10,"079653":10,"0x17fe4272220":12,"0x29c86bdabe0":11,"1":[2,3,5,6,7,10,11,12],"10":10,"1000":11,"11":10,"12":10,"128":[10,11,12],"13":10,"181":10,"2":[3,7,10,11,12],"20":10,"25":[4,8,9],"253":10,"254":5,"255":10,"256":5,"262857":10,"2d":[3,4,7,9],"2j":[2,6],"3":[10,11],"324798":10,"386542":10,"39":[10,11],"3d":[4,9],"4":[10,11,12],"400592":10,"415":10,"416290":10,"426":10,"433915":10,"46":10,"465":10,"470130":10,"49":10,"496847":10,"5":[10,11],"513862":10,"518102":10,"538848":10,"554054":10,"560717":10,"567605":10,"58":10,"59":10,"6":[10,11],"60":10,"602546":10,"61":10,"62":10,"623552":10,"63":[10,11],"639576":10,"64":10,"646":10,"65":10,"66":10,"663858":10,"67":10,"68":10,"682566":10,"7":[10,11],"73":10,"751986":10,"768133":10,"780472":10,"785398":10,"8":[10,11],"822705":10,"85":10,"87":10,"878888":10,"9":[10,11],"942191":10,"95":10,"951468":10,"969263":10,"976786":10,"class":0,"default":[4,8,9],"do":10,"float":[3,4,7,8,9],"function":[0,1,4,8,9,13],"import":[10,11,12],"int":[2,3,4,6,7,9],"new":10,"return":[2,3,4,5,6,7,8,9],"true":[3,7,10,11],For:10,It:10,On:13,The:[1,2,3,4,6,7,8,9,13],To:10,_:[2,6],abov:[4,8,9],accept:8,achiev:10,ad:[3,7],agreement:10,all:[1,3,7],along:[3,7],alpha:10,also:10,an:[0,1,3,7,10],annnoot:10,annnot:10,annot:[0,1,10],api:[1,13],append:[10,11],approach:10,ar:[1,3,4,7,8,9,10,11],arang:[10,11],arbitrari:[2,6],area:[3,7,10],arrai:[2,3,4,6,7,8,9,10,11],asarrai:[10,11],assign:[10,11],astyp:[10,11],ax:[10,11],ax_idx:10,axes_grid1:10,axesimag:[11,12],axi:[3,4,7,9,10],background:[3,7,10,11],becaus:[3,7],between:[2,3,6,7,8,10],biao:12,biapol:[0,1],biapol_util:[10,11,12],biau:[10,11],bin:10,bit:10,blob:[10,11,12],blog:13,both:[8,10,11],bottom:10,bundl:[0,1],calcul:10,can:[2,5,6],cbar2:10,cbar:10,certain:10,check:10,chosen:8,clij2:[3,7],clij:[3,7],cmap:[10,12],code:13,color:12,colorbar:10,column:[2,3,6,7,10],com:13,comment:1,compar:[1,2,6,11],compare_label:10,comprehens:13,consid:[4,9],continu:10,convert:11,correct:10,correspond:[2,6,8,10],counterpart:8,creat:[10,11],data:13,datafram:[2,6,10],datetim:11,defin:[2,6],denois:5,depend:10,deriv:[2,6],detail:0,determin:[2,6],di_map:10,dice:[2,6,10],dice_scor:[2,6,10],differ:[2,6],dimens:[2,6],doc:[3,7],docuemnt:[],don:[10,11],duplic:[3,7],e:[0,1],each:[2,3,6,7],eccentr:10,encod:[0,1],enough:0,enumer:10,epyseg:10,equival:[3,7],etc:10,evalu:[2,6],everi:[3,7,10],exampl:[0,5,10,11,13],except:[3,7],expand:10,expand_label:10,f:11,face:10,features_gt:10,features_seg:10,fig:[10,11],figsiz:10,filter:11,find:[3,7],first:[10,11],follow:[2,6],frac:[2,6],from:[2,4,6,8,9,10,11,12],full:0,further:0,gener:[3,7,10],github:[3,7,13],give:[0,3,7],gov:5,grai:5,ground:10,ground_truth:10,group:13,gt:[11,12],guarante:[3,7],guidelin:0,have:[2,6,10],here:1,highest:8,hist:10,histogram:10,how:[3,7,13],http:[3,5,7,13],i:[0,1],idend:[0,1],ident:[4,9,11],idx:10,ij:5,im2:10,im:10,imag:[0,1,2,3,4,5,6,7,8,9,10,11,12],imagea:[8,10,11],imagea_label:11,imageb:[8,11],imageb_label:11,imagej:5,imshow:[10,11,12],includ:[3,7],index:13,inferno_r:10,integ:[0,1],interest:10,intersect:[2,3,6,7,8,10],intersection_over_union_matrix:[4,8,9],io:[3,7,10,11,12,13],iou:[3,4,7,8,9,10],iou_streshold:8,j:[2,6],jaccard:[2,6],jaccard_scor:[2,6,10],ji_map:10,kwarg:[4,8,9],label:13,label_image_i:[2,3,6,7,8],label_image_x:[2,3,6,7,8],label_shuffl:[10,11],label_stack:[4,9],labels_colormap:12,lastli:10,left:10,legend:10,len:10,let:[10,11],level:[1,5],librari:[1,13],likewis:[3,7],list:1,lookup:[3,7],lt:[11,12],lut_dic:10,lut_jaccard:10,mai:[0,10],make_axes_locat:10,map:[10,11,12],mask:[3,4,7,9],match:[1,4,8,9],match_label:[10,11],match_labels_stack:[],matplotlib:[10,11,12],matrix:[3,7],max:[3,7,10,11,12],measur:[2,6,8,10,11,12],method:[4,8,9,10],modul:13,mpl_toolkit:10,ms:11,must:[0,1,2,6],nan:10,ncol:[10,11],nd:[2,3,6,7,8],ndarrai:5,next:10,nih:5,notebook:[10,11],now:11,np:[10,11],nrow:10,number:[0,1,11],numpi:[10,11],object:[0,1],obtain:10,occurr:10,off:10,often:10,one:11,onli:10,oper:[0,1],option:[4,8,9],order:[4,9],orient:10,os:[10,11],our:13,output:11,over:[2,3,6,7,8,10],overlai:10,overlap:[3,7,8,10],page:13,pair:[3,7,8,10],panda:[2,6,10],paramet:[2,3,4,6,7,8,9],pd:10,pipelin:10,pixel:[0,1,10],plantseg:10,pleas:0,plot:10,plt:[10,11],predict:[3,7],preserv:10,print:11,problem:10,process:8,prop:10,properti:10,provid:[0,1,10,12,13],pyplot:[10,11],quantitii:[2,6],random:[10,11],randomli:10,raw:0,reconstruct:[3,7],refer:[1,3,5,7,8,11,13],reference_generatejaccardindexmatrix:[3,7],regionprop:10,regionprops_t:10,relabel:11,relat:[2,6],resembl:11,respect:[2,6],result:10,right:10,row:[2,3,6,7,10],s:[2,6,10,11],same:[2,6,10],scikit:10,score:[2,6,10],script:11,search:13,second:[10,11],section:[0,1],segment:[1,5],serv:8,set:[3,7,10],set_titl:[10,11],set_xlabel:10,set_ylabel:10,shape:10,sharei:[10,11],sharex:[10,11],should:8,shuffl:[10,11],side:10,size:[3,7],skimag:[10,11,12],slice:[4,9],so:[3,7],some:10,sourc:[3,7,13],specif:0,specifi:[4,9],stack:[4,9],standard:12,stardist:10,start:[10,11],stitch:[4,9],stitch_threshold:[4,9],str:[4,8,9],subplot:[10,11],subplots_adjust:10,subsequ:[4,9],subtract:[3,7],sum:[3,7],t0:11,t1:11,t:[10,11],tabl:[3,7],take:10,taken:[3,7],text:[10,11],them:10,thi:[0,1,3,7,10,11,13],threshold:[4,8,9,10,11],through:[2,6],thu:[3,7],time:11,titl:10,to_numpi:10,togeth:[3,7],took:11,top:[1,10],total:[3,7],track:11,truth:10,two:[2,4,6,8,9,11],type:[3,4,5,7,8,9],uint8:[5,10,11],union:[2,3,6,7,8,10],us:[0,4,5,8,9,10,13],usag:1,usedin:[0,1],util:[0,1],valu:[0,1,4,8,9,10],vector:[3,7],version:[8,10,11],visual:[1,10,11],vmax:12,vmin:12,wa:10,want:[10,11],we:[1,10,11,13],where:[3,7],whether:10,which:[0,1,2,4,6,8,9,10,11],wise:[2,6],work:[3,7],wspace:10,x:[3,7],y:[3,7],zero:10,zyx:[4,9]},titles:["API Reference","Examples","biapol_utilities.label.compare_labels","biapol_utilities.label.intersection_over_union_matrix","biapol_utilities.label.match_labels_stack","biapol_utilities.data.blobs","biapol_utilities.label.compare_labels","biapol_utilities.label.intersection_over_union_matrix","biapol_utilities.label.match_labels","biapol_utilities.label.match_labels_stack","Quantitative segmentation quality estimation","Matching labels","Labels visualized in colours","Welcome to BiAPoL utilities\u2019s documentation!"],titleterms:{The:0,api:0,biapol:13,biapol_util:[2,3,4,5,6,7,8,9],blob:5,colour:12,compar:10,compare_label:[2,6],content:13,data:[0,1,5,10,11],document:13,estim:10,exampl:1,featur:10,index:10,indic:13,input:10,intersection_over_union_matrix:[3,7],jaccard:10,label:[0,1,2,3,4,6,7,8,9,10,11,12],labelwis:10,load:11,match:[10,11],match_label:8,match_labels_stack:[4,9],modul:[0,1],qualiti:10,quantit:10,re:10,refer:0,ressourc:13,s:13,segment:10,tabl:13,util:13,visual:12,welcom:13,wise:10}}) \ No newline at end of file +Search.setIndex({docnames:["_include/API_reference","_include/Contribute","_include/Examples","_include/generated/biapol_utilities.data.blobs","_include/generated/biapol_utilities.label.compare_labels","_include/generated/biapol_utilities.label.intersection_over_union_matrix","_include/generated/biapol_utilities.label.match_labels","_include/generated/biapol_utilities.label.match_labels_stack","_include/notebooks/label/Compare_segmentations","_include/notebooks/label/match_labels","_include/notebooks/label/visualize_labels","index"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,nbsphinx:3,sphinx:56},filenames:["_include\\API_reference.rst","_include\\Contribute.rst","_include\\Examples.rst","_include\\generated\\biapol_utilities.data.blobs.rst","_include\\generated\\biapol_utilities.label.compare_labels.rst","_include\\generated\\biapol_utilities.label.intersection_over_union_matrix.rst","_include\\generated\\biapol_utilities.label.match_labels.rst","_include\\generated\\biapol_utilities.label.match_labels_stack.rst","_include\\notebooks\\label\\Compare_segmentations.ipynb","_include\\notebooks\\label\\match_labels.ipynb","_include\\notebooks\\label\\visualize_labels.ipynb","index.rst"],objects:{"biapol_utilities.data":{blobs:[3,0,1,""]},"biapol_utilities.label":{compare_labels:[4,0,1,""],intersection_over_union_matrix:[5,0,1,""],match_labels:[6,0,1,""],match_labels_stack:[7,0,1,""]}},objnames:{"0":["py","function","Python function"]},objtypes:{"0":"py:function"},terms:{"0":[5,6,7,8,9,10],"000000":8,"044317":8,"05":8,"06":8,"079653":8,"0x17fe4272220":10,"0x29c86bdabe0":9,"1":[3,4,5,8,9,10],"10":8,"1000":9,"11":8,"12":8,"128":[8,9,10],"13":8,"181":8,"2":[5,8,9,10],"20":8,"25":[6,7],"253":8,"254":3,"255":8,"256":3,"262857":8,"2d":[5,7],"2j":4,"3":[8,9],"324798":8,"386542":8,"39":[8,9],"3d":7,"4":[8,9,10],"400592":8,"415":8,"416290":8,"426":8,"433915":8,"46":8,"465":8,"470130":8,"49":8,"496847":8,"5":[8,9],"513862":8,"518102":8,"538848":8,"554054":8,"560717":8,"567605":8,"58":8,"59":8,"6":[8,9],"60":8,"602546":8,"61":8,"62":8,"623552":8,"63":[8,9],"639576":8,"64":8,"646":8,"65":8,"66":8,"663858":8,"67":8,"68":8,"682566":8,"7":[8,9],"73":8,"751986":8,"768133":8,"780472":8,"785398":8,"8":[8,9],"822705":8,"85":8,"87":8,"878888":8,"9":[8,9],"942191":8,"95":8,"951468":8,"969263":8,"976786":8,"class":0,"default":[6,7],"do":[1,8],"float":[5,6,7],"function":[0,1,2,6,7,11],"import":[8,9,10],"int":[4,5,7],"new":8,"return":[3,4,5,6,7],"true":[5,8,9],"while":1,For:8,If:1,In:1,It:8,On:11,The:[1,2,4,5,6,7],To:[1,8],_:4,_build:1,abid:1,abov:[6,7],accept:[1,6],achiev:8,ad:5,add:1,addit:1,additional:[],advanc:1,agreement:8,all:[1,2,5],along:5,alpha:8,also:[1,8],an:[0,2,5,8],annnoot:8,annnot:8,annot:[0,2,8],api:[2,11],append:[8,9],approach:8,ar:[2,5,6,7,8,9],arang:[8,9],arbitrari:4,area:[5,8],arrai:[4,5,6,7,8,9],asarrai:[8,9],assign:[8,9],astyp:[8,9],automat:1,ax:[8,9],ax_idx:8,axes_grid1:8,axesimag:[9,10],axi:[5,7,8],background:[5,8,9],becaus:5,between:[4,5,6,8],biao:10,biapol:[0,1,2],biapol_util:[8,9,10],biau:[8,9],bin:8,bit:8,blob:[8,9,10],blog:11,both:[6,8,9],bottom:8,build:[],built:1,bundl:[0,2],calcul:8,can:[3,4],cbar2:8,cbar:8,cd:1,certain:8,check:8,chosen:6,clij2:5,clij:5,cmap:[8,10],code:11,cokela:[],collect:1,color:10,colorbar:8,column:[4,5,8],com:11,comment:2,compar:[2,4,9],compare_label:8,comprehens:11,conda:1,consid:[1,7],continu:8,contribut:11,convert:9,copi:1,correct:8,correspond:[4,6,8],counterpart:6,creat:[8,9],data:[],datafram:[4,8],datetim:9,defin:4,denois:3,depend:8,deriv:4,describ:1,detail:0,determin:4,di_map:8,dice:[4,8],dice_scor:[4,8],differ:4,dimens:4,directori:1,doc:[1,5],docstr:[],docuemnt:[],don:[8,9],duplic:5,e:[0,1,2],each:[4,5],eccentr:8,en:[],encod:[0,2],enough:0,enumer:8,epyseg:8,equival:5,etc:[1,8],evalu:4,everi:[5,8],exampl:[0,1,3,8,9,11],except:5,expand:8,expand_label:8,f:9,face:8,features_gt:8,features_seg:8,feel:1,fig:[8,9],figsiz:8,file:1,filter:9,find:5,first:[8,9],folder:1,follow:[1,4],footnot:1,format:[],frac:4,free:1,from:[1,4,6,7,8,9,10],full:0,further:0,g:1,gener:[1,5,8],github:[1,5,11],give:[0,5],gov:3,grai:3,ground:8,ground_truth:8,group:11,gt:[9,10],guarante:5,guideli:[],guidelin:[0,1],have:[4,8],here:[1,2],highest:6,hist:8,histogram:8,host:1,how:[5,11],html:1,http:[3,5,11],i:[0,2],id:1,idend:[0,2],ident:[7,9],idx:8,ij:3,im2:8,im:8,imag:[0,1,2,3,4,5,6,7,8,9,10],imagea:[6,8,9],imagea_label:9,imageb:[6,9],imageb_label:9,imagej:3,implement:1,imshow:[8,9,10],includ:5,index:11,inferno_r:8,info:[],instal:1,integ:[0,2],intent:1,interest:8,intersect:[4,5,6,8],intersection_over_union_matrix:[6,7],io:[5,8,9,10,11],iou:[5,6,7,8],iou_streshold:6,j:4,jaccard:4,jaccard_scor:[4,8],ji_map:8,kwarg:[6,7],label:[],label_image_i:[4,5,6],label_image_x:[4,5,6],label_shuffl:[8,9],label_stack:7,labels_colormap:10,lastli:8,latest:[],learn:1,left:8,legend:8,len:8,let:[8,9],level:[2,3],librari:[1,2,11],licens:1,license_thirdparti:[],likewis:5,list:2,lookup:5,lt:[9,10],lut_dic:8,lut_jaccard:8,mai:[0,1,8],make:1,make_axes_locat:8,map:[8,9,10],mask:[5,7],match:[2,6,7],match_label:[8,9],match_labels_stack:[],matplotlib:[8,9,10],matrix:5,max:[5,8,9,10],measur:[4,6,8,9,10],method:[6,7,8],modul:11,most:1,mpl_toolkit:8,ms:9,must:[0,2,4],nan:8,nbsphinx:1,ncol:[8,9],nd:[4,5,6],ndarrai:3,need:1,next:8,nih:3,notebook:[8,9],now:9,np:[8,9],nrow:8,number:[0,2,9],numpi:[1,8,9],numpydoc:[],object:[0,2],obtain:8,occurr:8,off:8,often:8,onc:1,one:9,onli:8,oper:[0,2],option:[6,7],order:7,orient:8,os:[8,9],our:11,output:9,over:[4,5,6,8],overlai:8,overlap:[5,6,8],packag:1,page:[1,11],pair:[5,6,8],panda:[4,8],pandoc:1,paramet:[4,5,6,7],parti:1,pd:8,pip:1,pipelin:8,pixel:[0,2,8],plantseg:8,pleas:[0,1],plot:8,plt:[8,9],pr:1,predict:5,preserv:8,print:9,prior:1,problem:8,process:[1,6],prompt:1,prop:8,properti:8,provid:[0,2,8,10,11],pull:1,pycharm:1,pyplot:[8,9],python:1,quantitii:4,random:[8,9],randomli:8,raw:0,re:[],readthedoc:[],reconstruct:5,refer:[2,3,5,6,9,11],reference_generatejaccardindexmatrix:5,regionprop:8,regionprops_t:8,relabel:9,relat:4,repositori:1,request:1,resembl:9,respect:[1,4],rest_syntax:[],result:8,right:8,row:[4,5,8],run:1,s:[4,8,9],same:[4,8],scikit:[1,8],score:[4,8],script:9,search:11,second:[8,9],section:[0,2],segment:[2,3],serv:6,set:[5,8],set_titl:[8,9],set_xlabel:8,set_ylabel:8,sever:1,shape:8,sharei:[8,9],sharex:[8,9],should:6,shuffl:[8,9],side:8,size:5,skimag:[8,9,10],slice:7,so:[1,5],some:8,sourc:[1,5,11],span:1,specif:0,specifi:7,sphinx:1,spyder:1,stack:7,standard:[1,10],stardist:8,start:[8,9],stitch:7,stitch_threshold:7,str:[6,7],style:1,submit:1,subplot:[8,9],subplots_adjust:8,subsequ:7,subtract:5,sum:5,sure:1,t0:9,t1:9,t:[8,9],tabl:5,take:[1,8],taken:5,templat:1,text:[8,9],thank:1,them:8,thi:[0,1,2,5,8,9,11],third:1,thoma:[],threshold:[6,7,8,9],through:4,thu:5,time:9,titl:8,to_numpi:8,togeth:5,took:9,top:[2,8],total:5,track:9,tree:[],truth:8,tutori:[],two:[4,6,7,9],type:[3,5,6,7],uint8:[3,8,9],union:[4,5,6,8],upon:1,us:[0,3,6,7,8,11],usag:2,usedin:[0,2],util:[0,1,2],utilit:1,valu:[0,2,6,7,8],vector:5,version:[6,8,9],visual:[2,8,9],vmax:10,vmin:10,wa:8,want:[8,9],we:[2,8,9,11],where:5,whether:8,which:[0,1,2,4,6,7,8,9],wise:4,work:5,wrapper:1,wspace:8,x:5,y:5,you:1,zero:8,zyx:7},titles:["API Reference","Contribute","Examples","biapol_utilities.data.blobs","biapol_utilities.label.compare_labels","biapol_utilities.label.intersection_over_union_matrix","biapol_utilities.label.match_labels","biapol_utilities.label.match_labels_stack","Quantitative segmentation quality estimation","Matching labels","Labels visualized in colours","Welcome to BiAPoL utilities\u2019s documentation!"],titleterms:{The:0,api:0,biapol:11,biapol_util:[3,4,5,6,7],blob:3,build:1,code:1,colour:10,compar:8,compare_label:4,content:11,contribut:1,data:[0,2,3,8,9],docstr:1,document:[1,11],estim:8,exampl:2,featur:8,format:1,index:8,indic:11,input:8,intersection_over_union_matrix:5,jaccard:8,label:[0,2,4,5,6,7,8,9,10],labelwis:8,load:9,match:[8,9],match_label:6,match_labels_stack:7,modul:[0,2],qualiti:8,quantit:8,re:[1,8],refer:0,ressourc:11,s:11,segment:8,tabl:11,us:1,util:11,visual:10,welcom:11,wise:8}}) \ No newline at end of file diff --git a/docs/_include/biapol_utilities.label.compare_labels.rst b/docs/_include/biapol_utilities.label.compare_labels.rst deleted file mode 100644 index 286bf6d..0000000 --- a/docs/_include/biapol_utilities.label.compare_labels.rst +++ /dev/null @@ -1,6 +0,0 @@ -biapol\_utilities.label.compare\_labels -======================================= - -.. currentmodule:: biapol_utilities.label - -.. autofunction:: compare_labels \ No newline at end of file diff --git a/docs/_include/biapol_utilities.label.intersection_over_union_matrix.rst b/docs/_include/biapol_utilities.label.intersection_over_union_matrix.rst deleted file mode 100644 index 3b66942..0000000 --- a/docs/_include/biapol_utilities.label.intersection_over_union_matrix.rst +++ /dev/null @@ -1,6 +0,0 @@ -biapol\_utilities.label.intersection\_over\_union\_matrix -========================================================= - -.. currentmodule:: biapol_utilities.label - -.. autofunction:: intersection_over_union_matrix \ No newline at end of file diff --git a/docs/_include/biapol_utilities.label.match_labels_stack.rst b/docs/_include/biapol_utilities.label.match_labels_stack.rst deleted file mode 100644 index 2f71b54..0000000 --- a/docs/_include/biapol_utilities.label.match_labels_stack.rst +++ /dev/null @@ -1,6 +0,0 @@ -biapol\_utilities.label.match\_labels\_stack -============================================ - -.. currentmodule:: biapol_utilities.label - -.. autofunction:: match_labels_stack \ No newline at end of file From 60517b7fc24eab79591caa1c8707633a87cb98c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Tue, 30 Nov 2021 16:08:16 +0100 Subject: [PATCH 46/47] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f8b0b16..e8ee4ea 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Collection of utility functions from the biapol group at DFG cluster of excellen * Github: https://github.com/BiAPoL * Homepage: https://physics-of-life.tu-dresden.de/en/research/core-groups/bio-image-analysis * Report bugs:https://github.com/BiAPoL/biapol-utilities/issues +* Contribute: https://biapol.github.io/biapol-utilities/_build/html/_include/Contribute.html ## Acknowledgements Developing biapol-utilities is a community effort. We would like to thank everybody who helped developing and testing. In particular, thanks goes to the contributions of From 8909eceb882d1633b255bc8cb90f3b8668dd36d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <38459088+jo-mueller@users.noreply.github.com> Date: Tue, 30 Nov 2021 16:10:22 +0100 Subject: [PATCH 47/47] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 39c1120..fa4e5cb 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -23,3 +23,4 @@ * [ ] My change is the minimal possible work for the desired feature/fix * [ ] I updated the documentation where necessary to cover the change +* [ ] I rebuilt the documentation page to document the change, if necessary