diff --git a/SK_ring-relabelling-secondattempt.ipynb b/SK_ring-relabelling-secondattempt.ipynb
index bfbe813..3d7219a 100644
--- a/SK_ring-relabelling-secondattempt.ipynb
+++ b/SK_ring-relabelling-secondattempt.ipynb
@@ -52,7 +52,7 @@
"outputs": [],
"source": [
"import numpy as np\n",
- "from scipy import linalg\n",
+ "from scipy import linalg, sparse\n",
"from mpl_toolkits.mplot3d import Axes3D\n",
"import matplotlib.pyplot as plt\n",
"import cv2\n",
@@ -402,138 +402,138 @@
"output_type": "stream",
"text": [
"trying shift by -20 pmt columns\n",
- "image 801 has reduced yaw error from 25.534564070251704 to -21.934994502088838\n",
+ "image 801 has reduced yaw error from 25.534564070251655 to -21.93499450208874\n",
"trying shift by -16 pmt columns\n",
- "image 801 has reduced yaw error from 25.534564070251704 to -11.638805107025306\n",
+ "image 801 has reduced yaw error from 25.534564070251655 to -11.638805107025407\n",
"trying shift by -12 pmt columns\n",
- "image 792 has reduced yaw error from 14.869267113523073 to -13.929434613176237\n",
- "image 800 has reduced yaw error from 17.79011388762643 to -11.11299060962441\n",
- "image 801 has reduced yaw error from 25.534564070251704 to -2.5828689006216994\n",
- "image 901 has reduced yaw error from 16.88525102662485 to -11.61049137305415\n",
+ "image 792 has reduced yaw error from 14.869267113523073 to -13.929434613176287\n",
+ "image 800 has reduced yaw error from 17.79011388762643 to -11.112990609624687\n",
+ "image 801 has reduced yaw error from 25.534564070251655 to -2.5828689006212926\n",
+ "image 901 has reduced yaw error from 16.88525102662485 to -11.610491373054382\n",
"trying shift by -8 pmt columns\n",
- "image 788 has reduced yaw error from 15.564220899694183 to -6.457165387096472\n",
- "image 791 has reduced yaw error from 12.548390511040258 to -6.089132751112064\n",
- "image 792 has reduced yaw error from 14.869267113523073 to -5.089431404768282\n",
- "image 793 has reduced yaw error from 12.03422669051545 to -6.681564332362487\n",
- "image 794 has reduced yaw error from 14.07930665890146 to -5.240368375612933\n",
- "image 795 has reduced yaw error from 12.728290912476995 to -6.441755830408477\n",
- "image 796 has reduced yaw error from 14.466774585053194 to -4.549337492763155\n",
- "image 797 has reduced yaw error from 11.759535955204232 to -7.209335153884957\n",
- "image 798 has reduced yaw error from 18.798585444158483 to -11.902804694198567\n",
- "image 799 has reduced yaw error from 14.576661098634967 to -5.195391742530237\n",
- "image 800 has reduced yaw error from 17.79011388762643 to -1.3336718201144266\n",
- "image 801 has reduced yaw error from 25.534564070251704 to 7.105197019874885\n",
- "image 901 has reduced yaw error from 16.88525102662485 to -2.7235447288878456\n",
- "image 902 has reduced yaw error from 12.268083204891818 to -6.168140158035983\n",
- "image 903 has reduced yaw error from 12.935193475098343 to -7.86710412719839\n",
+ "image 788 has reduced yaw error from 15.564220899694183 to -6.457165387097693\n",
+ "image 791 has reduced yaw error from 12.548390511040258 to -6.089132751112268\n",
+ "image 792 has reduced yaw error from 14.869267113523073 to -5.089431404768028\n",
+ "image 793 has reduced yaw error from 12.03422669051545 to -6.681564332362334\n",
+ "image 794 has reduced yaw error from 14.07930665890146 to -5.240368375612831\n",
+ "image 795 has reduced yaw error from 12.728290912476995 to -6.441755830408375\n",
+ "image 796 has reduced yaw error from 14.466774585053194 to -4.54933749276285\n",
+ "image 797 has reduced yaw error from 11.759535955204232 to -7.209335153885261\n",
+ "image 798 has reduced yaw error from 18.798585444158483 to -11.902804694198823\n",
+ "image 799 has reduced yaw error from 14.576661098634967 to -5.195391742530618\n",
+ "image 800 has reduced yaw error from 17.79011388762643 to -1.3336718201145794\n",
+ "image 801 has reduced yaw error from 25.534564070251655 to 7.105197019874682\n",
+ "image 901 has reduced yaw error from 16.88525102662485 to -2.723544728887642\n",
+ "image 902 has reduced yaw error from 12.268083204891818 to -6.168140158035958\n",
+ "image 903 has reduced yaw error from 12.935193475098343 to -7.867104127198415\n",
"trying shift by -4 pmt columns\n",
- "image 761 has reduced yaw error from 9.30112544770821 to -0.35049228325057175\n",
- "image 762 has reduced yaw error from 5.3375145732522755 to -3.8808238269710715\n",
- "image 786 has reduced yaw error from 6.392813797382068 to -2.795172181506747\n",
- "image 787 has reduced yaw error from 8.444697705952972 to -1.7768025015562394\n",
- "image 788 has reduced yaw error from 15.564220899694183 to 2.9247321886789055\n",
- "image 790 has reduced yaw error from 9.623939372048554 to 0.3375224599607775\n",
- "image 791 has reduced yaw error from 12.548390511040258 to 3.246094160841288\n",
- "image 792 has reduced yaw error from 14.869267113523073 to 5.332909106495658\n",
- "image 793 has reduced yaw error from 12.03422669051545 to 1.9717774124038068\n",
- "image 794 has reduced yaw error from 14.07930665890146 to 4.195452541882016\n",
- "image 795 has reduced yaw error from 12.728290912476995 to -2.228829475686343\n",
- "image 796 has reduced yaw error from 14.466774585053194 to 4.970430127682494\n",
- "image 797 has reduced yaw error from 11.759535955204232 to 1.647307996142614\n",
- "image 798 has reduced yaw error from 18.798585444158483 to -2.912578325286001\n",
- "image 799 has reduced yaw error from 14.576661098634967 to 4.295629687400236\n",
- "image 800 has reduced yaw error from 17.79011388762643 to 7.974090527465735\n",
- "image 801 has reduced yaw error from 25.534564070251704 to 16.759710594154686\n",
- "image 901 has reduced yaw error from 16.88525102662485 to 7.245055581358396\n",
- "image 902 has reduced yaw error from 12.268083204891818 to 3.2155426509939313\n",
- "image 903 has reduced yaw error from 12.935193475098343 to 1.6445283340622998\n",
+ "image 761 has reduced yaw error from 9.30112544770821 to -0.3504922832506481\n",
+ "image 762 has reduced yaw error from 5.3375145732522755 to -3.880823826971122\n",
+ "image 786 has reduced yaw error from 6.392813797382068 to -2.7951721815065436\n",
+ "image 787 has reduced yaw error from 8.444697705952972 to -1.776802501555934\n",
+ "image 788 has reduced yaw error from 15.564220899694183 to 2.924732188678855\n",
+ "image 790 has reduced yaw error from 9.623939372048554 to 0.33752245996072666\n",
+ "image 791 has reduced yaw error from 12.548390511040258 to 3.2460941608411353\n",
+ "image 792 has reduced yaw error from 14.869267113523073 to 5.33290910649576\n",
+ "image 793 has reduced yaw error from 12.03422669051545 to 1.971777412404163\n",
+ "image 794 has reduced yaw error from 14.07930665890146 to 4.1954525418822195\n",
+ "image 795 has reduced yaw error from 12.728290912476995 to -2.228829475686241\n",
+ "image 796 has reduced yaw error from 14.466774585053194 to 4.970430127682596\n",
+ "image 797 has reduced yaw error from 11.759535955204232 to 1.6473079961425123\n",
+ "image 798 has reduced yaw error from 18.798585444158483 to -2.912578325285187\n",
+ "image 799 has reduced yaw error from 14.576661098634967 to 4.295629687400338\n",
+ "image 800 has reduced yaw error from 17.79011388762643 to 7.97409052746543\n",
+ "image 801 has reduced yaw error from 25.534564070251655 to 16.759710594154534\n",
+ "image 901 has reduced yaw error from 16.88525102662485 to 7.245055581358599\n",
+ "image 902 has reduced yaw error from 12.268083204891818 to 3.215542650994237\n",
+ "image 903 has reduced yaw error from 12.935193475098343 to 1.6445283340621728\n",
"trying shift by 0 pmt columns\n",
- "image 755 has reduced yaw error from -0.8733408316600104 to -0.8113443500277746\n",
- "image 756 has reduced yaw error from -2.206310049943644 to -2.1711641468427385\n",
- "image 757 has reduced yaw error from -3.9486105703258785 to -3.8601596864757135\n",
- "image 759 has reduced yaw error from 1.5448980440476894 to 1.5173562963412721\n",
- "image 760 has reduced yaw error from -0.9048894730781343 to -0.7079178341951331\n",
- "image 761 has reduced yaw error from 9.30112544770821 to 9.258495486193825\n",
- "image 765 has reduced yaw error from 0.9720725289686496 to 0.9021502151679314\n",
- "image 770 has reduced yaw error from -6.06865366148957 to -5.65677400006745\n",
- "image 772 has reduced yaw error from 0.36406020614971357 to 0.2703696487224636\n",
- "image 774 has reduced yaw error from -0.9957703639144924 to -0.8015841333587035\n",
- "image 777 has reduced yaw error from -1.2359467482922037 to -1.0911778019043779\n",
- "image 778 has reduced yaw error from 0.736533679267461 to 0.5446979258296363\n",
- "image 779 has reduced yaw error from 2.9529519959647037 to 2.394660246786599\n",
- "image 780 has reduced yaw error from -4.093534042396289 to -3.3750144318589443\n",
+ "image 755 has reduced yaw error from -0.8733408316599849 to -0.8113443500275965\n",
+ "image 756 has reduced yaw error from -2.206310049943644 to -2.171164146842535\n",
+ "image 757 has reduced yaw error from -3.9486105703258785 to -3.8601596864758916\n",
+ "image 759 has reduced yaw error from 1.5448980440476894 to 1.5173562963413738\n",
+ "image 760 has reduced yaw error from -0.9048894730781343 to -0.7079178341952094\n",
+ "image 761 has reduced yaw error from 9.30112544770821 to 9.258495486193977\n",
+ "image 765 has reduced yaw error from 0.9720725289686496 to 0.9021502151678296\n",
+ "image 770 has reduced yaw error from -6.06865366148957 to -5.656774000067678\n",
+ "image 772 has reduced yaw error from 0.36406020614971357 to 0.2703696487224127\n",
+ "image 774 has reduced yaw error from -0.9957703639144924 to -0.8015841333586526\n",
+ "image 777 has reduced yaw error from -1.2359467482922037 to -1.0911778019041742\n",
+ "image 778 has reduced yaw error from 0.736533679267461 to 0.544697925829509\n",
+ "image 779 has reduced yaw error from 2.9529519959647037 to 2.3946602467868536\n",
+ "image 780 has reduced yaw error from -4.093534042396289 to -3.3750144318588933\n",
"image 783 has reduced yaw error from 3.718673297236211 to 1.3484422816264277\n",
- "image 784 has reduced yaw error from -0.35249692348878453 to 0.16045257397332618\n",
- "image 785 has reduced yaw error from 4.0119729660922285 to 3.852979706835748\n",
- "image 788 has reduced yaw error from 15.564220899694183 to 14.14351986061233\n",
- "image 793 has reduced yaw error from 12.03422669051545 to 11.873932229276773\n",
- "image 795 has reduced yaw error from 12.728290912476995 to 12.666579828776431\n",
- "image 797 has reduced yaw error from 11.759535955204232 to 11.706651656871612\n",
- "image 798 has reduced yaw error from 18.798585444158483 to 5.939572169526795\n",
- "image 799 has reduced yaw error from 14.576661098634967 to 13.975177638478932\n",
- "image 901 has reduced yaw error from 16.88525102662485 to 16.75158533362732\n",
- "image 903 has reduced yaw error from 12.935193475098343 to 11.57223984414676\n",
+ "image 784 has reduced yaw error from -0.35249692348878453 to 0.16045257397363152\n",
+ "image 785 has reduced yaw error from 4.0119729660922285 to 3.8529797068357987\n",
+ "image 788 has reduced yaw error from 15.564220899694183 to 14.143519860611821\n",
+ "image 793 has reduced yaw error from 12.03422669051545 to 11.873932229276875\n",
+ "image 795 has reduced yaw error from 12.728290912476995 to 12.666579828776788\n",
+ "image 797 has reduced yaw error from 11.759535955204232 to 11.706651656870898\n",
+ "image 798 has reduced yaw error from 18.798585444158483 to 5.939572169527304\n",
+ "image 799 has reduced yaw error from 14.576661098634967 to 13.97517763847878\n",
+ "image 901 has reduced yaw error from 16.88525102662485 to 16.75158533362722\n",
+ "image 903 has reduced yaw error from 12.935193475098343 to 11.572239844147118\n",
"trying shift by 4 pmt columns\n",
- "image 758 has reduced yaw error from -6.008549540172706 to 3.5824859202839403\n",
+ "image 758 has reduced yaw error from -6.008549540172706 to 3.5824859202842965\n",
"image 768 has reduced yaw error from -5.3072449824569485 to 4.218475724871712\n",
- "image 769 has reduced yaw error from -6.748155619138371 to -0.06053580951269085\n",
- "image 770 has reduced yaw error from -6.06865366148957 to 3.820397274540782\n",
- "image 771 has reduced yaw error from -5.963350067710753 to 2.7258821754416203\n",
- "image 798 has reduced yaw error from 18.798585444158483 to 16.258825719054528\n",
+ "image 769 has reduced yaw error from -6.748155619138371 to -0.06053580951258908\n",
+ "image 770 has reduced yaw error from -6.06865366148957 to 3.820397274540833\n",
+ "image 771 has reduced yaw error from -5.963350067710753 to 2.7258821754412894\n",
+ "image 798 has reduced yaw error from 18.798585444158483 to 16.25882571905412\n",
"trying shift by 8 pmt columns\n",
"trying shift by 12 pmt columns\n",
"trying shift by 16 pmt columns\n",
"final shifts:\n",
- "image 755: 0 from -0.8733408316600104 to -0.8113443500277746\n",
- "image 756: 0 from -2.206310049943644 to -2.1711641468427385\n",
- "image 757: 0 from -3.9486105703258785 to -3.8601596864757135\n",
- "image 758: 4 from -6.008549540172706 to 3.5824859202839403\n",
- "image 759: 0 from 1.5448980440476894 to 1.5173562963412721\n",
- "image 760: 0 from -0.9048894730781343 to -0.7079178341951331\n",
- "image 761: -4 from 9.30112544770821 to -0.35049228325057175\n",
- "image 762: -4 from 5.3375145732522755 to -3.8808238269710715\n",
+ "image 755: 0 from -0.8733408316599849 to -0.8113443500275965\n",
+ "image 756: 0 from -2.206310049943644 to -2.171164146842535\n",
+ "image 757: 0 from -3.9486105703258785 to -3.8601596864758916\n",
+ "image 758: 4 from -6.008549540172706 to 3.5824859202842965\n",
+ "image 759: 0 from 1.5448980440476894 to 1.5173562963413738\n",
+ "image 760: 0 from -0.9048894730781343 to -0.7079178341952094\n",
+ "image 761: -4 from 9.30112544770821 to -0.3504922832506481\n",
+ "image 762: -4 from 5.3375145732522755 to -3.880823826971122\n",
"image 763: 0 from 3.8499068523592404 to 3.8499068523592404\n",
"image 764: 0 from 1.3533676148311151 to 1.3533676148311151\n",
- "image 765: 0 from 0.9720725289686496 to 0.9021502151679314\n",
+ "image 765: 0 from 0.9720725289686496 to 0.9021502151678296\n",
"image 766: 0 from -1.3300971262351167 to -1.3300971262351167\n",
- "image 767: 0 from -2.2198435986523015 to -2.2198435986523015\n",
+ "image 767: 0 from -2.219843598652276 to -2.219843598652276\n",
"image 768: 4 from -5.3072449824569485 to 4.218475724871712\n",
- "image 769: 4 from -6.748155619138371 to -0.06053580951269085\n",
- "image 770: 4 from -6.06865366148957 to 3.820397274540782\n",
- "image 771: 4 from -5.963350067710753 to 2.7258821754416203\n",
- "image 772: 0 from 0.36406020614971357 to 0.2703696487224636\n",
+ "image 769: 4 from -6.748155619138371 to -0.06053580951258908\n",
+ "image 770: 4 from -6.06865366148957 to 3.820397274540833\n",
+ "image 771: 4 from -5.963350067710753 to 2.7258821754412894\n",
+ "image 772: 0 from 0.36406020614971357 to 0.2703696487224127\n",
"image 773: 0 from -0.05209309978998264 to -0.05209309978998264\n",
- "image 774: 0 from -0.9957703639144924 to -0.8015841333587035\n",
- "image 775: 0 from 1.2005478491241859 to 1.2005478491241859\n",
+ "image 774: 0 from -0.9957703639144924 to -0.8015841333586526\n",
+ "image 775: 0 from 1.2005478491241606 to 1.2005478491241606\n",
"image 776: 0 from 0.0 to 0.0\n",
- "image 777: 0 from -1.2359467482922037 to -1.0911778019043779\n",
- "image 778: 0 from 0.736533679267461 to 0.5446979258296363\n",
- "image 779: 0 from 2.9529519959647037 to 2.394660246786599\n",
- "image 780: 0 from -4.093534042396289 to -3.3750144318589443\n",
+ "image 777: 0 from -1.2359467482922037 to -1.0911778019041742\n",
+ "image 778: 0 from 0.736533679267461 to 0.544697925829509\n",
+ "image 779: 0 from 2.9529519959647037 to 2.3946602467868536\n",
+ "image 780: 0 from -4.093534042396289 to -3.3750144318588933\n",
"image 781: 0 from -1.5219803255064384 to -1.5219803255064384\n",
"image 782: 0 from 2.0939359187515483 to 2.0939359187515483\n",
"image 783: 0 from 3.718673297236211 to 1.3484422816264277\n",
- "image 784: 0 from -0.35249692348878453 to 0.16045257397332618\n",
- "image 785: 0 from 4.0119729660922285 to 3.852979706835748\n",
- "image 786: -4 from 6.392813797382068 to -2.795172181506747\n",
- "image 787: -4 from 8.444697705952972 to -1.7768025015562394\n",
- "image 788: -4 from 15.564220899694183 to 2.9247321886789055\n",
+ "image 784: 0 from -0.35249692348878453 to 0.16045257397363152\n",
+ "image 785: 0 from 4.0119729660922285 to 3.8529797068357987\n",
+ "image 786: -4 from 6.392813797382068 to -2.7951721815065436\n",
+ "image 787: -4 from 8.444697705952972 to -1.776802501555934\n",
+ "image 788: -4 from 15.564220899694183 to 2.924732188678855\n",
"image 789: 0 from -1.7575510813935526 to -1.7575510813935526\n",
- "image 790: -4 from 9.623939372048554 to 0.3375224599607775\n",
- "image 791: -4 from 12.548390511040258 to 3.246094160841288\n",
- "image 792: -8 from 14.869267113523073 to -5.089431404768282\n",
- "image 793: -4 from 12.03422669051545 to 1.9717774124038068\n",
- "image 794: -4 from 14.07930665890146 to 4.195452541882016\n",
- "image 795: -4 from 12.728290912476995 to -2.228829475686343\n",
- "image 796: -8 from 14.466774585053194 to -4.549337492763155\n",
- "image 797: -4 from 11.759535955204232 to 1.647307996142614\n",
- "image 798: -4 from 18.798585444158483 to -2.912578325286001\n",
- "image 799: -4 from 14.576661098634967 to 4.295629687400236\n",
- "image 800: -8 from 17.79011388762643 to -1.3336718201144266\n",
- "image 801: -12 from 25.534564070251704 to -2.5828689006216994\n",
- "image 901: -8 from 16.88525102662485 to -2.7235447288878456\n",
- "image 902: -4 from 12.268083204891818 to 3.2155426509939313\n",
- "image 903: -4 from 12.935193475098343 to 1.6445283340622998\n",
+ "image 790: -4 from 9.623939372048554 to 0.33752245996072666\n",
+ "image 791: -4 from 12.548390511040258 to 3.2460941608411353\n",
+ "image 792: -8 from 14.869267113523073 to -5.089431404768028\n",
+ "image 793: -4 from 12.03422669051545 to 1.971777412404163\n",
+ "image 794: -4 from 14.07930665890146 to 4.1954525418822195\n",
+ "image 795: -4 from 12.728290912476995 to -2.228829475686241\n",
+ "image 796: -8 from 14.466774585053194 to -4.54933749276285\n",
+ "image 797: -4 from 11.759535955204232 to 1.6473079961425123\n",
+ "image 798: -4 from 18.798585444158483 to -2.912578325285187\n",
+ "image 799: -4 from 14.576661098634967 to 4.295629687400338\n",
+ "image 800: -8 from 17.79011388762643 to -1.3336718201145794\n",
+ "image 801: -12 from 25.534564070251655 to -2.5828689006212926\n",
+ "image 901: -8 from 16.88525102662485 to -2.723544728887642\n",
+ "image 902: -4 from 12.268083204891818 to 3.215542650994237\n",
+ "image 903: -4 from 12.935193475098343 to 1.6445283340621728\n",
"image 904: 0 from 1.0654016218004685 to 1.0654016218004685\n"
]
}
@@ -565,7 +565,7 @@
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": 272,
"metadata": {},
"outputs": [],
"source": [
@@ -576,12 +576,16 @@
"\n",
"new_image_feature_locations['796'] = shift_labels(image_feature_locations['796'], -4) # automated relabelling suggested -8\n",
"\n",
- "new_image_feature_locations['799'] = shift_labels(image_feature_locations['799'], -6) # automated relabelling suggested -4, image looks like off by half supermodule\n"
+ "new_image_feature_locations['799'] = shift_labels(image_feature_locations['799'], -6) # automated relabelling suggested -4, image looks like off by half supermodule\n",
+ "\n",
+ "\n",
+ "\n",
+ "new_image_feature_locations['758'] = shift_labels(image_feature_locations['758'], 4) # automated relabelling suggested 4\n"
]
},
{
"cell_type": "code",
- "execution_count": 22,
+ "execution_count": 273,
"metadata": {},
"outputs": [],
"source": [
@@ -593,7 +597,7 @@
},
{
"cell_type": "code",
- "execution_count": 23,
+ "execution_count": 274,
"metadata": {
"pycharm": {
"is_executing": false,
@@ -628,7 +632,7 @@
},
{
"cell_type": "code",
- "execution_count": 24,
+ "execution_count": 249,
"metadata": {
"scrolled": false
},
@@ -883,6 +887,10 @@
" '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",
@@ -1140,11 +1148,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -1154,7 +1165,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -1273,10 +1284,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -1284,18 +1295,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -1320,7 +1330,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -1330,6 +1340,19 @@
" // 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",
@@ -1340,8 +1363,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -1594,7 +1623,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -1872,6 +1901,10 @@
" '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",
@@ -2129,11 +2162,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -2143,7 +2179,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -2262,10 +2298,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -2273,18 +2309,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -2309,7 +2344,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -2319,6 +2354,19 @@
" // 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",
@@ -2329,8 +2377,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -2612,7 +2666,7 @@
},
{
"cell_type": "code",
- "execution_count": 26,
+ "execution_count": 275,
"metadata": {},
"outputs": [
{
@@ -2638,7 +2692,7 @@
},
{
"cell_type": "code",
- "execution_count": 27,
+ "execution_count": 276,
"metadata": {
"pycharm": {
"is_executing": false
@@ -2650,57 +2704,57 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "image 0 reprojection errors: average:8.18390110876233 max: 24.940922334112226\n",
- "image 1 reprojection errors: average:5.805743311708305 max: 22.544199450115567\n",
- "image 2 reprojection errors: average:5.3932973825051 max: 17.746577796705097\n",
- "image 3 reprojection errors: average:9.249812619087006 max: 25.373555736715026\n",
- "image 4 reprojection errors: average:5.244403216477963 max: 26.30564049317777\n",
- "image 5 reprojection errors: average:5.442937098672511 max: 16.872318415315487\n",
- "image 6 reprojection errors: average:6.918473151842166 max: 32.00865423247106\n",
- "image 7 reprojection errors: average:6.535620723727593 max: 16.060733950131045\n",
- "image 8 reprojection errors: average:7.30100908490715 max: 27.14384362948084\n",
- "image 9 reprojection errors: average:8.041999905102857 max: 34.83824420274272\n",
- "image 10 reprojection errors: average:6.370255934425072 max: 20.10736496295024\n",
- "image 11 reprojection errors: average:6.887148773826209 max: 17.42767041281086\n",
- "image 12 reprojection errors: average:8.210569329964082 max: 26.585739470838494\n",
- "image 13 reprojection errors: average:6.39000960408589 max: 21.94211596885494\n",
- "image 14 reprojection errors: average:14.92900993644056 max: 30.31644632771952\n",
- "image 15 reprojection errors: average:7.097952944178674 max: 22.56536442999593\n",
- "image 16 reprojection errors: average:5.265234583168665 max: 17.417982326469886\n",
- "image 17 reprojection errors: average:5.252303406542907 max: 14.665181214138517\n",
- "image 18 reprojection errors: average:4.5200875154681555 max: 15.488591658253304\n",
- "image 19 reprojection errors: average:3.8739597282077156 max: 9.085935192378928\n",
- "image 20 reprojection errors: average:7.2513561632222805 max: 20.43400454194171\n",
- "image 21 reprojection errors: average:8.541820698222 max: 27.833814655175075\n",
- "image 22 reprojection errors: average:6.146747172907711 max: 15.61413459452357\n",
- "image 23 reprojection errors: average:4.88815583046527 max: 9.838168750394386\n",
- "image 24 reprojection errors: average:6.597261143243092 max: 19.43094723324123\n",
- "image 25 reprojection errors: average:4.062229166866455 max: 9.577115766033314\n",
- "image 26 reprojection errors: average:7.006709711877225 max: 17.976745856756295\n",
- "image 27 reprojection errors: average:7.615443569136982 max: 36.58264882365775\n",
- "image 28 reprojection errors: average:5.5658802495709825 max: 9.301873799033457\n",
- "image 29 reprojection errors: average:5.9226348773873 max: 21.646447530851813\n",
- "image 30 reprojection errors: average:6.447495264341781 max: 17.016725069353175\n",
- "image 31 reprojection errors: average:6.536835698748838 max: 21.629916614670336\n",
- "image 32 reprojection errors: average:5.538457374020163 max: 11.369721689674806\n",
- "image 33 reprojection errors: average:10.562864979598398 max: 44.49949437981786\n",
- "image 34 reprojection errors: average:9.906919655829332 max: 17.523899418061323\n",
- "image 35 reprojection errors: average:10.383395341200721 max: 19.371239749071695\n",
- "image 36 reprojection errors: average:10.90387585914992 max: 20.348652989508036\n",
- "image 37 reprojection errors: average:8.979812978701283 max: 21.428894394790177\n",
- "image 38 reprojection errors: average:12.82523134923746 max: 31.577812486117022\n",
- "image 39 reprojection errors: average:6.15677626549432 max: 21.514457392846346\n",
- "image 40 reprojection errors: average:31.72552517041376 max: 75.66715182174264\n",
- "image 41 reprojection errors: average:9.038105751756841 max: 29.701301540679278\n",
- "image 42 reprojection errors: average:2.9410401045486756 max: 6.641734089086367\n",
- "image 43 reprojection errors: average:6.2533880951232135 max: 11.10074038258666\n",
- "image 44 reprojection errors: average:4.920868359688668 max: 13.629635865637965\n",
- "image 45 reprojection errors: average:5.087970321241018 max: 11.127710112224214\n",
- "image 46 reprojection errors: average:4.214466769179211 max: 8.109655893746073\n",
- "image 47 reprojection errors: average:6.392564533301369 max: 20.021508272517355\n",
- "image 48 reprojection errors: average:5.787761900683224 max: 11.217884191587995\n",
- "image 49 reprojection errors: average:4.880935428336551 max: 9.281954054415156\n",
- "image 50 reprojection errors: average:5.893760543568564 max: 23.75724130874825\n"
+ "image 0 reprojection errors: average:8.18390110876375 max: 24.94092233411413\n",
+ "image 1 reprojection errors: average:5.8057433117079595 max: 22.54419945011449\n",
+ "image 2 reprojection errors: average:5.3932973825052315 max: 17.746577796702898\n",
+ "image 3 reprojection errors: average:9.249812619087974 max: 25.373555736717968\n",
+ "image 4 reprojection errors: average:5.244403216475949 max: 26.30564049317514\n",
+ "image 5 reprojection errors: average:5.442937098671642 max: 16.872318415314282\n",
+ "image 6 reprojection errors: average:6.91847315184272 max: 32.00865423247497\n",
+ "image 7 reprojection errors: average:6.535620723727753 max: 16.060733950136335\n",
+ "image 8 reprojection errors: average:7.301009084916339 max: 27.143843629499244\n",
+ "image 9 reprojection errors: average:8.041999905103376 max: 34.838244202745926\n",
+ "image 10 reprojection errors: average:6.37025593442635 max: 20.107364962952094\n",
+ "image 11 reprojection errors: average:6.887148773823956 max: 17.427670412805366\n",
+ "image 12 reprojection errors: average:8.210569329963937 max: 26.585739470833815\n",
+ "image 13 reprojection errors: average:6.39000960408542 max: 21.942115968856132\n",
+ "image 14 reprojection errors: average:14.929009936442187 max: 30.316446327719635\n",
+ "image 15 reprojection errors: average:7.097952944178554 max: 22.565364429994716\n",
+ "image 16 reprojection errors: average:5.2652345831695495 max: 17.417982326467932\n",
+ "image 17 reprojection errors: average:5.252303406543003 max: 14.665181214135375\n",
+ "image 18 reprojection errors: average:4.520087515467902 max: 15.48859165825143\n",
+ "image 19 reprojection errors: average:3.8739597282078924 max: 9.085935192382738\n",
+ "image 20 reprojection errors: average:7.251356163222619 max: 20.434004541942645\n",
+ "image 21 reprojection errors: average:8.541820698220842 max: 27.833814655174077\n",
+ "image 22 reprojection errors: average:6.146747172907995 max: 15.614134594523062\n",
+ "image 23 reprojection errors: average:4.88815583046578 max: 9.838168750390725\n",
+ "image 24 reprojection errors: average:6.59726114324304 max: 19.43094723324123\n",
+ "image 25 reprojection errors: average:4.062229166866377 max: 9.577115766031268\n",
+ "image 26 reprojection errors: average:7.0067097118768515 max: 17.976745856756665\n",
+ "image 27 reprojection errors: average:7.6154435691381686 max: 36.58264882365354\n",
+ "image 28 reprojection errors: average:5.565880249570669 max: 9.301873799042598\n",
+ "image 29 reprojection errors: average:5.922634877387619 max: 21.646447530853163\n",
+ "image 30 reprojection errors: average:6.447495264342218 max: 17.016725069346514\n",
+ "image 31 reprojection errors: average:6.536835698745158 max: 21.62991661467258\n",
+ "image 32 reprojection errors: average:5.5384573740207985 max: 11.369721689675746\n",
+ "image 33 reprojection errors: average:10.56286497960333 max: 44.49949437980213\n",
+ "image 34 reprojection errors: average:9.906919655833176 max: 17.523899418065618\n",
+ "image 35 reprojection errors: average:10.383395341199535 max: 19.37123974907046\n",
+ "image 36 reprojection errors: average:10.90387585914805 max: 20.34865298951052\n",
+ "image 37 reprojection errors: average:8.979812978701162 max: 21.428894394791442\n",
+ "image 38 reprojection errors: average:12.825231349234468 max: 31.577812486110894\n",
+ "image 39 reprojection errors: average:6.156776265494568 max: 21.514457392844474\n",
+ "image 40 reprojection errors: average:31.725525170418837 max: 75.66715182175243\n",
+ "image 41 reprojection errors: average:9.038105751755074 max: 29.70130154067451\n",
+ "image 42 reprojection errors: average:2.9410401045484855 max: 6.641734089083937\n",
+ "image 43 reprojection errors: average:6.253388095122778 max: 11.100740382590844\n",
+ "image 44 reprojection errors: average:4.920868359687841 max: 13.629635865639829\n",
+ "image 45 reprojection errors: average:5.087970321246291 max: 11.127710112231272\n",
+ "image 46 reprojection errors: average:4.214466769179164 max: 8.109655893746092\n",
+ "image 47 reprojection errors: average:6.392564533301612 max: 20.021508272525644\n",
+ "image 48 reprojection errors: average:5.787761900685547 max: 11.217884191590672\n",
+ "image 49 reprojection errors: average:4.88093542833702 max: 9.281954054413037\n",
+ "image 50 reprojection errors: average:5.893760543568262 max: 23.757241308739147\n"
]
}
],
@@ -2717,16 +2771,16 @@
},
{
"cell_type": "code",
- "execution_count": 28,
+ "execution_count": 277,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "795 04721-00 40 75.66715182174264\n",
- "795 04722-00 40 62.99503133115818\n",
- "795 04722-00 40 62.99503133115818\n"
+ "795 04721-00 40 75.66715182175243\n",
+ "795 04722-00 40 62.99503133115899\n",
+ "795 04722-00 40 62.99503133115899\n"
]
}
],
@@ -2758,10 +2812,42 @@
},
{
"cell_type": "code",
- "execution_count": 29,
+ "execution_count": 278,
"metadata": {
"scrolled": false
},
+ "outputs": [],
+ "source": [
+ "images_to_plot = []#common_image_feature_locations.keys()# ['766', '767', '768', '769']\n",
+ "for test_image in images_to_plot:\n",
+ " fig, ax = plt.subplots(figsize=(12,9))\n",
+ " coords = np.stack(list(common_image_feature_locations[test_image].values()))\n",
+ " repro_coords = np.stack(list(reprojected_points[test_image].values()))\n",
+ " ax.scatter(coords[:,0], 3000-coords[:,1], marker='.', label='detected')\n",
+ " ax.scatter(repro_coords[:,0], 3000-repro_coords[:,1], marker='.', label='reprojected')\n",
+ " for t, f in common_image_feature_locations[test_image].items():\n",
+ " ax.text(f[0], 3000-f[1], t, size=6, zorder=4, color='k')\n",
+ "# for t, f in reprojected_points[fitter_pmts.index_image[test_image]].items():\n",
+ "# ax.text(f[0], 3000-f[1], t, size=6, zorder=4, color='gray')\n",
+ " ax.set_title(\"Image {}\".format(test_image))\n",
+ " ax.set_ylim(0, 3000)\n",
+ " ax.set_xlim(0, 4000)\n",
+ " plt.legend(loc=0)\n",
+ " fig.tight_layout()\n",
+ " plt.savefig(saveLocation+\"initial_estimate/image_plots/\"+test_image+\"-initial_estimate-plot\"+imageExtension)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Plot camera position estimates in 3D"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 256,
+ "metadata": {},
"outputs": [
{
"data": {
@@ -3013,6 +3099,10 @@
" '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",
@@ -3270,11 +3360,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -3284,7 +3377,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -3403,10 +3496,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -3414,18 +3507,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -3450,7 +3542,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -3460,6 +3552,19 @@
" // 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",
@@ -3470,8 +3575,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -3724,7 +3835,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -3732,7 +3843,27 @@
},
"metadata": {},
"output_type": "display_data"
- },
+ }
+ ],
+ "source": [
+ "camera_orientations, camera_positions = fit.camera_world_poses(camera_rotations, camera_translations)\n",
+ "fig = plt.figure(figsize=(12,9))\n",
+ "pmt_array = np.stack(list(pmt_locations.values()))\n",
+ "feat_array = np.stack(list(pmt_locations.values()))\n",
+ "ax = fig.add_subplot(111, projection='3d')\n",
+ "ax.scatter(feat_array[:,0], feat_array[:,1], feat_array[:,2], marker='.', label=\"seed positions\", zorder=2)\n",
+ "for i, f in enumerate(pmt_locations.keys()):\n",
+ " ax.text(pmt_array[i,0], pmt_array[i,1], pmt_array[i,2], f[:5], size=4, zorder=4, color='k') \n",
+ "ax.scatter(camera_positions[:,0], camera_positions[:,1], camera_positions[:,2], marker='*', label=\"camera estimate\", zorder=1)\n",
+ "plt.legend(loc=0)\n",
+ "fig.tight_layout()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 31,
+ "metadata": {},
+ "outputs": [
{
"data": {
"application/javascript": [
@@ -3983,6 +4114,10 @@
" '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",
@@ -4240,11 +4375,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -4254,7 +4392,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -4373,10 +4511,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -4384,18 +4522,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -4420,7 +4557,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -4430,6 +4567,19 @@
" // 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",
@@ -4440,8 +4590,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -4694,7 +4850,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -4702,7 +4858,27 @@
},
"metadata": {},
"output_type": "display_data"
- },
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots(figsize=(9,9))\n",
+ "pmt_array = np.stack(list(pmt_locations.values()))\n",
+ "ax.scatter(pmt_array[:,0], pmt_array[:,1], marker='^', label=\"pmt (seed position)\")\n",
+ "ax.scatter(camera_positions[:,0], camera_positions[:,1], marker='*', label=\"camera estimate\", zorder=1)\n",
+ "for i, p in enumerate(camera_positions):\n",
+ " ax.text(p[0], p[1], fitter_all.index_image[i], size=7, zorder=4, color='k') \n",
+ "ax.set_ylim((-1800,1800))\n",
+ "ax.set_xlim((-1800,1800))\n",
+ "plt.legend(loc=0)\n",
+ "fig.tight_layout()\n",
+ "fig.savefig(saveLocation+\"initial_estimate/initial_estimate-top\"+imageExtension)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 33,
+ "metadata": {},
+ "outputs": [
{
"data": {
"application/javascript": [
@@ -4953,6 +5129,10 @@
" '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",
@@ -5210,11 +5390,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -5224,7 +5407,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -5343,10 +5526,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -5354,18 +5537,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -5390,7 +5572,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -5400,6 +5582,19 @@
" // 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",
@@ -5410,8 +5605,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -5664,7 +5865,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -5672,7 +5873,173 @@
},
"metadata": {},
"output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots(figsize=(16,6))\n",
+ "pmt_array = np.stack(list(pmt_locations.values()))\n",
+ "ax.scatter(np.arctan2(pmt_array[:,1],pmt_array[:,0]), pmt_array[:,2], marker='^', label=\"pmt (seed position)\")\n",
+ "ax.scatter(np.arctan2(camera_positions[:,1], camera_positions[:,0]), camera_positions[:,2], marker='*', label=\"camera estimate\", zorder=1)\n",
+ "for i, p in enumerate(camera_positions):\n",
+ " ax.text(np.arctan2(p[1],p[0]), p[2], fitter_all.index_image[i], size=7, zorder=4, color='k') \n",
+ "ax.set_xlim((-np.pi-0.1,np.pi+0.1))\n",
+ "ax.set_ylim((0,500))\n",
+ "plt.legend(loc=0)\n",
+ "fig.tight_layout()\n",
+ "fig.savefig(saveLocation+\"initial_estimate/initial_estimate-barrel\"+imageExtension)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Perform bundle asjustment starting from seed geometry and estimated camera poses"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 281,
+ "metadata": {
+ "pycharm": {
+ "is_executing": false
},
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 7.6712e+04 1.63e+06 \n",
+ " 1 2 1.7117e+04 5.96e+04 5.83e+01 2.03e+04 \n",
+ " 2 3 1.5525e+04 1.59e+03 2.11e+01 1.20e+04 \n",
+ " 3 4 1.4842e+04 6.83e+02 6.60e+00 4.74e+03 \n",
+ " 4 5 1.4676e+04 1.66e+02 2.79e+00 4.96e+03 \n",
+ " 5 6 1.4595e+04 8.07e+01 1.39e+00 4.94e+03 \n",
+ " 6 7 1.4544e+04 5.17e+01 9.25e-01 4.04e+03 \n",
+ " 7 8 1.4497e+04 4.70e+01 9.88e-01 5.08e+03 \n",
+ " 8 9 1.4451e+04 4.55e+01 8.65e-01 4.25e+03 \n",
+ " 9 10 1.4407e+04 4.42e+01 9.54e-01 5.16e+03 \n",
+ " 10 11 1.4364e+04 4.31e+01 8.45e-01 4.32e+03 \n",
+ " 11 12 1.4322e+04 4.18e+01 9.24e-01 5.39e+03 \n",
+ " 12 13 1.4281e+04 4.09e+01 8.25e-01 4.64e+03 \n",
+ " 13 14 1.4242e+04 3.96e+01 8.91e-01 5.96e+03 \n",
+ " 14 15 1.4203e+04 3.89e+01 8.03e-01 5.27e+03 \n",
+ " 15 16 1.4165e+04 3.77e+01 8.60e-01 6.49e+03 \n",
+ " 16 17 1.4128e+04 3.68e+01 7.72e-01 6.44e+03 \n",
+ " 17 18 1.4092e+04 3.56e+01 8.12e-01 8.30e+03 \n",
+ " 18 19 1.4058e+04 3.44e+01 7.14e-01 8.74e+03 \n",
+ " 19 20 1.4027e+04 3.07e+01 6.63e-01 1.21e+04 \n",
+ " 20 21 1.4007e+04 2.01e+01 3.08e-01 1.07e+04 \n",
+ " 21 22 1.4004e+04 3.72e+00 7.68e-04 2.94e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 22, initial cost 7.6712e+04, final cost 1.4004e+04, first-order optimality 2.94e+01.\n",
+ "mean reprojection error: 3.0502375288380037\n",
+ "max reprojection error: 21.636539426893115\n"
+ ]
+ }
+ ],
+ "source": [
+ "# camera_rotations, camera_translations, reco_locations, fitted_matrix, fitted_distortion = fitter_all.bundle_adjustment(\n",
+ "# camera_rotations, camera_translations, use_sparsity=True, max_error=5, fit_cam=True)\n",
+ "camera_rotations, camera_translations, reco_locations, opt = fitter_all.bundle_adjustment(camera_rotations, camera_translations, use_sparsity=True, return_opt=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 282,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "J=opt.jac[:,fitter_all.nimages*6:].toarray()\n",
+ "U, s, Vh = linalg.svd(J, full_matrices=False)\n",
+ "tol = np.finfo(float).eps*s[0]*max(J.shape)\n",
+ "w = s > tol\n",
+ "cov = (Vh[w].T/s[w]**2) @ Vh[w] # robust covariance matrix\n",
+ "perr = np.sqrt(np.diag(cov)) # 1sigma uncertainty on fitted parameters\n",
+ "feature_location_errors = perr.reshape((-1, 3))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 300,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "3522"
+ ]
+ },
+ "execution_count": 300,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "opt.fun.size"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 301,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2250"
+ ]
+ },
+ "execution_count": 301,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "opt.x.size"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 304,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1944"
+ ]
+ },
+ "execution_count": 304,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "perr.size"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 305,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "chi2dof = np.sum(opt.fun**2)/(opt.fun.size - perr.size)\n",
+ "cov_scaled = cov*chi2dof\n",
+ "perr = np.sqrt(np.diag(cov_scaled)) # 1sigma uncertainty on fitted parameters\n",
+ "feature_location_errors = perr.reshape((-1, 3))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 306,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
{
"data": {
"application/javascript": [
@@ -5923,6 +6290,10 @@
" '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",
@@ -6180,11 +6551,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -6194,7 +6568,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -6313,10 +6687,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -6324,18 +6698,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -6360,7 +6733,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -6370,6 +6743,19 @@
" // 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",
@@ -6380,8 +6766,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -6634,7 +7026,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -6643,6 +7035,50 @@
"metadata": {},
"output_type": "display_data"
},
+ {
+ "data": {
+ "text/plain": [
+ "Text(0, 0.5, 'Number of features')"
+ ]
+ },
+ "execution_count": 306,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots(figsize=(8,6))\n",
+ "ax.hist(feature_location_errors.flatten(), bins=20, histtype=\"step\")\n",
+ "ax.set_xlabel(\"Fitter error on feature position [cm]\", fontsize=15)\n",
+ "ax.set_ylabel(\"Number of features\", fontsize=15)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 307,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x_variance = np.diag(cov_scaled)[0::3]\n",
+ "y_variance = np.diag(cov_scaled)[1::3]\n",
+ "z_variance = np.diag(cov_scaled)[2::3]\n",
+ "variance_3d = x_variance + y_variance + z_variance\n",
+ "xy_covariance = cov_scaled[range(0,cov_scaled.shape[0],3),range(1,cov_scaled.shape[1],3)]\n",
+ "xz_covariance = cov_scaled[range(0,cov_scaled.shape[0],3),range(2,cov_scaled.shape[1],3)]\n",
+ "yz_covariance = cov_scaled[range(1,cov_scaled.shape[0],3),range(2,cov_scaled.shape[1],3)]\n",
+ "radial_positions = linalg.norm(fitter_all.reco_locations[:,:2], axis=1)\n",
+ "x_positions = fitter_all.reco_locations[:,0]\n",
+ "y_positions = fitter_all.reco_locations[:,1]\n",
+ "z_positions = fitter_all.reco_locations[:,2]\n",
+ "radial_variance = ((x_positions**2)*x_variance+(y_positions**2)*y_variance+2*x_positions*y_positions*xy_covariance)/radial_positions**2\n",
+ "tangential_variance = variance_3d-radial_variance"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 308,
+ "metadata": {},
+ "outputs": [
{
"data": {
"application/javascript": [
@@ -6893,6 +7329,10 @@
" '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",
@@ -7150,11 +7590,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -7164,7 +7607,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -7283,10 +7726,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -7294,18 +7737,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -7330,7 +7772,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -7340,6 +7782,19 @@
" // 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",
@@ -7350,8 +7805,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -7604,7 +8065,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -7613,6 +8074,32 @@
"metadata": {},
"output_type": "display_data"
},
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 308,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots(figsize=(8,6))\n",
+ "ax.hist(np.sqrt(x_variance), bins=range(20), histtype=\"step\", color=\"r\", label=f\"x position error\\nmean = {np.mean(np.sqrt(x_variance)):.3} cm\")\n",
+ "ax.hist(np.sqrt(y_variance), bins=range(20), histtype=\"step\", color=\"b\", label=f\"y position error\\nmean = {np.mean(np.sqrt(y_variance)):.3} cm\")\n",
+ "ax.hist(np.sqrt(z_variance), bins=range(20), histtype=\"step\", color=\"g\", label=f\"z position error\\nmean = {np.mean(np.sqrt(z_variance)):.3} cm\")\n",
+ "ax.set_xlabel(\"Fitter error on feature position [cm]\", fontsize=15)\n",
+ "ax.set_ylabel(\"Number of features\", fontsize=15)\n",
+ "plt.legend(loc=\"upper right\", prop={'size': 15})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 309,
+ "metadata": {},
+ "outputs": [
{
"data": {
"application/javascript": [
@@ -7863,6 +8350,10 @@
" '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",
@@ -8120,11 +8611,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -8134,7 +8628,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -8253,10 +8747,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -8264,18 +8758,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -8300,7 +8793,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -8310,6 +8803,19 @@
" // 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",
@@ -8320,8 +8826,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -8574,7 +9086,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -8583,6 +9095,30 @@
"metadata": {},
"output_type": "display_data"
},
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 309,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots(figsize=(8,6))\n",
+ "ax.hist(np.sqrt(variance_3d), bins=20, histtype=\"step\", label=f\"3D position error\\nmean = {np.mean(np.sqrt(variance_3d)):.3} cm\")\n",
+ "ax.set_xlabel(\"Fitter error on 3D feature position [cm]\", fontsize=15)\n",
+ "ax.set_ylabel(\"Number of features\", fontsize=15)\n",
+ "plt.legend(loc=\"upper right\", prop={'size': 15})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 310,
+ "metadata": {},
+ "outputs": [
{
"data": {
"application/javascript": [
@@ -8833,6 +9369,10 @@
" '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",
@@ -9090,11 +9630,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -9104,7 +9647,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -9223,10 +9766,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -9234,18 +9777,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -9270,7 +9812,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -9280,6 +9822,19 @@
" // 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",
@@ -9290,8 +9845,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -9544,7 +10105,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -9553,6 +10114,105 @@
"metadata": {},
"output_type": "display_data"
},
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 310,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots(figsize=(8,6))\n",
+ "ax.hist(np.sqrt(radial_variance), bins=20, histtype=\"step\", color=\"b\", label=f\"Radial position error\\nmean = {np.mean(np.sqrt(radial_variance)):.3} cm\")\n",
+ "ax.hist(np.sqrt(tangential_variance), bins=20, histtype=\"step\", color=\"r\", label=f\"Tangential position error\\nmean = {np.mean(np.sqrt(tangential_variance)):.3} cm\")\n",
+ "ax.set_xlabel(\"Fitter error on radial feature position [cm]\", fontsize=15)\n",
+ "ax.set_ylabel(\"Number of features\", fontsize=15)\n",
+ "plt.legend(loc=\"upper right\", prop={'size': 15})"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Kabsch algorithm to match reconstructed coordinate system to seed co-ordinate system"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 289,
+ "metadata": {
+ "pycharm": {
+ "is_executing": false
+ },
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "mean reconstruction error: 2.576439736972181\n",
+ "max reconstruction error: 10.759373732374454\n"
+ ]
+ }
+ ],
+ "source": [
+ "errors, reco_transformed, scale, R, translation, location_mean = fit.kabsch_errors(pmt_locations, reco_locations)\n",
+ "print(\"mean reconstruction error:\", linalg.norm(errors, axis=1).mean())\n",
+ "print(\"max reconstruction error:\", linalg.norm(errors, axis=1).max())"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 290,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ret = 1, 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 291,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "camera_orientations, camera_positions = fit.camera_world_poses(camera_rotations, camera_translations)\n",
+ "camera_orientations = np.matmul(R, camera_orientations)\n",
+ "camera_positions = camera_positions - translation\n",
+ "camera_positions = scale*R.dot(camera_positions.transpose()).transpose() + location_mean"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Check new yaws and depths for manual shifts if necessary"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 292,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "drone_yaw = np.array(list(drone_yaw_raw.values()))*np.pi/180\n",
+ "fitted_yaw = np.arctan2(camera_orientations[:,1,2],camera_orientations[:,0,2])\n",
+ "drone_yaw -= drone_yaw[21] - fitted_yaw[21] # correct for drone calibration by forcing image 21 (with light injector) to have the correct yaw\n",
+ "yaw_errors = ((fitted_yaw - drone_yaw + np.pi) % (2*np.pi)) - np.pi\n",
+ "yaw_errors_deg = yaw_errors*180/np.pi\n",
+ "depths = camera_positions[:,2]/100 - 2.9"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 293,
+ "metadata": {},
+ "outputs": [
{
"data": {
"application/javascript": [
@@ -9803,6 +10463,10 @@
" '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",
@@ -10060,11 +10724,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -10074,7 +10741,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -10193,10 +10860,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -10204,18 +10871,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -10240,7 +10906,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -10250,6 +10916,19 @@
" // 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",
@@ -10260,8 +10939,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -10514,7 +11199,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -10523,6 +11208,205 @@
"metadata": {},
"output_type": "display_data"
},
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " yaw depth\n",
+ "image 755: -0.8644 +0.0450\n",
+ "image 756: -2.0376 +0.0546\n",
+ "image 757: -4.1522 +0.0735\n",
+ "image 758: +3.7006 +0.1559\n",
+ "image 759: +1.6185 +0.0820\n",
+ "image 760: -0.9035 -0.0583\n",
+ "image 761: -0.1234 +0.1054\n",
+ "image 762: -3.8193 +0.0357\n",
+ "image 763: +3.9414 +0.1273\n",
+ "image 764: +1.6909 +0.0614\n",
+ "image 765: +0.8607 +0.1301\n",
+ "image 766: -1.2926 -0.0791\n",
+ "image 767: -2.1103 +0.0463\n",
+ "image 768: +4.3450 -0.0698\n",
+ "image 769: +0.7497 -0.1673\n",
+ "image 770: +3.3188 +0.0157\n",
+ "image 771: +2.9743 +0.0467\n",
+ "image 772: +0.2763 -0.0185\n",
+ "image 773: +0.1406 -0.0055\n",
+ "image 774: -1.0599 -0.0655\n",
+ "image 775: +1.1562 +0.1122\n",
+ "image 776: +0.0000 +0.0718\n",
+ "image 777: -1.1475 -0.0593\n",
+ "image 778: +0.8455 +0.0543\n",
+ "image 779: +3.0151 +0.0442\n",
+ "image 780: -4.0019 +0.1472\n",
+ "image 781: -1.3729 +0.1543\n",
+ "image 782: +2.1631 +0.0293\n",
+ "image 783: +1.6154 +0.1314\n",
+ "image 784: -0.2537 +0.1610\n",
+ "image 785: +3.9184 -0.0257\n",
+ "image 786: -3.1136 +0.0152\n",
+ "image 787: -1.8892 -0.0304\n",
+ "image 788: +3.0924 -0.0490\n",
+ "image 789: +2.7097 +0.0217\n",
+ "image 790: -0.0052 +0.1000\n",
+ "image 791: -1.7324 +0.1661\n",
+ "image 792: -0.7759 -0.1085\n",
+ "image 793: +3.1362 -0.0499\n",
+ "image 794: +4.6417 +0.0778\n",
+ "image 795: -0.2364 -0.1795\n",
+ "image 796: +4.7643 -0.0771\n",
+ "image 797: +2.0038 +0.0796\n",
+ "image 798: -4.4088 +0.0155\n",
+ "image 799: -0.1181 +0.1394\n",
+ "image 800: -1.1673 +0.1913\n",
+ "image 801: -2.5063 +0.2335\n",
+ "image 901: -2.4623 +0.1754\n",
+ "image 902: +3.1176 +0.0282\n",
+ "image 903: +1.8706 +0.1087\n",
+ "image 904: +0.8427 +0.0055\n"
+ ]
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots(figsize=(8,6))\n",
+ "ax.hist(yaw_errors_deg, bins=10)\n",
+ "ax.set_title(f\"Yaw error, mean = {yaw_errors_deg.mean():.2f} deg\")\n",
+ "fig.tight_layout()\n",
+ "print(\" yaw depth\")\n",
+ "for i, (e, d) in enumerate(zip(yaw_errors_deg, depths)):\n",
+ " print(f\"image {fitter_all.index_image[i]}: {e:+6.4f} {d:+6.4f}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Plot overlay of reprojected and observed feature locations for manual checking"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 294,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [],
+ "source": [
+ "#images_to_plot = images ['792']\n",
+ "for test_image in []:#images_to_plot:\n",
+ " fig, ax = plt.subplots(figsize=(12,9))\n",
+ " coords = np.stack(list(common_image_feature_locations[test_image].values()))\n",
+ " repro_coords = np.stack(list(reprojected_points[test_image].values()))\n",
+ " ax.scatter(coords[:,0], 3000-coords[:,1], marker='.', label='detected')\n",
+ " ax.scatter(repro_coords[:,0], 3000-repro_coords[:,1], marker='.', label='reprojected')\n",
+ " for t, f in common_image_feature_locations[test_image].items():\n",
+ " ax.text(f[0], 3000-f[1], t, size=6, zorder=4, color='k')\n",
+ "# for t, f in reprojected_points[fitter_pmts.index_image[test_image]].items():\n",
+ "# ax.text(f[0], 3000-f[1], t, size=6, zorder=4, color='gray')\n",
+ " ax.set_title(\"Image {}\".format(test_image))\n",
+ " ax.set_ylim(0, 3000)\n",
+ " ax.set_xlim(0, 4000)\n",
+ " plt.legend(loc=0)\n",
+ " fig.tight_layout()\n",
+ " plt.savefig(saveLocation+\"image_plots/\"+test_image+\"-plot\"+imageExtension)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Save results to txt file"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 295,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "fitter_all.save_result(saveLocation+\"SK_ring_features_relabelled.txt\", saveLocation+\"SK_ring_cameras_relabelled.txt\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Save results to pickle"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 296,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(saveLocation+\"SK_ring_relabelled.pkl\", 'wb') as output:\n",
+ " pickle.dump(fitter_all, output, pickle.HIGHEST_PROTOCOL)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Plots of reconstructed geometry"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 297,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from matplotlib.legend_handler import HandlerPatch\n",
+ "import matplotlib.patches as mpatches\n",
+ "class HandlerArrow(HandlerPatch):\n",
+ " def create_artists(self, legend, orig_handle,\n",
+ " xdescent, ydescent, width, height, fontsize, trans):\n",
+ " p = mpatches.FancyArrow(0, 0.5*height, width, 0, length_includes_head=True, head_width=0.75*height )\n",
+ " self.update_prop(p, orig_handle, legend)\n",
+ " p.set_transform(trans)\n",
+ " return [p]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 298,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([153.92161995, 147.92161995, 140.92161995, 136.92161995,\n",
+ " 135.92161995, 122.92161995, 121.92161995, 112.92161995,\n",
+ " 109.92161995, 102.92161995, 99.92161995, 94.92161995,\n",
+ " 88.92161995, 80.92161995, 77.92161995, 69.92161995,\n",
+ " 59.92161995, 58.92161995, 48.92161995, 45.92161995,\n",
+ " 39.92161995, 34.92161995, 28.92161995, 16.92161995,\n",
+ " 9.92161995, -4.07838005, -11.07838005, 341.92161995,\n",
+ " 334.92161995, 314.92161995, 303.92161995, 296.92161995,\n",
+ " 283.92161995, 276.92161995, 258.92161995, 247.92161995,\n",
+ " 240.92161995, 231.92161995, 219.92161995, 216.92161995,\n",
+ " 211.92161995, 201.92161995, 193.92161995, 185.92161995,\n",
+ " 184.92161995, 182.92161995, 173.92161995, 173.92161995,\n",
+ " 167.92161995, 161.92161995, 151.92161995])"
+ ]
+ },
+ "execution_count": 298,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "drone_yaw*180/np.pi"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 299,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
{
"data": {
"application/javascript": [
@@ -10773,93440 +11657,9 @@
" 'mouseup',\n",
" on_mouse_event_closure('button_release')\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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": "stderr",
- "output_type": "stream",
- "text": [
- ":3: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).\n",
- " fig, ax = plt.subplots(figsize=(12,9))\n"
- ]
- },
- {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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"
- }
- ],
- "source": [
- "images_to_plot = common_image_feature_locations.keys()# ['766', '767', '768', '769']\n",
- "for test_image in images_to_plot:\n",
- " fig, ax = plt.subplots(figsize=(12,9))\n",
- " coords = np.stack(list(common_image_feature_locations[test_image].values()))\n",
- " repro_coords = np.stack(list(reprojected_points[test_image].values()))\n",
- " ax.scatter(coords[:,0], 3000-coords[:,1], marker='.', label='detected')\n",
- " ax.scatter(repro_coords[:,0], 3000-repro_coords[:,1], marker='.', label='reprojected')\n",
- " for t, f in common_image_feature_locations[test_image].items():\n",
- " ax.text(f[0], 3000-f[1], t, size=6, zorder=4, color='k')\n",
- "# for t, f in reprojected_points[fitter_pmts.index_image[test_image]].items():\n",
- "# ax.text(f[0], 3000-f[1], t, size=6, zorder=4, color='gray')\n",
- " ax.set_title(\"Image {}\".format(test_image))\n",
- " ax.set_ylim(0, 3000)\n",
- " ax.set_xlim(0, 4000)\n",
- " plt.legend(loc=0)\n",
- " fig.tight_layout()\n",
- " plt.savefig(saveLocation+\"initial_estimate/image_plots/\"+test_image+\"-initial_estimate-plot\"+imageExtension)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Plot camera position estimates in 3D"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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"
- }
- ],
- "source": [
- "camera_orientations, camera_positions = fit.camera_world_poses(camera_rotations, camera_translations)\n",
- "fig = plt.figure(figsize=(12,9))\n",
- "pmt_array = np.stack(list(pmt_locations.values()))\n",
- "feat_array = np.stack(list(pmt_locations.values()))\n",
- "ax = fig.add_subplot(111, projection='3d')\n",
- "ax.scatter(feat_array[:,0], feat_array[:,1], feat_array[:,2], marker='.', label=\"seed positions\", zorder=2)\n",
- "for i, f in enumerate(pmt_locations.keys()):\n",
- " ax.text(pmt_array[i,0], pmt_array[i,1], pmt_array[i,2], f[:5], size=4, zorder=4, color='k') \n",
- "ax.scatter(camera_positions[:,0], camera_positions[:,1], camera_positions[:,2], marker='*', label=\"camera estimate\", zorder=1)\n",
- "plt.legend(loc=0)\n",
- "fig.tight_layout()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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"
- }
- ],
- "source": [
- "fig, ax = plt.subplots(figsize=(9,9))\n",
- "pmt_array = np.stack(list(pmt_locations.values()))\n",
- "ax.scatter(pmt_array[:,0], pmt_array[:,1], marker='^', label=\"pmt (seed position)\")\n",
- "ax.scatter(camera_positions[:,0], camera_positions[:,1], marker='*', label=\"camera estimate\", zorder=1)\n",
- "for i, p in enumerate(camera_positions):\n",
- " ax.text(p[0], p[1], fitter_all.index_image[i], size=7, zorder=4, color='k') \n",
- "ax.set_ylim((-1800,1800))\n",
- "ax.set_xlim((-1800,1800))\n",
- "plt.legend(loc=0)\n",
- "fig.tight_layout()\n",
- "fig.savefig(saveLocation+\"initial_estimate/initial_estimate-top\"+imageExtension)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 32,
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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"
- }
- ],
- "source": [
- "fig, ax = plt.subplots(figsize=(16,6))\n",
- "pmt_array = np.stack(list(pmt_locations.values()))\n",
- "ax.scatter(np.arctan2(pmt_array[:,1],pmt_array[:,0]), pmt_array[:,2], marker='^', label=\"pmt (seed position)\")\n",
- "ax.scatter(np.arctan2(camera_positions[:,1], camera_positions[:,0]), camera_positions[:,2], marker='*', label=\"camera estimate\", zorder=1)\n",
- "for i, p in enumerate(camera_positions):\n",
- " ax.text(np.arctan2(p[1],p[0]), p[2], fitter_all.index_image[i], size=7, zorder=4, color='k') \n",
- "ax.set_xlim((-np.pi,np.pi))\n",
- "ax.set_ylim((0,500))\n",
- "plt.legend(loc=0)\n",
- "fig.tight_layout()\n",
- "fig.savefig(saveLocation+\"initial_estimate/initial_estimate-barrel\"+imageExtension)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Perform bundle asjustment starting from seed geometry and estimated camera poses"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "metadata": {
- "pycharm": {
- "is_executing": false
- },
- "scrolled": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
- " 0 1 8.7240e+04 7.81e+06 \n",
- " 1 2 1.9348e+04 6.79e+04 6.97e+01 8.76e+04 \n",
- " 2 3 1.7435e+04 1.91e+03 2.33e+01 2.33e+04 \n",
- " 3 4 1.6627e+04 8.08e+02 7.80e+00 4.91e+03 \n",
- " 4 5 1.6382e+04 2.45e+02 3.87e+00 2.63e+03 \n",
- " 5 6 1.6216e+04 1.66e+02 2.86e+00 3.28e+03 \n",
- " 6 7 1.6138e+04 7.83e+01 1.25e+00 2.09e+03 \n",
- " 7 8 1.6085e+04 5.32e+01 9.86e-01 2.07e+03 \n",
- " 8 9 1.6034e+04 5.02e+01 1.00e+00 1.91e+03 \n",
- " 9 10 1.5985e+04 4.90e+01 9.48e-01 2.01e+03 \n",
- " 10 11 1.5938e+04 4.78e+01 9.75e-01 1.83e+03 \n",
- " 11 12 1.5891e+04 4.68e+01 9.30e-01 1.99e+03 \n",
- " 12 13 1.5845e+04 4.57e+01 9.51e-01 1.82e+03 \n",
- " 13 14 1.5800e+04 4.49e+01 9.14e-01 2.02e+03 \n",
- " 14 15 1.5756e+04 4.39e+01 9.28e-01 1.84e+03 \n",
- " 15 16 1.5713e+04 4.31e+01 8.98e-01 2.14e+03 \n",
- " 16 17 1.5671e+04 4.22e+01 9.06e-01 1.99e+03 \n",
- " 17 18 1.5630e+04 4.15e+01 8.83e-01 2.27e+03 \n",
- " 18 19 1.5589e+04 4.06e+01 8.86e-01 2.09e+03 \n",
- " 19 20 1.5549e+04 3.99e+01 8.69e-01 2.40e+03 \n",
- " 20 21 1.5510e+04 3.91e+01 8.66e-01 2.18e+03 \n",
- " 21 22 1.5471e+04 3.85e+01 8.55e-01 2.61e+03 \n",
- " 22 23 1.5434e+04 3.77e+01 8.46e-01 2.54e+03 \n",
- " 23 24 1.5397e+04 3.71e+01 8.41e-01 3.19e+03 \n",
- " 24 25 1.5360e+04 3.63e+01 8.26e-01 3.17e+03 \n",
- " 25 26 1.5325e+04 3.57e+01 8.24e-01 4.29e+03 \n",
- " 26 27 1.5290e+04 3.50e+01 8.01e-01 4.39e+03 \n",
- " 27 28 1.5256e+04 3.39e+01 7.86e-01 7.48e+03 \n",
- " 28 29 1.5224e+04 3.23e+01 7.22e-01 9.04e+03 \n",
- " 29 30 1.5196e+04 2.80e+01 5.90e-01 1.47e+04 \n",
- " 30 31 1.5189e+04 6.77e+00 3.16e-02 2.28e+03 \n",
- "`xtol` termination condition is satisfied.\n",
- "Function evaluations 31, initial cost 8.7240e+04, final cost 1.5189e+04, first-order optimality 2.28e+03.\n",
- "mean reprojection error: 3.173953418173125\n",
- "max reprojection error: 23.9958105832365\n"
- ]
- }
- ],
- "source": [
- "# camera_rotations, camera_translations, reco_locations, fitted_matrix, fitted_distortion = fitter_all.bundle_adjustment(\n",
- "# camera_rotations, camera_translations, use_sparsity=True, max_error=5, fit_cam=True)\n",
- "camera_rotations, camera_translations, reco_locations = fitter_all.bundle_adjustment(camera_rotations, camera_translations, use_sparsity=True)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Kabsch algorithm to match reconstructed coordinate system to seed co-ordinate system"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "metadata": {
- "pycharm": {
- "is_executing": false
- },
- "scrolled": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "mean reconstruction error: 2.9078601755008577\n",
- "max reconstruction error: 13.91719862886112\n"
- ]
- }
- ],
- "source": [
- "errors, reco_transformed, scale, R, translation, location_mean = fit.kabsch_errors(pmt_locations, reco_locations)\n",
- "print(\"mean reconstruction error:\", linalg.norm(errors, axis=1).mean())\n",
- "print(\"max reconstruction error:\", linalg.norm(errors, axis=1).max())"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [],
- "source": [
- "camera_orientations, camera_positions = fit.camera_world_poses(camera_rotations, camera_translations)\n",
- "camera_orientations = np.matmul(R, camera_orientations)\n",
- "camera_positions = camera_positions - translation\n",
- "camera_positions = scale*R.dot(camera_positions.transpose()).transpose() + location_mean"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Check new yaws and depths for manual shifts if necessary"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 36,
- "metadata": {},
- "outputs": [],
- "source": [
- "drone_yaw = np.array(list(drone_yaw_raw.values()))*np.pi/180\n",
- "fitted_yaw = np.arctan2(camera_orientations[:,1,2],camera_orientations[:,0,2])\n",
- "drone_yaw -= drone_yaw[21] - fitted_yaw[21] # correct for drone calibration by forcing image 21 (with light injector) to have the correct yaw\n",
- "yaw_errors = ((fitted_yaw - drone_yaw + np.pi) % (2*np.pi)) - np.pi\n",
- "yaw_errors_deg = yaw_errors*180/np.pi\n",
- "depths = camera_positions[:,2]/100 - 2.9"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 37,
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": [
- " yaw depth\n",
- "image 755: -0.9134 +0.0338\n",
- "image 756: -2.1533 +0.0556\n",
- "image 757: -4.0510 +0.0566\n",
- "image 758: +3.4926 +0.2046\n",
- "image 759: +1.5126 +0.1028\n",
- "image 760: -0.8427 -0.0716\n",
- "image 761: -0.1631 +0.1094\n",
- "image 762: -3.9015 +0.0459\n",
- "image 763: +3.9012 +0.1552\n",
- "image 764: +1.5209 +0.0441\n",
- "image 765: +0.8571 +0.1441\n",
- "image 766: -1.3648 -0.0956\n",
- "image 767: -2.1448 +0.0570\n",
- "image 768: +4.2798 -0.0738\n",
- "image 769: +0.2458 -0.1893\n",
- "image 770: +3.5235 +0.0060\n",
- "image 771: +2.8210 +0.0573\n",
- "image 772: +0.2321 -0.0221\n",
- "image 773: +0.0391 -0.0080\n",
- "image 774: -0.9613 -0.0698\n",
- "image 775: +1.2070 +0.1100\n",
- "image 776: +0.0000 +0.0762\n",
- "image 777: -1.2597 -0.0591\n",
- "image 778: +0.7023 +0.0644\n",
- "image 779: +2.9395 +0.0406\n",
- "image 780: -4.1009 +0.1496\n",
- "image 781: -1.5613 +0.1545\n",
- "image 782: +2.1787 +0.0276\n",
- "image 783: +1.4933 +0.1322\n",
- "image 784: -0.3455 +0.1668\n",
- "image 785: +3.8076 -0.0324\n",
- "image 786: -3.1597 +0.0176\n",
- "image 787: -1.9293 -0.0298\n",
- "image 788: +2.8350 -0.0593\n",
- "image 789: +2.7906 +0.0265\n",
- "image 790: -0.0754 +0.0996\n",
- "image 791: -1.9311 +0.1859\n",
- "image 792: -0.7958 -0.1179\n",
- "image 793: +2.5060 -0.0615\n",
- "image 794: +4.4523 +0.0941\n",
- "image 795: -1.2752 -0.2152\n",
- "image 796: +4.8223 -0.0972\n",
- "image 797: +1.7927 +0.0901\n",
- "image 798: -4.5399 +0.0143\n",
- "image 799: -0.1932 +0.1516\n",
- "image 800: -1.2636 +0.2073\n",
- "image 801: -2.5911 +0.2381\n",
- "image 901: -2.6524 +0.2025\n",
- "image 902: +3.1228 -0.0028\n",
- "image 903: +1.8058 +0.1136\n",
- "image 904: +0.8779 +0.0281\n"
- ]
- }
- ],
- "source": [
- "fig, ax = plt.subplots(figsize=(8,6))\n",
- "ax.hist(yaw_errors_deg, bins=10)\n",
- "ax.set_title(f\"Yaw error, mean = {yaw_errors_deg.mean():.2f} deg\")\n",
- "fig.tight_layout()\n",
- "print(\" yaw depth\")\n",
- "for i, (e, d) in enumerate(zip(yaw_errors_deg, depths)):\n",
- " print(f\"image {fitter_all.index_image[i]}: {e:+6.4f} {d:+6.4f}\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Plot overlay of reprojected and observed feature locations for manual checking"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "metadata": {
- "scrolled": false
- },
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
- " // 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",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
- "\n",
- " /* Free the memory for the previous frames */\n",
- " if (fig.imageObj.src) {\n",
- " (window.URL || window.webkitURL).revokeObjectURL(\n",
- " fig.imageObj.src\n",
- " );\n",
- " }\n",
- "\n",
- " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\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.which === this._key) {\n",
- " return;\n",
- " } else {\n",
- " this._key = event.which;\n",
- " }\n",
- " }\n",
- " if (name === 'key_release') {\n",
- " this._key = null;\n",
- " }\n",
- "\n",
- " var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
- " value += 'ctrl+';\n",
- " }\n",
- " if (event.altKey && event.which !== 18) {\n",
- " value += 'alt+';\n",
- " }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
- " value += 'shift+';\n",
- " }\n",
- "\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
- "\n",
- " this._key_event_extra(event, name);\n",
- "\n",
- " this.send_message(name, { key: value, 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\", \"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.close = function () {\n",
- " comm.close();\n",
- " };\n",
- " ws.send = function (m) {\n",
- " //console.log('sending', m);\n",
- " comm.send(m);\n",
- " };\n",
- " // Register the callback with on_msg.\n",
- " comm.on_msg(function (msg) {\n",
- " //console.log('receiving', msg['content']['data'], msg);\n",
- " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
- " ws.onmessage(msg['content']['data']);\n",
- " });\n",
- " return ws;\n",
- "};\n",
- "\n",
- "mpl.mpl_figure_comm = function (comm, msg) {\n",
- " // This is the function which gets called when the mpl process\n",
- " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
- "\n",
- " var id = msg.content.data.id;\n",
- " // Get hold of the div created by the display call when the Comm\n",
- " // socket was opened in Python.\n",
- " var element = 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": {
- "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",
+ " 'dblclick',\n",
+ " on_mouse_event_closure('dblclick')\n",
" );\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband_canvas.addEventListener(\n",
@@ -104465,11 +11918,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -104479,7 +11935,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -104598,10 +12054,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -104609,18 +12065,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -104645,7 +12100,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -104655,6 +12110,19 @@
" // 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",
@@ -104665,8 +12133,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -104919,7 +12393,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -104927,7 +12401,37 @@
},
"metadata": {},
"output_type": "display_data"
- },
+ }
+ ],
+ "source": [
+ "fig, ax = plt.subplots(figsize=(9,9))\n",
+ "pmt_array = np.stack(list(pmt_locations.values()))\n",
+ "ax.scatter(pmt_array[:,0], pmt_array[:,1], marker='o', label=\"seed pmt position\")\n",
+ "ax.scatter(reco_transformed[:,0], reco_transformed[:,1], marker='+', label=\"reconstructed pmt position\", color=\"green\")\n",
+ "ax.scatter(camera_positions[:,0], camera_positions[:,1], marker='*', label=\"fitted camera position\", zorder=1, color=\"orange\")\n",
+ "for i, p in enumerate(camera_positions):\n",
+ " ax.text(p[0], p[1], fitter_all.index_image[i], size=7, zorder=4, color='k')\n",
+ "for i, (p, o) in enumerate(zip(camera_positions, camera_orientations)):\n",
+ " fitarrow = plt.arrow(p[0], p[1], o[0,2]*200, o[1,2]*200, color=\"orange\", width=0.1, head_width=20, head_length=30)\n",
+ "for i, (p, y) in enumerate(zip(camera_positions, drone_yaw)):\n",
+ " dronearrow = plt.arrow(p[0], p[1], np.cos(y)*160, np.sin(y)*160, color=\"black\", width=0.01, head_width=20, head_length=30)\n",
+ "ax.set_ylim((-1800,1800))\n",
+ "ax.set_xlim((-1800,1800))\n",
+ "handles, labels = ax.get_legend_handles_labels()\n",
+ "handles.extend((fitarrow, dronearrow))\n",
+ "labels.extend((\"fitted camera yaw\", \"drone sensor yaw\"))\n",
+ "plt.legend(handles=handles, labels=labels, loc=0, handler_map={mpatches.FancyArrow : HandlerArrow()})\n",
+ "fig.tight_layout()\n",
+ "fig.savefig(saveLocation+\"top\"+imageExtension)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 199,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
{
"data": {
"application/javascript": [
@@ -105178,6 +12682,10 @@
" '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",
@@ -105435,11 +12943,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -105449,7 +12960,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -105568,10 +13079,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -105579,18 +13090,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -105615,7 +13125,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -105625,6 +13135,19 @@
" // 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",
@@ -105635,8 +13158,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -105889,7 +13418,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -105900,118 +13429,33 @@
}
],
"source": [
- "#images_to_plot = images ['792']\n",
- "for test_image in images_to_plot:\n",
- " fig, ax = plt.subplots(figsize=(12,9))\n",
- " coords = np.stack(list(common_image_feature_locations[test_image].values()))\n",
- " repro_coords = np.stack(list(reprojected_points[test_image].values()))\n",
- " ax.scatter(coords[:,0], 3000-coords[:,1], marker='.', label='detected')\n",
- " ax.scatter(repro_coords[:,0], 3000-repro_coords[:,1], marker='.', label='reprojected')\n",
- " for t, f in common_image_feature_locations[test_image].items():\n",
- " ax.text(f[0], 3000-f[1], t, size=6, zorder=4, color='k')\n",
- "# for t, f in reprojected_points[fitter_pmts.index_image[test_image]].items():\n",
- "# ax.text(f[0], 3000-f[1], t, size=6, zorder=4, color='gray')\n",
- " ax.set_title(\"Image {}\".format(test_image))\n",
- " ax.set_ylim(0, 3000)\n",
- " ax.set_xlim(0, 4000)\n",
- " plt.legend(loc=0)\n",
- " fig.tight_layout()\n",
- " plt.savefig(saveLocation+\"image_plots/\"+test_image+\"-plot\"+imageExtension)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Save results to txt file"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 39,
- "metadata": {},
- "outputs": [],
- "source": [
- "fitter_all.save_result(saveLocation+\"SK_ring_features_relabelled.txt\", saveLocation+\"SK_ring_cameras_relabelled.txt\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Save results to pickle"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 40,
- "metadata": {},
- "outputs": [],
- "source": [
- "with open(saveLocation+\"SK_ring_relabelled.pkl\", 'wb') as output:\n",
- " pickle.dump(fitter_all, output, pickle.HIGHEST_PROTOCOL)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Plots of reconstructed geometry"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 41,
- "metadata": {},
- "outputs": [],
- "source": [
- "from matplotlib.legend_handler import HandlerPatch\n",
- "import matplotlib.patches as mpatches\n",
- "class HandlerArrow(HandlerPatch):\n",
- " def create_artists(self, legend, orig_handle,\n",
- " xdescent, ydescent, width, height, fontsize, trans):\n",
- " p = mpatches.FancyArrow(0, 0.5*height, width, 0, length_includes_head=True, head_width=0.75*height )\n",
- " self.update_prop(p, orig_handle, legend)\n",
- " p.set_transform(trans)\n",
- " return [p]"
+ "fig, ax = plt.subplots(figsize=(9,9))\n",
+ "pmt_array = np.stack(list(pmt_locations.values()))\n",
+ "ax.scatter(pmt_array[:,0], pmt_array[:,1], marker='o', label=\"PMT position\")\n",
+ "#ax.scatter(reco_transformed[:,0], reco_transformed[:,1], marker='+', label=\"reconstructed pmt position\", color=\"green\")\n",
+ "ax.scatter(camera_positions[:,0], camera_positions[:,1], marker='*', label=\"Fitted camera position\", zorder=1, color=\"orange\", s=100)\n",
+ "#for i, p in enumerate(camera_positions):\n",
+ "# ax.text(p[0], p[1], fitter_all.index_image[i], size=7, zorder=4, color='k')\n",
+ "for i, (p, o) in enumerate(zip(camera_positions, camera_orientations)):\n",
+ " fitarrow = plt.arrow(p[0], p[1], o[0,2]*200, o[1,2]*200, color=\"orange\", width=0.1, head_width=20, head_length=30)\n",
+ "for i, (p, y) in enumerate(zip(camera_positions, drone_yaw)):\n",
+ " dronearrow = plt.arrow(p[0], p[1], np.cos(y)*160, np.sin(y)*160, color=\"black\", width=0.01, head_width=20, head_length=30)\n",
+ "ax.set_ylim((-1800,1800))\n",
+ "ax.set_xlim((-1800,1800))\n",
+ "handles, labels = ax.get_legend_handles_labels()\n",
+ "handles.extend((fitarrow, dronearrow))\n",
+ "labels.extend((\"Fitted camera direction\", \"Drone sensor direction\"))\n",
+ "plt.legend(handles=handles, labels=labels, loc=0, handler_map={mpatches.FancyArrow : HandlerArrow()})\n",
+ "ax.axes.xaxis.set_visible(False)\n",
+ "ax.axes.yaxis.set_visible(False)\n",
+ "fig.tight_layout()\n",
+ "#fig.savefig(saveLocation+\"top\"+imageExtension)"
]
},
{
"cell_type": "code",
- "execution_count": 42,
+ "execution_count": 200,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([154.0157751, 148.0157751, 141.0157751, 137.0157751, 136.0157751,\n",
- " 123.0157751, 122.0157751, 113.0157751, 110.0157751, 103.0157751,\n",
- " 100.0157751, 95.0157751, 89.0157751, 81.0157751, 78.0157751,\n",
- " 70.0157751, 60.0157751, 59.0157751, 49.0157751, 46.0157751,\n",
- " 40.0157751, 35.0157751, 29.0157751, 17.0157751, 10.0157751,\n",
- " -3.9842249, -10.9842249, 342.0157751, 335.0157751, 315.0157751,\n",
- " 304.0157751, 297.0157751, 284.0157751, 277.0157751, 259.0157751,\n",
- " 248.0157751, 241.0157751, 232.0157751, 220.0157751, 217.0157751,\n",
- " 212.0157751, 202.0157751, 194.0157751, 186.0157751, 185.0157751,\n",
- " 183.0157751, 174.0157751, 174.0157751, 168.0157751, 162.0157751,\n",
- " 152.0157751])"
- ]
- },
- "execution_count": 42,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "drone_yaw*180/np.pi"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 43,
- "metadata": {
- "scrolled": false
- },
"outputs": [
{
"data": {
@@ -106263,6 +13707,10 @@
" '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",
@@ -106520,11 +13968,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -106534,7 +13985,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -106653,10 +14104,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -106664,18 +14115,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -106700,7 +14150,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -106710,6 +14160,19 @@
" // 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",
@@ -106720,8 +14183,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -106974,7 +14443,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -106985,31 +14454,29 @@
}
],
"source": [
- "fig, ax = plt.subplots(figsize=(9,9))\n",
+ "fig, ax = plt.subplots(figsize=(16,6))\n",
"pmt_array = np.stack(list(pmt_locations.values()))\n",
- "ax.scatter(pmt_array[:,0], pmt_array[:,1], marker='o', label=\"seed pmt position\")\n",
- "ax.scatter(reco_transformed[:,0], reco_transformed[:,1], marker='+', label=\"reconstructed pmt position\", color=\"green\")\n",
- "ax.scatter(camera_positions[:,0], camera_positions[:,1], marker='*', label=\"fitted camera position\", zorder=1, color=\"orange\")\n",
+ "ax.scatter(np.arctan2(pmt_array[:,1],pmt_array[:,0]), pmt_array[:,2], marker='o', label=\"seed pmt position\")\n",
+ "ax.scatter(np.arctan2(camera_positions[:,1], camera_positions[:,0]), camera_positions[:,2], marker='*', label=\"fitted camera position\", zorder=1)\n",
+ "ax.scatter(np.arctan2(reco_transformed[:,1], reco_transformed[:,0]), reco_transformed[:,2], marker='+', label=\"reconstructed pmt position\")\n",
"for i, p in enumerate(camera_positions):\n",
- " ax.text(p[0], p[1], fitter_all.index_image[i], size=7, zorder=4, color='k')\n",
- "for i, (p, o) in enumerate(zip(camera_positions, camera_orientations)):\n",
- " fitarrow = plt.arrow(p[0], p[1], o[0,2]*200, o[1,2]*200, color=\"orange\", width=0.1, head_width=20, head_length=30)\n",
- "for i, (p, y) in enumerate(zip(camera_positions, drone_yaw)):\n",
- " dronearrow = plt.arrow(p[0], p[1], np.cos(y)*160, np.sin(y)*160, color=\"black\", width=0.01, head_width=20, head_length=30)\n",
- "ax.set_ylim((-1800,1800))\n",
- "ax.set_xlim((-1800,1800))\n",
- "handles, labels = ax.get_legend_handles_labels()\n",
- "handles.extend((fitarrow, dronearrow))\n",
- "labels.extend((\"fitted camera yaw\", \"drone sensor yaw\"))\n",
- "plt.legend(handles=handles, labels=labels, loc=0, handler_map={mpatches.FancyArrow : HandlerArrow()})\n",
+ " ax.text(np.arctan2(p[1],p[0]), p[2], fitter_all.index_image[i], size=7, zorder=4, color='k') \n",
+ "ax.set_xlim((-np.pi,np.pi))\n",
+ "ax.set_ylim((100,500))\n",
+ "plt.legend(loc=0)\n",
"fig.tight_layout()\n",
- "fig.savefig(saveLocation+\"top\"+imageExtension)"
+ "fig.savefig(saveLocation+\"barrel\"+imageExtension)"
]
},
{
"cell_type": "code",
"execution_count": 44,
- "metadata": {},
+ "metadata": {
+ "pycharm": {
+ "is_executing": false
+ },
+ "scrolled": false
+ },
"outputs": [
{
"data": {
@@ -107261,6 +14728,10 @@
" '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",
@@ -107518,11 +14989,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -107532,7 +15006,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -107651,10 +15125,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -107662,18 +15136,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -107698,7 +15171,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -107708,6 +15181,19 @@
" // 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",
@@ -107718,8 +15204,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -107972,7 +15464,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -107983,29 +15475,22 @@
}
],
"source": [
- "fig, ax = plt.subplots(figsize=(16,6))\n",
- "pmt_array = np.stack(list(pmt_locations.values()))\n",
- "ax.scatter(np.arctan2(pmt_array[:,1],pmt_array[:,0]), pmt_array[:,2], marker='o', label=\"seed pmt position\")\n",
- "ax.scatter(np.arctan2(camera_positions[:,1], camera_positions[:,0]), camera_positions[:,2], marker='*', label=\"fitted camera position\", zorder=1)\n",
- "ax.scatter(np.arctan2(reco_transformed[:,1], reco_transformed[:,0]), reco_transformed[:,2], marker='+', label=\"reconstructed pmt position\")\n",
- "for i, p in enumerate(camera_positions):\n",
- " ax.text(np.arctan2(p[1],p[0]), p[2], fitter_all.index_image[i], size=7, zorder=4, color='k') \n",
- "ax.set_xlim((-np.pi,np.pi))\n",
- "ax.set_ylim((100,500))\n",
+ "fig = plt.figure(figsize=(12,9))\n",
+ "ax = fig.add_subplot(111, projection='3d')\n",
+ "ax.scatter(reco_transformed[:,0], reco_transformed[:,1], reco_transformed[:,2], marker='.', label=\"reconstructed\", zorder=3)\n",
+ "ax.scatter(pmt_array[:,0], pmt_array[:,1], pmt_array[:,2], marker='.', label=\"expected\", zorder=2)\n",
+ "for f in pmt_locations.keys():\n",
+ " i = fitter_all.feature_index[f]\n",
+ " ax.text(reco_transformed[i,0], reco_transformed[i,1], reco_transformed[i,2], f[:5], size=6, zorder=4, color='k') \n",
+ "#ax.scatter(camera_positions[:,0], camera_positions[:,1], camera_positions[:,2], marker='*', label=\"camera\", zorder=1)\n",
"plt.legend(loc=0)\n",
- "fig.tight_layout()\n",
- "fig.savefig(saveLocation+\"barrel\"+imageExtension)"
+ "fig.tight_layout()"
]
},
{
"cell_type": "code",
- "execution_count": 45,
- "metadata": {
- "pycharm": {
- "is_executing": false
- },
- "scrolled": false
- },
+ "execution_count": 201,
+ "metadata": {},
"outputs": [
{
"data": {
@@ -108257,6 +15742,10 @@
" '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",
@@ -108514,11 +16003,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -108528,7 +16020,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -108647,10 +16139,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -108658,18 +16150,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -108694,7 +16185,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -108704,6 +16195,19 @@
" // 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",
@@ -108714,8 +16218,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -108968,7 +16478,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -108981,12 +16491,13 @@
"source": [
"fig = plt.figure(figsize=(12,9))\n",
"ax = fig.add_subplot(111, projection='3d')\n",
- "ax.scatter(reco_transformed[:,0], reco_transformed[:,1], reco_transformed[:,2], marker='.', label=\"reconstructed\", zorder=3)\n",
- "ax.scatter(pmt_array[:,0], pmt_array[:,1], pmt_array[:,2], marker='.', label=\"expected\", zorder=2)\n",
- "for f in pmt_locations.keys():\n",
- " i = fitter_all.feature_index[f]\n",
- " ax.text(reco_transformed[i,0], reco_transformed[i,1], reco_transformed[i,2], f[:5], size=6, zorder=4, color='k') \n",
- "#ax.scatter(camera_positions[:,0], camera_positions[:,1], camera_positions[:,2], marker='*', label=\"camera\", zorder=1)\n",
+ "ax.scatter(reco_transformed[:,0], reco_transformed[:,1], reco_transformed[:,2], marker='.', label=\"reconstructed PMT\", zorder=3)\n",
+ "#ax.scatter(pmt_array[:,0], pmt_array[:,1], pmt_array[:,2], marker='.', label=\"expected\", zorder=2)\n",
+ "#for f in pmt_locations.keys():\n",
+ "# i = fitter_all.feature_index[f]\n",
+ "# ax.text(reco_transformed[i,0], reco_transformed[i,1], reco_transformed[i,2], f[:5], size=6, zorder=4, color='k') \n",
+ "ax.scatter(camera_positions[:,0], camera_positions[:,1], camera_positions[:,2], marker='*', label=\"reconstructed camera\", zorder=1)\n",
+ "ax.set_zlim3d(-1500,1500)\n",
"plt.legend(loc=0)\n",
"fig.tight_layout()"
]
@@ -109000,7 +16511,7 @@
},
{
"cell_type": "code",
- "execution_count": 46,
+ "execution_count": 202,
"metadata": {},
"outputs": [
{
@@ -109253,6 +16764,10 @@
" '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",
@@ -109510,11 +17025,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -109524,7 +17042,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -109643,10 +17161,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -109654,18 +17172,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -109690,7 +17207,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -109700,6 +17217,19 @@
" // 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",
@@ -109710,8 +17240,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -109964,7 +17500,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -109987,17 +17523,17 @@
},
{
"cell_type": "code",
- "execution_count": 47,
+ "execution_count": 203,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "[[ 0 33 33 ... 3 39 38]\n",
- " [ 0 384 383 ... 495 360 397]]\n",
+ "[[ 0 33 33 ... 39 3 38]\n",
+ " [ 0 379 378 ... 333 41 373]]\n",
"0.0\n",
- "02733-00\n"
+ "00593-00\n"
]
}
],
@@ -110017,7 +17553,7 @@
},
{
"cell_type": "code",
- "execution_count": 48,
+ "execution_count": 311,
"metadata": {
"pycharm": {
"is_executing": false
@@ -110275,6 +17811,10 @@
" '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",
@@ -110532,11 +18072,14 @@
"mpl.figure.prototype._make_on_message_function = function (fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
- " /* FIXME: We get \"Resource interpreted as Image but\n",
- " * transferred with MIME type text/plain:\" errors on\n",
- " * Chrome. But how to set the MIME type? It doesn't seem\n",
- " * to be part of the websocket stream */\n",
- " evt.data.type = 'image/png';\n",
+ " 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",
@@ -110546,7 +18089,7 @@
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
- " evt.data\n",
+ " img\n",
" );\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
@@ -110665,10 +18208,10 @@
"mpl.figure.prototype.key_event = function (event, name) {\n",
" // Prevent repeat events\n",
" if (name === 'key_press') {\n",
- " if (event.which === this._key) {\n",
+ " if (event.key === this._key) {\n",
" return;\n",
" } else {\n",
- " this._key = event.which;\n",
+ " this._key = event.key;\n",
" }\n",
" }\n",
" if (name === 'key_release') {\n",
@@ -110676,18 +18219,17 @@
" }\n",
"\n",
" var value = '';\n",
- " if (event.ctrlKey && event.which !== 17) {\n",
+ " if (event.ctrlKey && event.key !== 'Control') {\n",
" value += 'ctrl+';\n",
" }\n",
- " if (event.altKey && event.which !== 18) {\n",
+ " else if (event.altKey && event.key !== 'Alt') {\n",
" value += 'alt+';\n",
" }\n",
- " if (event.shiftKey && event.which !== 16) {\n",
+ " else if (event.shiftKey && event.key !== 'Shift') {\n",
" value += 'shift+';\n",
" }\n",
"\n",
- " value += 'k';\n",
- " value += event.which.toString();\n",
+ " value += 'k' + event.key;\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
@@ -110712,7 +18254,7 @@
"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\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";/* global mpl */\n",
"\n",
@@ -110722,6 +18264,19 @@
" // 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",
@@ -110732,8 +18287,14 @@
" // 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(msg['content']['data']);\n",
+ " ws.onmessage(data);\n",
" });\n",
" return ws;\n",
"};\n",
@@ -110986,7 +18547,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -110998,9 +18559,9 @@
],
"source": [
"fig, ax = plt.subplots(figsize=(8,6))\n",
- "ax.hist(linalg.norm(errors, axis=1), bins='auto')\n",
- "ax.set_title(\"Reconstructed position distance from expected ({} images, {} features), mean = {:.2f} cm\".format(\n",
- " nimages, nfeatures, linalg.norm(errors, axis=1).mean()))\n",
+ "ax.hist(np.sqrt(variance_3d), bins=range(20), color=\"b\", histtype=\"step\", label=f\"Estimated 3D position error\\nmean = {np.mean(np.sqrt(variance_3d)):.3} cm\")\n",
+ "ax.hist(linalg.norm(errors, axis=1), bins=range(20), color=\"r\", histtype=\"step\", label=f\"Reconstructed position distance\\nfrom expected geometry\\nmean = {np.mean(linalg.norm(errors, axis=1)):.2f} cm\")\n",
+ "plt.legend(loc=\"upper right\", prop={'size': 15})\n",
"fig.tight_layout()\n",
"fig.savefig(saveLocation+\"distance from expected.png\")"
]
@@ -111029,7 +18590,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.9.2"
+ "version": "3.9.4"
},
"pycharm": {
"stem_cell": {
diff --git a/WCTE_16cShort_led_simulation.ipynb b/WCTE_16cShort_led_simulation.ipynb
new file mode 100644
index 0000000..7bf9bf3
--- /dev/null
+++ b/WCTE_16cShort_led_simulation.ipynb
@@ -0,0 +1,3552 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {
+ "pycharm": {
+ "is_executing": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "from scipy import linalg\n",
+ "from scipy.spatial.transform import Rotation as R\n",
+ "from mpl_toolkits.mplot3d import Axes3D\n",
+ "import matplotlib.pyplot as plt\n",
+ "import matplotlib.collections\n",
+ "import matplotlib.patches\n",
+ "import pg_fitter_tools as fit\n",
+ "import sk_geo_tools as geo\n",
+ "import cv2\n",
+ "from collections import Counter"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "from IPython.core.display import display, HTML\n",
+ "display(HTML(\"\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "pycharm": {
+ "is_executing": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "#%matplotlib notebook\n",
+ "%load_ext autoreload\n",
+ "%autoreload 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_led_positions(led_count, mpmt_locations):\n",
+ " led_ring_radius = 24.\n",
+ " led_positions = {}\n",
+ " for k, v in mpmt_locations.items():\n",
+ " for i in range(led_count):\n",
+ " if abs(v[1]) > 100:\n",
+ " led_positions[k+'-'+str(i)] = v+led_ring_radius*np.array([np.sin(i*2*np.pi/led_count),0,np.cos(i*2*np.pi/led_count)])\n",
+ " else:\n",
+ " phi = np.arctan2(v[2], v[0])\n",
+ " led_positions[k+'-'+str(i)] = v+led_ring_radius*np.array([np.sin(i*2*np.pi/led_count)*np.sin(phi), np.cos(i*2*np.pi/led_count), -np.sin(i*2*np.pi/led_count)*np.cos(phi)])\n",
+ " return led_positions"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_image_feature_locations(feature_positions, camera_matrix, distortion, camera_rotations, camera_translations, image_size):\n",
+ " image_feature_locations = {\n",
+ " i : {list(feature_positions.keys())[f]:v for f, v in enumerate(cv2.projectPoints(np.array(list(feature_positions.values())), r, t, camera_matrix, distortion)[0].reshape((-1,2)))\n",
+ " if v[0] > 0 and v[0] < image_size[0] and v[1] > 0 and v[1] < image_size[1]}\n",
+ " for i, (r, t) in enumerate(zip(camera_rotations, camera_translations))}\n",
+ " feature_counts = Counter([f for i in image_feature_locations.values() for f in i.keys()])\n",
+ " print(\"Feature in image counts:\", Counter(feature_counts.values()))\n",
+ " return image_feature_locations"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_smeared_feature_locations(image_feature_locations, pixel_error, image_size):\n",
+ " smeared_feature_locations = {}\n",
+ " for k, i in image_feature_locations.items():\n",
+ " smeared_feature_locations[k] = {}\n",
+ " for j, f in i.items():\n",
+ " smeared = np.random.normal(f, pixel_error)\n",
+ " if(smeared[0] > 0 and smeared[0] < image_size[0] and smeared[1] > 0 and smeared[1] < image_size[1]):\n",
+ " smeared_feature_locations[k][j] = smeared\n",
+ " smeared_feature_counts = Counter([f for i in smeared_feature_locations.values() for f in i.keys()])\n",
+ " print(\"Smeared feature in image counts:\", Counter(smeared_feature_counts.values()))\n",
+ " return smeared_feature_locations"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def setup_led_simulation(feature_positions, image_feature_locations, focal_length, principle_point, radial_distortion, seed_error=1):\n",
+ " seed_feature_positions = {}\n",
+ " for i, f in feature_positions.items():\n",
+ " seed_feature_positions[i] = np.random.normal(f, seed_error)\n",
+ " fitter = fit.PhotogrammetryFitter(image_feature_locations, seed_feature_positions, focal_length, principle_point, radial_distortion)\n",
+ " return fitter"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plot_images(image_feature_locations, image_size):\n",
+ " for i in image_feature_locations.values():\n",
+ " fig, ax = plt.subplots(figsize=(12,9))\n",
+ " coords = np.rint(np.stack(list(i.values())))\n",
+ " ax.scatter(coords[:,0], -coords[:,1], marker='s', s=0.2)\n",
+ " ax.set_xlim((0, image_size[0]))\n",
+ " ax.set_ylim((-image_size[1], 0))\n",
+ " ax.axes.xaxis.set_visible(False)\n",
+ " ax.axes.yaxis.set_visible(False)\n",
+ " fig.tight_layout()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def run_led_fit(fitter, led_positions):\n",
+ " reco_cam_rotations, reco_cam_translations, reprojected_points = fitter.estimate_camera_poses()\n",
+ " reco_cam_rotations, reco_cam_translations, reco_locations = fitter.bundle_adjustment(reco_cam_rotations, reco_cam_translations)\n",
+ " \n",
+ " reco_errors, reco_transformed, scale, R, translation, _ = fit.kabsch_errors(led_positions, reco_locations)\n",
+ " print(\"mean reconstruction error:\", linalg.norm(reco_errors, axis=1).mean())\n",
+ " print(\"max reconstruction error:\", linalg.norm(reco_errors, axis=1).max())\n",
+ "\n",
+ " reco_cam_orientations, reco_cam_positions = fit.camera_world_poses(reco_cam_rotations, reco_cam_translations)\n",
+ " cam_orientations_transformed = np.matmul(R, reco_cam_orientations)\n",
+ " cam_positions_translated = reco_cam_positions - translation\n",
+ " cam_positions_transformed = scale*R.dot(cam_positions_translated.transpose()).transpose()\n",
+ "\n",
+ " reco_led_positions = reco_positions_dict(reco_transformed, fitter.feature_index)\n",
+ " position_errors = linalg.norm(reco_errors, axis=1)\n",
+ "\n",
+ " return reco_led_positions, position_errors"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def reco_positions_dict(reco_positions, feature_index):\n",
+ " return {f: reco_positions[i] for f, i in feature_index.items()}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_mpmt_centre_errors(reco_led_positions, mpmt_positions, led_count):\n",
+ " reco_mpmt_positions = {k: np.mean([reco_led_positions[k + \"-\" + str(b)] for b in range(led_count)], axis=0)\n",
+ " for k in mpmt_positions.keys()}\n",
+ " errors = np.array([linalg.norm(reco_mpmt_positions[k] - mpmt_positions[k]) for k in mpmt_positions.keys()])\n",
+ " return errors"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def get_mpmt_orientation_errors(reco_led_positions, mpmt_orientations, led_coun):\n",
+ " reco_orientations = {}\n",
+ " for k in mpmt_orientations.keys():\n",
+ " c, n = geo.fit_plane(np.array([reco_led_positions[k + \"-\" + str(b)] for b in range(led_count)]))\n",
+ " # flip normal if it is directed away from tank centre\n",
+ " if np.dot(n,c) > 0:\n",
+ " n = -n\n",
+ " reco_orientations[k] = n\n",
+ " errors = np.array([np.degrees(np.arccos(np.dot(reco_orientations[k], mpmt_orientations[k]))) for k in mpmt_orientations.keys()])\n",
+ " return errors"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_fig(title=None, xlabel=None, ylabel=None, figsize=(8,6)):\n",
+ " fig, ax = plt.subplots(figsize=figsize)\n",
+ " ax.set_title(title)\n",
+ " ax.set_xlabel(xlabel)\n",
+ " ax.set_ylabel(ylabel)\n",
+ " fig.tight_layout()\n",
+ " return fig, ax"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plot_geometry(led_positions, cam_positions):\n",
+ " fig = plt.figure(figsize=(12,9))\n",
+ " ax = fig.add_subplot(111, projection='3d')\n",
+ " ax.scatter([l[0] for l in led_positions.values()], [l[2] for l in led_positions.values()], [l[1] for l in led_positions.values()], marker='*', label=\"LED\", s=1)\n",
+ " ax.scatter(cam_positions[:,0], cam_positions[:,2], cam_positions[:,1], marker='o', label=\"Camera\", s=60)\n",
+ " plt.legend(loc=0)\n",
+ " fig.tight_layout()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plot_reconstruction(reco_positions, cam_positions):\n",
+ " fig = plt.figure(figsize=(12,9))\n",
+ " ax = fig.add_subplot(111, projection='3d')\n",
+ " ax.scatter(reco_positions[:,0], reco_positions[:,2], reco_positions[:,1], marker='*', label=\"LED\", s=1)\n",
+ " ax.scatter(cam_positions[:,0], cam_positions[:,2], cam_positions[:,1], marker='o', label=\"Camera\", s=60)\n",
+ " plt.legend(loc=0)\n",
+ " fig.tight_layout()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pixel_errors = [1.0, 3.0, 5.0, 10.0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [],
+ "source": [
+ "pmt_locations = fit.read_3d_feature_locations(\"parameters/WCTE_16cShort_PMT_locations.txt\", delimiter=\" \")\n",
+ "#mpmt_locations = {k: v for k, v in pmt_locations.items() if int(k)%19==0}\n",
+ "mpmt_locations = fit.read_3d_feature_locations(\"parameters/WCTE_16cShort_centrePMT_locations.txt\", delimiter=\" \")\n",
+ "mpmt_orientations = {k: np.array((0,-1,0)) if v[1]>100\n",
+ " else np.array((0,1,0)) if v[1]<-100\n",
+ " else np.array((-v[0],0,-v[2]))/np.sqrt(v[0]**2+v[2]**2)\n",
+ " for k, v in mpmt_locations.items()}\n",
+ "led_count = 12\n",
+ "led_positions = get_led_positions(led_count, mpmt_locations)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'19': array([160.01661746, 26.7375 , 31.8292842 ]),\n",
+ " '38': array([135.65553801, 26.7375 , 90.64213261]),\n",
+ " '57': array([ 90.64213261, 26.7375 , 135.65553801]),\n",
+ " '76': array([ 31.8292842 , 26.7375 , 160.01661746]),\n",
+ " '95': array([-31.8292842 , 26.7375 , 160.01661746]),\n",
+ " '114': array([-90.64213261, 26.7375 , 135.65553801]),\n",
+ " '133': array([-135.65553801, 26.7375 , 90.64213261]),\n",
+ " '152': array([-160.01661746, 26.7375 , 31.8292842 ]),\n",
+ " '171': array([-160.01661746, 26.7375 , -31.8292842 ]),\n",
+ " '190': array([-135.65553801, 26.7375 , -90.64213261]),\n",
+ " '209': array([ -90.64213261, 26.7375 , -135.65553801]),\n",
+ " '228': array([ -31.8292842 , 26.7375 , -160.01661746]),\n",
+ " '247': array([ 31.8292842 , 26.7375 , -160.01661746]),\n",
+ " '266': array([ 90.64213261, 26.7375 , -135.65553801]),\n",
+ " '285': array([135.65553801, 26.7375 , -90.64213261]),\n",
+ " '304': array([160.01661746, 26.7375 , -31.8292842 ]),\n",
+ " '323': array([160.01661746, -26.7375 , 31.8292842 ]),\n",
+ " '342': array([135.65553801, -26.7375 , 90.64213261]),\n",
+ " '361': array([ 90.64213261, -26.7375 , 135.65553801]),\n",
+ " '380': array([ 31.8292842 , -26.7375 , 160.01661746]),\n",
+ " '399': array([-31.8292842 , -26.7375 , 160.01661746]),\n",
+ " '418': array([-90.64213261, -26.7375 , 135.65553801]),\n",
+ " '437': array([-135.65553801, -26.7375 , 90.64213261]),\n",
+ " '456': array([-160.01661746, -26.7375 , 31.8292842 ]),\n",
+ " '475': array([-160.01661746, -26.7375 , -31.8292842 ]),\n",
+ " '494': array([-135.65553801, -26.7375 , -90.64213261]),\n",
+ " '513': array([ -90.64213261, -26.7375 , -135.65553801]),\n",
+ " '532': array([ -31.8292842 , -26.7375 , -160.01661746]),\n",
+ " '551': array([ 31.8292842 , -26.7375 , -160.01661746]),\n",
+ " '570': array([ 90.64213261, -26.7375 , -135.65553801]),\n",
+ " '589': array([135.65553801, -26.7375 , -90.64213261]),\n",
+ " '608': array([160.01661746, -26.7375 , -31.8292842 ]),\n",
+ " '627': array([160.01661746, -80.2125 , 31.8292842 ]),\n",
+ " '646': array([135.65553801, -80.2125 , 90.64213261]),\n",
+ " '665': array([ 90.64213261, -80.2125 , 135.65553801]),\n",
+ " '684': array([ 31.8292842 , -80.2125 , 160.01661746]),\n",
+ " '703': array([-31.8292842 , -80.2125 , 160.01661746]),\n",
+ " '722': array([-90.64213261, -80.2125 , 135.65553801]),\n",
+ " '741': array([-135.65553801, -80.2125 , 90.64213261]),\n",
+ " '760': array([-160.01661746, -80.2125 , 31.8292842 ]),\n",
+ " '779': array([-160.01661746, -80.2125 , -31.8292842 ]),\n",
+ " '798': array([-135.65553801, -80.2125 , -90.64213261]),\n",
+ " '817': array([ -90.64213261, -80.2125 , -135.65553801]),\n",
+ " '836': array([ -31.8292842 , -80.2125 , -160.01661746]),\n",
+ " '855': array([ 31.8292842 , -80.2125 , -160.01661746]),\n",
+ " '874': array([ 90.64213261, -80.2125 , -135.65553801]),\n",
+ " '893': array([135.65553801, -80.2125 , -90.64213261]),\n",
+ " '912': array([160.01661746, -80.2125 , -31.8292842 ]),\n",
+ " '931': array([-116. , -128.05152833, -58. ]),\n",
+ " '950': array([-116. , -128.05152833, 0. ]),\n",
+ " '969': array([-116. , -128.05152833, 58. ]),\n",
+ " '988': array([ -58. , -128.05152833, -116. ]),\n",
+ " '1007': array([ -58. , -128.05152833, -58. ]),\n",
+ " '1026': array([ -58. , -128.05152833, 0. ]),\n",
+ " '1045': array([ -58. , -128.05152833, 58. ]),\n",
+ " '1064': array([ -58. , -128.05152833, 116. ]),\n",
+ " '1083': array([ 0. , -128.05152833, -116. ]),\n",
+ " '1102': array([ 0. , -128.05152833, -58. ]),\n",
+ " '1121': array([ 0. , -128.05152833, 0. ]),\n",
+ " '1140': array([ 0. , -128.05152833, 58. ]),\n",
+ " '1159': array([ 0. , -128.05152833, 116. ]),\n",
+ " '1178': array([ 58. , -128.05152833, -116. ]),\n",
+ " '1197': array([ 58. , -128.05152833, -58. ]),\n",
+ " '1216': array([ 58. , -128.05152833, 0. ]),\n",
+ " '1235': array([ 58. , -128.05152833, 58. ]),\n",
+ " '1254': array([ 58. , -128.05152833, 116. ]),\n",
+ " '1273': array([ 116. , -128.05152833, -58. ]),\n",
+ " '1292': array([ 116. , -128.05152833, 0. ]),\n",
+ " '1311': array([ 116. , -128.05152833, 58. ]),\n",
+ " '1330': array([160.01661746, 80.2125 , 31.8292842 ]),\n",
+ " '1349': array([135.65553801, 80.2125 , 90.64213261]),\n",
+ " '1368': array([ 90.64213261, 80.2125 , 135.65553801]),\n",
+ " '1387': array([ 31.8292842 , 80.2125 , 160.01661746]),\n",
+ " '1406': array([-31.8292842 , 80.2125 , 160.01661746]),\n",
+ " '1425': array([-90.64213261, 80.2125 , 135.65553801]),\n",
+ " '1444': array([-135.65553801, 80.2125 , 90.64213261]),\n",
+ " '1463': array([-160.01661746, 80.2125 , 31.8292842 ]),\n",
+ " '1482': array([-160.01661746, 80.2125 , -31.8292842 ]),\n",
+ " '1501': array([-135.65553801, 80.2125 , -90.64213261]),\n",
+ " '1520': array([ -90.64213261, 80.2125 , -135.65553801]),\n",
+ " '1539': array([ -31.8292842 , 80.2125 , -160.01661746]),\n",
+ " '1558': array([ 31.8292842 , 80.2125 , -160.01661746]),\n",
+ " '1577': array([ 90.64213261, 80.2125 , -135.65553801]),\n",
+ " '1596': array([135.65553801, 80.2125 , -90.64213261]),\n",
+ " '1615': array([160.01661746, 80.2125 , -31.8292842 ]),\n",
+ " '1634': array([-116. , 128.05152833, -58. ]),\n",
+ " '1653': array([-116. , 128.05152833, 0. ]),\n",
+ " '1672': array([-116. , 128.05152833, 58. ]),\n",
+ " '1691': array([ -58. , 128.05152833, -116. ]),\n",
+ " '1710': array([-58. , 128.05152833, -58. ]),\n",
+ " '1729': array([-58. , 128.05152833, 0. ]),\n",
+ " '1748': array([-58. , 128.05152833, 58. ]),\n",
+ " '1767': array([-58. , 128.05152833, 116. ]),\n",
+ " '1786': array([ 0. , 128.05152833, -116. ]),\n",
+ " '1805': array([ 0. , 128.05152833, -58. ]),\n",
+ " '1824': array([ 0. , 128.05152833, 0. ]),\n",
+ " '1843': array([ 0. , 128.05152833, 58. ]),\n",
+ " '1862': array([ 0. , 128.05152833, 116. ]),\n",
+ " '1881': array([ 58. , 128.05152833, -116. ]),\n",
+ " '1900': array([ 58. , 128.05152833, -58. ]),\n",
+ " '1919': array([ 58. , 128.05152833, 0. ]),\n",
+ " '1938': array([ 58. , 128.05152833, 58. ]),\n",
+ " '1957': array([ 58. , 128.05152833, 116. ]),\n",
+ " '1976': array([116. , 128.05152833, -58. ]),\n",
+ " '1995': array([116. , 128.05152833, 0. ]),\n",
+ " '2014': array([116. , 128.05152833, 58. ])}"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mpmt_locations"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{'19': array([-0.98078528, 0. , -0.19509032]),\n",
+ " '38': array([-0.83146961, 0. , -0.55557023]),\n",
+ " '57': array([-0.55557023, 0. , -0.83146961]),\n",
+ " '76': array([-0.19509032, 0. , -0.98078528]),\n",
+ " '95': array([ 0.19509032, 0. , -0.98078528]),\n",
+ " '114': array([ 0.55557023, 0. , -0.83146961]),\n",
+ " '133': array([ 0.83146961, 0. , -0.55557023]),\n",
+ " '152': array([ 0.98078528, 0. , -0.19509032]),\n",
+ " '171': array([0.98078528, 0. , 0.19509032]),\n",
+ " '190': array([0.83146961, 0. , 0.55557023]),\n",
+ " '209': array([0.55557023, 0. , 0.83146961]),\n",
+ " '228': array([0.19509032, 0. , 0.98078528]),\n",
+ " '247': array([-0.19509032, 0. , 0.98078528]),\n",
+ " '266': array([-0.55557023, 0. , 0.83146961]),\n",
+ " '285': array([-0.83146961, 0. , 0.55557023]),\n",
+ " '304': array([-0.98078528, 0. , 0.19509032]),\n",
+ " '323': array([-0.98078528, 0. , -0.19509032]),\n",
+ " '342': array([-0.83146961, 0. , -0.55557023]),\n",
+ " '361': array([-0.55557023, 0. , -0.83146961]),\n",
+ " '380': array([-0.19509032, 0. , -0.98078528]),\n",
+ " '399': array([ 0.19509032, 0. , -0.98078528]),\n",
+ " '418': array([ 0.55557023, 0. , -0.83146961]),\n",
+ " '437': array([ 0.83146961, 0. , -0.55557023]),\n",
+ " '456': array([ 0.98078528, 0. , -0.19509032]),\n",
+ " '475': array([0.98078528, 0. , 0.19509032]),\n",
+ " '494': array([0.83146961, 0. , 0.55557023]),\n",
+ " '513': array([0.55557023, 0. , 0.83146961]),\n",
+ " '532': array([0.19509032, 0. , 0.98078528]),\n",
+ " '551': array([-0.19509032, 0. , 0.98078528]),\n",
+ " '570': array([-0.55557023, 0. , 0.83146961]),\n",
+ " '589': array([-0.83146961, 0. , 0.55557023]),\n",
+ " '608': array([-0.98078528, 0. , 0.19509032]),\n",
+ " '627': array([-0.98078528, 0. , -0.19509032]),\n",
+ " '646': array([-0.83146961, 0. , -0.55557023]),\n",
+ " '665': array([-0.55557023, 0. , -0.83146961]),\n",
+ " '684': array([-0.19509032, 0. , -0.98078528]),\n",
+ " '703': array([ 0.19509032, 0. , -0.98078528]),\n",
+ " '722': array([ 0.55557023, 0. , -0.83146961]),\n",
+ " '741': array([ 0.83146961, 0. , -0.55557023]),\n",
+ " '760': array([ 0.98078528, 0. , -0.19509032]),\n",
+ " '779': array([0.98078528, 0. , 0.19509032]),\n",
+ " '798': array([0.83146961, 0. , 0.55557023]),\n",
+ " '817': array([0.55557023, 0. , 0.83146961]),\n",
+ " '836': array([0.19509032, 0. , 0.98078528]),\n",
+ " '855': array([-0.19509032, 0. , 0.98078528]),\n",
+ " '874': array([-0.55557023, 0. , 0.83146961]),\n",
+ " '893': array([-0.83146961, 0. , 0.55557023]),\n",
+ " '912': array([-0.98078528, 0. , 0.19509032]),\n",
+ " '931': array([0, 1, 0]),\n",
+ " '950': array([0, 1, 0]),\n",
+ " '969': array([0, 1, 0]),\n",
+ " '988': array([0, 1, 0]),\n",
+ " '1007': array([0, 1, 0]),\n",
+ " '1026': array([0, 1, 0]),\n",
+ " '1045': array([0, 1, 0]),\n",
+ " '1064': array([0, 1, 0]),\n",
+ " '1083': array([0, 1, 0]),\n",
+ " '1102': array([0, 1, 0]),\n",
+ " '1121': array([0, 1, 0]),\n",
+ " '1140': array([0, 1, 0]),\n",
+ " '1159': array([0, 1, 0]),\n",
+ " '1178': array([0, 1, 0]),\n",
+ " '1197': array([0, 1, 0]),\n",
+ " '1216': array([0, 1, 0]),\n",
+ " '1235': array([0, 1, 0]),\n",
+ " '1254': array([0, 1, 0]),\n",
+ " '1273': array([0, 1, 0]),\n",
+ " '1292': array([0, 1, 0]),\n",
+ " '1311': array([0, 1, 0]),\n",
+ " '1330': array([-0.98078528, 0. , -0.19509032]),\n",
+ " '1349': array([-0.83146961, 0. , -0.55557023]),\n",
+ " '1368': array([-0.55557023, 0. , -0.83146961]),\n",
+ " '1387': array([-0.19509032, 0. , -0.98078528]),\n",
+ " '1406': array([ 0.19509032, 0. , -0.98078528]),\n",
+ " '1425': array([ 0.55557023, 0. , -0.83146961]),\n",
+ " '1444': array([ 0.83146961, 0. , -0.55557023]),\n",
+ " '1463': array([ 0.98078528, 0. , -0.19509032]),\n",
+ " '1482': array([0.98078528, 0. , 0.19509032]),\n",
+ " '1501': array([0.83146961, 0. , 0.55557023]),\n",
+ " '1520': array([0.55557023, 0. , 0.83146961]),\n",
+ " '1539': array([0.19509032, 0. , 0.98078528]),\n",
+ " '1558': array([-0.19509032, 0. , 0.98078528]),\n",
+ " '1577': array([-0.55557023, 0. , 0.83146961]),\n",
+ " '1596': array([-0.83146961, 0. , 0.55557023]),\n",
+ " '1615': array([-0.98078528, 0. , 0.19509032]),\n",
+ " '1634': array([ 0, -1, 0]),\n",
+ " '1653': array([ 0, -1, 0]),\n",
+ " '1672': array([ 0, -1, 0]),\n",
+ " '1691': array([ 0, -1, 0]),\n",
+ " '1710': array([ 0, -1, 0]),\n",
+ " '1729': array([ 0, -1, 0]),\n",
+ " '1748': array([ 0, -1, 0]),\n",
+ " '1767': array([ 0, -1, 0]),\n",
+ " '1786': array([ 0, -1, 0]),\n",
+ " '1805': array([ 0, -1, 0]),\n",
+ " '1824': array([ 0, -1, 0]),\n",
+ " '1843': array([ 0, -1, 0]),\n",
+ " '1862': array([ 0, -1, 0]),\n",
+ " '1881': array([ 0, -1, 0]),\n",
+ " '1900': array([ 0, -1, 0]),\n",
+ " '1919': array([ 0, -1, 0]),\n",
+ " '1938': array([ 0, -1, 0]),\n",
+ " '1957': array([ 0, -1, 0]),\n",
+ " '1976': array([ 0, -1, 0]),\n",
+ " '1995': array([ 0, -1, 0]),\n",
+ " '2014': array([ 0, -1, 0])}"
+ ]
+ },
+ "execution_count": 19,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mpmt_orientations"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pixel_errors = [1.0, 3.0, 5.0, 10.0]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Simulation with Sony A6000"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {
+ "pycharm": {
+ "is_executing": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "focal_length = np.array([2925.84685880484, 2930.0351899542])\n",
+ "principle_point = np.array([3000, 2000])\n",
+ "radial_distortion = np.array([-0.251288719187471, 0.0622370807856553])#[-0.28009, 0.11246, -0.02736])\n",
+ "tangential_distortion = np.array([0, 0])\n",
+ "camera_matrix = fit.build_camera_matrix(focal_length, principle_point)\n",
+ "distortion = fit.build_distortion_array(radial_distortion, tangential_distortion)\n",
+ "image_size = np.array([6000, 4000])\n",
+ "image_area = [[0,image_size[0]],[0,image_size[1]]]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 4 camera configuration"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "camera_radial_position = 163.0\n",
+ "camera_halfz_position = 128.0\n",
+ "camera_positions = np.array([\n",
+ " [ camera_radial_position/np.sqrt(2), camera_halfz_position, camera_radial_position/np.sqrt(2)],\n",
+ " [ camera_radial_position/np.sqrt(2), camera_halfz_position, -camera_radial_position/np.sqrt(2)],\n",
+ " [-camera_radial_position/np.sqrt(2), -camera_halfz_position, camera_radial_position/np.sqrt(2)],\n",
+ " [-camera_radial_position/np.sqrt(2), -camera_halfz_position, -camera_radial_position/np.sqrt(2)]])\n",
+ "camera_directions = [[-1, -1.9, -1],\n",
+ " [-1, -1.9, 1],\n",
+ " [ 1, 1.9, -1],\n",
+ " [ 1, 1.9, 1]]\n",
+ "camera_directions = camera_directions / linalg.norm(camera_directions, axis=1, keepdims=True)\n",
+ "camera_rolls = np.array([0.0, 0.0, 0.0, 0.0])#[np.pi/2, np.pi/2, np.pi/2, np.pi/2])\n",
+ "camera_rotations, camera_translations = fit.camera_poses(camera_positions, camera_directions, camera_rolls)\n",
+ "camera_count = camera_positions.shape[0]\n",
+ "simulator = fit.PhotogrammetrySimulator(led_positions, focal_length, principle_point, camera_rotations, camera_translations, radial_distortion, tangential_distortion)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Total number of features: 1272\n",
+ "Number of features in more than one image: 1272\n",
+ "Feature in image counts: Counter({2: 696, 4: 432, 3: 144})\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1gAAAKACAYAAACBhdleAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAA7GUlEQVR4nO3dO24kSZowWuNFa6M00PUro9zeA6nECjzkWkRvw+FKL6IWUTJjAwyFpY/6K6PcbqCUkf0KzJhkMhnB8Kd9ZnYOkCiAlQ9zt7eb2WcP4zgmAAAAlvt/cicAAACgFiZYAAAAKzHBAgAAWIkJFgAAwEpMsAAAAFbylym/+Zdffhn//ve/b5QU+Nn//M//pP/+7/9O//mf/5n+4z/+I3dygBXkqtfaE6iTuk0uf/zxx7/Gcfw/H38+aYL197//Pb2+vq6XKvjC8XhM//Vf/5UOh0N6fn7OnRxgBbnqtfYE6qRuk8vDw8P//ezntggSWt/3qeu61Pd97qQQwPl8TsfjMZ3P5yx/nnXkqtfakxjWqIfqMu+p20TzMOWi4aenp9EKFpDL8XhMp9MpdV036yvl0j8PLLdGPVSXgQgeHh7+GMfx6ePPJ20RBMjp8nVy7lfKpX8eWG6NeqguA5FVsYJ1Pp/TMAyp7/t0OBxyJwcAAFighPH9tRWsKs5gDcOQTqdTGoYhd1IAVuGMCVMpM0BNSh7fV7FF0FYBoDaXjiWl5IwJd1FmgJqUPL6vYoIlLCdQm5I7FvJQZoCalDy+r+IMFgAAwJ6qPoMFAAAQgQkWizhUDQDUyjiHOUywWKTkCC/sr7SOqrT0Qg6l1ZPS0ktexjnMUUWQC/JxqJopSotyVlp6IYfS6klp6SUv4xzmMMFikZIjvERUwqV6S5TWUZWWXsihtHpSWnqnqr0f2ZtxDnOIIgiBHI/HdDqdUtd1GnQAJtOPwH5EEYQC9H2fuq6r9ssqfGarMzHO2tAi/QjkZwULgKy2+uLuSz4AW7q2guUMFgBZbXUmpvazNgDEZAULAABgImewAAAANmaCRVUcageAcunHqYEzWFTFBZIAUC79ODWwgkVVhKelZL7cshZliVLpx6mBIBcAQQgrzlqUJYDtCdMOEJyw4qxFWQLIxwoWAADARMK0w46cf6ib/KVFyn3d5C+sxwQLNnCJgjQMQ+6k7KalzrnF/IXWyn1LbVpK7eUvbMkZLNhAi+cfWgqt22L+QmvlvqU2LaX28he25AwWfHA+n9MwDKnv+3Q4HHInpxjeG1ATbdp03hmtuXYGywQLPhDeGACm03/SGkEu4E4uOYRt5Trb0tqZGtib/hPemGDBB4fDIT0/P4fZ3mBQSG1yHaZ3iJ8aReojovWfkIsgFxBcawetqV+uw/QO8VMjfQTEY4IFwRkUUpvLV+5W/l3Ykj4C4rFFEDa0xtYNWy4AuGZpHxFpiyHUwgoWbMjWDQAi00/B+qxgsQlfxN6IqMRS6hK3KB8spZ96oy6xJvdgsQl3YcA61CVuUT5gHeoSc1y7B8sWQTbh0C2sQ13iFuUD1qEusSYrWFCh8/mchmFIfd8LjgFQAO02lMcKFjTEoWWAsmi3oR4mWFAhWx0AyqLdhnqIIggVcnfWNkSZAvVgK9ptqIcJFsCdLlt4hmHInZSQahp41/Qsa1MPAG6zRRDgTrbw3FbTGZKanmVt6gHAbVawbvAFE+7TSl2xhee2mi4srelZ1tZSPWilbYMl1JOfCdN+g0vn4D7qSizCPZdL3sWibYOvtVxPhGmfwTYI3jPwuU5dicX2tnLJu1i0bdfpE7lQT35mBQvu1PIXGsqyZOBj0LTM0vfn/VMKfSJYwYLFfKGhFJczMnNYQVlm6ftbknewJ30iXGeCBXcy8KEFBk3LeH+0Qp8I19kiCAAAMNG1LYLCtAMAAKzEBAsAAGAlJljQGBcCAuSh/YU2mGBBYy5RzoZhyJ0UAjIAXMb74xbtL7RBFEFojChn3CJM+zLeH7dof6ENVrCgMZfQui4x/ZGVhzd936eu6wwAZ/L+3qhPn9P+QhtMsACSrTsXSwaAtQyqlzyHAfQb9QlomS2CAMnWnTXUsj2ulufISX0CWlbcClYtX0hrJG/4TCnlwsrDcrVsj6vlOXIqpT6V0j6xP2UjpmLyZRzHu389Pj6OuXVdN6aUxq7rcieFD+QNn1Eu8nh5eRm7rhtfXl5yJ4U7ybP9aZ+4RtmIKVq+pJRex0/mTMVtEbTtIC55w2eUizxscyuPPNuf9olrlI2YSsmXh7fJ132enp7G19fXDZMDwBrO53MahiH1fR9+mxZv5BlAWR4eHv4Yx/Hpp5+bYAEAAExzbYJVXJALAACAqEywAAAAVmKCBd8UE/qTL8lLKJO6Wwf5SOtMsOCbSwSvYRhyJ6V5SztneRnf3gMwA74yLKm78jgObTCtKy5MO2yllNCfLVgarlpexrd3SHIh0MuwpO7K4zi0wbTOBAu+ORwOOuUglnbO8jK+vQdgBnxlWFJ35XEc2mBaJ0w7AADARMK0AwAAbMwEKzOHcslBubvN+4F51J3bvB9yUO72Z4KVmUg75NBCuVvSoUR+PzpKIpeBuXUn8jOtKXLbQr2Uu/0JcpGZQ7nk0EK5WxJRLPL7ESmNyGVgbt2J/Exrity2UC/lLoNxHO/+9fj4ONKOl5eXseu68eXlJXdSYLJay2+tz8X9aiwDNT4T7VB+25VSeh0/mTOJIshVx+MxnU6n1HVd1V8UAQDmMl5q17UogrYIcpUlZQCA24yX+MgKFgAAwETuwSK7VqJE0Rblmpop39RIuWZrtgiym1aiRNEW5ZqaKd/USLlma1awKhT1y0zf96nrOnuUqYpyvY61262o7WBplG9qFLVca7fq4QxWhUSzoSbn8zkNw5D6vk+HwyF3ctjI2u2WdrAN2gdqot0qjyiCDRHNhprYytGGtdst7WAbtA/URLtVDytYQGi+UAPXaB+AnEQRZDF7g8nhcDik5+dngyfgJ9oHcjAe4ismWNztshVjGIZd/10NGQDwUa7xQa7xEOUwweJuuaLu7N2QmdABwHR795+5JjpRoxAShyAX3O2yFWNvex/6dGiaaJwz4TPKBdHs3X/mCgqRazxEOUywCG/vhkwUH6Ix6eczygXR7N1/mugQlS2C8EEth6ZtdayH7Sh8RrmoRy3tdS39JywlTDtUyoWFAGXQXkOZhGmHxvi6nVctX6RphzKbj/Ya6mIFC2ADvkhTGmUWYJprK1iCXABsQLAUSqPMAqzDFkGADTjs/bU9t6TZ/vY1ZRZgHSZY3+h8Afa15yWhuS4kBWhVy2NrE6xvdL6QR8sNcOv2PNgviEC7tDGQR8tja2ewvrH3HPJwWWq79rwk1IWk7dLGQB4tj61NsL7R+UIeLTfAwPa0MZBHy2NrYdoBAAAmctEwQEWcK2mL/AYohwkW1RDymZa0fHi4RfKb3Pbu9/SzlMwEq3E1NWC1h3yuKa9YTlS8tshv3svRH+zd79XyUUHf3SZBLhpXU3SlPQ8y5zg0XVNesVzLh4dbJL95L0d/sHe/V0twEn13m0ywGldLA5ZS/SGfa8orAObL0R/s3e/V8lFB390mWwQbd2nADodD7qTwhaV5ZZsCeym1rJWabsqztKzpu8shr9pkggU7yjmAq2U/O/GVWtZKTTflyVnWfEiA7dkiCDvKuRfbNoV9nM/nNAxD6vu+2S+WpZa1UtO9JuV3HznLmjNBsD0XDcOODF7qdzwe0+l0Sl3XGbxQHOW3fvohWI+LhiGANfZi294RW8Rw2spMTBHzJWL55bs1yowzQbA9K1hQmL2+MPvKWQ+rEjHJl3rs1V4qMxDLtRUsZ7CgMHvt3bdPvx5zy4xJ9n3mvidnvuqxV3upzEAZrGABnzK4xtfy+3hPaC+hTc5gAZPssU8/4hkUvnMe5z7eU2x7tDPONQHvWcECsvHlH9iadgbYijNYQDjOEwBb084Ae7OCBQAAMJEzWABM5pzc17wjAN4zwQLgqkv46WEY7v4zpU445qZ7zjsCoF7OYAFw1ZzzK6XeoTY33c74APCeCRYAV13CT09R6oRjbrrnvCMA6mWLIFUqdYsS8SlbXyv1TqBS070n5Z+tKFvUxASLKpV0JqLETqXENK+lpLL1Xst5FlGp+VFq+V9DiXlWUppbLlvUxxZBqlTSFqUSz6uUmOa1lFS23ms5zyIqNT9KLf9rKDHPSkpzy2WL+phgUaWSzkSU2KmUmOa1lFS23ms5zyIqNT9KLf9rKDHPSkpzy2WL+rhoGAjpfD6nYRhS3/fOxABf0mYAe3PR8Awl7V2G2tiPD0yhzYA8jJd/ZoJ1g8Ya8un7PnVdV8TWFubZq1PW+bdBmwF5GC//zBmsG0rauzyFbRSUwH78+u11AL+kg/7Mp82gBDWOwWodLy9hgnVDrY21wQZ8V2NnV4q9OmWdf17qGHxX4xis1vHyEiZYDTLYgO9q7OxKsVenrPPPSx2D74zB2uAMVoMugw1fEqnJ3HM2zm3AtubUMefmqJUxWBuEaQeqcDwe0+l0Sl3X+UoOhVOfgRII0w5UreWVKF/769RyvrZcn4HymWABVdh720Wkwa8QuXWKlK97l3fbqICSCXIBMEOkg/sOTdcpUr5GKu8A0VnBApo35+t8pC1MvvbXKVK+zi3vkVZ6AfYiyAXQPAfqYRvqFlCza0EubBEEmhdpKxbURN0CWmSLIDBLTVt/Im3FatlaZaqmslm6muqWcgXcywQLmCVShLPoDMzus1aZUjbvp2zeT7kC7mWLIOzkfD6nYRhS3/dVfM219ed+IrDdZ60ypWzeT9m8X03lqrb+CKIR5AJ24rB3uwxmiErZbJP+CNZxLciFLYJUI/pWl0hhvdlXTedQqIuy2abo/VH0/hy+YgWLavgiBwDl059TCitYVC/6Fzn24csnlEv9JSX9OeUzwaIatrqQUluRvgxG29BSPrdUf7lOf07pRBEEqlJTpK+viADXhpbyuaX6C9Rr8gpWbV/SanseaF1LXz5to2lDS/ncUv2FFtQ4zr7nmSYHufjll1+qOnjoICUAAKyvxnH2+2c6nU7rBLmo7Uvals9T46wdAIB6bDlerW3ekNJ9zzR5glXb8v2Wz1PaYV0TQtiP+vZm6/fgPX/nXcB+SqpvW45Xa5s3pHTfMwlysaHSDuu2dJAaclPf3mz9Hrzn77wL2E9J9a208WoJTLA2dJnhlkIFg/2ob2+2fg/e83feBeynpPpW2ni1BJODXLy+vm6YHAAAgPgeHh7WCXLBfkrav0u9lEOAz2kfiUA5jMcWwcBK2r9LvZRDgM9pH4lAOYzHClZgNYa2pDzKYVl8ySyb/CuL9pEIlMN4ip1gtdAJ1RjakvJELIct1P+5Srsegh/Jv+si1vuI7SPtaaUcRmwDril2gqUTYopIlTJSWkql/l/nS2bZ5N916v1y0fqfaOkhtqLagHEc7/71+Pg4RvHy8jJ2XTe+vLxU8e9w29J86LpuTCmNXdetnLKy01Iq9RLao94vF63/WZIe5SGGPfMhYp6nlF7HT+ZMxU6w9hKtMWrV0nyIVCkjpQW2VEpZLyWdsFS0sr4kPcZnMbSeDyZYM0VrjFrV+hcSKFEpHW8p6YTo9NXtaT0frk2wXDQMHxyPx3Q6nVLXdcKdwgLn8zkNw5D6vg99+LqUdEJ0+k9a46JhuJND5myppUPdpUS2KiWda2ip/LE//Se8McGCD1oabLG/KFGQDLT3FeV9Ryl/1En/CW9MsJgtyoABShLlC++cgbY6/93UdxFlYhOl/EFJtH1M9ZfcCaBclwFDSslea7jT5QtvbpcB9pSBtjr/3dR3Med9byFK+YOSaPuYygoWs+X8Eupr0nLeYdvmbOWx+vHd1Hdh6xTa3OVyvUNtH5N9Flrw2q8Ww7SzvjVCegqrvNzcd9h6SFagXe5tyqumOzGpQ7oSpt0WQXa3xlJ7lO02JZv7Dm2VAFq1pP3Tby239B3qv9iLCRa7W6OTqf0cwR738sx9hwYJQKuWtH979Fu13+m29B3qv9iLM1iVKWGPt7MIX4sScewz9+bfVmWxhDIObCN3uxK9/4rcd0QQPf9S0sfVwgpWZSx/16GGr2xblUVlHNqlXbmthr6jdbWUxeZ9djDr2i9BLuJzgHMf0d7zkvRs9Syl/b1AfCW2K3P/7mhtXbT01Mp7Lku6EuTi4e3/3efp6Wl8fX3dbrYHhTgej+l0OqWu60J8YVqSnmjPAlCTuW1stLY5WnoggoeHhz/GcXz6+HNbBGGGaNswlqQn2rPUoPaD5tRJud3G3DY2WtscLT0QmRUsgJX50kuJlFuAaaxgAezEl15KpNwCrMMKFgAAwETXVrDcgwUAALASEywAAICVmGABu3NTPZCDtgfYgwkWsLvLTfXDMKz69xo8QR22qstbtT0A75lgfWNgBvvp+z51Xbd6tDKDJ6jDVnV5q7YH+FHr42ph2r+5NOYpJfd/wMYOh8Mm9WzLMNMuYYXvtq4PW9Xlrdoe4Eetj6tNsL5x/0ccBrLMteXgqfXOAt7buj6YCDGH8UMcrY+rbRH85tKYq5D52ea1jtaX52+Z825sLYLv5tQHbdJt3s9yxg9xtD6utoJFOK1/9ViLFZfr5rwbX9Thuzn1QZt0m/eznPEDUZhgEY6B7Dp0NNd5N7A/9e4272c54weieBjH8e7f/PT0NL6+vm6YHAAAgPgeHh7+GMfx6ePPncECAABYiQkWLORgMgA10r/BPM5gwUIOJgNQI/0bzGOCBQs5mAxAjfRvMI8tgo2x3L++1u96AKBO+rf1GYe1wQpWYyz3AwDkYRzWBitYjen7PnVdZ7mfrHzBK4e8us37KYe8IgLjsDa4BwvY3fF4TKfTKXVd5wvejs7ncxqGIfV9f/eWH3l125z3MycfWE5ZBtZ27R4sWwSB3Tk4ncecrSny6rY578cWoTyUZWAvVrAAGmHlJAb5AFCHaytYJlgAAAATXZtgCXIBULBIB/cjpWWJSM8RKS0A3McZLICCRTrPEyktS0R6jkhpAeA+VrCgAr5ytytSyN9IaVki0nNESgv707ZDmZzBggoIPwxQH207xCZMO1RM+GGA+mjboUxWsAAAACYSRZDw7DUHAJYyniA3WwQJQ7QsAGAp4wlys4JFGKJlQZ2ifk2Omi5gGeMJcjPBIozD4ZCen5/T4XDInZS7GaDdx3uar4Z3d/maPAxD7qT8IGq6pqihfOTk/d2ntPdU4niCutgiCAvYhnAf72m+Gt5d1EhoUdM1RQ3lIyfv7z7eE0xjggUL1DBA24P3NF8N7+7yNTmaqOmaoobykZP3dx/vCaYRph0AAGAiYdoBAAA2ZoJ1Q2mHOgEAYG/GzD9yBusGhzoBAOA2Y+YfmWDd4FAnAADcZsz8I1sEb3CPAiWxPA9QB+05pTFm/pEJVsM04HWp4dJU6hS5rYmcNtqlPa+LdqY9JlgN04DXpe/71HWd5fmK1NIpR25rIqftXrWUE77TntelhnaGaZzBapj9snWp4dJUflTLoeHIbU3ktN2rlnLCd9rzutTQzjCNi4aBRc7ncxqGIfV9b+/1yrxb7qGcbMv7Ba65dtGwCRawyPF4TKfTKXVd54srUB1tHHDNtQnW5DNY9nrDbffWkVrqkrMCQM1qaONa65dgS/fUk8krWL/88osvOXDDvV87fRUFYA/6JVjP+3pyOp3WWcGq4UsO5Sjxa9q9dURdAmAPNfdLJY4TKNs99cQZLEKL8DWtlgPOtTwHQA1qaZNzP0eEcQLtWu0MFuwpwte0Wu6vqOU5Whfxa23ENK0h4nNFTBPz1NIm536OCOME+Mk4jnf/enx8HKE1Ly8vY9d148vLS+6kLDLlOWp55hp1XTemlMau63In5X+tnaa55W/tctvCu2ZdLbaztTwHzJFSeh0/mTOZYAE/MYi7bs5gYs0BSMTBTJSJTZSJ3pYilKWI7yUKbSe0xQQLuJsB1HVzBlAGXdMY+O8jykS2JsogtOXaBOsvGXYlAsEdDgeHha+47POfst9/zp9p2dzyp9xOM7dcKs/XKYNASoJcwCR7HTB3kD2uywBqSrSsOX8mJ+VvntLe29xyWVp5bsWe5a+0sg57M8GCCfaKlpQ7KhN1mDsIWrv8RR2MrZ2uue8t6vuhLHv2G/oo+MJn+wav/XIGi9bttb/ePv59RHzPa6Zp7lmZKEErthYlKEaUdGwlWnpqted7lqfwJglywVwthp2lDREH/mumKUp9jJKOj6Kkq/YJbbT0wC3GPExhgsVsUzrHXB3p1EZOo8g4xiwHEdNEWaKVoWjpIY9S+ukSxjzEYYLFbCV8zZnayGkUAWA/pfTTJYx5iOPaBEuYdr40JexsrhC1U8MGCzMMAPsppZ8uYcxDfA9vk6/7PD09ja+vrxsmBwAAIL6Hh4c/xnF8+vhzYdobIxwwAEA+xmL1M8FaWfRK4+4KAIB8oo/Foo9lS+AM1soulSalFHJfrrNHAAD5RB+LRR/LlsAK1sr6vk9d14WtNJcDmYfDIXdSgDuV8DWxhDROFf2ZoqcP+Fz0sVj0sWwJBLkAqnQ+n9MwDKnv+7Cd2L2Ox2M6nU6p67qwXxNLSONU0Z8pevqmqKm+Au24FuTCFkGgSjVtcYi+nSSlMtI4VfRnip6+KWqqrwBWsIAq+SIO5VBfgRIJ004ozg5M431NF32PO/Cd+jqPvuF+3hV7MsEiS6MTPURpNN4XAB/pG+6X612Z2LXJGSyy7H2PfHYg4laVyO8LgDyi9Q0R+8+LXO/K+cI2FXEGK3KFrYH3+6OaInMBwF70nz8zxtpOhHdbdBRBs/9tXfa+8ybaF0EAKIH+82fGWNuJPD8oYoKlwrInjSEATKf/ZE+R5werBLnY+gDfWtGFHDQEAIC81hiTbx19dEkaV5lglRLFppR0zmHyCORSa/tT63MB8dXe/pQwJl+UxnEc7/71+Pg4fubl5WXsum58eXn59P9HUUI656ax67oxpTR2XbdRyqAMJdTzKUp4nlrbn1Keq4QyMkVtzwNzzG1/Sqk/JaTznjSmlF7HT+ZMq0ywWE/tFQq2Vsqg+F4lPE+t7U8pz1VCGZmitueBOXxwL8O1CVYRQS5aMvfAnoOl8Cbyodc5SnieWtufUp6rhDIyRW3PA3PMbX/UnxiKuAcLAAAgkmv3YK0S5AIAAAATLAAAgNWYYAEAAKzEBAsAAGAlJlgAAAArMcECAABYiQkW4ZzP53Q8HtP5fM6dlBC8j3q1kLfRnzF6+tbQwjO2TP5+510Qxme3D1/79fj4uPoNyHNvqqZebiH/kfexTOQ2Zou8XfK8W7yr6OV3q/TNfZet5UHk+lmKyPm7N++Cz2zZzqSUXsdP5kzZJ1gqAx/pcH9U8vuYk/a1nzdyGxNtMB1twreHrdI39122lgdrP2+ENmdvpad/Td4Fn9lyHBB2gqUyQL3mNGoRBlwli7aC1apIK1iRRfigEvkjDLBckytYJWqtA2yJvF1Xi1+TgXy0OTF4p3WSrz+7NsF6ePt/93l6ehpfX19XOPlVtuPxmE6nU+q6Lj0/P+dODiuStwCwjL60TvL1Zw8PD3+M4/j08eeiCM7Q933qui71fZ87KbOJtPO5GvIWSrekfdK2QX760s+V3j7J1wk+W9a69ssWwXrYcw4/i3R+qYStGNECRCz9s9e0mhfOkcG6jL3qk5zB4j0dIFNFLDMRDsiv8Wf3+Pu2EC3E+dI/e02reRElEmLEtmcc46aLuJSZ+phgAYtEHGRGGshZwapXCc9Z8wpWxLZnHOOmC9jPtQmWIBfAXc7ncxqGIfV9nw6HQ+7kpJRipglYV9R6HjVdwH6uBbkwwQIAAJhIFEEAAICNmWABAACsxAQLAABgJSZYEETpFxACEIP+BPL6S+4EAG+GYUin0ymllNLz83Pm1ABQKv0J5GWCBUH0ff/DfwFgDv0J5GWLIARxOBzS8/Oz+1QaUfsWntKer7T0ztHCM/JGfwJ5mWBB42oadJX0LJctPMMw5E7KJkp7vtLSO0cpz1hSPf5KTc8C3M8WQbjhfD6nYRhS3/fVfgmsaa9+Sc9S+xae0p6vtPTOUcozllSPv1LTs1zTQj8JU5lgwQ0tdI6lDLruUdKzXLbw1Kq05ystvXOU8owl1eOv1PQs17TQT8JUD+M43v2bn56extfX1w2TAz/L+XXMlzkAuE4fTcseHh7+GMfx6aefm2AR3fF4TKfTKXVd5+sYAJBSMj4gv2sTLFsECa+FLRYAwDTGB0QliiDh1RJuVjQpAKKooU+qZXxAfaxgwU4cBAYgCn0SbMcKFix071fAvu9T13W2MgCQ3T19Ug2rXJCDIBewkEO2ANRI/wa3XQtyYQUrA1+E6mJlCoAa6d/qYvy5HytYGfgiBADAnow/1ydMeyDCigIAsCfjz/3YIphBxLCilo3bUWNel/RMJaV1iRKfs8Q0z1HKc5aSzilqfCY+FzGvI44/qzWO492/Hh8fxz28vLyMXdeNLy8vu/x7jGPXdWNKaey6LndSVqc8/ajGvC7pmUpK6xIlPmeJaZ6jlOcsJZ1T1PhMS9TcP8vr/eUoTyml1/GTOVPICZZCuT+NXDtqzOuSnqmktC5R4nOWmOY5SnnOUtI5RY3PtETN/bO83l+O8lTUBEuhZIqvyovyBADx6L9ZU6QVLFEEKZ6oOABQH/070YkiSLVExQGA+ujfKZUVLAAAgImurWAJ0w4AALASEyyaF/GuCgAonf6VVjmDRfOGYUin0ymllByiBYCV6F9plQkWzXOIFgDWp3+lVbYIEtoe2wsOh0N6fn5Oh8Nhs38DAFqzV/9qKyLRmGAR2mV7wTAMuZNSrcgdU+S0ra2kZy0prWsq6blLSutSkZ81ctpqYqxAOJ/dPnzt1+Pj4243I8M4usV9D13XjSmlseu63En5yRZpW1qmtiqTkfPhoy3TGjV/xlEeXSx5x1vkT+R8iZy2mhgrkEtK6XX8ZM5kggWNi9wxRRyMbTVgipwPH0WexESdWOwtah5F/GiypchpA5YzwQIYY6+QIH9KEG0FCyCXaxOsh7f/d5+np6fx9fV1vf2JMNH5fE7DMKS+7wWlAIAGGQsQxcPDwx/jOD59/Lkw7RTFnRoA0DZjAaIzwaIo7tQAgLYZCxCdMO0UxZ1V+SwJNyxU8TaWvlf5sg/5FNfcdytP8jIWILzPDmZd+yXIBQ4ot0vksHmiRnNb48/fUkr+XMin2PkU7XoE4dfbVUqdYR9JFEHWoFNpV7TIYaWUxciD48iTir3Jp9j5FO16BIPsdpVSZ9iHCRar0KkQRSllsZR0rq205y4tvWsp5blLSSf1UxZ579oES5h2uEEoWAC4TV9Jq4RphxmEggWA2/SV8CNRBAvQQrSiqM/Y933quk4oWAC4ImpfGXVssZban69ktggW4Hg8ptPplLquq/bLUAvPCADsp/axRe3PVwJbBAvWwoV6LTwjALCf2scWtT9fyaxgAQAATHRtBcsZLDZlfzAAEJmxCmuzRZBNiSwEAERmrMLaTLDYlP3BAEBkxiqszRksAACAiZzBAorQyl74kp+z5LQvUfJzl5z2KVp5TiA2WwSBUFrZC1/yc5ac9iVKfu6S0z5FK88JxGaCBYTSyl74kp+z5LQvUfJzl5z2KVp5TiA2Z7AAAAAmcgaL4tlbDwCkZExAbCZYDSutcbrsrR+GIXdSAICMShoTlDbeYrnqJ1gK9XUlNU4pve2p77rO3noAaFxJY4LSxlt7q3GsXn2QCxGFrivtMPDhcJCHAEBRY4LSxlt7q3GsXv0ES6G+rqTGCQCgRMZbt9U4Vq9+i+ClUB8Oh9xJ2V2NS645eZ8AoD9cW+vvs8axevUrWC2rcck1J+8TAPSHa/M+62OCVbEal1xz8j4BQH+4Nu+zPi4aBgAAmMhFwwAAABszwQIAAFiJCRZ3az3KDdtRtoC1aVfYkvLFLSZY3M1N5GyltbJVesdcevqXKP3ZS0//FK21K+xL+eIWUQS5myg3bKW1slV6SN7S079E6c9eevqnaK1dYV/KF7eYYHE3N5GzldbKVukdc+npX6L0Zy89/VO01q6wL+WLW4RpL9j5fE7DMKS+76u6/RoAgDfGe3FdC9NuBatgLW31AABokfFeeUywCtbSVg8AgBYZ75XHFkEAAICJrm0RFKYdAABgJSZYAAAAKzHBAgAAWIkJVqXO53M6Ho/pfD7nTspmWnhGAGhdC/19C8/YEhOsSl1Ceg7DkDspm9n7GTV+ALB/f2hMQ2mEaa9UCyE9935G91AAwP79oTENpbGCVanD4ZCen5+rvvF772fs+z51XVdd47fkS+SWXzGtGAL3itoW1dqO7d0fGtNQnHEc7/71+Pg4AnXpum5MKY1d1+36Z3P+3Vt5eXkZu64bX15eciclq5LfQ8lpX1Np7yFqW1RiOwbcL6X0On4yZzLBgsYtGUhtOQgrbYA3jtsPptZ4J3u815IHlXukvYR8LC0Po7ZFJbZjwP1MsAA2VsKgt5QJRC6lTEBLmMwD1O7aBEuQCzZzPp/TMAyp73t7imnCZQ/9VtY4BL3HQeqt38OW9kh7CflYch7CVMYrrO3hbfJ1n6enp/H19XXD5JRFhbzteDym0+mUuq7TUQMAIRmv3Ga8e93Dw8Mf4zg+ffy5FawFhO2+TchRACA645XbjHenE6Z9gVrDdq9FyNH91BoKGKBV2vX9GK/cZrw73eoTrJYaBBWSKNwA/6al9gdqpi5r14mjpfHuWm3P6hMsDcL2dDx8VMrXpa3L7tL2R92C5daoR1uOJUqp56W06+ynlLJbstXans9CC177dU+YdqFdt1fa/SRwET20dPT01W6t9+M931bCdQJbplEfSqmU3e1NbXuSe7DqYfBAqaKX3RIGnrmUcj/Umn/PLdHL8i2tf0iInj64RtmNxwQLZtCYsaaSy1NJk5aSJoM5lFwOiUmZolXXJljuwaJaa9zb4G4MeOMelB95H/Dd0r5SfaJU7sGiOWvc2+BuDHhziSLFG+8DvlvaV7pnidq4BysQ0WHWtUYEppZCkwLAHEv7ShET12dMmZctgoHYjgYAwFLGlPuwRbAAtqMBALCUMWVetggGYjva/iyhA8B29LN5GFPmZQWLpjlYCwDb0c/SIhMsmmYJHQC2o5+lRbYI0rToS+i2VgBwS/R+Ino/C1uwggWB2VoBwC36CYjHBAsCs7UCgFv0ExCPLYINir6dgO9a2VqhTAJbaKFtaaWfqEEL5ZE3JlgNumwnGIYhd1IgpVR+mdRpUqMaynXpbQt1UR7bYYtgg2wnIJrSy6QzEG/O53MahiH1fV/81/SanmWuGsp16W0LdVEe2/EwjuPdv/np6Wl8fX3dMDm0ymCGkim/b47HYzqdTqnrumIH5Bc1PctcyjUlU37Zw8PDwx/jOD59/LkVrE+olPur4Usp7bqcgWhdTV9na3qWuZRrSmZckYcx9BsTrE+olPszmIHy1TQgr+lZoEXGFXkYQ78xwfqESrk/gxkAYC3GFXkYQ79pJorglGhIQp4CAMA0946ha4hSekszEyyhMetVeyUFgFbp4+tU+7i8mS2ClizrZb8vANRJH1+n2sflzUyw7MWtV+2VFABapY+vU+3jcvdgAQAATHTtHqxmzmABAABszQQLAABgJSZYFGdqRKGSIhCVlFYA4impH5mT1pKej3Y1E+SCekyNKFRSBKKS0gpAPCX1I3PSWtLz0S4TLIozNaJQSRGISkorAPGU1I/MSWtJz0e7RBHcyfl8TsMwpL7vv7zdGlqgTgB70d7Aj9SJdVyLImgFayeWtOFH6gSwF+0N/Eid2JYgFzvp+z51XWdJG76poU44bE0LaijnNbQ3sCZ1YltVTLBKaPwvN1ZbhoU3NdSJyxfAYRhyJyW7EtrhKWp7niVqKOc1tDewphLqRMntcBVbBC1zAjk4bP1dbe1wbc+zhHIO5FByO1zFBEvjD+Rw+QJIfe1wbc+zhHIO5FByOyyKIAAAwETXoghWcQYLAAAgAhMsAACAlZhgUYSSI8kAAOszNiAqEyyKsEeYYA01ACy3V39awxUC1KmKKILUb49IMiWHAwWAKPbqT0uOMkfdrGBxt5wrPHtciOdWcwBYbq/+NNdluXa88BUTrG9Ulq/VvhQf8VZz5RKAWyL2ExH70zXVPh5aS8SyuRcTrG9Ulq9FW+FpoeIqlwDc0kI/Ea2/jzYeiqqFsnmNM1jf2Mf7tcsXqShaODOlXAJwSwv9RLT+Ptp4KKoWyuY1D+M43v2bn56extfX1w2TA/c7n89pGIbU93212xBKI0+A0mnH4pEnRPXw8PDHOI5PP/3cBAtYy/F4TKfTKXVd5+seUCTtGHCvaxMsZ7CA1Wy9Lz3aPnxgf1u3A87XAEuZYAGr2Tpy1BoHZveapJkMUpKS6sXWB+drj4AHbM8ECyjGGl+W94pqVEv0JBPF22p5PyXVCytMQHSiCALFWCNy015RjWqJnrRn9K41D7LvdSg+WnSzuUqqFyK4AdEJcgHAVXtG71ozuMBegQpENwNolyAXDahlqwrzKQOsbc/zKGtu/dprG5nzOqxNO44yUD4rWBURWpalZcDXeIBllraj+nKUgXJcW8FyBqsitZz5YL6lZaCW8yQAuSxtR/XlKAPls4IF/C8rWADLaEehHc5gUQX7kre19XkS+QdEsGVb5FzetvQjlMAEi6LUcrdQq+TffQwgmEO5uZ+2qFzyjhKYYFGUCBdMGsTMFyH/ltgr79ccQCiv8a2VR3sOPEsvV6W3RblEyHd5RxHGcbz71+Pj41iil5eXseu68eXlJXdSqEDXdWNKaey6LndS2Nleeb9mm6W8xrdWHu3Z1ylXbZLvrKmG8XlK6XX8ZM7UxARLgxBDDRVpHOt5DqYrMe/3SnOJ7+aWPZ+nxHdXYppZrpZ8r+U5SlfD+PzaBKuJKIIi+sTgXgeoV231u7bnAb5Tv2OoYXze9D1Yl4g+5OVeB6hXbfW7tucBvlO/Y6h5fN7EChYAAMCa3INFcSJEKwIAYjNeIBoTLMJaGnJYgwsA8S3tr92NRTRNnMGiTEv3SF8a3JRStXt8AaB0S/trZ6qIxgSLsJYeftTgAkB8S/vrmoMlUCZBLgAAACYS5AIAAGBjJlgAAAArCTnBEv0NAAC4V6T5Q8gJlnCbUI5IDRrA2rRxUIZI84eQUQRFf4NyCIcP1EwbB2WINH8IOcESbhPKEalBA1ibNg7KEGn+EHKLIFCOS4N2OBxyJyUr24ioifL8nTYOmCrkChZAaWwjoibKM8B8VrBgZb78tqnv+9R1XXXbiJTn22p9P7WWZ75Wa5mGPT2M43j3b356ehpfX183TA6U73g8ptPplLqu8+WX4inPt3k/1EaZhvs9PDz8MY7j08ef2yIIK3Mgmpooz7d5P9RGmYblbBHMpOQl+JLTvgcHoqmJ8nyb90NtlOnrSh7/lJz2ElnByqTkA8Qlpx0AYI6Sxz8lp71EJliZlLwEX3LaAQDmKHn8U3LaSyTIBQAAwETXglw4gwUAALASEyyyceASANiDMQd7cgaLbBy4BAD2YMzBnqxgkU3f96nrujAHLn3dAoDlIvan0cYc1E2QC/jG7fUAsJz+lFZcC3JhiyB8I4QpACynP6V1tghShD22G7i9HgCW26s/jbgVEVIywaIQl8OpwzDkTgpJpwa0SdsXi7EBUZlgkcXUTsrh1Fh0akCLtH2xTBkbmByzJ2ewyGJquNTLdoPSnM/nNAxD6vu+qq2H9tcDLaqx7Su5n5oyNhCmnT2ZYJFFjZ3UZ2pt0Eud8AIsUWPbV2s/9VEr4w5isEWQLFoJKGFrY/1sO6Fmynf9WumnWhl3EIN7sAAWcN8LNVO+Aa67dg+WFSyABWr/+msF42s1v6PayzfAFqxgAXCVFYyveUcAbbq2giXIBQBXORj+Ne8IgPdsEYSZat4WBBcOhn/NO6J2+juYxgoWzNRKaFsA2qa/g2msYMFMXx3+9sUPgFLc6rMEO4FpBLmAjTj4DkAp9FkwnSAXsDMH3wEohT4L1mOLIM3Ye8ueg+8AlGLPPssWempnBYtmOKQLAPnpj6mdFSzC2PqLlkO6AJDf1v2xFTJyE+SCMBywBQCWMp5gL9eCXFjBIgwrTOXz1RAonXasfMYT5GYFC1iNr4ZA6bRjwL2EaQc2J8wvUDrtGLBUqC2CluW5RfmIT2h6oHTasfiMB7glQvkINcG6hO0chiF3UghI+WAvERpnKI16w16MB7glQvkItUXQsjy3KB/sxR0tMJ16w16MB7glQvkQ5ALgg/P5nIZhSH3f2yYEd1JvgNYI0w5wp73PYJS+tar09F9Tw3Pt+QzOLgG8McHiBzUMKKA0a+4Xz1GHI+x330KO51o7/2rNG4jKOIqUgp3BIj976GF/a+4Xz1GHI+x330KO51o7/2rNG4jKOIqUTLD4QGcM+7tsrVpDjjq8ZvojyfFca+dfrXkDURlHkZIgFwAAAJMJcgGEZc86sDbtCpCLCRaQXelBHoD1rFWHBfgAcnEGC8iu9CAPwHrWqsPOwgC5WMGCmb76ymol5X5r3p/T933qus6gCgq1Vh12L9f99GewLkEuYKbj8ZhOp1Pquu7Tr6xf/X8AiEB/BvMIcgEr++or663/72tgHeQjLVDO63EtL5f0Z8DPrGBBBr4G1kE+rud8PqdhGFLf96ts6Vr772uZcl4PeQnruraCJcgFZODwdR1qzccck5O1g5PkCHZS66Su1nLeInkJ+7CCRRVqHdhADjm+ctewgmV1ANajX6cEVrComtDcsJ4cX7kvEd+i/n33sDoA69GvUzJBLqhCCQdwHRSnFMJbz+O9UZLofVIJ/TpcY4sg7MT2IQCi0CfBcrYIQma2DwEQhT4JtmMFCwAAYCIXDQMAAGzMBAsKEP0wMgD70i9AXM5gQQGEqwXgPf0CxGUFq3C+YLVBuFoA3tMvtMNYrzwmWIW7fMEahiF3UooXuQFzvw4A70XuFyL3pyUy1iuPCVbhavuClbNR1oABwHI5+9MaJ3e1jfVa4AxW4S5fsGqRc0+5O0EAYLmc/WmNZ9NqG+u1wAoWoSz9SrPky1Xk7RYAUIql/emSvtxqDxG4aJiqHI/HdDqdUtd1vvYAQIH05ZTCRcM0wZcrlqpx/z7sRf1hDfpySmeCRVVK3uZnYBKDYCcwn/oTQ+n9Scl9OaQkyAWEUePB3BIJdgLzqT8x6E8gLytYEIQtETH4cnq/0r+ST9HSsy6h/sSgP4G8TLAgiM8GJgZ1RNbSdrCWnpWyfNZPmOhCXrYIQmC2eRBZS9vBWnpWyqKfgHisYEFga27zsBrG2lr6St7Ss7KPtdpk2wEhHvdgQSPcKwIQhzYZynftHixbBKERtjgBxKFNhnpZwQIAAJjo2gqWM1gAAAArMcECAABYiQkWAADASkywAAAAVmKCBQAAsBITLAAAgJWYYAEAAKzEBAsAAGAlJliQwfl8TsfjMZ3P55B/HwD5rdm26ydgP3/JnQBo0TAM6XQ6pZRSen5+Dvf3AZDfmm27fgL2Y4IFGfR9/8N/o/19AOS3Ztuun4D9PIzjePdvfnp6Gl9fXzdMDgAAQHwPDw9/jOP49PHnzmABd6l9/37tzwd7qr0+1f58wDImWNCQJYOCy/79YRg2SFl+tT8f7Kn2+rTk+UzOoH7OYEFDlhxyrn3/fu3PB3uqvT4teT7BJqB+zmBRjfP5nIZhSH3fp8PhkDs5IXlHAHlph7/mHVEKZ7CoXu1bUtZwOBzS8/OzDovFWtvm1Nrzsh3t8Nf055TOBItq9H2fuq5btCXFIAru09oAqLXnhSWW9qVr9OeQkzNYVOPyVXAJe+PhPrWfsfmoteeFJZb2pWv055CTCRa8YxAF92ltANTa88IS+lJaZ4sgvFPb3nhbHgHiq62trq0vhalMsGCBCJ3irTQ4NwIQ37W2OnofA3zOFkFYIMKZrVtpsE0DIL5rbXX0Pgb4nAkWLBBhAnMrDc6NAMR3ra2O3scAn3PRMAAAwEQuGgYAANiYCRYs5ADwbd4PEJX26TbvB+ZxBgsWcgD4Nu8HiEr7dJv3A/OYYMFCDgDf5v0AUWmfbvN+YB5BLgAAACYS5AJYnf35QO20c8BUJlhMoqPhvcv+/GEYcicFYBPaOd4zDuIeJlhMoqPhvb7vU9d1zezP17HCm5bqQmvtHLcZB3EPQS6YxIHXGM7ncxqGIfV9nw6HQ7Z0HA6HpiJLiagFb1qqC1HauSjtfuuMg7iHCRaTROloWtfS4CYSHSu8URf2p92PwTiIe9giCAWyZSWPS8da69fjlrZ9bamF91h7XYhIuw/lMMGCAtUyuGlhIFoSZwvW4T3GU0NbU0u7Dy2wRRDY1ftzBLa8xGLb1zq8x3gubc2ff/6Z/vrXvzrHBGzKBAvY1ftJlYFoLM4WrMN7jOfSxvz5558+6gCbM8ECdvV+UmUgCuzh0ta8X0EH2MrDOI53/+anp6fx9fV1w+QAAADE9/Dw8Mc4jk8ffy7IBQAAwEpMsAAAAFZiggUVqSEUMUDrtOVQNhMsqEiu+3cMBoAa5Wrb3KUGZTPBgor0fZ+6rts9Qtb7wYDJ1m3eD7kpg7e9fz+5Jjq52nJgJeM43v3r8fFxBOrw8vIydl03vry8rPp3dV03ppTGrutWSGV9tng/a+YlsWyRt+robe/fz1rvXx2FOqWUXsdP5kzuwYJGvb/wd+ldVO/vs/r111/T6+tr+vXXXxensUZbXK68Zl4SyxZ564Lv2963YWvd1aeOQltMsKBRWw2yfv/99/Tvf/87/f777+kf//jHqn93Dba4XNmAuV5b5K0Lvm/bog1TR6EtLhoGVnU5t9D3fTocDrmTAzCJNgy4l4uGgV1cvo4vGZg4hA9MtVa7sUYbBrTNBAvI6rNBkRDFwFSftRs+1gA5OIMFZPXZ4W/nFYCpPms3BJcAcjDBArL6bFDkED4w1Wftho81QA6CXAAAAEwkyAXQrN9++y398ssv6bfffsudFOAddROokRUsoHq//PJL+ve//53+9re/pX/961+5kwN8o24CJbOCBTTrn//8Z/rb3/6W/vnPf+ZOCvCOugnUyAQLqN4//vGP9K9//Sv94x//uOv3C+0M80ytO1PrJkAJTLCAprmHC9bjLioAYdqBxl27h+vPP/9Mf/75Zzqfz+lwOORMIoR3Pp/TMAzp119/TSm5iwpomwkW0LRr93D99a9//d8v8QaFcNutSZS7qIDW2CIINOf9lqX3l5O+38bU933qus6gEO7wWX251LOU0qd1DKBWwrQDzTkej+l0OqWu634Y+H38GTDfxzqljgG1EaYd4JvPvrZvtWLlgD+RbVk+P9Ypq8JAK6xgAWzIV3siUz4B5rOCBVSjpFUhX+2JrLTyWVLdB9plBQsojq/u0CZ1H4jEChZQjdK+un/0/iu8L/Js7VLGfvvtt+LLWul1H2iDFSygWZfLUfu+3/Uy4fdf4VNKvsizqUt5+9vf/pb+/e9/ZylrueoawJaurWC5aBho1q3LUbf02cWrvsizlUvZ+vXXX9Pvv/+epazlqmsAOVjBAppV+lf10tPPfWrI5xqeAeCjaytYJlgAhXLgvw3yGSAmWwQBKvPZVkPqI58ByiKKIEAQ1yIKXvv54XBIz8/PtlxV7lo+Ty0vAOzDChZAENcCAQgQwGeUF4CYrGABBHHtjp+ld/+4dyuONfNiq/ICwDKCXABUbuq9WyK+zXPPe3MHGkA9BLkAaNTUe7dsMZvnnvfmDjSA+lnBAuAHVrDm8d4A2uIeLAAAgJVcm2AJcgHAJJ8FZ6ghkMZXz1DqcwGwLxMsgEbdM2H47PdczhoNw/Dpzz77/9EmJ18911fPeOvvueffAqBi4zje/evx8XEEWNPLy8vYdd348vKSOynFm/ouu64bU0pj13WTfs9n/877n332/+/5t/b01XN99Yy3/p57/q2vqBfr8B6BLaWUXsdP5kwmWEBW0Qbea9p7cDf1Xd6TvqnPcO33RxvorpXOLd7hOO5bL6LlzZpqbl+A/EywgJAM7tYT4V2WPqCNkv498zLKM28hQp0A6nVtguUeLCCrw+FQ7V1Ln915tKW13+WcsON7P/Pa5qR/i/Dse9aL0vPslprbFyAuYdoB+NTxeEyn0yl1XWeQeoP3BNCma2HarWAB8KmaVzbW5D0B8J4VLAAAgIlcNAwAALAxEywAAICVTNoi+PDw8P+llP7vdskBAAAowv87juP/+fjDSRMsAAAArrNFEAAAYCUmWAAAACsxwQIAAFiJCRYAAMBKTLAAAABWYoIFAACwEhMsAACAlZhgAQAArMQECwAAYCX/P7qGnowKxztdAAAAAElFTkSuQmCC\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "image_feature_locations = simulator.get_image_feature_locations(area_restrict = image_area, min_feature_count = 2)\n",
+ "feature_counts = Counter([f for i in image_feature_locations.values() for f in i.keys()])\n",
+ "feature_counts_counts = Counter(feature_counts.values())\n",
+ "print(\"Total number of features: \", len(led_positions))\n",
+ "print(\"Number of features in more than one image: \", sum(feature_counts_counts.values()))\n",
+ "print(\"Feature in image counts:\", feature_counts_counts)\n",
+ "simulator.show_images(image_feature_locations, area=image_area)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "camera_orientations, camera_positions = fit.camera_world_poses(camera_rotations, camera_translations)\n",
+ "plot_geometry(led_positions, camera_positions)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "=== Gaussian errors on feature image locations: 1.0 ===\n",
+ "4 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 13.883385636764606 max: 114.65356241858672\n",
+ "image 1 reprojection errors: average: 13.713662562824632 max: 132.52230212294577\n",
+ "image 2 reprojection errors: average: 14.066902502714576 max: 137.72565330474978\n",
+ "image 3 reprojection errors: average: 13.919607854024123 max: 303.11279610030897\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 7.7286e+05 1.40e+06 \n",
+ " 1 2 2.6866e+03 7.70e+05 6.97e+01 1.54e+05 \n",
+ " 2 3 1.3147e+03 1.37e+03 7.39e-01 3.49e+03 \n",
+ " 3 4 1.3084e+03 6.22e+00 4.98e-01 8.03e+02 \n",
+ " 4 5 1.3072e+03 1.20e+00 5.38e-02 9.28e+01 \n",
+ " 5 6 1.3071e+03 1.06e-01 8.47e-03 1.65e+01 \n",
+ " 6 7 1.3071e+03 5.05e-02 6.30e-03 2.37e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 7, initial cost 7.7286e+05, final cost 1.3071e+03, first-order optimality 2.37e+01.\n",
+ "mean reprojection error: 0.6392578043382984\n",
+ "max reprojection error: 2.56533518539307\n",
+ "mean reconstruction error: 0.1190688526480074\n",
+ "max reconstruction error: 0.5306016190654083\n",
+ "=== Gaussian errors on feature image locations: 3.0 ===\n",
+ "4 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 14.36925881990482 max: 103.76676434611505\n",
+ "image 1 reprojection errors: average: 13.694895095369638 max: 147.19632272808684\n",
+ "image 2 reprojection errors: average: 14.255586224366864 max: 154.52827868291894\n",
+ "image 3 reprojection errors: average: 14.402039121180508 max: 283.40543365185306\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 7.6647e+05 4.14e+06 \n",
+ " 1 2 1.4074e+04 7.52e+05 7.10e+01 2.44e+05 \n",
+ " 2 3 1.2307e+04 1.77e+03 7.64e-01 7.08e+03 \n",
+ " 3 4 1.2291e+04 1.67e+01 5.32e-01 1.84e+03 \n",
+ " 4 5 1.2285e+04 5.43e+00 8.91e-02 1.38e+02 \n",
+ " 5 6 1.2284e+04 8.78e-01 3.19e-02 5.64e+01 \n",
+ " 6 7 1.2284e+04 5.29e-01 1.58e-02 4.16e+01 \n",
+ " 7 8 1.2283e+04 3.65e-01 1.59e-02 4.27e+01 \n",
+ " 8 9 1.2283e+04 4.22e-01 1.57e-02 4.96e+01 \n",
+ " 9 10 1.2283e+04 3.46e-01 1.35e-02 3.56e+01 \n",
+ " 10 11 1.2282e+04 3.06e-01 1.23e-02 4.62e+01 \n",
+ " 11 12 1.2282e+04 3.19e-01 1.34e-02 3.76e+01 \n",
+ " 12 13 1.2282e+04 2.87e-01 1.12e-02 4.57e+01 \n",
+ " 13 14 1.2281e+04 3.05e-01 1.38e-02 3.96e+01 \n",
+ " 14 15 1.2281e+04 2.78e-01 1.04e-02 4.37e+01 \n",
+ " 15 16 1.2281e+04 3.10e-01 1.52e-02 4.72e+01 \n",
+ " 16 17 1.2281e+04 2.01e-01 6.43e-03 1.92e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 17, initial cost 7.6647e+05, final cost 1.2281e+04, first-order optimality 1.92e+01.\n",
+ "mean reprojection error: 1.9580852532917954\n",
+ "max reprojection error: 7.956843795703266\n",
+ "mean reconstruction error: 0.34158658199936864\n",
+ "max reconstruction error: 1.6336601724472413\n",
+ "=== Gaussian errors on feature image locations: 5.0 ===\n",
+ "4 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 15.042639687030883 max: 144.89514178273947\n",
+ "image 1 reprojection errors: average: 15.175912112787069 max: 110.24093393656742\n",
+ "image 2 reprojection errors: average: 15.38389189016894 max: 219.02711553402986\n",
+ "image 3 reprojection errors: average: 15.115226187792024 max: 247.1464281779609\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 8.6401e+05 3.30e+06 \n",
+ " 1 2 3.5556e+04 8.28e+05 7.40e+01 6.92e+04 \n",
+ " 2 3 3.4520e+04 1.04e+03 1.14e+00 1.94e+03 \n",
+ " 3 4 3.4468e+04 5.14e+01 1.12e+00 1.67e+03 \n",
+ " 4 5 3.4443e+04 2.52e+01 2.81e-01 3.19e+02 \n",
+ " 5 6 3.4440e+04 3.09e+00 7.73e-02 1.45e+02 \n",
+ " 6 7 3.4438e+04 2.50e+00 5.96e-02 1.46e+02 \n",
+ " 7 8 3.4436e+04 1.76e+00 4.37e-02 1.23e+02 \n",
+ " 8 9 3.4435e+04 7.90e-01 1.49e-02 6.92e+01 \n",
+ " 9 10 3.4434e+04 5.39e-01 1.58e-02 8.79e+01 \n",
+ " 10 11 3.4434e+04 5.17e-01 1.17e-02 6.43e+01 \n",
+ " 11 12 3.4433e+04 5.11e-01 1.54e-02 8.64e+01 \n",
+ " 12 13 3.4433e+04 4.77e-01 1.08e-02 5.73e+01 \n",
+ " 13 14 3.4432e+04 4.62e-01 1.45e-02 8.55e+01 \n",
+ " 14 15 3.4432e+04 4.59e-01 1.05e-02 5.83e+01 \n",
+ " 15 16 3.4432e+04 4.46e-01 1.40e-02 8.71e+01 \n",
+ " 16 17 3.4431e+04 4.40e-01 1.01e-02 6.04e+01 \n",
+ " 17 18 3.4431e+04 4.30e-01 1.35e-02 9.23e+01 \n",
+ " 18 19 3.4430e+04 4.23e-01 9.65e-03 6.38e+01 \n",
+ " 19 20 3.4430e+04 4.18e-01 1.30e-02 1.07e+02 \n",
+ " 20 21 3.4429e+04 4.50e-01 1.04e-02 7.48e+01 \n",
+ " 21 22 3.4429e+04 3.93e-01 1.15e-02 1.02e+02 \n",
+ " 22 23 3.4429e+04 3.89e-01 9.47e-03 8.39e+01 \n",
+ " 23 24 3.4428e+04 3.89e-01 1.14e-02 1.11e+02 \n",
+ " 24 25 3.4428e+04 3.85e-01 9.30e-03 8.67e+01 \n",
+ " 25 26 3.4427e+04 3.84e-01 1.13e-02 1.12e+02 \n",
+ " 26 27 3.4427e+04 3.79e-01 9.16e-03 8.59e+01 \n",
+ " 27 28 3.4427e+04 3.75e-01 1.12e-02 1.11e+02 \n",
+ " 28 29 3.4426e+04 3.70e-01 9.03e-03 8.42e+01 \n",
+ " 29 30 3.4426e+04 3.66e-01 1.10e-02 1.09e+02 \n",
+ " 30 31 3.4426e+04 3.60e-01 8.89e-03 8.23e+01 \n",
+ " 31 32 3.4425e+04 3.57e-01 1.09e-02 1.08e+02 \n",
+ " 32 33 3.4425e+04 3.52e-01 8.77e-03 8.07e+01 \n",
+ " 33 34 3.4425e+04 3.49e-01 1.08e-02 1.06e+02 \n",
+ " 34 35 3.4424e+04 3.44e-01 8.66e-03 7.90e+01 \n",
+ " 35 36 3.4424e+04 3.40e-01 1.07e-02 1.04e+02 \n",
+ " 36 37 3.4424e+04 3.36e-01 8.56e-03 7.75e+01 \n",
+ " 37 38 3.4423e+04 3.34e-01 1.06e-02 1.03e+02 \n",
+ " 38 39 3.4423e+04 3.29e-01 8.46e-03 7.59e+01 \n",
+ " 39 40 3.4423e+04 3.27e-01 1.05e-02 1.01e+02 \n",
+ " 40 41 3.4422e+04 3.23e-01 8.38e-03 7.43e+01 \n",
+ " 41 42 3.4422e+04 3.20e-01 1.05e-02 9.97e+01 \n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " 42 43 3.4422e+04 3.17e-01 8.30e-03 7.28e+01 \n",
+ " 43 44 3.4421e+04 3.14e-01 1.04e-02 9.82e+01 \n",
+ " 44 45 3.4421e+04 3.11e-01 8.22e-03 7.14e+01 \n",
+ " 45 46 3.4421e+04 3.08e-01 1.03e-02 9.67e+01 \n",
+ " 46 47 3.4420e+04 3.05e-01 8.15e-03 7.00e+01 \n",
+ " 47 48 3.4420e+04 3.02e-01 1.03e-02 9.55e+01 \n",
+ " 48 49 3.4420e+04 2.99e-01 8.08e-03 6.86e+01 \n",
+ " 49 50 3.4420e+04 2.42e-01 7.90e-03 8.73e+01 \n",
+ " 50 51 3.4419e+04 2.87e-01 8.68e-03 9.00e+01 \n",
+ " 51 52 3.4419e+04 2.85e-01 8.47e-03 8.58e+01 \n",
+ " 52 53 3.4419e+04 2.82e-01 8.62e-03 8.83e+01 \n",
+ " 53 54 3.4418e+04 2.79e-01 8.41e-03 8.43e+01 \n",
+ " 54 55 3.4418e+04 2.77e-01 8.56e-03 8.65e+01 \n",
+ " 55 56 3.4418e+04 2.74e-01 8.35e-03 8.29e+01 \n",
+ " 56 57 3.4418e+04 1.71e-01 4.47e-03 6.49e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 57, initial cost 8.6401e+05, final cost 3.4418e+04, first-order optimality 6.49e+01.\n",
+ "mean reprojection error: 3.2722951530862043\n",
+ "max reprojection error: 14.190425769322397\n",
+ "mean reconstruction error: 0.5786112193562779\n",
+ "max reconstruction error: 2.76880691795907\n",
+ "=== Gaussian errors on feature image locations: 10.0 ===\n",
+ "4 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 17.09512975652156 max: 120.87241518847067\n",
+ "image 1 reprojection errors: average: 16.921944023267525 max: 108.74584660267507\n",
+ "image 2 reprojection errors: average: 18.028821918415243 max: 123.18558268792229\n",
+ "image 3 reprojection errors: average: 17.84712610359939 max: 185.33013225169395\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 1.0159e+06 2.50e+06 \n",
+ " 1 2 1.4112e+05 8.75e+05 8.61e+01 7.15e+04 \n",
+ " 2 3 1.4044e+05 6.75e+02 1.42e+00 2.63e+03 \n",
+ " 3 4 1.4034e+05 1.05e+02 9.14e-01 1.16e+03 \n",
+ " 4 5 1.4028e+05 5.63e+01 3.25e-01 4.26e+02 \n",
+ " 5 6 1.4026e+05 2.13e+01 2.19e-01 3.31e+02 \n",
+ " 6 7 1.4025e+05 1.60e+01 1.34e-01 2.63e+02 \n",
+ " 7 8 1.4023e+05 1.50e+01 1.78e-01 3.34e+02 \n",
+ " 8 9 1.4022e+05 1.09e+01 8.65e-02 1.95e+02 \n",
+ " 9 10 1.4021e+05 8.79e+00 1.18e-01 2.95e+02 \n",
+ " 10 11 1.4020e+05 7.48e+00 6.08e-02 1.94e+02 \n",
+ " 11 12 1.4020e+05 7.17e+00 1.03e-01 2.92e+02 \n",
+ " 12 13 1.4019e+05 6.89e+00 5.73e-02 1.94e+02 \n",
+ " 13 14 1.4019e+05 4.17e+00 5.95e-02 2.06e+02 \n",
+ " 14 15 1.4018e+05 5.56e+00 6.24e-02 3.05e+02 \n",
+ " 15 16 1.4018e+05 3.49e+00 4.01e-02 1.45e+02 \n",
+ " 16 17 1.4017e+05 2.61e+00 3.26e-02 2.82e+02 \n",
+ " 17 18 1.4017e+05 2.24e+00 2.58e-02 1.33e+02 \n",
+ " 18 19 1.4017e+05 2.16e+00 2.81e-02 2.77e+02 \n",
+ " 19 20 1.4017e+05 2.12e+00 2.51e-02 1.31e+02 \n",
+ " 20 21 1.4017e+05 2.10e+00 2.76e-02 2.75e+02 \n",
+ " 21 22 1.4016e+05 2.07e+00 2.47e-02 1.30e+02 \n",
+ " 22 23 1.4016e+05 2.04e+00 2.72e-02 2.72e+02 \n",
+ " 23 24 1.4016e+05 2.01e+00 2.44e-02 1.28e+02 \n",
+ " 24 25 1.4016e+05 1.99e+00 2.67e-02 2.68e+02 \n",
+ " 25 26 1.4016e+05 1.96e+00 2.41e-02 1.27e+02 \n",
+ " 26 27 1.4015e+05 1.94e+00 2.63e-02 2.64e+02 \n",
+ " 27 28 1.4015e+05 1.91e+00 2.39e-02 1.25e+02 \n",
+ " 28 29 1.4015e+05 1.89e+00 2.59e-02 2.59e+02 \n",
+ " 29 30 1.4015e+05 1.73e+00 2.15e-02 1.12e+02 \n",
+ " 30 31 1.4015e+05 1.71e+00 2.45e-02 2.63e+02 \n",
+ " 31 32 1.4014e+05 1.67e+00 2.08e-02 1.00e+02 \n",
+ " 32 33 1.4014e+05 1.64e+00 2.37e-02 2.76e+02 \n",
+ " 33 34 1.4014e+05 1.62e+00 2.01e-02 9.80e+01 \n",
+ " 34 35 1.4014e+05 1.64e+00 2.37e-02 2.98e+02 \n",
+ " 35 36 1.4014e+05 1.62e+00 1.97e-02 1.09e+02 \n",
+ " 36 37 1.4014e+05 1.56e+00 2.25e-02 3.06e+02 \n",
+ " 37 38 1.4013e+05 1.56e+00 1.91e-02 1.22e+02 \n",
+ " 38 39 1.4013e+05 1.55e+00 2.22e-02 3.16e+02 \n",
+ " 39 40 1.4013e+05 1.53e+00 1.88e-02 1.25e+02 \n",
+ " 40 41 1.4013e+05 1.53e+00 2.20e-02 3.18e+02 \n",
+ " 41 42 1.4013e+05 1.51e+00 1.87e-02 1.24e+02 \n",
+ " 42 43 1.4013e+05 1.50e+00 2.19e-02 3.17e+02 \n",
+ " 43 44 1.4013e+05 1.48e+00 1.85e-02 1.22e+02 \n",
+ " 44 45 1.4012e+05 1.47e+00 2.17e-02 3.14e+02 \n",
+ " 45 46 1.4012e+05 1.45e+00 1.84e-02 1.20e+02 \n",
+ " 46 47 1.4012e+05 1.44e+00 2.16e-02 3.11e+02 \n",
+ " 47 48 1.4012e+05 1.42e+00 1.82e-02 1.17e+02 \n",
+ " 48 49 1.4012e+05 1.41e+00 2.14e-02 3.08e+02 \n",
+ " 49 50 1.4012e+05 1.40e+00 1.81e-02 1.15e+02 \n",
+ " 50 51 1.4012e+05 1.39e+00 2.12e-02 3.06e+02 \n",
+ " 51 52 1.4011e+05 1.37e+00 1.80e-02 1.12e+02 \n",
+ " 52 53 1.4011e+05 1.36e+00 2.11e-02 3.03e+02 \n",
+ " 53 54 1.4011e+05 1.34e+00 1.78e-02 1.10e+02 \n",
+ " 54 55 1.4011e+05 1.33e+00 2.09e-02 3.00e+02 \n",
+ " 55 56 1.4011e+05 1.32e+00 1.77e-02 1.08e+02 \n",
+ " 56 57 1.4011e+05 1.31e+00 2.08e-02 2.97e+02 \n",
+ " 57 58 1.4011e+05 1.29e+00 1.75e-02 1.06e+02 \n",
+ " 58 59 1.4011e+05 1.28e+00 2.06e-02 2.94e+02 \n",
+ " 59 60 1.4010e+05 1.27e+00 1.74e-02 1.04e+02 \n",
+ " 60 61 1.4010e+05 1.26e+00 2.05e-02 2.90e+02 \n",
+ " 61 62 1.4010e+05 1.24e+00 1.72e-02 1.02e+02 \n",
+ " 62 63 1.4010e+05 1.23e+00 2.03e-02 2.87e+02 \n",
+ " 63 64 1.4010e+05 1.22e+00 1.71e-02 9.96e+01 \n",
+ " 64 65 1.4010e+05 1.21e+00 2.01e-02 2.84e+02 \n",
+ " 65 66 1.4010e+05 1.20e+00 1.70e-02 9.76e+01 \n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " 66 67 1.4010e+05 1.19e+00 2.00e-02 2.81e+02 \n",
+ " 67 68 1.4009e+05 1.17e+00 1.68e-02 9.57e+01 \n",
+ " 68 69 1.4009e+05 9.50e-01 1.54e-02 2.55e+02 \n",
+ " 69 70 1.4009e+05 1.14e+00 1.81e-02 1.30e+02 \n",
+ " 70 71 1.4009e+05 1.13e+00 1.65e-02 2.52e+02 \n",
+ " 71 72 1.4009e+05 1.12e+00 1.80e-02 1.28e+02 \n",
+ " 72 73 1.4009e+05 1.11e+00 1.64e-02 2.49e+02 \n",
+ " 73 74 1.4009e+05 6.64e-01 9.02e-03 9.66e+01 \n",
+ " 74 75 1.4009e+05 2.51e-01 3.06e-03 5.72e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 75, initial cost 1.0159e+06, final cost 1.4009e+05, first-order optimality 5.72e+01.\n",
+ "mean reprojection error: 6.615597051442245\n",
+ "max reprojection error: 31.49402030061628\n",
+ "mean reconstruction error: 1.135460440055302\n",
+ "max reconstruction error: 4.5057558874349075\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 23,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjMAAAGoCAYAAACzG2TfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAABPwklEQVR4nO3deXwV5fn//9dFiIDsiAgYCiKUhBBkCdtPWSxVEBUUtWBtIbgBam3RtiAfC+JXLVSrtqIfRCzi9hG1LrVFi/uKYReUJEILliUgEhFBUZLcvz9mkp4k5yQny0kyyfv5eJxHzszcc881Myc5V+65Z25zziEiIiISVA1qOgARERGRylAyIyIiIoGmZEZEREQCTcmMiIiIBJqSGREREQk0JTMiIiISaEpmRGopM3vLzK6s6ThixcwOm1nXUpZ/YmYjqi+i2qesY1DXPyMi0VIyI1XKzHaY2bf+F9VeM3vEzJrVdFzhmJkzs24xqruLX3/DGNV/i5k9HmFZ6DkoeC30l6WZWV7I/O1mttTMfhiLOEvjnGvmnPu3H9cjZnZbseXJzrm3qjuu2iT0GJR2zsvLzOb6n88fV0V9IjVNyYzEwvnOuWZAH6AvcFPNhlMxsUpEqsn5frJQ8LouZNkq//y0BH4MfAusM7NeNRJpLRbuM2BmceWso1zlY83MTgUuBrJrOpbyqm3HUmoPJTMSM865vcA/8ZIaAMxssJl9YGYHzeyj0CZ0M2vjtxLsMbMvzeyFkGVXmdk2M8sxs7+ZWceQZc7MppnZVn+9+83M/GXdzOxtM/vKzL4ws+X+/Hf81T/yWygmmNkIM9tlZjPNbC+w1G/JeC90v0JbdMysiZn90cw+87fxnpk1AQrqP+jXP8Qvf7mZZfhx/tPMOofUe5aZZfr1LASskqegVM65POfcv5xz1wBvA7eEKxdyXGb7x3CHmV0WsrylmT1qZvv943CzmTXwl4U9/v4y5y+/GrgM+K1/rF7yl+8oaDkws0Zmdq//2djjv29ULL4bzexzM8s2symR9tuP92G/3G4zu63gS9I/3++b2T1mlgPc4rca/a+ZrTCzI8CZZpZk3iWeg+ZdChobUn+J8sW2f6aZbQ6Zfs3MVodMv2dmF4QeAzMbDcwGJvjH6KOQKjv7MX9tZivNrG2kffctBGYC35dWyCL8PppZazP7u3++v/TfJ4Ss95Z/TD8oOJ9mdoKZPWFmh8xsjZl1CSmfaGavmve7nWVmPyntWJrZuWa2wa9rp5ndElK+sZk9bmYH/HOzxsxOKuN4SF3gnNNLryp7ATuAH/vvE4DNwJ/86ZOBA8AYvET6LH/6RH/5P4DlQGsgHhjuz/8R8AXQD2gE3Ae8E7JNB/wdaAX8ANgPjPaX/R/wP/72GgNnFFuvW8j0CCAXWOBvpwmQBrxXbB8L1wPuB97y9y0O+P/8dbv45RqGrHcBsA1IAhoCNwMf+MvaAofw/mOOB2b4sVwZ4TjfAjxe1jkIs6zE/vjzLwf2RVin4Ljc7e/bcOAI0MNf/ijwItDc3+9PgSvKc/yBR4DbSvks3Qp8CLQDTgQ+AP5fsfhu9Y/dGOAboHWE/XkBeBBo6te3GpgacnxygV/456iJH9tXwOn+fjT3z+Ns4Di8z+fXIcejePnGxbbfGK81rK2/jb3AHr/eJv6yE8IcgxLnHO+z9y/gh/66bwHzS/n9vAR4sazPSRm/jycAFwHH+zE/A7xQLKZtwKl4rX9b/M/Ej/39fRRY6pdtCuwEpvjL+uH9ridHOpb++U7xp3sD+4AL/PJTgZf82OKA/kCLmv67qFfsXzUegF516+X/gTzs/3F3wOtAK3/ZTOCxYuX/CUwGOgD5hPkCAh4G/hAy3Qw4BnTxpx1FvySfBmb57x8FFgMJYeoNl8x8T8iXD6UkM/4f02+B08LU3YWSyczL+F/y/nQDvC/dzsAk4MOQZQbsouLJzGHgYMjrqkj7488fDRyLUN8IvC/4psWO8e/8L4zvgJ4hy6YCb5Xn+FN2MvMvYEzIslHAjpD4vi12rD8HBofZ5kl+vE1C5l0KvBlyfP5TbJ1HgEdDpofiJSANQub9H3BLuPIRjum7wHhgMLDSP56j8VpxNkU4BiXOOV7icHPI9DXAKxG22QzYCpxSvO4wZSP+PoYp2wf4slhM/xMy/Ufg5ZDp84GN/vsJwLvF6nsQmFuOY3kvcI///nK8RLd3WXHrVbdeuswksXCBc6453pdMIt5/oOB9aV/iN/8eNLODwBl4fzg7ATnOuS/D1NcR+Kxgwjl3GK9F5+SQMntD3n+D94cb4Ld4icFq/3LA5WXEvt85d7TsXQS8/WqM90Ubjc7An0L2PceP7WS8fdxZUNA550KnK+AC51yrkNdDZZQ/2Y8nki+dc0dCpj/Di7ktXuvEZ8WWFZyb8h7/SIp8BkK2X+CAcy43ZDr0MxCqM14rQ3bIeXgQr4WmQLjjHjqvI7DTOZdfLJ6TI5QP5228349h/vu38Fq8hvvT5RHps1/cPLx/JrZHUWfE30czO97MHjTvkuIhvEuqraxof5Z9Ie+/DTNdEGNnYFCxvwmXAe1Dyhc5lmY2yMze9C9zfQVM479/Yx7D+wfpKf/y2B/MLD6K/ZWAUzIjMeOcexvvP6u7/Fk78f6Yhn7JNnXOzfeXtTGzVmGq2oP3Rw8AM2uK19S9O4oY9jrnrnLOdcRrMXjASr+Dqfgw8kfwmqwLth36R/YL4Chec3pZ9YC3j1OL7X8T59wHeJ0xO4Vsx0Knq8GFeK0FkbT2j3uBH+Cdly/wWsk6F1u2G8p1/MMdr1BFPgMh2y+vnXgtM21DzkEL51xyGbGEztsDdDK/X1BIPLsjlA+neDLzNmUnM2XVWZaRwPXm3WW4F+/z9bSZzQxTtrTfxxuBHsAg51wLvH2AivXx2gm8Xex3oplzbnpImeL7/STwN6CTc64lsKhg2865Y865ec65nniXfM/Da/WUOk7JjMTavcBZZtYHeBw438xGmVmc31lvhJklOOey8S7DPOB3MIw3s4I/kk8CU8ysj3mdPu8A0p1zO8rauJldEtI58Uu8P4x5/vQ+IOJzTnwfAcn+thsT0knW/8/8L8DdZtbR36chfoz78ZrpQ+tfBNxkZsl+bC3N7BJ/2T/87Yw37w6a6yn632k4DfxjWPBqVEb5Ivx4TzGz+/C+WOeVsco8MzvOzIbifUk845zLw7tEcruZNTevQ/MNeOe6rOMfqqxz8X/AzWZ2onkdXOcUbKM8/M/ZSuCPZtbCzBqY2almNrwc1aTjJbm/9T+nI/AunTxVjjo+wEsIBgKrnXOf4LdS8N/O48XtA7oUS6LKYyTQC++yUB+8pGwqXr+vIsr4fWyO17py0MzaAHMrGA94fd1+aGY/97cRb2YDzCyplHWa47UaHTWzgcBPCxaY17k6xW8lOoSXaIf7vEkdo2RGYso5tx+v38TvnHM7gXF4HSf34/1X9hv++zn8Od4fn0y8Pg+/8ut4Ha9/xl/xWjBOBSZGGcIAIN3MDuP9N/fLkGb2W4BlfvP2T8Kt7Jz7FK9j6Wt4/Q3eK1bk13idnNfgXaZZgNeX4hvgduB9v/7Bzrnn/eVP+c3zHwPn+Nv5Aq9z5ny8S2jdgffL2LdL8b5UCl6hl7tesqLPmXk+ZNkQ/3gcwru80QIY4JzbTGR78ZKRPcATwDTnXKa/7Bd4X+7/9o/Pk3hJHpR+/EM9DPT0j9ULYZbfBqwFNuEd7/X+vIqYhHdpbIu/T8/iXeqMinPue2As3rn7AngAmBRyPKKp4wjePnzi1wewCvjMOfd5hNWe8X8eMLP10W4rZJsH/Jayvc670zAP7/Lh4QirhP19xPsHpQnevn8IvFLeWEJi+ho4G+/3eQ/e56ygA34k1wC3mtnXeEnt0yHL2uOdz0NABl4rV5U8m0dqN/MuzYuIhOe3PDzunEsoo6iISI1Qy4yIiIgEmpIZERERCTRdZhIREZFAU8uMiIiIBFqtGEivbdu2rkuXLjUdhoiIiNRi69at+8I5d2Lx+bUimenSpQtr166t6TBERESkFjOzz8LN12UmERERCTQlMyIiIhJoSmZEREQk0GpFnxkRkfri2LFj7Nq1i6NHox2cXaT+ady4MQkJCcTHRzfouZIZEZFqtGvXLpo3b06XLl3wBkcXkVDOOQ4cOMCuXbs45ZRTolpHl5lERKrR0aNHOeGEE5TIiERgZpxwwgnlar1UMiMiUs2UyIiUrry/I7rMJCJSQ+a99Alb9hyq0jp7dmzB3POTq7ROkdpOLTMiIjVky55DbMmuumRmS/ahqJKjyy+/nHbt2tGrV6+IZZxzXH/99XTr1o3evXuzfv36csUyZ84cXnvttXKtU6BZs2YVWk9g+/btDBo0iO7duzNhwgS+//77sOVGjx5Nq1atOO+884rMv+yyy+jRowe9evXi8ssv59ixY9URdqWpZUZEpAb17NCC5VOHVEldEx5cFVW5tLQ0rrvuOiZNmhSxzMsvv8zWrVvZunUr6enpTJ8+nfT09KhjufXWW6MuW5Xy8vKIi4uLOB2Ocw7nHA0aBP//+5kzZzJjxgwmTpzItGnTePjhh5k+fXqJcr/5zW/45ptvePDBB4vMv+yyy3j88ccB+OlPf8qSJUvCrl/bBP/MiYhIuQwbNow2bdqUWubFF19k0qRJmBmDBw/m4MGDZGdnlyjXrFkzbrzxRvr168fIkSPZv38/4CVMzz77LF999RU9evQgKysLgEsvvZSHHnoIgDvvvJMBAwbQu3dv5s6dW2bcjz/+OAMHDqRPnz5MnTqVvLy8whjmzJnDoEGDWLVqVYnpu+++m169etGrVy/uvfdeAHbs2EFSUhLXXHMN/fr1Y+fOnRG3O2LECGbMmMGwYcNISkpizZo1jB8/nu7du3PzzTeXGd/06dNJTU0lOTm5yH526dKFuXPn0q9fP1JSUsjMzCzzGJTGOccbb7zBxRdfDMDkyZN54YUXwpYdOXIkzZs3LzF/zJgxmBlmxsCBA9m1a1eJMnl5efz6178mJSWF3r17c9999xXuz+zZsxkyZAipqamsX7+eUaNGceqpp7Jo0aJK7VtZlMyIiEgJu3fvplOnToXTCQkJ7N69u0S5I0eO0K9fP9avX8/w4cOZN29ekeUtW7Zk4cKFpKWl8dRTT/Hll19y1VVXsXLlSrZu3crq1avZuHEj69at45133okYT0ZGBsuXL+f9999n48aNxMXF8cQTTxTG0KtXL9LT0znjjDOKTDdp0oSlS5eSnp7Ohx9+yEMPPcSGDRsAyMrKYtKkSWzYsIHOnTszZswY9uzZE3b7xx13HO+88w7Tpk1j3Lhx3H///Xz88cc88sgjHDhwoNT4br/9dtauXcumTZt4++232bRpU2G9bdu2Zf369UyfPp277rqrxHazsrLo06dP2NfBgweLlD1w4ACtWrWiYcOGpZ6zaBw7dozHHnuM0aNHl1i2ePFitm/fzoYNG9i0aROXXXZZ4bJOnTqxatUqhg4dWpjQfvjhh8yZM6dCcURLl5lERKQE51yJeeHuMGnQoAETJkwA4Gc/+xnjx48vUeass87imWee4dprr+Wjjz4CYOXKlaxcuZK+ffsCcPjwYbZu3cqwYcPCxvP666+zbt06BgwYAMC3335Lu3btAIiLi+Oiiy4qLBs6/d5773HhhRfStGlTAMaPH8+7777L2LFj6dy5M4MHDy5cb8WKFRGPx9ixYwFISUkhOTmZDh06ANC1a1d27tzJe++9FzG+p59+msWLF5Obm0t2djZbtmyhd+/ehfEA9O/fn+eee67Ednv06MHGjRsjxhUq2nMWjWuuuYZhw4YxdOjQEstee+01pk2bVpg0hbbyhR6nw4cP07x5c5o3b07jxo05ePAgrVq1qlA8ZVEyIyIiJSQkJBS59LJr1y46duxY5nrhvjzz8/PJyMigSZMm5OTkkJCQgHOOm266ialTp0YVj3OOyZMn8/vf/77EssaNGxfpFxM6He4LvkBBghONRo0aAV7yVvC+YDo3NzdifNu3b+euu+5izZo1tG7dmrS0tCLPTymoKy4ujtzc3BLbzcrKKkwWi3vrrbeKJAdt27bl4MGD5Obm0rBhw6jPWXHz5s1j//79JfrTFHDORUySyjpOsaJkRkSkBm3JPhR1x91o6urZoUWV1DV27FgWLlzIxIkTSU9Pp2XLloWtEaHy8/N59tlnmThxIk8++SRnnHFGiTL33HMPSUlJ3HHHHVx++eWsWrWKUaNG8bvf/Y7LLruMZs2asXv3buLj4wtbM4obOXIk48aNY8aMGbRr146cnBy+/vprOnfuXOp+DBs2jLS0NGbNmoVzjueff57HHnusYgelFJHiO3ToEE2bNqVly5bs27ePl19+mREjRkRdb3laZsyMM888s/B8LFu2jHHjxpVrP5YsWcI///lPXn/99Ygdos8++2wWLVrEiBEjaNiwITk5OWX2wYo1JTPRenkW7N1cepn2KXDO/OqJR0QCr2fHqkk8Cuvr0CKqOi+99FLeeustvvjiCxISEpg3bx5XXHFFYSfNadOmMWbMGFasWEG3bt04/vjjWbp0adi6mjZtyieffEL//v1p2bIly5cvL7L8008/ZcmSJaxevZrmzZszbNgwbrvtNubNm0dGRgZDhnh3cjVr1ozHH388YjLTs2dPbrvtNs4++2zy8/OJj4/n/vvvLzOZ6devH2lpaQwcOBCAK6+8kr59+7Jjx44SZceMGcOSJUsq1JoRKb7BgwfTt29fkpOT6dq1K6effnq56y6PBQsWMHHiRG6++Wb69u3LFVdcAcDatWtZtGgRS5YsAWDo0KFkZmZy+PBhEhISePjhhxk1ahTTpk2jc+fOhedl/PjxJfq7XHnllXz66af07t2b+Ph4rrrqKq677rqY7ldZrLQmuOqSmprq1q5dW9NhlG7puV4y0z4l/PKCZVP+Ub1xiUigZGRkkJSUVNNhVJlmzZpx+PDhmg5D6qBwvytmts45l1q8rFpmyqO0ZGXpudUbi4iIiAC6NVtERCpBrTJSG9TblpnQMVE0lomIiEhw1dtkpqrHRBEREZGaUW+TGaDKbmEUERGRmlOvkxkRkRoVzSMfykuPiJB6SB2ARURqyt7NVZvMRFHf0aNHGThwIKeddlqJgQ9DOee4/vrr6datG71792b9+vXlCmXOnDm89tpr5VqnQLNmzSq0nnhPHB40aBDdu3dnwoQJfP/99yXKfPbZZ/Tv358+ffqQnJwcdhDIX/ziF4E6D2qZiaEFqxeQmVPxUVAT2yQyc+DMKoxIRGqdqnw+VRSPiGjUqBFvvPEGzZo149ixY5xxxhmcc845RcYoAnj55ZfZunUrW7duJT09nenTp5Oenh51KLfeemu5w68KeXl5RYY2KD4djnMO51zEJ94GycyZM5kxYwYTJ05k2rRpPPzww0yfPr1ImQ4dOvDBBx/QqFEjDh8+TK9evRg7dmzhwwLXrl1bYhDL2i74Z64Wy8zJJCsnq0LrZuVkVSoREhEJx8wK/+M+duwYx44dCzvOzosvvsikSZMwMwYPHszBgwfJzs4uUa5Zs2bceOON9OvXj5EjR7J//36AwhGTv/rqK3r06EFWlve38NJLL+Whhx4C4M4772TAgAH07t07YgtRqMcff5yBAwfSp08fpk6dSl5eXmEMc+bMYdCgQaxatarE9N13302vXr3o1asX9957LwA7duwgKSmJa665hn79+hUZh6q4ESNGMGPGDIYNG0ZSUhJr1qxh/PjxdO/enZtvvrnM+KZPn05qamqJlrAuXbowd+5c+vXrR0pKCpmZlfub75zjjTfe4OKLLwZg8uTJvPDCCyXKHXfccYXjJn333Xfk5+cXLsvLy+M3v/kNf/jDHyJuJy8vj1//+tekpKTQu3dv7rvvvsL9mT17NkOGDCE1NZX169czatQoTj311LCtP1VJLTMx1qNND5aODv8Y8NJMeWVKDKIREfG+jPr378+2bdu49tprGTRoUIkyu3fvplOnToXTCQkJ7N69u8T4TEeOHKFfv3788Y9/5NZbb2XevHksXLiwcHnLli1ZuHAhaWlp/PKXv+TLL7/kqquuYuXKlWzdupXVq1fjnGPs2LG88847EUfNzsjIYPny5bz//vvEx8dzzTXX8MQTTzBp0iSOHDlCr169CluDQqfXrVvH0qVLSU9PxznHoEGDGD58OK1btyYrK4ulS5fywAMPAKUPZ3Dcccfxzjvv8Kc//Ylx48axbt062rRpw6mnnsqMGTP4/PPPI8Z3++2306ZNG/Ly8hg5ciSbNm0qHDW7bdu2rF+/ngceeIC77rqrcLiBAuUZaPLAgQO0atWqcDTrgnMWzs6dOzn33HPZtm0bd955Z+E+L1y4kLFjx4Ydh6vA4sWL2b59Oxs2bCgcm6lAp06dWLVqFTNmzCAtLY3333+fo0ePkpyczLRp0yLWWVlKZkRE6pm4uDg2btzIwYMHufDCC/n444/p1atXkTLhhroJ14LToEGDwi/bn/3sZ4wfP75EmbPOOotnnnmGa6+9lo8++giAlStXsnLlSvr27Qt4D9/bunVrxGTm9ddfZ926dQwYMACAb7/9tnAcp7i4OC666KIi+1cw/d5773HhhRcWjpA9fvx43n33XcaOHUvnzp2LXF5bsWJF2G2DN/AmQEpKCsnJyYVf9l27dmXnzp289957EeN7+umnWbx4Mbm5uWRnZ7Nly5bCZKbgePXv35/nnnuuxHbLM9BktOcMvKRj06ZN7NmzhwsuuICLL76YvLw8nnnmGd56661St/Paa68xbdq0wqQpdJDJ0ON0+PBhmjdvTvPmzWncuDEHDx4sknxVJSUzIiL1VKtWrRgxYgSvvPJKiWQmISGhyKWXXbt2RTUAY7gvz/z8fDIyMmjSpAk5OTkkJCTgnOOmm25i6tSpUcXqnGPy5Mn8/ve/L7GscePGRfrFhE6XNv5gQYITjYLLMg0aNCh8XzCdm5sbMb7t27dz1113sWbNGlq3bk1aWhpHjx4tUW9cXBy5ubkltluelpm2bdty8OBBcnNzadiwYVTnrGPHjiQnJ/Puu+/SpEkTtm3bRrdu3QD45ptv6NatG9u2bSuyjnMuYpJU1nGKFSUzIiI1ae/mqhvbrbTBcH379+8nPj6eVq1a8e233/Laa68xc2bJGw3Gjh3LwoULmThxIunp6bRs2TLspYf8/HyeffZZJk6cyJNPPskZZ5xRosw999xDUlISd9xxB5dffjmrVq1i1KhR/O53v+Oyyy6jWbNm7N69m/j4+IijZo8cOZJx48YxY8YM2rVrR05ODl9//XWZo2YPGzaMtLQ0Zs2ahXOO559/nscee6zUdSoiUnyHDh2iadOmtGzZkn379vHyyy8zYsSIqOstT8uMmXHmmWcWno9ly5Yxbty4EuV27drFCSecQJMmTfjyyy95//33ueGGG0hJSWHv3r2F5Zo1a1YikQE4++yzWbRoESNGjCi8zBTaOlMTlMyIiNSUMhKPCtVXRp3Z2dlMnjyZvLw88vPz+clPfsJ5550HUNhJc9q0aYwZM4YVK1bQrVs3jj/+eJYuDd/3r2nTpnzyySf079+fli1bsnz58iLLP/30U5YsWcLq1atp3rw5w4YN47bbbmPevHlkZGQwZMgQwPvifPzxxyMmMz179uS2227j7LPPJj8/n/j4eO6///4yk5l+/fqRlpbGwIEDAbjyyivp27cvO3bsKFG2tD4zZYkU3+DBg+nbty/Jycl07dqV008/vdx1l8eCBQuYOHEiN998M3379uWKK64AvDuUFi1axJIlS8jIyODGG2/EzHDOFXbmjdaVV17Jp59+Su/evYmPj+eqq67iuuuui9UuRcVKa4KrLqmpqW7t2rXVus0JD64qMr186pDSVyj4z6msUbNDlhd04q1MB+CKrCsitVdGRgZJSUk1HUaVadasmQablJgI97tiZuucc6nFy+rWbBEREQm0MpMZM2tsZqvN7CMz+8TM5vnz25jZq2a21f/ZOmSdm8xsm5llmdmoWO6AiIjUHLXKSG0QTcvMd8CPnHOnAX2A0WY2GJgFvO6c6w687k9jZj2BiUAyMBp4wMxKf/yiiIiISAWVmcw4T0HqHe+/HDAOWObPXwZc4L8fBzzlnPvOObcd2AYMrMqgRURERApE1WfGzOLMbCPwOfCqcy4dOMk5lw3g/yzogn4yEPpc6F3+vOJ1Xm1ma81sbcHjr0VERETKK6pbs51zeUAfM2sFPG9mvUopHu5JOiVumXLOLQYWg3c3UzRxiIjUJZUdjDYcDVAr9VG57mZyzh0E3sLrC7PPzDoA+D8/94vtAjqFrJYA7KlsoCIidU1lBqMNJ9oBart06UJKSgp9+vQhNbXEXa6A95TX66+/nm7dutG7d2/Wr19frljmzJnDa6+9Vq51ChQMhCnlt337dgYNGkT37t2ZMGEC33//fdhycXFx9OnThz59+hQOQQDesBH9+vWjT58+nHHGGWEfmlcbldkyY2YnAseccwfNrAnwY2AB8DdgMjDf//miv8rfgCfN7G6gI9AdWB2D2EVEAq+ig9GGU54Bat98803atm0bcfnLL7/M1q1b2bp1K+np6UyfPp309PSo6y8Y9LG65eXlFRnaoPh0OM45nHM0aBD8p5XMnDmTGTNmMHHiRKZNm8bDDz/M9OnTS5Rr0qRJ2CcLT58+nRdffJGkpCQeeOABbrvtNh555JHYB15J0Zy5DsCbZrYJWIPXZ+bveEnMWWa2FTjLn8Y59wnwNLAFeAW41r9MJSIiAfHiiy8yadIkzIzBgwdz8OBBsrOzS5Rr1qwZN954I/369WPkyJEU9IFMS0vj2Wef5auvvqJHjx5kZXktUJdeeikPPfQQAHfeeScDBgygd+/ezJ07t8yYHn/8cQYOHEifPn2YOnUqeXl5hTHMmTOHQYMGsWrVqhLTd999N7169aJXr17ce++9AOzYsYOkpCSuueYa+vXrV2QcquJGjBjBjBkzGDZsGElJSaxZs4bx48fTvXt3br755jLjmz59OqmpqSQnJxfZzy5dujB37lz69etHSkoKmZmVu+TonOONN97g4osvBmDy5Mm88MIL5arDzDh06BAAX331VdinIefl5RU+Nbh3797cd999hfsze/ZshgwZQmpqKuvXr2fUqFGceuqphU+XjpVo7mba5Jzr65zr7Zzr5Zy71Z9/wDk30jnX3f+ZE7LO7c65U51zPZxzL8dyB0REpHzMjLPPPpv+/fuzePHisGV2795Np07/7TGQkJDA7t27S5Q7cuQI/fr1Y/369QwfPpx58+YVWd6yZUsWLlxIWloaTz31FF9++SVXXXUVK1euZOvWraxevZqNGzeybt063nnnnYgxZ2RksHz5ct5//302btxIXFwcTzzxRGEMvXr1Ij09nTPOOKPIdJMmTVi6dCnp6el8+OGHPPTQQ2zYsAHwBnGcNGkSGzZsoHPnzowZM4Y9e8L3ijjuuON45513mDZtGuPGjeP+++/n448/5pFHHuHAgQOlxnf77bezdu1aNm3axNtvv82mTZsK623bti3r169n+vTp3HXXXSW2m5WVVXg5qPjr4MGDRcoeOHCAVq1aFY5mHemcARw9epTU1FQGDx5cJOFZsmQJY8aMISEhgccee4xZs2aVWHfx4sVs376dDRs2sGnTJi677LLCZZ06dWLVqlUMHTq0MKH98MMPmTNnTtg4qorGZhIRqWfef/99OnbsyOeff85ZZ51FYmIiw4YNK1Im3FA34UZKbtCgQeGozj/72c8YP358iTJnnXUWzzzzDNdeey0fffQRACtXrmTlypX07dsX8B6+t3Xr1hJxFHj99ddZt24dAwYMAODbb78tHMcpLi6Oiy66qLBs6PR7773HhRdeWDhC9vjx43n33XcZO3YsnTt3ZvDgwYXrrVixIuy2gcJ+JSkpKSQnJxcOutm1a1d27tzJe++9FzG+p59+msWLF5Obm0t2djZbtmyhd+/ehfEA9O/fn+eee67Edssz0GS05wzgP//5Dx07duTf//43P/rRj0hJSeHUU0/lnnvuYcWKFQwaNIg777yTG264gSVLlhRZ97XXXmPatGmFSVPoIJOhx+nw4cM0b96c5s2b07hxYw4ePFhklO+qpGRGRKSeKbh00K5dOy688EJWr15dIolISEgocull165dUQ3AGO7LMz8/n4yMDJo0aUJOTg4JCQk457jpppuYOnVqVDE755g8eTK///3vSyxr3LhxkX4xodOljT9YkOBEo1GjRoCXvBW8L5jOzc2NGN/27du56667WLNmDa1btyYtLY2jR4+WqDcuLo7c3NwS283KyipMFot76623iiQHbdu25eDBg+Tm5tKwYcNSz1nB/K5duzJixAg2bNhAixYt+Oijjxg0aBAAEyZMYPTo0SXWdc5FTJLKOk6xomRGRKQGZeVklavjbll19WjTo9QyR44cIT8/n+bNm3PkyBFWrlwZ9hLA2LFjWbhwIRMnTiQ9PZ2WLVsWtkaEys/P59lnn2XixIk8+eSTnHHGGSXK3HPPPSQlJXHHHXdw+eWXs2rVKkaNGsXvfvc7LrvsMpo1a8bu3buJj4+POGr2yJEjGTduHDNmzKBdu3bk5OTw9ddflzlq9rBhw0hLS2PWrFk453j++ed57LHHSl2nIiLFd+jQIZo2bUrLli3Zt28fL7/8MiNGjIi63vK0zJgZZ555ZuH5WLZsGePGjStR7ssvv+T444+nUaNGfPHFF7z//vv89re/pXXr1nz11Vd8+umn/PCHP+TVV18NOyjq2WefzaJFixgxYgQNGzYkJyenSOtMTVAyIyJSQxLbJFZpfT3a9Cizzn379nHhhRcCkJuby09/+tPC/74LOmlOmzaNMWPGsGLFCrp168bxxx/P0qXh77hq2rQpn3zyCf3796dly5YsX768yPJPP/2UJUuWsHr1apo3b86wYcO47bbbmDdvHhkZGQwZMgTwOvE+/vjjEZOZnj17ctttt3H22WeTn59PfHw8999/f5nJTL9+/UhLS2PgQO9B9FdeeSV9+/Zlx44dJcqOGTOGJUuWRNUCFW18gwcPpm/fviQnJ9O1a1dOP/30ctddHgsWLGDixIncfPPN9O3blyuuuAKAtWvXsmjRIpYsWUJGRgZTp06lQYMG5OfnM2vWLHr27AnAQw89xEUX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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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vXrl3jc/P7/E5UiOHTvmjh49Wu42TySXXHKJ+/Of/+ycc27y5MnuoYceKlZm//797qyzznL79+93ubm57qyzznK5ubnOOee+/vrrULlp06a5u+66q3ICLyL876QAsNZFySM00iIicpJKS0ujadOmJZZ5+eWXGTduHGZG3759ycvLIycnp1i5+vXrc+ONN9K9e3cGDx7Mvn37AEhPT+f555/n66+/JikpiezsbAAuvfRSHnnkEQDuueceevXqRWpqKrfddlupcT/11FP07t2brl27MnnyZI4ePRqKYdasWfTp04dVq1YVW77//vvp3LkznTt35ne/+x0AO3bsoEOHDlx99dV0796dzz//PGq7AwcOZNq0aaSlpdGhQwc+/PBDRo8eTfv27bnllltKjW/q1Kn07NmTTp06FTrONm3acNttt9G9e3dSUlLIysoqtQ9K4pzj7bff5uKLLwZg/PjxvPTSS8XKvf766wwZMoSmTZvSpEkThgwZwtKlSwFo2LBhqK5Dhw5FvL7k6NGj/OpXvyIlJYXU1FT+8Ic/hI5n5syZ9OvXj549e7J+/XqGDRvG2Wefzfz584/r2EqjpEVEpBrbtWsXZ5xxRmg5MTGRXbt2FSv37bff0r17d9avX8+5557L7NmzC21v1KgR8+bNIz09nWeffZavvvqKSZMmsWzZMrZt28aaNWvYuHEj69atY+XKlVHjyczMZPHixbz//vts3LiRmjVr8vTTT4di6Ny5MxkZGfTv37/Qct26dVm4cCEZGRmsXr2aRx55hA0bNgCQnZ3NuHHj2LBhA61bt2bEiBHs3r07YvunnHIKK1euZMqUKYwaNYoHH3yQLVu28Pjjj7N///4S4/vtb3/L2rVr2bRpEytWrGDTpk2heps1a8b69euZOnUq9957b7F2s7Oz6dq1a8RHXl5eobL79++ncePG1KpVq8TXrLTXdsKECbRo0YKsrCyuu+66YvsvWLCA7du3s2HDBjZt2sRll10W2nbGGWewatUqBgwYEEpcV69ezaxZsyL2a7zoQlwRkWrMG40vLNK37ho1ajBmzBgALr/8ckaPHl2szJAhQ3juuee45ppr+OijjwBYtmwZy5Yto1u3bgAcPHiQbdu2kZaWFjGet956i3Xr1tGrVy8ADh06RPPmzQGoWbMmF110Uahs+PJ7773HhRdeSL169QAYPXo07777LiNHjqR169b07ds3tN9rr70WtT9GjhwJQEpKCp06daJly5YAtG3bls8//5z33nsvanx/+ctfWLBgAfn5+eTk5LB161ZSU1ND8QD06NGDF154oVi7SUlJbNy4MWpc4WJ9zUort3DhQo4ePcp1113H4sWLmTBhQqGyb775JlOmTAklR+GjduH9dPDgQRo0aECDBg1ISEggLy+Pxo0bx3QsZaWkRUSkGktMTCx0ymTnzp20atWq1P0ifUgeO3aMzMxM6tatS25uLomJiTjnuPnmm5k8eXJM8TjnGD9+PHfddVexbQkJCdSsWTPicqQP6AIFiUws6tSpA3hJWsHzguX8/Pyo8W3fvp17772XDz/8kCZNmpCenl7oHiQFddWsWZP8/Pxi7WZnZ4eSwqKWL19eKAlo1qwZeXl55OfnU6tWraivWWJiIsuXLw8t79y5k4EDBxYqU7NmTcaMGcM999xTLGlxzkX9WXJp/VRRlLSIiFSCrTkHGPPwqrjV1bFlw7jUNXLkSObNm8fYsWPJyMigUaNGodGFcMeOHeP5559n7NixPPPMM/Tv379YmQceeIAOHTowZ84cJk6cyKpVqxg2bBi33norl112GfXr12fXrl3Url07NDpR1ODBgxk1ahTTpk2jefPm5Obm8s0339C6desSjyMtLY309HRmzJiBc44XX3yRJ598snydUoJo8R04cIB69erRqFEj9u7dy5IlS4olCCUpy0iLmTFo0KDQ67Fo0SJGjRpVrNywYcOYOXMmX331FeCNet1111045/j0009p164dzjleeeUVkpOTi+0/dOhQ5s+fz8CBA6lVqxa5ubmlXiNV0U7KpKXoPRF0PwMRqUodW8UnwQjV17JhTHVeeumlLF++nC+//JLExERmz57NFVdcEbpYcsqUKYwYMYLXXnuNdu3aceqpp7Jw4cKIddWrV4+PP/6YHj160KhRIxYvXlxo+yeffMKjjz7KmjVraNCgAWlpadx5553Mnj2bzMxM+vXrB3gX0z711FNRk5aOHTty5513MnToUI4dO0bt2rV58MEHS01aunfvTnp6Or179wbgyiuvpFu3buzYsaNY2REjRvDoo4/GNKIUa3x9+/alW7dudOrUibZt23LOOeeUue6ymDt3LmPHjuWWW26hW7duXHHFFQCsXbuW+fPn8+ijj9K0aVNuvfXW0KmsWbNm0bRpU44dO8b48eM5cOAAzjm6dOnCH//4x2JtXHnllXzyySekpqZSu3ZtJk2axLXXXluhx1UaK2lILd569uzp1q5dW+HtjHl4VeibSMG/iyf3q/B2RUQKZGZm0qFDh6oOI27q168fnHt5SGBE+jsxs3XOuZ6Ryp+0vx4qSFTiNYQqIiIiVeukTVpERCR+NMoiJwIlLSIiIhIISlpEREQkEJS0iIiISCCclD95FhE5oSyZAXs2x7fOFilw3t3xrVPkBKeRFhGRirZnc3yTlhjqO3z4ML1796ZLly7FJvAL55zj+uuvp127dqSmprJ+/foyhTJr1izefPPNMu1ToH79+uXaT7w78Pbp04f27dszZswYjhw5ErHc8OHDady4Meeff3659j/RaKRFRKQytEiBCa/Gp66FPym1SJ06dXj77bepX78+33//Pf379+e8884rNAcPwJIlS9i2bRvbtm0jIyODqVOnkpGREXMod9xxR5nDj4ejR48WuqV/0eVInHM456hRI/jf16dPn860adMYO3YsU6ZM4bHHHmPq1KnFyt100038+9//5uGHHy7X/iea4L9yIiJSjJmFRjK+//57vv/++4jzyLz88suMGzcOM6Nv377k5eWRk5NTrFz9+vW58cYb6d69O4MHD2bfvn0AoRl+v/76a5KSksjOzga8u/E+8sgjANxzzz306tWL1NTUqCM+4Z566il69+5N165dmTx5MkePHg3FMGvWLPr06cOqVauKLd9///107tyZzp0787vf/Q6AHTt20KFDB66++mq6d+9eaJ6logYOHMi0adNIS0ujQ4cOfPjhh4wePZr27dtzyy23lBrf1KlT6dmzZ7GRrTZt2nDbbbfRvXt3UlJSyMrKKrUPSuKc4+233+biiy8GYPz48bz00ksRyw4ePJgGDRqUa/+jR4/yq1/9ipSUFFJTU/nDH/4QOp6ZM2fSr18/evbsyfr16xk2bBhnn3126G7LFUVJi4jISero0aN07dqV5s2bM2TIEPr06VOszK5duzjjjDNCy4mJiezatatYuW+//Zbu3buzfv16zj33XGbPnl1oe6NGjZg3bx7p6ek8++yzfPXVV0yaNIlly5axbds21qxZw8aNG1m3bh0rV66MGnNmZiaLFy/m/fffZ+PGjdSsWZOnn346FEPnzp3JyMigf//+hZbr1q3LwoUL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ypQpoeQofLLE8H46ePAgDRo0oEGDBiQkJJCXl1doVup4iilpMbPaeAnL0865FwCcc3vDtj8C/L1CIhQRkXJp1aoVAM2bN+fCCy9kzZo1xZKFxMREPv/889Dyzp07Q/uVJNKH5LFjx8jMzKRu3brk5uaSmJiIc46bb76ZyZMnxxSzc47x48dz1113FduWkJBQ6LqV8OWS5tErSGRiUadOHcBL0gqeFyzn5+dHjW/79u3ce++9fPjhhzRp0oT09HQOHz5crN6aNWuSn59frN3s7OxQUljU8uXLCyUBzZo1Iy8vj/z8fGrVqhXza1bU/v37WbNmDS+++GLE7c65qMlQaf1UUUpNWsyL+DEg0zl3f9j6lv71LgAXAlsqJkQRkeDLzs2O2+hmdm42SU2TSizz7bffcuzYMRo0aMC3337LsmXLIg7djxw5knnz5jF27FgyMjJo1KhRsetZwEtInn/+ecaOHcszzzxD//79i5V54IEH6NChA3PmzGHixImsWrWKYcOGceutt3LZZZdRv359du3aRe3atUOjE0UNHjyYUaNGMW3aNJo3b05ubi7ffPNN1OtQCqSlpZGens6MGTNwzvHiiy/y5JNPlrhPeUSL78CBA9SrV49GjRqxd+9elixZwsCBA2OutywjLWbGoEGDQq/HokWLynUh7XPPPcf5559PQkJCxO1Dhw5l/vz5DBw4kFq1apGbm1totKUqxDLScg7wC2CzmW30180ELjWzrninh3YAsaXRIiLVTHLT8l90GUlS06RS69y7dy8XXnghAPn5+fz85z9n+PDhAMyfPx+AKVOmMGLECF577TXatWvHqaeeGvGCTPBGKz7++GN69OhBo0aNWLx4caHtn3zyCY8++ihr1qyhQYMGpKWlceeddzJ79mwyMzPp168f4F3Q+9RTT0VNWjp27Midd97J0KFDOXbsGLVr1+bBBx8sNWnp3r076enp9O7dG/AuxO3WrRs7duwoVnbEiBE8+uij5RqdiBZf37596datG506daJt27acc845Za67LObOncvYsWO55ZZb6NatG1dccQUAa9euZf78+Tz66KOA99PmrKwsDh48SGJiIo899hjDhg0D4Nlnn2XGjBlR27jyyiv55JNPSE1NpXbt2kyaNIlrr722Qo+rNFbSkFq89ezZ061du7bC2xnz8CoAFk/uV+j5yarg21t5r2mJ188wS1JwXUlVXtNSFW1L9ZWZmUmHDh2qOoy4qV+/viZNlLiL9HdiZuuccxFvLBT8H6uLiIhItaCkRURESqVRFjkRKGkRERGRQFDSIiIiIoGgpEVEREQCIeY74oqISPlUxNxbmk9LqiONtIiIVLB4z70V63xaEydOpHnz5nTu3LnQ+tzcXIYMGUL79u0ZMmQIX331VcT9ly5dSlJSEu3atePuu+8uU4xr167l+uuvL9M+BQrmspGyc85x/fXX065dO1JTU1m/fn3EcldccQVdunQhNTWViy++uNCF1suXL6dr16506tSJc889t7JCj4lGWkREKkE8596KdT6t9PR0rr32WsaNK1z+7rvvZvDgwcyYMYO7776bu+++m7lz5xYqc/ToUa655hreeOMNEhMT6dWrFyNHjqRjx44xtd2zZ0969ox4q40KVXBr+2jLse4XVEuWLGHbtm1s27aNjIwMpk6dSkZGRrFyDzzwQGiSxBtuuIF58+YxY8YM8vLyuPrqq1m6dClnnnkmX3zxRWUfQok00iIicpJKS0uLeNv1l19+mfHjxwMwfvx4XnrppWJl1qxZQ7t27Wjbti2nnHIKY8eO5eWXXy5WLj09nSlTpjBgwAB+9KMf8fe/e9PQLV++nPPPPx+A66+/njvuuAOA119/nbS0NI4dO8a6des499xz6dGjB8OGDSMnJ6dY/eE+/fRThg8fTo8ePUJ3ei2I4YYbbmDQoEFMnz692PLGjRvp27cvqampXHjhhaGRpYEDBzJz5kzOPfdc/u///i9qu48//jg//elPueCCCzjrrLOYN28e999/P926daNv377k5uaWGN8rr7xCnz596NatGz/+8Y/Zu9ebuu/2229n4sSJDBw4kLZt2/L73/++xOOPxcsvv8y4ceMwM/r27UteXl7Efi1IWJxzHDp0KDTH0DPPPMPo0aM588wzAaLeuXjp0qV0796dLl26MHjw4NDxjB8/nqFDh9KmTRteeOEFfv3rX5OSksLw4cP5/vvvj/v4lLSIiFQze/fuDc0v1LJly4jfpnft2sUZZ5wRWk5MTGTXrl0R69uxYwcrVqzg1VdfZcqUKYUmCgRvZGfx4sW88847XH/99SxcuJCjR49y3XXX8fzzz7Nu3TomTpzIb37zmxLjvuqqq/jDH/7AunXruPfee7n66qtD2z755BPefPNN7rvvvmLL48aNY+7cuWzatImUlBRmz54d2i8vL48VK1Zw4403Mn/+/NAUB0Vt2bKFZ555hjVr1vCb3/yGU089lQ0bNtCvXz+eeOKJEuPr378/q1evZsOGDYwdO5b//d//DdWblZXF66+/zpo1a5g9e3bED/YxY8bQtWvXYo+CdsOV5XWbMGECLVq0ICsri+uuuy7Ub1999RUDBw6kR48eEdvYt28fkyZN4q9//SsfffQRzz33XGjbp59+yquvvsrLL7/M5ZdfzqBBg9i8eTN169bl1VdfjRhHWQR/LExEROIu0hQv0Wb8/dnPfkaNGjVo3749bdu2DY0wFDj11FN55JFHSEtL44EHHuDss89my5YtbNmyhSFDhgDe6ahIEzUWOHjwIB988AGXXHJJaN13330Xen7JJZcUmgG6YPnrr78mLy8vdG3G+PHjC9URPrPylClTorY/aNAgGjRoQIMGDWjUqBEXXHABACkpKWzatKnE+Hbu3MmYMWPIycnhyJEjnHXWWaEyP/nJT6hTpw516tShefPm7N27l8TExEJtF53nqSRled3Ck8fFixczYcIE8vPzWbduHW+99RaHDh2iX79+9O3blx/96Eeh/VavXk1aWlroOMJH88477zxq165NSkoKR48eDc13lZKSEnEeqLJS0iIiUs388Ic/JCcnh5YtW5KTkxPxFEBiYiKff/55aHnnzp1RJxgs+qEY6UNy8+bN/OAHP2D37t2A9+HaqVMnVq1aFVPMx44do3HjxlFnQq5Xr16Jy9HEWq5OnTqh5zVq1Agt16hRg/z8/BLju+6667jhhhsYOXIky5cv5/bbb49Yb82aNcnPzy+2/5gxY8jOzi62/oYbbih2vVJZXreCNseMGcM999zDhAkTSExMpFmzZtSrV4969eqRlpbGRx99VChpcc5FTYTC+6V27dqhcgX9dLyUtIiIVILDWVkxX0AbS10JyeWfOXrkyJEsWrSIGTNmsGjRIkaNGlWsTK9evdi2bRvbt2/n9NNP59lnn+WZZ56JWN9zzz3H+PHj2b59O//85z9JSkpi9erVoe2fffYZ9913Hxs2bGDEiBH89Kc/pVu3buzbt49Vq1bRr18/vv/+ez755BM6deoUsY2GDRty1lln8dxzz3HJJZfgnGPTpk106dKlxGNt1KgRTZo04d1332XAgAE8+eSTFfKLmJLi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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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7pyKi4vj6aefLjJp6dChA9OmTeOyyy7j5MmT1KxZk0cffbTEpCU5OZn09HR69OgBwM0330zXrl3Ztm1bobIDBw5kzpw5ZWqdKCq+Xr160bVrVzp27EibNm1Cp04qyvTp00lLS+Ouu+6ia9eu3HTTTQCsXr2amTNnMmfOHAAuvvhiMjMzOXToEPHx8Tz++ONcfvnlPPLII/zhD39g165dJCUlhbZJuHHjxjFq1CiSkpLo0qVLaNuec845zJs3j+HDh3P06FEApk2bxkUXXcSf//xnBgwYQNOmTUPlK5IV18QWaykpKe5U3fM97LHloV8neX9jdfuhiEhBGRkZtG/fvrLDiJm4uLjQHSIiRTl06BBxcXE45xg/fjzt2rVj4sSJUc8f6f/GzNY451IilT+j7x7KS1Ri1awqIiIi35k9ezZdunShY8eOHDhwIOprmcrqjD09JCIiZadWFonGxIkTS9WyUl5ndEuLiIiInDmUtIiIiEggKGkRERGRQNA1LSIisbZoMuzaGNs6m3eGK+6PbZ0iAaOWFhGRWNu1MbZJSxT1HTlyhB49evD973+/UAd+4ZxzTJgwgbZt25KUlMTatWtLFcrdd9/NkiVLSjVPnri4uDLNJ94TeHv27Em7du0YNmwYx44dK1Tm888/p1u3bqG7efKezwNw4403kpCQQKdOnRg9ejTHjx8vcZl9+/blVD2mJFpqaRERqQjNO8Oof8amrrlXllikdu3avP3228TFxXH8+HH69OnDFVdcka8PHoBFixaxZcsWtmzZwsqVKxk3bhwrV66MOpR777231OHHwokTJ/I90r/gcCTOOZxzVKsW/N/nkyZNYuLEiaSlpTF27Fgef/xxxo0bl69MixYt+OCDD6hduzaHDh2iU6dODBo0iJYtW3LjjTfy9NNPA/DjH/+YOXPmFJo/CIK/J0VEBDMLtWQcP36c48ePR+xH5rXXXmPEiBGYGb169WL//v1kZ2cXKhcXF8ftt99OcnIy/fr1C/Xgm56ezosvvsiBAwdISEggKysL8J7GO3v2bAD++Mc/0r17d5KSkops8Qn39NNP06NHD7p06cKYMWM4ceJEKIa7776bnj17snz58kLDDz74IJ06daJTp048/PDDAGzbto327dtz6623kpycnK+fpYL69u3LxIkTSU1NpX379nz44YcMHTqUdu3acdddd5UY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gzAzNmzYwA033FDuXqkrklpaRETOEKmpqTRp0qTQ+Ndee42RI0cCMHLkyIhfcKtWraJt27a0adOGWrVqkZaWxmuvvVaoXHp6OmPHjuXiiy/moosu4h//+Afg9Zdz1VVXATBhwgTuvfdeAN544w1SU1M5efIka9as4ZJLLqFbt25cfvnlZGdnF7s+//73vxkwYADdunXj4osvDn2Zpqen88tf/pJLL72USZMmFRpev349vXr1IikpiSFDhoRalvr27csdd9zBJZdcwv/+7/8Wudx58+ZxzTXXcPXVV3PBBRcwY8YMHnzwQbp27UqvXr3IyckpNr6///3v9OzZk65du/KjH/2I3bt3A3DPPfcwevRo+vbtS5s2bXjkkUeKXf9oNGvWjO7du1OzZs0iyzjnePvtt7nuuuuA/MdAXFxcqL+hb775psiOGOfOnctFF13EJZdcwvvvvx8av2fPHq699lq6d+9O9+7dQ9P27NlD//79SU5OZsyYMbRq1Yq9e/eWe32VtIiInOF2794d6l+oRYsWfPnll4XK7Nixg/PPPz80HB8fz44dOyLWt23bNt59913++c9/Mnbs2HwdBYLXsjN//nz+9a9/MWHCBObOncuJEyf47//+b1588UXWrFnD6NGjufPOO4uN+5ZbbuH//u//WLNmDQ888AC33npraNonn3zCkiVL+NOf/lRoeMSIEUyfPp0NGzbQuXNnpk6dGppv//79vPvuu9x+++3MnDkz4uPsATZt2sSzzz7LqlWruPPOO6lXrx7r1q2jd+/ePPnkk8XG16dPH1asWMG6detIS0vjD3/4Q6jezMxM3njjDVatWsXUqVM5fvx4oWUPGzaMLl26FHrlLbe09u3bR+PGjUMtSwX37SuvvEJiYiJXXnklf/3rXwvNn52dzZQpU3j//fd588032bx5c2jaz3/+cyZOnMiHH37ISy+9xM033wzA1KlT+eEPf8jatWsZMmQI//nPf8oUe0HBbxsTEZFyi9SlS1G/um+44QaqVatGu3btaNOmTaHTCfXq1WP27Nmkpqby0EMPceGFF7Jp0yY2bdpE//79Ae90VKSOGvMcOnSIDz74gOuvvz40Lq/fG4Drr78+Xw/QecMHDhxg//79XHLJJYDXqhBeR3jPymPHji1y+ZdeeikNGjSgQYMGNGrUiKuvvhqAzp07s2HDhmLj2759O8OGDSM7O5tjx45xwQUXhMpceeWV1K5dm9q1a9OsWTN2795NfHx8vmXHuuPBkvbtkCFDGDJkCEuXLuW3v/0tS5YsyVd25cqV9O3bl3POOQfwtuEnn3wCwJIlS/IlMQcPHuTrr79m2bJlvPLKKwAMGDCAs846KybroqTlDFPSXQtpfk/Rnz8T3TnystBdDiKnl3PPPTfUy292dnbEzgvj4+P54osvQsPbt28vsoPBgslMpORm48aNnH322ezcuRPwvjg7duzI8uXLo4r55MmTNG7cuMiekOvXr1/scFGiLVe7du3Q+2rVqoWGq1WrRm5ubrHx/fd//ze//OUvGTRoEO+88w733HNPxHqrV69Obm5uofmHDRtGVlbhzm1/+ctfFrpeKRpNmzZl//79oet4itq3qamp/Pvf/2bv3r00bdo037SiEtiTJ0+yfPly6tatm298RfVrqKTlDJN310KdxNj2MhutWN4xIRJkRzIzo76ANpq6yvM/PWjQIJ544gkmT57ME088weDBgwuV6d69O1u2bGHr1q2cd955PP/88zz77LMR61uwYAEjR45k69atfPbZZyQkJLBixYrQ9M8//5w//elPrFu3joEDB3LNNdfQtWtX9uzZw/Lly+nduzfHjx/nk08+oWPHjhGX0bBhQy644AIWLFjA9ddfj3OODRs28P3vf7/YdW3UqBFnnXUW7733HhdffDFPPfVUqNUlloqL78CBA5x33nkAPPHEE6WuO9YtLWbGpZdeyosvvkhaWlq+Y+DTTz/lwgsvxMxYu3Ytx44d4+yzz843f8+ePfn5z3/Ovn37aNiwIQsWLAjth8suu4wZM2bwP//zPwCsX7+eLl260KdPH1544QUmTZrE4sWLi7xjrbSUtJyBirtr4Z4K7uU5Vh/SIkFWu31sfzTUSUyMqs7hw4fzzjvvsHfvXuLj45k6dSo33XQTkydP5oYbbuDxxx/ne9/7HgsWLABg586d3HzzzSxcuJAaNWowY8YMLr/8ck6cOMHo0aOLTCgSEhK45JJL2L17NzNnzqROnTqhac45brrpJh544AFatmzJ448/Tnp6Oh9++CEvvvgiEyZM4MCBA+Tm5vKLX/yiyGUAPPPMM4wbN45p06Zx/Phx0tLSSkxawEsUxo4dy7fffkubNm2YOzfy513e9SzFnSYqTlHx3XPPPVx//fWcd9559OrVi61bt5ap/mjs2rWLlJQUDh48SLVq1Xj44YfZvHkzDRs2ZODAgcyZM4eWLVsyffp00tLSuOuuu+jatSs33XQTAC+99BJPPvkkNWvWpG7dusyfP79Qq0qLFi2455576N27Ny1atCA5OZkTJ04A8MgjjzB+/HiSkpLIzc0lNTWVmTNnMmXKFIYPH878+fO55JJLaNGiBQ0aNCj3+lpFNeFEkpKS4lavXn1KljXsMa8Jcv6Y3qWadroaFWWykZc0FJW0RFtPWZW0fJEzVUZGBu3bt6/sMCpceno6V111VehOFJFIjh49SvXq1alRowbLly9n3LhxEU+lRfq/MbM1zrmI98+rpUVERERi6j//+Q833HADJ0+epFatWsyePTsm9SppERGRqM2bN6+yQ5AAaNeuHevWrYt5vXpOi4hIjJzK0+0iQVeW/xclLSIiMVCnTh327dunxEUkCs459u3bl+8i7mjo9JCISAzEx8ezfft29uzZU9mhiARCnTp1Cj1YryRKWkREYqBmzZr5nnwqIrGn00MiIiISCEpaREREJBBKTFrM7Hwz+5eZZZjZx2b2c398EzN708y2+H9j0xuSiIiISATRtLTkArc759oDvYDxZtYBmAy85ZxrB7zlD4uIiIhUiBIvxHXOZQPZ/vuvzSwDOA8YDPT1iz0BvANMqpAoo7Dizz+jwf6M0PCvjp2gXq3qMLdRobIjDzTliUZF9zUxfdV0MnNi0/FfYpNEJvWotM0iIiJyxijVNS1m1hroCqwEzvUTmrzEpnBf5948t5jZajNbXZG3AjbYn8H5x/4dGq5Xqzr1a0XIyXZtpFXuvwuPD5OZk0lWTuFuwUsrKycrZsmPiIhIVRf1Lc9mFge8BPzCOXewYC+QRXHOzQJmgddhYlmCjNYXtS6k4x3Lii8090rIPlBiXQlNEsrdqWBe54QiIiJSflG1tJhZTbyE5Rnn3Mv+6N1m1sKf3gL4smJCFBEREYnu7iEDHgcynHMPhk36GzDSfz8SeC324YmIiIh4ojk99APgp8BGM1vvj7sDuB94wcxuAv4DXF8hEYqIiIgQ3d1Dy4CiLmDpF9twRERERCLTE3FFREQkEJS0iIiISCAoaREREZFAUNIiIiIigaCkRURERAJBSYuIiIgEgpIWERERCQQlLSIiIhIIUXeYKMVYNBl2bSw83naTxTFGzUv5blyt+tCkTakXkZWTRUKThHIEmb+uWHTmmNgkkUk9JsUgIhERkZIpaYmFXRu9V/PO+UYnUit/uWPflHkRCU0SSGySWOb588SiDvASHxERkVNJSUusNO8Mo/6Zb1ShNoi5V4IDBsw9VVEVEquWkVi01IiIiJSGrmkRERGRQFDSIiIiIoGgpEVEREQCQUmLiIiIBIKSFhEREQkEJS0iIiISCEpaREREJBCUtIiIiEggKGkRERGRQFDSIiIiIoGgpEVEREQCQX0PVYBd993H0YzMCBN2en/fHlFhyz6SmUmdxNh0iigiInI6UUtLBTiakcmRzAhJyylQJzGR2u2VtIiIyJlHLS0VpE5iIq2eejL/yLlXen9HPVl4BhERESmWWlpEREQkEJS0iIiISCAoaREREZFAUNIiIiIigaCkRURERAJBSYuIiIgEgpIWERERCQQlLSIiIhIISlpEREQkEJS0iIiISCAoaREREZFAUNIiIiIigVAlO0xsffwzfpX9Sz6+r3poXP1aNWh9dn1vwHZ7fxdNhivur4QIpSx23XcfRzMqp3ftPLXbJ9L8jjsqNQYRkTNV1Utamndmz75vqHcsNzTq22MnCpc79g3s2ngKA5PyOpqRyZHMTOokJlbK8o9kVm7CJCJypqt6ScsV99P6ivyjhj22HID5o3p7I14f5SUs7hTHJuVWJzGRVk89WSnL/vynIypluSIiVYWuaREREZFAUNIiIiIigaCkRURERAJBSYuIiIgEgpIWERERCQQlLSIiIhIISlpEREQkEJS0iIiISCAoaREREZFAUNIiIiIigaCkRURERAJBSYuIiIgEgpIWERERCQQlLSIiIhIISlpEREQkEJS0iIiISCAoaREREZFAUNIiIiIigaCkRURERAJBSYuIiIgEgpIWERERCQQlLSIiIhIISlpEREQkEEpMWszsr2b2pZltCht3j5ntMLP1/mtgxYYpIiIiVV00LS3zgAERxj/knOvivxbGNiwRERGR/GqUVMA5t9TMWp+CWKqGXRth7pUll2veGa64v+LjqQBHMjP5/KcjKmW5dRITT/lyRUTk1CgxaSnGbWY2AlgN3O6c+ypSITO7BbgF4Hvf+145FncGaN45unK7NlZsHBWodvvKSxrqJCZW6vJFRKRilTVp+Qvw/wDn//0TMDpSQefcLGAWQEpKiivj8s4M0bac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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig_led_pos, ax_led_pos = make_fig(\"Reconstructed LED position error with {} cameras\".format(camera_count), \"Distance from true to reco. position [cm]\")\n",
+ "fig_mpmt_pos, ax_mpmt_pos = make_fig(\"Reconstructed mPMT position error with {} cameras\".format(camera_count), \"Distance from true to reco. position [cm]\")\n",
+ "fig_mpmt_ang, ax_mpmt_ang = make_fig(\"Reconstructed mPMT orientation error with {} cameras\".format(camera_count), \"Angle between true and reco. orientation [deg]\")\n",
+ "position_errors_4 = {}\n",
+ "centre_errors_4 = {}\n",
+ "orientation_errors_4 = {}\n",
+ "for pixel_error in pixel_errors:\n",
+ " print(\"=== Gaussian errors on feature image locations:\", pixel_error, \"===\")\n",
+ " smeared_feature_locations = simulator.get_image_feature_locations(area_restrict=image_area, min_feature_count=2, pixel_error=pixel_error)\n",
+ " led_positions_4 = {k: v for k, v in led_positions.items() if np.any([k in i.keys() for i in smeared_feature_locations.values()])}\n",
+ " fitter = setup_led_simulation(led_positions_4, smeared_feature_locations, focal_length, principle_point, radial_distortion) \n",
+ " reco_led_positions, position_errors_4[pixel_error] = run_led_fit(fitter, led_positions_4)\n",
+ " centre_errors_4[pixel_error] = get_mpmt_centre_errors(reco_led_positions, mpmt_locations, led_count)\n",
+ " orientation_errors_4[pixel_error] = get_mpmt_orientation_errors(reco_led_positions, mpmt_orientations, led_count)\n",
+ " ax_led_pos.hist(position_errors_4[pixel_error], bins=20, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} cm\".format(pixel_error, position_errors_4[pixel_error].mean()))\n",
+ " ax_mpmt_pos.hist(centre_errors_4[pixel_error], bins=15, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} cm\".format(pixel_error, centre_errors_4[pixel_error].mean()))\n",
+ " ax_mpmt_ang.hist(orientation_errors_4[pixel_error], bins=15, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} deg\".format(pixel_error, orientation_errors_4[pixel_error].mean()))\n",
+ "ax_led_pos.legend(loc='upper right')\n",
+ "ax_mpmt_pos.legend(loc='upper right')\n",
+ "ax_mpmt_ang.legend(loc='upper right')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "reco_errors, reco_transformed, scale, R, translation, _ = fit.kabsch_errors(led_positions, reco_led_positions)\n",
+ "\n",
+ "reco_cam_orientations, reco_cam_positions = fit.camera_world_poses(fitter.camera_rotations, fitter.camera_translations)\n",
+ "cam_orientations_transformed = np.matmul(R, reco_cam_orientations)\n",
+ "cam_positions_translated = reco_cam_positions - translation\n",
+ "cam_positions_transformed = scale*R.dot(cam_positions_translated.transpose()).transpose()\n",
+ "\n",
+ "plot_reconstruction(reco_transformed, cam_positions_transformed)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 8 camera configuration A"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "camera_radial_position = 163.0\n",
+ "camera_halfz_position = 168.0\n",
+ "camera_positions = np.array([\n",
+ " [ camera_radial_position/np.sqrt(2), camera_halfz_position, camera_radial_position/np.sqrt(2)],\n",
+ " [ camera_radial_position/np.sqrt(2), camera_halfz_position, -camera_radial_position/np.sqrt(2)],\n",
+ " [-camera_radial_position/np.sqrt(2), camera_halfz_position, camera_radial_position/np.sqrt(2)],\n",
+ " [-camera_radial_position/np.sqrt(2), camera_halfz_position, -camera_radial_position/np.sqrt(2)],\n",
+ " [ camera_radial_position/np.sqrt(2), -camera_halfz_position, camera_radial_position/np.sqrt(2)],\n",
+ " [ camera_radial_position/np.sqrt(2), -camera_halfz_position, -camera_radial_position/np.sqrt(2)],\n",
+ " [-camera_radial_position/np.sqrt(2), -camera_halfz_position, camera_radial_position/np.sqrt(2)],\n",
+ " [-camera_radial_position/np.sqrt(2), -camera_halfz_position, -camera_radial_position/np.sqrt(2)]])\n",
+ "camera_directions = [[-1, -1.9, -1],\n",
+ " [-1, -1.9, 1],\n",
+ " [ 1, -1.9, -1],\n",
+ " [ 1, -1.9, 1],\n",
+ " [-1, 1.9, -1],\n",
+ " [-1, 1.9, 1],\n",
+ " [ 1, 1.9, -1],\n",
+ " [ 1, 1.9, 1]]\n",
+ "camera_directions = camera_directions / linalg.norm(camera_directions, axis=1, keepdims=True)\n",
+ "camera_rolls = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])#[np.pi/2, np.pi/2, np.pi/2, np.pi/2])\n",
+ "camera_rotations, camera_translations = fit.camera_poses(camera_positions, camera_directions, camera_rolls)\n",
+ "camera_count = camera_positions.shape[0]\n",
+ "simulator = fit.PhotogrammetrySimulator(led_positions, focal_length, principle_point, camera_rotations, camera_translations, radial_distortion, tangential_distortion)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 52,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Total number of features: 1464\n",
+ "Number of features in more than one image: 1464\n",
+ "Feature in image counts: Counter({4: 648, 8: 560, 7: 144, 6: 64, 5: 48})\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1gAAAKACAYAAACBhdleAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAABEiUlEQVR4nO3dvY4sR3oo2uiDsY8EUMeRc8a5jtxugFNPkOWMwzfhExTSkTu2+BB0xtn1AlUaoOnKOdYxZN1LgBAgO6+xp8jN3lXd+R9fRKwFNDjTbFZFRsZvRsSXT8MwJAAAAJb7H7kTAAAAUAsTLAAAgJWYYAEAAKzEBAsAAGAlJlgAAAAr+cOUP/6nf/qn4Y9//ONGSQEAACjDTz/99P8Nw/C/3v5+0gTrj3/8Y3p9fV0vVQAAAAV6enr6v/d+b4sgAADASkywAAAAVmKCBQAAsBITLAA+dL1e0/F4TNfrNXdSQpAfADwyKcgFAG3q+z6dz+eUUkqfPn3KnJr85AcAj1jBAsKrYbWg9Gs4nU6p67p0Op1G/X1p1zs1vVPzI5rS7s89NVwDUKlhGEb/PD8/DwB767puSCkNXdflTspsOa7hcrkMXdcNl8tlt++8Ke2e5UxvjvtU2v25p4ZrAMqWUnod7syZTLCA8HJOFNYSfRA9Jn1TruHR3375+73y5O333PveNa5t7t+1NvleSw3XAJTNBAugMVMGoGMG+ff+5r3Jy+1//9u//duv//zmm29+/Yy9JhZvv+fbb78dUkrDv/zLvzxM63uTr7HpHvt3JgoAZXo0wRLkAqBSh8NhdACG21mi984U3fubt8Eevvz/KaV0Pp/T6+tr+vnnn3/95zfffPO7z9j6HNOja/vP//zP9B//8R9305rSb8Er3l7jmLx673vfmnKfAIjv6fPka5yXl5fh9fV1w+QAUJLr9Zr6vk+n0ykdDoff/f+UPk9Ovvvuu/Tjjz/++s/b3+ZO85fpeZvWL9P49hoBIKWUnp6efhqG4eWr35tgATBHSxOPlq4VgHEeTbCEaQdo3Hvhrm//7ocffvjqb25b5/q+3zO5Wby91vfy5UtCiQO0xxksgMa8XY1576W5t39372zS2DNGNXh7re/ly5fe5q2VMID6mWABFGruYH1K0Ibb796eV0qpreAMb6/1vXz50qOJWUr3J2T3mJQBlMUZLIDA3htcH4/HdD6fU9d1kyY6Buz5zMn7j+6z+wmQhzNYAAV675zT6XRKXddN3qJ3OBzS6XRKfd87G7ST21mslD6vXE2ZCH10n1s6CwdQAhMsgMDeG1zftq19OVgfG3zBoHxfH+X3l8Ew3gbGuHefvzR3og3ANpzBAnhH7u1XU885jQ2+0FKAigg+yu97L2hOadw5rZxn4XLXD4CITLAA3jEnKMFa5gxexwZfaClARQQf5fe9CdiUyW+uiU7O+gEQ1jAMo3+en58HgJZcLpeh67rhcrns/l1d1w0ppaHrumxpIo737vvbsrJXGVEWgZallF6HO3MmK1gA79hzpWds+HSrBm16776vEQ5+DiuhAF8T5AIo3tugAKX67rvv0jfffJO+++67lNLj4AaCGrRpbMCT6/Wafvnll/Ttt98WXUZqqddAe0ywgOKVGBHv3uDxxx9/TD///HP68ccf3/1vP4oqR53G3ve+79Pf/va39I//+I+//m2Jk5US6zVASiZYQAX2WtFZc5B6Gzz++c9//vXzrEyxhnvl6Pvvv0/n8zl9//33iz9/r8ma+gCU6unz+axxXl5ehtfX1w2TAxDX8XhM5/M5dV23+NzJ9XpNf/7zn9PPP/+8yufBe/70pz+lv/3tb+nbb79N//7v/77os9asBwAle3p6+mkYhpe3v7eCBfB3Hz2Zf/tE/aO/v16v6U9/+lP605/+9NXfHA6H9Ne//tUTenbxl7/8JXVdl/7yl7/87vfvldEv/+bLcv7RylKJ2xEB1mQFC+Dvpj6Z/+jvb/8+peRpPyGNKaNr1wuAWljBAvjAmBWqL3/30ZP80+mUvv322+KjuVGvMWX0y3L+UZ14+/cALbKCBfDAvSfxns7TMnUC4DePVrC8aBjggXsv+n308l9ogToB8DErWADp8zanvu/T6XTyfilYSH0CWmAFC+Ad33//ffrb3/6Wfvnll8VhrKF1t/e8vb6+pr/+9a8mWUBTBLkAAFZ1Op3SN998k37++efU933u5ADsygQLID1+TxAwnfe8AS0zwQKKstVLTA+HQ/r06VMzW5m8DHZfLeb3FnWqxXwEymOCBRTldraj7/umB1tLr/3LfGR7S/O75bKe0m/X//333yu3QHiCXABF+TIk9G3QmlJq7v07S69daO19Lc3vlst6Sr9d/7fffmvbIRCeCRZQlNu2o5TaniQsvfYv85HtLc3vlst6Sr+//la28QLlskUQmGzJdqU1tzqtdcajxO1XrZ0Za12p93utuhWhrpfYTgB5WMECJluyXSniVqeIaYIaRKtbtbVdQExWsIDJTqfT7HMQp9Mpffvtt+mXX35JP/zwQ4gnwt9991365ptv0nfffZc1HVCT6/Wafvnll/Ttt99m3dp4W3n64YcfFqVnSbsHtOVpGIbRf/zy8jK8vr5umBygBcfjMZ3P519fRNp1XdYnwrf05E4H1CRKvYrW3gD1eHp6+mkYhpe3v7eCBezu9iT4X//1X0M8EfZkepqWz6K0fO1TRalX0doboH5WsKBy1+s19X3fbPSt1q9/C1FWJnJo+dq30Hr9bP36oXRWsKBRrb9QtoTrL21VJMrKRA4lXXsJ5aqE+rml1q8faiWKIFTO+3PiX39p0clafodWSddeQrkqoX5uqfXrh1rZIgiE1cr2mVauk321VK5aulYgDlsEgeKsvX0m6papUl8iS2yRy9XaddFWOyASWwSBsG7bZr777rt0PB4XP50uYcsUtGCtunhbubq9w85WOyACEywgrNsT+FvktpSWDcacd4AY1qqLHpoAEZlgAeGtNRgrKUAB1GytuuihCRCRM1hQuajnjqaIfJYEyKf0tqGG9hn4mgkW2elgtuXwN0BM2udtGV+QiwkW2elgthXpxag6OyC3SO1QpPa5RsYX5OIMFtnZQ7+tSOeOlhxI954b4GZJexApMEak9rlGxhfkYoJFdjqYdizp7CINioC8lrQHBt3tML4gF1sEIYBIW1a2tORAuq00wM2S9qD0wBhjtdKvQEQmWBCAfeIfDwZaGRTVoNSBXanpbtFH7YF7qV+BnEywIACrM/MGAwZRMZU6sCs13bWbU8/dS/0K5OQMFgRgn/i8cxHOZcVU6hmXUtNduzn13L3Ur0BOT8MwjP7jl5eX4fX1dcPkAIxXUmTBktJKG0opk6WkE2jP09PTT8MwvLz9vS2CkIGtbeso6VyWLUtEU0qZLKmeR6bfgf2YYEEGuQc2Otr9OQ9BNMrkvnK3u7n7HWiJM1iQQe7zAffONNiGsy3nIYhGmdzOvfY095nR3P0OtMQEC1Y0dpKSe2Bzr6PN3fkD1OJee5p7gjOl3/HADZYxwYIVlTJJudfR5u78AWpxrz3N/WBtilL6MojKBAtWVPIkpaTOHyCy0tvTkvsyiECQC1iRaFfvy33IGyAlbdFH9GWwjAkW8KG1BiOiWAERrNEWmaQBj9giCHxorf34tp0AEazRFjmnBDxiBYsmeNK4zNT35TzK7/e2nbhHwFo+ak/utUVT2yDvEVtGm0/NnoZhGP3HLy8vw+vr64bJgW0cj8d0Pp9T13WeNO5gTn67R8BatEHxyW9q8PT09NMwDC9vf2+LIE2wNW1fc/LbPQLWog2KT35TMytYUBgvgARok/YfYnm0guUMFhRmafQr+94B8lja/orECmUwwYLCLD1YrYNma6VO4ktNN+VY2v4KrAFlcAYLCnOLfjWXfe9srdTw1aWmm3IsbX+Xtv/APqxgQWPeC5XOtlpZISn1KXup6Z6qlXIYkfYX2iDIBcBOhCUmAuUQYB3CtANkZnsmESiHANuyRRCY7b2tRrYhfc32ICJQDu971GZpy4CprGABs70XFEDAAKAkj9osbRkwlQkWMNt7W41sQwJK8qjN0pYBUwlyAQAAMNGjIBfOYAEAAKzEBAv4ikPdANNoN4EbEyyo1JLO/naou+/7u59nIAG06Nb2/fDDD1+1gffazamfq02FOghyAZVaEvnq3qHuLz8vpSSqFtCcWzv4+vqafv7555TSb23gkmAYIhVCXUywoFJLOvvbe3I++jxRtYCW3Nq87777Lv3444+/awPvtZtTP1ebCnUQRRAAAGAiUQShMvbsk9NW5W/p50ZNFyylDEI5TLCgUEsOVBNTSQOorcrf0s+Nmq49lVSOGK+kMgitcwYLCmXPfn1KOui+Vflb+rlR07WnksoR45VUBqF5wzCM/nl+fh6gNpfLZei6brhcLrmTQkG2KDfKImvYqhwpn8yh3FCzlNLrcGfOJMgFzTsej+l8Pqeu6xY/7b1er6nv+3Q6ndLhcFgphUS0ZrmBEijzbVi7H1NuqJkgF1Rv7rmD0+mUuq5bZduFPfJlWXJWZc1yAyWYW+adCSvL2v3YnHKjzFA6K1hUI8JTMitYZYlQZqB26llZIvRjygyleLSCJcgF1YhwAHjJiybZX4QyA7VTz8oSoR9TZiidLYJU49YpWDn6zBaLjykznykr25G36tkYysnvKTOUzgQLKuU8WDuWDs62KiulDBq3TOeSvC0l/1hOew11sUWwERH2VLMvWyzasfS9R1uVlVLex7RlOpfkbSn5x3La6zYZm1XsXuz2Rz/eg1WuruuGlNLQdV3upDCD94jUobX3E0VN11tR09laeWEa97F8xmblS96D1TZPScomolId3EciUA7r4D6Wz9isfKIINi5CVCDms32kDu4jESiHdXAfy2dsVi8rWEA1PA2EOqjLQAmsYAHVExQA6qAuAyUTpp0mCX/8m7d5UXLenE6n1HWdLTNQuFLr8r32s+Q2dW3ygmbci3zx6EcUQWpRYuSerSJGvc2LEvMGIIJ77ecWbWqpEQT1L9QmPYgiaIsgTSrxcPBWW2be5kWJeQMQwb32c4s2tdQtlPoXWiHIBQR074C3Q98ApKSPgCgeBblwBgt2NHb/+e3pZN/3v/7uFs5VxwnQtnv9wb1+4x7noGB7tgjCjsZu67CNAoApxvYbpW4vhJKYYMGOxnaAXj4IwBRj+w0P8GB7zmABAABM5AwWMIr9+YzVSllp5TpZh/ICmGCxCR1MHFPvxdiD0myjpLrTSlkp6TpLKj+1mlpe3LM43AvW4gwWm3CINo6p98L+/LxKqjutlJWSrrOk8lOrqeXFPYvDvWAtJlhsoqQBSe2m3gsBNvIqqe60UlZKus6Syk+tppYX9ywO94K1CHIBFMcLNaE96j0QjSAX8Hf2WJevpDMxwDrU+/Lpf2mFLYI0xx7r8tnGAe1R78un/6UVJlg0RyddvpLOxADrUO/Lp/+lFc5gAQAATOQMFgAAwMZMsAAAAFZiggUAALCS6iZYQoACAEB5ahnHVxdFUAhQAAAoTy3j+OpWsE6nU+q6TgjQBuz1lKOWpyn31HxtABHU3s7ucX215yG/qWUcL0w7xToej+l8Pqeu6zZ9yrHX9+RQ87UBRFB7O7vH9dWeh5RLmHaqs9dTjj2fpkx5SrfGE71anhSRT+1Plmu/Pra3Rju7d98wxR79iL6K4gzDMPrn+fl5AJa5XC5D13XD5XL56t91XTeklIau6z78nCl/S1neKyPR1F4OS7q+ksoN06zVNygjsK6U0utwZ85UXZALiO69A5y3p3NjntJN+VvKUtIh39rLYUnXV1K5YZq1+gZlBPbhDBbs7Hq9pr7v0+l0SofDIXdyCEgZYQ7lho8oI7CuR2ewTLCAYhksQP3UcyCqRxMsWwSBYtnuAvVTz4HSmGABxSrpfAwwj3oOlMYWQQAAgIm8B4sq1fiOmhqvCYB91NaH1HY9tMEWQYpW4978Gq8JgH3U1ofUdj20wQSLotW4N7/GawJgH7X1IbVdD21wBouqCe8LAHHppymZMO00ydYCAIhLP02NBLmgaqfTKXVdt/nWgsiHcCOnDaBlkdvnvdK2Vz8Ne7JFEFZwPB7T+XxOXdeFewIXOW3Ur4TtPyWkkTpFbp8jpw2iEKad6kR68hf5CVzktLUuUhneKi237T9936/6uWvaIo2R7m1K8dLDZ5Hb50hpU34pzjAMo3+en58HiKLruiGlNHRdlzspMMsWZfhyuQxd1w2XyyV7WpakZ09bpHFJfkZLD+Sm/BJVSul1uDNnMsGiWCUM3MgrehmJNJCOnlelWZKfkSbee4icNmJQRojq0QTLGSwIyrmQ5Vo8Q6DclK+1e9hiPV1ba2UGohCmHQojdO1yLb6g8nA4KC+Fa+0etlhP16a/gFgEuaiEA6D1iXTAeE9rluXbQNUTXYhr7XraYn/Yan9RsxbLcU1sEayELRZEM3fLirIMLDGnDbHFjmj0hWWwRbBytlgQzdwtK8oySwa7BsrMaUNssSMafWHZrGABmzDQrd9W93jJk9stnvoqy/Vzj4E5vGiYbOwjfl+t+VPq+acl92Ptexm9bGz1EuEl50m2OIsS/WXJW5STuZ8Zvcw+Ump79ZFS78de5A+buRe7/dGP92AxhxcEvk/+xLLkfqx9L6OXjVbeTRP9OrcoJ3M/M3qZbY378T75w1LJi4bJJfrgJDf5s9yaebjks9a+l8oGY2xRTuZ+pjoQi/x7n/xhqUcTLGewoHDODoi2BLVqvW5r3yE2UQShUqJfibYEtWq9bmvfoUyCXEDh9n7BZMRDwbUeUIfWRazbe7aBXiAMZbJFEJik9S07QNu0gcCNLYLAKlrfsgO0TRsIfMQWQQgk4va7tyJu2QHYSwltYAl9CdTMBAseyNFBRX+hKQDx7d2XmNDB79kiCA/kiN5k6wkAS+3dl4h2CL9nggUP5Jjs3LaeAMBce/clHg7C71WxRdDSNDdrloUS9tlDZKW0zaWkE6Jas79UH7kpuSxUMcFyboWbWstCyY0M7SqlPpaSTnirxr5BfeSm5LJQxRZBS9Pc1FoW7G+v2/V6TX3fp9PpVNWKaSn1sZR0TlVrueI3NfYNtdZHpiu6LAzDMPrn+fl5ALZ1uVyGruuGy+Xy7u8YL3r+dV03pJSGrutyJ4WKRC9X0etlCfQXkFdK6XW4M2cywaIILXUY0QdFJYqepy2Vb/YTvVxFr5elaiVfo5dv2vBoglXFFkHqV+M2iEeKXhIPKnqeih7JFqKXq+j1slSt5GtL4wLKU0WQC+p3Op1S13VFdhhTDyFHil5YywHqSHkKfFZLvYzWTk7J12hpn6LkcQH1e/q8ujXOy8vL8Pr6umFyoD7H4zGdz+fUdV1xT9lKTjvAHkpuJ0tOO0Tw9PT00zAML29/b4sgbKzk7Rolpx1gDyW3kyWnHSKzgkXVhCkGgLj005TMChZNcggWAOLST1MjEyyqZvsDAMSln6ZGogj+XcmRdHislihVAFAj/XSdWh9XW8H6O0vUAACwXOvjaitYf9fq+xRaf8IAALCVVsdZrY6rb0QRbJx3YAAAbMM4q26PoghawWpc608YIIoan3KWck2lpHOKGq8JSmSc1SYrWAAB1PiUs5RrKiWdU9R4TQDRWMGCNzzhbU/ke17jU85SrqmUdE4R/Zoi10W24Z7TEitYNKvEJ7zeeL9MifccaqQuzldqP+CeU6NHK1jCtG+o1EawFSW+3LD1sKdLlXjPoUbq4nyl9gPueWzGrCsbhmH0z/Pz88B4XdcNKaWh67rcSQnhcrkMXdcNl8sld1KKlTMP3T+Az7TFZZOHXzNmnSel9DrcmTOZYG1IBf49lXe8iGXH/QP4LGJ7GLHfiCri/ctN+Znn0QTLFsENHQ6Hopbvt1bj9oCtltQjbgGp8f4BzBGxPdyq36hx61jE+5ebMeu6BLmABbY6tFtjhwbAdrbqNwSngMcEuYANbPUUzJMkAKbYqt+w2gPTeQ8WLHDr0HKuMnm3CECdIrTvEfo5KI0JFlWK0Cnt5bbvvu/73EkBYEWtte8t9d3UzQSLKrXUKZ1Op9R1ne0bZFPzoKjmayO+1tr3lvpu6maCRZVa6pRs32hD5IH+2oOiude6RR5FHfBFLg+sp7X2vaW+m7oJckGVBImgNhFD99+sfQh+7rVukUdRD/hHLg8wl76bWljBAqq05hP+CCsqkZ/srv2Ufe61bpFHUVcQ1r7WOWV17VU0q3JALbwHC6jSmu9umftZ3h9DKeaU1bXLt/oClObRe7CsYEFGNT2xjXYtaz7hj7SiAluYU1bXLt+R6ku09myJmq4FSmEFi6Zs9ab7uWp6YlvTtQBtq6k9i3Yt0fphWOLRCpYgF8FpiNYV7WB41AP0c9R0LUDbamrPol1LtH64dMaJQQ3DMPrn+fl5YF9d1w0ppaHrutxJqcLlchm6rhsul8sqfweRzS3Hyv888puW6V/zME7MK6X0OtyZM5lgBachykODRQ5r1/e55Xjt8h+1HZPfsB79Zh7qe14mWDBBiQ1WiWmeas1rjJhfUQbaUSYeW5Pf+6m97m6htOssLb2whqYnWCo9LYg4qHrPnHq55jVGzK9a26qo1xU1XUtFvK7cdTdinnwkYhsFayqxXr7V9ARLI8U9NVTsL5V2PbkHSaXlF5Qsd90tcRxQUxtV07WwnhLr5VuPJlhNhGkXYYV7ooWubY16CexFe5OX/pZ7aqiXj8K0NzHB2kINhaJ17iEAbE9/Wwf38WsmWCvzNAYAgFYY+37Ni4ZXFu3FfQAAsBVj3/GsYAEAAEz0aAXrf+RIDAAAQI1MsDZyvV7T8XhM1+s1d1IAAOBdxq7rMcHaSN/36Xw+p77vcydlEyohANCS2sc+tY9d92SCtZHT6ZS6rqv2IGDuSlh7Iwf3RC73kdM2R+TriZw22EqEcp977LO12seuu7r39uFHP8/Pz/u9GpnQcr+VvdS3f+fON8oWudxHTtscka8nctqIr9R+KEK5LzXv2E5K6XW4M2cywaJIpTZyETqIFpVaXt6KfB2R0zZH5OuJnLYparmO0pTaDykvRPRogiVMO+zIW9Dz8HJEiEe9zEM/BOvxomEI4HA4GEhk4OWIEI96mYd+CLYnyAVUIMLh38huAwpPayEO9fJj2nYokxUsqMAtslFKyZNJgEpo26FMVrBggqhPE4VWBahPxLY9aj8IkQhyARM4lA1Ay/SD8BtBLmAFDmUD0DL9IHzMChYAAMBEj1awnMGCL9hbDgDz6UfBBKtoGrH13SI29X0/+b91PwCoxdw+bUk/ymPGGGVxBqtgwreub8necvcDgFrM7dOc0dqGMUZZrGAVLGL41tItefGl+8EeIj/FjJy2KSJfR+S0UZe5fZoXSG/DGKMsglwAzbher6nv+3Q6nYrt/COHSI6ctikiX0fktI1VQz0ESEmYdoAqtlhE3n4TOW1TRL6OyGkbq4Z6CPAeK1hAMzw5h/zUQ6AWwrRDAM5P5OVsAOSnHuanL4JtmWBVTiMai/C1AOSmL4rDOK1OJliV04jGslYUIA0yQFvWbPdFpIvDOK1OglxUrqQD0S3sy79tjVnKIXGAtqzZ7q/VF0VV0niipHEa45lgZbBnxS+pETVpGE+DDNAW7f54JY0n9h6nlTT5LJkJVgYlVfw96TzGK2niDMBy2v3xjCceMwbdhwlWBir+fToPAGAp44nHjEH3kS3IRcuH9EsIUVvz/an52iCqaPUuWnqgFbXWvVKuq4Qx6FZ2vUfDMIz+eX5+HtbSdd2QUhq6rlvtM1lPzfdnj2u7XC5D13XD5XLZ7DtYX7T7tlZ65n7OmvkRrU1ZOz1z8mrN/I1UdiOlhfH2um/R2oK11HpdNdniHqWUXoc7c6ZsEywNcGw13589rk1DW6Zo922t9Mz9nDXzI1qbsnZ65uTVmvkbqexGSgvj7XXforUFa6n1umqyxT0KN8GCmmlol5maf7lXeraS+7qi5UdkVrDWT0uudqBV8g+mezTBevr878Z5eXkZXl9f19mbCPDA8XhM5/M5dV036qDy1L8H4tMOANE9PT39NAzDy9vfiyIIhDM1ypGoSFAf7QBQqmxRBKF1Y6PZlBKZaE1Toxy1HBUJaqUd+NiU/qHFvgRyMcGCTG4v++v7fpW/Y39zBiwGOR+bm0fy9mPKbF2m9A/6EtjRvYNZj34EuYD1jD1Q7OBxXLkjx0UqGxFCuteat8OwXnpyl1nWNaVcRCvTUIMkiiCQW5QOPmd0vggTkS1EmNzUmrfDsF56cpbZ2uo/gAkWkF2UQWuUdCwVaaAYKS1riHY90dIzR5R6FyUdQPkeTbBEEYRArtdr6vs+nU6nKg9qR4nyFSUdS90O9UcQKS1riHY90dIzR5R6FyUdW6q9L4HovAcLAvEeFwCW0pfAPh69B0sUwQbkigAl8tR0p9MpdV1X9ZNVALalL5nGOIm1WcFqQK4nWZ6gAQDRGScx16MVLGewGpBrv3kL+9wBgLIZJ7E2K1gAAAATOYPFJPYFAwCMY9zEl2wR5K6+79P5fE4pJfuCAQDeYdzEl6xgcZcIRMt4klW2aPcvWnqmipr+qOkaK1r6o6WH6dzD+Yyb+J17bx9+9PP8/Lzny5GhWF3XDSmloeu63EnJ7nK5DF3XDZfLJXdSRot2/6KlZ6qo6Y+arrGipT9aesYqsY3aSqn3EHJJKb0Od+ZMJlhMVlJnlCutOfMo2v0pscOOlofR0jNV1PRHTddY0dIfLT1jRWujWus/Sis3paWXbZlgsZpondF7SkrrWqJds84IiCxaGxWtDd9aaddbWnrZ1qMJliAX77her6nv+3Q6ndLhcMidnDBKem9DSWldS7RrPhwODvwCYUVro6K14Vsr7XpLS+8ejJe/5j1Y7/CGbWqjEQTISztMbVoeL3sP1gwiwhDV3EhPtzCyfd9vlDIA3jO3HRbhj6iMl79mi+A7om0bgJu579uwtQEgr7ntsPcsEZXx8tdMsKBAcztojSBAXnPbYQ/IoBzOYAEAAEzkDBYAAMDGTLAAAABWYoIFUIDSI4hFTH/ENI1VctoBameCRRgGDHUr8f5GSnPpIfYjpj9imsaKlvZIdWWM0tLLdO4xOYkiSBhC0NatxPsbKc2lRxCLmP6IaRorWtoj1ZUxSksv07nHZDUMw+if5+fnAbZyuVyGruuGy+WSOynN2SPvS7y/JaYZciitrmjz6if/2UNK6XW4M2cSph1Ix+Mxnc/n1HWdJ30AK9CuQv0ehWm3RRAIt90IoHTaVWiXIBcUJeqh1T3SteV3HA6H9OnTp3Q4HFb/bIAWbd2ubt3vRO1vU4qdNkjJChaFiXpodY90Rb12APa3dZ8Quc+JnDZIyQSrKtfrNfV9n06nU7UrEVG3XOyRrqjXDsD+tu4TIvc5kdO2lhbGdDUT5KIiEQ/UaiAAgMgijlUijun42qMgF85gVeR0OqWu60I90YnwMkx7taldpDIeKS1zRbmGKOmALUUo5xHGKm9FHNMxwb3Y7Y9+vAeLqSK8h6LruiGlNHRdly0NfCx3WVnr+6d+zhrfG6mMr5WWHPl4EyU/10jHnHxZIy9rqc9sL0J9U16YKz14D5YJFtXTcJYhdye71vdP/Zxcg+itrJWWHPl4EyU/c02+18jLWuoz24tS32AOEywgtNydbMkrWDWSj+uwgqU8ANt5NMES5AIAAGAiQS4AAAA2ZoIF0JipUbsiRPmKaE6+yEuA+plgAV+JPgjMMUGIkCdrpWFqSOK1QhhHyMM10zEnX9bIywj5uFYapnxOhOt+T/T0ATu6dzDr0Y8gF9CG6BG4ckSYi5AnpYdAj5CHa6YjVwCJCPmYI+pmhOt+T/T0AetLoggCY0WPwJVjghAhTyKkYYko6Y+SjrkipD9H1M0I1/2e6OkD1vdogiWKIMW7Xq+p7/t0Op3S4XCo5rsAIBp9LvzmURTBP+RIDKzpdqYhpZQ+ffpUzXcBQDT6XPiYIBcU73Q6pa7r0ul0quq73nKAGoCU8vYHrfS5sIQtgjSn1C0Hx+Mxnc/n1HWdJ3kADSu1Pyi1/4VHbBGEvyt1y8HtCZ4neQBtK7U/KLX/halMsGhOqR3T4XDQIQFQbH9Qav8LUzmDRXNuHdO97QnOOQHAfO/1o+/1v1ATEyz4wm37Qt/3uZNCRiVOtCOlOVJapoiU7khpGavENLM+/Sikel807IV/26o1f2u9Lqbpum5IKQ1d1+VOymiR0hwpLVNESnektIxVYppZX639aK3XFUWp+ZsevGi42gmWhn5b8pealdjQR0pzpLRMESndkdIyVolphrGMe7ZVav4+mmBVG6ZdKNBtyV8AoBXGPdsqNX8fhWmvdoIFLFNqYwewN+0ltMl7sIBJvK8EYBztJfAlUQRhByVG1zqdTqnrOu8rAfhAie1lif0SlMIWQdjB8XhM5/M5dV3n6SYA2emXYLlHWwStYMEOxj7d9EQRgKXG9CUlrrpBKUywAjPYrsfYt9d7QSMAS43pS8b2S8RnvBiPCVZgBtvtmfpEUaMKULc57bzVqbYYL8ZjghWYBrI9U58oalS3VdoENkp6o6RjqijpjpKOsUpLb2nmtPNWp9pivBiPMO2B3RpIeOTWmGpUt1Fa6OUo6Y2SjqmipDtKOsYqLb2l0c7zEePFgIZhGP3z/Pw8QESXy2Xoum64XC5Nfj/bKO2+RklvlHRMFSXdUdIxVmnpZZzc9zX398MYKaXX4c6cSZh2qpA73Gzu7weANeXu13J/P4whTDtVy73/OPf3r8VZCoBlamlHc/drub8flrCCBfzKE0OAZbSj0I5HK1iCXAC/cpgaYBntKGAFCwAAYCJnsKBwtezrB2AZ/QHEZoIFhZj6skkd8LZy52/u758rd7pzf/9cudOd+/trNzV/vWQegrsXu/3Rj/dgQT5T3wnSdd2QUhq6rts4ZW3Knb9rfP/UMrXGe2nk2zw15BuPTc1f74iCGNKD92CZYEGlPuqAddDL5M6/HIP2HJOTtcm3Mr+/Bu/lofyFMj2aYAlyAY0SSpjr9Zr6vk+n0ykdDofV/75W8o05tLlQH0EugN/Z4iWOY84ROMsRx+FwSJ8+fRo96J/697WSb+XK2UZ5cS60wwQLGrXFoG/MwesWD2dPHbCZhMqzuabkQ4t5lrONMtGGhtzbN/joxxmsdtkfzhhjykmLZWnvMzu589g5p3zfPyUfWgxcoY1iTcoKSZALlmixI4a17B11Lnd9Fakv3/dPyQeDQ1gmd5tBfiZYLKIj/j35QWS5y2fu758rd7pzfz+8R/n8mjzh0QRLFEGYQTQoAFqi34OviSIIK2o9GlSLh+OBtrXe7rXe78EUJlgwQ+vRoLaOBNj6QAaYbut2o8UIqF9qvd+DKaqYYEUejEVOG8y19ZPM1gcywHRbtxtWcKhV1LFq1HSN8YfcCVjDrVFNKYXbFxw5bTDX7UnmVm4DGAMZYKyt242t2z3IJepYNWq6xqhiBSvyU6XIaStZyU811lRrPtiKAkxVa7tRazs/lXzYTtSxatR0jXIvtOCjH2HaicK7Jz6TD5QWJjhCeiOkYayS0so2tPOfyQciSg/CtFexRZD22EL2mXygtC0UEdIbIQ1jlZRWtqGd/0w+UJJJE6z//u//TsfjMZ1Op+qW4CmLvfCfyQdKG3RESG+ENIxVUlrZhnb+M/lAFNfrNfV9/267POlFw//wD/8w/Nd//ZeXzAEAAM358qXb5/P57ouGJ61g/fM//3M6HA6epAEAAM35cmfBbQv3W5NWsF5eXobX19dVEgcAAFCqp6enuytYVYRpB9oiXC+0Sd0HSmCCBUwSYYBzi6zW9322NAD7y133I7R/QHzCtAOTRAgbLbIatCl33Y/Q/gHxWcECJonwZvVbuF6vi/jMU/U6ua9fy133I7R/QHwmWMAkuQc4fC33tqkpIkwaIqRhjJLuayu0f8AYJlgwUymDNOpX0lP1CJOGCGkYo6T7St30dzCNM1jv+PJNzZ5W8Za9+ERxe6pegtxnaKKkYYyS7it109/xHuPlr1W/grXkqUvEp5yeIsXh6TJMF2GLVYQ0QEn0d3FEHAcuGS9HvJ5VDMMw+uf5+XkoTdd1Q0pp6Lpu8n97uVyGruuGy+WyQcrmmXs9a11LxDwBANhD7vHUknHtVpbkScTrmSKl9DrcmTNVP8GqbUKQu0KWXhFqVFsZB+Az7Xs8ucdTtZWJ0q/n0QSr+jNYte1hn3s9a505KOXsQkvsjQeok/Y9ntzjKePaMjx9nnyN8/LyMry+vm6YHPiNQ5PjyCeAOmnfx5FP5PL09PTTMAwvb39ffZALyhUxyEhEDuzznlwHiEs7uCyfiEj7Po7xAtGYYBGWqEWMZZD6WK6BR2kDHvkUk7rNGMYLRLP5GSzLtsxV675c1uecwmO5zk2Wdl5TPsWkbjOG8QJzbTVP2fwM1vF4TOfzOXVdp/BDhSI8RImQBmB9uet27u8HtrV0npLtDJZlW6hbhC1OziksN2UrVqvbtqZed6v5tKbcdTtC+wZsZ6t5yuZbBC3bQt1scarDlK1YrW7bmnrdreZTTbRvULet5inVvwcL2JaHKHWYMpBsddA59bpbzaeaaN+AObwHCwAAYCLvwQrEvnwAAPZk/LkfE6wMaj40O7byquQAwJ5aH6PUPP6MxgQrg6iRFddoUMZW3r0r+Z6NZa0NMwB1q72v3HOMEnEsEHX8WaVhGEb/PD8/D9Sr67ohpTR0XTf7My6Xy9B13XC5XFb5u7VMvbYl6VsjHz+yd/4BkNce7f7S/mtKGvfoK9/ac4yS4/rYX0rpdbgzZzLB4lc1D9qnXtuShrGETrAme5fbmusJfER9y6eEh3dT0lj7va39+vjMBAsmiN4wRk/fnvaebJrc0jL1LZ8S2v0S0ghrMsECsti6w13z88d81pTvM9igFGtvnVqr7JfUfgDteTTB8h4sYFPH4zGdz+fUdV34F3aundaSrp22tVr2S0knENOj92D9IUdigHbcohWVELVo7bSWdO20rdWyX0o6gbJYwQJGu16vqe/7dDqd0uFwyJ0cgCy0hUBKj1ewvAcLGjflXR1eUggwvi2M+C4kYHsmWJBBpE53yqQp90sKI+UbkEeEdmBsWxjpoVSEfINm3It88ehHFEEiKjEK1JjQw3tdV5T8G5MOIZuBSO3nRyK146W2n1HuJdyThGmnVjk7jbkNf82d4VwlDZqAfLSfX9u6/czZ9rZ2LymLCRbVqrXhb20ysff1RsnfKOmgTpHK155piXTde9j6ekt8kAl7eDTBEkUQFhBJqlxR3n8TJR3UKVL5ipQWptHXwX3egwUbOBwOBgp3lNAZR3n/TZR0UKdI5StSWu4pod3KRV8H01jBAlbnSTVQGu0WMJX3YEHD9g7PmzucO8BUe7dbwqZDvaxgQQM8mQWIRbsM5XMGCxoW/ewDQGu0y1AvK1gAAAATOYMFAACwMRMsAACAlaw6wRIRpx7uJeSlDjKF8gJ5qYP1WONerjrB6vs+nc/n1Pf9mh9LBu4ltYveGZZQB6Pn4VpKuM7o5aWEPIQlotdBxlvlXg7DMPrn+fl5eM/lchm6rhsul8u7f1ebGq+7xmuCL3VdN6SUhq7rciflrlx1cMr3Rs/DtUy9zhz3Lnqb3UpZoV3R6+AcNV7TGFOuO6X0OtyZM606wWqVjgOmy91w5/7+qKa0Z63k4dTr1Cd8LXdZyf39UCJt2cceTbC8B2sF3mUB092W4FNKWV6yeTgcvNzzjintWSt5OPU69Qlfy11Wcrc3UCJt2XzegwVkcb1eU9/36XQ6pcPhkDs5bCzi/Y6YJrbhXgNb8B4s2JED3R+7PdE22GlDxAPgEdPENrQ3H9NvwXpMsChKKR2AgRsR5aw/p9MpdV0XaqtJrjSV0o7RlpL6LXWI6JzBoiil7KO3b5mIctaf3Gdw7smVplLaMdpSUr+lDhGdCRZFKaUDiDSYdPaAm1LqT+3cB74UpY2O1G99RB0iOkEuoHLH4zGdz+fUdV0xnSdAK7TRUC5BLqBREc++MJ6zBnxEGSmbNhrqY4IFlRM9a7pIA9aSDp6TR6QyEqnulEIbDfUxwQJ4I9KAtZWn21sMzFsZ7EcqI5HqDkAuglwAvBHpAHVJB8+X2CIqWCuRxiKVkUh1ByAXEyyANyINWFuxxcDcYH9/6g6ALYIA1Sppi9wW51BKOdtS0n0C4GNWsAAq1coWudK5TwB1sYIFhOAp/voiBT/gMfdpfdoTICcTLCAE0cfWHxSWskWudWvfJ5ML7QmQlwkWEEKJT/HXHsgaFLKGtctRiRO2EtsToB7OYAEhlBh9bO2zM6LesYa1y1GJZ8RKbE+AephgAcy09kDWoJA1rF2OTPwBprFFEGCmKWdnStxmlcPSfJLP40zJJ2f5AKYxwYINGexx43zVOEvzST6PI5/4kr4K1mWCxa80sOuLOIhxn/Nw6H6cpfkkn8eRT3lEbX8j9lUli3qf2dEwDKN/np+fB+rVdd2QUhq6rsudlGpcLpeh67rhcrnkTsqv3Of2RCyHuC8titr+KovrinqfWV9K6XW4M2cS5IJfOci8vohBC9znr12v19T3fTqdTlWeMykxClwLar8vtderOaK2vxH7qpJFvc/s5+nz5Gucl5eX4fX1dcPkwMd02qzteDym8/mcuq6rcpChzsRU+32pvV6xv9rrDOV5enr6aRiGl7e/t4JFcWp/6sv+an/a6Ol0TLXfl9rrFfvT/1MKQS4ojsPZrG1qGGoHmGnR1HIvvDtr0/9TChMsiqPTrtMWk5atJkIibtGircr9VvXUg5D66P8phQnWDBptWN8Wg7etBoSeoq7LALsMW5X7reqpByGwLm3qeM5gzWAPMKxvi/MaW50Bqf3szN62alO11evaqtxvVU+dAYN1aVPHM8GaQaMN69ti8GYiVAYD7LZtVU/Vf1iXNnU8YdoBGif08TbkK0DdhGkH4C7bPrYhXwHaJMgFcJfDrO0QtGMb8rUd2kvgSyZYwF0icK2jhIHXlqGPo1//lukrIaR09PtTCu0l8CUTLOAuT9/XUdvAa+qAPPr1T01fbROS6PenFNpL4EvOYAF3bRWBq7WD/7VFXZp6rij69U9NX23nqqLfny1s0QaJWAj8zjAMo3+en58H4LHL5TJ0XTdcLpfcSQmr67ohpTR0XbfaZ8r3/bSe161f/562yust2qCaKOMwXkrpdbgzZ7KCBSuq7en2FrZ4Yi7f99P6k/rWr39PW9XrFlftptCewnLOYMGKIu3D3/usyNjv2+Lgf6R8B9axVb0e2wbt2YZGOtunPYXlvGgYKnU8HtP5fE5d1+3yFHLv7wPY0p5tmvYTyuRFw9CYvbfB2HYD1GTPNk37CXWxRZDqRNpqsaap17X3O3hKeOcPwFh7tmlTv0s/B7GZYDWklYar1ve61HpdAExTa39Q63W91cp4rGW2CDaklchAtW61qPW6AJim1v6g1ut6q5XxWMusYDWklchAtW5V2/q6PFFjjNbLSevXzzhblxP9XNlaGY+1zASrIa00XMzTytaMSHIP1ud8f+vlZM71l3ifWab1esL7jMfqZ4sgkFJqZ2tGJLm3icz5/tbLyZzrL/E+s0zr9QRaZ4JFGNfrNfV9n06nk6c6GdyeqLGf3IOwOd/fejmZc/0l3meWab2eRGBMQU62CBJGCVsqbLVhTbm3iezx/SXUmdrPy+T+fupSQp1OqYwxBfUywWJVSxreEg59arBjKqXDb1EJdaaENLZIvY6plPoyd0yh3LGKYRhG/zw/Pw/wnq7rhpTS0HVd7qSMdrlchq7rhsvlsurfsp8Sy10rSqgzJaSxRep1TLX3mcodU6SUXoc7cyYTrBWV2JCsrcQ80JiWr8RyB7xPvS5fif2rcicPpjDB2kGJDQlxGpIo6aAOylN53DPWEqUsRUkH0xjPjvdogiWK4IpEaipTlGhPQimzJuWpPO4Za4lSlqL0r0xjPLucCdaKNCQsoUFjTcpTedwz1qIssYTx7HJPn1e3xnl5eRleX183TA4AAEB8T09PPw3D8PL298K0UyyhVPOQ70CrtH95yHdKY4sgxYqyx7w18h1olfYvD/lOaaxgFaz1JzolvJi4RvJ9Xa3X462vX/62ff1r0/7lId/V5dI4g1Ww4/GYzudz6rrOEx0oVOv1eOvrl79tXz/UQl2O6dEZLFsECyZKEJSv9Xq89fXL37avH2qhLpfFChYAAMBETUQRLHF/aolphtLUXs9qv75WtXBfW7hGyKnUOlZqun81DMPon+fn5yGyruuGlNLQdV3upIxWQpovl8vQdd1wuVxyJwVmKaGeLVH79bWqhfvawjVSt+hjpFLrWCnpTim9DnfmTFWdwSpxf2oJaRYeldKVUM+WqP36WtXCfW3hGqlb9DFSqXWs1HTfOIPFh67Xa+r7Pp1Op3Q4HHInBwAgBGOktj06g2WCBQAAMFETQS4AAAByMsEC2EnxUZGognIIsC0TLMjMYKcdt8PQfd/nTgoNUw7boX+BPEywIDODnXacTqfUdV2xUZG2ttZg0KDyfcphO/QvkMeqEyydGkxnsBPLlu3Y4XBInz59EmnqgbUGgwaV79uyHBoHxKJ/gelWacfuvRzr0c9HLxou5aVgwPqiv2xxLO1YPmuVoVrKYolqqj/KEbRpSjuWHrxoeNUJVg2NUQ3XwG/cz/3UMrCaU2aUM2rUel2opU0rQU3lpnU13Msp17DLBKsGGtS6uJ/7qaFRnUs5o0atl+uW27S9tV7WatLavXw0wfrDgi2KVbrtU7ZfuQ7u535u5zpaFKWcXa/X1Pd9Op1OznkVLMp9jFKuc2m5Tdtb62WtJu7lZ0+fJ1/jvLy8DK+vrxsmB4C5jsdjOp/Pqes6A8OCuY8AZXh6evppGIaXt7+3ggVQCU8O6+A+ApTNChYAAMBEj1awvGgYAABgJSZYAAAAKzHBAqqzylvY2cXW90pZKIv7BdRAkAugOn3fp/P5nFJKorAFt/W9UhbK4n4BNbCCBVTndDqlrusmRWHz5DyPOfcq0udz39z65H4BNRBFECB59xCsSX0CWiCKIMA7WnlybqUur1byv5X6BHCPCRa/aqXjpzx7lM3D4ZA+ffqUDofDZt8Rwe2MS9/3uZPSpFbyf4/6pM8iKmUTEyx+1UrHXwoN9G+UzfVYWchL/q9Hu/B7+ow4lE1EEeRXtw5fxx9DSdG0rtdr6vs+nU6nTZ5YK5vrua0skIf8X8/W7cLW7draSuozaqfPQpALCKqkzt2Bdt4qqfymVF562V5p7ZoyDPt7FOTCChYEVdKTbk/r6jZn4Fba0/Q56TWgrVtp7VpJfQbUzgQLWKzFjr2lwfWcyUdpg9M56S1tErlES+X9psV2DViHCRbADC0NrudMPkobnM5Jb2mTyCVaKu8AS5lgAczQ0uC6tMnSXlrKl5bKO8BSwrTTBOFrWVsr782ClJR31qdfpmYmWBNoDMrlnRQAEId+uVzGwx+zRXACe9DLZXsLAMShXy6X8fDHTLAm0BiUq6WzEgAQnX65XMbDH7NFcAJ70GFbth0Aa9CWwHaMhz9mBQsIw7YDYA3aEiAnK1hQgT2e1u7xHafTKXVdZ9sBsMjWbUktbS6wjadhGEb/8cvLy/D6+rphcoA5jsdjOp/Pqeu6zZ7W7vEdACXQ5gIppfT09PTTMAwvb39vBQsqsMfKj9WlNnmK/j750yZtLvAeK1gAjbher6nv+3Q6nUYfTvYU/X1z82fOvQAglkcrWIJcADRizsF/4XjfNzd/BGEAqJctgtAw25u2EzFv52w5Eo73fXPzJ9r2r4jltSbyF9piiyA0zPav7chbSqK8bkv+Qp0EuQC+Eu0pek1azttSn9aXmu41tFxe9yB/oS1WsABYValP60tNNwB5CHIBwC5KDYxRaroBiMUWQe5qeavMnuQzNSo1MEap6YaP6Gu2J4/5kgkWd91CCPd9nzspVZPPLKVTr597zFL6mu3JY75kiyB32SqzD/nMUt6nVD/3mKX0NduTx3xJkAuAgl2v19T3fTqdTra2Vco9BohJmHaaU/O2mlqvrdbr2pJzQ/Vzj6eptR2p9bpSqvvaaJMJFtXacz/03p1DrXu9a70uYD+1tiN7X9ee/Vqt94x2OYNFtfbcD733GYla93rXel3AfmptR/a+rj37tVrvGe1yBgtW4IwEADXRr8HHnMGCDTkjAdPttQXJ+Q6YTr8G89kiCEAWe21BEuYcgD1ZwQLYkNWTx06nU+q6bvNzF3t9T6mUUYB1OYMFsKHj8ZjO53Pqus7qCSEpowDzPDqDZYsgwIZExyI6ZRRgXVawAAAAJhJFEKBwzspwoywAxGWLIEAhRMPjRlkAiMsK1gOeDgLRiIbHjbIARGLc/HsmWA/cng72fZ87KbCYhq8OXvzJjbJQPu0yNTFu/j1bBB8QVYma2E4EEIt2mZoYN/+eFawHPB0cL8dTuD2/s4anjLVsJ6rhXgDL1NIOaJdjf1eO7yuZcfMbwzCM/nl+fh7gra7rhpTS0HVdld+Z4/q4z70AtAOx1NwfK2t8JKX0OtyZM9kiyGI5loX3/E7L3nG4F3W7Xq+p7/t0Op0WPwVd87OIRTsQS839sbLGXF40DLACA/rljsdjOp/Pqeu6xWdS1vysFinPAB979KJhK1gAK3Bgfbk1nxZ78ryM8gwwnwkWwAoM6Je7HZKO9lktUp4B5hNFkKxE6KEWIihRE+WZmhhrsDcrWGRlGwoAsCVjDfZmgkVWtqEAAFsy1mBvtgiSlW0o7MH2EIhJ3WQPxhrszQQLqN5te0jf95P+u6iDv6jpYltR7/uSdM2tmwCR2SIIVG/u9pCo+/ajpottRb3vS9Jl6xZQIxOsynlZJMwP2R118Bc1XWwr6n1fki7h9GmdcVqdnoZhGP3HLy8vw+vr64bJYW3H4zGdz+fUdZ1ODAAgEOO0sj09Pf00DMPL299bwapc1CeeAACtM06rkxUsAACAiR6tYIkiCA2LGpWM+u1d9pR1clH2oD22CELDokYlo357lz1lnVyUPWiPFSw+5OlbvU6nU+q6zt5vdrd32VPWyUXZq5fxEY84g8WHRLgBAPg94yOcwWK2Vp++eTIFAB9rtb9sdXzEx0ywAonaQN1eBNnaC/Bu++b7vs+dFAAIq9X+Mur4KOp4siUmWIG02kBF5clUfjqJZeRfOdyr+eRdfvrLWIwnAxiGYfTP8/PzwHYul8vQdd1wuVxyJwVC6LpuSCkNXddN/m/Vp2X5x75av1dL6mvreQdv6f/2k1J6He7MmYRpD+S21Ax8tuQN90IjL8s/9tX6vVpSX1vPO3jLeDI/UQSBKl2v19T3fTqdTuH2xwO/p74CJRJFEGhK1MPHtSv9PEzp6S+V+grUxBZBAFZT+tbM0tMPQH5WsAD4nSWrOKVHE1uSfqtfAKRkggXsxOCzHEtC/Ja+1WtJ+oVGLof2CNiSLYLALmy9KoeobPPIt3Joj4AtmWABuzD4LIcQv/PIt3Joj4AtVbVF0JI/xFXK1jHtCMxXSv0ppT2CVpXSljxS1QqWJX9gKe0IzKf+AGsovS2paoJlyR9YSjsC86k/wBpKb0uq2iJoyT+G0pd1W+JefU07AvOpP1/TzpbF/Yqh9LakqhUsYih9Wbcl7hXAtrSzZXG/WIMJFqsrfVm3Je4VwLa0s2Vxv1jD0zAMo//45eVleH193TA5AAAA8T09Pf00DMPL299XdQYLAAAgJxMsmMEhWABaot+D8UywYIbbIdi+73MnBVZlELWM/KNW+j0YT5ALmMEhWGolgtYy8o9a6fdgPCtYMEPp72egbktWUU6nU+q6ziBqpiX5Z/WLyPR7MJ4JFrAaA8QYlmzlMYhaZkn+2YIVg3YMWMoWQWA1tkfFYCtPmdy3GLRjwFImWMBqDBBjuK2iUBb3LQbtGLCULYIT2ToAj7WyvUw7cF8t+VLLdWyhhbxppR2DOVpoA9ZgBWsiWwcA7cB9teRLLdexBXkDbdMGjGOCNZGtA4B24L5a8qWW69iCvIG2aQPGeRqGYfQfv7y8DK+vrxsmB1jb9XpNfd+n0+lkywtAMNpoKNfT09NPwzC8vP29FSyonOV8gLi00VAfEyyonOV8gLi00VAfUQShciJilU/UJu5RLuqgjYb6mGDBjgyImOO2hajv+9xJIRDlgrn0RbAtWwRhR/baM4ctRNyjXDCXvgi2ZYIFOzIgYo7bFiL4knLBXPoi2JYtgrCjJXvtbekAIKXl/YFzX7AtK1hQCFs6AEhJfwDRWcFiU1Zd1nM6nVLXdbZ0UIUcbYP2iFroD9ajXWALT8MwjP7jl5eX4fX1dcPkUJvj8ZjO53Pqus5TNuBXOdoG7RHwlnaBJZ6enn4ahuHl7e9tEWRTDtIC9+RoG7RHwFvaBbZgBQtY1fV6TX3fp9Pp5AA1UBTtFzCFFSxgFw5fA6XSfgFrEOQCWFVLh68djqYVrZT1ltovYDu2CALM5HA0rVDWAb5miyDAyhyOphXKOsB4tgjCHa1sh2GZw+GQPn365DA81VPW+Yh+E35jggV33A46932fOyk0xiCFpZQhctBvwm9sEYQ7bIchF1HMWEoZIgf9JvzGChbcscZ2GE+RmUMUM5ZShphqjf7KNlL4jSiCsBFRtwAogf4K5hFFEHZmuwQAJdBfwbqsYAEAAEz0aAXLGSwAAICVmGABkN0WQWEEmgEgBxMsqmRgBWXZ4h063ssD5dBvUxNBLqiS98BAWbY4ZO/gPpRDv01NrGBRJe+Bic2TSt7a4h063svDl7Q7sem3qYkJFlUysIqttK1bBmbwtdLqRWntTmv029TEFkFgd6Vt3bJ1Bb5WWr0ord0BymWCBezu9qSyFAZm8LXS6kVp7Q5QLi8aBgAAmMiLhqEQpZ1rACAG/QfEYIsgBFPauQYAYtB/QAxWsFiFp2brEaqWG/WKsZQVUtJ/rEmdYglnsFjF8XhM5/M5dV3nqRmsRL1iLGUF1qVOMUbTZ7A8hdiep2awPvWKsZQVWJc6tY9ax+hNTLC8XHB7XhDIXpY2xiU15uoVY5VSVlqqv5StlDpVulrH6E0EuSjtXR3AY0sPcTsEDvmov8CXah2jNzHB8nJBqMfSxrjWxhxKoP4CX6p1jC7IBQC7ul6vqe/7dDqddt1+k+t7AajToyAXTaxgARBHrm1etpcBsAcTLAB2lWubl+1lAOzBFkEAAICJmn4PFgAAwB5MsAAAAFZigkURvFwSAPiSsQFRCXJBEUT/AgC+ZGxAVFawKMLpdEpd14n+BXd4ilsn9xXeZ2xAVKIIAhTueDym8/mcuq7zFLci7itAbF40DFAp73eqk/sKUCZbBKEwtg3x1uFwSJ8+fUqHwyHL99daJnNfV+77Sky5yyXwsUlbBJ+env7flNL/3S45wAj/T0rpf6aU/iul9H8ypwVSqrdM1npdlE25hDj+9zAM/+vtLydNsAAAAHjMFkEAAICVmGABAACsxAQLAABgJSZYAAAAKzHBAgAAWIkJFgAAwEpMsAAAAFZiggUAALASEywAAICV/P9JJsys7UgTVgAAAABJRU5ErkJggg==\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "image_feature_locations = simulator.get_image_feature_locations(area_restrict = image_area, min_feature_count = 2)\n",
+ "feature_counts = Counter([f for i in image_feature_locations.values() for f in i.keys()])\n",
+ "feature_counts_counts = Counter(feature_counts.values())\n",
+ "print(\"Total number of features: \", len(led_positions))\n",
+ "print(\"Number of features in more than one image: \", sum(feature_counts_counts.values()))\n",
+ "print(\"Feature in image counts:\", feature_counts_counts)\n",
+ "simulator.show_images(image_feature_locations, area=image_area)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 48,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "camera_orientations, camera_positions = fit.camera_world_poses(camera_rotations, camera_translations)\n",
+ "plot_geometry(led_positions, camera_positions)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 38,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "=== Gaussian errors on feature image locations: 1.0 ===\n",
+ "8 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 13.828063542394737 max: 218.27011488545185\n",
+ "image 1 reprojection errors: average: 14.266911731441311 max: 168.02572846508102\n",
+ "image 2 reprojection errors: average: 13.259631557103953 max: 159.2642398699781\n",
+ "image 3 reprojection errors: average: 13.422864585752475 max: 137.03572224565602\n",
+ "image 4 reprojection errors: average: 14.042001696393454 max: 177.2409590707412\n",
+ "image 5 reprojection errors: average: 14.419637448618259 max: 232.93124855660497\n",
+ "image 6 reprojection errors: average: 14.28349841175458 max: 95.76014743378593\n",
+ "image 7 reprojection errors: average: 13.816511440007561 max: 110.1203537367734\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 1.5083e+06 2.55e+06 \n",
+ " 1 2 5.9099e+03 1.50e+06 6.91e+01 9.53e+04 \n",
+ " 2 3 4.1487e+03 1.76e+03 7.89e-01 1.47e+03 \n",
+ " 3 4 4.1432e+03 5.47e+00 2.66e-01 8.32e+02 \n",
+ " 4 5 4.1421e+03 1.18e+00 3.87e-02 9.54e+01 \n",
+ " 5 6 4.1419e+03 1.74e-01 9.74e-03 3.51e+01 \n",
+ " 6 7 4.1418e+03 7.01e-02 4.36e-03 1.38e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 7, initial cost 1.5083e+06, final cost 4.1418e+03, first-order optimality 1.38e+01.\n",
+ "mean reprojection error: 0.8453353393586547\n",
+ "max reprojection error: 3.1669253825859003\n",
+ "mean reconstruction error: 0.07599713093701795\n",
+ "max reconstruction error: 0.35918856633649\n",
+ "=== Gaussian errors on feature image locations: 3.0 ===\n",
+ "8 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 14.186361973998029 max: 142.13279660962115\n",
+ "image 1 reprojection errors: average: 14.3430728296801 max: 114.57890349429739\n",
+ "image 2 reprojection errors: average: 14.030040315205252 max: 143.10725465392943\n",
+ "image 3 reprojection errors: average: 14.251753739436086 max: 183.5931418951843\n",
+ "image 4 reprojection errors: average: 14.207830844722821 max: 149.83951606976632\n",
+ "image 5 reprojection errors: average: 14.44821544767734 max: 124.8193940574816\n",
+ "image 6 reprojection errors: average: 13.708985116983074 max: 111.01284859340113\n",
+ "image 7 reprojection errors: average: 13.930256656976045 max: 135.84947501329322\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 1.4939e+06 2.77e+06 \n",
+ " 1 2 3.9147e+04 1.45e+06 6.89e+01 7.63e+04 \n",
+ " 2 3 3.8133e+04 1.01e+03 8.75e-01 6.73e+02 \n",
+ " 3 4 3.8086e+04 4.70e+01 8.20e-01 4.48e+02 \n",
+ " 4 5 3.8072e+04 1.33e+01 1.44e-01 3.80e+01 \n",
+ " 5 6 3.8071e+04 1.59e+00 4.35e-02 5.31e+01 \n",
+ " 6 7 3.8070e+04 7.30e-01 1.38e-02 2.72e+01 \n",
+ " 7 8 3.8070e+04 4.30e-01 1.15e-02 3.81e+01 \n",
+ " 8 9 3.8069e+04 3.75e-01 9.62e-03 4.53e+01 \n",
+ " 9 10 3.8069e+04 3.59e-01 9.64e-03 5.63e+01 \n",
+ " 10 11 3.8069e+04 1.91e-01 3.68e-03 3.71e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 11, initial cost 1.4939e+06, final cost 3.8069e+04, first-order optimality 3.71e+01.\n",
+ "mean reprojection error: 2.5564564934849114\n",
+ "max reprojection error: 9.98131009620747\n",
+ "mean reconstruction error: 0.2290003305014601\n",
+ "max reconstruction error: 1.0506093661635483\n",
+ "=== Gaussian errors on feature image locations: 5.0 ===\n",
+ "8 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 15.100127042494083 max: 160.51986142773094\n",
+ "image 1 reprojection errors: average: 14.658957672792338 max: 151.55699428817383\n",
+ "image 2 reprojection errors: average: 14.687438047915299 max: 77.94474483482014\n",
+ "image 3 reprojection errors: average: 14.67090740732709 max: 129.3577026301649\n",
+ "image 4 reprojection errors: average: 14.871906549459718 max: 245.14146882194805\n",
+ "image 5 reprojection errors: average: 15.002691746208708 max: 181.49916389261205\n",
+ "image 6 reprojection errors: average: 14.142437625710745 max: 130.7997569389291\n",
+ "image 7 reprojection errors: average: 15.023724647497383 max: 155.0864057338731\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 1.6006e+06 2.02e+06 \n",
+ " 1 2 1.0686e+05 1.49e+06 7.10e+01 7.35e+04 \n",
+ " 2 3 1.0555e+05 1.31e+03 1.24e+00 1.98e+03 \n",
+ " 3 4 1.0541e+05 1.40e+02 1.38e+00 1.30e+03 \n",
+ " 4 5 1.0536e+05 5.00e+01 2.58e-01 1.23e+02 \n",
+ " 5 6 1.0535e+05 6.83e+00 9.27e-02 9.59e+01 \n",
+ " 6 7 1.0535e+05 3.87e+00 4.56e-02 8.69e+01 \n",
+ " 7 8 1.0535e+05 1.69e+00 2.22e-02 6.17e+01 \n",
+ " 8 9 1.0535e+05 1.31e+00 1.96e-02 8.12e+01 \n",
+ " 9 10 1.0535e+05 1.28e+00 1.87e-02 8.80e+01 \n",
+ " 10 11 1.0535e+05 1.03e+00 1.38e-02 1.13e+02 \n",
+ " 11 12 1.0534e+05 7.43e-01 9.27e-03 9.66e+01 \n",
+ " 12 13 1.0534e+05 3.53e-01 3.94e-03 4.33e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 13, initial cost 1.6006e+06, final cost 1.0534e+05, first-order optimality 4.33e+01.\n",
+ "mean reprojection error: 4.2565467060174385\n",
+ "max reprojection error: 16.392380585922076\n",
+ "mean reconstruction error: 0.378511613097883\n",
+ "max reconstruction error: 1.7280389068962418\n",
+ "=== Gaussian errors on feature image locations: 10.0 ===\n",
+ "8 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 17.09867179575005 max: 118.48103903261772\n",
+ "image 1 reprojection errors: average: 17.363731455254754 max: 155.74102883809007\n",
+ "image 2 reprojection errors: average: 16.937621673918557 max: 107.22656681795047\n",
+ "image 3 reprojection errors: average: 16.897941538151336 max: 104.96684275768155\n",
+ "image 4 reprojection errors: average: 17.939475068224173 max: 252.947133817352\n",
+ "image 5 reprojection errors: average: 17.62125191913709 max: 98.61883188730926\n",
+ "image 6 reprojection errors: average: 17.390697365602733 max: 135.27484877400363\n",
+ "image 7 reprojection errors: average: 17.61046441629536 max: 152.50414170677618\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 2.0189e+06 2.49e+06 \n",
+ " 1 2 4.2301e+05 1.60e+06 7.52e+01 2.75e+05 \n",
+ " 2 3 4.1944e+05 3.57e+03 2.99e+00 1.15e+04 \n",
+ " 3 4 4.1905e+05 3.90e+02 1.68e+00 2.64e+03 \n",
+ " 4 5 4.1885e+05 2.06e+02 5.72e-01 7.90e+02 \n",
+ " 5 6 4.1880e+05 4.98e+01 2.50e-01 5.96e+02 \n",
+ " 6 7 4.1876e+05 3.86e+01 1.87e-01 3.64e+02 \n",
+ " 7 8 4.1873e+05 2.71e+01 1.48e-01 4.46e+02 \n",
+ " 8 9 4.1871e+05 2.13e+01 1.09e-01 3.56e+02 \n",
+ " 9 10 4.1870e+05 1.04e+01 5.10e-02 1.98e+02 \n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " 10 11 4.1869e+05 1.00e+01 7.13e-02 3.50e+02 \n",
+ " 11 12 4.1868e+05 9.55e+00 4.88e-02 1.88e+02 \n",
+ " 12 13 4.1867e+05 8.06e+00 5.82e-02 2.89e+02 \n",
+ " 13 14 4.1866e+05 8.05e+00 4.57e-02 1.85e+02 \n",
+ " 14 15 4.1866e+05 7.56e+00 5.46e-02 2.60e+02 \n",
+ " 15 16 4.1865e+05 7.38e+00 4.38e-02 1.69e+02 \n",
+ " 16 17 4.1864e+05 7.17e+00 5.24e-02 2.90e+02 \n",
+ " 17 18 4.1863e+05 6.95e+00 4.21e-02 1.71e+02 \n",
+ " 18 19 4.1863e+05 6.47e+00 4.73e-02 3.32e+02 \n",
+ " 19 20 4.1862e+05 6.56e+00 4.09e-02 2.12e+02 \n",
+ " 20 21 4.1862e+05 5.75e+00 4.01e-02 3.53e+02 \n",
+ " 21 22 4.1861e+05 6.16e+00 4.02e-02 2.93e+02 \n",
+ " 22 23 4.1860e+05 5.53e+00 3.55e-02 3.70e+02 \n",
+ " 23 24 4.1860e+05 3.24e+00 1.78e-02 2.04e+02 \n",
+ " 24 25 4.1860e+05 1.70e+00 1.02e-02 1.79e+02 \n",
+ " 25 26 4.1860e+05 1.76e+00 1.34e-02 2.15e+02 \n",
+ " 26 27 4.1860e+05 1.69e+00 9.92e-03 1.70e+02 \n",
+ " 27 28 4.1859e+05 1.79e+00 1.41e-02 2.35e+02 \n",
+ " 28 29 4.1859e+05 1.71e+00 9.65e-03 1.57e+02 \n",
+ " 29 30 4.1859e+05 1.86e+00 1.53e-02 2.64e+02 \n",
+ " 30 31 4.1859e+05 1.61e+00 8.35e-03 1.11e+02 \n",
+ " 31 32 4.1859e+05 1.62e+00 1.44e-02 2.71e+02 \n",
+ " 32 33 4.1859e+05 1.50e+00 7.60e-03 9.34e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 33, initial cost 2.0189e+06, final cost 4.1859e+05, first-order optimality 9.34e+01.\n",
+ "mean reprojection error: 8.486325964905733\n",
+ "max reprojection error: 30.167549332567813\n",
+ "mean reconstruction error: 0.7507895219703264\n",
+ "max reconstruction error: 3.116007122632202\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 38,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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p59+Stu2bfnyyy+54IILiI+PZ9CgQfnKhBvqJtxIybVq1QqO6vyrX/2KUaNGFSpzwQUX8PLLL3PLLbfw+eefA7B06VKWLl1Kz549gcDD93bs2FEojjwffPAB69at49xzzwXgu+++C47jVLt2bS6//PJg2dDpFStWcNlllwVHyB41ahSffPIJI0aMoH379vlGjF68eHHYbUNg4E2ApKQkEhMTg4NuduzYkT179rBixYoi43vppZeYPXs2OTk5ZGVlsW3bNpKTk4PxAPTq1YtXX3210HajGWgy0s8MAknHpk2b2L9/P5deeilXXHEFZ5xxBo8//jiLFy+mb9++PPLII9x5553MnTs337rvv/8+EydODCZNoYNMhh6n48eP07hxYxo3bkz9+vU5cuRIvlG+y5OSGRGRGibvv/BWrVpx2WWXsXr16kJJRFxcXL5LL3v37o1oAMZwX54nT54kPT2dBg0akJ2dTVxcHM457r77biZMmBBRzM45xo0bxx/+8IdCy+rXr5+vX0zodHHjD+YlOJHIuyxTq1at4Pu86ZycnCLj27lzJ48++ihr1qyhefPmpKamcuLEiUL11q5dm5ycnELbzczMDCaLBS1btixfctCyZUuOHDlCTk4OderUiegza9u2LYmJiXzyySecd955fP755/Tt2xeA0aNHM2zYsELrOOeKTJJKOk6xomRGRKQSZWZnRtVxt6S6urToUmyZb7/9lpMnT9K4cWO+/fZbli5dGvYSwIgRI5g5cyZjxowhLS2Npk2bBlsjQp08eZJXXnmFMWPG8MILLzBgwIBCZR5//HESEhJ48MEHue6661i5ciVDhw7l97//Pddccw2NGjVi37591K1bt8hRs4cMGcLIkSO54447aNWqFdnZ2XzzzTcljpo9aNAgUlNTmTJlCs45XnvtNZ599tli1ymNouI7duwYDRs2pGnTphw8eJAlS5YwePDgiOuNpmXGzDj//PODn8eCBQsYOXJkoXJ79+7ltNNOo0GDBnz99dd8+umn3HnnnTRv3pyjR4+yfft2zjnnHN57772wg6JeeOGFzJo1i8GDB1OnTh2ys7Pztc5UBiUzIiKVJL5FfLnW16VFlxLrPHjwIJdddhkAOTk5/Pu//3vwv++8TpoTJ05k+PDhLF68mE6dOnHqqacyb174O64aNmzI1q1b6dWrF02bNmXhwoX5lm/fvp25c+eyevVqGjduzKBBg5gxYwbTp08nPT2d/v37A4FOvM8991yRyUzXrl2ZMWMGF154ISdPnqRu3bo88cQTJSYzKSkppKam0qdPHwBuuOEGevbsya5duwqVHT58OHPnzo2oBSrS+Pr160fPnj1JTEykY8eO/PznP4+67mg8/PDDjBkzhnvuuYeePXty/fXXA7B27VpmzZrF3LlzSU9P56677sLMcM4FO/MCzJkzh8svv5xatWrRvHlz/vrXvxbaxg033MD27dtJTk6mbt263Hjjjdx6660x3a+SWHFNcBWld+/ebu3atRW6zdFPrcw3vXBC/wrdvojUTOnp6WH/2/WrRo0aabBJiYlwvytmts45V+jhSLqbSURERHxNyYyIiJSaWmWkKlAyIyIiIr6mZEZERER8TXczxUBpR8LVaLciIiLRUzITA3kj4Zb0vIdQ5Tlyroj4w4EHH+T79LKNx1NQvYR4Wk+dWq51ilR1SmZiJNqRcMvroVki4h/fp2dwIiOD+vHl87yZExEOVHjdddfx1ltv0apVK7Zs2RKcn52dzejRo9m1axcdOnTgpZdeonnz5oXWf+edd/j1r39Nbm4uN9xwQ9jxe4qydu1annnmGf73f/834nXypKam8stf/jI4kKJEzjnHr3/9axYvXsypp57K/PnzSUlJKVRu4MCBfPPNNwB8+eWX9OnTh9dff51ly5YxcuRIzjrrLCAwDEOsx1uKhpIZEZFKVD8+nvbPPlMude2+dmxE5VJTU7n11lsZOzZ/+YceeoghQ4YwZcoUHnroIR566CEefvjhfGVyc3O55ZZbeO+994iLi+Pcc89lxIgRdO3aNaJt9+7dm969Cz0mJObyHvFf1HSk6/nVkiVL2LFjBzt27CAtLY1JkyaRlpZWqNwnn3wSfH/55Zfne4LwwIEDeeuttyok3mipA7CISA0zaNCgsI+fX7RoEePGjQNg3LhxvP7664XKrF69mk6dOtGxY0dOOeUUxowZw6JFiwqVS01NZeLEiQwcOJBzzjkn+CW4bNkyfvnLXwJw++23c//99wPw7rvvMmjQIE6ePMm6des477zz6NWrF0OHDiUrK6vY/fnHP/7BsGHD6NWrFwMHDiTDa6FKTU3lzjvv5Pzzz2fy5MmFpjdu3Ei/fv1ITk7msssu4+uvvwZg8ODBTJ06lfPOO4//+Z//KXK78+fP59JLL+WSSy7hrLPOYubMmTz22GP07NmTfv36kZ2dXWx8b775Jn379qVnz5784he/4ODBgwDcd999XHfddQwePJiOHTuWqhWroEWLFjF27FjMjH79+nHkyJFij+s333zDhx9+yKWXXhrVdt555x1SUlLo3r07Q4YMAQL7M27cOC688EI6dOjAq6++ym9/+1uSkpIYNmwYP/74Y1l2DVAyIyIinoMHDwbHX2rTpg1ffvlloTL79u2jXbt2wem4uDj27dsXtr5du3bx8ccf8/bbbzNx4sR8AyxCoCVo4cKFfPTRR9x+++3MmzeP3NxcbrvtNl555RXWrVvHddddx+9+97ti477pppv485//zLp163j00Ue5+eabg8u2b9/O+++/zx//+MdC02PHjuXhhx9m06ZNJCUlMX369OB6R44c4eOPP+auu+5i1qxZwaEeCtqyZQsvvPACq1ev5ne/+x2nnnoqGzZsoH///jzzzDPFxjdgwABWrVrFhg0bGDNmDP/93/8drDcjI4N3332X1atXM3369LBf+KNHj6ZHjx6FXnnbDRXN5wbw2muvMWTIEJo0aRKct3LlSrp3785FF13E1q1bC61z6NAhbrzxRv7+97/z+eef8/LLLweX/eMf/+Dtt99m0aJF/OpXv+L8889n8+bNNGjQgLfffrvIOCLl/7azirJkChzYXHyZ1klw0UMVE4+ISCUINwROUSMoX3XVVdSqVYvOnTvTsWPHYItEnlNPPZU5c+YwaNAgHn/8cc4++2y2bNnCli1buOCCC4DAZa1wA1zmOX78OJ999hlXXnllcN73338ffH/llVfmG1E7b/ro0aMcOXKE8847Dwi0RIXWETpS9cSJE4vc/vnnn0/jxo1p3LgxTZs25ZJLLgEgKSmJTZs2FRvf3r17GT16NFlZWfzwww/B/igAF198MfXq1aNevXq0atWKgwcPEhcXl2/bBcfBKk40nxvA3/72N2644YbgdEpKCrt376ZRo0YsXryYSy+9lB07duRbZ9WqVQwaNCi4H6GtfxdddBF169YlKSmJ3Nzc4HhgSUlJYcfJilaJyYyZ1QeWA/W88q845+41sxbAQqADsAu4yjn3tbfO3cD1QC5wu3Pu3TJHWtkObA68WicVvVxExMfOOOMMsrKyaNOmDVlZWWEHfYyLi2PPnj3B6b179xY5MGPBL8twX56bN2/mtNNOY//+/UDgSzcxMZGVK1cWKhvOyZMnadasWZEjSzds2LDY6aJEWq5evXrB97Vq1QpO16pVi5ycnGLju+2227jzzjsZMWIEy5Yt47777gtbb+3atcnJySm0/ujRo8nMLHwn7J133lmoP1Q0n9vhw4dZvXo1r732WnBeaAvN8OHDufnmm/nqq69o2bJlcL5zrsgEKfS41K1bN1gu7ziVVSQtM98D/+acO25mdYEVZrYEGAV84Jx7yMymAFOAyWbWFRgDJAJtgffN7BznXG6Zo61srZNgfBHNYfMurthYRKRaOJGREXHH3UjqKsudUSNGjGDBggVMmTKFBQsW5Ov8mefcc89lx44d7Ny5kzPPPJMXX3yRF154IWx9L7/8MuPGjWPnzp3885//pEuXLqxatSq4fPfu3fzxj39kw4YNDB8+nEsvvZSePXty6NAhVq5cSf/+/fnxxx/Zvn07iYmJYbfRpEkTzjrrLF5++WWuvPJKnHNs2rSJ7t27F7uvTZs2pXnz5nzyyScMHDiQZ599NthKU56Ki+/o0aOceeaZACxYsCDquqNpmRkxYgQzZ85kzJgxpKWl0bRp0yJbvF5++WV++ctfUr9+/eC8AwcOcMYZZ2BmrF69mpMnT3LaaaflW69///7ccsst7Ny5k7POOovs7OywfbNiocQ+My4gb/CNut7LASOBvKO/ALjUez8SeNE5971zbifwBdCnPIMWEakO6iXEl9tt2RC4M6peQsn1XX311fTv35/MzEzi4uJ4+umnAZgyZQrvvfcenTt35r333gvecr1//36GDx8OQJ06dZg5cyZDhw4lISGBq666qshEo0uXLpx33nlcdNFFzJo1K9+Xo3OO66+/nkcffZS2bdvy9NNPc8MNN3Dy5EleeeUVJk+eTPfu3enRowefffZZsfvz/PPP8/TTT9O9e3cSExPDdkgOZ8GCBfznf/4nycnJbNy4schbjYvrMxOJouK77777uPLKKxk4cGC+Fo5YGD58OB07dqRTp07ceOONPPnkk/mW5bWMAbz44otcffXV+dZ/5ZVX6NatG927d+f222/nxRdfLNQKc/rppzN79mxGjRpF9+7d812qizULdx2tUCGz2sA6oBPwhHNuspkdcc41CynztXOuuZnNBFY5557z5j8NLHHOvVKgzpuAmwB+9rOf9dq9e3d5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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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KfHWRURqgNl/+5BdB46Va51d2jbh7su7lmudItVdLD0tbYC3zWw78D7whnPu73jJyhAz2w0M8adFRKSAXQeOsSur/JKWXVnHYkqCJk2aRKtWrejWLfoZfecct956K506dSI5OZktW7aUKJZZs2bx5ptvlmidPI0aNSrVegJ79uyhb9++dO7cmTFjxvDtt99GLLd48WI6d+5M586dWbx4cWj+uHHjiI+Pp1u3bkyaNImTJ09WVuhl45yrtEfv3r2diEhNsGvXrtDza+a/566Z/1651R1rfatXr3abN292Xbt2jVrm1VdfdcOHD3e5ublu3bp1rk+fPuUWZ3EaNmxY6nVzcnKKnI4kNzfXnTp1qtTbrE6uvvpq96c//ck559yUKVPco48+WqjMkSNHXIcOHdyRI0dcdna269Chg8vOznbOea97bm6uy83NdWPHjo24fmUIf5/kATa5KHmE7ogrInKaSk1NpUWLFkWWeeWVVxg/fjxmRr9+/Th69ChZWVmFyjVq1Ijbb7+dXr16MXjwYA4fPgxAWloaL7zwAl988QXx8fFkZmYCcO211/L4448D8Nvf/pYLLriA5ORk7r777mLjfvrpp+nTpw89evRgypQpnDp1KhTDrFmz6Nu3L+vWrSs0/eCDD9KtWze6devGww8/DMDevXtJTEzkpptuolevXnzyySdRtzto0CBuu+02UlNTSUxM5P3332f06NF07tyZO++8s9j4pk2bRkpKCl27ds23n+3bt+fuu++mV69eJCUlkZGRUWwbFMU5x1tvvcVVV10FwIQJE3j55ZcLlXv99dcZMmQILVq0oHnz5gwZMoTly5cDMGLECMwMM6NPnz7s27ev0PqnTp3ijjvuICkpieTkZP7whz+E9mfmzJn079+flJQUtmzZwrBhwzj//POZP39+mfatOEpaRERqsP3793PuueeGpuPi4ti/f3+hcl999RW9evViy5YtXHTRRcyePTvf8qZNmzJv3jzS0tJ47rnn+Pzzz7nhhhtYsWIFu3fvZuPGjWzbto3NmzezZs2aqPGkp6ezdOlS3n33XbZt20bt2rV55plnQjF069aNDRs2MGDAgHzTDRo0YNGiRWzYsIH169fz+OOPs3XrVgAyMzMZP348W7dupV27dowYMYIDBw5E3P4ZZ5zBmjVrmDp1KqNGjeKRRx5h586dPPnkkxw5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uO2220hNTSUxMZH333+f0aNH07lzZ+68885i45s2bRopKSmFerbat2/P3XffTa9evUhKSiIjo2x3RHfO8dZbb3HVVVcBMGHCBF5++eVC5V5//XWGDBlCixYtaN68OUOGDGH58uX5ynz55Ze89dZbEXtaTp06xR133EFSUhLJycn84Q9/CO3PzJkz6d+/PykpKWzZsoVhw4Zx/vnnh+62XFGUtIiInKZOnTpFjx49aNWqFUOGDKFv376Fyuzfv59zzz03NB0XF8f+/fsLlfvqq6/o1asXW7Zs4aKLLmL27Nn5ljdt2pR58+aRlpbGc889x+eff84NN9zAihUr2L17Nxs3bmTbtm1s3ryZNWvWRI05PT2dpUuX8u6777Jt2zZq167NM888E4qhW7dubNiwgQEDBuSbbtCgAYsWLWLDhg2sX7+exx9/nK1btwLeYITjx49n69attGvXjhEjRnDgwIGI2z/jjDNYs2YNU6dOZdSoUTzyyCPs3LmTJ598kiNHjhQZ329+8xs2bdrE9u3bWb16Ndu3bw/V27JlS7Zs2cK0adOYO3duoe1mZmaGTtcUfBw9ejRf2SNHjtCsWbPQ6MvRXrNYXtuXXnqJwYMH06RJ4WEhFixYwJ49e9i6dSvbt29n3LhxoWXnnnsu69atY+DAgaHEdf369YWGAihvOj0kInKaql27Ntu2bePo0aNcccUV7Ny5k27duuUrE2kol0g9MrVq1QqNQnzdddcxevToQmWGDBnC888/z80338wHH3wAeIP0rVixgp49ewLeTep2795NampqxJhXrlzJ5s2bQ+PlfP3116FximrXrs2VV16Zb//ypteuXcsVV1wRGtF59OjRvPPOO4wcOZJ27drlOy322muvRdw2eANIAiQlJdG1a9fQ4JEdO3bkk08+Ye3atVHj+/Of/8yCBQvIyckhKyuLXbt2kZycHIoHoHfv3rz44ouFtluSARNjfc1iKfenP/2JyZMnR9zOm2++ydSpU0PJUfhgieHtdPz4cRo3bkzjxo2pX78+R48ezTcqdXlS0iIicppr1qwZgwYNYvny5YWSlri4uHynTPbt2xfTQIKRPiRzc3NJT0+nQYMGZGdnExcXh3OOX/3qV0yZMiWmWJ1zTJgwITQacbj69evnu24lfLqocfTyEplY1KtXD/CStLznedM5OTlR49uzZw9z587l/fffp3nz5qSlpXHixIlC9dauXZucnJxC283MzAwlhQWtWrUqXxLQsmVLjh49Sk5ODnXq1In6msXFxbFq1arQ9L59+/KNPH3kyBE2btzISy+9FHG7zrmIr3P4/kRrp4qipEVEpDIc3BHTBbQx19U6qcgihw8fpm7dujRr1oyvv/6aN998k+nTC48MP3LkSObNm8fYsWPZsGEDTZs2DfUuhMvNzeWFF15g7NixPPvsswwYMKBQmYceeojExETuv/9+Jk2axLp16xg2bBh33XUX48aNo1GjRuzfv5+6detGHeV58ODBjBo1ittuu41WrVqRnZ3Nl19+Wewoz6mpqaSlpTFjxgycc7z00kssWbKkyHVKI1p8x44do2HDhjRt2pRDhw6xbNmyfAlCcUrS02JmXHzxxaHXY/HixREvpB02bBgzZ87k888/B7xer/Bk6/nnn+eyyy6jfv36EbczdOhQ5s+fz6BBg6hTpw7Z2dn5eluqgpIWEZGKVkyCUar6iqkzKyuLCRMmcOrUKXJzc7nmmmu47LLLAEIXS06dOpURI0bw2muv0alTJ84880wWLYo8kGvDhg358MMP6d27N02bNmXp0qX5ln/00UcsXLiQjRs30rhxY1JTU7nvvvuYPXs26enp9O/fH/Aupn366aejJi1dunThvvvuY+jQoeTm5lK3bl0eeeSRYpOWXr16kZaWRp8+fQCYPHkyPXv2ZO/evYXKjhgxgoULF8bUoxRrfP369aNnz5507dqVjh07cuGFF5a47pKYM2cOY8eO5c4776Rnz55cf/31AGzatIn58+ezcOFCWrRowV133RU6lTVr1qx8Scdzzz3HjBkzom5j8uTJfPTRRyQnJ1O3bl1uuOEGbrnllgrdr+JYUV1q5S0lJcVt2rSp0rZXXeWN0lzWUZ5Lu76IVLz09HQSExOrOoxy06hRIw2aKOUu0vvEzDY751Iildevh0RERCQQlLSIiEix1Msi1YGSFhEREQkEJS0iIiISCEpaREREJBD0k2cRkQo2Z+McMrLLNt5MQQktEpjep/B9V0ROZ+ppERGpYBnZGWRmZ5ZbfZnZmTElQe3btycpKYkePXqQkhLxF6Q457j11lvp1KkTycnJbNmypUSxzJo1izfffLNE6+TJG9BRSm7Pnj307duXzp07M2bMGL799tuI5YYPH06zZs1C9+jJM2/ePDp16oSZ8dlnn1VGyOVCPS2xWjbDuwtlcVonwSUPVHw8IhIo8S3iy+3eSnn3aorF22+/TcuWLaMuX7ZsGbt372b37t1s2LCBadOmsWHDhpjrv/fee2MuW55OnTqV75b+Bacjcc7hnKNWreB/X58+fTq33XYbY8eOZerUqTzxxBNMmzatULlf/OIX/Pvf/+axxx7LN//CCy/ksssuK9Fde6uD4L9yleXgjuKTlljKiIhUI6+88grjx4/HzOjXrx9Hjx4lKyurULlGjRpx++2306tXLwYPHszhw4cBQiP8fvHFF8THx5OZ6fUoXXvttTz++OMA/Pa3v+WCCy4gOTmZu+++u9iYnn76afr06UOPHj2YMmUKp06dCsUwa9Ys+vbty7p16wpNP/jgg3Tr1o1u3brx8MMPA7B3714SExO56aab6NWrV75xlgoaNGgQt912G6mpqSQmJvL+++8zevRoOnfuzJ133llsfNOmTSMlJYWuXbvm28/27dtz991306tXL5KSksjIKNupQuccb731FldddRUAEyZM4OWXX45YdvDgwTRu3LjQ/J49e9K+ffsit3Pq1CnuuOMOkpKSSE5O5g9/+ENof2bOnEn//v1JSUlhy5YtDBs2jPPPPz90t+WKoqSlJFonwcRXoz/K+1bdIiJlYGYMHTqU3r17s2DBgohl9u/fz7nnnhuajouLY//+/YXKffXVV/Tq1YstW7Zw0UUXMXv27HzLmzZtyrx580hLS+O5557j888/54YbbmDFihXs3r2bjRs3sm3bNjZv3syaNWuixpyens7SpUt599132bZtG7Vr1+aZZ54JxdCtWzc2bNjAgAED8k03aNCARYsWsWHDBtavX8/jjz/O1q1bAW8wwvHjx7N161batWvHiBEjOHDgQMTtn3HGGaxZs4apU6cyatQoHnnkEXbu3MmTTz7JkSNHiozvN7/5DZs2bWL79u2sXr2a7du3h+pt2bIlW7ZsYdq0acydO7fQdjMzM+nRo0fEx9GjR/OVPXLkCM2aNQuNvhztNSurBQsWsGfPHrZu3cr27dsZN25caNm5557LunXrGDhwYChxXb9+PbNmzSr3OMLp9JCIyGnq3XffpW3btnz66acMGTKEhIQEUlNT85WJNJRLpJF9a9WqFRqF+LrrrmP06NGFygwZMoTnn3+em2++mQ8++ADwBulbsWIF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naVLl/L2229z6623smjRIk6dOsVPf/pTXnjhBTZv3sykSZP49a9/XWTcN954I3/4wx/YvHkzc+fO5aabbgot++ijj3jzzTf53e9+V2h6/PjxzJkzh+3bt5OUlMTs2bND6x09epTVq1dz++235xveoKCdO3fy7LPPsnHjRn79619z5plnsnXrVvr3789TTz1VZHwDBgxg/fr1bN26lbFjx/Lf//3foXozMjJ4/fXX2bhxI7Nnz474wT5mzBh69OhR6JG33XAled0ATp48yZIlS0JDPIR74oknuOSSSwrNP3z4MDfccAN/+ctf+OCDD3j++edDy/7xj3/w6quv8sorr3Dddddx8cUXs2PHDho0aMCrrxZ9t/hYBL8vTEREyl2kIV6ijfh7zTXXUKtWLTp37kzHjh1DPQx5zjzzTB5//HFSU1N56KGHOP/889m5cyc7d+5kyJAhgHc6KtJAjXmOHz/Oe++9x9VXXx2a980334SeX3311flGgM6b/uKLLzh69CgXXXQR4PUshdcRPrLy1KlTo27/4osvpnHjxjRu3JimTZty+eWXA5CUlMT27duLjG/fvn2MGTOGrKwsvv32Wzp06BAqc+mll1KvXj3q1atHq1atOHToEHFxcfm2vXTp0qhxFVSS1w3gpptuIjU1lYEDB+ab//bbb/PEE0+wdu3aQuusX7+e1NTU0H6E9+Zdcskl1K1bl6SkJE6dOhVKhpKSkti7d2/M+xGNkhYRkRrme9/7HllZWbRp04asrKyIIy7HxcXxySefhKb37dtH27ZtI9ZX8EMx0ofkjh07OOuss0IDFTrn6Nq1K+vWrYsp5tzcXJo1axZ1JOSGDRsWOR1NrOXq1asXel6rVq3QdK1atcjJySkyvp/+9Kf8/Oc/Z+TIkaxatYp77rknYr21a9cmJyen0PpjxowhMzOz0Pyf//znha5XKsnrNnv2bA4fPsxjjz2Wb/727duZPHkyy5Yt46yzziq0nnMuaiIU3i5169YNlctrp7JS0iIiUglOZGTEfAFtLHXVTyh6lOeijBw5ksWLFzNjxgwWL17MqFGjCpW54IIL2L17N3v27OGcc87hueeeizrK7/PPP8+ECRPYs2cP//znP4mPj2f9+vWh5R9//DG/+93v2Lp1KyNGjOBHP/oRPXv25PDhw6xbt47+/ftz8uRJPvroI7p27RpxG02aNKFDhw48//zzXH311Tjn2L59O927dy9yX5s2bUrz5s155513GDhwIEuWLAn1upSnouL74osvOOeccwBYvHhxiesuSU/LyJEjmTdvHmPHjmXDhg00bdo0Yg/WwoULef3111m5ciW1an13pci//vUvRo8ezZIlS/j+978fcRv9+/fn5ptvZs+ePXTo0IHs7OyI105VhGKvaTGzc83sbTNLN7MPzez/+fPvMbP9ZrbNf4yo+HBFRIKnXmJCmZKMguonJFAvsfj6rr32Wvr3709mZiZxcXE88cQTAMyYMYM33niDzp0788YbbzBjxgwADhw4wIgR3r/yOnXqMG/ePIYNG0ZiYiLXXHNN1IQiPj6eiy66iEsuuYT58+dTv3790DLnHNdffz1z586lbdu2PPHEE0yePJnc3FxeeOEFpk+fTvfu3enRowfvvfdekfvzzDPP8MQTT9C9e3e6du0a8cLgSBYvXswvfvELkpOT2bZtG7NmzYpYrqhrWmIRLb577rmHq6++moEDB9KyZctS1x+LESNG0LFjRzp16sQNN9zAo48+mm9ZXk/X1KlTOXToEP3796dHjx6hC6Xvvfdejhw5wk033USPHj0i/gLs7LPPZsGCBYwePZru3bvnO8VW0SzS+a98BczaAG2cc1vMrDGwGfgRcA1w3Dk3N9aNpaSkuE2bNpUh3Cq06FLv78QiLiSKpQwwcflEr/jwRaUKpazri0jFS09PJzExsarDqHBpaWlcdtllXHXVVVUdigRQpPeJmW12zkX8vXyxp4ecc1lAlv/8SzNLB84ph1hFREREYlaia1rMrD3QE9gAXAjcYmbjgU3A7c65QrdVNLMbgRsBzjvvvLLGKyIi1ciTTz5Z1SFIDRLzfVrMrBHwF+BnzrljwP8C5wM98HpifhdpPefcAudcinMu5eyzzy57xCIiAVHc6XeRmqw074+YkhYzq4uXsDzjnHvR39gh59wp51wu8DjQp8RbFxE5TdWvX58jR44ocRGJwDnHkSNH8l20HYtiTw+Z9yPrJ4B059yDYfPb+Ne7AFwB7CzRlkVETmNxcXHs27ePw4cPV3UoItVS/fr1C91IrzixXNNyIfATYIeZbfPnzQSuNbMegAP2AlNKtGURkdNY3bp18935VETKLpZfD60FIt367rXyD0dEREQkMg2YKCIiIoGgpEVEREQCQUmLiIiI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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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MWJE1DTLli1j27ZtbNu2jYyMDMaNG0dGRkbMZbn//vtjTlueTp48SdWqVaNOR+KcwzlHlSrB/30+adIkJk6cSFpaGmPHjuXxxx9n3LhxBdLk5uYybdo01q9fj5nRtWtXBg4cSKNGjXjrrbdC6W644QYGDRp0pnehXAT/SIqICACpqak0bty42DQvvfQSI0aMwMzo2bMnBw4cICcnp0i6uLg47rrrLlJSUujbty/79u0DvMDo+eef5+DBgyQkJJCdnQ3A8OHDmTNnDgC/+93vuPTSS0lKSmLq1Kkllvupp56ie/fuJCcnM2bMGE6ePBkqw5QpU+jRowdr1qwpMv3www/TqVMnOnXqxB/+8AcAduzYQfv27bnjjjtISUnh008/jZpvnz59mDhxIqmpqbRv35533nmHIUOG0K5dO+69994Syzdu3Di6detGx44dC+xn69atmTp1KikpKXTu3JmsrKwS66A4zjneeOMNbrzxRgBGjhzJiy++WCTdq6++Sr9+/WjcuDGNGjWiX79+vPLKKwXSfPnll7zxxhsRW1qOHDlCWloaSUlJDBs2jCNHjoSWLV++nF69epGSksLQoUM5fPgwAEuXLiUxMZHevXszYcIErr322tPa15IoaBEROY/s2rWLiy66KDQdHx/Prl27iqT76quvSElJYePGjVx++eVMmzatwPIGDRowc+ZM0tPTefbZZ/niiy/48Y9/zPLly9m2bRvr1q1j06ZNbNiwgVWrVkUtT2ZmJosWLeLtt99m06ZNVK1alYULF4bK0KlTJzIyMujdu3eB6dq1azNv3jwyMjJYu3Ytc+bM4d133wUgOzubESNG8O6779KqVSsGDBjA7t27I+Zfo0YNVq1axdixYxk0aBCPPvooW7ZsYf78+ezfv7/Y8v36179m/fr1bN68mTfffJPNmzeHttukSRM2btzIuHHjeOihh4rkm52dHbpcU/h14MCBAmn3799Pw4YNqVatWrHHLJZju2TJEvr27Uv9+vWLrP/nP/+ZOnXqsHnzZu655x42bNgAwOeff8706dNZsWIFGzdupFu3bjz88MMcPXqUMWPGsGzZMlavXh0KbCuSLg+JiJxHnHNF5kV6iqNKlSoMGzYMgB/96EcMGTKkSJp+/fqxePFixo8fz3vvvQd4v8iXL19Oly5dADh8+DDbtm0jNTU1Ynlef/11NmzY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cs7TPS0iIiISCApaREREJBAUtIiIiEggKGgRERGRQFDQIiIiIoGgoEVEREQCQUGLiIiIBIKCFhEREQkEBS0iIiISCApaREREJBAUtIiIiEggKGgRERGRQFDQIiIiIoGgoEVEREQCQUGLiIiIBIKCFhEREQkEBS0iIiISCApaREREJBAUtIiIiEggKGgRERGRQFDQIiIiIoGgoEVEREQCQUGLiIiIBIKCFhEREQkEBS0iIiISCApaREREJBAUtIiIiEggKGgRERGRQFDQIiIiIoGgoEVEREQCQUGLiIiIBEKJQYuZXWRm/zSzTDP7wMx+6s+/z8x2mdkm/zWg4osrIiIi56tqMaTJA+5yzm00s3rABjN7zV/2iHPuoYornoiIiIinxKDFOZcD5PjvvzSzTODCii5Yedqac4hhj60BoEPL+ky9rmPxKyybDHvej7zM9np/513j/W3eGa5+sJxKKiIiItGU6p4WM2sNdAEy/Fl3mtlmM/uLmTWKss7tZrbezNbv27fv9EpbBh1a1qdDi/qAF7xs3X2o5JX2vB89aClLOhERETltsVweAsDM4oC/Aj9zzh0ysz8D/wM4/+/vgdGF13POzQZmA3Tr1s2VR6FLI7xVJb+1JSbNO8OofxSd/8oo72//ed+0toiIiEiFi6mlxcyq4wUsC51zLwA45/Y65046504Bc4DuFVdMEREROd/F8vSQAY8Dmc65h8PmtwhLNhjYUv7FExEREfHEcnnoe8AtwPtmtsmfdzcw3MyS8S4P7QDGVED5RERERIDYnh5aDViERUvLvzgiIiIikalHXBEREQkEBS0iIiISCDE/8nyuGHlwFsybHpqeYV+QxfGCiU58BTXqfvN4c5js3GwSGidUdDFFRESkkPOupaVV3r8LdAiXxXGyCwctNep6rwgSGieQ2DixIosoIiIiEZx3LS1AwY7jXhlFAjCv/7xKLZKIiIgU77xraREREZFgUtAiIiIigaCgRURERAJBQYuIiIgEgoIWERERCQQFLSIiIhII5+cjz+eRo1lZfHLLiErJu2b7RJrffXel5C0iIuceBS3nsJrtK68TvKNZWZWWt4iInJsUtJzDKrOVo7Jad0RE5Nyle1pEREQkEBS0iIiISCAoaBEREZFAUNAiIiIigaCgRURERAJBQYuIiIgEwrnzyPOyybDnfQCm7D/ozZvXgD0r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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig_led_pos, ax_led_pos = make_fig(\"Reconstructed LED position error with {} cameras\".format(camera_count), \"Distance from true to reco. position [cm]\")\n",
+ "fig_mpmt_pos, ax_mpmt_pos = make_fig(\"Reconstructed mPMT position error with {} cameras\".format(camera_count), \"Distance from true to reco. position [cm]\")\n",
+ "fig_mpmt_ang, ax_mpmt_ang = make_fig(\"Reconstructed mPMT orientation error with {} cameras\".format(camera_count), \"Angle between true and reco. orientation [deg]\")\n",
+ "position_errors_8a = {}\n",
+ "centre_errors_8a = {}\n",
+ "orientation_errors_8a = {}\n",
+ "for pixel_error in [1.0, 3.0, 5.0, 10.0]:\n",
+ " print(\"=== Gaussian errors on feature image locations:\", pixel_error, \"===\")\n",
+ " smeared_feature_locations = simulator.get_image_feature_locations(area_restrict=image_area, min_feature_count=2, pixel_error=pixel_error)\n",
+ " led_positions_8a = {k: v for k, v in led_positions.items() if np.any([k in i.keys() for i in smeared_feature_locations.values()])}\n",
+ " fitter = setup_led_simulation(led_positions_8a, smeared_feature_locations, focal_length, principle_point, radial_distortion) \n",
+ " reco_led_positions, position_errors_8a[pixel_error] = run_led_fit(fitter, led_positions_8a)\n",
+ " centre_errors_8a[pixel_error] = get_mpmt_centre_errors(reco_led_positions, mpmt_locations, led_count)\n",
+ " orientation_errors_8a[pixel_error] = get_mpmt_orientation_errors(reco_led_positions, mpmt_orientations, led_count)\n",
+ " ax_led_pos.hist(position_errors_8a[pixel_error], bins=20, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} cm\".format(pixel_error, position_errors_8a[pixel_error].mean()))\n",
+ " ax_mpmt_pos.hist(centre_errors_8a[pixel_error], bins=15, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} cm\".format(pixel_error, centre_errors_8a[pixel_error].mean()))\n",
+ " ax_mpmt_ang.hist(orientation_errors_8a[pixel_error], bins=15, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} deg\".format(pixel_error, orientation_errors_8a[pixel_error].mean()))\n",
+ "ax_led_pos.legend(loc='upper right')\n",
+ "ax_mpmt_pos.legend(loc='upper right')\n",
+ "ax_mpmt_ang.legend(loc='upper right')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 39,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "reco_errors, reco_transformed, scale, R, translation, _ = fit.kabsch_errors(led_positions, reco_led_positions)\n",
+ "\n",
+ "reco_cam_orientations, reco_cam_positions = fit.camera_world_poses(fitter.camera_rotations, fitter.camera_translations)\n",
+ "cam_orientations_transformed = np.matmul(R, reco_cam_orientations)\n",
+ "cam_positions_translated = reco_cam_positions - translation\n",
+ "cam_positions_transformed = scale*R.dot(cam_positions_translated.transpose()).transpose()\n",
+ "\n",
+ "plot_reconstruction(reco_transformed, cam_positions_transformed)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 6 camera configuration A"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "camera_radial_position = 163.0\n",
+ "camera_halfz_position = 168.0\n",
+ "camera_positions = np.array([\n",
+ " [0, -camera_halfz_position, 0],\n",
+ " [0, camera_halfz_position, 0],\n",
+ " [camera_radial_position, 0, 0],\n",
+ " [-camera_radial_position, 0, 0],\n",
+ " [0, 0, camera_radial_position],\n",
+ " [0, 0, -camera_radial_position]])\n",
+ "camera_directions = [[0, 1, 0],\n",
+ " [0, -1, 0],\n",
+ " [-1, 0, 0],\n",
+ " [1, 0, 0],\n",
+ " [0, 0, -1],\n",
+ " [0, 0, 1]]\n",
+ "camera_directions = camera_directions / linalg.norm(camera_directions, axis=1, keepdims=True)\n",
+ "camera_rolls = np.array([0.0, np.pi/2, np.pi/2, np.pi/2, np.pi/2, np.pi/2])\n",
+ "camera_rotations, camera_translations = fit.camera_poses(camera_positions, camera_directions, camera_rolls)\n",
+ "camera_count = camera_positions.shape[0]\n",
+ "simulator = fit.PhotogrammetrySimulator(led_positions, focal_length, principle_point, camera_rotations, camera_translations, radial_distortion, tangential_distortion)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Total number of features: 1272\n",
+ "Number of features in more than one image: 1272\n",
+ "Feature in image counts: Counter({3: 568, 4: 400, 2: 192, 5: 68, 6: 44})\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "image_feature_locations = simulator.get_image_feature_locations(area_restrict = image_area, min_feature_count = 2)\n",
+ "feature_counts = Counter([f for i in image_feature_locations.values() for f in i.keys()])\n",
+ "feature_counts_counts = Counter(feature_counts.values())\n",
+ "print(\"Total number of features: \", len(led_positions))\n",
+ "print(\"Number of features in more than one image: \", sum(feature_counts_counts.values()))\n",
+ "print(\"Feature in image counts:\", feature_counts_counts)\n",
+ "simulator.show_images(image_feature_locations, area=image_area)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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GACJiAzMunXrcOfOHVy+fBnu7u7YtGkTAHCGLRF1GQZAIiID4+bmBktLS1hYWGD16tX627xSqRQFBQX68zjDlog6igGQiMjAlJSU6P+clJSk3yEsk8kQHx+PxsZG5OXlIScnB5MmTRKrTCIyYuJN6SYiIoSHhyM9PR2VlZWQSqXYsWMH0tPTcfnyZUgkEnh4eODjjz8GAPj6+mLhwoUYNWoUrKyscODAAe4AJqIOYRsYIiIiItPFNjBERERExABIREREZHYYAImIiIjMDAMgERERkZlhACQiIiIyMwyARERERGaGAZCIiIjIzDAAEhEREZkZBkAiIiIiM8MASERERGRmGACJiIiIzAwDIBEREZGZYQAkIiIiMjMMgERERERmhgGQiIiIyMwwABIRERGZGQZAIiIiIjPDAEhERERkZhgAiYiIiMwMAyARERGRmWEAJCIiIjIzDIBEREREZoYBkIiIiMjMMAASERERmRkGQCIiIiIzwwBIREREZGasnvO6pEeqICIiIqIewxVAIiIiIjPDAEhERERkZhgAiYiIiMwMAyARERGRmWEAJCIiIjIzDIBEREREZub/AT1ZjrjElh7wAAAAAElFTkSuQmCC\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "camera_orientations, camera_positions = fit.camera_world_poses(camera_rotations, camera_translations)\n",
+ "plot_geometry(led_positions, camera_positions)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 38,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "=== Gaussian errors on feature image locations: 1.0 ===\n",
+ "8 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 13.828063542394737 max: 218.27011488545185\n",
+ "image 1 reprojection errors: average: 14.266911731441311 max: 168.02572846508102\n",
+ "image 2 reprojection errors: average: 13.259631557103953 max: 159.2642398699781\n",
+ "image 3 reprojection errors: average: 13.422864585752475 max: 137.03572224565602\n",
+ "image 4 reprojection errors: average: 14.042001696393454 max: 177.2409590707412\n",
+ "image 5 reprojection errors: average: 14.419637448618259 max: 232.93124855660497\n",
+ "image 6 reprojection errors: average: 14.28349841175458 max: 95.76014743378593\n",
+ "image 7 reprojection errors: average: 13.816511440007561 max: 110.1203537367734\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 1.5083e+06 2.55e+06 \n",
+ " 1 2 5.9099e+03 1.50e+06 6.91e+01 9.53e+04 \n",
+ " 2 3 4.1487e+03 1.76e+03 7.89e-01 1.47e+03 \n",
+ " 3 4 4.1432e+03 5.47e+00 2.66e-01 8.32e+02 \n",
+ " 4 5 4.1421e+03 1.18e+00 3.87e-02 9.54e+01 \n",
+ " 5 6 4.1419e+03 1.74e-01 9.74e-03 3.51e+01 \n",
+ " 6 7 4.1418e+03 7.01e-02 4.36e-03 1.38e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 7, initial cost 1.5083e+06, final cost 4.1418e+03, first-order optimality 1.38e+01.\n",
+ "mean reprojection error: 0.8453353393586547\n",
+ "max reprojection error: 3.1669253825859003\n",
+ "mean reconstruction error: 0.07599713093701795\n",
+ "max reconstruction error: 0.35918856633649\n",
+ "=== Gaussian errors on feature image locations: 3.0 ===\n",
+ "8 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 14.186361973998029 max: 142.13279660962115\n",
+ "image 1 reprojection errors: average: 14.3430728296801 max: 114.57890349429739\n",
+ "image 2 reprojection errors: average: 14.030040315205252 max: 143.10725465392943\n",
+ "image 3 reprojection errors: average: 14.251753739436086 max: 183.5931418951843\n",
+ "image 4 reprojection errors: average: 14.207830844722821 max: 149.83951606976632\n",
+ "image 5 reprojection errors: average: 14.44821544767734 max: 124.8193940574816\n",
+ "image 6 reprojection errors: average: 13.708985116983074 max: 111.01284859340113\n",
+ "image 7 reprojection errors: average: 13.930256656976045 max: 135.84947501329322\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 1.4939e+06 2.77e+06 \n",
+ " 1 2 3.9147e+04 1.45e+06 6.89e+01 7.63e+04 \n",
+ " 2 3 3.8133e+04 1.01e+03 8.75e-01 6.73e+02 \n",
+ " 3 4 3.8086e+04 4.70e+01 8.20e-01 4.48e+02 \n",
+ " 4 5 3.8072e+04 1.33e+01 1.44e-01 3.80e+01 \n",
+ " 5 6 3.8071e+04 1.59e+00 4.35e-02 5.31e+01 \n",
+ " 6 7 3.8070e+04 7.30e-01 1.38e-02 2.72e+01 \n",
+ " 7 8 3.8070e+04 4.30e-01 1.15e-02 3.81e+01 \n",
+ " 8 9 3.8069e+04 3.75e-01 9.62e-03 4.53e+01 \n",
+ " 9 10 3.8069e+04 3.59e-01 9.64e-03 5.63e+01 \n",
+ " 10 11 3.8069e+04 1.91e-01 3.68e-03 3.71e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 11, initial cost 1.4939e+06, final cost 3.8069e+04, first-order optimality 3.71e+01.\n",
+ "mean reprojection error: 2.5564564934849114\n",
+ "max reprojection error: 9.98131009620747\n",
+ "mean reconstruction error: 0.2290003305014601\n",
+ "max reconstruction error: 1.0506093661635483\n",
+ "=== Gaussian errors on feature image locations: 5.0 ===\n",
+ "8 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 15.100127042494083 max: 160.51986142773094\n",
+ "image 1 reprojection errors: average: 14.658957672792338 max: 151.55699428817383\n",
+ "image 2 reprojection errors: average: 14.687438047915299 max: 77.94474483482014\n",
+ "image 3 reprojection errors: average: 14.67090740732709 max: 129.3577026301649\n",
+ "image 4 reprojection errors: average: 14.871906549459718 max: 245.14146882194805\n",
+ "image 5 reprojection errors: average: 15.002691746208708 max: 181.49916389261205\n",
+ "image 6 reprojection errors: average: 14.142437625710745 max: 130.7997569389291\n",
+ "image 7 reprojection errors: average: 15.023724647497383 max: 155.0864057338731\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 1.6006e+06 2.02e+06 \n",
+ " 1 2 1.0686e+05 1.49e+06 7.10e+01 7.35e+04 \n",
+ " 2 3 1.0555e+05 1.31e+03 1.24e+00 1.98e+03 \n",
+ " 3 4 1.0541e+05 1.40e+02 1.38e+00 1.30e+03 \n",
+ " 4 5 1.0536e+05 5.00e+01 2.58e-01 1.23e+02 \n",
+ " 5 6 1.0535e+05 6.83e+00 9.27e-02 9.59e+01 \n",
+ " 6 7 1.0535e+05 3.87e+00 4.56e-02 8.69e+01 \n",
+ " 7 8 1.0535e+05 1.69e+00 2.22e-02 6.17e+01 \n",
+ " 8 9 1.0535e+05 1.31e+00 1.96e-02 8.12e+01 \n",
+ " 9 10 1.0535e+05 1.28e+00 1.87e-02 8.80e+01 \n",
+ " 10 11 1.0535e+05 1.03e+00 1.38e-02 1.13e+02 \n",
+ " 11 12 1.0534e+05 7.43e-01 9.27e-03 9.66e+01 \n",
+ " 12 13 1.0534e+05 3.53e-01 3.94e-03 4.33e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 13, initial cost 1.6006e+06, final cost 1.0534e+05, first-order optimality 4.33e+01.\n",
+ "mean reprojection error: 4.2565467060174385\n",
+ "max reprojection error: 16.392380585922076\n",
+ "mean reconstruction error: 0.378511613097883\n",
+ "max reconstruction error: 1.7280389068962418\n",
+ "=== Gaussian errors on feature image locations: 10.0 ===\n",
+ "8 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 17.09867179575005 max: 118.48103903261772\n",
+ "image 1 reprojection errors: average: 17.363731455254754 max: 155.74102883809007\n",
+ "image 2 reprojection errors: average: 16.937621673918557 max: 107.22656681795047\n",
+ "image 3 reprojection errors: average: 16.897941538151336 max: 104.96684275768155\n",
+ "image 4 reprojection errors: average: 17.939475068224173 max: 252.947133817352\n",
+ "image 5 reprojection errors: average: 17.62125191913709 max: 98.61883188730926\n",
+ "image 6 reprojection errors: average: 17.390697365602733 max: 135.27484877400363\n",
+ "image 7 reprojection errors: average: 17.61046441629536 max: 152.50414170677618\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 2.0189e+06 2.49e+06 \n",
+ " 1 2 4.2301e+05 1.60e+06 7.52e+01 2.75e+05 \n",
+ " 2 3 4.1944e+05 3.57e+03 2.99e+00 1.15e+04 \n",
+ " 3 4 4.1905e+05 3.90e+02 1.68e+00 2.64e+03 \n",
+ " 4 5 4.1885e+05 2.06e+02 5.72e-01 7.90e+02 \n",
+ " 5 6 4.1880e+05 4.98e+01 2.50e-01 5.96e+02 \n",
+ " 6 7 4.1876e+05 3.86e+01 1.87e-01 3.64e+02 \n",
+ " 7 8 4.1873e+05 2.71e+01 1.48e-01 4.46e+02 \n",
+ " 8 9 4.1871e+05 2.13e+01 1.09e-01 3.56e+02 \n",
+ " 9 10 4.1870e+05 1.04e+01 5.10e-02 1.98e+02 \n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " 10 11 4.1869e+05 1.00e+01 7.13e-02 3.50e+02 \n",
+ " 11 12 4.1868e+05 9.55e+00 4.88e-02 1.88e+02 \n",
+ " 12 13 4.1867e+05 8.06e+00 5.82e-02 2.89e+02 \n",
+ " 13 14 4.1866e+05 8.05e+00 4.57e-02 1.85e+02 \n",
+ " 14 15 4.1866e+05 7.56e+00 5.46e-02 2.60e+02 \n",
+ " 15 16 4.1865e+05 7.38e+00 4.38e-02 1.69e+02 \n",
+ " 16 17 4.1864e+05 7.17e+00 5.24e-02 2.90e+02 \n",
+ " 17 18 4.1863e+05 6.95e+00 4.21e-02 1.71e+02 \n",
+ " 18 19 4.1863e+05 6.47e+00 4.73e-02 3.32e+02 \n",
+ " 19 20 4.1862e+05 6.56e+00 4.09e-02 2.12e+02 \n",
+ " 20 21 4.1862e+05 5.75e+00 4.01e-02 3.53e+02 \n",
+ " 21 22 4.1861e+05 6.16e+00 4.02e-02 2.93e+02 \n",
+ " 22 23 4.1860e+05 5.53e+00 3.55e-02 3.70e+02 \n",
+ " 23 24 4.1860e+05 3.24e+00 1.78e-02 2.04e+02 \n",
+ " 24 25 4.1860e+05 1.70e+00 1.02e-02 1.79e+02 \n",
+ " 25 26 4.1860e+05 1.76e+00 1.34e-02 2.15e+02 \n",
+ " 26 27 4.1860e+05 1.69e+00 9.92e-03 1.70e+02 \n",
+ " 27 28 4.1859e+05 1.79e+00 1.41e-02 2.35e+02 \n",
+ " 28 29 4.1859e+05 1.71e+00 9.65e-03 1.57e+02 \n",
+ " 29 30 4.1859e+05 1.86e+00 1.53e-02 2.64e+02 \n",
+ " 30 31 4.1859e+05 1.61e+00 8.35e-03 1.11e+02 \n",
+ " 31 32 4.1859e+05 1.62e+00 1.44e-02 2.71e+02 \n",
+ " 32 33 4.1859e+05 1.50e+00 7.60e-03 9.34e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 33, initial cost 2.0189e+06, final cost 4.1859e+05, first-order optimality 9.34e+01.\n",
+ "mean reprojection error: 8.486325964905733\n",
+ "max reprojection error: 30.167549332567813\n",
+ "mean reconstruction error: 0.7507895219703264\n",
+ "max reconstruction error: 3.116007122632202\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 38,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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p59+Stu2bfnyyy+54IILiI+PZ9CgQfnKhBvqJtxIybVq1QqO6vyrX/2KUaNGFSpzwQUX8PLLL3PLLbfw+eefA7B06VKWLl1Kz549gcDD93bs2FEojjwffPAB69at49xzzwXgu+++C47jVLt2bS6//PJg2dDpFStWcNlllwVHyB41ahSffPIJI0aMoH379vlGjF68eHHYbUNg4E2ApKQkEhMTg4NuduzYkT179rBixYoi43vppZeYPXs2OTk5ZGVlsW3bNpKTk4PxAPTq1YtXX3210HajGWgy0s8MAknHpk2b2L9/P5deeilXXHEFZ5xxBo8//jiLFy+mb9++PPLII9x5553MnTs337rvv/8+EydODCZNoYNMhh6n48eP07hxYxo3bkz9+vU5cuRIvlG+y5OSGRGRGibvv/BWrVpx2WWXsXr16kJJRFxcXL5LL3v37o1oAMZwX54nT54kPT2dBg0akJ2dTVxcHM457r77biZMmBBRzM45xo0bxx/+8IdCy+rXr5+vX0zodHHjD+YlOJHIuyxTq1at4Pu86ZycnCLj27lzJ48++ihr1qyhefPmpKamcuLEiUL11q5dm5ycnELbzczMDCaLBS1btixfctCyZUuOHDlCTk4OderUiegza9u2LYmJiXzyySecd955fP755/Tt2xeA0aNHM2zYsELrOOeKTJJKOk6xomRGRKQSZWZnRtVxt6S6urToUmyZb7/9lpMnT9K4cWO+/fZbli5dGvYSwIgRI5g5cyZjxowhLS2Npk2bBlsjQp08eZJXXnmFMWPG8MILLzBgwIBCZR5//HESEhJ48MEHue6661i5ciVDhw7l97//Pddccw2NGjVi37591K1bt8hRs4cMGcLIkSO54447aNWqFdnZ2XzzzTcljpo9aNAgUlNTmTJlCs45XnvtNZ599tli1ymNouI7duwYDRs2pGnTphw8eJAlS5YwePDgiOuNpmXGzDj//PODn8eCBQsYOXJkoXJ79+7ltNNOo0GDBnz99dd8+umn3HnnnTRv3pyjR4+yfft2zjnnHN57772wg6JeeOGFzJo1i8GDB1OnTh2ys7Pztc5UBiUzIiKVJL5FfLnW16VFlxLrPHjwIJdddhkAOTk5/Pu//3vwv++8TpoTJ05k+PDhLF68mE6dOnHqqacyb174O64aNmzI1q1b6dWrF02bNmXhwoX5lm/fvp25c+eyevVqGjduzKBBg5gxYwbTp08nPT2d/v37A4FOvM8991yRyUzXrl2ZMWMGF154ISdPnqRu3bo88cQTJSYzKSkppKam0qdPHwBuuOEGevbsya5duwqVHT58OHPnzo2oBSrS+Pr160fPnj1JTEykY8eO/PznP4+67mg8/PDDjBkzhnvuuYeePXty/fXXA7B27VpmzZrF3LlzSU9P56677sLMcM4FO/MCzJkzh8svv5xatWrRvHlz/vrXvxbaxg033MD27dtJTk6mbt263Hjjjdx6660x3a+SWHFNcBWld+/ebu3atRW6zdFPrcw3vXBC/wrdvojUTOnp6WH/2/WrRo0aabBJiYlwvytmts45V+jhSLqbSURERHxNyYyIiJSaWmWkKlAyIyIiIr6mZEZERER8TXczxUBpR8LVaLciIiLRUzITA3kj4Zb0vIdQ5Tlyroj4w4EHH+T79LKNx1NQvYR4Wk+dWq51ilR1SmZiJNqRcMvroVki4h/fp2dwIiOD+vHl87yZExEOVHjdddfx1ltv0apVK7Zs2RKcn52dzejRo9m1axcdOnTgpZdeonnz5oXWf+edd/j1r39Nbm4uN9xwQ9jxe4qydu1annnmGf73f/834nXypKam8stf/jI4kKJEzjnHr3/9axYvXsypp57K/PnzSUlJKVRu4MCBfPPNNwB8+eWX9OnTh9dff51ly5YxcuRIzjrrLCAwDEOsx1uKhpIZEZFKVD8+nvbPPlMude2+dmxE5VJTU7n11lsZOzZ/+YceeoghQ4YwZcoUHnroIR566CEefvjhfGVyc3O55ZZbeO+994iLi+Pcc89lxIgRdO3aNaJt9+7dm969Cz0mJObyHvFf1HSk6/nVkiVL2LFjBzt27CAtLY1JkyaRlpZWqNwnn3wSfH/55Zfne4LwwIEDeeuttyok3mipA7CISA0zaNCgsI+fX7RoEePGjQNg3LhxvP7664XKrF69mk6dOtGxY0dOOeUUxowZw6JFiwqVS01NZeLEiQwcOJBzzjkn+CW4bNkyfvnLXwJw++23c//99wPw7rvvMmjQIE6ePMm6des477zz6NWrF0OHDiUrK6vY/fnHP/7BsGHD6NWrFwMHDiTDa6FKTU3lzjvv5Pzzz2fy5MmFpjdu3Ei/fv1ITk7msssu4+uvvwZg8ODBTJ06lfPOO4//+Z//KXK78+fP59JLL+WSSy7hrLPOYubMmTz22GP07NmTfv36kZ2dXWx8b775Jn379qVnz5784he/4ODBgwDcd999XHfddQwePJiOHTuWqhWroEWLFjF27FjMjH79+nHkyJFij+s333zDhx9+yKWXXhrVdt555x1SUlLo3r07Q4YMAQL7M27cOC688EI6dOjAq6++ym9/+1uSkpIYNmwYP/74Y1l2DVAyIyIinoMHDwbHX2rTpg1ffvlloTL79u2jXbt2wem4uDj27dsXtr5du3bx8ccf8/bbbzNx4sR8AyxCoCVo4cKFfPTRR9x+++3MmzeP3NxcbrvtNl555RXWrVvHddddx+9+97ti477pppv485//zLp163j00Ue5+eabg8u2b9/O+++/zx//+MdC02PHjuXhhx9m06ZNJCUlMX369OB6R44c4eOPP+auu+5i1qxZwaEeCtqyZQsvvPACq1ev5ne/+x2nnnoqGzZsoH///jzzzDPFxjdgwABWrVrFhg0bGDNmDP/93/8drDcjI4N3332X1atXM3369LBf+KNHj6ZHjx6FXnnbDRXN5wbw2muvMWTIEJo0aRKct3LlSrp3785FF13E1q1bC61z6NAhbrzxRv7+97/z+eef8/LLLweX/eMf/+Dtt99m0aJF/OpXv+L8889n8+bNNGjQgLfffrvIOCLl/7azirJkChzYXHyZ1klw0UMVE4+ISCUINwROUSMoX3XVVdSqVYvOnTvTsWPHYItEnlNPPZU5c+YwaNAgHn/8cc4++2y2bNnCli1buOCCC4DAZa1wA1zmOX78OJ999hlXXnllcN73338ffH/llVfmG1E7b/ro0aMcOXKE8847Dwi0RIXWETpS9cSJE4vc/vnnn0/jxo1p3LgxTZs25ZJLLgEgKSmJTZs2FRvf3r17GT16NFlZWfzwww/B/igAF198MfXq1aNevXq0atWKgwcPEhcXl2/bBcfBKk40nxvA3/72N2644YbgdEpKCrt376ZRo0YsXryYSy+9lB07duRbZ9WqVQwaNCi4H6GtfxdddBF169YlKSmJ3Nzc4HhgSUlJYcfJilaJyYyZ1QeWA/W88q845+41sxbAQqADsAu4yjn3tbfO3cD1QC5wu3Pu3TJHWtkObA68WicVvVxExMfOOOMMsrKyaNOmDVlZWWEHfYyLi2PPnj3B6b179xY5MGPBL8twX56bN2/mtNNOY//+/UDgSzcxMZGVK1cWKhvOyZMnadasWZEjSzds2LDY6aJEWq5evXrB97Vq1QpO16pVi5ycnGLju+2227jzzjsZMWIEy5Yt47777gtbb+3atcnJySm0/ujRo8nMLHwn7J133lmoP1Q0n9vhw4dZvXo1r732WnBeaAvN8OHDufnmm/nqq69o2bJlcL5zrsgEKfS41K1bN1gu7ziVVSQtM98D/+acO25mdYEVZrYEGAV84Jx7yMymAFOAyWbWFRgDJAJtgffN7BznXG6Zo61srZNgfBHNYfMurthYRKRaOJGREXHH3UjqKsudUSNGjGDBggVMmTKFBQsW5Ov8mefcc89lx44d7Ny5kzPPPJMXX3yRF154IWx9L7/8MuPGjWPnzp3885//pEuXLqxatSq4fPfu3fzxj39kw4YNDB8+nEsvvZSePXty6NAhVq5cSf/+/fnxxx/Zvn07iYmJYbfRpEkTzjrrLF5++WWuvPJKnHNs2rSJ7t27F7uvTZs2pXnz5nzyyScMHDiQZ599NthKU56Ki+/o0aOceeaZACxYsCDquqNpmRkxYgQzZ85kzJgxpKWl0bRp0yJbvF5++WV++ctfUr9+/eC8AwcOcMYZZ2BmrF69mpMnT3LaaaflW69///7ccsst7Ny5k7POOovs7OywfbNiocQ+My4gb/CNut7LASOBvKO/ALjUez8SeNE5971zbifwBdCnPIMWEakO6iXEl9tt2RC4M6peQsn1XX311fTv35/MzEzi4uJ4+umnAZgyZQrvvfcenTt35r333gvecr1//36GDx8OQJ06dZg5cyZDhw4lISGBq666qshEo0uXLpx33nlcdNFFzJo1K9+Xo3OO66+/nkcffZS2bdvy9NNPc8MNN3Dy5EleeeUVJk+eTPfu3enRowefffZZsfvz/PPP8/TTT9O9e3cSExPDdkgOZ8GCBfznf/4nycnJbNy4schbjYvrMxOJouK77777uPLKKxk4cGC+Fo5YGD58OB07dqRTp07ceOONPPnkk/mW5bWMAbz44otcffXV+dZ/5ZVX6NatG927d+f222/nxRdfLNQKc/rppzN79mxGjRpF9+7d812qizULdx2tUCGz2sA6oBPwhHNuspkdcc41CynztXOuuZnNBFY5557z5j8NLHHOvVKgzpuAmwB+9rOf9dq9e3d57VNERj+Vvwlz4YT+xa+Q1/JSUsvM+LeDz4wpzXNmollHRPwnPT2dhISEyg4j5vRMGCmrcL8rZrbOOVfo3v6I7mZyzuU653oAcUAfM+tWTPFwF8wKZUzOudnOud7Oud6nn356JGGIiIiIFBLV3UzOuSNmtgwYBhw0szbOuSwzawPk3cO3F2gXslocsB8REakx5s+fX9khSA1SYsuMmZ1uZs289w2AXwAZwBvAOK/YOCDvIuUbwBgzq2dmZwGdgdXlHLeIiG9FcnlfpCaL9nckkpaZNsACr99MLeAl59xbZrYSeMnMrgf+D7jSC2Crmb0EbANygFuqxZ1MIiLloH79+hw+fJjTTjut2Od8iNRUzjkOHz6cr8N4SUpMZpxzm4CeYeYfBoYUsc4DwAMRRyEiUkPExcWxd+9eDh06VNmhiFRZ9evXL/SQwOLoCcAiIhWobt26+Z70KiJlp2TGZw48+CDfp2eUXLCU6iXE03rq1JjVLyIiUt400KTPfJ+ewYmM2CQzJzIyYpooiYiIxIJaZnyofnw87Z8tPCpqWZXXI9VFREQqklpmRERExNeUzIiIiIivKZkRERERX1MyIyIiIr6mZEZERER8TcmMiIiI+JqSGREREfE1JTMiIiLia0pmRERExNeUzIiIiIivKZkRERERX9PYTHmWTIEDm4tefmAztE6quHhEREQkImqZyXNgc/HJTOskJTMiIiJVkFpmQrVOgvFvV3YUIiIiEgW1zIiIiIivKZkRERERX1MyIyIiIr6mZEZERER8TcmMiIiI+JqSGREREfE13ZpdhWRmZzL+nfHFlhmTnQHAfV65+BbxTO4zOeaxiYiIVFVKZqqI+BbxUa+TmZ0Zg0hERET8RclMFRFp68ru58cCMG/YvBJbcURERGoC9ZkRERERX1PLTHk6sBnmXQx2MDA97+KflrVOgoseqpy4REREqjElM+WluEEoixvAUkRERMpEyUx5CW11yevLMmxe4GdoC00VdyIjg93Xjo1Z/fUS4mk9dWrM6hcRkZpHyYwE1UuI/o6qaJzIyIhp/SIiUjMpmZGgWLeYxLLFR0REai4lMyV4ePXDZGRH16KQmZ1JlxZdYhSRiIiIhKpRycz0N7eybf8xALZlHaNrmyYlrpORnRF1ctKlRZdSPQRPREREolejkplt+48Fk5iubZrQtW2TYHJTnC4tujAvrzOviIiIVCk1KpkB6NqmCQsn9A9Oj35qZSVGIyIiImWlJwCLiIiIrymZEREREV9TMiMiIiK+pmRGREREfK3EZMbM2pnZR2aWbmZbzezX3vz7zGyfmW30XsND1rnbzL4ws0wzGxrLHRAREZGaLZK7mXKAu5xz682sMbDOzN7zlj3unHs0tLCZdQXGAIlAW+B9MzvHOZdbnoGLiIiIQAQtM865LOfceu/9N0A6cGYxq4wEXnTOfe+c2wl8AfQpj2BFRERECoqqz4yZdQB6AmnerFvNbJOZ/dXMmnvzzgT2hKy2lzDJj5ndZGZrzWztoUOHoo9cREREhCiSGTNrBPwd+A/n3DHgL8DZQA8gC/hjXtEwq7tCM5yb7Zzr7Zzrffrpp0cbt4iIiAgQYTJjZnUJJDLPO+deBXDOHXTO5TrnTgJz+OlS0l6gXcjqccD+8gtZRERE5CeR3M1kwNNAunPusZD5bUKKXQZs8d6/AYwxs3pmdhbQGVhdfiGLiIiI/CSSu5l+DlwLbDazjd68qcDVZtaDwCWkXcAEAOfcVjN7CdhG4E6oW3Qnk4iIiMRKicmMc24F4fvBLC5mnQeAB8oQl4iIiEhE9ARgERER8TUlMyIiIuJrSmZERETE15TMANuyjrE16yhbs44y/c2tlR2OiIiIRCGSu5mqta5tmwTeHIZ//ZDLtv3HKjcgERERiUqNT2buvSQx8GZeU7ZmHa3cYERERCRquswkIiIivqZkRkRERHxNyYyIiIj4mpIZERER8TUlMyIiIuJrSmZERETE15TMiIiIiK8pmRERERFfUzIjIiIivqZkRkRERHxNyYyIiIj4mpIZERER8TUlMyIiIuJrSmZERETE15TMiIiIiK8pmRERERFfUzIjIiIivqZkRkRERHxNyYyIiIj4mpIZERER8TUlMyIiIuJrdSo7gOrmwIMP8n16RoGZ+wM/Pxxb5vpPZGRQPz6+zPWIiIhUF2qZKWffp2dwIiOj5IKlVD8+nnoJSmZERETyqGUmBurHx9P+2Wd+mjHv4sDP8c+EX0FERERKTS0zIiIi4mtKZkRERMTXlMyIiIiIr6nPjM9lZmcy/p3xUa0T3yKeyX0mxygiERGRiqVkxsfiW0R/V1NmdmYMIhEREak8SmZ8rDStK9G24oiIiFR16jMjIiIivqZkRkRERHxNyYyIiIj4mpIZERER8TUlMyIiIuJrJSYzZtbOzD4ys3Qz22pmv/bmtzCz98xsh/ezecg6d5vZF2aWaWZDY7kDIiIiUrNFcmt2DnCXc269mTUG1pnZe0Aq8IFz7iEzmwJMASabWVdgDJAItAXeN7NznHO5sdmF8rUt6xijn1oJQNe2TaBuJQckIiIixSqxZcY5l+WcW++9/wZIB84ERgILvGILgEu99yOBF51z3zvndgJfAH3KOe6YaHhKHbq2aQIEkppt+49VckQiIiJSkqgemmdmHYCeQBpwhnMuCwIJj5m18oqdCawKWW2vN69gXTcBNwH87Gc/izrwWOhwWkMWju8PEGydERERkaot4g7AZtYI+DvwH8654posLMw8V2iGc7Odc72dc71PP/30SMMQERERySeiZMbM6hJIZJ53zr3qzT5oZm285W2AL735e4F2IavHAfvLJ1wRERGR/CK5m8mAp4F059xjIYveAMZ578cBi0LmjzGzemZ2FtAZWF1+IYuIiIj8JJI+Mz8HrgU2m9lGb95U4CHgJTO7Hvg/4EoA59xWM3sJ2EbgTqhb/HInk4iIiPhPicmMc24F4fvBAAwpYp0HgAfKEJeIiIhIRPQEYBEREfE1JTMiIiLia0pmRERExNeUzIiIiIivKZkRERERX1MyIyIiIr6mZEZERER8TcmMiIiI+FpUo2ZLGRzYDPMuLnp56yS46KGKi0dERKSaUDJTEVonFb/8wOaKiaMKOJGRwe5rx8ak7noJ8bSeOjUmdYuISNWlZKYilNTiUlyLTTVSLyE+ZnWfyMiIWd0iIlK1KZmRChPLVpNYtfaIiEjVpw7AIiIi4mtKZkRERMTXlMyIiIiIrymZEREREV9TMiMiIiK+pmRGREREfE3JjIiIiPiakhkRERHxNSUzIiIi4mtKZkRERMTXlMyIiIiIrymZEREREV9TMiMiIiK+pmRGREREfE3JjIiIiPiakhkRERHxNSUzIiIi4mtKZkRERMTXlMyIiIiIrymZEREREV9TMiMiIiK+pmRGREREfE3JjIiIiPiakhkRERHxNSUzIiIi4mtKZkRERMTXlMyIiIiIrymZEREREV9TMiMiIiK+VmIyY2Z/NbMvzWxLyLz7zGyfmW30XsNDlt1tZl+YWaaZDY1V4CIiIiIQWcvMfGBYmPmPO+d6eK/FAGbWFRgDJHrrPGlmtcsrWBEREZGCSkxmnHPLgewI6xsJvOic+945txP4AuhThvhEREREilWWPjO3mtkm7zJUc2/emcCekDJ7vXmFmNlNZrbWzNYeOnSoDGGIiIhITVanlOv9BfgvwHk//whcB1iYsi5cBc652cBsgN69e4ctIxKNExkZ7L52bMzqr5cQT+upU2NWv4iIlE6pkhnn3MG892Y2B3jLm9wLtAspGgfsL3V0lWxb1jFOPeUYANPf3Mq9lyRWckRSlHoJ8TGt/0RGRkzrFxGR0itVMmNmbZxzWd7kZUDenU5vAC+Y2WNAW6AzsLrMUVaCrm2bALAL+Nf3OWzbf6xS45HixbrFJJYtPiIiUjYlJjNm9jdgMNDSzPYC9wKDzawHgUtIu4AJAM65rWb2ErANyAFucc7lxiTyGMtrhRn/ThO2ZR2DHyo5IBEREQmrxGTGOXd1mNlPF1P+AeCBsgQlIiIiEik9AVhERER8TcmMiIiI+Fppb82W8nZgM8y7uOjlrZPgoocqLh4RERGfUDJTFbROKn75gc0VE4eIiIgPKZmpCkpqcSmuxUZERKSGU58ZERER8TUlMyIiIuJrSmZERETE15TMiIiIiK8pmRERERFfUzIjIiIivqZkRkRERHxNz5mpgTKzMxn/zvio1olvEc/kPpNjFJGIiEjpKZmpYeJbxEe9TmZ2ZgwiERERKR9KZmqY0rSuRNuKIyIiUpHUZ0ZERER8TcmMiIiI+JqSGREREfE1JTMiIiLia0pmRERExNeUzIiIiIivKZkRERERX1MyIyIiIr6mZEZERER8TcmMiIiI+JqSGREREfE1JTMiIiLia0pmRERExNeUzIiIiIivKZkRERERX1MyIyIiIr6mZEZERER8TcmMiIiI+JqSGREREfG1OpUdgIhfnMjIYPe1Y2NSd72EeFpPnRqTukVEqjslMyIRqJcQH7O6T2RkxKxuEZGaQMmMSARi2WoSq9YeEZGaQn1mRERExNeUzIiIiIivKZkRERERX1MyIyIiIr5WYjJjZn81sy/NbEvIvBZm9p6Z7fB+Ng9ZdreZfWFmmWY2NFaBi4iIiEBkLTPzgWEF5k0BPnDOdQY+8KYxs67AGCDRW+dJM6tdbtGKiIiIFFBiMuOcWw5kF5g9EljgvV8AXBoy/0Xn3PfOuZ3AF0Cf8glVREREpLDS9pk5wzmXBeD9bOXNPxPYE1JurzevEDO7yczWmtnaQ4cOlTIMERERqenKuwOwhZnnwhV0zs12zvV2zvU+/fTTyzkMERERqSlKm8wcNLM2AN7PL735e4F2IeXigP2lD09ERESkeKVNZt4AxnnvxwGLQuaPMbN6ZnYW0BlYXbYQRURERIpW4thMZvY3YDDQ0sz2AvcCDwEvmdn1wP8BVwI457aa2UvANiAHuMU5lxuj2KUCZWZnMv6d8VGtE98insl9JscoIhERkYASkxnn3NVFLBpSRPkHgAfKEpRULfEtoh8xOjM7MwaRiIiIFKZRs6VEpWldibYVR0REpLRqTjKzZArTDq8IvJ/XtPDyA5uhdVLFxiQiIiJlVnPGZjqwmQ4//rPo5a2TlMyIiIj4UM1pmQF21e3I/ac9wsLx/Ss7FBERESknNadlRkRERKolJTMR2pZ1jNFPrWT6m1srOxQREREJUaMuM5XWqafUpkObJmzLOlbZoYiIiEgBapmJQIfTGrJwQn+6tmlS2aGIiIhIAUpmRERExNdq1GWmBU2/Y9cpjzL+nchbWDKzM+nSoksMoxIREZGyqFHJzK66uZywPUBixOt0adGlVI/zL3cHNsO8i4te3joJLnqo4uIRERGpImpUMgNQ37Vj3rB5lR1GdEp6mN+BzRUTh4iISBVU45IZXyqpxaW4FhsREZFqTh2ARURExNfUMiNSBZzIyGD3tWNjVn+9hHhaT50as/pFRCqTkhmRSlYvIbYdzE9kZMS0fhGRyqZkRqSSxbrFJJYtPiIiVYH6zIiIiIivKZkRERERX1MyIyIiIr5W7fvMTH9zK9v2H2Pa4aOcbOEqOxwREREpZ9W+ZWbb/mNsyzoGQK1axqmn1K7kiERERKQ8VfuWGYCubZqQeEpTGtoJGp7WsLLDERERkXJU7VtmREREpHpTMiMiIiK+pmRGREREfE3JjIiIiPiakhkRERHxNSUzIiIi4ms14tZskZruREZGTAecrJcQH/MBM0VEiqJkJkrbso4x+qmVAHRt24R7L0ms5IhEilcvIT6m9Z/IyIhp/SIiJVEyE4WubZsE3+c9VVikqot1i0ksW3xERCJR45KZf3t1F7ufL90f39SQ93nJzO4VTfKVOZGRQf342P4nLCIiIj+pcclMq33fcuLL2CUc9ePjY96s7xeZ2ZmMf2d8VOvEt4hncp/JMYpIRESqoxqXzEAg4Wj/7DNlquO3Xr+ZhRP6l0dI1U58i+gTuszszBhEIiIi1V2NTGYk9krTuhJtK46IiAgomak+DmyGeRcXvbx1Elz0UMXFIyIiUkGUzFQHrZOKX757ReB1YHPxdSjZERERH1IyUx2UlIQsmVJ8IlPcMhERkSpOyUxNUFKyU9zlKRERkSpOyUwZ6GnAIiIila9MyYyZ7QK+AXKBHOdcbzNrASwEOgC7gKucc1+XLcyqR08DFhERqRrKo2XmfOfcVyHTU4APnHMPmdkUb7raPQUttBUmr3VGREREKl6tGNQ5EljgvV8AXBqDbYiIiIgAZW+ZccBSM3PAU8652cAZzrksAOdclpm1KmuQIlK1ncjIiNmAk/US4mM+WKaI+FtZk5mfO+f2ewnLe2aWEemKZnYTcBPAz372szKGIdWFxnPyn1iORXYiI+I/KSJSg5UpmXHO7fd+fmlmrwF9gINm1sZrlWkDfFnEurOB2QC9e/d2ZYlDqgeN5+RPsWw1iVVrj4hUL6VOZsysIVDLOfeN9/5C4H7gDWAc8JD3c1F5BCrVn8ZzEhGR0ihLy8wZwGtmllfPC865d8xsDfCSmV0P/B9wZdnDFBEREQmv1MmMc+6fQPcw8w8DQ8oSlIiIiEikYnFrtoiIiEiFUTIjIiIivqZkRkRERHxNyYyIiIj4mpIZERER8TUlMyIiIuJrSmZERETE15TMiIiIiK+VdaBJ8WzLOsbop1bStW0T7r0ksbLDEak2YjkiN2hUbpHqQMlMOejatgkQSGhEpPzEckRu0KjcItWFkplykNcSM/qplZUciUj1EusWE43KLVI9qM+MiIiI+JpaZspZXt8ZQP1nREREKoCSmXKU13cG1H9GRESkoiiZKUehrTDqPyMiIlIxlMyI72VmZzL+nfFRrRPfIp7JfSbHKCIREalISmak7JZMgQObiy/TOgkueqjcNx3fIvpbdzOzM8s9DhERqTxKZqTsDmwOvFonFb08RkrTuhJtK46IiFRtSmYk4MBmmHdx0ctLallpnQTj3w6/rLh6RUREykjJjBTdopInhi0rlUX9bCRPLIdL0FAJIhVDyYyU3Jdl3sXFt9wUd4mpClI/G8kTy+ESNFSCSMVRMiMlKylRaZ3kq2SmtP1sStOaA2rRqcpi2WqioRJEKo6SGSlZDO5C8pvStOaAWnRERCqCkhmpGGXtYFzJStuyojunRERiT8mMxF4N7GAsArHtXAzqYCySR8mMxF4kHYxFqplYdi4GdTAWCaVkRkQkBmLdYqIOxiI/qVXZAYiIiIiUhZIZERER8TUlMyIiIuJr6jMjVYPPb90WEZHKo2RGKp9u3RYpFY0rJRKgZKYCTH9zK9v2HwtOd23bhHsvSazEiKqYan7rtga1lFjQuFIiP1EyE0Pbso4x+qmVpO3MBqDvWS3YlnWshLWkOtGglhIrGldK5CdKZmKka9smwfd9z2oRbI0Z/dTKSoxKKlppB7UUEZHIKZmJEV1GkrLQpSkRkcgpmRGpYirq0tTDqx8mIzv6vhFKmqSqO/Dgg3yfHrt+P+ocXfUomRGpYirq0lRGdgaZ2Zl0adEl4nXUn0f84Pv0DE5kZFA/vvw7SatzdNWkZEakBuvSogvzhs2LuLz689Qcfh/xu358PO2ffabc61Xn6KpJyUwl0e3aIlJVacRv8RslM5VgW9Yx3a4tIlWWRvwWv1EyU8FCb9kOvV0775k0ofNDW2/UclMGS6aU/BThajBcQrR3QEXbX6a02wF1GhaR2IpZMmNmw4D/AWoDc51z/v6mKCfhEpLQBCdtZzZpO7PZtv+n1pu8+TU6sSnL2E0HNgdeRQ2bUA2GSyjNHVBdWnSJer2q/BBA3Z3lL7HskxOrzr+h9fu1dam63okVk2TGzGoDTwAXAHuBNWb2hnNuWyy253ehiUloa0zew/aA4LzQZAdqSGJT0thNu1cEXkUlJXmJzPi3wy8vy3AJVaTVp6K+jEt7p1VFtObo7iz/iHWfnPrx8THbRqxjj6V/rVnDv9asqZa3rceqZaYP8IVz7p8AZvYiMBJQMlOCkhKT0GQntOWmWispESgpoWidFNlglqVJanavCPxsP6D45TVYaVpz1h5cy9qDa6NqaclLZHR3VtXn55YBP8ce6+fv/GvNmpjVXRJzzpV/pWZXAMOcczd409cCfZ1zt4aUuQm4yZvsAsTyX6SWwFcxrL+60fGKno5ZdHS8oqPjFT0ds+j45Xi1d86dXnBmrFpmLMy8fFmTc242MDtG288fjNla51zvithWdaDjFT0ds+joeEVHxyt6OmbR8fvxqhWjevcC7UKm44D9MdqWiIiI1GCxSmbWAJ3N7CwzOwUYA7wRo22JiIhIDRaTy0zOuRwzuxV4l8Ct2X91zm2NxbYiVCGXs6oRHa/o6ZhFR8crOjpe0dMxi46vj1dMOgCLiIiIVJRYXWYSERERqRBKZkRERMTXqlUyY2bDzCzTzL4wsylhlpuZ/a+3fJOZpVRGnFVFBMdrsJkdNbON3mtaZcRZVZjZX83sSzPbUsRynV8hIjheOr9CmFk7M/vIzNLNbKuZ/TpMGZ1jISI8ZjrPPGZW38xWm9nn3vGaHqaMP88x51y1eBHoaPwPoCNwCvA50LVAmeHAEgLPwekHpFV23FX8eA0G3qrsWKvKCxgEpABbiliu8yu646XzK//xaAOkeO8bA9v1N6xcjpnOs5+OhQGNvPd1gTSgX4EyvjzHqlPLTHAIBefcD0DeEAqhRgLPuIBVQDMza1PRgVYRkRwvCeGcWw4UN4aEzq8QERwvCeGcy3LOrffefwOkA2cWKKZzLESEx0w83nlz3Jus670K3gXky3OsOiUzZwJ7Qqb3UvikjqRMTRHpsejvNUkuMbNqPqJlmen8ip7OrzDMrAPQk8B/zqF0jhWhmGMGOs+CzKy2mW0EvgTec85Vi3MsVsMZVIYSh1CIsExNEcmxWE9gHIzjZjYceB3oHOvAfEznV3R0foVhZo2AvwP/4Zw7VnBxmFVq/DlWwjHTeRbCOZcL9DCzZsBrZtbNORfar82X51h1apmJZAgFDbPwkxKPhXPuWF6TpHNuMVDXzFpWXIi+o/MrCjq/CjOzugS+lJ93zr0apojOsQJKOmY6z8Jzzh0BlgHDCizy5TlWnZKZSIZQeAMY6/XW7gccdc5lVXSgVUSJx8vMWpuZee/7EDhfDld4pP6h8ysKOr/y847F00C6c+6xIorpHAsRyTHTefYTMzvda5HBzBoAvwAyChTz5TlWbS4zuSKGUDCzid7yWcBiAj21vwD+BYyvrHgrW4TH6wpgkpnlAN8BY5zX3b0mMrO/EbgzoqWZ7QXuJdCBTudXGBEcL51f+f0cuBbY7PVpAJgK/Ax0jhUhkmOm8+wnbYAFZlabQFL3knPurerwPanhDERERMTXqtNlJhEREamBlMyIiIiIrymZEREREV9TMiMiIiK+pmRGREREfE3JjAhgZrneiLpbvcee32lmtbxlvc3sf4tZt4OZ/XvFRVto+7d7owY/H+Pt/IeZnRqjuiv1GFYkM1tsZs28180h89ua2SvltI1dZrbZzHqXQ12PmNkBM/tNecQmEgu6NVsEMLPjzrlG3vtWwAvAp865eyNYdzDwG+fcL2MaZNHbzwAucs7tLDC/jnMupxy3swvo7Zz7Ksyy2t5j0ktb92DKcAzLuv3K4I0l9JZzrlsM6t5FEZ9VKeu7DzjunHu0POoTKW9qmREpwDn3JXATcKv3FMzBZvYWgJmd57XgbDSzDWbWGHgIGOjNu8NrZfjEzNZ7r//nrTvYzJaZ2StmlmFmz4c8mfRcM/vMaxVabWaNLTAg3CNmtsbMNpnZhIKxmtksoCPwhrft+8xstpktBZ4xs/Zm9oG3/gdm9jNvvflm9hcz+8jM/unt11+9Fp75YbZzO9AW+MjMPvLmHTez+80sjcBAfrvMe0y815q1zHvf0Kt7jXfMwo3OXvAY1jezeV7rwgYzOz9MTIO9+F8g8NC0Io+Xmf3Wq+tzM3vIm9fDzFZ5ZV8zs+bFnRfesX3WzD40sx1mdqM337ztbvG2Mdqb38bMlnv7tMXMBnrz847TQ8DZ3vJHvPNmi1cm7P6bWaqZvWpm73gx/HdxMYfEHu78SjWz183sTTPbaWa3WqBFcoN3XFpEUrdIleCc00uvGv8i8F9nwXlfA2cQeIrtW968N4Gfe+8bEXiKdnC5N/9UoL73vjOw1ns/GDhKYKyTWsBKYABwCvBP4FyvXBOv3puAe7x59YC1wFlh4twFtPTe3wesAxqExDvOe38d8Lr3fj7wIoFB5UYCx4AkL651QI/ituNNO+CqIuLoDSzz3j8I/Mp73wzYDjQsUHfBY3gXMM97Hw/8X94xLbDOt3nHpKjjBVwEfAac6i1r4f3cBJznvb8f+FMJ58h9wOdAA6AlgZGF2wKXA+8ReJL2GV6sbbx9+J23bm2gcehxAjoAW0LqD04Xtf9AKoFzpak3vRtoV8I5UdT5lUrgKa+NgdMJnJsTvTKPExi0MXTff1PZv6d66VXUSy0zIkULN3rsp8BjXktFMxf+Mk5dYI6ZbQZeBrqGLFvtnNvrnDsJbCTwBdYFyHLOrYHgwHg5wIUExkjZCKQBpxHZaL9vOOe+8973J3DJDOBZAslTnjedcw7YDBx0zm324trqxVWSXAID/JXkQmCKtx/LCHwJ/6yEdQZ48eKcyyDwpX1OmHKr3U+X14o6Xr8gkBj8y6sv28yaEvj8PvbWXQAMimBfFjnnvnOByzcfAX28WP/mnMt1zh0EPgbOJTD+2XgLXKJJcs59E0H9kez/B865o865E8A2oH0JdRV1fgF85Jz7xjl3iEAy86Y3fzORnQMiVUK1GZtJpDyZWUcCX9ZfAgl5851zD5nZ2wTGLlllZr8Is/odwEGgO4GWjhMhy74PeZ9L4HfQCLRyFAoDuM05926U4X9bzLLQ7eTFcrJAXCeJ7G/DCZe/n0oOP126rh8y34DLnXOZEdQZuk4kQvc17PEys2GEP76lUbAeRxGxOueWm9kg4GLgWTN7xDn3TITbKW7/w51DJdVV1P4X/NxDzwl9P4hvqGVGpAAzOx2YBcz0Wi5Cl53ttWA8TOAyRjzwDYGm+jxNCfwnfJLAIHi1S9hkBtDWzM71ttHYzOoQGAR0kpnV9eafY2YNo9ydzwiMiA5wDbAiyvVDFdzPgnYBvbz3l4fMfxe4zSzYP6hnBHUvJxAvZnYOgZackpKhoo7XUuA68+7EMrMWzrmjwNd5/VgIfE4fh6u0gJFef5bTCFzmWuPFOtrrs3M6gRae1WbWHvjSOTeHwMjOKSXsc6jS7H9Rijq/RKoNndAiAQ28yxN1CbQwPAs8Fqbcf3idMXMJNPEvIfBfbI6ZfU6gL8qTwN/N7EoClyKKaynBOfeD12n0z2bWgMDIvr8A5hJo6l/vJQKHgEuj3K/bgb+a2X9665dlBNzZwBIzy3LOFeqQC0wHnjazqQQu8+T5L+BPwCZvP3YBBe9a2kThYzjLu1SXA6Q6576neGGPl3PuHTPrAaw1sx8IjAo8FRjnbeNUAn1KxgOY2f0E+jm9EWYbq4G3CSQX/+Wc229mrxG4nPc5gRaQ3zrnDpjZOOA/zexH4DgwNrQi59xhM/vU6/S7BHgiZHHY/ffywagUc36JVBu6NVtEJALmo9uTTbdmSw2jy0wiItXPIeADK6eH5gG/ooQWRpHKpJYZERER8TW1zIiIiIivKZkRERERX1MyIyIiIr6mZEZERER8TcmMiIiI+Nr/BxlpAsBsVaSFAAAAAElFTkSuQmCC\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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KfHWRURqgNl/+5BdB46Va51d2jbh7su7lmudItVdLD0tbYC3zWw78D7whnPu73jJyhAz2w0M8adFRKSAXQeOsSur/JKWXVnHYkqCJk2aRKtWrejWLfoZfecct956K506dSI5OZktW7aUKJZZs2bx5ptvlmidPI0aNSrVegJ79uyhb9++dO7cmTFjxvDtt99GLLd48WI6d+5M586dWbx4cWj+uHHjiI+Pp1u3bkyaNImTJ09WVuhl45yrtEfv3r2diEhNsGvXrtDza+a/566Z/1651R1rfatXr3abN292Xbt2jVrm1VdfdcOHD3e5ublu3bp1rk+fPuUWZ3EaNmxY6nVzcnKKnI4kNzfXnTp1qtTbrE6uvvpq96c//ck559yUKVPco48+WqjMkSNHXIcOHdyRI0dcdna269Chg8vOznbOea97bm6uy83NdWPHjo24fmUIf5/kATa5KHmE7ogrInKaSk1NpUWLFkWWeeWVVxg/fjxmRr9+/Th69ChZWVmFyjVq1Ijbb7+dXr16MXjwYA4fPgxAWloaL7zwAl988QXx8fFkZmYCcO211/L4448D8Nvf/pYLLriA5ORk7r777mLjfvrpp+nTpw89evRgypQpnDp1KhTDrFmz6Nu3L+vWrSs0/eCDD9KtWze6devGww8/DMDevXtJTEzkpptuolevXnzyySdRtzto0CBuu+02UlNTSUxM5P3332f06NF07tyZO++8s9j4pk2bRkpKCl27ds23n+3bt+fuu++mV69eJCUlkZGRUWwbFMU5x1tvvcVVV10FwIQJE3j55ZcLlXv99dcZMmQILVq0oHnz5gwZMoTly5cDMGLECMwMM6NPnz7s27ev0PqnTp3ijjvuICkpieTkZP7whz+E9mfmzJn079+flJQUtmzZwrBhwzj//POZP39+mfatOEpaRERqsP3793PuueeGpuPi4ti/f3+hcl999RW9evViy5YtXHTRRcyePTvf8qZNmzJv3jzS0tJ47rnn+Pzzz7nhhhtYsWIFu3fvZuPGjWzbto3NmzezZs2aqPGkp6ezdOlS3n33XbZt20bt2rV55plnQjF069aNDRs2MGDAgHzTDRo0YNGiRWzYsIH169fz+OOPs3XrVgAyMzMZP348W7dupV27dowYMYIDBw5E3P4ZZ5zBmjVrmDp1KqNGjeKRRx5h586dPPnkkxw5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uO2220hNTSUxMZH333+f0aNH07lzZ+68885i45s2bRopKSmFerbat2/P3XffTa9evUhKSiIjo2x3RHfO8dZbb3HVVVcBMGHCBF5++eVC5V5//XWGDBlCixYtaN68OUOGDGH58uX5ynz55Ze89dZbEXtaTp06xR133EFSUhLJycn84Q9/CO3PzJkz6d+/PykpKWzZsoVhw4Zx/vnnh+62XFGUtIiInKZOnTpFjx49aNWqFUOGDKFv376Fyuzfv59zzz03NB0XF8f+/fsLlfvqq6/o1asXW7Zs4aKLLmL27Nn5ljdt2pR58+aRlpbGc889x+eff84NN9zAihUr2L17Nxs3bmTbtm1s3ryZNWvWRI05PT2dpUuX8u6777Jt2zZq167NM888E4qhW7dubNiwgQEDBuSbbtCgAYsWLWLDhg2sX7+exx9/nK1btwLeYITjx49n69attGvXjhEjRnDgwIGI2z/jjDNYs2YNU6dOZdSoUTzyyCPs3LmTJ598kiNHjhQZ329+8xs2bdrE9u3bWb16Ndu3bw/V27JlS7Zs2cK0adOYO3duoe1mZmaGTtcUfBw9ejRf2SNHjtCsWbPQ6MvRXrNYXtuXXnqJwYMH06RJ4WEhFixYwJ49e9i6dSvbt29n3LhxoWXnnnsu69atY+DAgaHEdf369YWGAihvOj0kInKaql27Ntu2bePo0aNcccUV7Ny5k27duuUrE2kol0g9MrVq1QqNQnzdddcxevToQmWGDBnC888/z80338wHH3wAeIP0rVixgp49ewLeTep2795NampqxJhXrlzJ5s2bQ+PlfP3116FximrXrs2VV16Zb//ypteuXcsVV1wRGtF59OjRvPPOO4wcOZJ27drlOy322muvRdw2eANIAiQlJdG1a9fQ4JEdO3bkk08+Ye3atVHj+/Of/8yCBQvIyckhKyuLXbt2kZycHIoHoHfv3rz44ouFtluSARNjfc1iKfenP/2JyZMnR9zOm2++ydSpU0PJUfhgieHtdPz4cRo3bkzjxo2pX78+R48ezTcqdXlS0iIicppr1qwZgwYNYvny5YWSlri4uHynTPbt2xfTQIKRPiRzc3NJT0+nQYMGZGdnExcXh3OOX/3qV0yZMiWmWJ1zTJgwITQacbj69evnu24lfLqocfTyEplY1KtXD/CStLznedM5OTlR49uzZw9z587l/fffp3nz5qSlpXHixIlC9dauXZucnJxC283MzAwlhQWtWrUqXxLQsmVLjh49Sk5ODnXq1In6msXFxbFq1arQ9L59+/KNPH3kyBE2btzISy+9FHG7zrmIr3P4/kRrp4qipEVEpDIc3BHTBbQx19U6qcgihw8fpm7dujRr1oyvv/6aN998k+nTC48MP3LkSObNm8fYsWPZsGEDTZs2DfUuhMvNzeWFF15g7NixPPvsswwYMKBQmYceeojExETuv/9+Jk2axLp16xg2bBh33XUX48aNo1GjRuzfv5+6detGHeV58ODBjBo1ittuu41WrVqRnZ3Nl19+Wewoz6mpqaSlpTFjxgycc7z00kssWbKkyHVKI1p8x44do2HDhjRt2pRDhw6xbNmyfAlCcUrS02JmXHzxxaHXY/HixREvpB02bBgzZ87k888/B7xer/Bk6/nnn+eyyy6jfv36EbczdOhQ5s+fz6BBg6hTpw7Z2dn5eluqgpIWEZGKVkyCUar6iqkzKyuLCRMmcOrUKXJzc7nmmmu47LLLAEIXS06dOpURI0bw2muv0alTJ84880wWLYo8kGvDhg358MMP6d27N02bNmXp0qX5ln/00UcsXLiQjRs30rhxY1JTU7nvvvuYPXs26enp9O/fH/Aupn366aejJi1dunThvvvuY+jQoeTm5lK3bl0eeeSRYpOWXr16kZaWRp8+fQCYPHkyPXv2ZO/evYXKjhgxgoULF8bUoxRrfP369aNnz5507dqVjh07cuGFF5a47pKYM2cOY8eO5c4776Rnz55cf/31AGzatIn58+ezcOFCWrRowV133RU6lTVr1qx8Scdzzz3HjBkzom5j8uTJfPTRRyQnJ1O3bl1uuOEGbrnllgrdr+JYUV1q5S0lJcVt2rSp0rZXXeWN0lzWUZ5Lu76IVLz09HQSExOrOoxy06hRIw2aKOUu0vvEzDY751Iildevh0RERCQQlLSIiEix1Msi1YGSFhEREQkEJS0iIiISCEpaREREJBD0k2cRkQo2Z+McMrLLNt5MQQktEpjep/B9V0ROZ+ppERGpYBnZGWRmZ5ZbfZnZmTElQe3btycpKYkePXqQkhLxF6Q457j11lvp1KkTycnJbNmypUSxzJo1izfffLNE6+TJG9BRSm7Pnj307duXzp07M2bMGL799tuI5YYPH06zZs1C9+jJM2/ePDp16oSZ8dlnn1VGyOVCPS2xWjbDuwtlcVonwSUPVHw8IhIo8S3iy+3eSnn3aorF22+/TcuWLaMuX7ZsGbt372b37t1s2LCBadOmsWHDhpjrv/fee2MuW55OnTqV75b+Bacjcc7hnKNWreB/X58+fTq33XYbY8eOZerUqTzxxBNMmzatULlf/OIX/Pvf/+axxx7LN//CCy/ksssuK9Fde6uD4L9yleXgjuKTlljKiIhUI6+88grjx4/HzOjXrx9Hjx4lKyurULlGjRpx++2306tXLwYPHszhw4cBQiP8fvHFF8THx5OZ6fUoXXvttTz++OMA/Pa3v+WCCy4gOTmZu+++u9iYnn76afr06UOPHj2YMmUKp06dCsUwa9Ys+vbty7p16wpNP/jgg3Tr1o1u3brx8MMPA7B3714SExO56aab6NWrV75xlgoaNGgQt912G6mpqSQmJvL+++8zevRoOnfuzJ133llsfNOmTSMlJYWuXbvm28/27dtz991306tXL5KSksjIKNupQuccb731FldddRUAEyZM4OWXX45YdvDgwTRu3LjQ/J49e9K+ffsit3Pq1CnuuOMOkpKSSE5O5g9/+ENof2bOnEn//v1JSUlhy5YtDBs2jPPPPz90t+WKoqSlJFonwcRXoz/K+1bdIiJlYGYMHTqU3r17s2DBgohl9u/fz7nnnhuajouLY//+/YXKffXVV/Tq1YstW7Zw0UUXMXv27HzLmzZtyrx580hLS+O5557j888/54YbbmDFihXs3r2bjRs3sm3bNjZv3syaNWuixpyens7SpUt599132bZtG7Vr1+aZZ54JxdCtWzc2bNjAgAED8k03aNCARYsWsWHDBtavX8/jjz/O1q1bAW8wwvHjx7N161batWvHiBEjOHDgQMTtn3HGGaxZs4apU6cyatQoHnnkEXbu3MmTTz7JkSNHiozvN7/5DZs2bWL79u2sXr2a7du3h+pt2bIlW7ZsYdq0acydO7fQdjMzM+nRo0fEx9GjR/OVPXLkCM2aNQuNvhztNSurBQsWsGfPHrZu3cr27dsZN25caNm5557LunXrGDhwYChxXb9+PbNmzSr3OMLp9JCIyGnq3XffpW3btnz66acMGTKEhIQEUlNT85WJNJRLpJF9a9WqFRqF+LrrrmP06NGFygwZMoTnn3+em2++mQ8++ADwBulbsWIF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naVLl/L2229z6623smjRIk6dOsVPf/pTXnjhBTZv3sykSZP49a9/XWTcN954I3/4wx/YvHkzc+fO5aabbgot++ijj3jzzTf53e9+V2h6/PjxzJkzh+3bt5OUlMTs2bND6x09epTVq1dz++235xveoKCdO3fy7LPPsnHjRn79619z5plnsnXrVvr3789TTz1VZHwDBgxg/fr1bN26lbFjx/Lf//3foXozMjJ4/fXX2bhxI7Nnz474wT5mzBh69OhR6JG33XAled0ATp48yZIlS0JDPIR74oknuOSSSwrNP3z4MDfccAN/+ctf+OCDD3j++edDy/7xj3/w6quv8sorr3Dddddx8cUXs2PHDho0aMCrrxZ9t/hYBL8vTEREyl2kIV6ijfh7zTXXUKtWLTp37kzHjh1DPQx5zjzzTB5//HFSU1N56KGHOP/889m5cyc7d+5kyJAhgHc6KtJAjXmOHz/Oe++9x9VXXx2a980334SeX3311flGgM6b/uKLLzh69CgXXXQR4PUshdcRPrLy1KlTo27/4osvpnHjxjRu3JimTZty+eWXA5CUlMT27duLjG/fvn2MGTOGrKwsvv32Wzp06BAqc+mll1KvXj3q1atHq1atOHToEHFxcfm2vXTp0qhxFVSS1w3gpptuIjU1lYEDB+ab//bbb/PEE0+wdu3aQuusX7+e1NTU0H6E9+Zdcskl1K1bl6SkJE6dOhVKhpKSkti7d2/M+xGNkhYRkRrme9/7HllZWbRp04asrKyIIy7HxcXxySefhKb37dtH27ZtI9ZX8EMx0ofkjh07OOuss0IDFTrn6Nq1K+vWrYsp5tzcXJo1axZ1JOSGDRsWOR1NrOXq1asXel6rVq3QdK1atcjJySkyvp/+9Kf8/Oc/Z+TIkaxatYp77rknYr21a9cmJyen0PpjxowhMzOz0Pyf//znha5XKsnrNnv2bA4fPsxjjz2Wb/727duZPHkyy5Yt46yzziq0nnMuaiIU3i5169YNlctrp7JS0iIiUglOZGTEfAFtLHXVTyh6lOeijBw5ksWLFzNjxgwWL17MqFGjCpW54IIL2L17N3v27OGcc87hueeeizrK7/PPP8+ECRPYs2cP//znP4mPj2f9+vWh5R9//DG/+93v2Lp1KyNGjOBHP/oRPXv25PDhw6xbt47+/ftz8uRJPvroI7p27RpxG02aNKFDhw48//zzXH311Tjn2L59O927dy9yX5s2bUrz5s155513GDhwIEuWLAn1upSnouL74osvOOeccwBYvHhxiesuSU/LyJEjmTdvHmPHjmXDhg00bdo0Yg/WwoULef3111m5ciW1an13pci//vUvRo8ezZIlS/j+978fcRv9+/fn5ptvZs+ePXTo0IHs7OyI105VhGKvaTGzc83sbTNLN7MPzez/+fPvMbP9ZrbNf4yo+HBFRIKnXmJCmZKMguonJFAvsfj6rr32Wvr3709mZiZxcXE88cQTAMyYMYM33niDzp0788YbbzBjxgwADhw4wIgR3r/yOnXqMG/ePIYNG0ZiYiLXXHNN1IQiPj6eiy66iEsuuYT58+dTv3790DLnHNdffz1z586lbdu2PPHEE0yePJnc3FxeeOEFpk+fTvfu3enRowfvvfdekfvzzDPP8MQTT9C9e3e6du0a8cLgSBYvXswvfvELkpOT2bZtG7NmzYpYrqhrWmIRLb577rmHq6++moEDB9KyZctS1x+LESNG0LFjRzp16sQNN9zAo48+mm9ZXk/X1KlTOXToEP3796dHjx6hC6Xvvfdejhw5wk033USPHj0i/gLs7LPPZsGCBYwePZru3bvnO8VW0SzS+a98BczaAG2cc1vMrDGwGfgRcA1w3Dk3N9aNpaSkuE2bNpUh3Cq06FLv78QiLiSKpQwwcflEr/jwRaUKpazri0jFS09PJzExsarDqHBpaWlcdtllXHXVVVUdigRQpPeJmW12zkX8vXyxp4ecc1lAlv/8SzNLB84ph1hFREREYlaia1rMrD3QE9gAXAjcYmbjgU3A7c65QrdVNLMbgRsBzjvvvLLGKyIi1ciTTz5Z1SFIDRLzfVrMrBHwF+BnzrljwP8C5wM98HpifhdpPefcAudcinMu5eyzzy57xCIiAVHc6XeRmqw074+YkhYzq4uXsDzjnHvR39gh59wp51wu8DjQp8RbFxE5TdWvX58jR44ocRGJwDnHkSNH8l20HYtiTw+Z9yPrJ4B059yDYfPb+Ne7AFwB7CzRlkVETmNxcXHs27ePw4cPV3UoItVS/fr1C91IrzixXNNyIfATYIeZbfPnzQSuNbMegAP2AlNKtGURkdNY3bp18935VETKLpZfD60FIt367rXyD0dEREQkMg2YKCIiIoGgpEVEREQCQUmLiIiIBIKSFhEREQkEJS0iIiISCEpaREREJBCUtIiIiEggKGkRERGRQFDSIiIiIoGgpEVEREQCQUmLiIiIBIKSFhEREQkEJS0iIiISCEpaREREJBCUtIiIiEggKGkRERGRQFDSIiIiIoFQp6oDqDaWzYCDO6IvP7gDWidVXjyniYP338836RlVtv16iQm0njmzyrYvIiLlRz0teQ7uKDppaZ2kpKUUvknP4ERG1SQtJzIyqjRhEhGR8qWelnCtk2Diq1UdxWmnfkIC7ZY8Venb/fgn4yt9myIiUnHU0yIiIiKBoKRFREREAkFJi4iIiASCkhYREREJBCUtIiIiEghKWkRERCQQlLSIiIhIIChpERERkUBQ0iIiIiKBoKRFREREAkFJi4iIiASCkhYREREJBCUtIiIiEghKWkRERCQQlLSIiIhIIChpERERkUBQ0iIiIiKBoKRFREREAkFJi4iIiASCkhYREREJBCUtIiIiEgh1qjqAyjT7bx+y68CxiMvmfPkV7c9qWMkRlV5mdiYTl0+Mqex/vLiXVvu/Ck2fWfdMzmt8XkWFls+JjAzqJyRUyrZEROT0VqN6WnYdOMaurMJJy66sY3z1bU4VRFQ6CS0SiG8RH3P5Vvu/otX+fwPw75yv+ffJf1dUaIXUT0igXqKSFhERKbsa1dMC0KVNE5ZO6Z9v3pjH1sGRKgqoFKb3mV6i8h8/Mx5aQM8lT4V6ZxYNX1QRoYmIiFSYGtXTIiIiIsGlpEVEREQCQUmLiIiIBIKSFhEREQkEJS0iIiISCEpaREREJBCUtIiIiEggFJu0mNm5Zva2maWb2Ydm9v/8+S3M7A0z2+3/bV7x4YqIiEhNFUtPSw5wu3MuEegH3GxmXYAZwErnXGdgpT8tIiIiUiGKTVqcc1nOuS3+8y+BdOAcYBSw2C+2GPhRBcUoIiIiUrJrWsysPdAT2AB8zzmXBV5iA7SKss6NZrbJzDYdPny4jOGKiIhITRVz0mJmjYC/AD9zzkUeKjkC59wC51yKcy7l7LPPLk2MIiIiIrElLWZWFy9hecY596I/+5CZtfGXtwE+rZgQRURERGL79ZABTwDpzrkHwxb9FZjgP58AvFL+4YmIiIh46sRQ5kLgJ8AOM9vmz5sJPAD82cyuB/4FXF0hEYqIiIgQQ9LinFsLWJTFg8s3HBEREZHIdEdcERERCQQlLSIiIhIISlpEREQkEJS0iIiISCAoaREREZFAiOUnz4Ez+28fsuvAdzft7dK2CXdf3rUKIxIREZGyOi2Tll0HjrEr6xhd2jRhV1bMIw6IiIhINXbanh7q0qYJS6f0p0ubJlUdioiIiJSD0zZpERERkdOLkhYREREJBCUtIiIiEghKWkRERCQQlLSIiIhIIChpERERkUBQ0iIiIiKBoKRFREREAkFJi4iIiASCkhYREREJBCUtIiIiEghKWkRERCQQlLSIiIhIIChpERERkUBQ0iIiIiKBoKRFREREAkFJi4iIiASCkhYREREJBCUtIiIiEghKWkRERCQQlLSIiIhIINSp6gAqw66sY4x5bB27so7RpU2TMtc3Z+McMrIzCi+wQ97f5ROLXD8zO5P4FvFljkNERKQmOe17Wrq0bRJKVLq0aUKXtmVPWjKyM8jMziz1+vEt4klokVDmOERERGqS076n5e7Lu1ZIvfEt4lk0fFH+mYsu9f4WnC8iIiJldtr3tIiIiMjpQUmLiIiIBIKSFhEREQkEJS0iIiISCEpaREREJBCUtIiIiEggKGkRERGRQFDSIiIiIoGgpEVEREQC4bS/I26lO7jjuzvjRtM6CS55oHLiiSAzO5OJxYyPVJSEFglM7zO9HCM6/Ry8/36+SY8wPlUlqZeYQOuZM6ts+yIiFUFJS3lqnVR8mYM7Kj6OIpR1zKOyjLlUk3yTnsGJjAzqJ1T+GFMnMqouWRIRqUhKWspTLL0nxfXCVLCy9pCUpYempqmfkEC7JU9V+nY//sn4St+miEhl0DUtIiIiEghKWkRERCQQlLSIiIhIIChpERERkUBQ0iIiIiKBoKRFREREAkFJi4iIiARCsUmLmf3RzD41s51h8+4xs/1mts1/jKjYMEVERKSmi6Wn5UlgeIT5DznneviP18o3LBEREZH8ir0jrnNujZm1r4RYRMrdiYyMKrlDbFXdwl9E5HRWlmtabjGz7f7po+bRCpnZjWa2ycw2HT58uAybEymZeokJVZY41E9IoF6ikhYRkfJU2rGH/hf4T8D5f38HTIpU0Dm3AFgAkJKS4kq5PZES0yjHIiKnl1L1tDjnDjnnTjnncoHHgT7lG5aIiIhIfqVKWsysTdjkFcDOaGVFREREykOxp4fM7E/AIKClme0D7gYGmVkPvNNDe4EpFReiiIiISGy/Hro2wuwnKiAWERERkah0R1wREREJBCUtIiIiEghKWkRERCQQlLSIiIhIIChpERERkUAo7R1xpYQO3n8/36RnwMED3oy3Km88HI2DIyIipwP1tFSSb9IzOJGRUSXb1jg4IiJyOlBPSyWqn5BAu/844k1MfKpqgxEREQkY9bSIiIhIIChpERERkUBQ0iIiIiKBoKRFREREAkFJi4iIiASCkhYREREJBCUtIiIiEghKWkRERCQQlLSIiIhIIJw2d8Sd/bcP2XXgGAC7so7RpU2TKo5IREREytNp09Oy68AxdmV5SUuXNk3o0lZJi4iIyOnktOlpAS9ZWTqlf1WHISIiIhXgtOlpERERkdObkhYREREJBCUtIiIiEghKWkRERCQQlLSIiIhIIChpERERkUBQ0iIiIiKBoKRFREREAkFJi4iIiATCaXVHXKkcmdmZTFw+sdTrJ7RIYHqf6eUYkYiI1ARKWqREEloklGn9zOzMcopERERqGiUtUiJl7SEpSw+NiIjUbLqmRURERAJBSYuIiIgEgpIWERERCQQlLSIiIhIISlpEREQkEJS0iIiISCAoaREREZFAUNIiIiIigaCkRURERAKhZtwRd9kMOLgj6uJZR76g/cl/Aj3zzZ/9tw/ZdeBYaLpL2ybcfXnXssdzcAcsurToMq2T4JIHoi8vZp9irkdERCQgakbScnCH92idFLXI3rod6Vpg+a4Dx9iVdYwubZqwK+tYlDVLqIgYQmJJRmLYp5jqERERCYiakbSA9+E+8dWIi+59bB0ASy/pX2hZlzZNWDqlP2P8MmUWS69Hcb0weYrYpxLVIyIiEgC6pkVEREQCQUmLiIiIBIKSFhEREQkEJS0iIiISCEpaREREJBCUtIiIiEggFJu0mNkfzexTM9sZNq+Fmb1hZrv9v80rNkwRERGp6WLpaXkSGF5g3gxgpXOuM7DSnxYRERGpMMXeXM45t8bM2heYPQoY5D9fDKwCppdnYCIFzdk4h4zsjDLVkdAigel9dKiKiARRaa9p+Z5zLgvA/9sqWkEzu9HMNpnZpsOHD5dycyKQkZ1BZnZmqdfPzM4sc9IjIiJVp8Jv4++cWwAsAEhJSXEVvT05vcW3iGfR8EWlWnfi8onlHI2IiFSm0va0HDKzNgD+30/LLyQRERGRwkqbtPwVmOA/nwC8Uj7hiIiIiEQWy0+e/wSsA+LNbJ+ZXQ88AAwxs93AEH9aREREpMLE8uuha6MsGlzOsYiIiIhEpTviioiISCAoaREREZFAUNIiIiIigaCkRURERAJBSYuIiIgEQoXfEbe6Ch/HZu8ZxwCYuLxJvjLh88OfZ2ZnEt8ivhKjFRERkRrb01KWcWziW8ST0CKhnCMSERGRotTYnhb4bhybMY+tA2DR8P75lofPj1ZGREREKkeN7WkRERGRYFHSIiIiIoGgpEVEREQCQUmLiIiIBIKSFhEREQkEJS0iIiISCEpaREREJBCUtIiIiEggKGkRERGRQKjRd8QNtyvrWOiut13aNuHuy7tWcUQipXciI4OPfzK+qsOoEvUSE2g9c2ZVhyEiFUBJC16SkmdX1rEqjESk7Ool1txxsU5kZFR1CCJSgZS0QL5elbzeFpGgqsm9DDW1d0mkptA1LSIiIhIISlpEREQkEJS0iIiISCAoaREREZFAUNIiIiIigaCkRURERAJBSYuIiIgEgpIWERERCQQlLSIiIhIIuiNudXVwByy6tOjlrZPKXg949VzyQMniExERqWRKWqqjWJKR1knFl4s1qREREQkAJS3VUXn1esRST3G9MCIiItWErmkRERGRQFDSIiIiIoGgpEVEREQCQUmLiIiIBIKSFhEREQkEJS0iIiISCEpaREREJBCUtIiIiEggKGkRERGRQNAdcSPYlXWMMY+tY1fWMbq0aVLV4Ui47H/GdhdfjadUY53IyODjn4yvkm3XS0yg9cyZlb7dg/ffzzfpGZW+3TxVtd9S8yhpKaBL2++SlC5tmuSblmrg26/g4J6ix1XSeEo1Vr3EhCrb9omMqksavknP4ERGBvUTKn//q3K/peZR0lLA3Zd3reoQpDitk2Diq9GXazylGqsqv+1XVe9OnvoJCbRb8lSlb7eq91tqFl3TIiIiIoGgpEVEREQCQUmLiIiIBIKSFhEREQkEJS0iIiISCEpaREREJBCUtIiIiEgglOk+LWa2F/gSOAXkOOdSyiMoERERkYLK4+ZyFzvnPiuHekRERESiqlF3xA0fn2Nstvf342diu5tjWtYxr/za0t3Wv6pusV0dZWZnMnH5xFKtF18B8YiISDCU9ZoWB6wws81mdmOkAmZ2o5ltMrNNhw8fLuPmyiZvfI6qUD8hoUrHRakuElokEN+idKlHfIt4EjijnCMSEZGgKGtPy4XOuQNm1gp4w8wynHNrwgs45xYACwBSUlJcGbdXZnnjc9zjf9NfNHxRTOv98rF1ACyd0r/CYqsJpveZXrYKNK6QiEiNVaaeFufcAf/vp8BLQJ/yCEpERESkoFInLWbW0Mwa5z0HhgI7yyswERERkXBlOT30PeAlM8ur51nn3PJyiUpERESkgFInLc65fwLdyzEWERERkah0R1wREREJBCUtIiIiEghKWkRERCQQlLSIiIhIIChpERERkUCoUWMPiZR23CPwhiAo8x19RUSk1JS0SI2R0KL0Yz9lZmeWYyQiIlIaSlqkxihLL0lpe2dERKT86JoWERERCQQlLSIiIhIISlpEREQkEJS0iIiISCAoaREREZFAUNIiIiIigaCkRURERAJBSYuIiIgEgpIWERERCQTdEbcEdmUdY8xj6wDo0rYJd1/eldl/+5BdB44Vu25e+cBZNgMO7ii+XOskuOSBio9HpBo7kZHBxz8ZXyXbrZ9Q+mEqRIJCSUuMurRtEnq+K+u7JGXXgWPsyjpGlzZNIq1WqHzgHNzhPVonFV1GpIarl1h1SUP9hIQq3b5IZVHSEqPwXpK83pY8Xdo0YemU/lHXLVg+cFonwcRXoy9fdGnlxSJSTbWeObOqQxA57emaFhEREQkEJS0iIiISCEpaREREJBCUtIiIiEggKGkRERGRQFDSIiIiIoGgpEVEREQCQUmLiIiIBIKSFhEREQkE3RG3lPLGISruFv6BcHBH9LvaFncL/1jqKE/lFU8lj5U0Z+McMrIzKm175S2hRQLT+0yv6jBE8jl4//18kx7c91WQ1UtMqJK7QCtpKYXwcYi6tGmSbzpwiksAWifFVqaylEc8VTBWUkZ2BpnZmcS3iK/0bZdVZnZmVYcgEtE36RkaLLIKnMioukRRSUspBHK05mjKo7ehuo3uXFw8VTRWUnyLeBYNX1Ql2y6LicsnVnUIIlHVT0ig3ZKnqjqMGqUqRjLPo2taREREJBCUtIiIiEggKGkRERGRQFDSIiIiIoGgpEVEREQCQUmLiIiIBIKSFhEREQkEJS0iIiISCEpaREREJBB0R9xKkjdWUUFd2jY5ve6wexrLzM4s9d1hg3oL/zxl2fey0rhH1d+JjIwquUuqbuFf8yhpqQTRxibalXWskiOR0kpoUbZ/jPEt4stcR1Wpyrg17lH1Vy+x6o6P+gkJVbp9qXxKWipBtJ6USD0vUj3V5G/6VbnvGveo+quKkX6l5tI1LSIiIhIISlpEREQkEJS0iIiISCAoaREREZFAUNIiIiIigaCkRURERAJBSYuIiIgEQpmSFjMbbmaZZvZ/ZjajvIISERERKajUSYuZ1QYeAS4BugDXmlmX8gpMREREJFxZelr6AP/nnPunc+5b4DlgVPmEJSIiIpKfOedKt6LZVcBw59xkf/onQF/n3C0Fyt0I3OhPxgPlOZhIS+CzcqzvdKf2ip3aqmTUXiWj9oqd2qpkTof2auecOzvSgrKMPWQR5hXKgJxzC4AFZdhO9ADMNjnnUiqi7tOR2it2aquSUXuVjNordmqrkjnd26ssp4f2AeeGTccBB8oWjoiIiEhkZUla3gc6m1kHMzsDGAv8tXzCEhEREcmv1KeHnHM5ZnYL8DpQG/ijc+7DcossNhVy2uk0pvaKndqqZNReJaP2ip3aqmRO6/Yq9YW4IiIiIpVJd8QVERGRQFDSIiIiIoEQiKSluOECzPN7f/l2M+tVFXFWBzG0VYKZrTOzb8zsjqqIsTqJob3G+cfUdjN7z8y6V0Wc1UUM7TXKb6ttZrbJzAZURZzVQazDnJjZBWZ2yr/3VY0Vw7E1yMy+8I+tbWY2qyrirC5iOb78NttmZh+a2erKjrFCOOeq9QPvIt9/AB2BM4APgC4FyowAluHdO6YfsKGq467GbdUKuAD4DXBHVcccgPb6AdDcf35JTT22StBejfjuWrlkIKOq466ubRVW7i3gNeCqqo67OrcXMAj4e1XHWh0eMbZXM2AXcJ4/3aqq4y6PRxB6WmIZLmAU8JTzrAeamVmbyg60Gii2rZxznzrn3gdOVkWA1Uws7fWec+5zf3I93v2IaqpY2uu48/9DAg2JcMPJGiLWYU5+CvwF+LQyg6uGNCxMycTSXj8GXnTO/Qu8//2VHGOFCELScg7wSdj0Pn9eScvUBGqHkilpe12P16NXU8XUXmZ2hZllAK8Ckyoptuqm2LYys3OAK4D5lRhXdRXre7G/mX1gZsvMrGvlhFYtxdJe3weam9kqM9tsZuMrLboKVJbb+FeWWIYLiGlIgRpA7VAyMbeXmV2Ml7TU2Gs0iH3ojpeAl8wsFfhP4IcVHVg1FEtbPQxMd86dMotUvEaJpb224I1Jc9zMRgAvA50rOrBqKpb2qgP0BgYDDYB1ZrbeOfdRRQdXkYKQtMQyXICGFPCoHUompvYys2RgIXCJc+5IJcVWHZXo+HLOrTGz882spXMu6AO4lVQsbZUCPOcnLC2BEWaW45x7uVIirF6KbS/n3LGw56+Z2aM19NiC2D8XP3POfQV8ZWZrgO5AoJOWIJweimW4gL8C4/1fEfUDvnDOZVV2oNWAhlYomWLby8zOA14EfhL0byjlIJb26mT+p7D/K74zgJqY6BXbVs65Ds659s659sALwE01NGGB2I6t1mHHVh+8z6+aeGxBbP/rXwEGmlkdMzsT6AukV3Kc5a7a97S4KMMFmNlUf/l8vCvvRwD/B/wbmFhV8ValWNrKzFoDm4AmQK6Z/QzvqvNj0eo9XcV4bM0CzgIe9f9f5rjTeATVosTYXlfifYE4CXwNjAm7MLfGiLGtxBdje10FTDOzHLxja2xNPLYgtvZyzqWb2XJgO5ALLHTO7ay6qMuHbuMvIiIigRCE00MiIiIiSlpEREQkGJS0iIiISCAoaREREZFAUNIiIiIigaCkRWoUfzTdvFFPPzCzn5tZLX9Zipn9voh125vZjysv2kLbv9XM0s3smQrezs/8+zpURN1V2oaVycxeM7Nm/uOmsPltzeyFctrGXjPbYWZl/hm+mf3WzA6aRn+Xakw/eZYaxcyOO+ca+c9bAc8C7zrn7o5h3UF4I2NfVqFBRt9+Bt5defcUmF/HOZdTjtvZC6REutOomdV2zp0qQ92DKEMblnX7VcHM2uONTtytAureS5TXqpT13QMcd87NLY/6RMqbelqkxvJHPb0RuMW/m/IgM/s7gJld5PfIbDOzrWbWGHgA7w6T28zsNr/X4B0z2+I/fuCvO8i8QcpeMLMMM3sm7E6eF5jZe34vz0Yza2xmtf1vue+b2XYzm1IwVjObjzcM/V/9bd9jZgvMbAXwlJm1M7OV/vorzbuTL2b2pJn9r5m9bWb/9Pfrj36PzZMRtnMr0BZ428ze9ucdN7N7zWwD3oB1e82spb8sxcxW+c8b+nW/77dZpFF6C7ZhfTNb5PcWbDVvjKeCMQ3y438W2FFUe5nZL/26PjCzB/x5PcxsvV/2JTNrXtRx4bftEjN7y8x2m9kN/nzzt7vT38YYf34bM1vj79NOMxvoz89rpweA8/3lv/WPm51+mYj7b2ZpZvaimS33Y/jvomIOiz3S8ZVmZi+b2d/MbI+Z3WJeD+NWv11axFK3SLXgnNNDjxrzwPsWWXDe58D3gEF434gB/gZc6D9vhHf36NByf/6ZQH3/eWdgk/98EPAF3nggtYB1eAMtngH8E7jAL9fEr/dG4E5/Xj28OxZ3iBDnXqCl//weYDPQICzeCf7zScDL/vMn8YatN7yh648BSX5cm4EeRW3Hn3bANVHiSAFW+c/vB67znzfDG+OkYYG6C7bh7cAi/3kC8K+8Ni2wzld5bRKtvYBLgPeAM/1lLfy/24GL/Of3Ag8Xc4zcA3yAN8hcS7zRdNvi3e33Dbw7kH7Pj7WNvw+/9tetDTQObyegPbAzrP7QdLT9B9LwjpWm/vTHwLnFHBPRjq80vLuFNwbOxjs2p/plHgJ+VmDf76jq96keekR7qKdFJPKIqe8CD/o9D81c5NMvdYHHzWwH8DzQJWzZRufcPudcLrAN74MqHshyzr0P3gBwfr1D8W59vw3YgDdsQCyj1/7VOfe1/7w/3qkugCXkH436b845B+wADjnndvhxfejHVZxTwF9iKDcUmOHvxyq8D9vzillngB8vzrkMvA/n70cot9F9d1osWnv9EC8B+LdfX7aZNcV7/Vb76y4GUmPYl1ecc18777TL20AfP9Y/OedOOecOAauBC/DGgZlo3qmVJOfclzHUH8v+r3TOfeGcOwHsAtoVU1e04wvgbefcl865w3hJy9/8+TuI7RgQqRaq/dhDIhXJzDrifSh/CiTmzXfOPWBmr+KNabXezH4YYfXbgEN4I6fWAk6ELfsm7PkpvPeaUXj4ePz5P3XOvV7C8L8qYln4dvJiyS0QVy6x/Q844fJfR5LDd6eW64fNN+BK51xmDHWGrxOL8H2N2F5mNpzI7VsaBetxRInVeaNZpwKXAkvM7LfOuadi3E5R+x/pGCqurmj7X/B1Dz8m9DkggaGeFqmxzOxsYD4wz++JCF92vt8jMQfv9EMC8CVeF3uepnjfbHOBn+CdGihKBtDWzC7wt9HYzOrgDXo2zczq+vO/b2YNS7g77+GN9AowDlhbwvXDFdzPgvYCvf3nV4bNfx34qVno+p2eMdS9Bi9ezOz7eD0zxSU90dprBTDJ/F8+mVkL59wXwOd515ngvU6rI1VawCj/epOz8E5Pve/HOsa/puZsvB6bjWbWDvjUOfc48ATQq5h9Dlea/Y8m2vElctrQAS01TQP/tEJdvB6DJcCDEcr9zL8o8hRe1/wyvG+lOWb2Ad61Io8CfzGzq/FOIRTV84Fz7lv/4s0/mFkDvJFqfwgsxOui3+J/4B8GflTC/boV+KOZ/cJfvywjnS8AlplZlnOu0IWxwGzgCTObiXd6Js9/Ag8D2/392AsU/JXQdgq34Xz/FFsOkOac+4aiRWwv59xyM+sBbDKzb/FGf58JTPC3cSbeNR8TAczsXrzrkP4aYRsbgVfxkoj/dM4dMLOX8E7DfYDXo/FL59xBM5sA/MK8ka2PA+PDK3LOHTGzd/2Lb5cBj4Qtjrj/ft5XIkUcXyKnDf3kWUQkjAXoZ7+mnzxLDaPTQyIiwXUYWGnldHM54DqK6TEUqUrqaREREZFAUE+LiIiIBIKSFhEREQkEJS0iIiISCEpaREREJBCUtIiIiEgg/H9gqtHBFq3tqQAAAABJRU5ErkJggg==\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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MWJE1DTLli1j27ZtbNu2jYyMDMaNG0dGRkbMZbn//vtjTlueTp48SdWqVaNOR+KcwzlHlSrB/30+adIkJk6cSFpaGmPHjuXxxx9n3LhxBdLk5uYybdo01q9fj5nRtWtXBg4cSKNGjXjrrbdC6W644QYGDRp0pnehXAT/SIqICACpqak0bty42DQvvfQSI0aMwMzo2bMnBw4cICcnp0i6uLg47rrrLlJSUujbty/79u0DvMDo+eef5+DBgyQkJJCdnQ3A8OHDmTNnDgC/+93vuPTSS0lKSmLq1Kkllvupp56ie/fuJCcnM2bMGE6ePBkqw5QpU+jRowdr1qwpMv3www/TqVMnOnXqxB/+8AcAduzYQfv27bnjjjtISUnh008/jZpvnz59mDhxIqmpqbRv35533nmHIUOG0K5dO+69994Syzdu3Di6detGx44dC+xn69atmTp1KikpKXTu3JmsrKwS66A4zjneeOMNbrzxRgBGjhzJiy++WCTdq6++Sr9+/WjcuDGNGjWiX79+vPLKKwXSfPnll7zxxhsRW1qOHDlCWloaSUlJDBs2jCNHjoSWLV++nF69epGSksLQoUM5fPgwAEuXLiUxMZHevXszYcIErr322tPa15IoaBEROY/s2rWLiy66KDQdHx/Prl27iqT76quvSElJYePGjVx++eVMmzatwPIGDRowc+ZM0tPTefbZZ/niiy/48Y9/zPLly9m2bRvr1q1j06ZNbNiwgVWrVkUtT2ZmJosWLeLtt99m06ZNVK1alYULF4bK0KlTJzIyMujdu3eB6dq1azNv3jwyMjJYu3Ytc+bM4d133wUgOzubESNG8O6779KqVSsGDBjA7t27I+Zfo0YNVq1axdixYxk0aBCPPvooW7ZsYf78+ezfv7/Y8v36179m/fr1bN68mTfffJPNmzeHttukSRM2btzIuHHjeOihh4rkm52dHbpcU/h14MCBAmn3799Pw4YNqVatWrHHLJZju2TJEvr27Uv9+vWLrP/nP/+ZOnXqsHnzZu655x42bNgAwOeff8706dNZsWIFGzdupFu3bjz88MMcPXqUMWPGsGzZMlavXh0KbCuSLg+JiJxHnHNF5kV6iqNKlSoMGzYMgB/96EcMGTKkSJp+/fqxePFixo8fz3vvvQd4v8iXL19Oly5dADh8+DDbtm0jNTU1Ynlef/11NmzY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cs7TPS0iIiISCApaREREJBAUtIiIiEggKGgRERGRQFDQIiIiIoGgoEVEREQCQUGLiIiIBIKCFhEREQkEBS0iIiISCApaREREJBAUtIiIiEggKGgRERGRQFDQIiIiIoGgoEVEREQCQUGLiIiIBIKCFhEREQkEBS0iIiISCApaREREJBAUtIiIiEggKGgRERGRQFDQIiIiIoGgoEVEREQCQUGLiIiIBIKCFhEREQkEBS0iIiISCApaREREJBAUtIiIiEggKGgRERGRQFDQIiIiIoGgoEVEREQCQUGLiIiIBEKJQYuZXWRm/zSzTDP7wMx+6s+/z8x2mdkm/zWg4osrIiIi56tqMaTJA+5yzm00s3rABjN7zV/2iHPuoYornoiIiIinxKDFOZcD5PjvvzSzTODCii5Yedqac4hhj60BoEPL+ky9rmPxKyybDHvej7zM9np/513j/W3eGa5+sJxKKiIiItGU6p4WM2sNdAEy/Fl3mtlmM/uLmTWKss7tZrbezNbv27fv9EpbBh1a1qdDi/qAF7xs3X2o5JX2vB89aClLOhERETltsVweAsDM4oC/Aj9zzh0ysz8D/wM4/+/vgdGF13POzQZmA3Tr1s2VR6FLI7xVJb+1JSbNO8OofxSd/8oo72//ed+0toiIiEiFi6mlxcyq4wUsC51zLwA45/Y65046504Bc4DuFVdMEREROd/F8vSQAY8Dmc65h8PmtwhLNhjYUv7FExEREfHEcnnoe8AtwPtmtsmfdzcw3MyS8S4P7QDGVED5RERERIDYnh5aDViERUvLvzgiIiIikalHXBEREQkEBS0iIiISCDE/8nyuGHlwFsybHpqeYV+QxfGCiU58BTXqfvN4c5js3GwSGidUdDFFRESkkPOupaVV3r8LdAiXxXGyCwctNep6rwgSGieQ2DixIosoIiIiEZx3LS1AwY7jXhlFAjCv/7xKLZKIiIgU77xraREREZFgUtAiIiIigaCgRURERAJBQYuIiIgEgoIWERERCQQFLSIiIhII5+cjz+eRo1lZfHLLiErJu2b7RJrffXel5C0iIuceBS3nsJrtK68TvKNZWZWWt4iInJsUtJzDKrOVo7Jad0RE5Nyle1pEREQkEBS0iIiISCAoaBEREZFAUNAiIiIigaCgRURERAJBQYuIiIgEwrnzyPOyybDnfQCm7D/ozZvXgD0r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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig_led_pos, ax_led_pos = make_fig(\"Reconstructed LED position error with {} cameras\".format(camera_count), \"Distance from true to reco. position [cm]\")\n",
+ "fig_mpmt_pos, ax_mpmt_pos = make_fig(\"Reconstructed mPMT position error with {} cameras\".format(camera_count), \"Distance from true to reco. position [cm]\")\n",
+ "fig_mpmt_ang, ax_mpmt_ang = make_fig(\"Reconstructed mPMT orientation error with {} cameras\".format(camera_count), \"Angle between true and reco. orientation [deg]\")\n",
+ "position_errors_8a = {}\n",
+ "centre_errors_8a = {}\n",
+ "orientation_errors_8a = {}\n",
+ "for pixel_error in [1.0, 3.0, 5.0, 10.0]:\n",
+ " print(\"=== Gaussian errors on feature image locations:\", pixel_error, \"===\")\n",
+ " smeared_feature_locations = simulator.get_image_feature_locations(area_restrict=image_area, min_feature_count=2, pixel_error=pixel_error)\n",
+ " led_positions_8a = {k: v for k, v in led_positions.items() if np.any([k in i.keys() for i in smeared_feature_locations.values()])}\n",
+ " fitter = setup_led_simulation(led_positions_8a, smeared_feature_locations, focal_length, principle_point, radial_distortion) \n",
+ " reco_led_positions, position_errors_8a[pixel_error] = run_led_fit(fitter, led_positions_8a)\n",
+ " centre_errors_8a[pixel_error] = get_mpmt_centre_errors(reco_led_positions, mpmt_locations, led_count)\n",
+ " orientation_errors_8a[pixel_error] = get_mpmt_orientation_errors(reco_led_positions, mpmt_orientations, led_count)\n",
+ " ax_led_pos.hist(position_errors_8a[pixel_error], bins=20, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} cm\".format(pixel_error, position_errors_8a[pixel_error].mean()))\n",
+ " ax_mpmt_pos.hist(centre_errors_8a[pixel_error], bins=15, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} cm\".format(pixel_error, centre_errors_8a[pixel_error].mean()))\n",
+ " ax_mpmt_ang.hist(orientation_errors_8a[pixel_error], bins=15, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} deg\".format(pixel_error, orientation_errors_8a[pixel_error].mean()))\n",
+ "ax_led_pos.legend(loc='upper right')\n",
+ "ax_mpmt_pos.legend(loc='upper right')\n",
+ "ax_mpmt_ang.legend(loc='upper right')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 39,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "reco_errors, reco_transformed, scale, R, translation, _ = fit.kabsch_errors(led_positions, reco_led_positions)\n",
+ "\n",
+ "reco_cam_orientations, reco_cam_positions = fit.camera_world_poses(fitter.camera_rotations, fitter.camera_translations)\n",
+ "cam_orientations_transformed = np.matmul(R, reco_cam_orientations)\n",
+ "cam_positions_translated = reco_cam_positions - translation\n",
+ "cam_positions_transformed = scale*R.dot(cam_positions_translated.transpose()).transpose()\n",
+ "\n",
+ "plot_reconstruction(reco_transformed, cam_positions_transformed)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Simulation with Sony a7R-IV"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 45,
+ "metadata": {
+ "pycharm": {
+ "is_executing": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "ratio = np.array([9504/6000,6336/4000])\n",
+ "focal_length = np.array([2925.84685880484, 2930.0351899542])*ratio\n",
+ "principle_point = np.array([3000, 2000])*ratio\n",
+ "radial_distortion = np.array([-0.251288719187471, 0.0622370807856553])#[-0.28009, 0.11246, -0.02736])\n",
+ "tangential_distortion = np.array([0, 0])\n",
+ "camera_matrix = fit.build_camera_matrix(focal_length, principle_point)\n",
+ "distortion = fit.build_distortion_array(radial_distortion, tangential_distortion)\n",
+ "image_size = np.array([9504, 6336])\n",
+ "image_area = [[0,image_size[0]],[0,image_size[1]]]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 4 camera configuration"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 46,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "camera_radial_position = 175.0\n",
+ "camera_halfz_position = 160.0\n",
+ "camera_positions = np.array([\n",
+ " [0, camera_halfz_position, camera_radial_position],\n",
+ " [0, camera_halfz_position, -camera_radial_position],\n",
+ " [camera_radial_position, -camera_halfz_position, 0],\n",
+ " [-camera_radial_position, -camera_halfz_position, 0]])\n",
+ "camera_directions = [[0, -1.1, -1],\n",
+ " [0, -1.1, 1],\n",
+ " [-1, 1.1, 0],\n",
+ " [1, 1.1, 0]]\n",
+ "camera_directions = camera_directions / linalg.norm(camera_directions, axis=1, keepdims=True)\n",
+ "camera_rolls = np.array([0.0, 0.0, 0.0, 0.0])#[np.pi/2, np.pi/2, np.pi/2, np.pi/2])\n",
+ "camera_rotations, camera_translations = fit.camera_poses(camera_positions, camera_directions, camera_rolls)\n",
+ "camera_count = camera_positions.shape[0]\n",
+ "simulator = fit.PhotogrammetrySimulator(led_positions, focal_length, principle_point, camera_rotations, camera_translations, radial_distortion, tangential_distortion)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 47,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "=== Gaussian errors on feature image locations: 1.0 ===\n",
+ "4 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 21.520390402995194 max: 185.70287979566353\n",
+ "image 1 reprojection errors: average: 22.26358912963671 max: 267.1689273880863\n",
+ "image 2 reprojection errors: average: 21.984447896212796 max: 222.64995498925018\n",
+ "image 3 reprojection errors: average: 22.211958002703994 max: 283.77446306759606\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 1.8934e+06 6.15e+06 \n",
+ " 1 2 3.6471e+03 1.89e+06 6.72e+01 1.95e+05 \n",
+ " 2 3 1.3059e+03 2.34e+03 4.38e+00 2.03e+03 \n",
+ " 3 4 1.3035e+03 2.45e+00 1.21e-01 6.84e+02 \n",
+ " 4 5 1.3029e+03 5.78e-01 3.15e-02 1.28e+02 \n",
+ " 5 6 1.3027e+03 2.18e-01 1.61e-02 8.96e+01 \n",
+ " 6 7 1.3026e+03 1.04e-01 8.21e-03 2.85e+01 \n",
+ " 7 8 1.3025e+03 5.72e-02 4.60e-03 2.74e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 8, initial cost 1.8934e+06, final cost 1.3025e+03, first-order optimality 2.74e+01.\n",
+ "mean reprojection error: 0.6388473110821935\n",
+ "max reprojection error: 2.6315289284078736\n",
+ "mean reconstruction error: 0.07395240275817924\n",
+ "max reconstruction error: 0.32834927168588207\n",
+ "=== Gaussian errors on feature image locations: 3.0 ===\n",
+ "4 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 22.711888913566533 max: 184.46919675350037\n",
+ "image 1 reprojection errors: average: 22.549763121108743 max: 195.46446511289201\n",
+ "image 2 reprojection errors: average: 22.861226692956464 max: 244.14570798266172\n",
+ "image 3 reprojection errors: average: 23.888202881192218 max: 483.1818774192915\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 2.0557e+06 8.29e+06 \n",
+ " 1 2 1.9304e+04 2.04e+06 7.12e+01 7.65e+05 \n",
+ " 2 3 1.2004e+04 7.30e+03 8.34e-01 3.02e+04 \n",
+ " 3 4 1.1981e+04 2.25e+01 2.27e-01 2.31e+03 \n",
+ " 4 5 1.1977e+04 3.99e+00 4.71e-02 2.83e+02 \n",
+ " 5 6 1.1976e+04 1.69e+00 3.37e-02 1.65e+02 \n",
+ " 6 7 1.1975e+04 1.18e+00 1.86e-02 1.21e+02 \n",
+ " 7 8 1.1973e+04 1.23e+00 3.04e-02 1.87e+02 \n",
+ " 8 9 1.1972e+04 8.49e-01 1.13e-02 6.25e+01 \n",
+ " 9 10 1.1972e+04 9.18e-01 2.82e-02 1.87e+02 \n",
+ " 10 11 1.1971e+04 8.16e-01 1.03e-02 4.96e+01 \n",
+ " 11 12 1.1970e+04 8.74e-01 2.92e-02 1.84e+02 \n",
+ " 12 13 1.1969e+04 7.97e-01 9.66e-03 4.00e+01 \n",
+ " 13 14 1.1969e+04 3.66e-01 1.22e-02 9.61e+01 \n",
+ " 14 15 1.1968e+04 4.12e-01 7.55e-03 5.03e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 15, initial cost 2.0557e+06, final cost 1.1968e+04, first-order optimality 5.03e+01.\n",
+ "mean reprojection error: 1.9470376716553401\n",
+ "max reprojection error: 8.76596845887681\n",
+ "mean reconstruction error: 0.22444447866170772\n",
+ "max reconstruction error: 1.0470452237867538\n",
+ "=== Gaussian errors on feature image locations: 5.0 ===\n",
+ "4 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 21.958458395369146 max: 191.04954543740516\n",
+ "image 1 reprojection errors: average: 22.471435732132797 max: 262.8019902299815\n",
+ "image 2 reprojection errors: average: 23.02204045802236 max: 359.79576912051186\n",
+ "image 3 reprojection errors: average: 23.02568017986665 max: 385.04619593986587\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 2.0767e+06 6.26e+06 \n",
+ " 1 2 3.8056e+04 2.04e+06 7.05e+01 1.97e+05 \n",
+ " 2 3 3.5071e+04 2.99e+03 7.76e-01 3.34e+03 \n",
+ " 3 4 3.5017e+04 5.33e+01 7.22e-01 2.76e+03 \n",
+ " 4 5 3.5002e+04 1.52e+01 1.41e-01 3.33e+02 \n",
+ " 5 6 3.4998e+04 3.74e+00 6.49e-02 1.80e+02 \n",
+ " 6 7 3.4996e+04 2.39e+00 3.76e-02 9.19e+01 \n",
+ " 7 8 3.4995e+04 1.15e+00 1.93e-02 7.15e+01 \n",
+ " 8 9 3.4994e+04 6.47e-01 1.02e-02 4.74e+01 \n",
+ " 9 10 3.4994e+04 4.14e-01 7.63e-03 4.95e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 10, initial cost 2.0767e+06, final cost 3.4994e+04, first-order optimality 4.95e+01.\n",
+ "mean reprojection error: 3.3216849504158836\n",
+ "max reprojection error: 13.65539615610933\n",
+ "mean reconstruction error: 0.362063983717853\n",
+ "max reconstruction error: 1.4649157297696673\n",
+ "=== Gaussian errors on feature image locations: 10.0 ===\n",
+ "4 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 23.741571765472546 max: 237.00736672231469\n",
+ "image 1 reprojection errors: average: 24.750985504093233 max: 330.2517559366125\n",
+ "image 2 reprojection errors: average: 24.546894133014984 max: 317.998241764834\n",
+ "image 3 reprojection errors: average: 25.441199696266413 max: 451.3968358437266\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 2.3795e+06 9.89e+06 \n",
+ " 1 2 1.4743e+05 2.23e+06 7.59e+01 5.37e+05 \n",
+ " 2 3 1.3847e+05 8.96e+03 1.14e+00 2.01e+04 \n",
+ " 3 4 1.3829e+05 1.78e+02 1.20e+00 1.79e+04 \n",
+ " 4 5 1.3824e+05 5.21e+01 1.62e-01 1.39e+03 \n",
+ " 5 6 1.3823e+05 8.50e+00 6.18e-02 5.73e+02 \n",
+ " 6 7 1.3823e+05 4.49e+00 2.84e-02 1.76e+02 \n",
+ " 7 8 1.3823e+05 3.11e+00 2.70e-02 3.95e+02 \n",
+ " 8 9 1.3822e+05 3.99e+00 3.19e-02 2.01e+02 \n",
+ " 9 10 1.3822e+05 2.09e+00 1.40e-02 1.29e+02 \n",
+ " 10 11 1.3822e+05 1.96e+00 2.14e-02 1.94e+02 \n",
+ " 11 12 1.3822e+05 1.92e+00 1.33e-02 1.21e+02 \n",
+ " 12 13 1.3821e+05 2.01e+00 2.25e-02 1.98e+02 \n",
+ " 13 14 1.3821e+05 1.92e+00 1.30e-02 1.06e+02 \n",
+ " 14 15 1.3821e+05 1.90e+00 2.19e-02 1.91e+02 \n",
+ " 15 16 1.3821e+05 1.86e+00 1.28e-02 9.95e+01 \n",
+ " 16 17 1.3821e+05 1.85e+00 2.17e-02 1.82e+02 \n",
+ " 17 18 1.3820e+05 1.82e+00 1.26e-02 9.34e+01 \n",
+ " 18 19 1.3820e+05 1.80e+00 2.15e-02 1.79e+02 \n",
+ " 19 20 1.3820e+05 1.77e+00 1.23e-02 8.74e+01 \n",
+ " 20 21 1.3820e+05 1.74e+00 2.11e-02 1.76e+02 \n",
+ " 21 22 1.3820e+05 1.71e+00 1.21e-02 8.14e+01 \n",
+ " 22 23 1.3820e+05 1.69e+00 2.08e-02 1.73e+02 \n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " 23 24 1.3819e+05 1.67e+00 1.19e-02 7.55e+01 \n",
+ " 24 25 1.3819e+05 1.65e+00 2.05e-02 1.71e+02 \n",
+ " 25 26 1.3819e+05 1.63e+00 1.17e-02 7.04e+01 \n",
+ " 26 27 1.3819e+05 1.62e+00 2.04e-02 1.79e+02 \n",
+ " 27 28 1.3819e+05 1.60e+00 1.15e-02 7.26e+01 \n",
+ " 28 29 1.3819e+05 1.59e+00 2.04e-02 1.88e+02 \n",
+ " 29 30 1.3818e+05 1.57e+00 1.15e-02 7.13e+01 \n",
+ " 30 31 1.3818e+05 1.56e+00 2.02e-02 2.08e+02 \n",
+ " 31 32 1.3818e+05 1.54e+00 1.13e-02 7.37e+01 \n",
+ " 32 33 1.3818e+05 1.31e+00 1.70e-02 2.00e+02 \n",
+ " 33 34 1.3818e+05 1.31e+00 1.04e-02 8.36e+01 \n",
+ " 34 35 1.3818e+05 1.30e+00 1.69e-02 2.14e+02 \n",
+ " 35 36 1.3818e+05 1.28e+00 1.03e-02 8.49e+01 \n",
+ " 36 37 1.3818e+05 1.26e+00 1.66e-02 2.26e+02 \n",
+ " 37 38 1.3817e+05 1.24e+00 1.00e-02 9.13e+01 \n",
+ " 38 39 1.3817e+05 1.10e+00 1.43e-02 2.97e+02 \n",
+ " 39 40 1.3817e+05 1.21e+00 1.01e-02 1.38e+02 \n",
+ " 40 41 1.3817e+05 9.00e-01 1.06e-02 2.78e+02 \n",
+ " 41 42 1.3817e+05 8.58e-01 7.20e-03 1.89e+02 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 42, initial cost 2.3795e+06, final cost 1.3817e+05, first-order optimality 1.89e+02.\n",
+ "mean reprojection error: 6.60901696250545\n",
+ "max reprojection error: 30.188506880869582\n",
+ "mean reconstruction error: 0.7296500078394403\n",
+ "max reconstruction error: 3.2310657203260353\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 47,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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3/yffvqJZ555hoEDBxZaZ+7cuezcuZMNGzawadMmRo4cmbesVatWrFy5kj59+uQltKtWrWLatGlFxlFaxV5mMrM6wHKgtl/+ZefcdDNrAiwC2gC7gJ875w7769wN3AzkAHc6596NSfQiIlJi1atXZ+PGjRw5coShQ4eyZcsWOnXqlK9MuKFuwrXgVKtWLW9U51/+8pcMGzasUJn+/fvz0ksvcfvtt/PZZ58B3uCGS5YsoUuXLoD38L0dO3aQmpoaNub333+fdevW5Y0n9MMPP+SN41S9enWuvfbafPuXO71ixQqGDh2aN0L2sGHD+Pjjjxk8eDCtW7fOd3nt7bffDrtt8AbeBEhKSiIxMTFv0M22bduye/duVqxYETG+F198kblz55KdnU1mZibbtm0jOTk5Lx6Abt268corrxTabkkGmoz2M8uVmZnJjTfeyMKFCwtdYrvttttITU2lT58+hdZbunQpEyZMyEuaQsd1Cj1Ox44do0GDBjRo0IA6depw5MiRfKN8l6Vo+sz8CPwf59wxM6sJrDCzxcAw4H3n3EwzmwJMASabWUdgBJAItASWmtmFzrmcmOyBiIicksaNG9O3b1/eeeedQslMXFxcvksve/bsiWoAxnBfnidPnmT79u3UrVuXrKws4uLicM5x9913M378+Khidc4xevTofKM756pTp06+fjGh00WNP5ib4ESjdu3agJe85b7Pnc7Ozo4Y386dO3n44YdZs2YNZ555JmPGjOH48eOF6q1evTrZ2dmFtpuRkZGXLBa0bNmyfMlB06ZNOXLkCNnZ2dSoUaPIz+zo0aNceeWVPPDAA4X6S82YMYODBw/yxBNPhF3XORcxSSruOMVKscmM886E3OdV1/RfDhgC9PXnLwSWAZP9+S84534EdprZF0APoGzGuBcROZ3s3xxVx92o62qeVGSRgwcPUrNmTRo3bswPP/zA0qVLmTx5cqFygwcPZvbs2YwYMYK0tDQaNWqU1xoR6uTJk7z88suMGDGC559/nksuuaRQmUcffZSEhAQeeughxo4dy8qVKxkwYAD33nsvI0eOpH79+uzdu5eaNWtGHDW7X79+DBkyhEmTJtGsWTOysrL47rvvih01OzU1lTFjxjBlyhScc7z66qs888wzRa5zKiLFd/ToUerVq0ejRo04cOAAixcvpm/fvlHXW5KWGTPjsssu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9ttvh902eANvAiQlJZGYmJg36Gbbtm3ZvXs3K1asiBjfiy++yNy5c8nOziYzM5Nt27aRnJycFw9At27deOWVVwpttyQDTUb7mYGXdGzatIl9+/ZxzTXXcN1113HOOefw448/UqdOHdauXcsrr7zC2LFj+fjjj/Otu3TpUiZMmJCXNIUOMhl6nI4dO0aDBg1o0KABderU4ciRI/lG+S5LSmaitXiKNyJtJM2T4IqZ5RePiMgpyv0vvFmzZgwdOpTVq1cXSiLi4uLyXXrZs2dP3npFCfflefLkSbZv307dunXJysoiLi4O5xx3330348ePjypm5xyjR4/mv/7rvwotq1OnTr5+MaHTRY0/mJvgRCP3sky1atXy3udOZ2dnR4xv586dPPzww6xZs4YzzzyTMWPGcPz48UL1Vq9enezs7ELbzcjIyEsWC1q2bFm+5KBp06YcOXKE7OxsatSoEdVn1rJlSxITE/n444+57rrriIuLy0sEhw4dyk03Fe6H5ZyLmCQVd5xiRclMtPZv9l7hRqQtKskRESlCRlZGiTruFldXhyYdiizz/fffc/LkSRo0aMD333/PkiVLwl4CGDx4MLNnz2bEiBGkpaXRqFGjvNaIUCdPnuTll19mxIgRPP/881xyySWFyjz66KMkJCTw0EMPMXbsWFauXMmAAQO49957GTlyJPXr12fv3r3UrFkzbB8NgH79+jFkyBAmTZpEs2bNyMrK4rvvvqN169ZF7m9qaipjxoxhypQpOOd49dVXeeaZZ4pc51REiu/o0aPUq1ePRo0aceDAARYvXkzfvn2jrrckLTNmxmWXXZb3eSxcuJAhQ4YUKrdnzx7OOuss6taty+HDh/nkk0/49a9/DcA111zDBx98wNixY/noo4+48MILC61/+eWXM2fOHPr27UuNGjXIysrK1zpTEZTMlETzJLjprcLz519Z/rGISODFN4kv0/o6NOlQbJ0HDhxg6NChAGRnZ/OLX/yCgQMHAuR10pwwYQKDBg3i7bffpl27dpxxxhnMnx/+jqt69eqxdetWunXrRqNGjVi0aFG+5Z9//jnz5s1j9erVNGjQgNTUVB544AFmzJjB9u3b6d27N+B14n322WcjJjMdO3bkgQce4PLLL+fkyZPUrFmTxx9/vNhkpmvXrowZM4YePXoAMG7cOLp06cKuXbsKlR00aBDz5s2L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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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Qzly5AhAaITfL774gvj4eDIzvR6la665hscffxyA3/72t5x//vkkJydz1113lRrT008/Tb9+/ejVqxfTpk0jNzc3FMOcOXPo378/69evLzL9wAMP0KNHD3r06MFDDz0EwL59+0hMTOTGG2+kT58+BcZZKmzIkCHceuutpKamkpiYyAcffMDYsWPp2rUrd9xxR6nxzZgxg5SUFLp3715gPzt27Mhdd91Fnz59SEpKIuM0xytzzvHWW29x5ZVXAjBp0iRefvnliGWHDh1K06ZNy7R+bm4ut99+O0lJSSQnJ/Pwww+H9mf27NkMHDiQlJQUtm7dyogRIzjvvPNCT1uuKLUmabnrsu4snzYw9ApPYEREaiIzY/jw4fTt25dFixZFLHPgwAHOPffc0HRcXBwHDhwoUu6rr76iT58+bN26lQsvvJC5c+cWWN68eXMWLFhAWloazz33HJ9//jnXX389q1atYs+ePWzatInt27ezZcsW3nnnnWJjTk9PZ/ny5bz33nts376dunXr8swzz4Ri6NGjBxs3bmTQoEEFphs1asSSJUvYuHEjGzZs4PHHH2fbtm2ANxjhxIkT2bZtGx06dGDUqFEcPHgw4vbPOOMM3nnnHaZPn86YMWN45JFH2LVrF08++SRHjx4tMb7f/OY3bN68mR07drB27Vp27NgRqrd169Zs3bqVGTNmMH/+/CLbzczMpFevXhFfx44dK1D26NGjtGjRIjT6cnHHrDjRrr9o0SL27t3Ltm3b2LFjBxMmTAgtO/fcc1m/fj2DBw8OJa4bNmxgzpw5UcdRFrXq8pCISG3y3nvv0b59ez777DOGDRtGQkICqampBcpEGsol0si+derUCY1CfO211zJ27NgiZYYNG8bzzz/PTTfdxIcffgh4g/StWrWK3r17A95D6vbs2VMkjnyrV69my5YtofFyvv7669A4RXXr1uWKK64IlQ2fXrduHZdffnloROexY8fy7rvvMnr0aDp06MCAAQNC67322msRtw3eAJIASUlJdO/ePTR4ZOfOnfn0009Zt25dsfH96U9/YtGiReTk5JCVlcXu3btJTk4OxQPQt29fXnzxxSLbjWXAxGiP2emu/+abbzJ9+vRQchM+blF4O504cYKmTZvStGlTGjZsyLFjxwqMSl2elLSIiNRQ+QMCtmnThssvv5xNmzYVSRbi4uIKXDLZ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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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xtOxY8eoXr161OlInHM456hWLfifzydOnMiECRMYNmwYY8eO5dFHH2XcuHEFyuTl5TF16lTWrFmDmdG5c2cGDBhA48aNeeedd0LlrrrqKgYOHFjZuxAXwT+SIiICQK9evWjSpEmxZV5++WVGjBiBmdG9e3f27t1Lbm5ukXL169fn1ltvJT09nT59+rB7927AS4yee+459u3bR1JSEjk5OQAMHz6cOXPmAPDHP/6RLl26kJaWxpQpU0qM+4knnqBr16507NiRMWPGcOzYsVAMkydPplu3bqxcubLI9MyZM2nfvj3t27fnz3/+MwBbt24lJSWFG2+8kfT0dLZt2xZ1u71792bChAn06tWLlJQU3nvvPQYPHkxiYiJ33nlnifGNGzeOjIwMUlNTC+xn69atmTJlCunp6XTo0IHs7OwS26A4zjneeustrr76agBGjhzJSy+9VKTc66+/Tt++fWnSpAmNGzemb9++vPbaawXKfPPNN7z11lsRe1oOHTrEsGHDSEtLY+jQoRw6dCi0bPHixfTo0YP09HSGDBnCgQMHAHj11VdJTk6mZ8+ejB8/nssvv7xc+1oSJS0iIqeQHTt2cM4554SmExIS2LFjR5FyBw8eJD09nXXr1nHRRRcxderUAssbNmzIrFmzyMzM5JlnnuHrr7/m+uuvZ/HixWzZsoXVq1ezfv161q5dy7Jly6LGs3nzZhYsWMCKFStYv3491atX58knnwzF0L59e7KysujZs2eB6Tp16jB37lyysrJYtWoVc+bM4f333wcgJyeHESNG8P7779OqVSv69+/Pzp07I27/tNNOY9myZYwdO5aBAwdy//33s3HjRubNm8eePXuKje93v/sda9asYcOGDSxdupQNGzaE6m3atCnr1q1j3LhxzJgxo8h2c3JyQpdrCr/27t1boOyePXto1KgRNWrUKPaYxXJsX3zxRfr06UODBg2KrP/ggw9St25dNmzYwB133MHatWsB+Oqrr5g2bRpLlixh3bp1ZGRkMHPmTA4fPsyYMWNYtGgRy5cvDyW2FUmXh0RETiHOuSLzIn2Lo1q1agwdOhSAX/ziFwwePLhImb59+7Jw4UJuuukmPvjgA8D7RL548WI6deoEwIEDB9iyZQu9evWKGM+bb77J2rVr6dKlC+B92m/WrBkA1atX56qrrgqVDZ9evnw5gwYNol69egAMHjyYd955hwEDBtCqVSu6d+8eWu/VV1+N2h4DBgwAoEOHDqSmptKiRQsA2rRpw7Zt21i+fHnU+J599llmz57N0aNHyc3NZdOmTaSlpYXiAejcuTMvvPBCke0mJSWxfv36qHGFi/WYxVLu6aef5rrrrou4nWXLljF+/HgA0tLSQvuyatUqNm3axAUXXADAkSNH6NGjB9nZ2bRp0yb0nJXhw4cze/bsmPaprJS0iIicQhISEgpcMtm+fTstW7Yscb1I/ySPHz/O5s2bqVOnDnl5eSQkJOCc47bbbmPMmDExxeOcY+TIkfz+978vsqx27doF7lsJn470DzpffiITi1q1agFekpb/Pn/66NGjUeP77LPPmDFjBu+99x6NGzcmMzOzwDNH8uuqXr06R48eLbLdnJycUFJY2Ntvv02jRo1C002bNmXv3r0cPXqUGjVqRD1mCQkJvP3226Hp7du307t379D0nj17WL16NS+++GLU9oiWDPXt25enn366wPz8nq3KpKRFRKQCbMrdH/MNtLHU1a5F0e78shgwYACzZs1i2LBhZGVl0bBhw1DvQrjjx4/z3HPPMWzYMJ566il69uxZpMx9991HSkoK99xzD6NHj2blypVceuml/Pa3v+XnP/859evXZ8eOHdSsWTPUO1FYnz59GDhwIBMmTKBZs2bk5eXxzTff0KpVq2L3o1evXmRmZjJp0iScc7z44os8/vjjZWuUYkSLb//+/dSrV4+GDRuya9cuFi1aVCBBKElpelrMjIsvvjh0PObPnx/xRtpLL72U22+/na+//hrwer3Ck62FCxdy+eWXU7t27Yjb6dWrF08++SQXX3wxGzduDF3u6t69OzfddBOffPIJbdu25dtvv2X79u0kJyfz6aefsnXrVlq3bs2CBQti3v+yOimTlkjPSNAzDkSksrRrGZ8EI1RfiwYx1Tl8+HDefvttvvrqKxISEpg6dSrXXnstDz30EABjx46lf//+vPrqq7Rt25a6desyd+7ciHXVq1ePjz76iM6dO9OwYcMi/5A+/vhjHnnkEVavXs3pp59Or169mDZtGlOnTmXz5s306OF9c6p+/fo88cQTUZOWdu3aMW3aNC655BKOHz9OzZo1uf/++0tMWtLT08nMzKRr164AXHfddXTq1ImtW7cWKdu/f38eeeSRmHqUYo2ve/fudOrUidTUVNq0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fZg0aRL33nsv9957L9OnTy9Q5tixY9x000288cYbJCQk0KVLFwYMGEC7du1i2nZGRgYZGREfrVGh8h9tH2061vWCatGiRWzZsoUtW7aQlZXFuHHjyMrKKlJu3rx5bNu2jezsbKpVq8aXX34JwG9+8xt+85vfAPDKK69w33330aRJk0rdh9JQT4uIyEmiV69eEf/hvPzyy4wcORKAkSNH8tJLLxUps3r1atq2bUubNm047bTTGDZsGC+//HKRcpmZmYwdO5YLL7yQ8847j7///e+AN17O5ZdfDsD48eO5++67AXj99dfp1asXx48fZ+3atVx00UV07tyZSy+9lNzc3GL351//+hf9+vWjc+fOXHjhhWT7vVeZmZnccsstXHzxxUycOLHI9Pr16+nevTtpaWkMGjQo1LPUu3dvbr/9di666CL+93//N+p2582bx5VXXskVV1zBueeey6xZs5g5cyadOnWie/fuoZ6IaPG98sordOvWjU6dOvHjH/+YXbt2AXDXXXcxevRoevfuTZs2bUK9HeXx8ssvM2LECMyM7t27s3fv3ojt+uCDDzJ58mSqVfP+7Ud6QvHTTz/N8OHDI25n7ty5nHfeeVx00UWsWLEiNH/37t1cddVVdOnShS5duoSW7d69m759+5Kens6YMWNo1aoVX331Vbn3V0mLiMhJbteuXaHxhVq0aBH6lB1ux44dnHPOOaHphIQEduzYEbG+rVu3snTpUv7xj38wduzYAgMFgtezs2DBAv75z38yfvz4AqMLP/fcc6xdu5bRo0dzxx13FBv3DTfcwP/93/+xdu1aZsyYwY033hha9vHHH7NkyRL+9Kc/FZkeMWIE06dPZ8OGDXTo0IGpU6eG1tu7dy9Lly7l1ltv5aGHHgoNcVDYxo0beeqpp1i9ejV33HEHdevW5f3336dHjx489thjxcbXs2dPVq1axfvvv8+wYcP4wx/+EKo3Ozub119/ndWrVzN16lS+//77ItseOnRo6JJN+Ct/u+FiPW7/+te/WLBgARkZGVx22WVs2bKlwPJvv/2W1157rcCo2vlyc3OZMmUKK1as4I033mDTpk2hZb/61a+YMGEC7733Hs8//zzXXXcdAFOnTuVHP/oR69atY9CgQfz73/+O2M6lFfy+MRERKbdIQ7pEGvEX4Kc//SnVqlUjMTGRNm3ahHoY8tWtW5c5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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fig_led_pos, ax_led_pos = make_fig(\"Reconstructed LED position error with {} cameras\".format(camera_count), \"Distance from true to reco. position [cm]\")\n",
+ "fig_mpmt_pos, ax_mpmt_pos = make_fig(\"Reconstructed mPMT position error with {} cameras\".format(camera_count), \"Distance from true to reco. position [cm]\")\n",
+ "fig_mpmt_ang, ax_mpmt_ang = make_fig(\"Reconstructed mPMT orientation error with {} cameras\".format(camera_count), \"Angle between true and reco. orientation [deg]\")\n",
+ "position_errors_4_a7r = {}\n",
+ "centre_errors_4_a7r = {}\n",
+ "orientation_errors_4_a7r = {}\n",
+ "for pixel_error in [1.0, 3.0, 5.0, 10.0]:\n",
+ " print(\"=== Gaussian errors on feature image locations:\", pixel_error, \"===\")\n",
+ " smeared_feature_locations = simulator.get_image_feature_locations(area_restrict=image_area, min_feature_count=2, pixel_error=pixel_error)\n",
+ " led_positions_4_a7r = {k: v for k, v in led_positions.items() if np.any([k in i.keys() for i in smeared_feature_locations.values()])}\n",
+ " fitter = setup_led_simulation(led_positions_4_a7r, smeared_feature_locations, focal_length, principle_point, radial_distortion) \n",
+ " reco_led_positions, position_errors_4_a7r[pixel_error] = run_led_fit(fitter, led_positions_4_a7r)\n",
+ " centre_errors_4_a7r[pixel_error] = get_mpmt_centre_errors(reco_led_positions, mpmt_locations, led_count)\n",
+ " orientation_errors_4_a7r[pixel_error] = get_mpmt_orientation_errors(reco_led_positions, mpmt_orientations, led_count)\n",
+ " ax_led_pos.hist(position_errors_4_a7r[pixel_error], bins=20, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} cm\".format(pixel_error, position_errors_4_a7r[pixel_error].mean()))\n",
+ " ax_mpmt_pos.hist(centre_errors_4_a7r[pixel_error], bins=15, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} cm\".format(pixel_error, centre_errors_4_a7r[pixel_error].mean()))\n",
+ " ax_mpmt_ang.hist(orientation_errors_4_a7r[pixel_error], bins=15, histtype='step', lw=1.5, label=\"{} pixel error: mean = {:.2f} deg\".format(pixel_error, orientation_errors_4_a7r[pixel_error].mean()))\n",
+ "ax_led_pos.legend(loc='upper right')\n",
+ "ax_mpmt_pos.legend(loc='upper right')\n",
+ "ax_mpmt_ang.legend(loc='upper right')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## 6 camera configuration A"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 48,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "camera_radial_position = 175.0\n",
+ "camera_halfz_position = 160.0\n",
+ "camera_positions = np.array([\n",
+ " [-camera_radial_position, -camera_halfz_position, 0],\n",
+ " [0.5*camera_radial_position, -camera_halfz_position, -camera_radial_position*np.sqrt(3)/2],\n",
+ " [0.5*camera_radial_position, -camera_halfz_position, camera_radial_position*np.sqrt(3)/2],\n",
+ " [camera_radial_position, camera_halfz_position, 0],\n",
+ " [-0.5*camera_radial_position, camera_halfz_position, -camera_radial_position*np.sqrt(3)/2],\n",
+ " [-0.5*camera_radial_position, camera_halfz_position, camera_radial_position*np.sqrt(3)/2]])\n",
+ "camera_directions = [[1, 1.1, 0],\n",
+ " [-0.5, 1.1, np.sqrt(3)/2],\n",
+ " [-0.5, 1.1, -np.sqrt(3)/2],\n",
+ " [-1, -1.1, 0],\n",
+ " [0.5, -1.1, np.sqrt(3)/2],\n",
+ " [0.5, -1.1, -np.sqrt(3)/2]]\n",
+ "camera_directions = camera_directions / linalg.norm(camera_directions, axis=1, keepdims=True)\n",
+ "camera_rolls = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0])#[np.pi/2, np.pi/2, np.pi/2, np.pi/2])\n",
+ "camera_rotations, camera_translations = fit.camera_poses(camera_positions, camera_directions, camera_rolls)\n",
+ "camera_count = camera_positions.shape[0]\n",
+ "simulator = fit.PhotogrammetrySimulator(led_positions, focal_length, principle_point, camera_rotations, camera_translations, radial_distortion, tangential_distortion)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 49,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "=== Gaussian errors on feature image locations: 1.0 ===\n",
+ "6 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 22.821718286013542 max: 448.8736259901742\n",
+ "image 1 reprojection errors: average: 22.507822032865693 max: 281.5605900558616\n",
+ "image 2 reprojection errors: average: 22.50313075982111 max: 225.6310710251895\n",
+ "image 3 reprojection errors: average: 22.64851799167888 max: 273.8561613485784\n",
+ "image 4 reprojection errors: average: 22.418917817688715 max: 282.37009397011036\n",
+ "image 5 reprojection errors: average: 22.21851888722326 max: 244.10096633609555\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 3.1149e+06 1.27e+07 \n",
+ " 1 2 7.4368e+03 3.11e+06 6.91e+01 2.02e+05 \n",
+ " 2 3 2.8400e+03 4.60e+03 3.02e+00 4.37e+03 \n",
+ " 3 4 2.8005e+03 3.95e+01 1.12e+00 2.73e+03 \n",
+ " 4 5 2.7908e+03 9.68e+00 2.00e-01 4.19e+02 \n",
+ " 5 6 2.7893e+03 1.54e+00 6.48e-02 1.95e+02 \n",
+ " 6 7 2.7888e+03 5.11e-01 1.89e-02 6.17e+01 \n",
+ " 7 8 2.7885e+03 2.32e-01 1.23e-02 3.82e+01 \n",
+ " 8 9 2.7884e+03 1.73e-01 8.05e-03 2.79e+01 \n",
+ " 9 10 2.7882e+03 1.51e-01 8.87e-03 4.04e+01 \n",
+ " 10 11 2.7881e+03 1.40e-01 6.92e-03 2.52e+01 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 11, initial cost 3.1149e+06, final cost 2.7881e+03, first-order optimality 2.52e+01.\n",
+ "mean reprojection error: 0.7868649617435626\n",
+ "max reprojection error: 3.129771899326001\n",
+ "mean reconstruction error: 0.05711351307439404\n",
+ "max reconstruction error: 0.3396403915949969\n",
+ "=== Gaussian errors on feature image locations: 3.0 ===\n",
+ "6 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 21.862734373565793 max: 186.16706774726129\n",
+ "image 1 reprojection errors: average: 22.054740438011294 max: 189.43979052623146\n",
+ "image 2 reprojection errors: average: 22.276412178476143 max: 197.06857257346005\n",
+ "image 3 reprojection errors: average: 22.52924304280216 max: 246.73167389704759\n",
+ "image 4 reprojection errors: average: 22.076165806960965 max: 260.7772267231314\n",
+ "image 5 reprojection errors: average: 21.89693685872337 max: 191.36005640244286\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 2.8280e+06 1.06e+07 \n",
+ " 1 2 2.6974e+04 2.80e+06 6.85e+01 1.50e+05 \n",
+ " 2 3 2.5350e+04 1.62e+03 1.11e+00 1.40e+03 \n",
+ " 3 4 2.5231e+04 1.19e+02 1.47e+00 7.51e+02 \n",
+ " 4 5 2.5184e+04 4.66e+01 2.78e-01 2.06e+02 \n",
+ " 5 6 2.5177e+04 7.04e+00 1.14e-01 1.93e+02 \n",
+ " 6 7 2.5172e+04 5.12e+00 6.15e-02 2.42e+02 \n",
+ " 7 8 2.5170e+04 2.14e+00 3.36e-02 1.23e+02 \n",
+ " 8 9 2.5168e+04 1.77e+00 2.79e-02 2.30e+02 \n",
+ " 9 10 2.5167e+04 1.68e+00 2.87e-02 1.29e+02 \n",
+ " 10 11 2.5165e+04 1.61e+00 2.60e-02 2.38e+02 \n",
+ " 11 12 2.5163e+04 1.54e+00 2.68e-02 1.31e+02 \n",
+ " 12 13 2.5162e+04 1.46e+00 2.39e-02 2.41e+02 \n",
+ " 13 14 2.5161e+04 1.35e+00 2.37e-02 1.29e+02 \n",
+ " 14 15 2.5159e+04 1.25e+00 2.06e-02 2.38e+02 \n",
+ " 15 16 2.5158e+04 1.16e+00 2.06e-02 1.24e+02 \n",
+ " 16 17 2.5157e+04 1.09e+00 1.82e-02 2.31e+02 \n",
+ " 17 18 2.5156e+04 1.01e+00 1.83e-02 1.19e+02 \n",
+ " 18 19 2.5155e+04 1.02e+00 1.78e-02 2.39e+02 \n",
+ " 19 20 2.5154e+04 8.98e-01 1.57e-02 1.18e+02 \n",
+ " 20 21 2.5153e+04 1.01e+00 1.88e-02 3.02e+02 \n",
+ " 21 22 2.5152e+04 7.91e-01 1.19e-02 1.07e+02 \n",
+ " 22 23 2.5152e+04 3.90e-01 6.49e-03 1.81e+02 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 23, initial cost 2.8280e+06, final cost 2.5152e+04, first-order optimality 1.81e+02.\n",
+ "mean reprojection error: 2.378321481670786\n",
+ "max reprojection error: 8.340049722185547\n",
+ "mean reconstruction error: 0.17568703377497497\n",
+ "max reconstruction error: 1.1540460514721482\n",
+ "=== Gaussian errors on feature image locations: 5.0 ===\n",
+ "6 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 22.79238975954296 max: 289.7260298321374\n",
+ "image 1 reprojection errors: average: 21.96597762744127 max: 248.8319462627144\n",
+ "image 2 reprojection errors: average: 22.131168968436516 max: 190.10154718052814\n",
+ "image 3 reprojection errors: average: 22.04396962605084 max: 454.3865274451203\n",
+ "image 4 reprojection errors: average: 21.819963266705855 max: 191.14970620162597\n",
+ "image 5 reprojection errors: average: 22.532078742252363 max: 206.8246314333731\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 2.8597e+06 7.23e+06 \n",
+ " 1 2 7.2424e+04 2.79e+06 6.83e+01 3.50e+05 \n",
+ " 2 3 6.9468e+04 2.96e+03 1.58e+00 8.35e+03 \n",
+ " 3 4 6.9240e+04 2.28e+02 1.70e+00 6.36e+03 \n",
+ " 4 5 6.9137e+04 1.03e+02 3.82e-01 6.00e+02 \n",
+ " 5 6 6.9120e+04 1.67e+01 1.55e-01 5.85e+02 \n",
+ " 6 7 6.9108e+04 1.18e+01 8.36e-02 2.38e+02 \n",
+ " 7 8 6.9103e+04 4.89e+00 4.10e-02 2.55e+02 \n",
+ " 8 9 6.9099e+04 4.02e+00 3.42e-02 2.09e+02 \n",
+ " 9 10 6.9095e+04 3.94e+00 3.68e-02 2.27e+02 \n",
+ " 10 11 6.9092e+04 3.86e+00 3.35e-02 1.97e+02 \n",
+ " 11 12 6.9088e+04 3.78e+00 3.60e-02 2.06e+02 \n",
+ " 12 13 6.9084e+04 3.73e+00 3.30e-02 1.84e+02 \n",
+ " 13 14 6.9080e+04 3.67e+00 3.56e-02 2.00e+02 \n",
+ " 14 15 6.9077e+04 3.48e+00 3.10e-02 1.61e+02 \n",
+ " 15 16 6.9074e+04 3.43e+00 3.45e-02 1.87e+02 \n",
+ " 16 17 6.9070e+04 3.38e+00 3.03e-02 1.85e+02 \n",
+ " 17 18 6.9067e+04 3.34e+00 3.40e-02 1.97e+02 \n",
+ " 18 19 6.9064e+04 3.28e+00 2.97e-02 2.03e+02 \n",
+ " 19 20 6.9060e+04 3.25e+00 3.36e-02 2.08e+02 \n",
+ " 20 21 6.9057e+04 3.19e+00 2.92e-02 2.12e+02 \n",
+ " 21 22 6.9054e+04 3.16e+00 3.33e-02 2.14e+02 \n",
+ " 22 23 6.9051e+04 3.10e+00 2.86e-02 2.14e+02 \n",
+ " 23 24 6.9048e+04 3.06e+00 3.30e-02 2.15e+02 \n",
+ " 24 25 6.9045e+04 3.00e+00 2.81e-02 2.14e+02 \n",
+ " 25 26 6.9042e+04 2.96e+00 3.26e-02 2.18e+02 \n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " 26 27 6.9039e+04 2.91e+00 2.77e-02 2.13e+02 \n",
+ " 27 28 6.9036e+04 2.88e+00 3.22e-02 2.18e+02 \n",
+ " 28 29 6.9033e+04 2.81e+00 2.71e-02 2.06e+02 \n",
+ " 29 30 6.9030e+04 2.78e+00 3.19e-02 2.14e+02 \n",
+ " 30 31 6.9028e+04 2.67e+00 2.58e-02 2.08e+02 \n",
+ " 31 32 6.9025e+04 2.72e+00 3.22e-02 2.30e+02 \n",
+ " 32 33 6.9022e+04 2.66e+00 2.56e-02 2.01e+02 \n",
+ " 33 34 6.9021e+04 1.22e+00 1.26e-02 1.17e+02 \n",
+ " 34 35 6.9020e+04 9.46e-01 1.12e-02 1.60e+02 \n",
+ " 35 36 6.9019e+04 9.40e-01 1.09e-02 1.15e+02 \n",
+ " 36 37 6.9018e+04 9.34e-01 1.11e-02 1.59e+02 \n",
+ " 37 38 6.9017e+04 8.87e-01 1.03e-02 1.10e+02 \n",
+ " 38 39 6.9017e+04 8.40e-01 1.02e-02 1.53e+02 \n",
+ " 39 40 6.9016e+04 8.39e-01 1.00e-02 1.16e+02 \n",
+ " 40 41 6.9015e+04 8.38e-01 1.02e-02 1.54e+02 \n",
+ " 41 42 6.9014e+04 8.31e-01 9.95e-03 1.15e+02 \n",
+ " 42 43 6.9013e+04 8.26e-01 1.01e-02 1.52e+02 \n",
+ " 43 44 6.9012e+04 8.22e-01 9.90e-03 1.14e+02 \n",
+ " 44 45 6.9012e+04 8.17e-01 1.01e-02 1.50e+02 \n",
+ " 45 46 6.9011e+04 8.12e-01 9.86e-03 1.12e+02 \n",
+ " 46 47 6.9010e+04 8.08e-01 1.00e-02 1.48e+02 \n",
+ " 47 48 6.9009e+04 8.03e-01 9.81e-03 1.11e+02 \n",
+ " 48 49 6.9008e+04 7.98e-01 9.94e-03 1.47e+02 \n",
+ " 49 50 6.9008e+04 7.91e-01 9.71e-03 1.12e+02 \n",
+ " 50 51 6.9007e+04 7.75e-01 9.62e-03 1.55e+02 \n",
+ " 51 52 6.9006e+04 7.85e-01 9.68e-03 1.21e+02 \n",
+ " 52 53 6.9005e+04 7.62e-01 9.28e-03 1.58e+02 \n",
+ " 53 54 6.9005e+04 7.77e-01 9.66e-03 1.35e+02 \n",
+ " 54 55 6.9004e+04 7.72e-01 9.26e-03 1.55e+02 \n",
+ " 55 56 6.9003e+04 7.67e-01 9.59e-03 1.34e+02 \n",
+ " 56 57 6.9002e+04 7.59e-01 9.13e-03 1.55e+02 \n",
+ " 57 58 6.9001e+04 7.43e-01 9.27e-03 1.40e+02 \n",
+ " 58 59 6.9001e+04 7.53e-01 9.09e-03 1.65e+02 \n",
+ " 59 60 6.9000e+04 7.38e-01 9.08e-03 1.40e+02 \n",
+ " 60 61 6.8999e+04 6.86e-01 8.08e-03 1.77e+02 \n",
+ " 61 62 6.8999e+04 7.43e-01 9.24e-03 1.75e+02 \n",
+ " 62 63 6.8998e+04 6.60e-01 6.96e-03 1.72e+02 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 63, initial cost 2.8597e+06, final cost 6.8998e+04, first-order optimality 1.72e+02.\n",
+ "mean reprojection error: 3.93161102514504\n",
+ "max reprojection error: 13.95317275359787\n",
+ "mean reconstruction error: 0.2898542552146252\n",
+ "max reconstruction error: 1.8021597218804615\n",
+ "=== Gaussian errors on feature image locations: 10.0 ===\n",
+ "6 images with total of 1584 features\n",
+ "image 0 reprojection errors: average: 24.42884832001907 max: 204.19052467142072\n",
+ "image 1 reprojection errors: average: 24.861555626407068 max: 329.51098954993284\n",
+ "image 2 reprojection errors: average: 25.420273339451597 max: 374.91162553451653\n",
+ "image 3 reprojection errors: average: 24.325791255441985 max: 231.62720190071104\n",
+ "image 4 reprojection errors: average: 25.675480611429162 max: 454.6677484980528\n",
+ "image 5 reprojection errors: average: 25.71749791605633 max: 246.76199955676117\n",
+ " Iteration Total nfev Cost Cost reduction Step norm Optimality \n",
+ " 0 1 3.5852e+06 1.07e+07 \n",
+ " 1 2 2.8563e+05 3.30e+06 7.27e+01 5.38e+05 \n",
+ " 2 3 2.7767e+05 7.96e+03 2.08e+00 1.90e+04 \n",
+ " 3 4 2.7657e+05 1.10e+03 4.34e+00 1.13e+04 \n",
+ " 4 5 2.7634e+05 2.29e+02 4.96e-01 1.44e+03 \n",
+ " 5 6 2.7632e+05 2.34e+01 1.02e-01 3.33e+02 \n",
+ " 6 7 2.7630e+05 1.77e+01 1.05e-01 3.81e+02 \n",
+ " 7 8 2.7628e+05 1.48e+01 7.99e-02 2.71e+02 \n",
+ " 8 9 2.7627e+05 8.67e+00 5.20e-02 3.99e+02 \n",
+ " 9 10 2.7627e+05 4.25e+00 1.98e-02 2.03e+02 \n",
+ " 10 11 2.7627e+05 3.09e+00 2.19e-02 3.35e+02 \n",
+ " 11 12 2.7626e+05 2.90e+00 1.60e-02 2.88e+02 \n",
+ " 12 13 2.7626e+05 3.03e+00 2.16e-02 4.43e+02 \n",
+ " 13 14 2.7626e+05 2.76e+00 1.38e-02 2.68e+02 \n",
+ " 14 15 2.7626e+05 6.27e-01 2.92e-03 1.34e+02 \n",
+ "`xtol` termination condition is satisfied.\n",
+ "Function evaluations 15, initial cost 3.5852e+06, final cost 2.7626e+05, first-order optimality 1.34e+02.\n",
+ "mean reprojection error: 7.855400463165263\n",
+ "max reprojection error: 31.882406803939908\n",
+ "mean reconstruction error: 0.5661356555731609\n",
+ "max reconstruction error: 2.5364666494769206\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 49,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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e2jWrFmx60X68jxx4gTbtm2jVq1aZGVlERcXh3OOe++9l1tuuSWqeJxzjBw5kt/97ncFltWsWTPPdTHh05G+uHPlJjjRqFGjBuAlb7nvc6ezs7MLjW/nzp3MmDGDTz/9lIYNG5Kamprn+Sm5dVWtWpXs7OwC283IyAgli/ktW7YsT3LQuHFjDh06RHZ2NtWqVSv0M4uLi2PZsmWh6T179tCnT5/QstxE8KqrrmLUqFEF1nfOFXrrdHHtFCtKZkREytHWzCNRX7gbTV3tm9Yrk7oGDx7MzJkzSUlJIS0tjfr164d6I8KdOHGC1157jZSUFF566SV69epVoMzjjz9OQkICjzzyCKNHj2bVqlUMGDCA3/72twwfPpw6deqwd+9eqlevHvEaDYC+ffsyZMgQxo8fT5MmTcjKyuK7776jRYsWRe5H7969SU1NZeLEiTjneOONN3j++edPrlGKUFh8R44coXbt2tSvX5/9+/ezaNGiUOIQjZL0zJgZl156aejzmD9/PkOGDClQbsCAAUyaNIlvv/0W8HrJcpOwK6+8kg8++IDRo0ezfPly2rZtW2D9/v37M2vWLPr06UO1atXIysoq9hqsWFMyk9+iifDV5ujLn5MIl02LXTwictpq36xsEo9QfU3rRVXnddddx7Jly/jmm2+Ii4tjypQp3HjjjaGLNMeOHcugQYN45513aN26NWeeeSZz586NWFft2rX5/PPP6dKlC/Xr12fBggV5lm/fvp05c+awZs0a6tatS+/evZk6dSpTpkxh27Zt9Ozp3clVp04dXnjhhUKTmfbt2zN16lT69+/PiRMnqF69Ok899VSxyUxycjKpqal069YNgJtuuonOnTuza9euAmUHDRrEnDlzouqBija+Hj160LlzZzp06ECrVq246KKLSlx3SUyfPp2UlBTuv/9+OnfuzI033gjA2rVrmTVrFnPmzKFRo0b89re/DZ0Smzx5cigZmThxIsOHD+fxxx+nTp06zJkzp8A2brrpJrZv305SUhLVq1dnzJgx3H777THdr+JYUV1wp0rXrl3d2rVryzsMz9zLvWTmnMTiy+aWG/V27OMSkdPCtm3bSEhIKO8wykydOnU4evRoeYchp6FIvytmts451zV/WfXMRBJtgjL38tjHIiIiIkXSrdkiInLS1CsjFYGSGREREQk0nWYqgelrppOeFfaE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tGnThn79+vHtt99GXH/x4sW0a9eO1q1bM23atBLFuHbtWu64444SrZMrd6wfKTnnHHfccQetW7cmKSmJ9evXRyyXmprKeeedFxr/KfeBfY8++mhoXseOHalatSpZWVmncA+KVql6Zqa89Tlb9x0JTbdvVo8HruhQjhGJSGVXMz6eFs8/VyZ1fXnDiKjKpaamcvvttzNiRN7y06ZNo2/fvkycOJFp06Yxbdo0pk+fnqdMTk4Ot912G++99x5xcXFceOGFDB48mPbt20e17a5du9K1a4HHhMRc7iP+C5uOdr2gWrRoETt27GDHjh2kpaUxbtw40tLSIpZ99NFHQyNv57rnnnu45557AHjrrbd4/PHHy/2pv+EqVc/M1n1H2JrpJTNbM4/kSWxERCqL3r17R/wiWrhwISNHjgRg5MiRvPnmmwXKrFmzhtatW9OqVSvOOOMMUlJSWLhwYYFyqampjB07losvvpi2bdvyt7/9DfDGE/rlL38JwB133MFDDz0EwLvvvkvv3r05ceIE69at45JLLqFLly4MGDCAzMzMIvfn73//OwMHDqRLly5cfPHFpPu9Xampqdx5551ceumlTJgwocD0xo0b6dGjB0lJSVx11VWhnqg+ffowadIkLrnkEv7nf/6n0O3OmzePK6+8kiuuuILzzjuPmTNn8thjj9G5c2d69OgR6rkoLL633nqL7t2707lzZ37xi1+wf/9+AB588EFGjx5Nnz59aNWqFX/4wx+K3P9oLFy4kBEjRmBm9OjRg0OHDhXbroX585//zHXXXRdx2eLFi0lOTuaCCy6gb9++gLc/I0eOpH///rRs2ZLXX3+d3/zmNyQmJjJw4EB++umnk96vXJUqmQFo37QeC27pSfum9co7FBGRCmX//v2h8ZeaNm3K119/XaDM3r17ad68eWg6Li6OvXv3Rqxv165dLF++nLfffpuxY8fmGWARvJ6gBQsW8OGHH3LHHXcwd+5ccnJy+PWvf81rr73GunXrGD16dMTxgcLdfPPNPPnkk6xbt44ZM2Zw6623hpZt376dpUuX8vvf/77A9IgRI5g+fTqbNm0iMTGRKVOmhNY7dOgQy5cv56677mLWrFmhoR7y27JlCy+99BJr1qzhvvvu48wzz2TDhg307NmT5557rsj4evXqxerVq9mwYQMpKSn893//d6je9PR03n33Xdas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\n",
+ "text/plain": [
+ "