diff --git a/csiborgtools/clustering/2pcf.py b/csiborgtools/clustering/2pcf.py deleted file mode 100644 index 16e0284..0000000 --- a/csiborgtools/clustering/2pcf.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (C) 2023 Richard Stiskalek -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# 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. -""" -2PCF calculation. - -NOTE: This is an old script that needs to be updated. -""" -import numpy -from Corrfunc.mocks import DDtheta_mocks -from Corrfunc.utils import convert_3d_counts_to_cf -from .utils import (rvs_on_sphere, wrapRA) - - -def sphere_angular_tpcf(bins, RA1, DEC1, RA2=None, DEC2=None, nthreads=1, - Nmult=5, seed1=42, seed2=666): - """ - Calculate the angular two-point correlation function. The coordinates must - be provided in degrees. With the right ascension and degrees being - in range of :math:`[-180, 180]` and :math:`[-90, 90]` degrees. - If `RA2` and `DEC2` are provided cross-correlates the first data set with - the second. Creates a uniformly sampled randoms on the surface of a sphere - of size `Nmult` times the corresponding number of data points. Uses the - Landy-Szalay estimator. - - Parameters - ---------- - bins : 1-dimensional array - Angular bins to calculate the angular twop-point correlation function. - RA1 : 1-dimensional array - Right ascension of the 1st data set, in degrees. - DEC1 : 1-dimensional array - Declination of the 1st data set, in degrees. - RA2 : 1-dimensional array, optional - Right ascension of the 2nd data set, in degrees. - DEC2 : 1-dimensional array, optional - Declination of the 2nd data set, in degrees. - nthreads : int, optional - Number of threads, by default 1. - Nmult : int, optional - Relative randoms size with respect to the data set. By default 5. - seed1 : int, optional - Seed to generate the first set of randoms. - seed2 : int, optional - Seed to generate the second set of randoms. - - Returns - ------- - cf : 1-dimensional array - The angular 2-point correlation function. - """ - # If not provided calculate autocorrelation - if RA2 is None: - RA2 = RA1 - DEC2 = DEC1 - # Get the array sizes - ND1 = RA1.size - ND2 = RA2.size - NR1 = ND1 * Nmult - NR2 = ND2 * Nmult - # Generate randoms. Note that these are over the sphere! - randRA1, randDEC1 = rvs_on_sphere(NR1, indeg=True, random_state=seed1) - randRA2, randDEC2 = rvs_on_sphere(NR2, indeg=True, random_state=seed2) - # Wrap RA - RA1 = wrapRA(numpy.copy(RA1), indeg=True) - RA2 = wrapRA(numpy.copy(RA2), indeg=True) - # Calculate pairs - D1D2 = DDtheta_mocks(0, nthreads, bins, RA1, DEC1, RA2=RA2, DEC2=DEC2) - D1R2 = DDtheta_mocks(0, nthreads, bins, RA1, DEC1, - RA2=randRA2, DEC2=randDEC2) - D2R1 = DDtheta_mocks(0, nthreads, bins, RA2, DEC2, - RA2=randRA1, DEC2=randDEC1) - R1R2 = DDtheta_mocks(0, nthreads, bins, randRA1, randDEC1, - RA2=randRA2, DEC2=randDEC2) - # Convert to the CF - return convert_3d_counts_to_cf(ND1, ND2, NR1, NR2, D1D2, D1R2, D2R1, R1R2) \ No newline at end of file diff --git a/csiborgtools/clustering/__init__.py b/csiborgtools/clustering/__init__.py index 49b32f6..49f68b4 100644 --- a/csiborgtools/clustering/__init__.py +++ b/csiborgtools/clustering/__init__.py @@ -12,5 +12,11 @@ # 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 warnings import warn from .knn import kNN_CDF # noqa from .utils import (RVSinsphere, RVSinbox, RVSonsphere, BaseRVS, normalised_marks) # noqa +try: + import Corrfunc + from .tpcf import Mock2PCF # noqa +except ImportError: + warn("`Corrfunc` not installed. 2PCF modules will not be available (`Mock2PCF`).") # noqa diff --git a/csiborgtools/clustering/tpcf.py b/csiborgtools/clustering/tpcf.py new file mode 100644 index 0000000..8f4f3c6 --- /dev/null +++ b/csiborgtools/clustering/tpcf.py @@ -0,0 +1,68 @@ +# Copyright (C) 2023 Richard Stiskalek +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# 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. +"""2PCF calculation.""" +import numpy +from Corrfunc.theory.DD import DD +from Corrfunc.utils import convert_3d_counts_to_cf +from .utils import BaseRVS + + +class Mock2PCF: + """ + Tool to calculate the 2PCF of a catalogue. + """ + def __call__(self, pos, rvs_gen, nrandom, bins, random_state=42): + """ + Calculate the 2PCF from 3D pair counts. + + Parameters + ---------- + pos : 2-dimensional array of shape `(ndata, 3)` + Positions of the data. + rvs_gen : :py:class:`csiborgtools.clustering.BaseRVS` + Uniform RVS generator. + nrandom : int + Number of random points to generate. + bins : 1-dimensional array of shape `(nbins,)` + Separation bins. + random_state : int, optional + Random state for the RVS generator. + + Returns + ------- + rp : 1-dimensional array of shape `(nbins - 1,)` + Projected separation where the auto-2PCF is evaluated. + xi : 1-dimensional array of shape `(nbins - 1,)` + The auto-2PCF. + """ + assert isinstance(rvs_gen, BaseRVS) + pos = pos.astype(numpy.float64) + rand_pos = rvs_gen(nrandom, random_state=random_state, + dtype=numpy.float64) + + dd = DD(autocorr=1, nthreads=1, binfile=bins, + X1=pos[:, 0], Y1=pos[:, 1], Z1=pos[:, 2], periodic=False) + dr = DD(autocorr=0, nthreads=1, binfile=bins, + X1=pos[:, 0], Y1=pos[:, 1], Z1=pos[:, 2], + X2=rand_pos[:, 0], Y2=rand_pos[:, 1], Z2=rand_pos[:, 2], + periodic=False) + rr = DD(autocorr=1, nthreads=1, binfile=bins, + X1=rand_pos[:, 0], Y1=rand_pos[:, 1], Z1=rand_pos[:, 2], + periodic=False) + + ndata = pos.shape[0] + xi = convert_3d_counts_to_cf(ndata, ndata, nrandom, nrandom, dd, dr, dr, rr) + rp = 0.5 * (bins[1:] + bins[:-1]) + return rp, xi diff --git a/csiborgtools/read/__init__.py b/csiborgtools/read/__init__.py index bb583ef..77b104a 100644 --- a/csiborgtools/read/__init__.py +++ b/csiborgtools/read/__init__.py @@ -21,3 +21,4 @@ from .outsim import (dump_split, combine_splits) # noqa from .overlap_summary import (PairOverlap, NPairsOverlap, binned_resample_mean) # noqa from .knn_summary import kNNCDFReader # noqa from .pk_summary import PKReader # noqa +from .tpcf_summary import TPCFReader # noqa diff --git a/csiborgtools/read/tpcf_summary.py b/csiborgtools/read/tpcf_summary.py new file mode 100644 index 0000000..7e3d625 --- /dev/null +++ b/csiborgtools/read/tpcf_summary.py @@ -0,0 +1,76 @@ +# Copyright (C) 2023 Richard Stiskalek +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# 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. +"""2PCF reader.""" +from os.path import join +from glob import glob +import numpy +import joblib + + +class TPCFReader: + """ + Shortcut object to read in the 2PCF data. + """ + def read(self, run, folder): + """ + Read the auto- or cross-correlation kNN-CDF data. Infers the type from + the data files. + + Parameters + ---------- + run : str + Run ID to read in. + folder : str + Path to the folder where the auto-2PCF is stored. + + Returns + ------- + rp : 1-dimensional array of shape `(neval, )` + Projected separations where the 2PCF is evaluated. + out : 2-dimensional array of shape `(len(files), len(rp))` + Array of 2PCFs. + """ + run += ".p" + files = [f for f in glob(join(folder, "*")) if run in f] + if len(files) == 0: + raise RuntimeError("No files found for run `{}`.".format(run[:-2])) + + for i, file in enumerate(files): + data = joblib.load(file) + if i == 0: # Initialise the array + rp = data["rp"] + out = numpy.full((len(files), rp.size), numpy.nan, + dtype=numpy.float32) + out[i, ...] = data["wp"] + + return rp, out + + def mean_wp(self, wp): + r""" + Calculate the mean 2PCF and its standard deviation averaged over the + IC realisations. + + Parameters + ---------- + wp : 2-dimensional array of shape `(len(files), len(rp))` + Array of CDFs + Returns + ------- + out : 2-dimensional array of shape `(len(rp), 2)` + Mean 2PCF and its standard deviation, stored along the last + dimension, respectively. + """ + return numpy.stack([numpy.mean(wp, axis=0), numpy.std(wp, axis=0)], + axis=-1) diff --git a/notebooks/knn.ipynb b/notebooks/knn.ipynb index 7dd7ec5..178c36d 100644 --- a/notebooks/knn.ipynb +++ b/notebooks/knn.ipynb @@ -6,51 +6,138 @@ "id": "5a38ed25", "metadata": { "ExecuteTime": { - "end_time": "2023-04-09T17:12:51.060443Z", - "start_time": "2023-04-09T17:12:47.288759Z" + "end_time": "2023-04-12T14:25:46.519408Z", + "start_time": "2023-04-12T14:25:03.003304Z" }, "scrolled": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "not found\n" - ] - } - ], + "outputs": [], "source": [ - "import numpy as np\n", - "import matplotlib\n", - "import matplotlib.pyplot as plt\n", - "from sklearn.neighbors import NearestNeighbors\n", + "import sys\n", "import joblib\n", "from glob import glob\n", "from tqdm import tqdm\n", - "try:\n", - " import csiborgtools\n", - "except ModuleNotFoundError:\n", - " print(\"not found\")\n", - " import sys\n", - " sys.path.append(\"../\")\n", - " import csiborgtools\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.neighbors import NearestNeighbors\n", "import yaml\n", + "import scienceplots\n", "\n", + "sys.path.append(\"../\")\n", + "import csiborgtools\n", "\n", - "%matplotlib notebook\n", + "plt.style.use([\"science\", \"notebook\"])\n", + "%matplotlib widget \n", "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 2, + "id": "68a45ea8", + "metadata": { + "ExecuteTime": { + "end_time": "2023-04-12T14:25:46.554959Z", + "start_time": "2023-04-12T14:25:46.521474Z" + } + }, + "outputs": [], + "source": [ + "folder = \"/mnt/extraspace/rstiskalek/csiborg/tpcf/auto/\"\n", + "reader = csiborgtools.read.TPCFReader()" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "430044b3", + "metadata": { + "ExecuteTime": { + "end_time": "2023-04-09T22:38:52.737953Z", + "start_time": "2023-04-09T22:38:51.453058Z" + } + }, + "outputs": [], + "source": [ + "rp, wp = reader.read(\"mass002_spinlow\", folder)\n", + "wp = reader.mean_wp(wp)\n", + "\n", + "rp2, wp2 = reader.read(\"mass002_spinhigh\", folder)\n", + "wp2 = reader.mean_wp(wp2)\n", + "\n", + "rp3, wp3 = reader.read(\"mass002_spinmedian_perm\", folder)\n", + "wp3 = reader.mean_wp(wp3)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "9a07acc5", + "metadata": { + "ExecuteTime": { + "end_time": "2023-04-09T22:40:07.043102Z", + "start_time": "2023-04-09T22:40:06.448027Z" + } + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d33ac43bd06947f69731ba806ecd1e51", + "version_major": 2, + "version_minor": 0 + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAwwAAAJECAYAAAC7A6POAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy89olMNAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdd3hUZfbA8e+dmkx6L/RO6CQC0gQFFRv2HoF1C6trXV1XXV3RLe7q2taKroqIZcXfYkWlCAhigdAhdEJJQnqdXu7vjyFDQmZSJgkJyfk8D48zc9uZCYZ75n3PexRVVVWEEEIIIYQQwg9NewcghBBCCCGE6LgkYRBCCCGEEEIEJAmDEEIIIYQQIiBdewfQFoqLi/nmm2/o3bs3oaGh7R2OEEIIIYQQHZ7VaiUnJ4cLL7yQ+Ph43+udMmH45ptvyMzMbO8whBBCCCGEOOMsWrSIm2++2fe8UyYMvXv3BrxvNi0trcnHZWdnk5mZ2ezjWqKtr9kW52/Nc7b0XO3xMxMt15V/bmfqe+9Iccvv6tN/Tvld3fV09Z/Zmfr+W+v/1Zp76RqdMmGomYaUlpZGenp6s48P9riWaOtrtsX5W/OcLT1Xe/zMRMt15Z/bmfreO1Lc8rv69J9Tfld3PV39Z3amvv+Wxn3qlH4pehZCCCGEEEIEJAlDLSkpKTz22GOkpKR0mmu2xflb85zt8ZmL9teVf+5n6nvvSHHL7+rTf86O9PMXp0dX/5mfqe+/reJWOmKn5zlz5vDOO+80uI/VaiUkJMTvtk2bNpGRkUFWVtYZOYwkmk5+1kII0fHJ72ohzgyB/l/t0DUMEydOpH///n63abXa0xyNEEIIIYQQXU+HThh+9atfMWfOnPYOQwghhBBCiC5LahjEGe1MnWMohBBdifyuFuLM1qFHGIRoTEpKCvPmzWvvMIQQQjRAflcLcWbr0AnDqlWr2L59O1VVVcTFxTF27FguvvhijEZje4cmhBBCCCFEl9ChE4aFCxfWey0lJYW33nqLGTNmtENEQgghhBBCdC0dMmEYOXIkL7zwAtOmTaNnz55YrVa2bt3KvHnzWL9+PTNnzmTZsmVMnTq1wfNkZ2cH3JaSkiJzKYUQQgghRJeSn59Pfn6+322B7p07ZB+GQFRV5corr+TTTz9l5MiRbNmyxe9+NWvINuSxxx6T+ZRCCCGEEKJLmTdvHo8//niD+5zah+GMShgAtm7dyqhRowA4cuQIPXr0qLdPTcKwaNEi0tLS/J5HRhiEEEIIIURX09gIQ2Zm5pnVuM2f2gnAsWPH/CYMtfeVjpJCCCGEEEJ4BfOl+RnXh6GkpMT3OCIioh0jEUIIIYQQovM74xKGDz/8EIDIyEgGDRrUztEIIYQQQgjRuXW4hGHLli189tlnuFyuOq97PB7efPNNHn74YQDuuusu9Hp9e4QohBBCCCFEl9HhahhycnK48soriYmJIT09naSkJMrLy9mxYwdHjhwB4MYbb+Sxxx5r50iFEEIIIYTo/DrcCMPIkSO55557GDp0KLt37+Z///sfK1euBOCaa67hyy+/5P3330en63C5jhBCCCGaqHfv3iiKUu9PeHg4I0eO5KGHHqpTt9gaaq4h2sa8efNQFKXesvULFixAURTmzJnTLnF1JIE+o46uw9119+nTh+eee669wxBCCCHEaTBx4kT69+8PeKcf5+XlsX79ev7xj3+wcOFC1q5dS9++fds5SiG6tg6XMAghhBCi6/jVr35V75vn48ePM2XKFPbu3csDDzzAxx9/3D7BiVZx5ZVXcvbZZxMVFdXeobS7O+64gxtuuIH4+Pj2DqVZOtyUJCFE17azKoefyrM5w3pKCiFaUXJyMn/4wx8AfNOSxZkrKiqKwYMHS8NcID4+nsGDB0vCIIQQwXJ6XGytPshPFbs5YM1r73CEEO0oOTkZoN6qibV9/PHHzJgxg4SEBAwGA926dSMzM5Ndu3Y1+3qlpaU8/PDDDB06FJPJREREBBkZGTz11FNYrdY6+27btg1FURgxYkS98zz11FO+WolT4zhy5AiKotCzZ88mx1VT65GTk8NXX33F1KlTiYqKIiYmhksvvZTt27f79n3//fcZP348ERERREdHc9VVV3HgwIGA587Ly+P3v/89aWlpvvc8ZswYXnrppYCfu9VqZd68eQwYMACj0UhKSgqzZ8/2LUzjT0M1DP/73//41a9+xbBhw4iJiSEkJIQ+ffpw6623smfPHr/nmzNnDoqisGDBAg4dOsQtt9xCcnIyRqORfv368cgjj2C32wPGE8jixYuZPn06cXFx6PV64uLiGDJkCL/+9a/Ztm1bnX2nTp2KoiisXr2aNWvWcMEFFxAbG4vJZGLs2LG8++67fq/RlDoPs9nMQw89RP/+/TEajSQnJzN79mxyc3Ob/Z5aiyQMQogOI9deTKGjDIDvy3ZR5qxq54iEEO3l559/BmDo0KH1trlcLq6//nquvfZaVq9ezcCBA7niiitISEjgvffe46yzzuLrr79u8rUOHjxIeno6Tz75JEVFRVx88cWcd9557Nu3jz/+8Y9MmjSJsrIy3/7Dhw8nMTGRHTt2UFhYWOdcK1as8Pu49vPp06c3ObYa8+fP55JLLsHlcjFjxgwSExP58ssvOeecczhw4AAPPPAAs2fPxmQyMWPGDCIjI1myZAnnnHNOndhrfPfddwwbNoznnnsOm83G+eefz8SJEzlw4AB33nknl1xyCU6ns84xFouF8847j8cff5z8/HwuuOACJk+ezDfffEN6ejqHDh1q9vu67rrr+OCDDwgNDeW8887jwgsvRKPR8Pbbb5ORkcH69esDHrtlyxZGjRrF2rVrmTJlCueccw75+fn87W9/44YbbmhWHE888QTXXXcda9asYdiwYVx77bWcffbZaLVa3nzzTb799lu/xy1ZsoTzzjuP3NxcLrzwQsaMGUNWVhazZs3ivvvua1YMABUVFUyYMIHXXnuNIUOGcNFFF6GqKgsXLmTixIlUVFQ0+5ytQu2EsrKyVEDNyspq71CEEM2woniT+syhj9VPjq9Tnz70kfpl4U+q0+1q77CEEG2gV69eKqC+/fbbvtfcbrd67Ngx9cUXX1SNRqOq1WrVzz//vN6xDz/8sAqo48aNUw8ePFhn2+LFi1WtVqvGxMSoZWVldbYBqr9bn3HjxqmAOnPmTLW6utr3emFhoZqenq4C6k033VTnmBtvvFEF1Pfee8/3ms1mU0NDQ9WhQ4eqGo1Gveyyyxo9pjE1n5PRaFRXrFjhe93lcqnXXnutCqjDhg1T4+Li1C1btvi2m81mdcKECSqg/vWvf61zzvz8fDUuLk5VFEV95ZVXVLfb7dtWXFysnnfeeSqgPv7443WOu//++1VAHTx4sJqbm1vnWpdffrnv833sscfqHPf222+rgDp79ux67+/DDz+s85mrqqp6PB715ZdfVgF16NChqsfjqbN99uzZvmv96U9/Ul2uk/9ObN++XQ0LC1MBdf369QE+1bpqfm7h4eHq7t27623PyclRs7Oz67w2ZcoUXwx///vf62xbvXq1GhoaqgLq119/XWfbY4891uBnBKgXXnihWlFR4dtWWlqqjho1yu+1Wluge2gpehZCdAiVLjMHLfnE6yPQKBp6hySyq/oISYZoMqIGtnd4QrSac/78NQUV1sZ37ICSokL57okZrXrOX/ziF/ziF7+o9/qYMWN47rnnmDhxYp3XS0tLee655wgJCeH//u//6NatW53t11xzDXPnzuWVV15h0aJF3HHHHQ1ef926dfz000+YTCZef/11wsLCfNsSEhJ4/fXXOeuss/jwww/55z//Sffu3QHvKMEHH3zA8uXLuemmmwD4/vvvsVqtXHPNNSxdupTVq1fjcrnQ6XSoqsq3336LoihMmzat2Z/TXXfdVec4rVbLQw89xOLFi9mxYwcvv/wyI0eO9G03mUzcd999rF+/npUrV/KnP/3Jt+3555+npKSEO+64g9tuu63OdeLi4li4cCF9+vThpZde4tFHH0VRFKxWK/PnzwfgueeeIzU1tc61XnvtNb755htsNluz3tf1119f7zVFUbj99ttZtGgRP/zwA9nZ2QwZMqTefhkZGfzlL3+ps1TusGHDuOWWW3jttddYsWIF48ePbzSGyspKrFYrI0aMYNCgQfW29+rVK+Cxo0eP5qGHHqrz2pQpU7j99tt55plneOaZZ7jwwgsbjaFGWFgYb7/9NpGRkb7XYmJiePDBB7nhhhtYsWJFveudDpIwCCE6hCPWQspd1Qw0ef/xN2oMxOsj+LlyD0nGGLqHJLRzhEK0joIKK3llZ2bC0BZqL6sKUFxczLZt29iwYQP33nsv7733HgMGDPBtX7VqFVarlWnTptVLFmpMnTqVV155hfXr1zeaMKxevRqAGTNmkJSUVG97RkYGI0eOZOvWraxZs4abb74ZODmtqHZRds2Uo/PPPx+Hw8GGDRv46aefmDhxItu3b6egoIDhw4f7vU5jLr744nqv1f5cGtqel1e3JuzLL78E/N+sA3Tr1o0BAwawa9cu9u3bx8CBA9m0aRNVVVXEx8czY0b9pDE5OZkLLriAzz77rOlv6oT9+/fz9ddfs3//fqqqqnC73QAUFBQAsGfPHr8Jw6WXXuq3r0ZaWhpAk+f8JyQk0Lt3b7Zt28Z9993HL3/5S7/X82fWrFl+X589ezbPPPMM69atw+12o9Vqm3S+s846y29xeHPfU2uThEEI0e7cqpts81HCtCFolJOlVXGGSA5aj7O+fCeXxI8jTBfajlEK0TqSos7cv8dtEbu/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+P32NpJwKkJgaIonHfeeYB3lZuxY8c29WNpc+eccw47d+7k0UcfpXv37mzYsIHFixezZcsWkpKSeOyxx3jjjTfqHBMWFsaqVat49NFHSUpK4ptvvuG7775j2rRpbNy4sdmrJI0bN46NGzcyc+ZMzGYzn332ma/T9A8//OD3G/220K9fP55//nkuvfRSysvLWbp0KV9++SVms5lZs2axYcMGfvnLX/o99sorr2T58uUkJyezdOlSfv75Z9LT01mwYAHPP//8aYn/dFDU5pRunyE2bdpERkYGWVlZMsIgRAe2oXwPa8q2MiisR+M713LYWkC0PoKZiWcTqWv/+cBCCCG6lqlTp7JmzRpWrVrlq4PpDALdQ8sIgxCiXdg9DnZbjhClC29851P0CEkg317CD+XZuFV3G0QnhBBCiBqSMAgh2sUxWzFFjkriGil29kejaOgVksjO6hx2Vtdf5k4IIYQQrUcSBiFEu9hvzkOjKOg1wa29EKo1Eq0L44fybPLtJa0cnRBCCCFqSMIghDjtSp2V5NgKiNe3rKAtwRCN1WPn+7KdWN32VopOCCGEaNjq1atRVbVT1S80RBIGIcRpd9RWRKXLTKTW1OJz9QpJ5JD1OBsq9tIJ13AQQggh2p0kDEKI08rlcbOr+ggR2lAURWnx+XSKlm7GODZX7WefJbcVIhRCCCFEbZIwCCFOqzx7CQWOMuINTeu90BQROhMGRccP5bsoddbv1CmEEEKI4EnCIIQ4rQ5a83GrHowafauet5sxjiJHBevLd+H0uFr13EIIIURXJgmDEOK0qXJZ2G/Ja3Gxsz+KotA7NIk95qNsrTrY6ucXQgghuipJGIQQp80RWyHlzmqi26g7s1GjJ04fyYbK3RyxFrbJNYQQQoiuRhIGIcRp4VE97Kk+RqjGgEZpu189cfpIXB4P35fvpNplbbPrCCGEEF2FJAxCiNOiwFFGrr24VYudA+kRksAxexE/VezGo3ra/HpCCCFEZyYJgxDitMixFmBXnZi0xja/llbR0MOYwLaqg2Sbj7T59YQQQojOTNfeAbSl7Oxs3+OUlBRSUlLaMRohui6r284e81FideGn7Zph2hDCtSH8UJ5Ngj6KRGPMabu2EEIIcabIz88nPz8fqHvvXFunHmHIzMwkIyODjIwM5s+f397hCNFlHbUVUeKsIlYfcVqvm2SIodJlZn35Luwex2m9thCieUaOHImiKBiNRkpKShrcd+rUqSiKwurVq09PcKLZAv2M5syZg6IoLFiwoF3i6kg6yt/j+fPn++6XMzMz/e7TqROGRYsWkZWVRVZWFnPnzm3vcIToklRVZZ8lFx0atIr2tF5bURR6hySxz5LLxoq9qKp6Wq8vhGiaDRs2sG3bNgAcDgeLFi1q54iE6Drmzp3ru18O9P9ep56SlJaWRnp6enuHIUSXVuys4IitgITTUOzsj16jI8UYy6bK/aQY4+hrkqmJQnQ0b775JgDdunUjNzeXN998k7vvvrudoxJt4cknn+TBBx+UaeLAwoULsVgs9OzZs13jaMq0/U49wiCEaH9HrIVUu21E6EztFkOULgyNorC+fCcVTnO7xSGEqM9isfDBBx8A8O677xIeHs727dvZsGFDO0cm2kJKSgqDBw8mKqp9vkTqSHr27MngwYMxmdrv38emkoRBCNFmHB4n2eajRGnbplFbc3Q3xnPcXsYP5btwedztHY4Q4oTFixdTWVnJsGHDOPfcc7n++uuBk6MOjVmzZg0XXHABsbGxmEwmxo4dy7vvvhtwf5fLxWuvvcaECROIiooiJCSEAQMGcNddd5Gbm1tn3927d6MoCjExMdhstoDnPOuss1AUhU8//bTetf7zn/8wdepUYmNjMRqN9OnTh9tuu42jR4826f3VyMnJ8U6z7N0bj8fDv//9b0aMGIHJZCIlJYXf/va3lJaWAmC32/nLX/7C4MGDCQ0NJTU1lbvvvhuzOfAXJllZWdx888307NkTo9FIbGwsF154IUuXLg14zNGjR7n11ltJSUnxfY5/+tOfsFoD98AJVMNQVVXFG2+8wVVXXcWAAQMICwsjLCyM4cOH86c//Yny8nK/5+vduzeKopCTk8OqVau44IILiImJITQ0lPT0dBYuXBj4Qw3Abrfz9NNPk5GRQUREBAaDgeTkZMaMGcMDDzzg+5xrKIqCoigAvPHGG2RkZBAWFkZ0dDQXX3wxP/74o9/rNKXO49ChQ9xyyy0kJydjNBrp168fjzzyCHa7vdnvqyUkYRBCtJlcWzGFjnLi9ZHtHQoaRUOvkER2mHPYUX2ovcMRQpxQkxjceuutdf774YcfNnjjCbBkyRLOO+88cnNzufDCCxkzZgxZWVnMmjWL++67r97+drudiy66iNtuu43NmzczceJErrjiCux2Oy+++CKjRo1i06ZNvv0HDx7M+PHjKS8v55NPPvEbw/bt28nKyiIpKYlLLrnE93pVVRXnn38+v/71r8nKymLEiBHMnDkTo9HIa6+9xujRo9m8eXOzPqsamZmZPPjgg3Tr1o0LL7wQj8fD/PnzmT59OmazmenTp/Ovf/2LQYMGMX36dCwWC//+97+59tpr/Z7vhRdeYOzYsbz//vvExcUxc+ZMhg4dyurVq7nkkkt44okn6h2ze/duzjrrLN5++20URWHmzJkMHDiQ5557jmnTpuFwNG+hia1bt/Kb3/yGdevWkZyczGWXXcakSZPIz8/n73//O2PGjGmwGP6tt95i2rRplJaWMmPGDEaNGsXmzZuZPXs2zz//fJPj8Hg8XHLJJTzwwAPs37+fyZMnc8011zB8+HCKiop4+umnOXLE/3Ldv//975k7dy4mk4nLL7+cHj168NVXXzF58mSWLFnSrM8DYMuWLYwaNYq1a9cyZcoUzjnnHPLz8/nb3/7GDTfc0OzztYjaCWVlZamAmpWV1d6hCNGlLSveqD576GP1s4L1HebPm0e/Ul878oWaay1u749HiC5vz549KqDq9Xq1sLDQ9/rgwYNVQF24cKHf46ZMmaICKqD+/e9/r7Nt9erVamhoqAqoX3/9dZ1tf/zjH1VA7devn3ro0CHf6w6HQ/3lL3+pAmqfPn1Uu93u2/bGG2+ogHrhhRf6jeXee+9VAfW+++6r8/pNN92kAuqll16qFhQU1Nn23HPPqYA6YMAA1eVyBf6Aajl06JDvPffr10/NycnxbSsuLlYHDBigAurw4cPVsWPHqsXFJ3/HHTx4UI2JiVEBdd26dXXO+/XXX6uKoqjx8fHqmjVr6mzbtm2b2r17dxVQV69eXWfbmDFjVEC97rrrVKvV6nv98OHDar9+/Xyxrlq1qs5xs2fPVgH17bffrvP60aNH1RUrVqhut7vO62azWZ01a5YKqLfffnu9z6VXr16+v0Off/55nW1vv/22CqhRUVGqxWKpd6w/a9asUQF19OjRamVlZb3tGzZsqPPZqqrqe6+hoaHqypUr62x76qmnfDGc+veg5u9xoM8IUP/0pz/V+Tuyfft2NSwsTAXU9evXN+k9NUege+hOXfQshGg/5c5qDlmOd4jRhdoSDFEcsOazrnwHlyaMw6QNae+QRBdz1o+/47i9rL3DCEqyMYaNZ7/caud76623AJg5cyYJCQm+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///jd33XVXnWOG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Hnin1W/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/JwoKCoiKiqqXLAAkJiaSmJjo97iUlBSeeeYZ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e7fvdbfbzf33309eXvMaYVosFp599llfnURta9eupby8HK1W63ekIC8vj/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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", + "text/html": [ + "\n", + "
\n", + "
\n", + " Figure\n", + "
\n", + " \n", + "
\n", + " " + ], + "text/plain": [ + "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "cols = plt.rcParams[\"axes.prop_cycle\"].by_key()[\"color\"]\n", + "\n", + "plt.figure()\n", + "# for i in range(4):\n", + "plt.plot(rp, wp[:, 0], c=cols[0], label=\"Below median spin\")\n", + "plt.fill_between(rp, wp[:, 0] - wp[:, 1], wp[:, 0] + wp[:, 1], color=cols[0], alpha=0.3)\n", + "\n", + "plt.plot(rp2, wp2[:, 0], c=cols[1], label=\"Above median spin\")\n", + "plt.fill_between(rp2, wp2[:, 0] - wp2[:, 1], wp2[:, 0] + wp2[:, 1], color=cols[1], alpha=0.3)\n", + "\n", + "plt.plot(rp3, wp3[:, 0], c=cols[2], label=\"Randomised spin\")\n", + "plt.fill_between(rp3, wp3[:, 0] - wp3[:, 1], wp3[:, 0] + wp3[:, 1], color=cols[2], alpha=0.3)\n", + "\n", + "plt.legend()\n", + "plt.xscale(\"log\")\n", + "plt.xlabel(r\"$r~[\\mathrm{Mpc}]$\")\n", + "plt.ylabel(r\"$\\xi(r)$\")\n", + "plt.tight_layout()\n", + "plt.savefig(\"../plots/tpcf_spin.png\", dpi=450)\n", + "plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, "id": "3d39187a", "metadata": { "ExecuteTime": { - "end_time": "2023-04-09T19:51:15.144264Z", - "start_time": "2023-04-09T19:51:14.672337Z" + "end_time": "2023-04-12T14:25:46.878788Z", + "start_time": "2023-04-12T14:25:46.556378Z" } }, "outputs": [], @@ -67,2073 +154,38 @@ }, { "cell_type": "code", - "execution_count": 52, - "id": "202cb57b", - "metadata": { - "ExecuteTime": { - "end_time": "2023-04-09T19:53:58.915750Z", - "start_time": "2023-04-09T19:53:55.595006Z" - } - }, - "outputs": [], - "source": [ - "rs, corr = knnreader.read(\"mass001\", cross_folder, rmin=1, rmax=50)\n", - "rs, corr_rand = knnreader.read(\"mass001_random\", auto_folder, rmin=1, rmax=50)" - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "id": "9b3adce7", - "metadata": { - "ExecuteTime": { - "end_time": "2023-04-09T19:55:25.114871Z", - "start_time": "2023-04-09T19:55:24.983841Z" - } - }, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_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", - "\n", - "mpl.figure.prototype._init_header = function () {\n", - " var titlebar = document.createElement('div');\n", - " titlebar.classList =\n", - " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", - " var titletext = document.createElement('div');\n", - " titletext.classList = 'ui-dialog-title';\n", - " titletext.setAttribute(\n", - " 'style',\n", - " 'width: 100%; text-align: center; padding: 3px;'\n", - " );\n", - " titlebar.appendChild(titletext);\n", - " this.root.appendChild(titlebar);\n", - " this.header = titletext;\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._init_canvas = function () {\n", - " var fig = this;\n", - "\n", - " var canvas_div = (this.canvas_div = document.createElement('div'));\n", - " canvas_div.setAttribute(\n", - " 'style',\n", - " 'border: 1px solid #ddd;' +\n", - " 'box-sizing: content-box;' +\n", - " 'clear: both;' +\n", - " 'min-height: 1px;' +\n", - " 'min-width: 1px;' +\n", - " 'outline: 0;' +\n", - " 'overflow: hidden;' +\n", - " 'position: relative;' +\n", - " 'resize: both;'\n", - " );\n", - "\n", - " function on_keyboard_event_closure(name) {\n", - " return function (event) {\n", - " return fig.key_event(event, name);\n", - " };\n", - " }\n", - "\n", - " canvas_div.addEventListener(\n", - " 'keydown',\n", - " on_keyboard_event_closure('key_press')\n", - " );\n", - " canvas_div.addEventListener(\n", - " 'keyup',\n", - " on_keyboard_event_closure('key_release')\n", - " );\n", - "\n", - " this._canvas_extra_style(canvas_div);\n", - " this.root.appendChild(canvas_div);\n", - "\n", - " var canvas = (this.canvas = document.createElement('canvas'));\n", - " canvas.classList.add('mpl-canvas');\n", - " canvas.setAttribute('style', 'box-sizing: content-box;');\n", - "\n", - " this.context = canvas.getContext('2d');\n", - "\n", - " var backingStore =\n", - " this.context.backingStorePixelRatio ||\n", - " this.context.webkitBackingStorePixelRatio ||\n", - " this.context.mozBackingStorePixelRatio ||\n", - " this.context.msBackingStorePixelRatio ||\n", - " this.context.oBackingStorePixelRatio ||\n", - " this.context.backingStorePixelRatio ||\n", - " 1;\n", - "\n", - " this.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", - " 'canvas'\n", - " ));\n", - " rubberband_canvas.setAttribute(\n", - " 'style',\n", - " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", - " );\n", - "\n", - " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n", - " if (this.ResizeObserver === undefined) {\n", - " if (window.ResizeObserver !== undefined) {\n", - " this.ResizeObserver = window.ResizeObserver;\n", - " } else {\n", - " var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n", - " this.ResizeObserver = obs.ResizeObserver;\n", - " }\n", - " }\n", - "\n", - " this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n", - " var nentries = entries.length;\n", - " for (var i = 0; i < nentries; i++) {\n", - " var entry = entries[i];\n", - " var width, height;\n", - " if (entry.contentBoxSize) {\n", - " if (entry.contentBoxSize instanceof Array) {\n", - " // Chrome 84 implements new version of spec.\n", - " width = entry.contentBoxSize[0].inlineSize;\n", - " height = entry.contentBoxSize[0].blockSize;\n", - " } else {\n", - " // Firefox implements old version of spec.\n", - " width = entry.contentBoxSize.inlineSize;\n", - " height = entry.contentBoxSize.blockSize;\n", - " }\n", - " } else {\n", - " // Chrome <84 implements even older version of spec.\n", - " width = entry.contentRect.width;\n", - " height = entry.contentRect.height;\n", - " }\n", - "\n", - " // Keep the size of the canvas and rubber band canvas in sync with\n", - " // the canvas container.\n", - " if (entry.devicePixelContentBoxSize) {\n", - " // Chrome 84 implements new version of spec.\n", - " canvas.setAttribute(\n", - " 'width',\n", - " entry.devicePixelContentBoxSize[0].inlineSize\n", - " );\n", - " canvas.setAttribute(\n", - " 'height',\n", - " entry.devicePixelContentBoxSize[0].blockSize\n", - " );\n", - " } else {\n", - " canvas.setAttribute('width', width * fig.ratio);\n", - " canvas.setAttribute('height', height * fig.ratio);\n", - " }\n", - " canvas.setAttribute(\n", - " 'style',\n", - " 'width: ' + width + 'px; height: ' + height + 'px;'\n", - " );\n", - "\n", - " rubberband_canvas.setAttribute('width', width);\n", - " rubberband_canvas.setAttribute('height', height);\n", - "\n", - " // And update the size in Python. We ignore the initial 0/0 size\n", - " // that occurs as the element is placed into the DOM, which should\n", - " // otherwise not happen due to the minimum size styling.\n", - " if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n", - " fig.request_resize(width, height);\n", - " }\n", - " }\n", - " });\n", - " this.resizeObserverInstance.observe(canvas_div);\n", - "\n", - " function on_mouse_event_closure(name) {\n", - " return function (event) {\n", - " return fig.mouse_event(event, name);\n", - " };\n", - " }\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mousedown',\n", - " on_mouse_event_closure('button_press')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseup',\n", - " on_mouse_event_closure('button_release')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\n", - " );\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband_canvas.addEventListener(\n", - " 'mousemove',\n", - " on_mouse_event_closure('motion_notify')\n", - " );\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseenter',\n", - " on_mouse_event_closure('figure_enter')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseleave',\n", - " on_mouse_event_closure('figure_leave')\n", - " );\n", - "\n", - " canvas_div.addEventListener('wheel', function (event) {\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " on_mouse_event_closure('scroll')(event);\n", - " });\n", - "\n", - " canvas_div.appendChild(canvas);\n", - " canvas_div.appendChild(rubberband_canvas);\n", - "\n", - " this.rubberband_context = rubberband_canvas.getContext('2d');\n", - " this.rubberband_context.strokeStyle = '#000000';\n", - "\n", - " this._resize_canvas = function (width, height, forward) {\n", - " if (forward) {\n", - " canvas_div.style.width = width + 'px';\n", - " canvas_div.style.height = height + 'px';\n", - " }\n", - " };\n", - "\n", - " // Disable right mouse context menu.\n", - " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", - " event.preventDefault();\n", - " return false;\n", - " });\n", - "\n", - " function set_focus() {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'mpl-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " continue;\n", - " }\n", - "\n", - " var button = (fig.buttons[name] = document.createElement('button'));\n", - " button.classList = 'mpl-widget';\n", - " button.setAttribute('role', 'button');\n", - " button.setAttribute('aria-disabled', 'false');\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - "\n", - " var icon_img = document.createElement('img');\n", - " icon_img.src = '_images/' + image + '.png';\n", - " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", - " icon_img.alt = tooltip;\n", - " button.appendChild(icon_img);\n", - "\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " var fmt_picker = document.createElement('select');\n", - " fmt_picker.classList = 'mpl-widget';\n", - " toolbar.appendChild(fmt_picker);\n", - " this.format_dropdown = fmt_picker;\n", - "\n", - " for (var ind in mpl.extensions) {\n", - " var fmt = mpl.extensions[ind];\n", - " var option = document.createElement('option');\n", - " option.selected = fmt === mpl.default_extension;\n", - " option.innerHTML = fmt;\n", - " fmt_picker.appendChild(option);\n", - " }\n", - "\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "};\n", - "\n", - "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", - " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", - " // which will in turn request a refresh of the image.\n", - " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", - "};\n", - "\n", - "mpl.figure.prototype.send_message = function (type, properties) {\n", - " properties['type'] = type;\n", - " properties['figure_id'] = this.id;\n", - " this.ws.send(JSON.stringify(properties));\n", - "};\n", - "\n", - "mpl.figure.prototype.send_draw_message = function () {\n", - " if (!this.waiting) {\n", - " this.waiting = true;\n", - " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " var format_dropdown = fig.format_dropdown;\n", - " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", - " fig.ondownload(fig, format);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", - " var size = msg['size'];\n", - " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", - " fig._resize_canvas(size[0], size[1], msg['forward']);\n", - " fig.send_message('refresh', {});\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", - " var x0 = msg['x0'] / fig.ratio;\n", - " var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n", - " var x1 = msg['x1'] / fig.ratio;\n", - " var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n", - " x0 = Math.floor(x0) + 0.5;\n", - " y0 = Math.floor(y0) + 0.5;\n", - " x1 = Math.floor(x1) + 0.5;\n", - " y1 = Math.floor(y1) + 0.5;\n", - " var min_x = Math.min(x0, x1);\n", - " var min_y = Math.min(y0, y1);\n", - " var width = Math.abs(x1 - x0);\n", - " var height = Math.abs(y1 - y0);\n", - "\n", - " fig.rubberband_context.clearRect(\n", - " 0,\n", - " 0,\n", - " fig.canvas.width / fig.ratio,\n", - " fig.canvas.height / fig.ratio\n", - " );\n", - "\n", - " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", - " // Updates the figure title.\n", - " fig.header.textContent = msg['label'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", - " fig.rubberband_canvas.style.cursor = msg['cursor'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_message = function (fig, msg) {\n", - " fig.message.textContent = msg['message'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", - " // Request the server to send over a new figure.\n", - " fig.send_draw_message();\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", - " fig.image_mode = msg['mode'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", - " for (var key in msg) {\n", - " if (!(key in fig.buttons)) {\n", - " continue;\n", - " }\n", - " fig.buttons[key].disabled = !msg[key];\n", - " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", - " if (msg['mode'] === 'PAN') {\n", - " fig.buttons['Pan'].classList.add('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " } else if (msg['mode'] === 'ZOOM') {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.add('active');\n", - " } else {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Called whenever the canvas gets updated.\n", - " this.send_message('ack', {});\n", - "};\n", - "\n", - "// A function to construct a web socket function for onmessage handling.\n", - "// Called in the figure constructor.\n", - "mpl.figure.prototype._make_on_message_function = function (fig) {\n", - " return function socket_on_message(evt) {\n", - " if (evt.data instanceof Blob) {\n", - " var img = evt.data;\n", - " if (img.type !== 'image/png') {\n", - " /* FIXME: We get \"Resource interpreted as Image but\n", - " * transferred with MIME type text/plain:\" errors on\n", - " * Chrome. But how to set the MIME type? It doesn't seem\n", - " * to be part of the websocket stream */\n", - " img.type = 'image/png';\n", - " }\n", - "\n", - " /* Free the memory for the previous frames */\n", - " if (fig.imageObj.src) {\n", - " (window.URL || window.webkitURL).revokeObjectURL(\n", - " fig.imageObj.src\n", - " );\n", - " }\n", - "\n", - " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", - " img\n", - " );\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " } else if (\n", - " typeof evt.data === 'string' &&\n", - " evt.data.slice(0, 21) === 'data:image/png;base64'\n", - " ) {\n", - " fig.imageObj.src = evt.data;\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " }\n", - "\n", - " var msg = JSON.parse(evt.data);\n", - " var msg_type = msg['type'];\n", - "\n", - " // Call the \"handle_{type}\" callback, which takes\n", - " // the figure and JSON message as its only arguments.\n", - " try {\n", - " var callback = fig['handle_' + msg_type];\n", - " } catch (e) {\n", - " console.log(\n", - " \"No handler for the '\" + msg_type + \"' message type: \",\n", - " msg\n", - " );\n", - " return;\n", - " }\n", - "\n", - " if (callback) {\n", - " try {\n", - " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", - " callback(fig, msg);\n", - " } catch (e) {\n", - " console.log(\n", - " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", - " e,\n", - " e.stack,\n", - " msg\n", - " );\n", - " }\n", - " }\n", - " };\n", - "};\n", - "\n", - "// from https://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", - "mpl.findpos = function (e) {\n", - " //this section is from http://www.quirksmode.org/js/events_properties.html\n", - " var targ;\n", - " if (!e) {\n", - " e = window.event;\n", - " }\n", - " if (e.target) {\n", - " targ = e.target;\n", - " } else if (e.srcElement) {\n", - " targ = e.srcElement;\n", - " }\n", - " if (targ.nodeType === 3) {\n", - " // defeat Safari bug\n", - " targ = targ.parentNode;\n", - " }\n", - "\n", - " // pageX,Y are the mouse positions relative to the document\n", - " var boundingRect = targ.getBoundingClientRect();\n", - " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", - " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", - "\n", - " return { x: x, y: y };\n", - "};\n", - "\n", - "/*\n", - " * return a copy of an object with only non-object keys\n", - " * we need this to avoid circular references\n", - " * https://stackoverflow.com/a/24161582/3208463\n", - " */\n", - "function simpleKeys(original) {\n", - " return Object.keys(original).reduce(function (obj, key) {\n", - " if (typeof original[key] !== 'object') {\n", - " obj[key] = original[key];\n", - " }\n", - " return obj;\n", - " }, {});\n", - "}\n", - "\n", - "mpl.figure.prototype.mouse_event = function (event, name) {\n", - " var canvas_pos = mpl.findpos(event);\n", - "\n", - " if (name === 'button_press') {\n", - " this.canvas.focus();\n", - " this.canvas_div.focus();\n", - " }\n", - "\n", - " var x = canvas_pos.x * this.ratio;\n", - " var y = canvas_pos.y * this.ratio;\n", - "\n", - " this.send_message(name, {\n", - " x: x,\n", - " y: y,\n", - " button: event.button,\n", - " step: event.step,\n", - " guiEvent: simpleKeys(event),\n", - " });\n", - "\n", - " /* This prevents the web browser from automatically changing to\n", - " * the text insertion cursor when the button is pressed. We want\n", - " * to control all of the cursor setting manually through the\n", - " * 'cursor' event from matplotlib */\n", - " event.preventDefault();\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", - " // Handle any extra behaviour associated with a key event\n", - "};\n", - "\n", - "mpl.figure.prototype.key_event = function (event, name) {\n", - " // Prevent repeat events\n", - " if (name === 'key_press') {\n", - " if (event.key === this._key) {\n", - " return;\n", - " } else {\n", - " this._key = event.key;\n", - " }\n", - " }\n", - " if (name === 'key_release') {\n", - " this._key = null;\n", - " }\n", - "\n", - " var value = '';\n", - " if (event.ctrlKey && event.key !== 'Control') {\n", - " value += 'ctrl+';\n", - " }\n", - " else if (event.altKey && event.key !== 'Alt') {\n", - " value += 'alt+';\n", - " }\n", - " else if (event.shiftKey && event.key !== 'Shift') {\n", - " value += 'shift+';\n", - " }\n", - "\n", - " value += 'k' + event.key;\n", - "\n", - " this._key_event_extra(event, name);\n", - "\n", - " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", - " if (name === 'download') {\n", - " this.handle_save(this, null);\n", - " } else {\n", - " this.send_message('toolbar_button', { name: name });\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", - " this.message.textContent = tooltip;\n", - "};\n", - "\n", - "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n", - "// prettier-ignore\n", - "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\n", - "\n", - "mpl.default_extension = \"png\";/* global mpl */\n", - "\n", - "var comm_websocket_adapter = function (comm) {\n", - " // Create a \"websocket\"-like object which calls the given IPython comm\n", - " // object with the appropriate methods. Currently this is a non binary\n", - " // socket, so there is still some room for performance tuning.\n", - " var ws = {};\n", - "\n", - " ws.binaryType = comm.kernel.ws.binaryType;\n", - " ws.readyState = comm.kernel.ws.readyState;\n", - " function updateReadyState(_event) {\n", - " if (comm.kernel.ws) {\n", - " ws.readyState = comm.kernel.ws.readyState;\n", - " } else {\n", - " ws.readyState = 3; // Closed state.\n", - " }\n", - " }\n", - " comm.kernel.ws.addEventListener('open', updateReadyState);\n", - " comm.kernel.ws.addEventListener('close', updateReadyState);\n", - " comm.kernel.ws.addEventListener('error', updateReadyState);\n", - "\n", - " ws.close = function () {\n", - " comm.close();\n", - " };\n", - " ws.send = function (m) {\n", - " //console.log('sending', m);\n", - " comm.send(m);\n", - " };\n", - " // Register the callback with on_msg.\n", - " comm.on_msg(function (msg) {\n", - " //console.log('receiving', msg['content']['data'], msg);\n", - " var data = msg['content']['data'];\n", - " if (data['blob'] !== undefined) {\n", - " data = {\n", - " data: new Blob(msg['buffers'], { type: data['blob'] }),\n", - " };\n", - " }\n", - " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", - " ws.onmessage(data);\n", - " });\n", - " return ws;\n", - "};\n", - "\n", - "mpl.mpl_figure_comm = function (comm, msg) {\n", - " // This is the function which gets called when the mpl process\n", - " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", - "\n", - " var id = msg.content.data.id;\n", - " // Get hold of the div created by the display call when the Comm\n", - " // socket was opened in Python.\n", - " var element = document.getElementById(id);\n", - " var ws_proxy = comm_websocket_adapter(comm);\n", - "\n", - " function ondownload(figure, _format) {\n", - " window.open(figure.canvas.toDataURL());\n", - " }\n", - "\n", - " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", - "\n", - " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", - " // web socket which is closed, not our websocket->open comm proxy.\n", - " ws_proxy.onopen();\n", - "\n", - " fig.parent_element = element;\n", - " fig.cell_info = mpl.find_output_cell(\"
\");\n", - " if (!fig.cell_info) {\n", - " console.error('Failed to find cell for figure', id, fig);\n", - " return;\n", - " }\n", - " fig.cell_info[0].output_area.element.on(\n", - " 'cleared',\n", - " { fig: fig },\n", - " fig._remove_fig_handler\n", - " );\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_close = function (fig, msg) {\n", - " var width = fig.canvas.width / fig.ratio;\n", - " fig.cell_info[0].output_area.element.off(\n", - " 'cleared',\n", - " fig._remove_fig_handler\n", - " );\n", - " fig.resizeObserverInstance.unobserve(fig.canvas_div);\n", - "\n", - " // Update the output cell to use the data from the current canvas.\n", - " fig.push_to_output();\n", - " var dataURL = fig.canvas.toDataURL();\n", - " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", - " // the notebook keyboard shortcuts fail.\n", - " IPython.keyboard_manager.enable();\n", - " fig.parent_element.innerHTML =\n", - " '';\n", - " fig.close_ws(fig, msg);\n", - "};\n", - "\n", - "mpl.figure.prototype.close_ws = function (fig, msg) {\n", - " fig.send_message('closing', msg);\n", - " // fig.ws.close()\n", - "};\n", - "\n", - "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", - " // Turn the data on the canvas into data in the output cell.\n", - " var width = this.canvas.width / this.ratio;\n", - " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] =\n", - " '';\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Tell IPython that the notebook contents must change.\n", - " IPython.notebook.set_dirty(true);\n", - " this.send_message('ack', {});\n", - " var fig = this;\n", - " // Wait a second, then push the new image to the DOM so\n", - " // that it is saved nicely (might be nice to debounce this).\n", - " setTimeout(function () {\n", - " fig.push_to_output();\n", - " }, 1000);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'btn-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " var button;\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " continue;\n", - " }\n", - "\n", - " button = fig.buttons[name] = document.createElement('button');\n", - " button.classList = 'btn btn-default';\n", - " button.href = '#';\n", - " button.title = name;\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message pull-right';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = document.createElement('div');\n", - " buttongrp.classList = 'btn-group inline pull-right';\n", - " button = document.createElement('button');\n", - " button.classList = 'btn btn-mini btn-primary';\n", - " button.href = '#';\n", - " button.title = 'Stop Interaction';\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', function (_evt) {\n", - " fig.handle_close(fig, {});\n", - " });\n", - " button.addEventListener(\n", - " 'mouseover',\n", - " on_mouseover_closure('Stop Interaction')\n", - " );\n", - " buttongrp.appendChild(button);\n", - " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", - " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", - "};\n", - "\n", - "mpl.figure.prototype._remove_fig_handler = function (event) {\n", - " var fig = event.data.fig;\n", - " if (event.target !== this) {\n", - " // Ignore bubbled events from children.\n", - " return;\n", - " }\n", - " fig.close_ws(fig, {});\n", - "};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (el) {\n", - " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (el) {\n", - " // this is important to make the div 'focusable\n", - " el.setAttribute('tabindex', 0);\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " } else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which === 13) {\n", - " this.canvas_div.blur();\n", - " // select the cell after this one\n", - " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", - " IPython.notebook.select(index + 1);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " fig.ondownload(fig, null);\n", - "};\n", - "\n", - "mpl.find_output_cell = function (html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i = 0; i < ncells; i++) {\n", - " var cell = cells[i];\n", - " if (cell.cell_type === 'code') {\n", - " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", - " var data = cell.output_area.outputs[j];\n", - " if (data.data) {\n", - " // IPython >= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] === html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "};\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel !== null) {\n", - " IPython.notebook.kernel.comm_manager.register_target(\n", - " 'matplotlib',\n", - " mpl.mpl_figure_comm\n", - " );\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "cols = plt.rcParams[\"axes.prop_cycle\"].by_key()[\"color\"]\n", - "plt.figure()\n", - "for k in range(64):\n", - " plt.plot(rs, corr[0, k, :], c=cols[0], lw=0.5)\n", - "# plt.plot(rs, np.abs(corr_rand[0, k, :]), c=cols[1], lw=0.5)\n", - "\n", - "plt.xscale(\"log\")\n", - "plt.axvline(2.65 / 0.705, c=\"red\", ls=\"--\")\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0ec93a98", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "952cc374", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e38b7cf9", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 57, + "execution_count": 37, "id": "d46e176f", "metadata": { "ExecuteTime": { - "end_time": "2023-04-09T16:12:21.080837Z", - "start_time": "2023-04-09T16:12:19.137559Z" + "end_time": "2023-04-12T14:51:22.432093Z", + "start_time": "2023-04-12T14:49:45.843753Z" } }, - "outputs": [ - { - "ename": "RuntimeError", - "evalue": "No files found for run `mass001_spinloww`.", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn [57], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m rs, cdf \u001b[38;5;241m=\u001b[39m knnreader\u001b[38;5;241m.\u001b[39mread_auto(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmass001_spinloww\u001b[39m\u001b[38;5;124m\"\u001b[39m, folder, rmin\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m, rmax\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m50\u001b[39m)\n\u001b[1;32m 2\u001b[0m pk \u001b[38;5;241m=\u001b[39m knnreader\u001b[38;5;241m.\u001b[39mmean_prob_k(cdf)\n", - "File \u001b[0;32m~/csiborgtools/csiborgtools/read/summaries.py:215\u001b[0m, in \u001b[0;36mkNNCDFReader.read_auto\u001b[0;34m(self, run, folder, rmin, rmax, to_clip)\u001b[0m\n\u001b[1;32m 213\u001b[0m files \u001b[38;5;241m=\u001b[39m [f \u001b[38;5;28;01mfor\u001b[39;00m f \u001b[38;5;129;01min\u001b[39;00m glob(join(folder, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m*\u001b[39m\u001b[38;5;124m\"\u001b[39m)) \u001b[38;5;28;01mif\u001b[39;00m run \u001b[38;5;129;01min\u001b[39;00m f]\n\u001b[1;32m 214\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(files) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[0;32m--> 215\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNo files found for run `\u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m`.\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mformat(run[:\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m2\u001b[39m]))\n\u001b[1;32m 216\u001b[0m kind \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcorr\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcross\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01min\u001b[39;00m run \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcdf\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 218\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i, file \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28menumerate\u001b[39m(files):\n", - "\u001b[0;31mRuntimeError\u001b[0m: No files found for run `mass001_spinloww`." - ] - } - ], + "outputs": [], "source": [ - "rs, cdf = knnreader.read_auto(\"mass001_spinloww\", folder, rmin=1, rmax=50)\n", + "rs, cdf = knnreader.read(\"mass001_spinlow\", auto_folder, rmin=0.5, rmax=50)\n", "pk = knnreader.mean_prob_k(cdf)\n", "\n", "\n", - "# rs, cdf = knnreader.read_auto(\"mass001_spinhigh\", folder, rmin=1, rmax=50)\n", - "# pk_perm = knnreader.mean_prob_k(cdf)" + "rs, cdf = knnreader.read(\"mass001_spinhigh\", auto_folder, rmin=0.5, rmax=50)\n", + "pk2 = knnreader.mean_prob_k(cdf)" ] }, { "cell_type": "code", - "execution_count": 48, - "id": "ad36cab2", - "metadata": { - "ExecuteTime": { - "end_time": "2023-04-09T16:09:55.420866Z", - "start_time": "2023-04-09T16:09:55.391296Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(63, 5663, 2)" - ] - }, - "execution_count": 48, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "pk.shape" - ] - }, - { - "cell_type": "code", - "execution_count": 58, + "execution_count": 39, "id": "09015847", "metadata": { "ExecuteTime": { - "end_time": "2023-04-09T16:13:34.120967Z", - "start_time": "2023-04-09T16:13:31.837869Z" + "end_time": "2023-04-12T14:51:47.023893Z", + "start_time": "2023-04-12T14:51:46.404156Z" } }, "outputs": [ { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_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", - "\n", - "mpl.figure.prototype._init_header = function () {\n", - " var titlebar = document.createElement('div');\n", - " titlebar.classList =\n", - " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", - " var titletext = document.createElement('div');\n", - " titletext.classList = 'ui-dialog-title';\n", - " titletext.setAttribute(\n", - " 'style',\n", - " 'width: 100%; text-align: center; padding: 3px;'\n", - " );\n", - " titlebar.appendChild(titletext);\n", - " this.root.appendChild(titlebar);\n", - " this.header = titletext;\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._init_canvas = function () {\n", - " var fig = this;\n", - "\n", - " var canvas_div = (this.canvas_div = document.createElement('div'));\n", - " canvas_div.setAttribute(\n", - " 'style',\n", - " 'border: 1px solid #ddd;' +\n", - " 'box-sizing: content-box;' +\n", - " 'clear: both;' +\n", - " 'min-height: 1px;' +\n", - " 'min-width: 1px;' +\n", - " 'outline: 0;' +\n", - " 'overflow: hidden;' +\n", - " 'position: relative;' +\n", - " 'resize: both;'\n", - " );\n", - "\n", - " function on_keyboard_event_closure(name) {\n", - " return function (event) {\n", - " return fig.key_event(event, name);\n", - " };\n", - " }\n", - "\n", - " canvas_div.addEventListener(\n", - " 'keydown',\n", - " on_keyboard_event_closure('key_press')\n", - " );\n", - " canvas_div.addEventListener(\n", - " 'keyup',\n", - " on_keyboard_event_closure('key_release')\n", - " );\n", - "\n", - " this._canvas_extra_style(canvas_div);\n", - " this.root.appendChild(canvas_div);\n", - "\n", - " var canvas = (this.canvas = document.createElement('canvas'));\n", - " canvas.classList.add('mpl-canvas');\n", - " canvas.setAttribute('style', 'box-sizing: content-box;');\n", - "\n", - " this.context = canvas.getContext('2d');\n", - "\n", - " var backingStore =\n", - " this.context.backingStorePixelRatio ||\n", - " this.context.webkitBackingStorePixelRatio ||\n", - " this.context.mozBackingStorePixelRatio ||\n", - " this.context.msBackingStorePixelRatio ||\n", - " this.context.oBackingStorePixelRatio ||\n", - " this.context.backingStorePixelRatio ||\n", - " 1;\n", - "\n", - " this.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", - " 'canvas'\n", - " ));\n", - " rubberband_canvas.setAttribute(\n", - " 'style',\n", - " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", - " );\n", - "\n", - " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n", - " if (this.ResizeObserver === undefined) {\n", - " if (window.ResizeObserver !== undefined) {\n", - " this.ResizeObserver = window.ResizeObserver;\n", - " } else {\n", - " var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n", - " this.ResizeObserver = obs.ResizeObserver;\n", - " }\n", - " }\n", - "\n", - " this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n", - " var nentries = entries.length;\n", - " for (var i = 0; i < nentries; i++) {\n", - " var entry = entries[i];\n", - " var width, height;\n", - " if (entry.contentBoxSize) {\n", - " if (entry.contentBoxSize instanceof Array) {\n", - " // Chrome 84 implements new version of spec.\n", - " width = entry.contentBoxSize[0].inlineSize;\n", - " height = entry.contentBoxSize[0].blockSize;\n", - " } else {\n", - " // Firefox implements old version of spec.\n", - " width = entry.contentBoxSize.inlineSize;\n", - " height = entry.contentBoxSize.blockSize;\n", - " }\n", - " } else {\n", - " // Chrome <84 implements even older version of spec.\n", - " width = entry.contentRect.width;\n", - " height = entry.contentRect.height;\n", - " }\n", - "\n", - " // Keep the size of the canvas and rubber band canvas in sync with\n", - " // the canvas container.\n", - " if (entry.devicePixelContentBoxSize) {\n", - " // Chrome 84 implements new version of spec.\n", - " canvas.setAttribute(\n", - " 'width',\n", - " entry.devicePixelContentBoxSize[0].inlineSize\n", - " );\n", - " canvas.setAttribute(\n", - " 'height',\n", - " entry.devicePixelContentBoxSize[0].blockSize\n", - " );\n", - " } else {\n", - " canvas.setAttribute('width', width * fig.ratio);\n", - " canvas.setAttribute('height', height * fig.ratio);\n", - " }\n", - " canvas.setAttribute(\n", - " 'style',\n", - " 'width: ' + width + 'px; height: ' + height + 'px;'\n", - " );\n", - "\n", - " rubberband_canvas.setAttribute('width', width);\n", - " rubberband_canvas.setAttribute('height', height);\n", - "\n", - " // And update the size in Python. We ignore the initial 0/0 size\n", - " // that occurs as the element is placed into the DOM, which should\n", - " // otherwise not happen due to the minimum size styling.\n", - " if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n", - " fig.request_resize(width, height);\n", - " }\n", - " }\n", - " });\n", - " this.resizeObserverInstance.observe(canvas_div);\n", - "\n", - " function on_mouse_event_closure(name) {\n", - " return function (event) {\n", - " return fig.mouse_event(event, name);\n", - " };\n", - " }\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mousedown',\n", - " on_mouse_event_closure('button_press')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseup',\n", - " on_mouse_event_closure('button_release')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\n", - " );\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband_canvas.addEventListener(\n", - " 'mousemove',\n", - " on_mouse_event_closure('motion_notify')\n", - " );\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseenter',\n", - " on_mouse_event_closure('figure_enter')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseleave',\n", - " on_mouse_event_closure('figure_leave')\n", - " );\n", - "\n", - " canvas_div.addEventListener('wheel', function (event) {\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " on_mouse_event_closure('scroll')(event);\n", - " });\n", - "\n", - " canvas_div.appendChild(canvas);\n", - " canvas_div.appendChild(rubberband_canvas);\n", - "\n", - " this.rubberband_context = rubberband_canvas.getContext('2d');\n", - " this.rubberband_context.strokeStyle = '#000000';\n", - "\n", - " this._resize_canvas = function (width, height, forward) {\n", - " if (forward) {\n", - " canvas_div.style.width = width + 'px';\n", - " canvas_div.style.height = height + 'px';\n", - " }\n", - " };\n", - "\n", - " // Disable right mouse context menu.\n", - " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", - " event.preventDefault();\n", - " return false;\n", - " });\n", - "\n", - " function set_focus() {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'mpl-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " continue;\n", - " }\n", - "\n", - " var button = (fig.buttons[name] = document.createElement('button'));\n", - " button.classList = 'mpl-widget';\n", - " button.setAttribute('role', 'button');\n", - " button.setAttribute('aria-disabled', 'false');\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - "\n", - " var icon_img = document.createElement('img');\n", - " icon_img.src = '_images/' + image + '.png';\n", - " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", - " icon_img.alt = tooltip;\n", - " button.appendChild(icon_img);\n", - "\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " var fmt_picker = document.createElement('select');\n", - " fmt_picker.classList = 'mpl-widget';\n", - " toolbar.appendChild(fmt_picker);\n", - " this.format_dropdown = fmt_picker;\n", - "\n", - " for (var ind in mpl.extensions) {\n", - " var fmt = mpl.extensions[ind];\n", - " var option = document.createElement('option');\n", - " option.selected = fmt === mpl.default_extension;\n", - " option.innerHTML = fmt;\n", - " fmt_picker.appendChild(option);\n", - " }\n", - "\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "};\n", - "\n", - "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", - " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", - " // which will in turn request a refresh of the image.\n", - " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", - "};\n", - "\n", - "mpl.figure.prototype.send_message = function (type, properties) {\n", - " properties['type'] = type;\n", - " properties['figure_id'] = this.id;\n", - " this.ws.send(JSON.stringify(properties));\n", - "};\n", - "\n", - "mpl.figure.prototype.send_draw_message = function () {\n", - " if (!this.waiting) {\n", - " this.waiting = true;\n", - " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " var format_dropdown = fig.format_dropdown;\n", - " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", - " fig.ondownload(fig, format);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", - " var size = msg['size'];\n", - " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", - " fig._resize_canvas(size[0], size[1], msg['forward']);\n", - " fig.send_message('refresh', {});\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", - " var x0 = msg['x0'] / fig.ratio;\n", - " var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n", - " var x1 = msg['x1'] / fig.ratio;\n", - " var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n", - " x0 = Math.floor(x0) + 0.5;\n", - " y0 = Math.floor(y0) + 0.5;\n", - " x1 = Math.floor(x1) + 0.5;\n", - " y1 = Math.floor(y1) + 0.5;\n", - " var min_x = Math.min(x0, x1);\n", - " var min_y = Math.min(y0, y1);\n", - " var width = Math.abs(x1 - x0);\n", - " var height = Math.abs(y1 - y0);\n", - "\n", - " fig.rubberband_context.clearRect(\n", - " 0,\n", - " 0,\n", - " fig.canvas.width / fig.ratio,\n", - " fig.canvas.height / fig.ratio\n", - " );\n", - "\n", - " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", - " // Updates the figure title.\n", - " fig.header.textContent = msg['label'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", - " fig.rubberband_canvas.style.cursor = msg['cursor'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_message = function (fig, msg) {\n", - " fig.message.textContent = msg['message'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", - " // Request the server to send over a new figure.\n", - " fig.send_draw_message();\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", - " fig.image_mode = msg['mode'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", - " for (var key in msg) {\n", - " if (!(key in fig.buttons)) {\n", - " continue;\n", - " }\n", - " fig.buttons[key].disabled = !msg[key];\n", - " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", - " if (msg['mode'] === 'PAN') {\n", - " fig.buttons['Pan'].classList.add('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " } else if (msg['mode'] === 'ZOOM') {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.add('active');\n", - " } else {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Called whenever the canvas gets updated.\n", - " this.send_message('ack', {});\n", - "};\n", - "\n", - "// A function to construct a web socket function for onmessage handling.\n", - "// Called in the figure constructor.\n", - "mpl.figure.prototype._make_on_message_function = function (fig) {\n", - " return function socket_on_message(evt) {\n", - " if (evt.data instanceof Blob) {\n", - " var img = evt.data;\n", - " if (img.type !== 'image/png') {\n", - " /* FIXME: We get \"Resource interpreted as Image but\n", - " * transferred with MIME type text/plain:\" errors on\n", - " * Chrome. But how to set the MIME type? It doesn't seem\n", - " * to be part of the websocket stream */\n", - " img.type = 'image/png';\n", - " }\n", - "\n", - " /* Free the memory for the previous frames */\n", - " if (fig.imageObj.src) {\n", - " (window.URL || window.webkitURL).revokeObjectURL(\n", - " fig.imageObj.src\n", - " );\n", - " }\n", - "\n", - " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", - " img\n", - " );\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " } else if (\n", - " typeof evt.data === 'string' &&\n", - " evt.data.slice(0, 21) === 'data:image/png;base64'\n", - " ) {\n", - " fig.imageObj.src = evt.data;\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " }\n", - "\n", - " var msg = JSON.parse(evt.data);\n", - " var msg_type = msg['type'];\n", - "\n", - " // Call the \"handle_{type}\" callback, which takes\n", - " // the figure and JSON message as its only arguments.\n", - " try {\n", - " var callback = fig['handle_' + msg_type];\n", - " } catch (e) {\n", - " console.log(\n", - " \"No handler for the '\" + msg_type + \"' message type: \",\n", - " msg\n", - " );\n", - " return;\n", - " }\n", - "\n", - " if (callback) {\n", - " try {\n", - " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", - " callback(fig, msg);\n", - " } catch (e) {\n", - " console.log(\n", - " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", - " e,\n", - " e.stack,\n", - " msg\n", - " );\n", - " }\n", - " }\n", - " };\n", - "};\n", - "\n", - "// from https://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", - "mpl.findpos = function (e) {\n", - " //this section is from http://www.quirksmode.org/js/events_properties.html\n", - " var targ;\n", - " if (!e) {\n", - " e = window.event;\n", - " }\n", - " if (e.target) {\n", - " targ = e.target;\n", - " } else if (e.srcElement) {\n", - " targ = e.srcElement;\n", - " }\n", - " if (targ.nodeType === 3) {\n", - " // defeat Safari bug\n", - " targ = targ.parentNode;\n", - " }\n", - "\n", - " // pageX,Y are the mouse positions relative to the document\n", - " var boundingRect = targ.getBoundingClientRect();\n", - " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", - " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", - "\n", - " return { x: x, y: y };\n", - "};\n", - "\n", - "/*\n", - " * return a copy of an object with only non-object keys\n", - " * we need this to avoid circular references\n", - " * https://stackoverflow.com/a/24161582/3208463\n", - " */\n", - "function simpleKeys(original) {\n", - " return Object.keys(original).reduce(function (obj, key) {\n", - " if (typeof original[key] !== 'object') {\n", - " obj[key] = original[key];\n", - " }\n", - " return obj;\n", - " }, {});\n", - "}\n", - "\n", - "mpl.figure.prototype.mouse_event = function (event, name) {\n", - " var canvas_pos = mpl.findpos(event);\n", - "\n", - " if (name === 'button_press') {\n", - " this.canvas.focus();\n", - " this.canvas_div.focus();\n", - " }\n", - "\n", - " var x = canvas_pos.x * this.ratio;\n", - " var y = canvas_pos.y * this.ratio;\n", - "\n", - " this.send_message(name, {\n", - " x: x,\n", - " y: y,\n", - " button: event.button,\n", - " step: event.step,\n", - " guiEvent: simpleKeys(event),\n", - " });\n", - "\n", - " /* This prevents the web browser from automatically changing to\n", - " * the text insertion cursor when the button is pressed. We want\n", - " * to control all of the cursor setting manually through the\n", - " * 'cursor' event from matplotlib */\n", - " event.preventDefault();\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", - " // Handle any extra behaviour associated with a key event\n", - "};\n", - "\n", - "mpl.figure.prototype.key_event = function (event, name) {\n", - " // Prevent repeat events\n", - " if (name === 'key_press') {\n", - " if (event.key === this._key) {\n", - " return;\n", - " } else {\n", - " this._key = event.key;\n", - " }\n", - " }\n", - " if (name === 'key_release') {\n", - " this._key = null;\n", - " }\n", - "\n", - " var value = '';\n", - " if (event.ctrlKey && event.key !== 'Control') {\n", - " value += 'ctrl+';\n", - " }\n", - " else if (event.altKey && event.key !== 'Alt') {\n", - " value += 'alt+';\n", - " }\n", - " else if (event.shiftKey && event.key !== 'Shift') {\n", - " value += 'shift+';\n", - " }\n", - "\n", - " value += 'k' + event.key;\n", - "\n", - " this._key_event_extra(event, name);\n", - "\n", - " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", - " if (name === 'download') {\n", - " this.handle_save(this, null);\n", - " } else {\n", - " this.send_message('toolbar_button', { name: name });\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", - " this.message.textContent = tooltip;\n", - "};\n", - "\n", - "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n", - "// prettier-ignore\n", - "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home\", \"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", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\", \"webp\"];\n", - "\n", - "mpl.default_extension = \"png\";/* global mpl */\n", - "\n", - "var comm_websocket_adapter = function (comm) {\n", - " // Create a \"websocket\"-like object which calls the given IPython comm\n", - " // object with the appropriate methods. Currently this is a non binary\n", - " // socket, so there is still some room for performance tuning.\n", - " var ws = {};\n", - "\n", - " ws.binaryType = comm.kernel.ws.binaryType;\n", - " ws.readyState = comm.kernel.ws.readyState;\n", - " function updateReadyState(_event) {\n", - " if (comm.kernel.ws) {\n", - " ws.readyState = comm.kernel.ws.readyState;\n", - " } else {\n", - " ws.readyState = 3; // Closed state.\n", - " }\n", - " }\n", - " comm.kernel.ws.addEventListener('open', updateReadyState);\n", - " comm.kernel.ws.addEventListener('close', updateReadyState);\n", - " comm.kernel.ws.addEventListener('error', updateReadyState);\n", - "\n", - " ws.close = function () {\n", - " comm.close();\n", - " };\n", - " ws.send = function (m) {\n", - " //console.log('sending', m);\n", - " comm.send(m);\n", - " };\n", - " // Register the callback with on_msg.\n", - " comm.on_msg(function (msg) {\n", - " //console.log('receiving', msg['content']['data'], msg);\n", - " var data = msg['content']['data'];\n", - " if (data['blob'] !== undefined) {\n", - " data = {\n", - " data: new Blob(msg['buffers'], { type: data['blob'] }),\n", - " };\n", - " }\n", - " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", - " ws.onmessage(data);\n", - " });\n", - " return ws;\n", - "};\n", - "\n", - "mpl.mpl_figure_comm = function (comm, msg) {\n", - " // This is the function which gets called when the mpl process\n", - " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", - "\n", - " var id = msg.content.data.id;\n", - " // Get hold of the div created by the display call when the Comm\n", - " // socket was opened in Python.\n", - " var element = document.getElementById(id);\n", - " var ws_proxy = comm_websocket_adapter(comm);\n", - "\n", - " function ondownload(figure, _format) {\n", - " window.open(figure.canvas.toDataURL());\n", - " }\n", - "\n", - " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", - "\n", - " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", - " // web socket which is closed, not our websocket->open comm proxy.\n", - " ws_proxy.onopen();\n", - "\n", - " fig.parent_element = element;\n", - " fig.cell_info = mpl.find_output_cell(\"
\");\n", - " if (!fig.cell_info) {\n", - " console.error('Failed to find cell for figure', id, fig);\n", - " return;\n", - " }\n", - " fig.cell_info[0].output_area.element.on(\n", - " 'cleared',\n", - " { fig: fig },\n", - " fig._remove_fig_handler\n", - " );\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_close = function (fig, msg) {\n", - " var width = fig.canvas.width / fig.ratio;\n", - " fig.cell_info[0].output_area.element.off(\n", - " 'cleared',\n", - " fig._remove_fig_handler\n", - " );\n", - " fig.resizeObserverInstance.unobserve(fig.canvas_div);\n", - "\n", - " // Update the output cell to use the data from the current canvas.\n", - " fig.push_to_output();\n", - " var dataURL = fig.canvas.toDataURL();\n", - " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", - " // the notebook keyboard shortcuts fail.\n", - " IPython.keyboard_manager.enable();\n", - " fig.parent_element.innerHTML =\n", - " '';\n", - " fig.close_ws(fig, msg);\n", - "};\n", - "\n", - "mpl.figure.prototype.close_ws = function (fig, msg) {\n", - " fig.send_message('closing', msg);\n", - " // fig.ws.close()\n", - "};\n", - "\n", - "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", - " // Turn the data on the canvas into data in the output cell.\n", - " var width = this.canvas.width / this.ratio;\n", - " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] =\n", - " '';\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Tell IPython that the notebook contents must change.\n", - " IPython.notebook.set_dirty(true);\n", - " this.send_message('ack', {});\n", - " var fig = this;\n", - " // Wait a second, then push the new image to the DOM so\n", - " // that it is saved nicely (might be nice to debounce this).\n", - " setTimeout(function () {\n", - " fig.push_to_output();\n", - " }, 1000);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'btn-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " var button;\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " continue;\n", - " }\n", - "\n", - " button = fig.buttons[name] = document.createElement('button');\n", - " button.classList = 'btn btn-default';\n", - " button.href = '#';\n", - " button.title = name;\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message pull-right';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = document.createElement('div');\n", - " buttongrp.classList = 'btn-group inline pull-right';\n", - " button = document.createElement('button');\n", - " button.classList = 'btn btn-mini btn-primary';\n", - " button.href = '#';\n", - " button.title = 'Stop Interaction';\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', function (_evt) {\n", - " fig.handle_close(fig, {});\n", - " });\n", - " button.addEventListener(\n", - " 'mouseover',\n", - " on_mouseover_closure('Stop Interaction')\n", - " );\n", - " buttongrp.appendChild(button);\n", - " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", - " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", - "};\n", - "\n", - "mpl.figure.prototype._remove_fig_handler = function (event) {\n", - " var fig = event.data.fig;\n", - " if (event.target !== this) {\n", - " // Ignore bubbled events from children.\n", - " return;\n", - " }\n", - " fig.close_ws(fig, {});\n", - "};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (el) {\n", - " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (el) {\n", - " // this is important to make the div 'focusable\n", - " el.setAttribute('tabindex', 0);\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " } else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which === 13) {\n", - " this.canvas_div.blur();\n", - " // select the cell after this one\n", - " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", - " IPython.notebook.select(index + 1);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " fig.ondownload(fig, null);\n", - "};\n", - "\n", - "mpl.find_output_cell = function (html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i = 0; i < ncells; i++) {\n", - " var cell = cells[i];\n", - " if (cell.cell_type === 'code') {\n", - " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", - " var data = cell.output_area.outputs[j];\n", - " if (data.data) {\n", - " // IPython >= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] === html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "};\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel !== null) {\n", - " IPython.notebook.kernel.comm_manager.register_target(\n", - " 'matplotlib',\n", - " mpl.mpl_figure_comm\n", - " );\n", - "}\n" - ], + "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", "text/plain": [ "" ] @@ -2144,7 +196,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -2159,34 +211,97 @@ "\n", "\n", "plt.figure()\n", + "plt.title(r\"Solid: high $\\lambda$, dashed: low $\\lambda$\")\n", "# plt.plot(rs, np.nansum(pk, axis=0)[:, 0], c=cols[k])\n", "# plt.plot(rs, np.nansum(pk_perm, axis=0)[:, 0], c=cols[k], ls=\"--\")\n", - "for k in range(1, 2):\n", - " plt.plot(rs, pk[k, :, 0], c=cols[k])\n", + "for k in range(1, 5):\n", + " plt.plot(rs, pk[k, :, 0], c=cols[k], label=r\"$k = {}$\".format(k))\n", + " plt.plot(rs, pk2[k, :, 0], c=cols[k], ls=\"--\")\n", "# plt.plot(rs, pk_perm[k, :, 0], c=cols[k], ls=\"--\")\n", "# plt.fill_between(rs, pk[k, :, 0] - pk[k, :, 1], pk[k, :, 0] + pk[k, :, 1])\n", "\n", "# plt.plot(rs, np.sum(pk, axis=0)[:, 0])\n", "\n", - "# plt.xscale(\"log\")\n", + "plt.xscale(\"log\")\n", + "plt.ylabel(r\"$P(k | r)$\")\n", + "plt.xlabel(r\"$r~[\\mathrm{Mpc}]$\")\n", + "plt.legend()\n", + "\n", + "plt.savefig(\"../plots/autoknn.png\", dpi=450)\n", "plt.show()\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 32, "id": "1279a8cb", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2023-04-12T14:39:14.994393Z", + "start_time": "2023-04-12T14:38:38.593354Z" + } + }, "outputs": [], - "source": [] + "source": [ + "rs, cross = knnreader.read(\"mass001\", cross_folder, rmin=1, rmax=50)\n", + "# pk = knnreader.mean_prob_k(cdf)\n", + "\n", + "rs, cdf = knnreader.read(\"mass001_random\", auto_folder, rmin=1, rmax=50)\n", + "pk = knnreader.mean_prob_k(cdf)" + ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "id": "9e0185ce", - "metadata": {}, - "outputs": [], - "source": [] + "metadata": { + "ExecuteTime": { + "end_time": "2023-04-12T14:48:35.806517Z", + "start_time": "2023-04-12T14:48:35.106183Z" + } + }, + "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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "cols = plt.rcParams[\"axes.prop_cycle\"].by_key()[\"color\"]\n", + "\n", + "plt.figure()\n", + "for i in range(1, 6):\n", + " plt.plot(rs, cross[0, i, :], c=cols[i], label=r\"k = {}\".format(i))\n", + " \n", + " plt.plot(rs, pk[i, :, 0], c=cols[i], ls=\"--\")\n", + "\n", + "plt.axvline(2.65 / 0.705, c=\"red\", ls=\"--\")\n", + "plt.xlabel(r\"$r~[\\mathrm{Mpc}]$\")\n", + "plt.ylabel(r\"Cross-correlation\")\n", + "plt.xscale(\"log\")\n", + "plt.legend()\n", + "plt.tight_layout()\n", + "plt.savefig(\"../plots/knncross.png\", dpi=450)\n", + "plt.show()" + ] }, { "cell_type": "code", @@ -4065,7 +2180,7 @@ "kernelspec": { "display_name": "venv_galomatch", "language": "python", - "name": "venv_galomatch" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -4078,11 +2193,6 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.0" - }, - "vscode": { - "interpreter": { - "hash": "f29d02a8350410abc2a9fb79641689d10bf7ab64afc03ec87ca3cf6ed2daa499" - } } }, "nbformat": 4, diff --git a/scripts/knn_auto.yml b/scripts/knn_auto.yml index ae02db9..1d82215 100644 --- a/scripts/knn_auto.yml +++ b/scripts/knn_auto.yml @@ -44,7 +44,7 @@ nbins_marks: 10 secondary: name: lambda200c toperm: false - marked: false + marked: true max: 0.5 "mass001_spinhigh": @@ -77,7 +77,7 @@ nbins_marks: 10 secondary: name: lambda200c toperm: false - marked: false + marked: true max: 0.5 "mass002_spinhigh": @@ -109,7 +109,7 @@ nbins_marks: 10 secondary: name: lambda200c toperm: false - marked: false + marked: true max: 0.5 "mass003_spinhigh": diff --git a/scripts/tpcf_auto.py b/scripts/tpcf_auto.py new file mode 100644 index 0000000..3e13be0 --- /dev/null +++ b/scripts/tpcf_auto.py @@ -0,0 +1,146 @@ +# Copyright (C) 2022 Richard Stiskalek +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# 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. +"""A script to calculate the auto-2PCF of CSiBORG catalogues.""" +from os.path import join +from warnings import warn +from argparse import ArgumentParser +from copy import deepcopy +from datetime import datetime +from mpi4py import MPI +from TaskmasterMPI import master_process, worker_process +import numpy +import joblib +import yaml +try: + import csiborgtools +except ModuleNotFoundError: + import sys + sys.path.append("../") + import csiborgtools + + +############################################################################### +# MPI and arguments # +############################################################################### +comm = MPI.COMM_WORLD +rank = comm.Get_rank() +nproc = comm.Get_size() + +parser = ArgumentParser() +parser.add_argument("--runs", type=str, nargs="+") +args = parser.parse_args() +with open('../scripts/tpcf_auto.yml', 'r') as file: + config = yaml.safe_load(file) + +Rmax = 155 / 0.705 # Mpc (h = 0.705) high resolution region radius +minmass = 1e12 +ics = [7444, 7468, 7492, 7516, 7540, 7564, 7588, 7612, 7636, 7660, 7684, + 7708, 7732, 7756, 7780, 7804, 7828, 7852, 7876, 7900, 7924, 7948, + 7972, 7996, 8020, 8044, 8068, 8092, 8116, 8140, 8164, 8188, 8212, + 8236, 8260, 8284, 8308, 8332, 8356, 8380, 8404, 8428, 8452, 8476, + 8500, 8524, 8548, 8572, 8596, 8620, 8644, 8668, 8692, 8716, 8740, + 8764, 8788, 8812, 8836, 8860, 8884, 8908, 8932, 8956, 8980, 9004, + 9028, 9052, 9076, 9100, 9124, 9148, 9172, 9196, 9220, 9244, 9268, + 9292, 9316, 9340, 9364, 9388, 9412, 9436, 9460, 9484, 9508, 9532, + 9556, 9580, 9604, 9628, 9652, 9676, 9700, 9724, 9748, 9772, 9796, + 9820, 9844] +dumpdir = "/mnt/extraspace/rstiskalek/csiborg/tpcf" +fout = join(dumpdir, "auto", "tpcf_{}_{}.p") +paths = csiborgtools.read.CSiBORGPaths() +tpcf = csiborgtools.clustering.Mock2PCF() + +############################################################################### +# Analysis # +############################################################################### + +def read_single(selection, cat): + """Positions for single catalogue auto-correlation.""" + mmask = numpy.ones(len(cat), dtype=bool) + pos = cat.positions(False) + # Primary selection + psel = selection["primary"] + pmin, pmax = psel.get("min", None), psel.get("max", None) + if pmin is not None: + mmask &= (cat[psel["name"]] >= pmin) + if pmax is not None: + mmask &= (cat[psel["name"]] < pmax) + pos = pos[mmask, ...] + + # Secondary selection + if "secondary" not in selection: + return pos + smask = numpy.ones(pos.shape[0], dtype=bool) + ssel = selection["secondary"] + smin, smax = ssel.get("min", None), ssel.get("max", None) + prop = cat[ssel["name"]][mmask] + if ssel.get("toperm", False): + prop = numpy.random.permutation(prop) + if ssel.get("marked", True): + x = cat[psel["name"]][mmask] + prop = csiborgtools.clustering.normalised_marks( + x, prop, nbins=config["nbins_marks"]) + + if smin is not None: + smask &= (prop >= smin) + if smax is not None: + smask &= (prop < smax) + + return pos[smask, ...] + +def do_auto(run, cat, ic): + _config = config.get(run, None) + if _config is None: + warn("No configuration for run {}.".format(run)) + return + + rvs_gen = csiborgtools.clustering.RVSinsphere(Rmax) + bins = numpy.logspace(numpy.log10(config["rpmin"]), + numpy.log10(config["rpmax"]), config["nrpbins"] + 1) + pos = read_single(_config, cat) + nrandom = int(config["randmult"] * pos.shape[0]) + rp, wp = tpcf(pos, rvs_gen, nrandom, bins) + + joblib.dump({"rp": rp, "wp": wp}, fout.format(str(ic).zfill(5), run)) + + +def do_runs(ic): + cat = csiborgtools.read.HaloCatalogue(ic, paths, max_dist=Rmax, + min_mass=minmass) + for run in args.runs: + do_auto(run, cat, ic) + + +############################################################################### +# MPI task delegation # +############################################################################### + + +if nproc > 1: + if rank == 0: + tasks = deepcopy(ics) + master_process(tasks, comm, verbose=True) + else: + worker_process(do_runs, comm, verbose=False) +else: + tasks = deepcopy(ics) + for task in tasks: + print("{}: completing task `{}`.".format(datetime.now(), task)) + do_runs(task) +comm.Barrier() + + +if rank == 0: + print("{}: all finished.".format(datetime.now())) +quit() # Force quit the script diff --git a/scripts/tpcf_auto.yml b/scripts/tpcf_auto.yml new file mode 100644 index 0000000..1d898d9 --- /dev/null +++ b/scripts/tpcf_auto.yml @@ -0,0 +1,136 @@ +rpmin: 0.5 +rpmax: 40 +nrpbins: 20 +randmult: 100 +seed: 42 +nbins_marks: 10 + + +################################################################################ +# totpartmass # +################################################################################ + + +"mass001": + primary: + name: totpartmass + min: 1.e+12 + max: 1.e+13 + +"mass002": + primary: + name: totpartmass + min: 1.e+13 + max: 1.e+14 + +"mass003": + primary: + name: totpartmass + min: 1.e+14 + + +################################################################################ +# totpartmass + lambda200c # +################################################################################ + + +"mass001_spinlow": + primary: + name: totpartmass + min: 1.e+12 + max: 1.e+13 + secondary: + name: lambda200c + marked: true + max: 0.5 + +"mass001_spinhigh": + primary: + name: totpartmass + min: 1.e+12 + max: 1.e+13 + secondary: + name: lambda200c + marked: true + min: 0.5 + +"mass001_spinmedian_perm": + primary: + name: totpartmass + min: 1.e+12 + max: 1.e+13 + secondary: + name: lambda200c + toperm: true + marked : true + min: 0.5 + +"mass002_spinlow": + primary: + name: totpartmass + min: 1.e+13 + max: 1.e+14 + secondary: + name: lambda200c + marked: true + max: 0.5 + +"mass002_spinhigh": + primary: + name: totpartmass + min: 1.e+13 + max: 1.e+14 + secondary: + name: lambda200c + marked: true + min: 0.5 + +"mass002_spinmedian_perm": + primary: + name: totpartmass + min: 1.e+13 + max: 1.e+14 + secondary: + name: lambda200c + toperm: true + marked : true + min: 0.5 + +"mass003_spinlow": + primary: + name: totpartmass + min: 1.e+14 + secondary: + name: lambda200c + marked: true + max: 0.5 + +"mass003_spinhigh": + primary: + name: totpartmass + min: 1.e+14 + secondary: + name: lambda200c + marked: true + min: 0.5 + +"mass003_spinmedian_perm": + primary: + name: totpartmass + min: 1.e+14 + secondary: + name: lambda200c + toperm: true + marked : true + min: 0.5 + + +################################################################################ +# Cross with random # +################################################################################ + +"mass001_random": + primary: + name: totpartmass + min: 1.e+12 + max: 1.e+13 \ No newline at end of file