From e0d3854277975b3d4987a81a940fc0feb1b172c0 Mon Sep 17 00:00:00 2001 From: Richard Stiskalek Date: Fri, 14 Apr 2023 23:24:52 +0100 Subject: [PATCH] Add cleaner paths (#43) * ignore venv * ignore pylians if unavaible * Edit loading paths * Edit paths * Stop having default paths * Add nb * Add glamdring paths --------- Co-authored-by: Richard Stiskalek Co-authored-by: Richard Stiskalek --- .gitignore | 1 + csiborgtools/__init__.py | 7 + csiborgtools/field/__init__.py | 7 +- csiborgtools/read/halo_cat.py | 4 +- csiborgtools/read/readsim.py | 87 ++- notebooks/knn.ipynb | 31 +- notebooks/test_cosma.ipynb | 1305 ++++++++++++++++++++++++++++++++ scripts/crosspk.py | 2 +- scripts/fieldprop.py | 2 +- scripts/fit_halos.py | 5 +- scripts/initmatch.py | 12 +- scripts/knn_auto.py | 2 +- scripts/knn_cross.py | 2 +- scripts/singlematch.py | 2 +- scripts/split_halos.py | 2 +- 15 files changed, 1421 insertions(+), 50 deletions(-) create mode 100644 notebooks/test_cosma.ipynb diff --git a/.gitignore b/.gitignore index de42f81..6334f4c 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ csiborgtools.egg-info/* Pylians3/* scripts/plot_correlation.ipynb scripts/*.sh +venv/ diff --git a/csiborgtools/__init__.py b/csiborgtools/__init__.py index 1ff0324..db5c679 100644 --- a/csiborgtools/__init__.py +++ b/csiborgtools/__init__.py @@ -13,3 +13,10 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from csiborgtools import (read, match, utils, units, fits, field, clustering) # noqa + +# Arguments to csiborgtools.read.CSiBORGPaths. +paths_glamdring = { + "srcdir": "/mnt/extraspace/hdesmond/", + "dumpdir": "/mnt/extraspace/rstiskalek/csiborg/", + "mmain_path": "/mnt/zfsusers/hdesmond/Mmain", + "initmatch_path": "/mnt/extraspace/rstiskalek/csiborg/initmatch/"} diff --git a/csiborgtools/field/__init__.py b/csiborgtools/field/__init__.py index 329be0d..1e61853 100644 --- a/csiborgtools/field/__init__.py +++ b/csiborgtools/field/__init__.py @@ -12,4 +12,9 @@ # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from .density import DensityField # noqa +from warnings import warn +try: + import MAS_library as MASL + from .density import DensityField +except ImportError: + warn("MAS_library not found, `DensityField` will not be available", UserWarning) # noqa diff --git a/csiborgtools/read/halo_cat.py b/csiborgtools/read/halo_cat.py index d1c588d..1f17aca 100644 --- a/csiborgtools/read/halo_cat.py +++ b/csiborgtools/read/halo_cat.py @@ -99,9 +99,7 @@ class HaloCatalogue: Loads the data, merges with mmain, does various coordinate transforms. """ # Load the processed data - fname = "ramses_out_{}_{}.npy".format( - str(self.nsim).zfill(5), str(self.nsnap).zfill(5)) - data = numpy.load(join(self.paths.dumpdir, fname)) + data = numpy.load(self.paths.hcat_path(self.nsim)) # Load the mmain file and add it to the data mmain = read_mmain(self.nsim, self.paths.mmain_path) diff --git a/csiborgtools/read/readsim.py b/csiborgtools/read/readsim.py index e0f1c7f..0f958ad 100644 --- a/csiborgtools/read/readsim.py +++ b/csiborgtools/read/readsim.py @@ -35,13 +35,13 @@ class CSiBORGPaths: Parameters ---------- - srcdir : str, optional + srcdir : str Path to the folder where CSiBORG simulations are stored. - dumpdir : str, optional + dumpdir : str Path to the folder where files from `run_fit_halos` are stored. - mmain_path : str, optional + mmain_path : str Path to folder where mmain files are stored. - initmatch_path : str, optional + initmatch_path : str Path to the folder where particle ID match between the first and final snapshot is stored. """ @@ -50,16 +50,12 @@ class CSiBORGPaths: _mmain_path = None _initmatch_path = None - def __init__(self, srcdir="/mnt/extraspace/hdesmond/", - dumpdir="/mnt/extraspace/rstiskalek/csiborg/", - mmain_path="/mnt/zfsusers/hdesmond/Mmain", - initmatch_path="/mnt/extraspace/rstiskalek/csiborg/initmatch/"): # noqa - for path in [srcdir, dumpdir, mmain_path, initmatch_path]: - self._check_directory(path) - self._srcdir = srcdir - self._dumpdir = dumpdir - self._mmain_path = mmain_path - self._initmatch_path = initmatch_path + def __init__(self, srcdir=None, dumpdir=None, mmain_path=None, + initmatch_path=None): + self.srcdir = srcdir + self.dumpdir = dumpdir + self.mmain_path = mmain_path + self.initmatch_path = initmatch_path @staticmethod def _check_directory(path): @@ -75,8 +71,17 @@ class CSiBORGPaths: ------- path : str """ + if self._srcdir is None: + raise ValueError("`srcdir` is not set!") return self._srcdir + @srcdir.setter + def srcdir(self, path): + if path is None: + return + self._check_directory(path) + self._srcdir = path + @property def dumpdir(self): """ @@ -86,8 +91,17 @@ class CSiBORGPaths: ------- path : str """ + if self._dumpdir is None: + raise ValueError("`dumpdir` is not set!") return self._dumpdir + @dumpdir.setter + def dumpdir(self, path): + if path is None: + return + self._check_directory(path) + self._dumpdir = path + @property def temp_dumpdir(self): """ @@ -111,8 +125,17 @@ class CSiBORGPaths: ------- path : str """ + if self._mmain_path is None: + raise ValueError("`mmain_path` is not set!") return self._mmain_path + @mmain_path.setter + def mmain_path(self, path): + if path is None: + return + self._check_directory(path) + self._mmain_path = path + @property def initmatch_path(self): """ @@ -123,8 +146,17 @@ class CSiBORGPaths: ------- path : str """ + if self._initmatch_path is None: + raise ValueError("`initmatch_path` is not set!") return self._initmatch_path + @initmatch_path.setter + def initmatch_path(self, path): + if path is None: + return + self._check_directory(path) + self._initmatch_path = path + def ic_ids(self, tonew): """ CSiBORG IC realisation IDs from the list of folders in `self.srcdir`. @@ -211,7 +243,7 @@ class CSiBORGPaths: cdir = join(self.dumpdir, "initmatch") return join(cdir, "clump_{}_{}.npy".format(nsim, "particles")) - def snapshot_path(self, nsnap, nsim, tonew=False): + def snapshot_path(self, nsnap, nsim): """ Path to a CSiBORG IC realisation snapshot. @@ -221,16 +253,33 @@ class CSiBORGPaths: Snapshot index. nsim : int IC realisation index. - tonew : bool, optional - Whether to return the path to the '_new' IC realisation. Returns ------- snappath : str """ + if nsnap == 1: + tonew = True simpath = self.ic_path(nsim, tonew=tonew) return join(simpath, "output_{}".format(str(nsnap).zfill(5))) + def hcat_path(self, nsim): + """ + Path to the final snapshot halo catalogue from `fit_halos.py`. + + Parameters + ---------- + nsim : int + IC realisation index. + + Returns + ------- + path : str + """ + nsnap = str(max(self.get_snapshots(nsim))).zfill(5) + fname = "ramses_out_{}_{}.npy".format(str(self.nsim).zfill(5), nsnap) + return join(self.dumpdir, fname) + ############################################################################### # Fortran readers # @@ -248,7 +297,7 @@ class ParticleReader: _paths = None def __init__(self, paths): - assert isinstance(paths, CSiBORGPaths) +# assert isinstance(paths, CSiBORGPaths) self._paths = paths @property @@ -306,7 +355,7 @@ class ParticleReader: Opened part files. """ snappath = self.paths.snapshot_path(nsnap, nsim) - ncpu = int(self.read_info()["ncpu"]) + ncpu = int(self.read_info(nsnap, nsim)["ncpu"]) nsnap = str(nsnap).zfill(5) if verbose: print("Reading in output `{}` with ncpu = `{}`." diff --git a/notebooks/knn.ipynb b/notebooks/knn.ipynb index 178c36d..da810d2 100644 --- a/notebooks/knn.ipynb +++ b/notebooks/knn.ipynb @@ -26,7 +26,6 @@ "sys.path.append(\"../\")\n", "import csiborgtools\n", "\n", - "plt.style.use([\"science\", \"notebook\"])\n", "%matplotlib widget \n", "%load_ext autoreload\n", "%autoreload 2" @@ -35,7 +34,7 @@ { "cell_type": "code", "execution_count": 2, - "id": "68a45ea8", + "id": "3d39187a", "metadata": { "ExecuteTime": { "end_time": "2023-04-12T14:25:46.554959Z", @@ -44,8 +43,14 @@ }, "outputs": [], "source": [ - "folder = \"/mnt/extraspace/rstiskalek/csiborg/tpcf/auto/\"\n", - "reader = csiborgtools.read.TPCFReader()" + "with open('../scripts/knn_auto.yml', 'r') as file:\n", + " config = yaml.safe_load(file)\n", + "\n", + "paths = csiborgtools.read.CSiBORGPaths(**csiborgtools.paths_glamdring)\n", + "knnreader = csiborgtools.read.kNNCDFReader()\n", + "\n", + "auto_folder = \"/mnt/extraspace/rstiskalek/csiborg/knn/auto/\"\n", + "cross_folder = \"/mnt/extraspace/rstiskalek/csiborg/knn/cross/\"\n" ] }, { @@ -83,12 +88,16 @@ "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d33ac43bd06947f69731ba806ecd1e51", - "version_major": 2, - "version_minor": 0 - }, - "image/png": "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0TqSos7cv8dtEbu/ZVVdLhd//vOfefLJJ5kyZQp79uwhIiIC8NYbgPdGvbEmbEVFRY1ev+YGrE+fPgH36devH1u3bq1zs9azZ08GDBjAvn372LNnD4MGDWLFihVERkYybtw47HY7Tz75JCtWrGDixIktql+oud6pwsPDG9xe85md+q1/zWc4efLkRq9bVFTEwIEDOXbsGOAtwg6koc/QH7fbzR133MH8+fMbXBmvsrLS7+uBisdrvp1vzmjHwoULueaaa3j22Wd59tlniY2NZdy4cZx//vnccsstAVc1CvSea163Wq2UlJSQmJjYpDha8z21JkkYhBDt7ri9jHx7CSmG2HrbeoUksM+Sx88Ve5gSO6JOQiHEmai1p/R0Rjqdjr/+9a+88cYb5Ofns3DhQn73u98B3uZuAP379683XelUgwcPbtM4p0+fzr59+1i+fDlJSUlkZWVx6aWXotPpmDhxIqGhoSxfvpzHHnusxQmDRtPw777GttdW8xlec801daZg+RMXF9fk8zbXCy+8wGuvvUZycjLPPvssEyZMICkpiZCQEABuuukmPvjgg4DJRHPec2MmT55MTk4OX375JWvWrGH9+vV88803fPXVVzz22GMsWbIkqKlkQLOWCW/N99SaOnXCkJ2d7XuckpIi6/8K0UEdsh7H4XERojXU26ZVtHQ3xrOl6gDJxljSwpu+HKEQ4syl0Wjo3bs3xcXFdf4979GjBwCDBg1iwYIFLb5OzbSmmm/d/anZduoUqOnTp/Pqq6+yYsUKUlNT8Xg8voTAaDQyadIkVq1aRUlJCd999x16vZ4pU6a0OOaW6tGjh28FqLPOOqtJx9S895ycnID7NLTNn48++gjwrgA1c+bMetv37dvXrPO1VGhoKNdccw3XXHMN4B1deeSRR3j99de59dZbOXz4cL1jAq0MVfNZhISEtGnS1Rry8/PJz88H6t4719Yx05hWkpmZSUZGBhkZGb5CHSFEx2Jx29hrOUasPiLgPuG6UMK0Iawv30mRo/z0BSeEaDcej8d301V76s20adMwGAysXr263pKmwZg6dSoAX3/9tW/OfG2bN29my5YtaDQazjnnnDrbzjvvPDQaDatWreKbb74BvPULNaZPn47L5eIf//gHZrOZs88+u9Fv9E+Hiy66CDh5w94UGRkZhIeHU1xczLJly+ptLygo8Pt6Q0pLSwH/RcU7d+5ky5YtzTpfa0tISOCpp54CvD00/C1Pu2jRIr/HLly4EIBJkyah03Xs7+fnz5/vu1/OzMz0u0+nThgWLVpEVlYWWVlZzJ07t73DEUL4ccRWSKmjusGEASDZEEOFy8L6sl04PM4G9xVCnNlcLhePPPIIxcXFAHW+fU5KSuLOO+/EbDZz2WWX1WlcVsNut/PZZ5+xe/fuRq81adIkxo0bh9VqZe7cuVgsFt+24uJi3/3DDTfc4BvdqBEdHU1GRgaVlZUsXLiQ7t2715kGVTPa8NJLL9V53t7+8Ic/EB0dzbPPPsszzzyDw+Got8+hQ4fq3AyHhobym9/8BoB7773X9400eOfp33bbbfUa3DWmppD35Zdf9k2TAu833rNmzWqwaV9rOnz4MP/5z3/81kp8/vnngHelotorF9XIysryJRU11q1bx8svvwx4P6uObu7cub775UAJUMdOeVooLS2N9PT09g5DCBGAqqrsNedi0GjRNlKboCgKvUIS2GvJJakyhrOj005TlEKItvSf//zHt1IRQElJCVu3buXo0aMA/OlPf2LChAl1jvnHP/5Bfn4+77//PqNGjWLkyJH07dsXnU7HsWPH2LJlC2azma+++qpJdQzvv/8+5513Hp9++il9+vThnHPOwel0smrVKiorK0lPT/fd9J9q+vTpbNiwwdf8rLbRo0cTFxdHSUmJb9+OoHv37nz66adcffXV3H///Tz11FMMGzaMlJQUKioqyM7O5sCBA4wbN67ON85PPPEE69at4+eff2bgwIGce+65hISEsHbtWpxOJ7NmzfJ9s94UDz/8MF9//TVvvPEGq1atIj09ncrKStasWUPfvn258sorWbJkSVt8BHWUlZXx61//mttvv51Ro0b5Cpb37dvH5s2bURSFp59+2u9KR3fddRcPPfQQCxcuZMSIEeTl5bF27Vo8Hg93332339WrOpqmTNvv1CMMQoiOrchRzlFbEQn6qCbtb9DoSTJEs7FiD4cs+Y0fIITo8L7//nveeecd359ly5ah0Wi4/vrrWbVqFX/961/rHaPT6XjvvfdYunQpV1xxBYWFhXz22Wd88803lJaWctlll/H+++/Xm0IUSN++fdm0aRMPPfQQcXFxfPHFFyxfvpx+/frxj3/8g3Xr1hETE+P32NpJwKkJgaIonHfeeYB3lZuxY8c2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cyYJCQm+12+99VYeeOAB3nzzTW655ZaAx48ePZqHHnqozmtTpkzh9ttv55lnnuGZZ57hwgsvBMBms/Hyy97Yn3vuOXr37u07Rq/X8+9//5svvviCQ4cO8fHHH3PTTTcBcP3113P33XezfPlycnNz6datm+84p9PpW1XmF7/4he/17OxsPvjgA1JTU3n//feJiKi7pPQ999zD8uXLWbp0KV999RWXXnppkz8zgH//+9/06tXL9zwuLo7bbruN3//+9+zYsYNt27YRFxfn296nTx8yMzN58cUXWblyJRMnTvRte+yxx1BVlddee41zzjmnznWGDx/Os88+y3XXXceLL77IlClTAPj+++/ZsGEDYWFhvPLKK4SEnPw92rNnT/71r39x5ZVXNus9de/ene7du9d73WQy8eqrr/L++++zePFi38/wVHfeeWe9z3HOnDn885//ZPfu3WzcuJHJkyc3GkdBQQEAkydPrvdzA+/0s0Dmzp3LeeedV+e1P/zhD3z00Uds3LiR//znPzz88MONxlAjIyODv/zlL77pTgDDhg3jlltu4bXXXmPFihWMHz++yedrCUkYhBBt4oitkAqXmWRTx2uY1iskkX2WPH6u2MOUmBF1fhkL0daO28vItRe3dxjtzuVy8c477wAnpyHVmDVrFg8//DDfffcdBw4coF+/fn7PMWvWLL+vz549m2eeeYZ169bhdrvRarVs3LiR6upqYmNjueyyy+odYzKZuOGGG3jhhRdYtWqVL2GIiIjgmmuuYeHChSxcuLBOgvLll19SVFTE2LFjGTp0qO/1pUuXoqoqF110kd+bTvDOX1+6dCnr169vVsKg0+m44IIL6r0+YMAAwHvDPmzYsIDb8/LyfK8VFxfz888/Exoa6vczqYkTYP369b7Xaubcz5gxo05iUuPyyy8nKiqKioqKpr2pWtavX8/atWs5cuQIFovFtxy2wWCgqKiIsrIyYmLq/7sSKP60tDR2795drz4lkPT0dLRaLW+99RYDBw7kqquuavKKTrNnz/b7+qxZs9i4cSOrV69uVsJw6aWX+v33KS0tDaDJ76k1SMIghGh1btXNbvMRwrUhHfJmXKdo6W6MY0vVAVKMsQwK69HeIYkuJPkM7jremrF/+eWXHD9+3DcPv7akpCQuvvhiPvvsM9566y3+9re/+T1Hnz59GnzdarVSUlJCYmKi7+Yq0DGALzE59Ubs1ltvZeHChSxYsKBOwvD2228DdUcXAA4ePAh46zMaK94uKipqcPupUlJS0Onq376Fh4cDBFyisyZxqV28fejQIVRVxWq1YjQamxznsWPHgMCfZU1x9tatWxs8Z22FhYVcffXVrFu3rsH9Kisr/SYMgd53ZKR3lLuhovXa+vXrx3PPPccf/vAH7rjjDu644w569erF+PHjufTSS7n22msxGAx+j23s72PN59ZUrfWeWoMkDEKIVpdvLyXfXkY3Y2x7hxJQhM5EldvK+vJdxOujiDN0rKlTovNqzSk9Z7KaG2mbzeab6lJbzU37ggULeOKJJ9Bqg2v8qLZCw8ZzzjmHfv36sXfvXtavX8+ECRMoLCxk6dKlhISE1CtA9Xg8AIwaNYqRI0c2eO5x48Y1KxaNpuH1ahrbXltNnOHh4Vx99dXNiqO1/epXv2LdunWMHz+exx9/nJEjRxITE4NerwcgNTWV/Pz8gD/P5rzvxtx5551cd911fPbZZ6xbt45169bx4Ycf8uGHH/LYY4+xdu3aoPpINPfvYmu+p5aShEEI0eoOWo7jUt0YNf6/hekoUgyx7LPksb58JzPix6DXyK9EIU6H/Px833KdJSUlfP/99wH3zcvL4+uvv66zAlGNQ4f8r3iWk5MDQEhIiG/KTE3tQaBj4OTIQO06BfB+Yz5nzhweffRR3n77bSZMmMCiRYtwuVxcd911REdH19m/Rw/vqOXEiRN56aWXAl6vvdXEqSgKb731VpNvUGs+n5rP2Z/Dhw83OQ6z2czSpUvRaDQsXbq03udpNps5fvx4k8/XGpKSkvj1r3/Nr3/9a8C7KtStt97KDz/8wIMPPuibTlfboUOHGDVqVL3Xaz4nfzUaZ4qOk7oIIToFs8vKfksucTr/83Y7EkVR6BWayB7LMTZX7m/vcIToMhYsWIDb7WbcuHGoqhrwzwMPPAAE7slQU3B8qpq19ydNmuSbvnPWWWcRHh5OaWkpn332Wb1jrFYrH374IQDnnntuve1z5sxBo9Hw0UcfYbFYAk5HArjooosA+Oyzz07rtJHmSk1NZcSIEVRVVfH11183+biaEaGvv/66Xk8C8L7vQH0T/KmoqMDtdhMZGVkvWQDvz7k1RopaYvDgwfzxj38EvMud+hOo/0fN6zX1IGciSRiEEK3qiK2IMlcV0frw9g6lSYwaPYn6KDZU7uWwtaC9wxGiS6hZHSlQkWiNmqLmL774wu9c/6ysLJ566qk6r61bt863ks69997rez0kJITf/e53ANx33311vgF3Op3cfffdHD9+nD59+nDNNdfUu1b37t05//zzqays5OGHH2bHjh307Nmz3qo44F296eqrr+bo0aNcddVVfr+JN5vNvPfee75VedrLX//6V8Cb+Hz++ef1tquqyk8//cSyZct8r02ePJn09HSqq6v53e9+V6eJ2NGjR7n//vubFUNSUhIxMTGUl5fXu+n+8ccf662E1Za+/fZbli5ditPprPO6qqp88cUXAHVWqKrt1VdfrdeE7bnnnuPnn38mIiKCX/7yl20S8+kg4+9CiFajqip7zEcxKHq0ypnzfUSMPoJyl5n15TuJ1UcQoTO1d0hCdFpr1qxh//79GI3GRptPDR06lPT0dDZt2sTChQvrNWO76667eOihh1i4cCEjRowgLy+PtWvX4vF4uPvuu7n44ovr7P/444+zceNGVq5cSVpaGueeey4RERH88MMPHDlyhLi4OBYvXhywqPUXv/gF33zzDS+88AJwctTBn7fffpvy8nK++uorBg0axMiRI+nTpw+qqpKTk8PWrVtxOBxkZ2eTlJTU1I+v1V122WW88MIL3HfffcycOZP+/fszaNAgoqKiKCoqYuvWrRQWFvLHP/6xzupM7777LlOnTuXDDz/ku+++Y9KkSVgsFr799ltGjBhBfHw8P/zwQ5Ni0Gq1/PnPf+bee+9l1qxZvPzyy/Tt25cjR46wfv16MjMz+e6775o1zSlY27Zt49577yUyMpL09HRSU1OxWq1s2rSJw4cPExUV5beRHZxcVnXy5Ml069aNHTt2sH37dt+qS8nJyW0ef1s5c/5FF0J0eAUO73KRiYaooI53qx6O2YrwqJ5WjqxxPUMSOWYr5qeK3e1yfSG6iprpRZdddpnf1W5OVTPK4G9a0pVXXsny5ctJTk5m6dKl/Pzzz6Snp7NgwQK/3X2NRiNff/01r7zyCiNHjmTt2rUsWbIEvV7PnXfeydatW8nIyAgYyxVXXEFsrHcxh5q6hkAiIiJYtmwZ77//PtOnT+fIkSMsWbKEb7/9FqvVys0338ySJUsCLhl7Ot11111s3ryZ3/zmNyiKwsqVK/nkk084cOAAo0eP5t///jd33XVXnWOGDBnCxo0bmTNnDm63m08++YRdu3Zx5513snLlyoBJVyD33HMPn3zyCRMmTGDPnj18/vnn2O12Xn75Zb/1Am3lsssuY968eYwZM4aDBw/yv//9j9WrVxMVFcWDDz7Ijh07/NYpgHc04ZVXXqGyspJPPvmEw4cPM2PGDL777ju/o1ZnEkVt70lhbWDTpk1kZGSQlZVFenp6e4cjRJfxU3k2a8t2MCgsuMKul458yrLSTaSF9eSxvpmYtA0v89faLG4bufYSLojLYFhE4KUXhRBCiBo1y4d3hlvqQPfQMsIghGgVNreD3eZjROvCgjq+zFnFitItAGSbj/CXg+9h9zhaMcLGmbQhRGhN/FCeTcEZ2olXCCGEaG2dOmHIzs5m06ZNbNq0ifz8/PYOR4hO7Zi9iGJnRdD9DL4r246Hk1OBdpoP8/dD/8XpcbVWiE2SbIyhym3l+/Kd2NynN2ERQgghTrf8/Hzf/XJ2drbffTp1wpCZmUlGRgYZGRnMnz+/vcMRolPbZ85Fp2jRKcE1V1pVts33OORE/4bNVft5+vBiXKq7VWJsqt4hiRyw5LGxcm+nGGIWQgghApk/f77vfjkzM9PvPp06YVi0aBFZWVlkZWUxd+7c9g5HiE6rxFHJYVsh8frgRhcOWws4aPWOAg4wdWNe31swarzdPX+s2M0LR5bgPo2FyHqNjlRjLFurDpBvr7/GuBBCCFGjpm/ImWru3Lm+++VAvU069bKqaWlpUvQsxGlw2FpAlctCN2NcUMevKtvqe3xuzEiGhPfkkT438cTB93CqLtaUbceo6Pldj5m+4rK2FqkL47i9nH2WXFJDgntfQgghREeXkpJCSkpKg/t06hEGIUTbc3pc7LEcJTLI3gVu1cPqE9ORtGg4J2YYACMj+vLH3tehPfFralnpJv6T+/Vp/RYn3hDJPvMxKl3m03ZNIYQQoqORhEEI0SJ59hIKHGVBT0faVn2IUmcVABmRA4istcrS2KhB3NfrajR4RxU+L/6R945/2/KgmyhGF06Zq5pD1uOn7ZpCCCFERyMJgxCiRQ5Y8vCoYDhRc9Bcq0trTUeKHVlv+6SYYdzZ43Lf848KvmNxwXdBXau5FEUhUmdiV/Xh075akxBCCNFRSMIghAhapcvMAUs+8fqIoI63uu2sr9gFQJg2hDGRA/3uNy1uNL/tfonv+bv5K/m86MegrtlcCfoo8u1lHLEVnpbrCSGEEB2NJAxCiKAdsRZS4TITFWSzth8rdmP3OAGYFD20wVGKi+PHMif1fN/zN3K/YllJVlDXbQ69RodW0bDbfPSMXgVDCCGECJYkDEKIoHhUD7vNRwnVGtAowf0q+fZEZ2eAc2NGNbr/VYmTuCFpiu/5y0c/Z03Z9qCu3RyJ+ihyrAUUOsrb/FpCCCFERyMJgxAiKPn2UvLspSToo4I6vsRRybbqQwAkG2JIC+vRpONuTD6XyxPGA6Ci8tzh//Fjxe6gYmiqcF0oVo+d/ZbcNr2OEEII0RFJwiCECMoh63EcHiehWmNQx68u24aKd4rP1JiRTe6voCgKt6ZeyIy4swDw4OGpnI/YXLk/qDiaKk4XwR7zMapd1ja9jhBCCNHRSMIghGg2i9vGXssxYoMsdlZVtW6zNj+rIzVEURR+2/0Szo3xHudS3fzt0IfsqM4JKp6miNVHUOKsIkeWWBVCCNHFSMIghGi2o7YiSh3VQScMB63HfasODQ7rQYoxttnn0Cga7up5OROihgDgUJ385eD77DUfCyqmplwvXGtkl/kwLo+7Ta4hRFfSu3dvFEWp88doNNK9e3cuv/xyvvjii/YOsUlWr16NoihMnTq1vUNpUM3nnZOT096h1LNgwQIURWHOnDntHUo9HTm200kSBiFEs6iqyl7zMQwaLdogi51XlW3xPT4vpnmjC7VpFS339bqajIgBAFg9duYdXNRmjdYSDNHk2Us4Zi9qk/ML0RVNnDiR2bNnM3v2bC6++GJ0Oh2fffYZl112Gb///e/bOzwhBJIwCCGaqchRzlFbUdDFzm7V7VvZSKdomRQ9rEXx6DU6HuxzPcPDewNQ7bby5wMLOWZr/Zt6o0aPCuypbptRDCG6ol/96lcsWLCABQsWsGTJEvbv388dd9wBwHPPPceGDRvaOcLOYeXKlWRnZ9OtW7f2DuWMcuWVV5Kdnc2TTz7Z3qG0K0kYhBDNcthaiNltI1wXGtTxm6sOUOEyAzA2clDQ56nNqNHzpz43McjUHYAKl5lHDyzkuL2sxec+VaI+moO2fIodFa1+biEE6HQ6nn76aSIjIwH4/PPP2zmizqFfv34MHjwYvT5wvxtRX1RUFIMHDyYlJaW9Q2lXkjAIIZrM4XGyx3KU6CAbtQGsKg2+2LkhJq2Rx/pm0ic0GYASZyWPHnin1W/sI3Umql1WDljyWvW8QoiTQkJCGDDAO9WwoKCg3vYVK1Zw5513MmrUKOLj4321D9dff33AEYl58+ahKArz5s2jqKiI3/3ud/To0QODwUCPHj248847KS8vDxjTwoULGTNmDCaTidjYWGbMmMHatWsbfS8///wz1113HampqRgMBhITE7nssstYvny53/3nzJmDoigsWLCAPXv2cP3115OYmEhYWBhjxozh008/9e37008/MXPmTBISEggNDWX8+PGsXLnS73kD1TBUVFTwyCOPMHz4cMLCwjAajaSmpjJx4kT+/Oc/43Q6652rrKyMxx57jFGjRhEREYHJZGL48OH89a9/xWKx+L2+y+Xi+eefZ/jw4YSEhJCQkMDVV1/N9u3B99JZsWIFl112GUlJSej1emJiYhgwYACZmZl89913dfat/blu3bqVq666yve5jRgxghdeeAG3u359WqAahtq1K06nk3/+858MHTqU0NBQ4uLiuOqqq8jOzg76vXU0kjAIIZrsmK2YQkcFcfrIoI43u238dKJnQoTWRHpE/9YMj3BdKE/0m0WPkAQAChxlPHpgIeXO6la9Tqw+gt3mo1jd9lY9rxDipMrKSgCSkpLqbfvtb3/L66+/jkajYeLEiVx66aVERUXx0UcfMWHCBP7v//4v4HmPHj1Keno6//d//8fYsWM5//zzqaqq4qWXXuKCCy7we4N89913M3v2bDZt2sSYMWO48MILOXr0KFOnTuWTTz4JeK033niD8ePHs3jxYpKTk7nmmmsYMGAAX3zxBRdccAGPP/54wGM3bdpERkYGW7duZdq0aYwcOZKNGzdy5ZVX8vHHH/PJJ58wefJkjh07xrRp0xg0aBA//vgjM2bMYN26dQ18sidZLBYmTZrE3/72NwoKCpg2bRpXXXUVgwYN4uDBg/zlL3/BbDbXOWbXrl2MHDmSJ554gsLCQiZNmsT06dMpKiri0UcfZeLEiVRU1P2ixuPxcO2113Lvvfeyd+9epkyZwrRp09i0aRNjx44NatrZO++8wwUXXMCXX35Jnz59uPrqqznnnHOIjIzkww8/5H//+5/f437++WfOPvtsNm/ezLRp0zjnnHPYs2cP99xzDzfccAOqqjYrDqfTycUXX8wTTzxBz549ueSSSwgLC2PJkiVMmDChQxaZB0PX3gG0pdqZXUpKSpcfThKipfZbctEoCnpNcL861pfvwqG6ADgnZljQ52lIlC6MJ/rN4qF9b3PcUUquvZg/H1jI3/rPIUJnapVrxOkjOWDNI8daQFp4z1Y5pxDipOzsbA4ePAjAzJkz623/17/+xZQpU4iJianz+ieffMK1117L3LlzufjiiwkNrT/l8a233mLOnDm89tprGI3ePjJHjx5l/PjxbNiwgY8//pgbb7zRt/+XX37Jv//9b8LCwvjqq6+YPHmyb9uTTz7Jww8/7Pc9bN++ndtvvx1VVVm4cCG33HKLb9tXX33FFVdcwbx585gwYQLnn39+veNffPFF/vrXv/Lwww/7+tS8+OKL3HXXXdx7772YzWbefPPNOue99957ef7553n88ccDjmDU9vHHH7Njxw4uuugiPv300zrTlTweD2vXrsVkOvl702q1MnPmTI4ePcojjzzCo48+isFgALzJx69+9Ss++OAD7r33Xt566y3fca+++iqffPIJSUlJrFq1irS0NMA76nDXXXfxyiuvNBrrqR5//HFUVWXt2rVMmjSpzrbCwkJyc/032nz11Ve5/fbbeeGFF9DpvP8G7dy5k3PPPZePP/6Y119/nblz5zY5jvXr1zN69GgOHDhAcrJ3hNtms3HFFVfwzTff8OSTTzJ//vxmv7/TKT8/n/z8fICAoyKdOmHIzMz0PX7ssceYN29e+wUjxBmuzFnFIWsB8UGOLsAp05FasDpSY+L0kfy1/2we3PcWxc4KcmwFPH5wEU/0m4VJG9Li82sVDSGKgV3VhxkY1g2tom2FqEWXsfgssJyh/TxMyXDtxjY7fUVFBT/99BN33303brebRx55hLPOOqvefldccYXf46+44gquvfZaPvjgA1atWsXFF19cb5/u3bvz8ssv+5IFwDcl6cEHH2TFihV1Eobnn38egDvuuKNOsgDw0EMP8dFHH7Fly5Z613nhhRdwuVxcddVVdW7qAS666CJ+85vf8NJLL/H000/7TRjGjh1bJ1kAuO2225g3bx7Hjh3j2muvrXfeRx55hOeff57vvvsOp9PZaL1CzXSv888/v96+Go2GKVOm1HntnXfe4cCBA1x66aX85S9/qbPNZDLx+uuvs3LlSt59912eeeYZX0JX8xnOmzfPlyyAt17l2WefZcmSJRw/3rz/JwoKCoiKiqqXLAAkJiaSmJjo97iUlBSeeeYZX7IAMHToUP785z9z55138swzzzQrYVAUhbffftuXLIB3St3jjz/ON998w4oVK5rxrtrH/PnzGxztgk6eMCxatMj3F1NGF4RomSO2QipdZlIMMY3v7Eeho5wd5hwAuhnjGWBq25U6Eg3R/KXfLB7a/zblrmr2WnJ54uD7PN4vE6PG0CrnP2YvJs9eQo8Q//8wCeGX5TiY/X/72RX94he/4Be/+EWd17RaLYsWLeLmm28OeFxeXh5ffvklu3fvpqKiApfLO3q5c+dOAPbs2eM3YZg2bVqdb81r1Nwv1P5m2uVy+ab31P4SsrZZs2b5TRhWr14NEHD9/l/+8pe89NJLrF27FrfbjVZb94uHiy66qE6yAN4b7D59+lBaWur3vcXFxREbG0tpaSklJSV1bmL9GTNmDABPPfUUcXFxXHrppcTGBu6L8+WXXwJw/fXX+90eHh7OWWedxdKlS9mwYQMXXHABubm57N+/H/D/GYaEhHDdddfx73//u8FYTzV27FhWr17NrFmzuPvuuxk9ejQaTeMz7a+77jpCQup/cTR79mzuvPNO9u3bR15eHqmpqU2Ko2fPnowcWf8LMH9/nzqquXPn+kbysrOz/f6cOnXCkJaWRnp6enuHIcQZz+Vxs7v6KBHa0Hr/gDXV6jqjCyOCPk9zdAuJ5y/9ZvHw/repclvZZT7M3w99yCN9bmrxdKgQrQG36mavOVcSBtE8poZv4jq0Noh94sSJ9O/vrWcqKipi7dq1VFVVcdtttzFgwADGjh1b75jHH3+cv/3tb37rDWrU1ECcqmdP/9MIa1ZlstlsvtdKSkp8z/v06eP3uECv19woBtrer18/3/VKSkrqfSMeKM7w8PAGt0dERFBaWlrnfQQydepU/vjHP/L0008ze/ZsFEVhwIABTJw4kcsvv5zLLruszk14zTSxW265pd7oxqmKirxLWx875l2GOj4+3hf7qQJ9Rg155ZVXuPTSS3n33Xd59913iYiIYMyYMZx33nnccsstAT+fQNeKiIggLi6OkpISjh071qyEwZ+av092e8evdWvKtP1OnTAIIVpHnr2EfEcp3Y3xQR2vqiqryk4mDFNbcXWkxvQKTeLxfrN4ZP8CLB47m6sO8FTOYv7Y5zp0LZxKlKCPYr8lj9GR/YhtwVQt0cW04ZSeM9GvfvWrOt/CV1RUcOWVV7Jq1Squu+46du3aVWdE4H//+x/z5s0jPDycl156ifPOO4/U1FRCQ71faDz88MM8+eSTAYtXm/ItdEfQWJyt9T7+8Y9/8Nvf/pbPP/+cdevW8f333/P222/z9ttvM2bMGFatWkVYmHdlPI/HA8CMGTP8FqPX1qtXr1aJL5C0tDT27NnDsmXL+Pbbb1m/fj1r167l22+/5YknnuDNN98MOCrUmOYUPp8pf59aShIGIUSjDlrz8agqRk1w63fvs+SSay8BYHh4bxIN0a0YXeP6m1L5c99MHju4ELvHyU+Vu3n+8BLu7XVV0N2qwVtgfdxSxiHLcWKjJGEQojVERUXx3//+l8GDB3P48GGeffZZHnnkEd/2jz76CIC//e1v/OY3v6l3/L59+1otlri4OIxGI3a7nZycHIYOHVpvn0Cr4HTr1o0DBw5w8OBBhg2r36Cy5tv6kJCQBqcBnQ69e/fmzjvv5M477wRgw4YNZGZmsmHDBp566inf/PYePXqwe/dufvnLX3LNNdc06dw1jeKKi4uprq72O8oQ7EpCOp2Oiy++2Dc9q7KykmeffZbHH3+cuXPncuWVV/qSnRqHDh3ye66qqipKSrz/TnXv3j2oeDqzrpEWCSGCVu2yst+SR6ze/1ByU3xbe3ShDYudGzIkvKd3KpLi/Z7ku/LtvHL0czyqJ+hzKopCtC6MXebD2NyO1gpViC4vISHBlyT861//qtMfobS0FPD/DXZhYWGTVgdqKp1Ox8SJEwF47733/O7z7rvv+n196tSpgHcdf39qVhGaPHlynQLcjmDMmDHcfvvtAHXqMy666CLgZNLWFN27d6dv374AvP/++/W22+12Fi9e3IJoT4qMjGTevHlER0djsVjYu3dvvX0WL17sd5pQzc+xf//+0g3bD0kYhBANOmIrpNxZTYwuuITB6XGxtmwHAAZFx8ToIa0ZXrOMjOjLg72vQ3viV9/y0k28mft1s9fdri3eEEWho4IjtsLWClMIAdx+++307NmTiooKnnnmGd/rNcWkr7/+Og7HyUS9oqKC2bNn1+sB0FL33HMP4F3SdP369XW2PfXUU2zatMnvcXfffTc6nY5PPvmERYsW1dm2bNky31Kb999/f6vG2xxLlizhu+++8001quF0Ovn666+BuonZb37zG3r16sXixYv54x//SFVVVb1zHj9+nDfeeKPOazWf4bx589i9e7fvdbfbzf33309eXvMaYVosFp599llfnURta9eupby8HK1W63ekIC8vj/vvv79Ok7bs7GyeeOIJwLs0rahPEgYhREAe1cNu81FCNQY0QU7dyaraT5Xb2/lzXNTgVlnWtCXGRA3ivl5Xo8FbdP158U8sOu6/M2pT6BQtekXLrurDLRqtEELUZTQafcuhv/DCC76RhXvuuYfo6GiWLl1K3759ueaaa7j88svp1asXW7du5dZbb23VOC677DJ+97vfUV1dzeTJkzn33HO56aabGDZsGA899BB333233+OGDx/Oyy+/jKIo3HLLLWRkZHDzzTczadIkZsyYgd1uZ968eVxwwQWtGm9zrFmzhilTppCUlMQFF1xAZmYml19+Od27d+frr7+mW7duPPDAA779w8LC+PLLL+nduzdPPfUUPXv2ZMqUKdx8881ceeWVDB06lNTUVB599NE61/nd737HZZddRn5+PiNHjmTGjBnceOONDBgwgP/85z/cdtttzYrb4XBw3333kZyczKhRo7j22mu56aabmDBhgm8p2D/96U8kJCTUO/a3v/0t//nPfxgwYAA33ngjM2bMYNSoURQUFHDllVc2O5auQhIGIURABY4y8mzFxBuigj5H7dWRzosd1QpRtdykmGHc2eNy3/PFBWv5qOC7oM+XZIjhiK2IfHtpa4QnhDhh1qxZDBkyhKqqKp5++mnAu8rN5s2bufnmm9FqtXzxxRds3bqVG2+8kc2bN9OjR49Wj+Oll17irbfeYvTo0fz4448sXbqUlJQUVq5cGbAnBHi/kV+/fj3XXHMNeXl5fPTRR+zevZuLL76YZcuW8dhjj7V6rM0xZ84cHnzwQQYPHsyuXbtYvHgxP/zwAz169ODvf/87W7durfct/dChQ9m2bRtPPfUUaWlpbNu2jcWLF/PTTz8RFhbG/fffz5IlS+oco9Fo+N///sczzzxD//79Wb16NcuXL2fEiBH8+OOPflfCakh4eDivvfYa119/PXa7neXLl/PJJ59QWFjIVVddxcqVKwP2FRg3bhzr169n2LBhLF++nNWrVzNgwACeffZZPvroo9Oygt+ZSFFbMhbfQdW0U8/KypJlVYVogR/Kd/F9+U4GmYIrAKt2WZm182lcqptoXThvD/19h2pytrT4Z1479qXv+a+6zWBmwvigzrXXkstZkQOYchpXgBJC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", + "application/javascript": "/* Put everything inside the global mpl namespace */\n/* global mpl */\nwindow.mpl = {};\n\nmpl.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\nmpl.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_device_pixel_ratio', {\n device_pixel_ratio: fig.ratio,\n });\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\nmpl.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\nmpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._init_canvas = function () {\n var fig = this;\n\n var canvas_div = (this.canvas_div = document.createElement('div'));\n canvas_div.setAttribute(\n 'style',\n 'border: 1px solid #ddd;' +\n 'box-sizing: content-box;' +\n 'clear: both;' +\n 'min-height: 1px;' +\n 'min-width: 1px;' +\n 'outline: 0;' +\n 'overflow: hidden;' +\n 'position: relative;' +\n 'resize: both;'\n );\n\n function on_keyboard_event_closure(name) {\n return function (event) {\n return fig.key_event(event, name);\n };\n }\n\n canvas_div.addEventListener(\n 'keydown',\n on_keyboard_event_closure('key_press')\n );\n canvas_div.addEventListener(\n 'keyup',\n on_keyboard_event_closure('key_release')\n );\n\n this._canvas_extra_style(canvas_div);\n this.root.appendChild(canvas_div);\n\n var canvas = (this.canvas = document.createElement('canvas'));\n canvas.classList.add('mpl-canvas');\n canvas.setAttribute('style', 'box-sizing: content-box;');\n\n this.context = canvas.getContext('2d');\n\n var backingStore =\n this.context.backingStorePixelRatio ||\n this.context.webkitBackingStorePixelRatio ||\n this.context.mozBackingStorePixelRatio ||\n this.context.msBackingStorePixelRatio ||\n this.context.oBackingStorePixelRatio ||\n this.context.backingStorePixelRatio ||\n 1;\n\n this.ratio = (window.devicePixelRatio || 1) / backingStore;\n\n var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n 'canvas'\n ));\n rubberband_canvas.setAttribute(\n 'style',\n 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n );\n\n // Apply a ponyfill if ResizeObserver is not implemented by browser.\n if (this.ResizeObserver === undefined) {\n if (window.ResizeObserver !== undefined) {\n this.ResizeObserver = window.ResizeObserver;\n } else {\n var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n this.ResizeObserver = obs.ResizeObserver;\n }\n }\n\n this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n var nentries = entries.length;\n for (var i = 0; i < nentries; i++) {\n var entry = entries[i];\n var width, height;\n if (entry.contentBoxSize) {\n if (entry.contentBoxSize instanceof Array) {\n // Chrome 84 implements new version of spec.\n width = entry.contentBoxSize[0].inlineSize;\n height = entry.contentBoxSize[0].blockSize;\n } else {\n // Firefox implements old version of spec.\n width = entry.contentBoxSize.inlineSize;\n height = entry.contentBoxSize.blockSize;\n }\n } else {\n // Chrome <84 implements even older version of spec.\n width = entry.contentRect.width;\n height = entry.contentRect.height;\n }\n\n // Keep the size of the canvas and rubber band canvas in sync with\n // the canvas container.\n if (entry.devicePixelContentBoxSize) {\n // Chrome 84 implements new version of spec.\n canvas.setAttribute(\n 'width',\n entry.devicePixelContentBoxSize[0].inlineSize\n );\n canvas.setAttribute(\n 'height',\n entry.devicePixelContentBoxSize[0].blockSize\n );\n } else {\n canvas.setAttribute('width', width * fig.ratio);\n canvas.setAttribute('height', height * fig.ratio);\n }\n canvas.setAttribute(\n 'style',\n 'width: ' + width + 'px; height: ' + height + 'px;'\n );\n\n rubberband_canvas.setAttribute('width', width);\n rubberband_canvas.setAttribute('height', height);\n\n // And update the size in Python. We ignore the initial 0/0 size\n // that occurs as the element is placed into the DOM, which should\n // otherwise not happen due to the minimum size styling.\n if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n fig.request_resize(width, height);\n }\n }\n });\n this.resizeObserverInstance.observe(canvas_div);\n\n function on_mouse_event_closure(name) {\n return function (event) {\n return fig.mouse_event(event, name);\n };\n }\n\n rubberband_canvas.addEventListener(\n 'mousedown',\n on_mouse_event_closure('button_press')\n );\n rubberband_canvas.addEventListener(\n 'mouseup',\n on_mouse_event_closure('button_release')\n );\n rubberband_canvas.addEventListener(\n 'dblclick',\n on_mouse_event_closure('dblclick')\n );\n // Throttle sequential mouse events to 1 every 20ms.\n rubberband_canvas.addEventListener(\n 'mousemove',\n on_mouse_event_closure('motion_notify')\n );\n\n rubberband_canvas.addEventListener(\n 'mouseenter',\n on_mouse_event_closure('figure_enter')\n );\n rubberband_canvas.addEventListener(\n 'mouseleave',\n on_mouse_event_closure('figure_leave')\n );\n\n canvas_div.addEventListener('wheel', function (event) {\n if (event.deltaY < 0) {\n event.step = 1;\n } else {\n event.step = -1;\n }\n on_mouse_event_closure('scroll')(event);\n });\n\n canvas_div.appendChild(canvas);\n canvas_div.appendChild(rubberband_canvas);\n\n this.rubberband_context = rubberband_canvas.getContext('2d');\n this.rubberband_context.strokeStyle = '#000000';\n\n this._resize_canvas = function (width, height, forward) {\n if (forward) {\n canvas_div.style.width = width + 'px';\n canvas_div.style.height = height + 'px';\n }\n };\n\n // Disable right mouse context menu.\n this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n event.preventDefault();\n return false;\n });\n\n function set_focus() {\n canvas.focus();\n canvas_div.focus();\n }\n\n window.setTimeout(set_focus, 100);\n};\n\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.figure.prototype.handle_figure_label = function (fig, msg) {\n // Updates the figure title.\n fig.header.textContent = msg['label'];\n};\n\nmpl.figure.prototype.handle_cursor = function (fig, msg) {\n fig.rubberband_canvas.style.cursor = msg['cursor'];\n};\n\nmpl.figure.prototype.handle_message = function (fig, msg) {\n fig.message.textContent = msg['message'];\n};\n\nmpl.figure.prototype.handle_draw = function (fig, _msg) {\n // Request the server to send over a new figure.\n fig.send_draw_message();\n};\n\nmpl.figure.prototype.handle_image_mode = function (fig, msg) {\n fig.image_mode = msg['mode'];\n};\n\nmpl.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\nmpl.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\nmpl.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.\nmpl.figure.prototype._make_on_message_function = function (fig) {\n return function socket_on_message(evt) {\n if (evt.data instanceof Blob) {\n var img = evt.data;\n if (img.type !== 'image/png') {\n /* FIXME: We get \"Resource interpreted as Image but\n * transferred with MIME type text/plain:\" errors on\n * Chrome. But how to set the MIME type? It doesn't seem\n * to be part of the websocket stream */\n img.type = 'image/png';\n }\n\n /* Free the memory for the previous frames */\n if (fig.imageObj.src) {\n (window.URL || window.webkitURL).revokeObjectURL(\n fig.imageObj.src\n );\n }\n\n fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n img\n );\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n } else if (\n typeof evt.data === 'string' &&\n evt.data.slice(0, 21) === 'data:image/png;base64'\n ) {\n fig.imageObj.src = evt.data;\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n }\n\n var msg = JSON.parse(evt.data);\n var msg_type = msg['type'];\n\n // Call the \"handle_{type}\" callback, which takes\n // the figure and JSON message as its only arguments.\n try {\n var callback = fig['handle_' + msg_type];\n } catch (e) {\n console.log(\n \"No handler for the '\" + msg_type + \"' message type: \",\n msg\n );\n return;\n }\n\n if (callback) {\n try {\n // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n callback(fig, msg);\n } catch (e) {\n console.log(\n \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n e,\n e.stack,\n msg\n );\n }\n }\n };\n};\n\n// from https://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\nmpl.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 * https://stackoverflow.com/a/24161582/3208463\n */\nfunction 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\nmpl.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\nmpl.figure.prototype._key_event_extra = function (_event, _name) {\n // Handle any extra behaviour associated with a key event\n};\n\nmpl.figure.prototype.key_event = function (event, name) {\n // Prevent repeat events\n if (name === 'key_press') {\n if (event.key === this._key) {\n return;\n } else {\n this._key = event.key;\n }\n }\n if (name === 'key_release') {\n this._key = null;\n }\n\n var value = '';\n if (event.ctrlKey && event.key !== 'Control') {\n value += 'ctrl+';\n }\n else if (event.altKey && event.key !== 'Alt') {\n value += 'alt+';\n }\n else if (event.shiftKey && event.key !== 'Shift') {\n value += 'shift+';\n }\n\n value += 'k' + event.key;\n\n this._key_event_extra(event, name);\n\n this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n return false;\n};\n\nmpl.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\nmpl.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\nvar _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\nmpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o\", \"download\"]];\n\nmpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\n\nmpl.default_extension = \"png\";/* global mpl */\n\nvar comm_websocket_adapter = function (comm) {\n // Create a \"websocket\"-like object which calls the given IPython comm\n // object with the appropriate methods. Currently this is a non binary\n // socket, so there is still some room for performance tuning.\n var ws = {};\n\n ws.binaryType = comm.kernel.ws.binaryType;\n ws.readyState = comm.kernel.ws.readyState;\n function updateReadyState(_event) {\n if (comm.kernel.ws) {\n ws.readyState = comm.kernel.ws.readyState;\n } else {\n ws.readyState = 3; // Closed state.\n }\n }\n comm.kernel.ws.addEventListener('open', updateReadyState);\n comm.kernel.ws.addEventListener('close', updateReadyState);\n comm.kernel.ws.addEventListener('error', updateReadyState);\n\n ws.close = function () {\n comm.close();\n };\n ws.send = function (m) {\n //console.log('sending', m);\n comm.send(m);\n };\n // Register the callback with on_msg.\n comm.on_msg(function (msg) {\n //console.log('receiving', msg['content']['data'], msg);\n var data = msg['content']['data'];\n if (data['blob'] !== undefined) {\n data = {\n data: new Blob(msg['buffers'], { type: data['blob'] }),\n };\n }\n // Pass the mpl event to the overridden (by mpl) onmessage function.\n ws.onmessage(data);\n });\n return ws;\n};\n\nmpl.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\nmpl.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\nmpl.figure.prototype.close_ws = function (fig, msg) {\n fig.send_message('closing', msg);\n // fig.ws.close()\n};\n\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.figure.prototype._root_extra_style = function (el) {\n el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n};\n\nmpl.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\nmpl.figure.prototype._key_event_extra = function (event, _name) {\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\nmpl.figure.prototype.handle_save = function (fig, _msg) {\n fig.ondownload(fig, null);\n};\n\nmpl.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.\nif (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": [ "\n", "
\n", @@ -185,7 +194,7 @@ "outputs": [ { "data": { - "application/javascript": "/* Put everything inside the global mpl namespace */\n/* global mpl */\nwindow.mpl = {};\n\nmpl.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\nmpl.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_device_pixel_ratio', {\n device_pixel_ratio: fig.ratio,\n });\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\nmpl.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\nmpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._init_canvas = function () {\n var fig = this;\n\n var canvas_div = (this.canvas_div = document.createElement('div'));\n canvas_div.setAttribute('tabindex', '0');\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 'z-index: 2;'\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(\n 'style',\n 'box-sizing: content-box;' +\n 'pointer-events: none;' +\n 'position: relative;' +\n 'z-index: 0;'\n );\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;' +\n 'left: 0;' +\n 'pointer-events: none;' +\n 'position: absolute;' +\n 'top: 0;' +\n '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 /* This rescales the canvas back to display pixels, so that it\n * appears correct on HiDPI screens. */\n canvas.style.width = width + 'px';\n canvas.style.height = height + 'px';\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 /* User Agent sniffing is bad, but WebKit is busted:\n * https://bugs.webkit.org/show_bug.cgi?id=144526\n * https://bugs.webkit.org/show_bug.cgi?id=181818\n * The worst that happens here is that they get an extra browser\n * selection when dragging, if this check fails to catch them.\n */\n var UA = navigator.userAgent;\n var isWebKit = /AppleWebKit/.test(UA) && !/Chrome/.test(UA);\n if(isWebKit) {\n return function (event) {\n /* This prevents the web browser from automatically changing to\n * the text insertion cursor when the button is pressed. We\n * want to control all of the cursor setting manually through\n * the 'cursor' event from matplotlib */\n event.preventDefault()\n return fig.mouse_event(event, name);\n };\n } else {\n return function (event) {\n return fig.mouse_event(event, name);\n };\n }\n }\n\n canvas_div.addEventListener(\n 'mousedown',\n on_mouse_event_closure('button_press')\n );\n canvas_div.addEventListener(\n 'mouseup',\n on_mouse_event_closure('button_release')\n );\n canvas_div.addEventListener(\n 'dblclick',\n on_mouse_event_closure('dblclick')\n );\n // Throttle sequential mouse events to 1 every 20ms.\n canvas_div.addEventListener(\n 'mousemove',\n on_mouse_event_closure('motion_notify')\n );\n\n canvas_div.addEventListener(\n 'mouseenter',\n on_mouse_event_closure('figure_enter')\n );\n canvas_div.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 canvas_div.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.figure.prototype.handle_figure_label = function (fig, msg) {\n // Updates the figure title.\n fig.header.textContent = msg['label'];\n};\n\nmpl.figure.prototype.handle_cursor = function (fig, msg) {\n fig.canvas_div.style.cursor = msg['cursor'];\n};\n\nmpl.figure.prototype.handle_message = function (fig, msg) {\n fig.message.textContent = msg['message'];\n};\n\nmpl.figure.prototype.handle_draw = function (fig, _msg) {\n // Request the server to send over a new figure.\n fig.send_draw_message();\n};\n\nmpl.figure.prototype.handle_image_mode = function (fig, msg) {\n fig.image_mode = msg['mode'];\n};\n\nmpl.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\nmpl.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\nmpl.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.\nmpl.figure.prototype._make_on_message_function = function (fig) {\n return function socket_on_message(evt) {\n if (evt.data instanceof Blob) {\n var img = evt.data;\n if (img.type !== 'image/png') {\n /* FIXME: We get \"Resource interpreted as Image but\n * transferred with MIME type text/plain:\" errors on\n * Chrome. But how to set the MIME type? It doesn't seem\n * to be part of the websocket stream */\n img.type = 'image/png';\n }\n\n /* Free the memory for the previous frames */\n if (fig.imageObj.src) {\n (window.URL || window.webkitURL).revokeObjectURL(\n fig.imageObj.src\n );\n }\n\n fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n img\n );\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n } else if (\n typeof evt.data === 'string' &&\n evt.data.slice(0, 21) === 'data:image/png;base64'\n ) {\n fig.imageObj.src = evt.data;\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n }\n\n var msg = JSON.parse(evt.data);\n var msg_type = msg['type'];\n\n // Call the \"handle_{type}\" callback, which takes\n // the figure and JSON message as its only arguments.\n try {\n var callback = fig['handle_' + msg_type];\n } catch (e) {\n console.log(\n \"No handler for the '\" + msg_type + \"' message type: \",\n msg\n );\n return;\n }\n\n if (callback) {\n try {\n // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n callback(fig, msg);\n } catch (e) {\n console.log(\n \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n e,\n e.stack,\n msg\n );\n }\n }\n };\n};\n\nfunction getModifiers(event) {\n var mods = [];\n if (event.ctrlKey) {\n mods.push('ctrl');\n }\n if (event.altKey) {\n mods.push('alt');\n }\n if (event.shiftKey) {\n mods.push('shift');\n }\n if (event.metaKey) {\n mods.push('meta');\n }\n return mods;\n}\n\n/*\n * return a copy of an object with only non-object keys\n * we need this to avoid circular references\n * https://stackoverflow.com/a/24161582/3208463\n */\nfunction 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\nmpl.figure.prototype.mouse_event = function (event, name) {\n if (name === 'button_press') {\n this.canvas.focus();\n this.canvas_div.focus();\n }\n\n // from https://stackoverflow.com/q/1114465\n var boundingRect = this.canvas.getBoundingClientRect();\n var x = (event.clientX - boundingRect.left) * this.ratio;\n var y = (event.clientY - boundingRect.top) * this.ratio;\n\n this.send_message(name, {\n x: x,\n y: y,\n button: event.button,\n step: event.step,\n modifiers: getModifiers(event),\n guiEvent: simpleKeys(event),\n });\n\n return false;\n};\n\nmpl.figure.prototype._key_event_extra = function (_event, _name) {\n // Handle any extra behaviour associated with a key event\n};\n\nmpl.figure.prototype.key_event = function (event, name) {\n // Prevent repeat events\n if (name === 'key_press') {\n if (event.key === this._key) {\n return;\n } else {\n this._key = event.key;\n }\n }\n if (name === 'key_release') {\n this._key = null;\n }\n\n var value = '';\n if (event.ctrlKey && event.key !== 'Control') {\n value += 'ctrl+';\n }\n else if (event.altKey && event.key !== 'Alt') {\n value += 'alt+';\n }\n else if (event.shiftKey && event.key !== 'Shift') {\n value += 'shift+';\n }\n\n value += 'k' + event.key;\n\n this._key_event_extra(event, name);\n\n this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n return false;\n};\n\nmpl.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\nmpl.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\nvar _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\nmpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o\", \"download\"]];\n\nmpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\n\nmpl.default_extension = \"png\";/* global mpl */\n\nvar comm_websocket_adapter = function (comm) {\n // Create a \"websocket\"-like object which calls the given IPython comm\n // object with the appropriate methods. Currently this is a non binary\n // socket, so there is still some room for performance tuning.\n var ws = {};\n\n ws.binaryType = comm.kernel.ws.binaryType;\n ws.readyState = comm.kernel.ws.readyState;\n function updateReadyState(_event) {\n if (comm.kernel.ws) {\n ws.readyState = comm.kernel.ws.readyState;\n } else {\n ws.readyState = 3; // Closed state.\n }\n }\n comm.kernel.ws.addEventListener('open', updateReadyState);\n comm.kernel.ws.addEventListener('close', updateReadyState);\n comm.kernel.ws.addEventListener('error', updateReadyState);\n\n ws.close = function () {\n comm.close();\n };\n ws.send = function (m) {\n //console.log('sending', m);\n comm.send(m);\n };\n // Register the callback with on_msg.\n comm.on_msg(function (msg) {\n //console.log('receiving', msg['content']['data'], msg);\n var data = msg['content']['data'];\n if (data['blob'] !== undefined) {\n data = {\n data: new Blob(msg['buffers'], { type: data['blob'] }),\n };\n }\n // Pass the mpl event to the overridden (by mpl) onmessage function.\n ws.onmessage(data);\n });\n return ws;\n};\n\nmpl.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\nmpl.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\nmpl.figure.prototype.close_ws = function (fig, msg) {\n fig.send_message('closing', msg);\n // fig.ws.close()\n};\n\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.figure.prototype._root_extra_style = function (el) {\n el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n};\n\nmpl.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\nmpl.figure.prototype._key_event_extra = function (event, _name) {\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\nmpl.figure.prototype.handle_save = function (fig, _msg) {\n fig.ondownload(fig, null);\n};\n\nmpl.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.\nif (IPython.notebook.kernel !== null) {\n IPython.notebook.kernel.comm_manager.register_target(\n 'matplotlib',\n mpl.mpl_figure_comm\n );\n}\n", + "application/javascript": "/* Put everything inside the global mpl namespace */\n/* global mpl */\nwindow.mpl = {};\n\nmpl.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\nmpl.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_device_pixel_ratio', {\n device_pixel_ratio: fig.ratio,\n });\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\nmpl.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\nmpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._init_canvas = function () {\n var fig = this;\n\n var canvas_div = (this.canvas_div = document.createElement('div'));\n canvas_div.setAttribute(\n 'style',\n 'border: 1px solid #ddd;' +\n 'box-sizing: content-box;' +\n 'clear: both;' +\n 'min-height: 1px;' +\n 'min-width: 1px;' +\n 'outline: 0;' +\n 'overflow: hidden;' +\n 'position: relative;' +\n 'resize: both;'\n );\n\n function on_keyboard_event_closure(name) {\n return function (event) {\n return fig.key_event(event, name);\n };\n }\n\n canvas_div.addEventListener(\n 'keydown',\n on_keyboard_event_closure('key_press')\n );\n canvas_div.addEventListener(\n 'keyup',\n on_keyboard_event_closure('key_release')\n );\n\n this._canvas_extra_style(canvas_div);\n this.root.appendChild(canvas_div);\n\n var canvas = (this.canvas = document.createElement('canvas'));\n canvas.classList.add('mpl-canvas');\n canvas.setAttribute('style', 'box-sizing: content-box;');\n\n this.context = canvas.getContext('2d');\n\n var backingStore =\n this.context.backingStorePixelRatio ||\n this.context.webkitBackingStorePixelRatio ||\n this.context.mozBackingStorePixelRatio ||\n this.context.msBackingStorePixelRatio ||\n this.context.oBackingStorePixelRatio ||\n this.context.backingStorePixelRatio ||\n 1;\n\n this.ratio = (window.devicePixelRatio || 1) / backingStore;\n\n var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n 'canvas'\n ));\n rubberband_canvas.setAttribute(\n 'style',\n 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n );\n\n // Apply a ponyfill if ResizeObserver is not implemented by browser.\n if (this.ResizeObserver === undefined) {\n if (window.ResizeObserver !== undefined) {\n this.ResizeObserver = window.ResizeObserver;\n } else {\n var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n this.ResizeObserver = obs.ResizeObserver;\n }\n }\n\n this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n var nentries = entries.length;\n for (var i = 0; i < nentries; i++) {\n var entry = entries[i];\n var width, height;\n if (entry.contentBoxSize) {\n if (entry.contentBoxSize instanceof Array) {\n // Chrome 84 implements new version of spec.\n width = entry.contentBoxSize[0].inlineSize;\n height = entry.contentBoxSize[0].blockSize;\n } else {\n // Firefox implements old version of spec.\n width = entry.contentBoxSize.inlineSize;\n height = entry.contentBoxSize.blockSize;\n }\n } else {\n // Chrome <84 implements even older version of spec.\n width = entry.contentRect.width;\n height = entry.contentRect.height;\n }\n\n // Keep the size of the canvas and rubber band canvas in sync with\n // the canvas container.\n if (entry.devicePixelContentBoxSize) {\n // Chrome 84 implements new version of spec.\n canvas.setAttribute(\n 'width',\n entry.devicePixelContentBoxSize[0].inlineSize\n );\n canvas.setAttribute(\n 'height',\n entry.devicePixelContentBoxSize[0].blockSize\n );\n } else {\n canvas.setAttribute('width', width * fig.ratio);\n canvas.setAttribute('height', height * fig.ratio);\n }\n canvas.setAttribute(\n 'style',\n 'width: ' + width + 'px; height: ' + height + 'px;'\n );\n\n rubberband_canvas.setAttribute('width', width);\n rubberband_canvas.setAttribute('height', height);\n\n // And update the size in Python. We ignore the initial 0/0 size\n // that occurs as the element is placed into the DOM, which should\n // otherwise not happen due to the minimum size styling.\n if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n fig.request_resize(width, height);\n }\n }\n });\n this.resizeObserverInstance.observe(canvas_div);\n\n function on_mouse_event_closure(name) {\n return function (event) {\n return fig.mouse_event(event, name);\n };\n }\n\n rubberband_canvas.addEventListener(\n 'mousedown',\n on_mouse_event_closure('button_press')\n );\n rubberband_canvas.addEventListener(\n 'mouseup',\n on_mouse_event_closure('button_release')\n );\n rubberband_canvas.addEventListener(\n 'dblclick',\n on_mouse_event_closure('dblclick')\n );\n // Throttle sequential mouse events to 1 every 20ms.\n rubberband_canvas.addEventListener(\n 'mousemove',\n on_mouse_event_closure('motion_notify')\n );\n\n rubberband_canvas.addEventListener(\n 'mouseenter',\n on_mouse_event_closure('figure_enter')\n );\n rubberband_canvas.addEventListener(\n 'mouseleave',\n on_mouse_event_closure('figure_leave')\n );\n\n canvas_div.addEventListener('wheel', function (event) {\n if (event.deltaY < 0) {\n event.step = 1;\n } else {\n event.step = -1;\n }\n on_mouse_event_closure('scroll')(event);\n });\n\n canvas_div.appendChild(canvas);\n canvas_div.appendChild(rubberband_canvas);\n\n this.rubberband_context = rubberband_canvas.getContext('2d');\n this.rubberband_context.strokeStyle = '#000000';\n\n this._resize_canvas = function (width, height, forward) {\n if (forward) {\n canvas_div.style.width = width + 'px';\n canvas_div.style.height = height + 'px';\n }\n };\n\n // Disable right mouse context menu.\n this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n event.preventDefault();\n return false;\n });\n\n function set_focus() {\n canvas.focus();\n canvas_div.focus();\n }\n\n window.setTimeout(set_focus, 100);\n};\n\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.figure.prototype.handle_figure_label = function (fig, msg) {\n // Updates the figure title.\n fig.header.textContent = msg['label'];\n};\n\nmpl.figure.prototype.handle_cursor = function (fig, msg) {\n fig.rubberband_canvas.style.cursor = msg['cursor'];\n};\n\nmpl.figure.prototype.handle_message = function (fig, msg) {\n fig.message.textContent = msg['message'];\n};\n\nmpl.figure.prototype.handle_draw = function (fig, _msg) {\n // Request the server to send over a new figure.\n fig.send_draw_message();\n};\n\nmpl.figure.prototype.handle_image_mode = function (fig, msg) {\n fig.image_mode = msg['mode'];\n};\n\nmpl.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\nmpl.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\nmpl.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.\nmpl.figure.prototype._make_on_message_function = function (fig) {\n return function socket_on_message(evt) {\n if (evt.data instanceof Blob) {\n var img = evt.data;\n if (img.type !== 'image/png') {\n /* FIXME: We get \"Resource interpreted as Image but\n * transferred with MIME type text/plain:\" errors on\n * Chrome. But how to set the MIME type? It doesn't seem\n * to be part of the websocket stream */\n img.type = 'image/png';\n }\n\n /* Free the memory for the previous frames */\n if (fig.imageObj.src) {\n (window.URL || window.webkitURL).revokeObjectURL(\n fig.imageObj.src\n );\n }\n\n fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n img\n );\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n } else if (\n typeof evt.data === 'string' &&\n evt.data.slice(0, 21) === 'data:image/png;base64'\n ) {\n fig.imageObj.src = evt.data;\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n }\n\n var msg = JSON.parse(evt.data);\n var msg_type = msg['type'];\n\n // Call the \"handle_{type}\" callback, which takes\n // the figure and JSON message as its only arguments.\n try {\n var callback = fig['handle_' + msg_type];\n } catch (e) {\n console.log(\n \"No handler for the '\" + msg_type + \"' message type: \",\n msg\n );\n return;\n }\n\n if (callback) {\n try {\n // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n callback(fig, msg);\n } catch (e) {\n console.log(\n \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n e,\n e.stack,\n msg\n );\n }\n }\n };\n};\n\n// from https://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\nmpl.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 * https://stackoverflow.com/a/24161582/3208463\n */\nfunction 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\nmpl.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\nmpl.figure.prototype._key_event_extra = function (_event, _name) {\n // Handle any extra behaviour associated with a key event\n};\n\nmpl.figure.prototype.key_event = function (event, name) {\n // Prevent repeat events\n if (name === 'key_press') {\n if (event.key === this._key) {\n return;\n } else {\n this._key = event.key;\n }\n }\n if (name === 'key_release') {\n this._key = null;\n }\n\n var value = '';\n if (event.ctrlKey && event.key !== 'Control') {\n value += 'ctrl+';\n }\n else if (event.altKey && event.key !== 'Alt') {\n value += 'alt+';\n }\n else if (event.shiftKey && event.key !== 'Shift') {\n value += 'shift+';\n }\n\n value += 'k' + event.key;\n\n this._key_event_extra(event, name);\n\n this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n return false;\n};\n\nmpl.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\nmpl.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\nvar _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\nmpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o\", \"download\"]];\n\nmpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\n\nmpl.default_extension = \"png\";/* global mpl */\n\nvar comm_websocket_adapter = function (comm) {\n // Create a \"websocket\"-like object which calls the given IPython comm\n // object with the appropriate methods. Currently this is a non binary\n // socket, so there is still some room for performance tuning.\n var ws = {};\n\n ws.binaryType = comm.kernel.ws.binaryType;\n ws.readyState = comm.kernel.ws.readyState;\n function updateReadyState(_event) {\n if (comm.kernel.ws) {\n ws.readyState = comm.kernel.ws.readyState;\n } else {\n ws.readyState = 3; // Closed state.\n }\n }\n comm.kernel.ws.addEventListener('open', updateReadyState);\n comm.kernel.ws.addEventListener('close', updateReadyState);\n comm.kernel.ws.addEventListener('error', updateReadyState);\n\n ws.close = function () {\n comm.close();\n };\n ws.send = function (m) {\n //console.log('sending', m);\n comm.send(m);\n };\n // Register the callback with on_msg.\n comm.on_msg(function (msg) {\n //console.log('receiving', msg['content']['data'], msg);\n var data = msg['content']['data'];\n if (data['blob'] !== undefined) {\n data = {\n data: new Blob(msg['buffers'], { type: data['blob'] }),\n };\n }\n // Pass the mpl event to the overridden (by mpl) onmessage function.\n ws.onmessage(data);\n });\n return ws;\n};\n\nmpl.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\nmpl.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\nmpl.figure.prototype.close_ws = function (fig, msg) {\n fig.send_message('closing', msg);\n // fig.ws.close()\n};\n\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.figure.prototype._root_extra_style = function (el) {\n el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n};\n\nmpl.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\nmpl.figure.prototype._key_event_extra = function (event, _name) {\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\nmpl.figure.prototype.handle_save = function (fig, _msg) {\n fig.ondownload(fig, null);\n};\n\nmpl.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.\nif (IPython.notebook.kernel !== null) {\n IPython.notebook.kernel.comm_manager.register_target(\n 'matplotlib',\n mpl.mpl_figure_comm\n );\n}\n", "text/plain": [ "" ] diff --git a/notebooks/test_cosma.ipynb b/notebooks/test_cosma.ipynb new file mode 100644 index 0000000..27356aa --- /dev/null +++ b/notebooks/test_cosma.ipynb @@ -0,0 +1,1305 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "5a38ed25", + "metadata": { + "ExecuteTime": { + "end_time": "2023-03-24T14:16:01.928614Z", + "start_time": "2023-03-24T14:15:34.242247Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "../csiborgtools/field/__init__.py:20: UserWarning: MAS_library not found, `DensityField` will not be available\n", + " warn(\"MAS_library not found, `DensityField` will not be available\", UserWarning) # noqa\n" + ] + } + ], + "source": [ + "import sys\n", + "from os.path import join\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from numba import jit\n", + "from tqdm import tqdm, trange\n", + "import joblib\n", + "sys.path.append(\"../\")\n", + "import csiborgtools\n", + "\n", + "%matplotlib widget\n", + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "6f3ae40e", + "metadata": {}, + "outputs": [], + "source": [ + "srcdir = \"/cosma8/data/dp016/dc-stis1/csiborg_new\"\n", + "dumpdir = \"/cosma8/data/dp016/dc-stis1/csiborg_dump\"\n", + "paths = csiborgtools.read.CSiBORGPaths(srcdir=srcdir, dumpdir=dumpdir)\n", + "\n", + "\n", + "reader = csiborgtools.read.ParticleReader(paths)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "33abfe57", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reading in output `00001` with ncpu = `324`.\n", + "Opened 324 particle files.\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 324/324 [03:57<00:00, 1.36it/s]\n" + ] + } + ], + "source": [ + "part = reader.read_particle(1, 7444, [\"x\", \"y\", \"z\", \"M\", \"ID\"], verbose=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "32ab40ee", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ls: cannot access /cosma8/data/dp016/dc-stis1/csiborg_new/ramsess_out_7444/outputs_00001/: No such file or directory\n" + ] + } + ], + "source": [ + "/cosma8/data/dp016/dc-stis1/csiborg_new/ramses_out_7444_new/output_00001/info_00001.txt" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "fc116dff", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cat: /cosma8/data/dp016/dc-stis1/csiborg_new/ramses_out_7444/output_00001/info_00001.txt: No such file or directory\n" + ] + } + ], + "source": [ + "!cat /cosma8/data/dp016/dc-stis1/csiborg_new/ramses_out_7444/output_00001/info_00001.txt" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e6b05ceb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ncpu = 324\n", + "ndim = 3\n", + "levelmin = 8\n", + "levelmax = 19\n", + "ngridmax = 2800000\n", + "nstep_coarse= 0\n", + "\n", + "boxlen = 0.100000000000000E+01\n", + "time = -0.260788354371079E+02\n", + "aexp = 0.142857000000000E-01\n", + "H0 = 0.705000000000000E+02\n", + "omega_m = 0.307000011205673E+00\n", + "omega_l = 0.693000018596649E+00\n", + "omega_k = -0.298023223876953E-07\n", + "omega_b = 0.000000000000000E+00\n", + "unit_l = 0.423740962969913E+26\n", + "unit_d = 0.983942902810118E-24\n", + "unit_t = 0.893232429772148E+14\n", + "\n", + "ordering type=hilbert \n", + " DOMAIN ind_min ind_max\n", + " 1 0.000000000000000E+00 0.890921902481080E+17\n", + " 2 0.890921902481080E+17 0.903741664479150E+17\n", + " 3 0.903741664479150E+17 0.905655754235576E+17\n", + " 4 0.905655754235576E+17 0.907569842649825E+17\n", + " 5 0.907569842649825E+17 0.910375727335997E+17\n", + " 6 0.910375727335997E+17 0.916149055929713E+17\n", + " 7 0.916149055929713E+17 0.918096761858294E+17\n", + " 8 0.918096761858294E+17 0.920010850272543E+17\n", + " 9 0.920010850272543E+17 0.942688305781146E+17\n", + " 10 0.942688305781146E+17 0.945672973849723E+17\n", + " 11 0.945672973849723E+17 0.947587062263972E+17\n", + " 12 0.947587062263972E+17 0.949501751973642E+17\n", + " 13 0.949501751973642E+17 0.955129510703923E+17\n", + " 14 0.955129510703923E+17 0.958726141818962E+17\n", + " 15 0.958726141818962E+17 0.963097707172332E+17\n", + " 16 0.963097707172332E+17 0.965012398224179E+17\n", + " 17 0.965012398224179E+17 0.966926486638428E+17\n", + " 18 0.966926486638428E+17 0.968840576394854E+17\n", + " 19 0.968840576394854E+17 0.970754664809103E+17\n", + " 20 0.970754664809103E+17 0.972668753223352E+17\n", + " 21 0.972668753223352E+17 0.974582842979779E+17\n", + " 22 0.974582842979779E+17 0.976496931394028E+17\n", + " 23 0.976496931394028E+17 0.978411019808276E+17\n", + " 24 0.978411019808276E+17 0.980325109564703E+17\n", + " 25 0.980325109564703E+17 0.982239197978952E+17\n", + " 26 0.982239197978952E+17 0.984153286393201E+17\n", + " 27 0.984153286393201E+17 0.986067376149627E+17\n", + " 28 0.986067376149627E+17 0.987981464563876E+17\n", + " 29 0.987981464563876E+17 0.989895554320302E+17\n", + " 30 0.989895554320302E+17 0.991810244029972E+17\n", + " 31 0.991810244029972E+17 0.993724332444221E+17\n", + " 32 0.993724332444221E+17 0.995638422200648E+17\n", + " 33 0.995638422200648E+17 0.997552510614897E+17\n", + " 34 0.997552510614897E+17 0.999467200324567E+17\n", + " 35 0.999467200324567E+17 0.100143568852615E+18\n", + " 36 0.100143568852615E+18 0.100840961751384E+18\n", + " 37 0.100840961751384E+18 0.101193427034571E+18\n", + " 38 0.101193427034571E+18 0.101812721724424E+18\n", + " 39 0.101812721724424E+18 0.107245430957408E+18\n", + " 40 0.107245430957408E+18 0.115866535335035E+18\n", + " 41 0.115866535335035E+18 0.204958656863666E+18\n", + " 42 0.204958656863666E+18 0.252936659161580E+18\n", + " 43 0.252936659161580E+18 0.257043514674643E+18\n", + " 44 0.257043514674643E+18 0.258590894486192E+18\n", + " 45 0.258590894486192E+18 0.259300492205621E+18\n", + " 46 0.259300492205621E+18 0.259620404321059E+18\n", + " 47 0.259620404321059E+18 0.260240103140491E+18\n", + " 48 0.260240103140491E+18 0.260431693444284E+18\n", + " 49 0.260431693444284E+18 0.260623102285709E+18\n", + " 50 0.260623102285709E+18 0.260814511127134E+18\n", + " 51 0.260814511127134E+18 0.261005920102777E+18\n", + " 52 0.261005920102777E+18 0.261197381557551E+18\n", + " 53 0.261197381557551E+18 0.261388790398976E+18\n", + " 54 0.261388790398976E+18 0.261580199374619E+18\n", + " 55 0.261580199374619E+18 0.261771608216044E+18\n", + " 56 0.261771608216044E+18 0.261963017057468E+18\n", + " 57 0.261963017057468E+18 0.262154426033111E+18\n", + " 58 0.262154426033111E+18 0.262345834874536E+18\n", + " 59 0.262345834874536E+18 0.262537243850179E+18\n", + " 60 0.262537243850179E+18 0.262728652691603E+18\n", + " 61 0.262728652691603E+18 0.262920061533028E+18\n", + " 62 0.262920061533028E+18 0.263111470508671E+18\n", + " 63 0.263111470508671E+18 0.263302879350096E+18\n", + " 64 0.263302879350096E+18 0.263494288191521E+18\n", + " 65 0.263494288191521E+18 0.263685697167163E+18\n", + " 66 0.263685697167163E+18 0.263877106008588E+18\n", + " 67 0.263877106008588E+18 0.264074332383216E+18\n", + " 68 0.264074332383216E+18 0.264505062976389E+18\n", + " 69 0.264505062976389E+18 0.265212269338558E+18\n", + " 70 0.265212269338558E+18 0.265425398098035E+18\n", + " 71 0.265425398098035E+18 0.265616859552809E+18\n", + " 72 0.265616859552809E+18 0.265859579026342E+18\n", + " 73 0.265859579026342E+18 0.268130852221747E+18\n", + " 74 0.268130852221747E+18 0.268372849603903E+18\n", + " 75 0.268372849603903E+18 0.268567500742984E+18\n", + " 76 0.268567500742984E+18 0.268759689523626E+18\n", + " 77 0.268759689523626E+18 0.269423404241650E+18\n", + " 78 0.269423404241650E+18 0.269614813217292E+18\n", + " 79 0.269614813217292E+18 0.269806222058717E+18\n", + " 80 0.269806222058717E+18 0.269997630900142E+18\n", + " 81 0.269997630900142E+18 0.306265813826929E+18\n", + " 82 0.306265813826929E+18 0.306556648074248E+18\n", + " 83 0.306556648074248E+18 0.306748056915673E+18\n", + " 84 0.306748056915673E+18 0.306939465757098E+18\n", + " 85 0.306939465757098E+18 0.307221961728066E+18\n", + " 86 0.307221961728066E+18 0.307794217399222E+18\n", + " 87 0.307794217399222E+18 0.307988715395875E+18\n", + " 88 0.307988715395875E+18 0.308180124237300E+18\n", + " 89 0.308180124237300E+18 0.310444717550600E+18\n", + " 90 0.310444717550600E+18 0.310740185664979E+18\n", + " 91 0.310740185664979E+18 0.310931594506404E+18\n", + " 92 0.310931594506404E+18 0.311123041063010E+18\n", + " 93 0.311123041063010E+18 0.311680816251929E+18\n", + " 94 0.311680816251929E+18 0.312038281548136E+18\n", + " 95 0.312038281548136E+18 0.312471011985457E+18\n", + " 96 0.312471011985457E+18 0.312662450891653E+18\n", + " 97 0.312662450891653E+18 0.312853859867296E+18\n", + " 98 0.312853859867296E+18 0.313045268708721E+18\n", + " 99 0.313045268708721E+18 0.313236677684363E+18\n", + " 100 0.313236677684363E+18 0.313428086525788E+18\n", + " 101 0.313428086525788E+18 0.313619495367213E+18\n", + " 102 0.313619495367213E+18 0.313810904342856E+18\n", + " 103 0.313810904342856E+18 0.314002313184281E+18\n", + " 104 0.314002313184281E+18 0.314193722025705E+18\n", + " 105 0.314193722025705E+18 0.314385131001348E+18\n", + " 106 0.314385131001348E+18 0.314576539842773E+18\n", + " 107 0.314576539842773E+18 0.314767948684198E+18\n", + " 108 0.314767948684198E+18 0.314959357659841E+18\n", + " 109 0.314959357659841E+18 0.315150766501265E+18\n", + " 110 0.315150766501265E+18 0.315342175476908E+18\n", + " 111 0.315342175476908E+18 0.315533614383104E+18\n", + " 112 0.315533614383104E+18 0.315725023224529E+18\n", + " 113 0.315725023224529E+18 0.315916432200172E+18\n", + " 114 0.315916432200172E+18 0.316107878622560E+18\n", + " 115 0.316107878622560E+18 0.316302087245791E+18\n", + " 116 0.316302087245791E+18 0.316995494012256E+18\n", + " 117 0.316995494012256E+18 0.317341733203476E+18\n", + " 118 0.317341733203476E+18 0.317950474621813E+18\n", + " 119 0.317950474621813E+18 0.322765279123735E+18\n", + " 120 0.322765279123735E+18 0.323602548101480E+18\n", + " 121 0.323602548101480E+18 0.404285202853003E+18\n", + " 122 0.404285202853003E+18 0.493377324381635E+18\n", + " 123 0.493377324381635E+18 0.505798757690900E+18\n", + " 124 0.505798757690900E+18 0.506944051119915E+18\n", + " 125 0.506944051119915E+18 0.507135512574689E+18\n", + " 126 0.507135512574689E+18 0.507326921550332E+18\n", + " 127 0.507326921550332E+18 0.507518330391757E+18\n", + " 128 0.507518330391757E+18 0.507896890285621E+18\n", + " 129 0.507896890285621E+18 0.508206872973541E+18\n", + " 130 0.508206872973541E+18 0.508401475257369E+18\n", + " 131 0.508401475257369E+18 0.508600811534680E+18\n", + " 132 0.508600811534680E+18 0.509602348381766E+18\n", + " 133 0.509602348381766E+18 0.514502795336876E+18\n", + " 134 0.514502795336876E+18 0.515690615787225E+18\n", + " 135 0.515690615787225E+18 0.516460272584491E+18\n", + " 136 0.516460272584491E+18 0.516797047278404E+18\n", + " 137 0.516797047278404E+18 0.516988456254046E+18\n", + " 138 0.516988456254046E+18 0.517179865095471E+18\n", + " 139 0.517179865095471E+18 0.517371326550245E+18\n", + " 140 0.517371326550245E+18 0.517587226905805E+18\n", + " 141 0.517587226905805E+18 0.517778688494797E+18\n", + " 142 0.517778688494797E+18 0.517970097336222E+18\n", + " 143 0.517970097336222E+18 0.518161506177647E+18\n", + " 144 0.518161506177647E+18 0.518352915153289E+18\n", + " 145 0.518352915153289E+18 0.518544323994714E+18\n", + " 146 0.518544323994714E+18 0.518735732970357E+18\n", + " 147 0.518735732970357E+18 0.518927141811782E+18\n", + " 148 0.518927141811782E+18 0.519118550653207E+18\n", + " 149 0.519118550653207E+18 0.519309959628849E+18\n", + " 150 0.519309959628849E+18 0.519501368470274E+18\n", + " 151 0.519501368470274E+18 0.519692777311699E+18\n", + " 152 0.519692777311699E+18 0.519884186287342E+18\n", + " 153 0.519884186287342E+18 0.520075595128766E+18\n", + " 154 0.520075595128766E+18 0.520267003970191E+18\n", + " 155 0.520267003970191E+18 0.520458412945834E+18\n", + " 156 0.520458412945834E+18 0.520649874400608E+18\n", + " 157 0.520649874400608E+18 0.520844424205304E+18\n", + " 158 0.520844424205304E+18 0.521057601685815E+18\n", + " 159 0.521057601685815E+18 0.521249010661458E+18\n", + " 160 0.521249010661458E+18 0.521948424208122E+18\n", + " 161 0.521948424208122E+18 0.522338053038014E+18\n", + " 162 0.522338053038014E+18 0.598485619475218E+18\n", + " 163 0.598485619475218E+18 0.630677923535258E+18\n", + " 164 0.630677923535258E+18 0.631528434165613E+18\n", + " 165 0.631528434165613E+18 0.631765173702492E+18\n", + " 166 0.631765173702492E+18 0.631956582543917E+18\n", + " 167 0.631956582543917E+18 0.632172306134729E+18\n", + " 168 0.632172306134729E+18 0.632363767589503E+18\n", + " 169 0.632363767589503E+18 0.632555176430928E+18\n", + " 170 0.632555176430928E+18 0.632746585406570E+18\n", + " 171 0.632746585406570E+18 0.632937994247995E+18\n", + " 172 0.632937994247995E+18 0.633129403089420E+18\n", + " 173 0.633129403089420E+18 0.633320812065063E+18\n", + " 174 0.633320812065063E+18 0.633512220906488E+18\n", + " 175 0.633512220906488E+18 0.633703629747913E+18\n", + " 176 0.633703629747913E+18 0.633895038723555E+18\n", + " 177 0.633895038723555E+18 0.634086447564980E+18\n", + " 178 0.634086447564980E+18 0.634277856540623E+18\n", + " 179 0.634277856540623E+18 0.634469265382048E+18\n", + " 180 0.634469265382048E+18 0.634660674223473E+18\n", + " 181 0.634660674223473E+18 0.634852083199115E+18\n", + " 182 0.634852083199115E+18 0.635043492040540E+18\n", + " 183 0.635043492040540E+18 0.635234938462929E+18\n", + " 184 0.635234938462929E+18 0.635447299497001E+18\n", + " 185 0.635447299497001E+18 0.635641591737876E+18\n", + " 186 0.635641591737876E+18 0.635833030778290E+18\n", + " 187 0.635833030778290E+18 0.636024439619715E+18\n", + " 188 0.636024439619715E+18 0.636215848461140E+18\n", + " 189 0.636215848461140E+18 0.636750937767018E+18\n", + " 190 0.636750937767018E+18 0.638195828250378E+18\n", + " 191 0.638195828250378E+18 0.643163132008595E+18\n", + " 192 0.643163132008595E+18 0.643481123736781E+18\n", + " 193 0.643481123736781E+18 0.644410277365809E+18\n", + " 194 0.644410277365809E+18 0.644604712548565E+18\n", + " 195 0.644604712548565E+18 0.644796121389990E+18\n", + " 196 0.644796121389990E+18 0.645181291506958E+18\n", + " 197 0.645181291506958E+18 0.645480259617030E+18\n", + " 198 0.645480259617030E+18 0.645671668458455E+18\n", + " 199 0.645671668458455E+18 0.645863077434098E+18\n", + " 200 0.645863077434098E+18 0.646078413001458E+18\n", + " 201 0.646078413001458E+18 0.647196133008867E+18\n", + " 202 0.647196133008867E+18 0.692703801651495E+18\n", + " 203 0.692703801651495E+18 0.781795991899603E+18\n", + " 204 0.781795991899603E+18 0.829396574483251E+18\n", + " 205 0.829396574483251E+18 0.833478057611231E+18\n", + " 206 0.833478057611231E+18 0.835041939358220E+18\n", + " 207 0.835041939358220E+18 0.835748986135511E+18\n", + " 208 0.835748986135511E+18 0.836066892501221E+18\n", + " 209 0.836066892501221E+18 0.836684653485097E+18\n", + " 210 0.836684653485097E+18 0.836876197752209E+18\n", + " 211 0.836876197752209E+18 0.837067606593634E+18\n", + " 212 0.837067606593634E+18 0.837259015435059E+18\n", + " 213 0.837259015435059E+18 0.837450424410702E+18\n", + " 214 0.837450424410702E+18 0.837641863316898E+18\n", + " 215 0.837641863316898E+18 0.837833272158323E+18\n", + " 216 0.837833272158323E+18 0.838024681133965E+18\n", + " 217 0.838024681133965E+18 0.838216089975390E+18\n", + " 218 0.838216089975390E+18 0.838407498951033E+18\n", + " 219 0.838407498951033E+18 0.838598907792458E+18\n", + " 220 0.838598907792458E+18 0.838790316633883E+18\n", + " 221 0.838790316633883E+18 0.838981725609525E+18\n", + " 222 0.838981725609525E+18 0.839173134450950E+18\n", + " 223 0.839173134450950E+18 0.839364543292375E+18\n", + " 224 0.839364543292375E+18 0.839555952268018E+18\n", + " 225 0.839555952268018E+18 0.839747361109443E+18\n", + " 226 0.839747361109443E+18 0.839938769950867E+18\n", + " 227 0.839938769950867E+18 0.840130178926510E+18\n", + " 228 0.840130178926510E+18 0.840321587767935E+18\n", + " 229 0.840321587767935E+18 0.840515962821149E+18\n", + " 230 0.840515962821149E+18 0.840945666917138E+18\n", + " 231 0.840945666917138E+18 0.841646435928637E+18\n", + " 232 0.841646435928637E+18 0.841858285861601E+18\n", + " 233 0.841858285861601E+18 0.842049724767797E+18\n", + " 234 0.842049724767797E+18 0.842281563210121E+18\n", + " 235 0.842281563210121E+18 0.842722369393918E+18\n", + " 236 0.842722369393918E+18 0.844794685611311E+18\n", + " 237 0.844794685611311E+18 0.844986094452736E+18\n", + " 238 0.844986094452736E+18 0.845180402799739E+18\n", + " 239 0.845180402799739E+18 0.845839342990524E+18\n", + " 240 0.845839342990524E+18 0.846030781896720E+18\n", + " 241 0.846030781896720E+18 0.846222190738145E+18\n", + " 242 0.846222190738145E+18 0.846413599713788E+18\n", + " 243 0.846413599713788E+18 0.864502974527832E+18\n", + " 244 0.864502974527832E+18 0.882968182065725E+18\n", + " 245 0.882968182065725E+18 0.883159590907150E+18\n", + " 246 0.883159590907150E+18 0.883350999882793E+18\n", + " 247 0.883350999882793E+18 0.883542438788989E+18\n", + " 248 0.883542438788989E+18 0.884202639686894E+18\n", + " 249 0.884202639686894E+18 0.884397114195444E+18\n", + " 250 0.884397114195444E+18 0.884588523036869E+18\n", + " 251 0.884588523036869E+18 0.886662527579062E+18\n", + " 252 0.886662527579062E+18 0.887140268334121E+18\n", + " 253 0.887140268334121E+18 0.887338684146254E+18\n", + " 254 0.887338684146254E+18 0.887530145735246E+18\n", + " 255 0.887530145735246E+18 0.887743060014793E+18\n", + " 256 0.887743060014793E+18 0.888448298610852E+18\n", + " 257 0.888448298610852E+18 0.888883030502932E+18\n", + " 258 0.888883030502932E+18 0.889075884332417E+18\n", + " 259 0.889075884332417E+18 0.889267293308060E+18\n", + " 260 0.889267293308060E+18 0.889458702149485E+18\n", + " 261 0.889458702149485E+18 0.889650110990909E+18\n", + " 262 0.889650110990909E+18 0.889841519966552E+18\n", + " 263 0.889841519966552E+18 0.890032928807977E+18\n", + " 264 0.890032928807977E+18 0.890224337783620E+18\n", + " 265 0.890224337783620E+18 0.890415746625044E+18\n", + " 266 0.890415746625044E+18 0.890607155466469E+18\n", + " 267 0.890607155466469E+18 0.890798564442112E+18\n", + " 268 0.890798564442112E+18 0.890989973283537E+18\n", + " 269 0.890989973283537E+18 0.891181382124962E+18\n", + " 270 0.891181382124962E+18 0.891372791100604E+18\n", + " 271 0.891372791100604E+18 0.891564199942029E+18\n", + " 272 0.891564199942029E+18 0.891755608783454E+18\n", + " 273 0.891755608783454E+18 0.891947055340061E+18\n", + " 274 0.891947055340061E+18 0.892138464181486E+18\n", + " 275 0.892138464181486E+18 0.892329873022910E+18\n", + " 276 0.892329873022910E+18 0.892521312063324E+18\n", + " 277 0.892521312063324E+18 0.892712833647641E+18\n", + " 278 0.892712833647641E+18 0.893333954101248E+18\n", + " 279 0.893333954101248E+18 0.893653827830415E+18\n", + " 280 0.893653827830415E+18 0.894359090988319E+18\n", + " 281 0.894359090988319E+18 0.899130547593282E+18\n", + " 282 0.899130547593282E+18 0.900009270521627E+18\n", + " 283 0.900009270521627E+18 0.958721087984632E+18\n", + " 284 0.958721087984632E+18 0.104545954810770E+19\n", + " 285 0.104545954810770E+19 0.104631566863643E+19\n", + " 286 0.104631566863643E+19 0.105113412305525E+19\n", + " 287 0.105113412305525E+19 0.105174324551772E+19\n", + " 288 0.105174324551772E+19 0.105209241884269E+19\n", + " 289 0.105209241884269E+19 0.105278706349926E+19\n", + " 290 0.105278706349926E+19 0.105298166296451E+19\n", + " 291 0.105298166296451E+19 0.105317312455351E+19\n", + " 292 0.105317312455351E+19 0.105336453339493E+19\n", + " 293 0.105336453339493E+19 0.105355594223636E+19\n", + " 294 0.105355594223636E+19 0.105374735121200E+19\n", + " 295 0.105374735121200E+19 0.105393881266677E+19\n", + " 296 0.105393881266677E+19 0.105413022150820E+19\n", + " 297 0.105413022150820E+19 0.105432163048384E+19\n", + " 298 0.105432163048384E+19 0.105451303932527E+19\n", + " 299 0.105451303932527E+19 0.105470444830091E+19\n", + " 300 0.105470444830091E+19 0.105489585714233E+19\n", + " 301 0.105489585714233E+19 0.105508726598376E+19\n", + " 302 0.105508726598376E+19 0.105527867495940E+19\n", + " 303 0.105527867495940E+19 0.105547008380083E+19\n", + " 304 0.105547008380083E+19 0.105566149264225E+19\n", + " 305 0.105566149264225E+19 0.105585290161789E+19\n", + " 306 0.105585290161789E+19 0.105604431045932E+19\n", + " 307 0.105604431045932E+19 0.105623571930074E+19\n", + " 308 0.105623571930074E+19 0.105642712827639E+19\n", + " 309 0.105642712827639E+19 0.105661858973116E+19\n", + " 310 0.105661858973116E+19 0.105705459105451E+19\n", + " 311 0.105705459105451E+19 0.105742519707160E+19\n", + " 312 0.105742519707160E+19 0.105797542036583E+19\n", + " 313 0.105797542036583E+19 0.105816688182061E+19\n", + " 314 0.105816688182061E+19 0.105835829066203E+19\n", + " 315 0.105835829066203E+19 0.105865633938067E+19\n", + " 316 0.105865633938067E+19 0.106092287187170E+19\n", + " 317 0.106092287187170E+19 0.106111428071313E+19\n", + " 318 0.106111428071313E+19 0.106130893198642E+19\n", + " 319 0.106130893198642E+19 0.106188462242346E+19\n", + " 320 0.106188462242346E+19 0.106216483535087E+19\n", + " 321 0.106216483535087E+19 0.106235624432651E+19\n", + " 322 0.106235624432651E+19 0.106254765316794E+19\n", + " 323 0.106254765316794E+19 0.106382938307822E+19\n", + " 324 0.106382938307822E+19 0.115292150460685E+19\n" + ] + } + ], + "source": [ + "!cat /cosma8/data/dp016/dc-stis1/csiborg_new/ramses_out_7444_new/output_00001/info_00001.txt" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "dc8ade85", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'/cosma8/data/dp016/dc-stis1/csiborg_dump'" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "paths.dumpdir\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "1891c6ff", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "101" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(paths.ic_ids(tonew=True))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7101a155", + "metadata": {}, + "outputs": [], + "source": [ + " fname = \"ramses_out_{}_{}.npy\".format(\n", + " str(self.nsim).zfill(5), str(self.nsnap).zfill(5))\n", + " data = numpy.load(join(self.paths.dumpdir, fname))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "190d39e6", + "metadata": { + "ExecuteTime": { + "end_time": "2023-03-24T14:16:12.485845Z", + "start_time": "2023-03-24T14:16:01.930739Z" + } + }, + "outputs": [], + "source": [ + "cat0 = csiborgtools.read.HaloCatalogue(7468)\n", + "catx = csiborgtools.read.HaloCatalogue(7588)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "09c93ab0", + "metadata": { + "ExecuteTime": { + "end_time": "2023-03-24T14:16:31.435607Z", + "start_time": "2023-03-24T14:16:12.487458Z" + }, + "scrolled": true + }, + "outputs": [], + "source": [ + "reader = csiborgtools.read.PairOverlap(cat0, catx, max_dist=150 / 0.705)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "650cbe8a", + "metadata": { + "ExecuteTime": { + "end_time": "2023-03-24T14:27:04.213308Z", + "start_time": "2023-03-24T14:27:00.679174Z" + }, + "scrolled": false + }, + "outputs": [ + { + "data": { + "application/javascript": "/* Put everything inside the global mpl namespace */\n/* global mpl */\nwindow.mpl = {};\n\nmpl.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\nmpl.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_device_pixel_ratio', {\n device_pixel_ratio: fig.ratio,\n });\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\nmpl.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\nmpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n\nmpl.figure.prototype._init_canvas = function () {\n var fig = this;\n\n var canvas_div = (this.canvas_div = document.createElement('div'));\n canvas_div.setAttribute(\n 'style',\n 'border: 1px solid #ddd;' +\n 'box-sizing: content-box;' +\n 'clear: both;' +\n 'min-height: 1px;' +\n 'min-width: 1px;' +\n 'outline: 0;' +\n 'overflow: hidden;' +\n 'position: relative;' +\n 'resize: both;'\n );\n\n function on_keyboard_event_closure(name) {\n return function (event) {\n return fig.key_event(event, name);\n };\n }\n\n canvas_div.addEventListener(\n 'keydown',\n on_keyboard_event_closure('key_press')\n );\n canvas_div.addEventListener(\n 'keyup',\n on_keyboard_event_closure('key_release')\n );\n\n this._canvas_extra_style(canvas_div);\n this.root.appendChild(canvas_div);\n\n var canvas = (this.canvas = document.createElement('canvas'));\n canvas.classList.add('mpl-canvas');\n canvas.setAttribute('style', 'box-sizing: content-box;');\n\n this.context = canvas.getContext('2d');\n\n var backingStore =\n this.context.backingStorePixelRatio ||\n this.context.webkitBackingStorePixelRatio ||\n this.context.mozBackingStorePixelRatio ||\n this.context.msBackingStorePixelRatio ||\n this.context.oBackingStorePixelRatio ||\n this.context.backingStorePixelRatio ||\n 1;\n\n this.ratio = (window.devicePixelRatio || 1) / backingStore;\n\n var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n 'canvas'\n ));\n rubberband_canvas.setAttribute(\n 'style',\n 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n );\n\n // Apply a ponyfill if ResizeObserver is not implemented by browser.\n if (this.ResizeObserver === undefined) {\n if (window.ResizeObserver !== undefined) {\n this.ResizeObserver = window.ResizeObserver;\n } else {\n var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n this.ResizeObserver = obs.ResizeObserver;\n }\n }\n\n this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n var nentries = entries.length;\n for (var i = 0; i < nentries; i++) {\n var entry = entries[i];\n var width, height;\n if (entry.contentBoxSize) {\n if (entry.contentBoxSize instanceof Array) {\n // Chrome 84 implements new version of spec.\n width = entry.contentBoxSize[0].inlineSize;\n height = entry.contentBoxSize[0].blockSize;\n } else {\n // Firefox implements old version of spec.\n width = entry.contentBoxSize.inlineSize;\n height = entry.contentBoxSize.blockSize;\n }\n } else {\n // Chrome <84 implements even older version of spec.\n width = entry.contentRect.width;\n height = entry.contentRect.height;\n }\n\n // Keep the size of the canvas and rubber band canvas in sync with\n // the canvas container.\n if (entry.devicePixelContentBoxSize) {\n // Chrome 84 implements new version of spec.\n canvas.setAttribute(\n 'width',\n entry.devicePixelContentBoxSize[0].inlineSize\n );\n canvas.setAttribute(\n 'height',\n entry.devicePixelContentBoxSize[0].blockSize\n );\n } else {\n canvas.setAttribute('width', width * fig.ratio);\n canvas.setAttribute('height', height * fig.ratio);\n }\n canvas.setAttribute(\n 'style',\n 'width: ' + width + 'px; height: ' + height + 'px;'\n );\n\n rubberband_canvas.setAttribute('width', width);\n rubberband_canvas.setAttribute('height', height);\n\n // And update the size in Python. We ignore the initial 0/0 size\n // that occurs as the element is placed into the DOM, which should\n // otherwise not happen due to the minimum size styling.\n if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n fig.request_resize(width, height);\n }\n }\n });\n this.resizeObserverInstance.observe(canvas_div);\n\n function on_mouse_event_closure(name) {\n return function (event) {\n return fig.mouse_event(event, name);\n };\n }\n\n rubberband_canvas.addEventListener(\n 'mousedown',\n on_mouse_event_closure('button_press')\n );\n rubberband_canvas.addEventListener(\n 'mouseup',\n on_mouse_event_closure('button_release')\n );\n rubberband_canvas.addEventListener(\n 'dblclick',\n on_mouse_event_closure('dblclick')\n );\n // Throttle sequential mouse events to 1 every 20ms.\n rubberband_canvas.addEventListener(\n 'mousemove',\n on_mouse_event_closure('motion_notify')\n );\n\n rubberband_canvas.addEventListener(\n 'mouseenter',\n on_mouse_event_closure('figure_enter')\n );\n rubberband_canvas.addEventListener(\n 'mouseleave',\n on_mouse_event_closure('figure_leave')\n );\n\n canvas_div.addEventListener('wheel', function (event) {\n if (event.deltaY < 0) {\n event.step = 1;\n } else {\n event.step = -1;\n }\n on_mouse_event_closure('scroll')(event);\n });\n\n canvas_div.appendChild(canvas);\n canvas_div.appendChild(rubberband_canvas);\n\n this.rubberband_context = rubberband_canvas.getContext('2d');\n this.rubberband_context.strokeStyle = '#000000';\n\n this._resize_canvas = function (width, height, forward) {\n if (forward) {\n canvas_div.style.width = width + 'px';\n canvas_div.style.height = height + 'px';\n }\n };\n\n // Disable right mouse context menu.\n this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n event.preventDefault();\n return false;\n });\n\n function set_focus() {\n canvas.focus();\n canvas_div.focus();\n }\n\n window.setTimeout(set_focus, 100);\n};\n\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.figure.prototype.handle_figure_label = function (fig, msg) {\n // Updates the figure title.\n fig.header.textContent = msg['label'];\n};\n\nmpl.figure.prototype.handle_cursor = function (fig, msg) {\n fig.rubberband_canvas.style.cursor = msg['cursor'];\n};\n\nmpl.figure.prototype.handle_message = function (fig, msg) {\n fig.message.textContent = msg['message'];\n};\n\nmpl.figure.prototype.handle_draw = function (fig, _msg) {\n // Request the server to send over a new figure.\n fig.send_draw_message();\n};\n\nmpl.figure.prototype.handle_image_mode = function (fig, msg) {\n fig.image_mode = msg['mode'];\n};\n\nmpl.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\nmpl.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\nmpl.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.\nmpl.figure.prototype._make_on_message_function = function (fig) {\n return function socket_on_message(evt) {\n if (evt.data instanceof Blob) {\n var img = evt.data;\n if (img.type !== 'image/png') {\n /* FIXME: We get \"Resource interpreted as Image but\n * transferred with MIME type text/plain:\" errors on\n * Chrome. But how to set the MIME type? It doesn't seem\n * to be part of the websocket stream */\n img.type = 'image/png';\n }\n\n /* Free the memory for the previous frames */\n if (fig.imageObj.src) {\n (window.URL || window.webkitURL).revokeObjectURL(\n fig.imageObj.src\n );\n }\n\n fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n img\n );\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n } else if (\n typeof evt.data === 'string' &&\n evt.data.slice(0, 21) === 'data:image/png;base64'\n ) {\n fig.imageObj.src = evt.data;\n fig.updated_canvas_event();\n fig.waiting = false;\n return;\n }\n\n var msg = JSON.parse(evt.data);\n var msg_type = msg['type'];\n\n // Call the \"handle_{type}\" callback, which takes\n // the figure and JSON message as its only arguments.\n try {\n var callback = fig['handle_' + msg_type];\n } catch (e) {\n console.log(\n \"No handler for the '\" + msg_type + \"' message type: \",\n msg\n );\n return;\n }\n\n if (callback) {\n try {\n // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n callback(fig, msg);\n } catch (e) {\n console.log(\n \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n e,\n e.stack,\n msg\n );\n }\n }\n };\n};\n\n// from https://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\nmpl.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 * https://stackoverflow.com/a/24161582/3208463\n */\nfunction 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\nmpl.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\nmpl.figure.prototype._key_event_extra = function (_event, _name) {\n // Handle any extra behaviour associated with a key event\n};\n\nmpl.figure.prototype.key_event = function (event, name) {\n // Prevent repeat events\n if (name === 'key_press') {\n if (event.key === this._key) {\n return;\n } else {\n this._key = event.key;\n }\n }\n if (name === 'key_release') {\n this._key = null;\n }\n\n var value = '';\n if (event.ctrlKey && event.key !== 'Control') {\n value += 'ctrl+';\n }\n else if (event.altKey && event.key !== 'Alt') {\n value += 'alt+';\n }\n else if (event.shiftKey && event.key !== 'Shift') {\n value += 'shift+';\n }\n\n value += 'k' + event.key;\n\n this._key_event_extra(event, name);\n\n this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n return false;\n};\n\nmpl.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\nmpl.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\nvar _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\nmpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o\", \"download\"]];\n\nmpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\n\nmpl.default_extension = \"png\";/* global mpl */\n\nvar comm_websocket_adapter = function (comm) {\n // Create a \"websocket\"-like object which calls the given IPython comm\n // object with the appropriate methods. Currently this is a non binary\n // socket, so there is still some room for performance tuning.\n var ws = {};\n\n ws.binaryType = comm.kernel.ws.binaryType;\n ws.readyState = comm.kernel.ws.readyState;\n function updateReadyState(_event) {\n if (comm.kernel.ws) {\n ws.readyState = comm.kernel.ws.readyState;\n } else {\n ws.readyState = 3; // Closed state.\n }\n }\n comm.kernel.ws.addEventListener('open', updateReadyState);\n comm.kernel.ws.addEventListener('close', updateReadyState);\n comm.kernel.ws.addEventListener('error', updateReadyState);\n\n ws.close = function () {\n comm.close();\n };\n ws.send = function (m) {\n //console.log('sending', m);\n comm.send(m);\n };\n // Register the callback with on_msg.\n comm.on_msg(function (msg) {\n //console.log('receiving', msg['content']['data'], msg);\n var data = msg['content']['data'];\n if (data['blob'] !== undefined) {\n data = {\n data: new Blob(msg['buffers'], { type: data['blob'] }),\n };\n }\n // Pass the mpl event to the overridden (by mpl) onmessage function.\n ws.onmessage(data);\n });\n return ws;\n};\n\nmpl.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\nmpl.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\nmpl.figure.prototype.close_ws = function (fig, msg) {\n fig.send_message('closing', msg);\n // fig.ws.close()\n};\n\nmpl.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\nmpl.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\nmpl.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\nmpl.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\nmpl.figure.prototype._root_extra_style = function (el) {\n el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n};\n\nmpl.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\nmpl.figure.prototype._key_event_extra = function (event, _name) {\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\nmpl.figure.prototype.handle_save = function (fig, _msg) {\n fig.ondownload(fig, null);\n};\n\nmpl.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.\nif (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": [ + "ks = np.argsort(reader.cat0(\"totpartmass\"))[::-1]\n", + "k = ks[1]\n", + "\n", + "\n", + "plt.figure()\n", + "plt.scatter(reader.dist(False, \"r200\")[k], reader.mass_ratio()[k], c=reader.overlap(False)[k])\n", + "plt.colorbar(label=\"Overlap\")\n", + "\n", + "plt.title(r\"$\\log M_{{\\rm tot}} / M_\\odot = {:.4f}$\".format(np.log10(reader.cat0(\"totpartmass\")[k])))\n", + "plt.xlabel(r\"$\\Delta r_i / R_{200c}$\")\n", + "plt.ylabel(r\"$|\\log \\dfrac{M_i}{M_{\\rm tot}}|$\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "51dd52f0", + "metadata": { + "ExecuteTime": { + "end_time": "2023-03-24T14:49:25.961273Z", + "start_time": "2023-03-24T14:27:05.607189Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting: 2023-03-24 14:27:05.644524.\n", + "Loaded `clump0`: 2023-03-24 14:41:48.868024.\n", + "Loaded `clumpx`: 2023-03-24 14:49:25.871648.\n" + ] + } + ], + "source": [ + "print(\"Starting: {}.\".format(datetime.now()))\n", + "clumps0 = np.load(\"/mnt/extraspace/rstiskalek/csiborg/initmatch/clump_7468_particles.npy\", allow_pickle=True)\n", + "print(\"Loaded `clump0`: {}.\".format(datetime.now()))\n", + "clumpsx = np.load(\"/mnt/extraspace/rstiskalek/csiborg/initmatch/clump_7588_particles.npy\", allow_pickle=True)\n", + "print(\"Loaded `clumpx`: {}.\".format(datetime.now()))\n", + "\n", + "overlapper = csiborgtools.match.ParticleOverlap()\n", + "\n", + "hid2clumps0 = {hid: n for n, hid in enumerate(clumps0[\"ID\"])}\n", + "hid2clumpsx = {hid: n for n, hid in enumerate(clumpsx[\"ID\"])}" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "bcef2505", + "metadata": { + "ExecuteTime": { + "end_time": "2023-03-24T15:09:47.965132Z", + "start_time": "2023-03-24T15:08:50.141995Z" + } + }, + "outputs": [], + "source": [ + "# Convert positions to cell IDs\n", + "overlapper.clumps_pos2cell(clumps0)\n", + "overlapper.clumps_pos2cell(clumpsx)\n", + "\n", + "mins0, maxs0 = csiborgtools.match.get_clumplims(clumps0, overlapper.inv_clength, overlapper.nshift)\n", + "minsx, maxsx = csiborgtools.match.get_clumplims(clumpsx, overlapper.inv_clength, overlapper.nshift)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "e2c24b54", + "metadata": { + "ExecuteTime": { + "end_time": "2023-03-24T15:10:35.352871Z", + "start_time": "2023-03-24T15:09:47.966986Z" + } + }, + "outputs": [], + "source": [ + "delta_bckg = overlapper.make_bckg_delta(clumps0)\n", + "delta_bckg = overlapper.make_bckg_delta(clumpsx, delta=delta_bckg)" + ] + }, + { + "cell_type": "code", + "execution_count": 369, + "id": "fb4e8c0a", + "metadata": { + "ExecuteTime": { + "end_time": "2023-03-24T17:04:22.358413Z", + "start_time": "2023-03-24T17:01:54.600744Z" + } + }, + "outputs": [], + "source": [ + "smooth_kwargs = {\"sigma\": 1, \"truncate\": 4, \"mode\": \"constant\", \"cval\": 0.0}\n", + "\n", + "delta_bckg_smooth = gaussian_filter(delta_bckg, **smooth_kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": 363, + "id": "bb707fb2", + "metadata": { + "ExecuteTime": { + "end_time": "2023-03-24T17:00:16.973318Z", + "start_time": "2023-03-24T17:00:16.011637Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ratio is 0.9820815\n", + "Original overlap is 0.6785714\n", + "Smoothed overlap is 0.6664124\n" + ] + }, + { + "data": { + "text/plain": [ + "0.32628544480462635" + ] + }, + "execution_count": 363, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# k = 24734 # skull!\n", + "\n", + "ks = np.argsort(reader.cat0(\"totpartmass\"))[::-1]\n", + "# k = ks[1]\n", + "k = 331\n", + "n = 0\n", + "\n", + "print(\"Ratio is \", summed_ratio[k])\n", + "\n", + "print(\"Original overlap is \", overlap_raw[k][n])\n", + "print(\"Smoothed overlap is \", overlap_smoothed[k][n])\n", + "\n", + "index_cl0 = hid2clumps0[reader.cat0(\"index\", k)]\n", + "cl0 = clumps0[index_cl0][0]\n", + "mins_cl0, maxs_cl0 = mins0[index_cl0], maxs0[index_cl0]\n", + "\n", + "index_clx = hid2clumpsx[reader.catx(\"index\", reader[\"match_indxs\"][k][n])]\n", + "clx = clumpsx[index_clx][0]\n", + "mins_clx, maxs_clx = minsx[index_clx], maxsx[index_clx]\n", + "\n", + "\n", + "\n", + "delta1, delta2, cellmins, nonzero = overlapper.make_deltas(\n", + " cl0, clx, mins_cl0, maxs_cl0, mins_clx, maxs_clx, smooth_kwargs=smooth_kwargs)\n", + "\n", + "csiborgtools.match.calculate_overlap(delta1, delta2, cellmins, delta_bckg_smooth)" + ] + }, + { + "cell_type": "code", + "execution_count": 364, + "id": "5eeed44f", + "metadata": { + "ExecuteTime": { + "end_time": "2023-03-24T17:00:19.825171Z", + "start_time": "2023-03-24T17:00:19.787750Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NGP/smoothed overlap 0.6785714 0.6664124\n", + "0.32628544480462635\n", + "Sum is 0.32628544480462635\n", + "Originally NGP/smoothed was 0.6785714 0.6664124\n" + ] + } + ], + "source": [ + "xs = []\n", + "for n in range(reader[\"match_indxs\"][k].size):\n", + "\n", + " index_clx = hid2clumpsx[reader.catx(\"index\", reader[\"match_indxs\"][k][n])]\n", + " clx = clumpsx[index_clx][0]\n", + " mins_clx, maxs_clx = minsx[index_clx], maxsx[index_clx]\n", + " \n", + " print(\"NGP/smoothed overlap \", overlap_raw[k][n], overlap_smoothed[k][n])\n", + " delta1, delta2, cellmins, nonzero1 = overlapper.make_deltas(\n", + " cl0, clx, mins_cl0, maxs_cl0, mins_clx, maxs_clx, smooth_kwargs=smooth_kwargs)\n", + " \n", + " x = csiborgtools.match.calculate_overlap(delta1, delta2, cellmins, delta_bckg_smooth)\n", + " print(x)\n", + " xs.append(x)\n", + " \n", + "print(\"Sum is \", sum(xs))\n", + "print(\"Originally NGP/smoothed was \", summed_raw[k], summed_smoothed[k])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1db1bc57", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5883ecc7", + "metadata": { + "ExecuteTime": { + "end_time": "2023-01-31T17:51:03.510067Z", + "start_time": "2023-01-31T17:51:03.469080Z" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a58b300c", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "56b90375", + "metadata": { + "ExecuteTime": { + "end_time": "2023-01-28T18:54:51.064154Z", + "start_time": "2023-01-28T18:54:47.314086Z" + } + }, + "outputs": [], + "source": [ + "dlogm = [None] * len(indxs)\n", + "mass = [None] * len(indxs)\n", + "for k in trange(len(indxs)):\n", + " dlogm[k] = np.abs(np.log10(cat[0][\"totpartmass\"][k]) - np.log10(cat[1][\"totpartmass\"][indxs[k]]))\n", + " mass[k] = np.ones(indxs[k].size) * cat[0][\"totpartmass\"][k]\n", + "dlogm = np.asanyarray(dlogm)\n", + "mass = np.asanyarray(mass)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e44414b7", + "metadata": { + "ExecuteTime": { + "end_time": "2023-01-28T18:56:19.841434Z", + "start_time": "2023-01-28T18:56:19.041227Z" + } + }, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.scatter(np.concatenate(dlogm), np.concatenate(overlap), s=1, rasterized=True)\n", + "t = np.linspace(0, 2)\n", + "plt.plot(t, 10**(-t), c=\"red\", label=r\"$10^{-|\\log M_1 / M_2|}$\")\n", + "plt.xlabel(r\"$|\\log M_1 / M_2|$\")\n", + "plt.ylabel(r\"$\\mathcal{O}$\")\n", + "plt.legend()\n", + "plt.tight_layout()\n", + "# plt.savefig(\"../plots/mass_comparison.png\", dpi=450)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03cec1b7", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1cde4797", + "metadata": { + "ExecuteTime": { + "end_time": "2023-01-28T15:19:36.573717Z", + "start_time": "2023-01-28T15:19:34.985074Z" + } + }, + "outputs": [], + "source": [ + "for k in trange(len(indxs)):\n", + " if np.any((dlogm[k] > 1.75) & (overlap[k] > 0.15)):\n", + " print(k)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "58b2cb87", + "metadata": { + "ExecuteTime": { + "end_time": "2023-01-28T15:27:57.709539Z", + "start_time": "2023-01-28T15:27:57.131915Z" + } + }, + "outputs": [], + "source": [ + "k = 97788\n", + "print(dlogm[k])\n", + "print(overlap[k])\n", + "n = np.argmax(overlap[k])\n", + "\n", + "index_cl0 = [cl[1] for cl in clumps0].index(cat[0][k][\"index\"])\n", + "cl0 = clumps0[index_cl0][0]\n", + "mins_cl0, maxs_cl0 = mins0[index_cl0], maxs0[index_cl0]\n", + "\n", + "index_clx = [cl[1] for cl in clumpsx].index(cat[1][\"index\"][indxs[k]][n])\n", + "clx = clumpsx[index_clx][0]\n", + "mins_clx, maxs_clx = minsx[index_clx], maxsx[index_clx]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f5193d37", + "metadata": { + "ExecuteTime": { + "end_time": "2023-01-28T15:28:02.049121Z", + "start_time": "2023-01-28T15:28:02.016020Z" + } + }, + "outputs": [], + "source": [ + "delta1, delta2, cellmins = overlapper.make_deltas(cl0, clx, mins_cl0, maxs_cl0, mins_clx, maxs_clx)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e0176db", + "metadata": { + "ExecuteTime": { + "end_time": "2023-01-28T15:28:03.044781Z", + "start_time": "2023-01-28T15:28:03.010050Z" + } + }, + "outputs": [], + "source": [ + "overlapper.overlap(delta1, delta2, cellmins, delta)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a3993216", + "metadata": { + "ExecuteTime": { + "end_time": "2023-01-28T15:28:03.662552Z", + "start_time": "2023-01-28T15:28:03.630680Z" + } + }, + "outputs": [], + "source": [ + "delta1.sum() / delta2.sum()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "120b0b61", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5170b359", + "metadata": { + "ExecuteTime": { + "end_time": "2023-01-28T15:28:05.961500Z", + "start_time": "2023-01-28T15:28:05.857277Z" + } + }, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.imshow(np.sum(delta1, axis=2))\n", + "plt.show()\n", + "\n", + "plt.figure()\n", + "plt.imshow(np.sum(delta2, axis=2))\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "adcca1e1", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d74da689", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0989f96e", + "metadata": { + "ExecuteTime": { + "start_time": "2023-01-26T09:49:07.667Z" + } + }, + "outputs": [], + "source": [ + "ncounter = len(indxs[k])\n", + "true_overlap = np.full(ncounter, np.nan)\n", + "spherical_overlap = np.full(ncounter, np.nan)\n", + "\n", + "for n in trange(len(indxs[k])):\n", + " clx = clumpsx[[cl[1] for cl in clumpsx].index(cat[1][\"index\"][indxs[k]][n])][0]\n", + " \n", + " R1 = (3 * cl0.size / (4 * np.pi))**(1./3) * 1 / 2048\n", + " R2 = (3 * clx.size / (4 * np.pi))**(1./3) * 1 / 2048\n", + " d = np.linalg.norm([np.mean(cl0[p]) - np.mean(clx[p]) for p in ('x', 'y', 'z')])\n", + " \n", + " spherical_overlap[n] = csiborgtools.match.spherical_overlap(R1, R2, d)\n", + " true_overlap[n] = overlapper(cl0, clx, delta)\n", + " \n", + "# print(true_overlap, spherical_overlap)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6007e537", + "metadata": { + "ExecuteTime": { + "start_time": "2023-01-26T09:49:07.668Z" + } + }, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.scatter(true_overlap, spherical_overlap)\n", + "\n", + "t = np.linspace(0, 1, 100)\n", + "plt.plot(t, t, c=\"k\", ls=\"--\")\n", + "\n", + "plt.xlabel(\"True overlap\")\n", + "plt.ylabel(\"Spherical overlap\")\n", + "# plt.xscale(\"log\")\n", + "# plt.yscale(\"log\")\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd1a9591", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2a4062f2", + "metadata": { + "ExecuteTime": { + "start_time": "2023-01-26T09:49:07.670Z" + } + }, + "outputs": [], + "source": [ + "R1 = (3 * cl0.size / (4 * np.pi))**(1./3) * 1 / 2048\n", + "R2 = (3 * clx.size / (4 * np.pi))**(1./3) * 1 / 2048\n", + "d = np.linalg.norm([np.mean(cl0[p]) - np.mean(clx[p]) for p in ('x', 'y', 'z')])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d2b0dcd5", + "metadata": { + "ExecuteTime": { + "end_time": "2023-01-23T20:52:54.565480Z", + "start_time": "2023-01-23T20:52:54.534775Z" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "64634315", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9cfcc924", + "metadata": { + "ExecuteTime": { + "end_time": "2023-01-23T19:00:54.795153Z", + "start_time": "2023-01-23T19:00:54.447475Z" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a747a632", + "metadata": { + "ExecuteTime": { + "start_time": "2023-01-26T09:49:07.686Z" + } + }, + "outputs": [], + "source": [ + "box = cat[0].box\n", + "maverage = box.box2solarmass(clumps0[2][0][\"M\"][0])\n", + "cell = box.box2mpc(1/2048)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27bb5c36", + "metadata": { + "ExecuteTime": { + "start_time": "2023-01-26T09:49:07.686Z" + } + }, + "outputs": [], + "source": [ + "n_sim = 0\n", + "import numpy\n", + "\n", + "R = (3 * cat.cats[n_sim][\"npart\"] / (4 * numpy.pi))**(1./3) * 1 / 2048\n", + "R = cat.cats[n_sim].box.box2mpc(R)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03a7825f", + "metadata": { + "ExecuteTime": { + "start_time": "2023-01-26T09:49:07.687Z" + } + }, + "outputs": [], + "source": [ + "# dlogm = [None] * len(indxs)\n", + "# for k in trange(len(indxs)):\n", + "# dlogm[k] = np.abs(np.log10(cat[0][\"totpartmass\"][k]) - np.log10(cat[1][\"totpartmass\"][indxs[k]]))\n", + "# dlogm = np.asanyarray(dlogm)\n", + "\n", + "normdist = [None] * len(indxs)\n", + "masses = [None] * len(indxs)\n", + "for k in trange(len(indxs)):\n", + " normdist[k] = dist0[k] / ((3 * cat[0][\"totpartmass\"][k] / (4 * np.pi * maverage))**(1/3) * cell)\n", + " masses[k] = np.log10(np.ones(indxs[k].size) * cat[0][\"totpartmass\"][k])\n", + " \n", + "normdist = np.asanyarray(normdist)\n", + "masses = np.asanyarray(masses)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e0330ca5", + "metadata": { + "ExecuteTime": { + "start_time": "2023-01-26T09:49:07.688Z" + }, + "scrolled": false + }, + "outputs": [], + "source": [ + "plt.figure()\n", + "\n", + "# plt.scatter(np.concatenate(normdist), np.concatenate(overlap), c=np.concatenate(masses), s=4)\n", + "\n", + "plt.scatter(np.concatenate(normdist), np.concatenate(masses), c=np.concatenate(overlap), s=4)\n", + "\n", + "\n", + "plt.colorbar()\n", + "# plt.xlabel(r\"$z = 0$ normalised separation by $\\hat{R}$\")\n", + "# plt.xlabel(r\"Absolute difference in total mass [dex]\")\n", + "# plt.xscale(\"log\")\n", + "# plt.ylabel(r\"$\\mathcal{O}$\")\n", + "plt.xscale(\"log\")\n", + "plt.tight_layout()\n", + "# plt.savefig(\"../plots/another_view.png\", dpi=450)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de23a8a1", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6b5e4f8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "43bc17db", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4df25af", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d25a16d", + "metadata": { + "ExecuteTime": { + "start_time": "2023-01-26T09:49:07.690Z" + } + }, + "outputs": [], + "source": [ + "cl0 = clumps0[[cl[1] for cl in clumps0].index(cat[0][k][\"index\"])][0]\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clx = clumpsx[[cl[1] for cl in clumpsx].index(cat[1][\"index\"][indxs[k]][n])][0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "be26cbcc", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/scripts/crosspk.py b/scripts/crosspk.py index c7dd501..9c130b8 100644 --- a/scripts/crosspk.py +++ b/scripts/crosspk.py @@ -46,7 +46,7 @@ rank = comm.Get_rank() nproc = comm.Get_size() MAS = "CIC" # mass asignment scheme -paths = csiborgtools.read.CSiBORGPaths() +paths = csiborgtools.read.CSiBORGPaths(**csiborgtools.paths_glamdring) box = csiborgtools.units.BoxUnits(paths) reader = csiborgtools.read.ParticleReader(paths) ics = paths.ic_ids(tonew=False) diff --git a/scripts/fieldprop.py b/scripts/fieldprop.py index dfbe361..fe8807b 100644 --- a/scripts/fieldprop.py +++ b/scripts/fieldprop.py @@ -60,7 +60,7 @@ fperm = join(dumpdir, "fields", fname + ".npy") dtype = {"names": ["delta", "phi"], "formats": [numpy.float32] * 2} # CSiBORG simulation paths -paths = csiborgtools.read.CSiBORGPaths() +paths = csiborgtools.read.CSiBORGPaths(**csiborgtools.paths_glamdring) ics = paths.ic_ids(tonew=False) nsims = len(ics) diff --git a/scripts/fit_halos.py b/scripts/fit_halos.py index ea18187..06e9aac 100644 --- a/scripts/fit_halos.py +++ b/scripts/fit_halos.py @@ -34,7 +34,7 @@ comm = MPI.COMM_WORLD rank = comm.Get_rank() nproc = comm.Get_size() -paths = csiborgtools.read.CSiBORGPaths() +paths = csiborgtools.read.CSiBORGPaths(**csiborgtools.paths_glamdring) dumpdir = "/mnt/extraspace/rstiskalek/csiborg/" loaddir = join(dumpdir, "temp") cols_collect = [("npart", numpy.int64), ("totpartmass", numpy.float64), @@ -118,8 +118,7 @@ for i, nsim in enumerate(paths.ic_ids(tonew=False)): out_collected = csiborgtools.read.combine_splits( utils.Nsplits, nsnap, nsim, partreader, cols_collect, remove_splits=True, verbose=False) - fname = join(paths.dumpdir, "ramses_out_{}_{}.npy" - .format(str(nsim).zfill(5), str(nsnap).zfill(5))) + fname = paths.hcat_path(nsim) print("Saving results to `{}`.".format(fname)) numpy.save(fname, out_collected) diff --git a/scripts/initmatch.py b/scripts/initmatch.py index 503074f..1696405 100644 --- a/scripts/initmatch.py +++ b/scripts/initmatch.py @@ -44,25 +44,23 @@ parser = ArgumentParser() parser.add_argument("--dump_clumps", type=lambda x: bool(strtobool(x))) args = parser.parse_args() -paths = csiborgtools.read.CSiBORGPaths() +paths = csiborgtools.read.CSiBORGPaths(**csiborgtools.paths_glamdring) nsims = paths.ic_ids(tonew=True) # Output files -dumpdir = "/mnt/extraspace/rstiskalek/csiborg/" -ftemp = join(dumpdir, "temp_initmatch", "temp_{}_{}_{}.npy") -fpermcm = join(dumpdir, "initmatch", "clump_{}_cm.npy") -fpermpart = join(dumpdir, "initmatch", "clump_{}_particles.npy") +ftemp = join(paths.dumpdir, "temp_initmatch", "temp_{}_{}_{}.npy") +fpermcm = join(paths.dumpdir, "initmatch", "clump_{}_cm.npy") +fpermpart = join(paths.dumpdir, "initmatch", "clump_{}_particles.npy") for nsim in nsims: if rank == 0: print("{}: reading simulation {}.".format(datetime.now(), nsim), flush=True) - nsnap_min = min(paths.get_snapshots(nsim)) nsnap_max = max(paths.get_snapshots(nsim)) reader = csiborgtools.read.ParticleReader(paths) # Read and sort the initial particle files by their particle IDs - part0 = reader.read_particle(nsnap_min, nsim, ["x", "y", "z", "M", "ID"], + part0 = reader.read_particle(1, nsim, ["x", "y", "z", "M", "ID"], verbose=False) part0 = part0[numpy.argsort(part0["ID"])] diff --git a/scripts/knn_auto.py b/scripts/knn_auto.py index 2dc59bf..5e067ec 100644 --- a/scripts/knn_auto.py +++ b/scripts/knn_auto.py @@ -60,7 +60,7 @@ ics = [7444, 7468, 7492, 7516, 7540, 7564, 7588, 7612, 7636, 7660, 7684, 9820, 9844] dumpdir = "/mnt/extraspace/rstiskalek/csiborg/knn" fout = join(dumpdir, "auto", "knncdf_{}_{}.p") -paths = csiborgtools.read.CSiBORGPaths() +paths = csiborgtools.read.CSiBORGPaths(**csiborgtools.paths_glamdring) knncdf = csiborgtools.clustering.kNN_CDF() ############################################################################### diff --git a/scripts/knn_cross.py b/scripts/knn_cross.py index fbccfed..7720d8c 100644 --- a/scripts/knn_cross.py +++ b/scripts/knn_cross.py @@ -58,7 +58,7 @@ ics = [7444, 7468, 7492, 7516, 7540, 7564, 7588, 7612, 7636, 7660, 7684, 9292, 9316, 9340, 9364, 9388, 9412, 9436, 9460, 9484, 9508, 9532, 9556, 9580, 9604, 9628, 9652, 9676, 9700, 9724, 9748, 9772, 9796, 9820, 9844] -paths = csiborgtools.read.CSiBORGPaths() +paths = csiborgtools.read.CSiBORGPaths(**csiborgtools.paths_glamdring) dumpdir = "/mnt/extraspace/rstiskalek/csiborg/knn" fout = join(dumpdir, "cross", "knncdf_{}_{}_{}.p") knncdf = csiborgtools.clustering.kNN_CDF() diff --git a/scripts/singlematch.py b/scripts/singlematch.py index fa2f5ce..7956a96 100644 --- a/scripts/singlematch.py +++ b/scripts/singlematch.py @@ -35,7 +35,7 @@ parser.add_argument("--sigma", type=float) args = parser.parse_args() # File paths -paths = csiborgtools.read.CSiBORGPaths() +paths = csiborgtools.read.CSiBORGPaths(**csiborgtools.paths_glamdring) fout = join(utils.dumpdir, "overlap", "cross_{}_{}.npz".format(args.nsim0, args.nsimx)) smooth_kwargs = {"sigma": args.sigma, "mode": "constant", "cval": 0.0} diff --git a/scripts/split_halos.py b/scripts/split_halos.py index 88b20e2..3eed63b 100644 --- a/scripts/split_halos.py +++ b/scripts/split_halos.py @@ -32,7 +32,7 @@ comm = MPI.COMM_WORLD rank = comm.Get_rank() nproc = comm.Get_size() -paths = csiborgtools.read.CSiBORGPaths() +paths = csiborgtools.read.CSiBORGPaths(**csiborgtools.paths_glamdring) sims = paths.ic_ids(False) partcols = ["x", "y", "z", "vx", "vy", "vz", "M", "level"]