From e0df3f64a1f909007b30a77ae98ad0f3c55d07a3 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 16 Dec 2024 14:45:59 +0100 Subject: [PATCH] Update example notebooks (WIP) --- examples/fit_helium.ipynb | 11825 +++------------------------- examples/predict_UV.ipynb | 390 +- src/sunbather/convergeT_parker.py | 44 +- 3 files changed, 1478 insertions(+), 10781 deletions(-) diff --git a/examples/fit_helium.ipynb b/examples/fit_helium.ipynb index 34d3fdb..0d9a559 100644 --- a/examples/fit_helium.ipynb +++ b/examples/fit_helium.ipynb @@ -1,22 +1,43 @@ { "cells": [ + { + "cell_type": "markdown", + "id": "41ae9ef8-a389-4246-a783-9eb9f103cfe9", + "metadata": {}, + "source": [ + "# Fit Helium" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c2fa30e-6bfd-47bc-9672-3245cb376f59", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sunbather\n", + "sunbather.tools.get_sunbather_project_path()\n", + "sunbather.firstrun()" + ] + }, { "cell_type": "markdown", "id": "d7370e97", "metadata": {}, "source": [ - "# License\n", - "\n", + "## License\n", "The code in this notebook is free to be used, edited and redistributed by anyone free of charge. Please cite Linssen et al. (2024) when making use of _sunbather_ and/or the code in this notebook." ] }, { "cell_type": "markdown", "id": "90d0f8d2", - "metadata": {}, + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, "source": [ - "# Scientific goal\n", - "\n", + "## Scientific goal\n", "In this notebook, we demonstrate how sunbather can be used to obtain mass-loss rate estimates from spectral observations. Fitting Parker wind models to helium data is a commonly applied method, but it can result in a degeneracy between the free parameters of the Parker wind model: the temperature and the mass-loss rate. Constraints on the mass-loss rate are not very stringent in that case. In this notebook, we follow the approach described in Linssen et al. (2022), to mitigate this. We fit the helium line and combine this with additional constraints on the Parker wind temperature parameter, in order to break the degeneracy and get better constraints on the mass-loss rate. We first do this for a simple case of a spectrum that we generate from random data, which will reproduce the results of Fig. 6 from Linssen et al. (2024). Then, we move on to fitting the observed He 10830 Å signal of TOI-2134 b from Zhang et al. (2023). We will perform fits with both an atmospheric composition that is a hydrogen/helium mixture in the solar ratio, and a 100x solar metallicity atmosphere. This reproduces the results of Fig. 7 from Linssen et al. (2024)." ] }, @@ -25,7 +46,7 @@ "id": "9c3b972d", "metadata": {}, "source": [ - "# Methodology\n", + "## Methodology\n", "\n", "We need to run a grid of Parker wind models with different temperatures ($T_0$) and mass-loss rates ($\\dot{M}$), which can be computationally expensive depending on the size of the grid. Here, we include the commands to run your own grid (as commented out Python lines), but by default this notebook uses the model runs that we have pre-run to save computation time.\n", "\n", @@ -44,120 +65,171 @@ }, { "cell_type": "markdown", - "id": "0da3ff8d", + "id": "3e620f6b-9d14-4796-bef8-adf0ced1ca22", "metadata": {}, "source": [ - "# Preparation\n", + "## Preparation\n", "\n", "To reproduce these results, we assume you have all codes set-up. That is; you have downloaded *sunbather* and installed its dependencies (the Python packages, including *p-winds*). You have installed *Cloudy* and have the path to it stored as the *\\$CLOUDY_PATH* environmental variable. You have created your \"project\" folder, and have the path to it stored as the *\\$SUNBATHER_PROJECT_PATH* environmental variable. These steps are described in more detail in the \"installation\" section of the _sunbather_ wiki.\n", "\n", - "Before *sunbather* can create Parker wind profiles, we need to make sure the parameters of the system are available to the code. The parameters are stored in the *$SUNBATHER_PROJECT_PATH/planets.txt* file. To run the models for the generic hot Neptune mock retrieval, as well as the TOI-2134 b models, you will need to add their parameters.\n", - "\n", - "> **Add the following two lines to _$SUNBATHER_PROJECT_PATH/planets.txt_:**

\n", - "> TOI2134b,TOI-2134 b,0.240,0.709,0.078,0.0287,0.744,0.20,TOI2134.spec #parameters from Zhang et al. (2023)\n", - "
\n", - "> hotNeptune,generic hot Neptune,0.5,1.0,0.05,0.1,1.0,0.,solar.spec\n", - "\n", + "Before *sunbather* can create Parker wind profiles, we need to make sure the parameters of the system are available to the code. The parameters are stored in the *$SUNBATHER_PROJECT_PATH/planets.txt* file. To run the models for the generic hot Neptune mock retrieval, as well as the TOI-2134 b models, you will need to add their parameters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29bd070a-1891-4325-a53a-7d4467175935", + "metadata": {}, + "outputs": [], + "source": [ + "# Adds two lines to _$SUNBATHER_PROJECT_PATH/planets.txt_:\n", + "import sunbather.tools\n", + "with open(\n", + " f\"{sunbather.tools.get_sunbather_project_path()}/planets.txt\", \"a+\", encoding=\"utf-8\"\n", + ") as planetfile:\n", + " planets = planetfile.read()\n", + " if \"TOI2134b\" not in planets:\n", + " planetfile.write(\n", + " \"TOI2134b,TOI-2134 b,0.240,0.709,0.078,0.0287,0.744,0.20,TOI2134.spec \"\n", + " \"#parameters from Zhang et al. (2023)\\n\"\n", + " )\n", + " if \"hotneptune\" not in planets:\n", + " planetfile.write(\n", + " \"hotNeptune,generic hot Neptune,0.5,1.0,0.05,0.1,1.0,0.,solar.spec\\n\"\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "0aa89533-96e2-4b80-b884-a64f215815d0", + "metadata": {}, + "source": [ "The last column of the _planets.txt_ file specifies the **name** of the stellar SED that we want to use. The SED with exactly this name must be available to *Cloudy*, so it must be placed in its source folder, specifically: _\\$CLOUDY_PATH/data/SED/_. In the */sunbather/stellar_SEDs/* folder, the solar.spec file is provided, which is combined from Woods et al. (2005) and Rottman (2005). The TOI2134.spec file is also provided, which is downloaded from the online material of Zhang et al. (2023) ( https://iopscience.iop.org/article/10.3847/2041-8213/aced51 ) and put in the format accepted by *sunbather* (see wiki).\n", "> **The only step you need to take here, is make sure these two spectra are in Cloudy's SED folder: \\$CLOUDY_PATH/data/SED/ (so copy them there).**" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "ede7a4e4-8bb3-47b4-b18e-76f97acd3064", + "metadata": {}, + "outputs": [], + "source": [ + "import os.path\n", + "import shutil\n", + "cloudy_sed_folder = f\"{sunbather.tools.get_cloudy_path()}/data/SED\"\n", + "local_sed_folder = f\"{sunbather.tools.get_sunbather_project_path}/stellar_SEDs/\"\n", + "\n", + "for file in [\"TOI2134.spec\", \"solar.spec\"]:\n", + " if not os.path.isfile(f\"{cloudy_sed_folder}/{file}\"):\n", + " shutil.copyfile(\n", + " f\"{local_sed_folder}/{file}\",\n", + " f\"{cloudy_sed_folder}/{file}\"\n", + " )" + ] + }, { "cell_type": "markdown", "id": "84e276fe", "metadata": {}, "source": [ - "# ------------\n", - "\n", - "# Function definitions\n", - "\n", + "## Function definitions\n", "Since this notebook contains quite a lot of functions for performing the various calculations, we have grouped them all together here, so that the rest of the notebook has improved readability. Once the functions are defined, most parts of the analysis are really only one line of code!" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "4d7362e7", "metadata": {}, "outputs": [], "source": [ - "import sys\n", - "sys.path.append('/Users/dion/src/sunbather/src/') #add your path to /sunbather/src/ here\n", - "\n", - "#import sunbather modules\n", - "import tools\n", - "import RT\n", - "\n", - "#import other modules\n", + "import traceback\n", + "import numpy as np\n", "import pandas as pd\n", "from scipy.integrate import trapezoid\n", "from scipy.integrate import cumulative_trapezoid\n", "import matplotlib.pyplot as plt\n", "import matplotlib\n", "from mpl_toolkits.axes_grid1 import make_axes_locatable\n", - "import numpy as np\n", "import scipy.stats as sps\n", - "import traceback\n", "from scipy.optimize import curve_fit\n", - "import spectres #to resample synthetic spectra to the wavelength grid of observations (pip install spectres)\n", + "import spectres # to resample synthetic spectra to the wavelength grid of observations (pip install spectres)\n", "\n", - "#for interactive matplotlib plots\n", - "%matplotlib notebook" + "# import sunbather modules\n", + "import sunbather\n", + "from sunbather import tools\n", + "from sunbather import RT\n", + "\n", + "# for interactive matplotlib plots\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1084514e-cde2-4120-85d8-5075df89e2f1", + "metadata": {}, + "outputs": [], + "source": [ + "projectpath = tools.get_sunbather_project_path()" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "7dd9f6cd", "metadata": {}, "outputs": [], "source": [ - "### Useful functions ###\n", + "# Useful functions\n", + "\n", "\n", "def get_xyz(df):\n", - " '''\n", + " \"\"\"\n", " Takes as input a Pandas DataFrame which has the x-values\n", " as the index, and the y-values as the column names,\n", " and the z-values as the dataframe contents.\n", - " Returns three 1D arrays with the x, y, z values \n", + " Returns three 1D arrays with the x, y, z values\n", " that can e.g. be plotted with matplotlib tricontour.\n", - " '''\n", - " \n", + " \"\"\"\n", + "\n", " stacked_data = df.stack()\n", " stacked_data = stacked_data.dropna()\n", " x_values = stacked_data.index.get_level_values(0).tolist() # x-values\n", " y_values = stacked_data.index.get_level_values(1).tolist() # y-values\n", - " z_values = stacked_data.tolist() # z-values \n", - " \n", + " z_values = stacked_data.tolist() # z-values\n", + "\n", " return x_values, y_values, z_values\n", "\n", "\n", "def truncate_colormap(cmap, minval=0.0, maxval=1.0, n=1000):\n", - " '''\n", + " \"\"\"\n", " Cuts a colormap to a smaller range.\n", " from https://stackoverflow.com/questions/18926031/how-to-extract-a-subset-of-a-colormap-as-a-new-colormap-in-matplotlib\n", - " '''\n", + " \"\"\"\n", "\n", " new_cmap = matplotlib.colors.LinearSegmentedColormap.from_list(\n", - " 'trunc({n},{a:.2f},{b:.2f})'.format(n=cmap.name, a=minval, b=maxval),\n", - " cmap(np.linspace(minval, maxval, n)))\n", + " \"trunc({n},{a:.2f},{b:.2f})\".format(n=cmap.name, a=minval, b=maxval),\n", + " cmap(np.linspace(minval, maxval, n)),\n", + " )\n", " return new_cmap\n", "\n", "\n", "def get_array_from_contour(cn, levelnum):\n", - " '''\n", + " \"\"\"\n", " Takes an ax.contour object and returns the 'levelnum'-th contour as an\n", " array of x and y values. You can then extract the min/max values from\n", " such a contour/array.\n", - " '''\n", - " \n", + " \"\"\"\n", + "\n", " lines = []\n", " for line in cn.collections[levelnum].get_paths():\n", " lines.append(line.vertices)\n", "\n", " if lines:\n", - " x = np.concatenate(lines, axis=0)[:,0]\n", - " y = np.concatenate(lines, axis=0)[:,1]\n", + " x = np.concatenate(lines, axis=0)[:, 0]\n", + " y = np.concatenate(lines, axis=0)[:, 1]\n", " else:\n", " print(\"No 1 sigma contour could be found\")\n", " x, y = None, None\n", @@ -165,226 +237,305 @@ " return x, y\n", "\n", "\n", - "### Functions that calculate statistics ###\n", - "\n", - "def calc_chisqs_He10830(Tstrucpath, observed_wavs, observed_ea, observed_sig_ea,\n", - " instrument_R=None,\n", - " T0low=2000, T0up=12000, T0step=100,\n", - " Mdotlow=8, Mdotup=12, Mdotstep=0.05,\n", - " **kwargs):\n", - " '''\n", + "# Functions that calculate statistics\n", + "\n", + "\n", + "def calc_chisqs_He10830(\n", + " Tstrucpath,\n", + " observed_wavs,\n", + " observed_ea,\n", + " observed_sig_ea,\n", + " instrument_R=None,\n", + " T0low=2000,\n", + " T0up=12000,\n", + " T0step=100,\n", + " Mdotlow=8,\n", + " Mdotup=12,\n", + " Mdotstep=0.05,\n", + " **kwargs,\n", + "):\n", + " \"\"\"\n", " Reads in all Parker wind profiles present in the Tstrucpath folder,\n", " calculates the metastable helium line, compares it to the observed\n", " profile and calculates the chi-squared value.\n", " Expects excess absorption and error in units of %.\n", - " '''\n", + " \"\"\"\n", + "\n", + " Mdots = [\n", + " \"%.3f\" % Mdot for Mdot in np.arange(Mdotlow, Mdotup + 1e-5, Mdotstep)\n", + " ] # set up a grid of Mdot\n", + " T0s = [\n", + " \"%i\" % T0 for T0 in np.arange(T0low, T0up + 1e-5, T0step)\n", + " ] # set up a grid of T_0\n", "\n", - " Mdots = [\"%.3f\" % Mdot for Mdot in np.arange(Mdotlow, Mdotup+1e-5, Mdotstep)] #set up a grid of Mdot\n", - " T0s = [\"%i\" % T0 for T0 in np.arange(T0low, T0up+1e-5, T0step)] #set up a grid of T_0\n", - " \n", " chisqs = pd.DataFrame(columns=Mdots, index=T0s, dtype=float)\n", "\n", " for Mdot in Mdots:\n", " for T0 in T0s:\n", " try:\n", - " #read in the converged simulation for this combination of T0 and Mdot by specifying the path\n", - " sim = tools.Sim(Tstrucpath+'parker_'+T0+'_'+Mdot+'/converged')\n", - " #we calculate the model spectrum on a high-resolution grid\n", + " # read in the converged simulation for this combination of T0 and Mdot by specifying the path\n", + " sim = tools.Sim(Tstrucpath + \"parker_\" + T0 + \"_\" + Mdot + \"/converged\")\n", + " # we calculate the model spectrum on a high-resolution grid\n", " highres_wavs = np.linspace(10830, 10836, 100)\n", - " FinFout, lines_found, lines_not_found = RT.FinFout(sim, highres_wavs, 'He', **kwargs)\n", - " #convert to excess absorption in units of %\n", + " FinFout, lines_found, lines_not_found = RT.FinFout(\n", + " sim, highres_wavs, \"He\", **kwargs\n", + " )\n", + " # convert to excess absorption in units of %\n", " model_excess_absorption = (np.max(FinFout) - FinFout) * 100\n", - " #convolve with instrumental resolution, if any was passed\n", + " # convolve with instrumental resolution, if any was passed\n", " if instrument_R is not None:\n", - " model_excess_absorption = RT.convolve_spectrum_R(highres_wavs, model_excess_absorption, instrument_R) #careful - it gets the same variable name\n", - " #resample model to the observed wav points\n", - " model_excess_absorption_ondata = spectres.spectres(observed_wavs, highres_wavs, model_excess_absorption, fill=0., verbose=False)\n", - " #calculate chi squared\n", - " chisq = np.sum(((model_excess_absorption_ondata - observed_ea) / observed_sig_ea)**2)\n", - " #save chisq value in the pandas dataframe\n", + " model_excess_absorption = RT.convolve_spectrum_R(\n", + " highres_wavs, model_excess_absorption, instrument_R\n", + " ) # careful - it gets the same variable name\n", + " # resample model to the observed wav points\n", + " model_excess_absorption_ondata = spectres.spectres(\n", + " observed_wavs,\n", + " highres_wavs,\n", + " model_excess_absorption,\n", + " fill=0.0,\n", + " verbose=False,\n", + " )\n", + " # calculate chi squared\n", + " chisq = np.sum(\n", + " ((model_excess_absorption_ondata - observed_ea) / observed_sig_ea)\n", + " ** 2\n", + " )\n", + " # save chisq value in the pandas dataframe\n", " chisqs.loc[Mdot][T0] = chisq\n", "\n", - " except FileNotFoundError as e: #then this Parker wind model was not calculated\n", + " except (\n", + " FileNotFoundError\n", + " ) as e: # then this Parker wind model was not calculated\n", " pass\n", - " \n", - " except Exception as e: #if something else went wrong\n", + "\n", + " except Exception as e: # if something else went wrong\n", " traceback.print_exc()\n", "\n", " return chisqs\n", "\n", "\n", - "def calc_EWs_He10830(Tstrucpath, \n", - " T0low=2000, T0up=12000, T0step=100,\n", - " Mdotlow=8, Mdotup=12, Mdotstep=0.05,\n", - " **kwargs):\n", - " '''\n", + "def calc_EWs_He10830(\n", + " Tstrucpath,\n", + " T0low=2000,\n", + " T0up=12000,\n", + " T0step=100,\n", + " Mdotlow=8,\n", + " Mdotup=12,\n", + " Mdotstep=0.05,\n", + " **kwargs,\n", + "):\n", + " \"\"\"\n", " Reads in all Parker wind profiles present in the Tstrucpath folder,\n", " calculates the metastable helium line and integrates it to get the EW.\n", - " '''\n", + " \"\"\"\n", + "\n", + " Mdots = [\n", + " \"%.3f\" % Mdot for Mdot in np.arange(Mdotlow, Mdotup + 1e-5, Mdotstep)\n", + " ] # set up a grid of Mdot\n", + " T0s = [\n", + " \"%i\" % T0 for T0 in np.arange(T0low, T0up + 1e-5, T0step)\n", + " ] # set up a grid of T_0\n", "\n", - " Mdots = [\"%.3f\" % Mdot for Mdot in np.arange(Mdotlow, Mdotup+1e-5, Mdotstep)] #set up a grid of Mdot\n", - " T0s = [\"%i\" % T0 for T0 in np.arange(T0low, T0up+1e-5, T0step)] #set up a grid of T_0\n", - " \n", " model_EWs = pd.DataFrame(columns=Mdots, index=T0s, dtype=float)\n", "\n", " for Mdot in Mdots:\n", " for T0 in T0s:\n", " try:\n", - " #read in the converged simulation for this combination of T0 and Mdot by specifying the path\n", - " sim = tools.Sim(Tstrucpath+'parker_'+T0+'_'+Mdot+'/converged')\n", - " #set up the wavelength array in vacuum angstrom units\n", + " # read in the converged simulation for this combination of T0 and Mdot by specifying the path\n", + " sim = tools.Sim(Tstrucpath + \"parker_\" + T0 + \"_\" + Mdot + \"/converged\")\n", + " # set up the wavelength array in vacuum angstrom units\n", " wavs = np.logspace(np.log10(10831), np.log10(10835), num=100)\n", - " #run the radiative transfer (to check if all lines were calculated, print lines_found)\n", - " FinFout, lines_found, lines_not_found = RT.FinFout(sim, wavs, 'He', **kwargs)\n", - " #convert from Fin/Fout to excess absorption - this assumes we reach the continuum somewhere\n", + " # run the radiative transfer (to check if all lines were calculated, print lines_found)\n", + " FinFout, lines_found, lines_not_found = RT.FinFout(\n", + " sim, wavs, \"He\", **kwargs\n", + " )\n", + " # convert from Fin/Fout to excess absorption - this assumes we reach the continuum somewhere\n", " absorption = np.max(FinFout) - FinFout\n", - " #integrate to get EW\n", + " # integrate to get EW\n", " EW = trapezoid(absorption, x=wavs)\n", - " #save EW value in the pandas dataframe\n", + " # save EW value in the pandas dataframe\n", " model_EWs.loc[Mdot][T0] = EW\n", - " \n", - " except FileNotFoundError as e: #then this Parker wind model was not calculated\n", + "\n", + " except (\n", + " FileNotFoundError\n", + " ) as e: # then this Parker wind model was not calculated\n", " pass\n", - " \n", - " except Exception as e: #if something else went wrong\n", + "\n", + " except Exception as e: # if something else went wrong\n", " traceback.print_exc()\n", "\n", " return model_EWs\n", "\n", "\n", "def metaHe_weighted_T(sim):\n", - " '''\n", + " \"\"\"\n", " Calculates the mean temperature and its standard devation of the atmosphere weighted by\n", " the metastable helium number density (Eq. 4 & 5 in Linssen et al. 2022).\n", - " '''\n", - " \n", - " #in Cloudy, not all bins have the same thickness, so we must compensate for that to do a fair weighting\n", - " bin_thickness = np.diff(np.insert(sim.den.depth.values, 0, 0.))\n", - " #the metastable helium state is the second lowest energy level and thus stored in the He[2] column of the density file\n", - " T_He = np.sum(sim.ovr.Te.values * sim.den['He[2]'].values * bin_thickness) / np.sum(sim.den['He[2]'].values * bin_thickness)\n", - " sigmaT = np.sqrt( np.sum(sim.den['He[2]'].values * bin_thickness * (sim.ovr.Te.values - T_He)**2) / np.sum(sim.den['He[2]'].values * bin_thickness) )\n", - " \n", + " \"\"\"\n", + "\n", + " # in Cloudy, not all bins have the same thickness, so we must compensate for that to do a fair weighting\n", + " bin_thickness = np.diff(np.insert(sim.den.depth.values, 0, 0.0))\n", + " # the metastable helium state is the second lowest energy level and thus stored in the He[2] column of the density file\n", + " T_He = np.sum(sim.ovr.Te.values * sim.den[\"He[2]\"].values * bin_thickness) / np.sum(\n", + " sim.den[\"He[2]\"].values * bin_thickness\n", + " )\n", + " sigmaT = np.sqrt(\n", + " np.sum(\n", + " sim.den[\"He[2]\"].values * bin_thickness * (sim.ovr.Te.values - T_He) ** 2\n", + " )\n", + " / np.sum(sim.den[\"He[2]\"].values * bin_thickness)\n", + " )\n", + "\n", " return T_He, sigmaT\n", "\n", "\n", - "def calc_dT_helium(Tstrucpath,\n", - " T0low=2000, T0up=12000, T0step=100,\n", - " Mdotlow=8, Mdotup=12, Mdotstep=0.05):\n", - " '''\n", + "def calc_dT_helium(\n", + " Tstrucpath, T0low=2000, T0up=12000, T0step=100, Mdotlow=8, Mdotup=12, Mdotstep=0.05\n", + "):\n", + " \"\"\"\n", " Reads in all Parker wind profiles present in the Tstrucpath folder,\n", " calculates the mean temperature weighted by the metastable helium density\n", " and its standard deviation. Calculates the temperature difference between\n", - " the isothermal value and the He-weighted value, which can be used as \n", + " the isothermal value and the He-weighted value, which can be used as\n", " a measure of model self-consistency.\n", - " '''\n", - " \n", - " Mdots = [\"%.3f\" % Mdot for Mdot in np.arange(Mdotlow, Mdotup+1e-5, Mdotstep)] #set up a grid of Mdot\n", - " T0s = [\"%i\" % T0 for T0 in np.arange(T0low, T0up+1e-5, T0step)] #set up a grid of T_0\n", + " \"\"\"\n", + "\n", + " Mdots = [\n", + " \"%.3f\" % Mdot for Mdot in np.arange(Mdotlow, Mdotup + 1e-5, Mdotstep)\n", + " ] # set up a grid of Mdot\n", + " T0s = [\n", + " \"%i\" % T0 for T0 in np.arange(T0low, T0up + 1e-5, T0step)\n", + " ] # set up a grid of T_0\n", "\n", - " T_He = pd.DataFrame(columns=Mdots, index=T0s, dtype=float) #stores the weighted T\n", - " sigmaT = T_He.copy() #stores standard deviation of T(r) around T_He\n", - " dT = T_He.copy() #stores T_He - isothermal T\n", + " T_He = pd.DataFrame(columns=Mdots, index=T0s, dtype=float) # stores the weighted T\n", + " sigmaT = T_He.copy() # stores standard deviation of T(r) around T_He\n", + " dT = T_He.copy() # stores T_He - isothermal T\n", "\n", " for Mdot in Mdots:\n", " for T0 in T0s:\n", " try:\n", - " sim = tools.Sim(Tstrucpath+'/parker_'+T0+'_'+Mdot+'/converged') #load the converged simulation\n", - " ClT, ClsigmaT = metaHe_weighted_T(sim) #find the T_He and sigT_He for this simulation\n", + " sim = tools.Sim(\n", + " Tstrucpath + \"/parker_\" + T0 + \"_\" + Mdot + \"/converged\"\n", + " ) # load the converged simulation\n", + " ClT, ClsigmaT = metaHe_weighted_T(\n", + " sim\n", + " ) # find the T_He and sigT_He for this simulation\n", " T_He.loc[Mdot][T0] = ClT\n", " sigmaT.loc[Mdot][T0] = ClsigmaT\n", " dT.loc[Mdot][T0] = ClT - int(T0)\n", "\n", - " except FileNotFoundError: #then this profile was not calculated\n", + " except FileNotFoundError: # then this profile was not calculated\n", " pass\n", - " \n", + "\n", " return dT, sigmaT\n", "\n", "\n", "### Functions that calculate the Bayesian terms ###\n", "\n", + "\n", "def calc_likelihood_resolved(chisq_fit):\n", - " '''\n", + " \"\"\"\n", " Calculates the likelihood of a spectrally resolved fit to data,\n", " based on the chi-squared value.\n", "\n", " See e.g. https://philuttley.github.io/statistical-inference/10-mle_model_fitting/index.html\n", " for how the chi-squared statistic relates to the likelihood.\n", - " '''\n", + " \"\"\"\n", "\n", - " likelihood = np.exp(-chisq_fit.values / 2.)\n", + " likelihood = np.exp(-chisq_fit.values / 2.0)\n", + "\n", + " likelihood = pd.DataFrame(\n", + " columns=chisq_fit.columns.values,\n", + " index=chisq_fit.index.values,\n", + " data=likelihood,\n", + " dtype=float,\n", + " ) # turn into pd.DataFrame\n", "\n", - " likelihood = pd.DataFrame(columns=chisq_fit.columns.values, index=chisq_fit.index.values, \n", - " data=likelihood, dtype=float) #turn into pd.DataFrame\n", - " \n", " return likelihood\n", "\n", "\n", "def calc_likelihood_unresolved(nsig_fit):\n", - " '''\n", + " \"\"\"\n", " Calculates the likelihood of spectrally unresolved data,\n", - " expects a pandas dataframe that stores the number of \n", + " expects a pandas dataframe that stores the number of\n", " errorbars difference between model and data.\n", - " '''\n", + " \"\"\"\n", "\n", " likelihood = sps.norm.pdf(nsig_fit.abs())\n", "\n", - " likelihood = pd.DataFrame(columns=nsig_fit.columns.values, index=nsig_fit.index.values, \n", - " data=likelihood, dtype=float) #turn into pd.DataFrame\n", - " \n", + " likelihood = pd.DataFrame(\n", + " columns=nsig_fit.columns.values,\n", + " index=nsig_fit.index.values,\n", + " data=likelihood,\n", + " dtype=float,\n", + " ) # turn into pd.DataFrame\n", + "\n", " return likelihood\n", "\n", "\n", "def calc_prior(dT, sigmaT):\n", - " '''\n", + " \"\"\"\n", " Calculates a prior based on the model temperature self-consistency.\n", " See Linssen et al. (2022) for details on the choice of prior evaluation.\n", - " '''\n", + " \"\"\"\n", "\n", - " #check that dT and sigmaT are defined on the same T-Mdot grid\n", - " assert np.array_equal(dT.index.values, sigmaT.index.values), \"Different temperature grids.\"\n", - " assert np.array_equal(dT.columns.values, sigmaT.columns.values), \"Different mass-loss rate grids.\"\n", + " # check that dT and sigmaT are defined on the same T-Mdot grid\n", + " assert np.array_equal(\n", + " dT.index.values, sigmaT.index.values\n", + " ), \"Different temperature grids.\"\n", + " assert np.array_equal(\n", + " dT.columns.values, sigmaT.columns.values\n", + " ), \"Different mass-loss rate grids.\"\n", "\n", " T0grid = dT.index.values.astype(float)\n", " Mdotgrid = dT.columns.values.astype(float)\n", "\n", - " #assume prior is a normal distribution around dT=0 with std dev sigmaT\n", + " # assume prior is a normal distribution around dT=0 with std dev sigmaT\n", " number_sigma = dT / sigmaT\n", " prior = sps.norm.pdf(number_sigma)\n", - " #now normalize the prior\n", - " prior[np.isnan(prior)] = 0.\n", + " # now normalize the prior\n", + " prior[np.isnan(prior)] = 0.0\n", " prior_sum = trapezoid(trapezoid(prior, axis=1, x=Mdotgrid), x=T0grid)\n", " prior = prior / prior_sum\n", "\n", - " prior = pd.DataFrame(columns=dT.columns.values, index=dT.index.values, \n", - " data=prior, dtype=float) #turn into pd.DataFrame\n", - " \n", + " prior = pd.DataFrame(\n", + " columns=dT.columns.values, index=dT.index.values, data=prior, dtype=float\n", + " ) # turn into pd.DataFrame\n", + "\n", " return prior\n", "\n", "\n", "def calc_posterior(prior, likelihood):\n", - " '''\n", + " \"\"\"\n", " Combines the prior from the T0-T_He analysis with the likelihoods\n", " from the data fit with Bayes' theorem to calculate the posterior.\n", - " '''\n", + " \"\"\"\n", "\n", " if isinstance(prior, pd.DataFrame):\n", - " #check that the prior and likelihoods are defined on the same T-Mdot grid\n", - " assert np.array_equal(prior.index.values, likelihood.index.values), \"Different temperature grids.\"\n", - " assert np.array_equal(prior.columns.values, likelihood.columns.values), \"Different mass-loss rate grids.\"\n", + " # check that the prior and likelihoods are defined on the same T-Mdot grid\n", + " assert np.array_equal(\n", + " prior.index.values, likelihood.index.values\n", + " ), \"Different temperature grids.\"\n", + " assert np.array_equal(\n", + " prior.columns.values, likelihood.columns.values\n", + " ), \"Different mass-loss rate grids.\"\n", "\n", " T0grid = likelihood.index.values.astype(float)\n", " Mdotgrid = likelihood.columns.values.astype(float)\n", "\n", - " integrand = prior*likelihood\n", - " integrand[np.isnan(integrand)] = 0.\n", + " integrand = prior * likelihood\n", + " integrand[np.isnan(integrand)] = 0.0\n", " evidence = trapezoid(trapezoid(integrand, axis=1, x=Mdotgrid), x=T0grid)\n", " posterior = integrand / evidence\n", "\n", - " posterior = pd.DataFrame(columns=likelihood.columns.values, index=likelihood.index.values, \n", - " data=posterior, dtype=float) #turn into pd.DataFrame\n", + " posterior = pd.DataFrame(\n", + " columns=likelihood.columns.values,\n", + " index=likelihood.index.values,\n", + " data=posterior,\n", + " dtype=float,\n", + " ) # turn into pd.DataFrame\n", "\n", - "\n", - " #calculate marginalized posteriors\n", + " # calculate marginalized posteriors\n", " post_Mdot = trapezoid(posterior.values, axis=0, x=T0grid)\n", " post_T0 = trapezoid(posterior.values, axis=1, x=Mdotgrid)\n", "\n", @@ -392,7 +543,9 @@ " lowsig_Mdot = Mdotgrid[np.argmax(post_Mdot_cum > 0.16)]\n", " mid_Mdot = Mdotgrid[np.argmin(np.abs(post_Mdot_cum - 0.5)) + 1]\n", " upsig_Mdot = Mdotgrid[np.argmax(post_Mdot_cum > 0.84) + 1]\n", - " print(\"Constraints from marginalized posteriors (not necessarily normally distributed!):\")\n", + " print(\n", + " \"Constraints from marginalized posteriors (not necessarily normally distributed!):\"\n", + " )\n", " print(f\"log10(Mdot) = {mid_Mdot} + {upsig_Mdot-mid_Mdot} - {mid_Mdot-lowsig_Mdot}\")\n", "\n", " post_T0_cum = cumulative_trapezoid(post_T0, x=T0grid)\n", @@ -401,45 +554,61 @@ " upsig_T0 = T0grid[np.argmax(post_T0_cum > 0.84) + 1]\n", " print(f\"T0 = {mid_T0} + {upsig_T0-mid_T0} - {mid_T0-lowsig_T0}\")\n", "\n", - "\n", " return posterior\n", "\n", "\n", - "### Functions that plot stuff ###\n", + "# Functions that plot stuff\n", "\n", - "def plot_chisq_fit(chisq_fit,\n", - " dof=None, bounds_T0=None, bounds_Mdot=None,\n", - " title=None, save=None, fig=None, ax=None):\n", - " '''\n", + "\n", + "def plot_chisq_fit(\n", + " chisq_fit,\n", + " dof=None,\n", + " bounds_T0=None,\n", + " bounds_Mdot=None,\n", + " title=None,\n", + " save=None,\n", + " fig=None,\n", + " ax=None,\n", + "):\n", + " \"\"\"\n", " Makes a standard plot of the Parker wind models fitted to the data.\n", " In this case, we fit the resolved line shape, and\n", " the colormap shows the chi squared statistic.\n", - " '''\n", + " \"\"\"\n", "\n", - " pixT = float(chisq_fit.index[1])-float(chisq_fit.index[0]) #T step size\n", - " pixM = float(chisq_fit.columns[1]) - float(chisq_fit.columns[0]) #Mdot step size\n", + " pixT = float(chisq_fit.index[1]) - float(chisq_fit.index[0]) # T step size\n", + " pixM = float(chisq_fit.columns[1]) - float(chisq_fit.columns[0]) # Mdot step size\n", "\n", - " if dof != None: #then we assume you want to plot the reduced chi squared\n", + " if dof != None: # then we assume you want to plot the reduced chi squared\n", " plotted_vals = chisq_fit / dof\n", - " cbar_label = r'Reduced $\\chi ^2$'\n", + " cbar_label = r\"Reduced $\\chi ^2$\"\n", " else:\n", " plotted_vals = chisq_fit\n", - " cbar_label = r'$\\chi ^2$'\n", + " cbar_label = r\"$\\chi ^2$\"\n", "\n", - " \n", " if fig == None and ax == None:\n", " _showplot = True\n", " fig, ax = plt.subplots(1)\n", " else:\n", " _showplot = False\n", "\n", - " im = ax.imshow(plotted_vals.T, cmap='Blues_r', norm=matplotlib.colors.LogNorm(), \n", - " origin='lower', aspect='auto', interpolation='none',\n", - " extent=[float(chisq_fit.index[0])-0.5*pixT, float(chisq_fit.index[-1])+0.5*pixT, \n", - " float(chisq_fit.columns[0])-0.5*pixM, float(chisq_fit.columns[-1])+0.5*pixM])\n", - " ax.set_facecolor('grey')\n", - " ax.set_xlabel(r'$T_0$ [K]')\n", - " ax.set_ylabel(r'log$_{10}$($\\dot{M}$ [g s$^{-1}$])')\n", + " im = ax.imshow(\n", + " plotted_vals.T,\n", + " cmap=\"Blues_r\",\n", + " norm=matplotlib.colors.LogNorm(),\n", + " origin=\"lower\",\n", + " aspect=\"auto\",\n", + " interpolation=\"none\",\n", + " extent=[\n", + " float(chisq_fit.index[0]) - 0.5 * pixT,\n", + " float(chisq_fit.index[-1]) + 0.5 * pixT,\n", + " float(chisq_fit.columns[0]) - 0.5 * pixM,\n", + " float(chisq_fit.columns[-1]) + 0.5 * pixM,\n", + " ],\n", + " )\n", + " ax.set_facecolor(\"grey\")\n", + " ax.set_xlabel(r\"$T_0$ [K]\")\n", + " ax.set_ylabel(r\"log$_{10}$($\\dot{M}$ [g s$^{-1}$])\")\n", " fig.colorbar(im, label=cbar_label)\n", " if title != None:\n", " ax.set_title(title)\n", @@ -448,24 +617,25 @@ " if bounds_Mdot != None:\n", " ax.set_ylim(*bounds_Mdot)\n", " if save != None:\n", - " plt.savefig(save, bbox_inches='tight', dpi=300)\n", + " plt.savefig(save, bbox_inches=\"tight\", dpi=300)\n", " if _showplot:\n", " plt.show()\n", "\n", "\n", - "def plot_nsig_fit(nsig_fit, bounds_T0=None, bounds_Mdot=None,\n", - " title=None, save=None, fig=None, ax=None):\n", - " '''\n", + "def plot_nsig_fit(\n", + " nsig_fit, bounds_T0=None, bounds_Mdot=None, title=None, save=None, fig=None, ax=None\n", + "):\n", + " \"\"\"\n", " Makes a standard plot of the Parker wind models fitted to the data.\n", " In this case, we fit the EW of the model to the EW of the data, and\n", " the colormap simply indicates how many data errorbars difference there is.\n", - " '''\n", - " \n", - " cmap = plt.get_cmap('Blues_r')\n", + " \"\"\"\n", + "\n", + " cmap = plt.get_cmap(\"Blues_r\")\n", " normalize = matplotlib.colors.Normalize(vmin=0, vmax=5)\n", "\n", - " pixT = float(nsig_fit.index[1]) - float(nsig_fit.index[0]) #T step size\n", - " pixM = float(nsig_fit.columns[1]) - float(nsig_fit.columns[0]) #Mdot step size\n", + " pixT = float(nsig_fit.index[1]) - float(nsig_fit.index[0]) # T step size\n", + " pixM = float(nsig_fit.columns[1]) - float(nsig_fit.columns[0]) # Mdot step size\n", "\n", " if fig == None and ax == None:\n", " _showplot = True\n", @@ -473,13 +643,24 @@ " else:\n", " _showplot = False\n", "\n", - " im = ax.imshow(nsig_fit.T.abs(), cmap=cmap, norm=normalize, origin='lower', aspect='auto', interpolation='none',\n", - " extent=[float(nsig_fit.index[0])-0.5*pixT, float(nsig_fit.index[-1])+0.5*pixT, \n", - " float(nsig_fit.columns[0])-0.5*pixM, float(nsig_fit.columns[-1])+0.5*pixM])\n", - " ax.set_facecolor('grey')\n", - " ax.set_xlabel(r'$T_0$ [K]')\n", - " ax.set_ylabel(r'log$_{10}$($\\dot{M}$ [g s$^{-1}$])')\n", - " fig.colorbar(im, label=r'$\\Delta\\sigma$')\n", + " im = ax.imshow(\n", + " nsig_fit.T.abs(),\n", + " cmap=cmap,\n", + " norm=normalize,\n", + " origin=\"lower\",\n", + " aspect=\"auto\",\n", + " interpolation=\"none\",\n", + " extent=[\n", + " float(nsig_fit.index[0]) - 0.5 * pixT,\n", + " float(nsig_fit.index[-1]) + 0.5 * pixT,\n", + " float(nsig_fit.columns[0]) - 0.5 * pixM,\n", + " float(nsig_fit.columns[-1]) + 0.5 * pixM,\n", + " ],\n", + " )\n", + " ax.set_facecolor(\"grey\")\n", + " ax.set_xlabel(r\"$T_0$ [K]\")\n", + " ax.set_ylabel(r\"log$_{10}$($\\dot{M}$ [g s$^{-1}$])\")\n", + " fig.colorbar(im, label=r\"$\\Delta\\sigma$\")\n", " if title != None:\n", " ax.set_title(title)\n", " if bounds_T0 != None:\n", @@ -487,45 +668,62 @@ " if bounds_Mdot != None:\n", " ax.set_ylim(*bounds_Mdot)\n", " if save != None:\n", - " plt.savefig(save, bbox_inches='tight', dpi=300)\n", + " plt.savefig(save, bbox_inches=\"tight\", dpi=300)\n", " if _showplot:\n", " plt.show()\n", "\n", "\n", - "def plot_selfcons(dT, sigmaT,\n", - " bounds_T0=None, bounds_Mdot=None,\n", - " title=None, fig=None, ax=None):\n", - " '''\n", + "def plot_selfcons(\n", + " dT, sigmaT, bounds_T0=None, bounds_Mdot=None, title=None, fig=None, ax=None\n", + "):\n", + " \"\"\"\n", " Makes a standard plot of the self-consistency of the Parker wind parameter space.\n", " Self-consistent models are white, while blue/red models indicate models for which\n", " Cloudy indicates that the temperature in the helium line-forming region is\n", " cooler/hotter than that assumed in creating the isothermal profiles, respectively.\n", - " The dotted lines indicate 1 standard deviation discrepancy. \n", - " '''\n", - " \n", - " cmap = truncate_colormap(plt.get_cmap('seismic'), 0.2, 0.8)\n", + " The dotted lines indicate 1 standard deviation discrepancy.\n", + " \"\"\"\n", + "\n", + " cmap = truncate_colormap(plt.get_cmap(\"seismic\"), 0.2, 0.8)\n", " normalize = matplotlib.colors.Normalize(vmin=-4000, vmax=4000)\n", "\n", - " pixT = float(dT.index[1])-float(dT.index[0]) #T step size\n", - " pixM = float(dT.columns[1]) - float(dT.columns[0]) #Mdot step size\n", + " pixT = float(dT.index[1]) - float(dT.index[0]) # T step size\n", + " pixM = float(dT.columns[1]) - float(dT.columns[0]) # Mdot step size\n", "\n", - " \n", " if fig == None and ax == None:\n", " _showplot = True\n", " fig, ax = plt.subplots(1)\n", " else:\n", " _showplot = False\n", "\n", - " im = ax.imshow(dT.T, cmap=cmap, norm=normalize, origin='lower', aspect='auto', interpolation='none',\n", - " extent=[float(dT.index[0])-0.5*pixT, float(dT.index[-1])+0.5*pixT, \n", - " float(dT.columns[0])-0.5*pixM, float(dT.columns[-1])+0.5*pixM])\n", - " #plot the 1 sigma line (i.e. dT = sigmaT)\n", - " sig1lines = ax.contour(dT.index.astype(float), dT.columns.astype(float), (dT / sigmaT).T, \n", - " levels=[-1,1], zorder=1, colors='black', linestyles='dotted')\n", - " ax.set_facecolor('grey')\n", - " ax.set_xlabel(r'$T_0$ [K]')\n", - " ax.set_ylabel(r'log$_{10}$($\\dot{M}$ [g s$^{-1}$])')\n", - " fig.colorbar(im, label=r'$T_{He} - T_0$ [K]')\n", + " im = ax.imshow(\n", + " dT.T,\n", + " cmap=cmap,\n", + " norm=normalize,\n", + " origin=\"lower\",\n", + " aspect=\"auto\",\n", + " interpolation=\"none\",\n", + " extent=[\n", + " float(dT.index[0]) - 0.5 * pixT,\n", + " float(dT.index[-1]) + 0.5 * pixT,\n", + " float(dT.columns[0]) - 0.5 * pixM,\n", + " float(dT.columns[-1]) + 0.5 * pixM,\n", + " ],\n", + " )\n", + " # plot the 1 sigma line (i.e. dT = sigmaT)\n", + " sig1lines = ax.contour(\n", + " dT.index.astype(float),\n", + " dT.columns.astype(float),\n", + " (dT / sigmaT).T,\n", + " levels=[-1, 1],\n", + " zorder=1,\n", + " colors=\"black\",\n", + " linestyles=\"dotted\",\n", + " )\n", + " ax.set_facecolor(\"grey\")\n", + " ax.set_xlabel(r\"$T_0$ [K]\")\n", + " ax.set_ylabel(r\"log$_{10}$($\\dot{M}$ [g s$^{-1}$])\")\n", + " fig.colorbar(im, label=r\"$T_{He} - T_0$ [K]\")\n", " if title != None:\n", " ax.set_title(title)\n", " if bounds_T0 != None:\n", @@ -536,22 +734,22 @@ " plt.show()\n", "\n", "\n", - "def plot_posterior(posterior,\n", - " bounds_T0=None, bounds_Mdot=None,\n", - " title=None, save=None, log=False):\n", - " '''\n", + "def plot_posterior(\n", + " posterior, bounds_T0=None, bounds_Mdot=None, title=None, save=None, log=False\n", + "):\n", + " \"\"\"\n", " Plots the posterior distribution and the marginalized distributions.\n", " Prints the 1 sigma confidence intervals, at the precision of the T0/Mdot-grid.\n", - " '''\n", + " \"\"\"\n", "\n", " T0grid = posterior.index.values.astype(float)\n", " Mdotgrid = posterior.columns.values.astype(float)\n", " post = posterior.values\n", - " \n", - " pixT = np.diff(T0grid)[0] #T step size\n", - " pixM = np.diff(Mdotgrid)[0] #Mdot step size\n", "\n", - " #calculate marginalized posteriors\n", + " pixT = np.diff(T0grid)[0] # T step size\n", + " pixM = np.diff(Mdotgrid)[0] # Mdot step size\n", + "\n", + " # calculate marginalized posteriors\n", " post_Mdot = trapezoid(post, axis=0, x=T0grid)\n", " post_T0 = trapezoid(post, axis=1, x=Mdotgrid)\n", "\n", @@ -565,40 +763,57 @@ " mid_T0 = T0grid[np.argmin(np.abs(post_T0_cum - 0.5)) + 1]\n", " upsig_T0 = T0grid[np.argmax(post_T0_cum > 0.84) + 1]\n", "\n", - "\n", " fig = plt.figure(figsize=(5, 5))\n", - " gs = fig.add_gridspec(2, 2, width_ratios=(3, 1), height_ratios=(1, 3),\n", - " left=0.1, right=0.9, bottom=0.1, top=0.9,\n", - " wspace=0.05, hspace=0.05)\n", + " gs = fig.add_gridspec(\n", + " 2,\n", + " 2,\n", + " width_ratios=(3, 1),\n", + " height_ratios=(1, 3),\n", + " left=0.1,\n", + " right=0.9,\n", + " bottom=0.1,\n", + " top=0.9,\n", + " wspace=0.05,\n", + " hspace=0.05,\n", + " )\n", " ax = fig.add_subplot(gs[1, 0])\n", " ax_T0 = fig.add_subplot(gs[0, 0])\n", " ax_Mdot = fig.add_subplot(gs[1, 1])\n", "\n", - " im = ax.imshow(post.T, cmap=plt.get_cmap('Greys'), origin='lower', aspect='auto', interpolation='none',\n", - " extent=[T0grid[0]-0.5*pixT, T0grid[-1]+0.5*pixT, \n", - " Mdotgrid[0]-0.5*pixM, Mdotgrid[-1]+0.5*pixM])\n", + " im = ax.imshow(\n", + " post.T,\n", + " cmap=plt.get_cmap(\"Greys\"),\n", + " origin=\"lower\",\n", + " aspect=\"auto\",\n", + " interpolation=\"none\",\n", + " extent=[\n", + " T0grid[0] - 0.5 * pixT,\n", + " T0grid[-1] + 0.5 * pixT,\n", + " Mdotgrid[0] - 0.5 * pixM,\n", + " Mdotgrid[-1] + 0.5 * pixM,\n", + " ],\n", + " )\n", " if log:\n", " im.set_norm(matplotlib.colors.LogNorm())\n", - " ax_T0.plot(T0grid, post_T0, color='k')\n", - " ax_Mdot.plot(post_Mdot, Mdotgrid, color='k')\n", - "\n", + " ax_T0.plot(T0grid, post_T0, color=\"k\")\n", + " ax_Mdot.plot(post_Mdot, Mdotgrid, color=\"k\")\n", "\n", - " ax_T0.axvline(mid_T0, color='blue', linewidth=0.7)\n", - " ax_T0.axvline(lowsig_T0, color='blue', linewidth=0.7, linestyle='dotted')\n", - " ax_T0.axvline(upsig_T0, color='blue', linewidth=0.7, linestyle='dotted')\n", - " ax_Mdot.axhline(mid_Mdot, color='blue', linewidth=0.7)\n", - " ax_Mdot.axhline(lowsig_Mdot, color='blue', linewidth=0.7, linestyle='dotted')\n", - " ax_Mdot.axhline(upsig_Mdot, color='blue', linewidth=0.7, linestyle='dotted')\n", + " ax_T0.axvline(mid_T0, color=\"blue\", linewidth=0.7)\n", + " ax_T0.axvline(lowsig_T0, color=\"blue\", linewidth=0.7, linestyle=\"dotted\")\n", + " ax_T0.axvline(upsig_T0, color=\"blue\", linewidth=0.7, linestyle=\"dotted\")\n", + " ax_Mdot.axhline(mid_Mdot, color=\"blue\", linewidth=0.7)\n", + " ax_Mdot.axhline(lowsig_Mdot, color=\"blue\", linewidth=0.7, linestyle=\"dotted\")\n", + " ax_Mdot.axhline(upsig_Mdot, color=\"blue\", linewidth=0.7, linestyle=\"dotted\")\n", "\n", " ax_T0.set_xticks([])\n", " ax_T0.set_yticks([])\n", " ax_Mdot.set_xticks([])\n", " ax_Mdot.set_yticks([])\n", "\n", - " ax.set_xlim(T0grid[0]-0.5*pixT, T0grid[-1]+0.5*pixT)\n", - " ax_T0.set_xlim(T0grid[0]-0.5*pixT, T0grid[-1]+0.5*pixT)\n", - " ax.set_ylim(Mdotgrid[0]-0.5*pixM, Mdotgrid[-1]+0.5*pixM)\n", - " ax_Mdot.set_ylim(Mdotgrid[0]-0.5*pixM, Mdotgrid[-1]+0.5*pixM)\n", + " ax.set_xlim(T0grid[0] - 0.5 * pixT, T0grid[-1] + 0.5 * pixT)\n", + " ax_T0.set_xlim(T0grid[0] - 0.5 * pixT, T0grid[-1] + 0.5 * pixT)\n", + " ax.set_ylim(Mdotgrid[0] - 0.5 * pixM, Mdotgrid[-1] + 0.5 * pixM)\n", + " ax_Mdot.set_ylim(Mdotgrid[0] - 0.5 * pixM, Mdotgrid[-1] + 0.5 * pixM)\n", " if bounds_T0 != None:\n", " ax_T0.set_xlim(*bounds_T0)\n", " ax.set_xlim(*bounds_T0)\n", @@ -606,113 +821,153 @@ " ax_Mdot.set_ylim(*bounds_Mdot)\n", " ax.set_ylim(*bounds_Mdot)\n", "\n", - " ax.set_xlabel(r'$T_0$ [K]')\n", - " ax.set_ylabel(r'log$_{10}$($\\dot{M}$ [g s$^{-1}$])')\n", + " ax.set_xlabel(r\"$T_0$ [K]\")\n", + " ax.set_ylabel(r\"log$_{10}$($\\dot{M}$ [g s$^{-1}$])\")\n", " if title != None:\n", " ax_T0.set_title(title)\n", "\n", " if save != None:\n", - " plt.savefig(save, bbox_inches='tight', dpi=300)\n", + " plt.savefig(save, bbox_inches=\"tight\", dpi=300)\n", " plt.show()\n", "\n", "\n", - "def plot_joint_constraint_resolved(dT, sigmaT, chisq_fit, posterior, \n", - " bounds_T0=None, bounds_Mdot=None, \n", - " title=None, save=None, fig=None, ax=None, \n", - " post_uptosigma=1, cmap_T=None,\n", - " cmap_fit=None, show_colorbar=True):\n", - " '''\n", - " Makes a standard plot of the posterior distribution, \n", + "def plot_joint_constraint_resolved(\n", + " dT,\n", + " sigmaT,\n", + " chisq_fit,\n", + " posterior,\n", + " bounds_T0=None,\n", + " bounds_Mdot=None,\n", + " title=None,\n", + " save=None,\n", + " fig=None,\n", + " ax=None,\n", + " post_uptosigma=1,\n", + " cmap_T=None,\n", + " cmap_fit=None,\n", + " show_colorbar=True,\n", + "):\n", + " \"\"\"\n", + " Makes a standard plot of the posterior distribution,\n", " on top of the prior (self-consistency) and likelihood (data fit) constraints.\n", " Also prints out the 1sigma bounds on T and Mdot.\n", "\n", " chisq_fit must be given, but dT, sigmaT and posterior can be passed as None\n", " if they should not be plotted.\n", - " '''\n", + " \"\"\"\n", "\n", - " assert post_uptosigma <=3, \"Maximum value of post_uptosigma is 3\"\n", + " assert post_uptosigma <= 3, \"Maximum value of post_uptosigma is 3\"\n", "\n", " if cmap_T is None:\n", - " cmap_T = truncate_colormap(plt.get_cmap('autumn'), 0.35, 0.65)\n", + " cmap_T = truncate_colormap(plt.get_cmap(\"autumn\"), 0.35, 0.65)\n", " if cmap_fit is None:\n", - " cmap_fit = truncate_colormap(plt.get_cmap('winter_r'), 0.35, 0.65)\n", - " \n", + " cmap_fit = truncate_colormap(plt.get_cmap(\"winter_r\"), 0.35, 0.65)\n", "\n", " if fig == None and ax == None:\n", " showplot = True\n", " fig, ax = plt.subplots(1)\n", " else:\n", " showplot = False\n", - " \n", - " #### Plot the model temperature discrepancy (i.e. prior)\n", + "\n", + " # Plot the model temperature discrepancy (i.e. prior)\n", " if dT is not None and sigmaT is not None:\n", " nsig_T = dT / sigmaT\n", "\n", " x, y, z = get_xyz(nsig_T)\n", "\n", - " ax.tricontour(x, y, z, cmap=cmap_T, levels=[0], zorder=0) #plots the orange line\n", - " prior_contour = ax.tricontourf(x, y, np.abs(z), cmap=cmap_T, levels=[0,1,2], alpha=0.5, zorder=0) #plots the orange contours\n", - " \n", - " \n", - " #### Plot the fit constraints (i.e. likelihood):\n", + " ax.tricontour(\n", + " x, y, z, cmap=cmap_T, levels=[0], zorder=0\n", + " ) # plots the orange line\n", + " prior_contour = ax.tricontourf(\n", + " x, y, np.abs(z), cmap=cmap_T, levels=[0, 1, 2], alpha=0.5, zorder=0\n", + " ) # plots the orange contours\n", + "\n", + " # Plot the fit constraints (i.e. likelihood):\n", " likelihood = calc_likelihood_resolved(chisq_fit)\n", - " likelihood = likelihood.fillna(0.)\n", + " likelihood = likelihood.fillna(0.0)\n", " highest_likelihood = likelihood.max().max()\n", - " sigma1_likelihood = highest_likelihood * np.exp(-1/2)\n", - " sigma2_likelihood = highest_likelihood * np.exp(-4/2)\n", - " sigma3_likelihood = highest_likelihood * np.exp(-9/2)\n", - " \n", + " sigma1_likelihood = highest_likelihood * np.exp(-1 / 2)\n", + " sigma2_likelihood = highest_likelihood * np.exp(-4 / 2)\n", + " sigma3_likelihood = highest_likelihood * np.exp(-9 / 2)\n", + "\n", " x, y, z = get_xyz(likelihood)\n", - " \n", - " likelihood_contour = ax.tricontourf(x, y, z, cmap=cmap_fit, levels=[sigma2_likelihood, sigma1_likelihood, highest_likelihood], alpha=0.5, zorder=1) #plots the blue contours\n", - " \n", - " \n", - " #### Plot the posterior\n", + "\n", + " likelihood_contour = ax.tricontourf(\n", + " x,\n", + " y,\n", + " z,\n", + " cmap=cmap_fit,\n", + " levels=[sigma2_likelihood, sigma1_likelihood, highest_likelihood],\n", + " alpha=0.5,\n", + " zorder=1,\n", + " ) # plots the blue contours\n", + "\n", + " # Plot the posterior\n", " if posterior is not None and post_uptosigma > 0:\n", - " #calculate the posterior values that corresponds to the 1,2,3 sigma contours\n", + " # calculate the posterior values that corresponds to the 1,2,3 sigma contours\n", " posterior_sorted = np.sort(posterior.values.flatten())[::-1]\n", " posterior_sum = np.sum(posterior_sorted)\n", " posterior_cumsum = np.cumsum(posterior_sorted)\n", " p1sigma = posterior_sorted[posterior_cumsum > 0.3935 * posterior_sum][0]\n", " p2sigma = posterior_sorted[posterior_cumsum > 0.8647 * posterior_sum][0]\n", " p3sigma = posterior_sorted[posterior_cumsum > 0.9889 * posterior_sum][0]\n", - " post_levels = [p3sigma, p2sigma, p1sigma][3-post_uptosigma:]\n", - " post_linestyles = ['dotted', 'dashed', 'solid'][3-post_uptosigma:]\n", + " post_levels = [p3sigma, p2sigma, p1sigma][3 - post_uptosigma :]\n", + " post_linestyles = [\"dotted\", \"dashed\", \"solid\"][3 - post_uptosigma :]\n", "\n", " x, y, z = get_xyz(posterior)\n", - " \n", - " #plot the joint posterior 1/2/3 sigma lines:\n", - " cn_post = ax.tricontour(x, y, z, levels=post_levels, linestyles=post_linestyles, colors='black', zorder=2)\n", - " \n", - " #print the posterior 1sigma credible intervals:\n", - " pT0, pMdot = get_array_from_contour(cn_post, -1) #get last level (=1 sigma) from posterior\n", + "\n", + " # plot the joint posterior 1/2/3 sigma lines:\n", + " cn_post = ax.tricontour(\n", + " x,\n", + " y,\n", + " z,\n", + " levels=post_levels,\n", + " linestyles=post_linestyles,\n", + " colors=\"black\",\n", + " zorder=2,\n", + " )\n", + "\n", + " # print the posterior 1sigma credible intervals:\n", + " pT0, pMdot = get_array_from_contour(\n", + " cn_post, -1\n", + " ) # get last level (=1 sigma) from posterior\n", " if pT0 is not None and pMdot is not None:\n", - " bestT0_index, bestMdot_index = np.unravel_index(np.nanargmax(posterior), posterior.shape)\n", - " bestT0, bestMdot = float(posterior.index[bestT0_index]), float(posterior.columns[bestMdot_index]) #T, Mdot of the maximum of the posterior\n", - " max_pMdot, min_pMdot, max_pT0, min_pT0 = np.max(pMdot), np.min(pMdot), np.max(pT0), np.min(pT0) #\n", - " print(f\"1 sigma constraints:\\nlog10(Mdot) = {bestMdot} + {max_pMdot-bestMdot} - {bestMdot-min_pMdot}\")\n", + " bestT0_index, bestMdot_index = np.unravel_index(\n", + " np.nanargmax(posterior), posterior.shape\n", + " )\n", + " bestT0, bestMdot = float(posterior.index[bestT0_index]), float(\n", + " posterior.columns[bestMdot_index]\n", + " ) # T, Mdot of the maximum of the posterior\n", + " max_pMdot, min_pMdot, max_pT0, min_pT0 = (\n", + " np.max(pMdot),\n", + " np.min(pMdot),\n", + " np.max(pT0),\n", + " np.min(pT0),\n", + " ) #\n", + " print(\n", + " f\"1 sigma constraints:\\nlog10(Mdot) = {bestMdot} + {max_pMdot-bestMdot} - {bestMdot-min_pMdot}\"\n", + " )\n", " print(f\"T0 = {bestT0} + {max_pT0-bestT0} - {bestT0-min_pT0}\")\n", - " \n", - " \n", + "\n", " if show_colorbar:\n", " divider = make_axes_locatable(ax)\n", - " \n", + "\n", " if dT is not None and sigmaT is not None:\n", - " #plot the prior colorbar\n", + " # plot the prior colorbar\n", " cax1 = divider.append_axes(\"right\", size=\"5%\", pad=0.05)\n", " cbar1 = fig.colorbar(prior_contour, cax=cax1)\n", - " cax1.yaxis.set_major_locator(plt.NullLocator()) #turn the ticks for cbar1 off\n", - " \n", - " #plot the likelihood colorbar \n", + " cax1.yaxis.set_major_locator(\n", + " plt.NullLocator()\n", + " ) # turn the ticks for cbar1 off\n", + "\n", + " # plot the likelihood colorbar\n", " cax2 = divider.append_axes(\"right\", size=\"5%\", pad=0.05)\n", " cbar2 = fig.colorbar(likelihood_contour, cax=cax2)\n", - " cax2.set_yticklabels([r'2$\\sigma$', r'1$\\sigma$', r'0$\\sigma$'])\n", - " cax2.invert_yaxis() #because the p-values and sigma values are in opposite direction\n", + " cax2.set_yticklabels([r\"2$\\sigma$\", r\"1$\\sigma$\", r\"0$\\sigma$\"])\n", + " cax2.invert_yaxis() # because the p-values and sigma values are in opposite direction\n", "\n", - " \n", - " \n", - " ax.set_xlabel(r'$T_0$ [K]')\n", - " ax.set_ylabel(r'log$_{10}$($\\dot{M}$ [g s$^{-1}$])')\n", + " ax.set_xlabel(r\"$T_0$ [K]\")\n", + " ax.set_ylabel(r\"log$_{10}$($\\dot{M}$ [g s$^{-1}$])\")\n", " if bounds_T0:\n", " ax.set_xlim(*bounds_T0)\n", " if bounds_Mdot:\n", @@ -721,97 +976,133 @@ " if title != None:\n", " ax.set_title(title)\n", " if save != None:\n", - " plt.savefig(save, bbox_inches='tight', dpi=300)\n", + " plt.savefig(save, bbox_inches=\"tight\", dpi=300)\n", " if showplot:\n", " plt.show()\n", "\n", "\n", - "def plot_joint_constraint_unresolved(dT, sigmaT, nsig_fit, posterior, \n", - " bounds_T0=None, bounds_Mdot=None, \n", - " title=None, save=None, \n", - " fig=None, ax=None, cmap_T=None,\n", - " cmap_fit=None, post_uptosigma=1,\n", - " show_colorbar=True):\n", - " '''\n", - " Makes a plot of the 1sigma posterior contour \n", + "def plot_joint_constraint_unresolved(\n", + " dT,\n", + " sigmaT,\n", + " nsig_fit,\n", + " posterior,\n", + " bounds_T0=None,\n", + " bounds_Mdot=None,\n", + " title=None,\n", + " save=None,\n", + " fig=None,\n", + " ax=None,\n", + " cmap_T=None,\n", + " cmap_fit=None,\n", + " post_uptosigma=1,\n", + " show_colorbar=True,\n", + "):\n", + " \"\"\"\n", + " Makes a plot of the 1sigma posterior contour\n", " on top of the prior (self-consistency) and likelihood (data fit) constraints.\n", " Also prints out the 1sigma bounds on T and Mdot, which are calculated\n", " based on the matplotlib contour, and thus involve interpolation to\n", " higher precision than the data itself.\n", - " '''\n", + " \"\"\"\n", "\n", - " assert post_uptosigma <=3, \"Maximum value of post_uptosigma is 3\"\n", + " assert post_uptosigma <= 3, \"Maximum value of post_uptosigma is 3\"\n", "\n", " if cmap_T is None:\n", - " cmap_T = truncate_colormap(plt.get_cmap('autumn'), 0.35, 0.65)\n", + " cmap_T = truncate_colormap(plt.get_cmap(\"autumn\"), 0.35, 0.65)\n", " if cmap_fit is None:\n", - " cmap_fit = truncate_colormap(plt.get_cmap('winter'), 0.35, 0.65)\n", + " cmap_fit = truncate_colormap(plt.get_cmap(\"winter\"), 0.35, 0.65)\n", "\n", - " \n", " if fig == None and ax == None:\n", " _showplot = True\n", " fig, ax = plt.subplots(1)\n", " else:\n", " _showplot = False\n", - " \n", - " #### Plot the model temperature discrepancy (i.e. prior)\n", + "\n", + " # Plot the model temperature discrepancy (i.e. prior)\n", " if dT is not None and sigmaT is not None:\n", " nsig_T = dT / sigmaT\n", "\n", " x, y, z = get_xyz(nsig_T)\n", "\n", - " ax.tricontour(x, y, z, cmap=cmap_T, levels=[0], zorder=0) #plots the orange line\n", - " prior_contour = ax.tricontourf(x, y, np.abs(z), cmap=cmap_T, levels=[0,1,2], alpha=0.5, zorder=0) #plots the orange contours\n", - " \n", - " #### Plot the fit constraints (i.e. likelihood):\n", + " ax.tricontour(\n", + " x, y, z, cmap=cmap_T, levels=[0], zorder=0\n", + " ) # plots the orange line\n", + " prior_contour = ax.tricontourf(\n", + " x, y, np.abs(z), cmap=cmap_T, levels=[0, 1, 2], alpha=0.5, zorder=0\n", + " ) # plots the orange contours\n", + "\n", + " # Plot the fit constraints (i.e. likelihood):\n", " x, y, z = get_xyz(nsig_fit)\n", - " ax.tricontour(x, y, z, cmap=cmap_fit, levels=[0], zorder=1) #plots the blue line\n", - " likelihood_contour = ax.tricontourf(x, y, np.abs(z), cmap=cmap_fit, levels=[0,1,2], alpha=0.5, zorder=1) #plots the blue contours\n", - " \n", - " #### Plot the posterior\n", + " ax.tricontour(x, y, z, cmap=cmap_fit, levels=[0], zorder=1) # plots the blue line\n", + " likelihood_contour = ax.tricontourf(\n", + " x, y, np.abs(z), cmap=cmap_fit, levels=[0, 1, 2], alpha=0.5, zorder=1\n", + " ) # plots the blue contours\n", + "\n", + " # Plot the posterior\n", " if posterior is not None and post_uptosigma > 0:\n", - " #calculate the posterior values that corresponds to the 1,2,3 sigma contours\n", + " # calculate the posterior values that corresponds to the 1,2,3 sigma contours\n", " posterior_sorted = np.sort(posterior.values.flatten())[::-1]\n", " posterior_sum = np.sum(posterior_sorted)\n", " posterior_cumsum = np.cumsum(posterior_sorted)\n", " p1sigma = posterior_sorted[posterior_cumsum > 0.3935 * posterior_sum][0]\n", " p2sigma = posterior_sorted[posterior_cumsum > 0.8647 * posterior_sum][0]\n", " p3sigma = posterior_sorted[posterior_cumsum > 0.9889 * posterior_sum][0]\n", - " post_levels = [p3sigma, p2sigma, p1sigma][3-post_uptosigma:]\n", - " post_linestyles = ['dotted', 'dashed', 'solid'][3-post_uptosigma:]\n", + " post_levels = [p3sigma, p2sigma, p1sigma][3 - post_uptosigma :]\n", + " post_linestyles = [\"dotted\", \"dashed\", \"solid\"][3 - post_uptosigma :]\n", "\n", " x, y, z = get_xyz(posterior)\n", "\n", - " #plot the joint posterior 1/2/3 sigma lines:\n", - " cn_post = ax.tricontour(x, y, z, levels=post_levels, linestyles=post_linestyles, colors='black', zorder=2)\n", - " \n", - " #print the posterior 1sigma credible intervals:\n", - " pT0, pMdot = get_array_from_contour(cn_post, -1) #get last level (=1 sigma) from posterior\n", + " # plot the joint posterior 1/2/3 sigma lines:\n", + " cn_post = ax.tricontour(\n", + " x,\n", + " y,\n", + " z,\n", + " levels=post_levels,\n", + " linestyles=post_linestyles,\n", + " colors=\"black\",\n", + " zorder=2,\n", + " )\n", + "\n", + " # print the posterior 1sigma credible intervals:\n", + " pT0, pMdot = get_array_from_contour(\n", + " cn_post, -1\n", + " ) # get last level (=1 sigma) from posterior\n", " if pT0 is not None and pMdot is not None:\n", - " bestT0_index, bestMdot_index = np.unravel_index(np.nanargmax(posterior), posterior.shape)\n", - " bestT0, bestMdot = float(posterior.index[bestT0_index]), float(posterior.columns[bestMdot_index]) #T, Mdot of the maximum of the posterior\n", - " max_pMdot, min_pMdot, max_pT0, min_pT0 = np.max(pMdot), np.min(pMdot), np.max(pT0), np.min(pT0) #\n", - " print(f\"1 sigma constraints:\\nlog10(Mdot) = {bestMdot} + {max_pMdot-bestMdot} - {bestMdot-min_pMdot}\")\n", + " bestT0_index, bestMdot_index = np.unravel_index(\n", + " np.nanargmax(posterior), posterior.shape\n", + " )\n", + " bestT0, bestMdot = float(posterior.index[bestT0_index]), float(\n", + " posterior.columns[bestMdot_index]\n", + " ) # T, Mdot of the maximum of the posterior\n", + " max_pMdot, min_pMdot, max_pT0, min_pT0 = (\n", + " np.max(pMdot),\n", + " np.min(pMdot),\n", + " np.max(pT0),\n", + " np.min(pT0),\n", + " ) #\n", + " print(\n", + " f\"1 sigma constraints:\\nlog10(Mdot) = {bestMdot} + {max_pMdot-bestMdot} - {bestMdot-min_pMdot}\"\n", + " )\n", " print(f\"T0 = {bestT0} + {max_pT0-bestT0} - {bestT0-min_pT0}\")\n", - " \n", - " \n", + "\n", " if show_colorbar:\n", " divider = make_axes_locatable(ax)\n", - " \n", + "\n", " if dT is not None and sigmaT is not None:\n", - " #plot the prior colorbar\n", + " # plot the prior colorbar\n", " cax1 = divider.append_axes(\"right\", size=\"5%\", pad=0.05)\n", " cbar1 = fig.colorbar(prior_contour, cax=cax1)\n", - " cax1.yaxis.set_major_locator(plt.NullLocator()) #turn the ticks for cbar1 off\n", - " \n", - " #plot the likelihood colorbar \n", + " cax1.yaxis.set_major_locator(\n", + " plt.NullLocator()\n", + " ) # turn the ticks for cbar1 off\n", + "\n", + " # plot the likelihood colorbar\n", " cax2 = divider.append_axes(\"right\", size=\"5%\", pad=0.05)\n", " cbar2 = fig.colorbar(likelihood_contour, cax=cax2)\n", - " cax2.set_yticklabels([r'0$\\sigma$', r'1$\\sigma$', r'2$\\sigma$'])\n", - " \n", - " \n", - " ax.set_xlabel(r'$T_0$ [K]')\n", - " ax.set_ylabel(r'log$_{10}$($\\dot{M}$ [g s$^{-1}$])')\n", + " cax2.set_yticklabels([r\"0$\\sigma$\", r\"1$\\sigma$\", r\"2$\\sigma$\"])\n", + "\n", + " ax.set_xlabel(r\"$T_0$ [K]\")\n", + " ax.set_ylabel(r\"log$_{10}$($\\dot{M}$ [g s$^{-1}$])\")\n", " if bounds_T0:\n", " ax.set_xlim(*bounds_T0)\n", " if bounds_Mdot:\n", @@ -820,7 +1111,7 @@ " if title != None:\n", " ax.set_title(title)\n", " if save != None:\n", - " plt.savefig(save, bbox_inches='tight', dpi=300)\n", + " plt.savefig(save, bbox_inches=\"tight\", dpi=300)\n", " if _showplot:\n", " plt.show()" ] @@ -830,38 +1121,84 @@ "id": "aa8609df", "metadata": {}, "source": [ - "# --------------\n", - "\n", - "# Retrieval of a mock spectrum of a hot Neptune" + "## Retrieval of a mock spectrum of a hot Neptune" ] }, { "cell_type": "markdown", - "id": "6964e61b", + "id": "dea2e2a7-78c6-4974-b3e9-4028834d87fd", "metadata": {}, "source": [ "### Step 1: Create a grid of Parker wind profiles with p-winds (skip or run a rougher grid if you use our pre-run models)\n", "\n", - "This step can be done by calling `construct_parker.py` from the command-line with the proper arguments. Running `python construct_parker.py --help` will give an overview of the available arguments. In our case, we will run *p-winds* with a solar composition (so including metals at the solar abundances). This is done by passing `-z 1`. We will run a grid of models that span temperatures $T_0$ from 4000 to 7000 K in steps of 100 K, and log10-mass-loss rates $\\dot{M}$ from 10.5 to 11.5 in steps of 0.05 dex. To run a grid of temperatures, we need to pass the lowest temperature, the highest temperature, and the step size to the `-T` argument, and similarly for the log-10 mass-loss rate `-Mdot`. Since in the future, we might want to explore different compositions, `construct_parker.py` always expects you to give a folder name `-pdir` where we want to store our Parker profiles. We reccommend using a descriptive name, so in this case we will go with *z_1* and the path where our profiles will be saved is then *$SUNBATHER_PROJECT_PATH/parker_profiles/hotNeptune/z_1/*. Finally, tidal gravity is included by default, but we will turn it off here in order to reproduce the results from Linssen et al. (2024), by passing the `-no_tidal` flag.\n", - "\n", - "> **The full command to create a grid of solar composition Parker wind models is**:

\n", - "> `python construct_parker.py -plname hotNeptune -pdir z_1 -T 4000 7000 100 -Mdot 10.5 11.5 0.05 -z 1 -no_tidal`\n", - "\n", + "This step can be done by calling `construct_parker.py` from the command-line with the proper arguments. Running `python construct_parker.py --help` will give an overview of the available arguments. In our case, we will run *p-winds* with a solar composition (so including metals at the solar abundances). This is done by passing `-z 1`. We will run a grid of models that span temperatures $T_0$ from 4000 to 7000 K in steps of 100 K, and log10-mass-loss rates $\\dot{M}$ from 10.5 to 11.5 in steps of 0.05 dex. To run a grid of temperatures, we need to pass the lowest temperature, the highest temperature, and the step size to the `-T` argument, and similarly for the log-10 mass-loss rate `-Mdot`. Since in the future, we might want to explore different compositions, `construct_parker.py` always expects you to give a folder name `-pdir` where we want to store our Parker profiles. We reccommend using a descriptive name, so in this case we will go with *z_1* and the path where our profiles will be saved is then *$SUNBATHER_PROJECT_PATH/parker_profiles/hotNeptune/z_1/*. Finally, tidal gravity is included by default, but we will turn it off here in order to reproduce the results from Linssen et al. (2024), by passing the `-no_tidal` flag." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4c61a5f8-b946-4220-859d-3bee7000a0cf", + "metadata": {}, + "outputs": [], + "source": [ + "# The full command to create a grid of solar composition Parker wind models is:\n", + "from sunbather import construct_parker\n", + "temp = np.arange(4000, 7001, 100)\n", + "mdot = np.arange(10.5, 11.51, 0.05)\n", + "zdict = tools.get_zdict(z=1)\n", + "\n", + "construct_parker.run_models(\n", + " plname=\"hotNeptune\",\n", + " pdir=\"z_1\",\n", + " temp_list=temp,\n", + " mdot_list=mdot,\n", + " zdict=zdict,\n", + " no_tidal=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "630591f8-bbbd-4ab7-89de-58ed6e9872d1", + "metadata": {}, + "source": [ "Additionally, with the `-cores` flag you can specify the number of parallel CPUs used. For this set of parameters, this command should take on the order of a few minutes. In the *$SUNBATHER_PROJECT_PATH/parker_profiles/hotNeptune/z_1/* folder, there should now be many different .txt files with the isothermal Parker wind structures, feel free to inspect them!" ] }, { "cell_type": "markdown", - "id": "e73b1280", + "id": "4d05d58c-6821-498e-9f63-df7a6cdd0523", "metadata": {}, "source": [ "### Step 2: Run the Parker wind profiles through Cloudy (skip or run a rougher grid if you use our pre-run models)\n", "\n", - "This step can be done by calling `convergeT_parker.py` from the command-line with the proper arguments (`--help` will explain these). The $T_0$ and $\\dot{M}$ grid-commands are the same as in Step 1. We also again need to specify a folder name where we want to save our *Cloudy* simulations (which is a different directory from where the isothermal Parker wind profiles were stored). In this case we will indicate that we used _Cloudy_ with a solar composition/metallicity, i.e. a metallicity of z=1: `-dir z_1` and so our simulations will be saved in _$SUNBATHER_PROJECT_PATH/sims/1D/hotNeptune/z_0/_. We now again need to specify the folder where we want to read the Parker wind profiles from: `-pdir fH_0.9`. Since the *Cloudy* simulations are more time-consuming, you can easily run the different simulations in parallel by using the `-cores` flag. We then need to choose the atmospheric composition in _Cloudy_. We go with the default solar composition so we do not have to provide a command-line argument for it. The last thing we need to think about, is for which atomic/ionic species we want to save *Cloudy's* output. The default behavior is to save everything that's available, but this generally results in large file sizes (~5 MB per model, if metals are included). In our particular case, we want to fit helium observations, so we are fine with just saving the densities of the different atomic helium energy levels: `-save_sp He`.\n", - "\n", - "> **The full command to run our grid of hydrogen/helium Parker wind models through *Cloudy* is:**:

\n", - "> `python convergeT_parker.py -plname hotNeptune -dir z_1 -pdir fH_0.9 -T 4000 7000 100 -Mdot 10.5 11.5 0.05 -save_sp He`\n", - "\n", + "This step can be done by calling `convergeT_parker.py` from the command-line with the proper arguments (`--help` will explain these). The $T_0$ and $\\dot{M}$ grid-commands are the same as in Step 1. We also again need to specify a folder name where we want to save our *Cloudy* simulations (which is a different directory from where the isothermal Parker wind profiles were stored). In this case we will indicate that we used _Cloudy_ with a solar composition/metallicity, i.e. a metallicity of z=1: `-dir z_1` and so our simulations will be saved in _$SUNBATHER_PROJECT_PATH/sims/1D/hotNeptune/z_0/_. We now again need to specify the folder where we want to read the Parker wind profiles from: `-pdir fH_0.9`. Since the *Cloudy* simulations are more time-consuming, you can easily run the different simulations in parallel by using the `-cores` flag. We then need to choose the atmospheric composition in _Cloudy_. We go with the default solar composition so we do not have to provide a command-line argument for it. The last thing we need to think about, is for which atomic/ionic species we want to save *Cloudy's* output. The default behavior is to save everything that's available, but this generally results in large file sizes (~5 MB per model, if metals are included). In our particular case, we want to fit helium observations, so we are fine with just saving the densities of the different atomic helium energy levels: `-save_sp He`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bbdc7986-6d55-4e35-aa04-5948e0d717f0", + "metadata": {}, + "outputs": [], + "source": [ + "# The full command to run our grid of hydrogen/helium Parker wind models through *Cloudy* is:\n", + "import sunbather.convergeT_parker\n", + "sunbather.convergeT_parker.main(\n", + " plname=\"hotNeptune\",\n", + " dir=\"z_1\",\n", + " pdir=\"fH_0.9\",\n", + " T=\"4000 7000 100\",\n", + " Mdot=\"10.5 11.5 0.05\",\n", + " save_sp=\"He\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "1f26281f-bcf9-4738-8af8-b6b829658b47", + "metadata": {}, + "source": [ "Additionally, with the `-cores` flag you can specify the number of parallel CPUs used. For this set of parameters, this command should take many hours (roughly 10 minutes per model, and we are running roughy 30x20 models), and it is adviced to run it on a compute cluster. In the _$SUNBATHER_PROJECT_PATH/sims/1D/hotNeptune/fH_0.9/_ folder, there should now be many different sub-folders, with the output of the _Cloudy_ simulations, feel free to inspect the files! The _converged.png_ file shows the converged temperature structure, and the other _converged.*_ files are the _Cloudy_ output files." ] }, @@ -891,1017 +1228,12 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "5c08a50d", "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_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('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", - "\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.canvas_div.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", - "function 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", - " */\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", - " 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", - "\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" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The true EW is 0.014318327135537906. We have drawn an observed EW = 0.013534265740520248 +- 0.0017897908919422383 (which is a 7.561925698388814 sigma detection)\n" - ] - } - ], + "outputs": [], "source": [ - "#set random seed for consistent results\n", + "# set random seed for consistent results\n", "np.random.seed(0)\n", "\"\"\"\n", "#if due to a different numpy version, your generated mock spectrum is different,\n", @@ -1909,40 +1241,44 @@ "#which has stored np.column_stack((wavs, observed_excess_absorption, observed_excess_absorption_errorbar))\n", "\"\"\"\n", "\n", - "#Let's make the spectrum of the generic hot Neptune\n", - "hotNep = tools.Sim(tools.projectpath+\"/sims/1D/hotNeptune/z_1/parker_5100_10.950/converged\")\n", + "# Let's make the spectrum of the generic hot Neptune\n", + "hotNep = tools.Sim(\n", + " projectpath + \"/sims/1D/hotNeptune/z_1/parker_5100_10.950/converged\"\n", + ")\n", "\n", "wavs = RT.constantR_wavs(10830, 10836, 80000)\n", - "true_spec, _, _ = RT.FinFout(hotNep, wavs, 'He')\n", + "true_spec, _, _ = RT.FinFout(hotNep, wavs, \"He\")\n", "\n", - "#draw errors from normal distribution\n", - "observed_errorbar = np.ones_like(wavs) * 0.0025 #just pick a number\n", + "# draw errors from normal distribution\n", + "observed_errorbar = np.ones_like(wavs) * 0.0025 # just pick a number\n", "observed_spec = np.random.normal(loc=true_spec, scale=observed_errorbar)\n", "\n", - "#convert into excess absorption in % which is what the calc_chisqs_He10830() function expects\n", - "#we pretend we don't know the continuum level and take it as the average away from the line (last 15 points)\n", + "# convert into excess absorption in % which is what the calc_chisqs_He10830() function expects\n", + "# we pretend we don't know the continuum level and take it as the average away from the line (last 15 points)\n", "observed_excess_absorption = 100 * (np.mean(observed_spec[-15:]) - observed_spec)\n", "observed_excess_absorption_errorbar = 100 * observed_errorbar\n", "\n", - "highres_wavs = np.linspace(10830, 10836, 1000) #for smooth plotting\n", - "highres_true_spec, _, _ = RT.FinFout(hotNep, highres_wavs, 'He')\n", + "highres_wavs = np.linspace(10830, 10836, 1000) # for smooth plotting\n", + "highres_true_spec, _, _ = RT.FinFout(hotNep, highres_wavs, \"He\")\n", "\n", "\n", "fig, ax = plt.subplots(1)\n", "ax.plot(highres_wavs, highres_true_spec)\n", - "ax.errorbar(wavs, observed_spec, yerr=observed_errorbar, fmt='o')\n", + "ax.errorbar(wavs, observed_spec, yerr=observed_errorbar, fmt=\"o\")\n", "ax.set_xlabel(\"Wavelength [Å]\")\n", "ax.set_ylabel(r\"$F_{in}$/$F_{out}$\")\n", "plt.show()\n", "\n", "\n", - "#integrate the difference with the continuum to obtain the equivalent width\n", - "true_EW = trapezoid(np.max(true_spec) - true_spec, x=wavs) #units: Å\n", - "#let's choose the errorbar as 1/8 of the EW so that we will get around a 8 sigma detection\n", - "observed_EW_errorbar = true_EW / 8.\n", + "# integrate the difference with the continuum to obtain the equivalent width\n", + "true_EW = trapezoid(np.max(true_spec) - true_spec, x=wavs) # units: Å\n", + "# let's choose the errorbar as 1/8 of the EW so that we will get around a 8 sigma detection\n", + "observed_EW_errorbar = true_EW / 8.0\n", "observed_EW = np.random.normal(loc=true_EW, scale=observed_EW_errorbar)\n", - "print(f\"The true EW is {true_EW}. We have drawn an observed EW = {observed_EW} +- {observed_EW_errorbar} \" \\\n", - " f\"(which is a {observed_EW/observed_EW_errorbar} sigma detection)\")\n" + "print(\n", + " f\"The true EW is {true_EW}. We have drawn an observed EW = {observed_EW} +- {observed_EW_errorbar} \"\n", + " f\"(which is a {observed_EW/observed_EW_errorbar} sigma detection)\"\n", + ")" ] }, { @@ -1965,27 +1301,27 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "afb89ddc", "metadata": {}, "outputs": [], "source": [ - "#chisqs = calc_chisqs_He10830(tools.projectpath+'/sims/1D/hotNeptune/z_1/', \n", + "# chisqs = calc_chisqs_He10830(tools.projectpath+'/sims/1D/hotNeptune/z_1/',\n", "# wavs, observed_excess_absorption, observed_excess_absorption_errorbar)\n", - "#chisqs.to_csv('materials/hotNeptune_chisqs.csv') #this overwrites the supplied file" + "# chisqs.to_csv('materials/hotNeptune_chisqs.csv') #this overwrites the supplied file" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "98436f6e", "metadata": {}, "outputs": [], "source": [ - "#read in the chi-squared values from file\n", - "chisqs = pd.read_csv('materials/hotNeptune_chisqs.csv', index_col=0, dtype=float)\n", + "# read in the chi-squared values from file\n", + "chisqs = pd.read_csv(\"materials/hotNeptune_chisqs.csv\", index_col=0, dtype=float)\n", "\n", - "#calculate the likelihood (an actual p-value, contrary to the chi-squared statistic)\n", + "# calculate the likelihood (an actual p-value, contrary to the chi-squared statistic)\n", "likelihood_resolved = calc_likelihood_resolved(chisqs)" ] }, @@ -1999,1010 +1335,14 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "133461ec", "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_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('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", - "\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.canvas_div.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", - "function 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", - " */\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", - " 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", - "\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" - } - ], + "outputs": [], "source": [ - "plot_chisq_fit(chisqs, bounds_T0=(4000,7000), bounds_Mdot=(10.5, 11.5), title='Resolved line fit')" + "plot_chisq_fit(\n", + " chisqs, bounds_T0=(4000, 7000), bounds_Mdot=(10.5, 11.5), title=\"Resolved line fit\"\n", + ")" ] }, { @@ -3023,28 +1363,28 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "c86ecca2", "metadata": {}, "outputs": [], "source": [ - "#EWs = calc_EWs_He10830(tools.projectpath+'/sims/1D/hotNeptune/z_1/')\n", - "#EWs.to_csv('materials/hotNeptune_EWs.csv') #this overwrites the supplied file" + "# EWs = calc_EWs_He10830(tools.projectpath+'/sims/1D/hotNeptune/z_1/')\n", + "# EWs.to_csv('materials/hotNeptune_EWs.csv') #this overwrites the supplied file" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "bc6f2960", "metadata": {}, "outputs": [], "source": [ - "#read in the EW values from file\n", - "EWs = pd.read_csv('materials/hotNeptune_EWs.csv', index_col=0, dtype=float)\n", + "# read in the EW values from file\n", + "EWs = pd.read_csv(\"materials/hotNeptune_EWs.csv\", index_col=0, dtype=float)\n", "\n", - "#calculate the number of errorbars discrepancy between model and data\n", - "#this is what the calc_likelihood_unresolved() function expects\n", - "nsig_fit = (EWs - observed_EW)/observed_EW_errorbar\n", + "# calculate the number of errorbars discrepancy between model and data\n", + "# this is what the calc_likelihood_unresolved() function expects\n", + "nsig_fit = (EWs - observed_EW) / observed_EW_errorbar\n", "\n", "likelihood_unresolved = calc_likelihood_unresolved(nsig_fit)" ] @@ -3059,1010 +1399,17 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "0b5ded03", "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_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('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", - "\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.canvas_div.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", - "function 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", - " */\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", - " 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", - "\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" - } - ], + "outputs": [], "source": [ - "plot_nsig_fit(nsig_fit, bounds_T0=(4000,7000), bounds_Mdot=(10.5,11.5), title='Equivalent width fit')" + "plot_nsig_fit(\n", + " nsig_fit,\n", + " bounds_T0=(4000, 7000),\n", + " bounds_Mdot=(10.5, 11.5),\n", + " title=\"Equivalent width fit\",\n", + ")" ] }, { @@ -4085,29 +1432,29 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "a6d078e4", "metadata": {}, "outputs": [], "source": [ - "#dT, sigmaT = calc_dT_helium(tools.projectpath+'/sims/1D/hotNeptune/z_1/')\n", - "#dT.to_csv('materials/hotNeptune_dT.csv', float_format='%.3e') #these overwrite the supplied files\n", - "#sigmaT.to_csv('materials/hotNeptune_sigmaT.csv', float_format='%.3e')" + "# dT, sigmaT = calc_dT_helium(tools.projectpath+'/sims/1D/hotNeptune/z_1/')\n", + "# dT.to_csv('materials/hotNeptune_dT.csv', float_format='%.3e') #these overwrite the supplied files\n", + "# sigmaT.to_csv('materials/hotNeptune_sigmaT.csv', float_format='%.3e')" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "14a91e2d", "metadata": {}, "outputs": [], "source": [ - "#read in the dT and sigmaT values from file\n", - "dT = pd.read_csv('materials/hotNeptune_dT.csv', index_col=0, dtype=float)\n", - "sigmaT = pd.read_csv('materials/hotNeptune_sigmaT.csv', index_col=0, dtype=float) \n", + "# read in the dT and sigmaT values from file\n", + "dT = pd.read_csv(\"materials/hotNeptune_dT.csv\", index_col=0, dtype=float)\n", + "sigmaT = pd.read_csv(\"materials/hotNeptune_sigmaT.csv\", index_col=0, dtype=float)\n", "\n", - "#now we can calculate the prior based on the model self-consistency\n", - "prior = calc_prior(dT, sigmaT)" + "# now we can calculate the prior based on the model self-consistency\n", + "prior = calc_prior(dT, sigmaT)" ] }, { @@ -4120,1010 +1467,18 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "67f04b54", "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_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('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", - "\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.canvas_div.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", - "function 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", - " */\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", - " 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", - "\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" - } - ], + "outputs": [], "source": [ - "plot_selfcons(dT, sigmaT, bounds_T0=(4000,7000), bounds_Mdot=(10.5,11.5), title='Model self-consistency')" + "plot_selfcons(\n", + " dT,\n", + " sigmaT,\n", + " bounds_T0=(4000, 7000),\n", + " bounds_Mdot=(10.5, 11.5),\n", + " title=\"Model self-consistency\",\n", + ")" ] }, { @@ -5144,30 +1499,17 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "d2f8579b", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Constraints from marginalized posteriors (not necessarily normally distributed!):\n", - "log10(Mdot) = 10.9 + 0.09999999999999964 - 0.09999999999999964\n", - "T0 = 4800.0 + 600.0 - 500.0\n", - "Constraints from marginalized posteriors (not necessarily normally distributed!):\n", - "log10(Mdot) = 10.9 + 0.09999999999999964 - 0.09999999999999964\n", - "T0 = 4900.0 + 400.0 - 500.0\n" - ] - } - ], + "outputs": [], "source": [ - "#for the resolved line fit, we calculate the posterior with a flat prior\n", - "#we do this only so that calc_posterior() prints the constrained T0 and Mdot based on\n", - "#the likelihood alone, which we can then quote\n", - "posterior_resolved = calc_posterior(1., likelihood_resolved)\n", + "# for the resolved line fit, we calculate the posterior with a flat prior\n", + "# we do this only so that calc_posterior() prints the constrained T0 and Mdot based on\n", + "# the likelihood alone, which we can then quote\n", + "posterior_resolved = calc_posterior(1.0, likelihood_resolved)\n", "\n", - "#for the EW fit, we calculate the posterior with the prior based on model self-consistency\n", + "# for the EW fit, we calculate the posterior with the prior based on model self-consistency\n", "posterior_unresolved = calc_posterior(prior, likelihood_unresolved)" ] }, @@ -5181,2009 +1523,24 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "id": "44e9ab5c", "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_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('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", - "\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.canvas_div.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", - "function 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", - " */\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", - " 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", - "\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" - }, - { - "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('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", - "\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.canvas_div.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", - "function 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", - " */\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", - " 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", - "\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" - } - ], + "outputs": [], "source": [ - "plot_posterior(posterior_resolved, bounds_T0=(4000,7000), bounds_Mdot=(10.5,11.5), title='Resolved fit posterior')\n", - "\n", - "plot_posterior(posterior_unresolved, bounds_T0=(4000,7000), bounds_Mdot=(10.5,11.5), title='Equivalent width fit posterior')" + "plot_posterior(\n", + " posterior_resolved,\n", + " bounds_T0=(4000, 7000),\n", + " bounds_Mdot=(10.5, 11.5),\n", + " title=\"Resolved fit posterior\",\n", + ")\n", + "\n", + "plot_posterior(\n", + " posterior_unresolved,\n", + " bounds_T0=(4000, 7000),\n", + " bounds_Mdot=(10.5, 11.5),\n", + " title=\"Equivalent width fit posterior\",\n", + ")" ] }, { @@ -7198,1073 +1555,199 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "id": "950d3c60", - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_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('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", - "\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.canvas_div.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", - "function 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", - " */\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", - " 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", - "\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" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1 sigma constraints:\n", - "log10(Mdot) = 10.9 + 0.06793855530304249 - 0.05619954871618482\n", - "T0 = 5000.0 + 227.31345196987695 - 442.4995430827812\n" - ] - } - ], + "metadata": {}, + "outputs": [], "source": [ - "with plt.rc_context({\"font.family\": \"serif\", \"mathtext.fontset\": \"dejavuserif\"}): #identical to paper\n", + "with plt.rc_context(\n", + " {\"font.family\": \"serif\", \"mathtext.fontset\": \"dejavuserif\"}\n", + "): # identical to paper\n", "\n", - " fig, axes = plt.subplots(ncols=1, nrows=3, figsize=(4.5,12))\n", + " fig, axes = plt.subplots(ncols=1, nrows=3, figsize=(4.5, 12))\n", "\n", " #######\n", "\n", - " #re-calculate the best-fit spectrum\n", - " bestfitsim = tools.Sim(tools.projectpath+\"/sims/1D/hotNeptune/z_1/parker_4800_10.900/converged\")\n", - " bestspec, _, _ = RT.FinFout(bestfitsim, highres_wavs, 'He')\n", - " \n", - " axes[0].plot(highres_wavs, highres_true_spec, color='blueviolet', label='True model', lw=2, zorder=-20)\n", - " axes[0].errorbar(wavs, observed_spec, yerr=observed_errorbar, fmt='o', color='black', label='Mock observation', lw=2, zorder=-10)\n", - " axes[0].plot(highres_wavs, bestspec, color='dodgerblue', label='Retrieved model', linestyle='dashed', lw=2, zorder=-5)\n", - " axes[0].text(0.96,0.04, r'$\\bf{a)}$', ha='right', va='bottom', transform=axes[0].transAxes)\n", + " # re-calculate the best-fit spectrum\n", + " bestfitsim = tools.Sim(\n", + " tools.projectpath + \"/sims/1D/hotNeptune/z_1/parker_4800_10.900/converged\"\n", + " )\n", + " bestspec, _, _ = RT.FinFout(bestfitsim, highres_wavs, \"He\")\n", + "\n", + " axes[0].plot(\n", + " highres_wavs,\n", + " highres_true_spec,\n", + " color=\"blueviolet\",\n", + " label=\"True model\",\n", + " lw=2,\n", + " zorder=-20,\n", + " )\n", + " axes[0].errorbar(\n", + " wavs,\n", + " observed_spec,\n", + " yerr=observed_errorbar,\n", + " fmt=\"o\",\n", + " color=\"black\",\n", + " label=\"Mock observation\",\n", + " lw=2,\n", + " zorder=-10,\n", + " )\n", + " axes[0].plot(\n", + " highres_wavs,\n", + " bestspec,\n", + " color=\"dodgerblue\",\n", + " label=\"Retrieved model\",\n", + " linestyle=\"dashed\",\n", + " lw=2,\n", + " zorder=-5,\n", + " )\n", + " axes[0].text(\n", + " 0.96, 0.04, r\"$\\bf{a)}$\", ha=\"right\", va=\"bottom\", transform=axes[0].transAxes\n", + " )\n", " axes[0].set_xlabel(\"Wavelength [Å]\")\n", " axes[0].set_ylabel(r\"$F_{in}$/$F_{out}$\")\n", - " axes[0].legend(loc=\"lower left\", edgecolor='none', facecolor='none', framealpha=0)\n", - " axes[0].xaxis.set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, _: '{:g}'.format(x)))\n", + " axes[0].legend(loc=\"lower left\", edgecolor=\"none\", facecolor=\"none\", framealpha=0)\n", + " axes[0].xaxis.set_major_formatter(\n", + " matplotlib.ticker.FuncFormatter(lambda x, _: \"{:g}\".format(x))\n", + " )\n", "\n", " #######\n", "\n", - " plot_joint_constraint_resolved(None, None, chisqs, None, bounds_T0=(4000,7000), \n", - " bounds_Mdot = (10.5, 11.5), fig=fig, ax=axes[1],\n", - " show_colorbar=False)\n", - " axes[1].scatter(5100, 10.95, marker='x', color='blueviolet', s=100, zorder=100) #the true model\n", - " axes[1].text(4870, 11, 'True model', color='blueviolet', ha='left', va='bottom')\n", - " axes[1].text(4400,10.75, 'Fit likelihood', ha='left', va='top', color=plt.get_cmap('winter_r')(0.65))\n", - " axes[1].text(0.96,0.96, r'$\\bf{b)}$ Resolved line fit', ha='right', va='top', transform=axes[1].transAxes)\n", - " axes[1].text(4900, 10.887, r'1$\\sigma$', va='center', ha='center', color=plt.get_cmap('winter_r')(0.55), fontsize=9)\n", - " axes[1].text(4120, 10.765, r'2$\\sigma$', va='center', ha='center', color=plt.get_cmap('winter_r')(0.45), fontsize=9)\n", - " axes[1].set_yticks(np.arange(10.6,11.41, 0.1), minor=True)\n", - " \n", + " plot_joint_constraint_resolved(\n", + " None,\n", + " None,\n", + " chisqs,\n", + " None,\n", + " bounds_T0=(4000, 7000),\n", + " bounds_Mdot=(10.5, 11.5),\n", + " fig=fig,\n", + " ax=axes[1],\n", + " show_colorbar=False,\n", + " )\n", + " axes[1].scatter(\n", + " 5100, 10.95, marker=\"x\", color=\"blueviolet\", s=100, zorder=100\n", + " ) # the true model\n", + " axes[1].text(4870, 11, \"True model\", color=\"blueviolet\", ha=\"left\", va=\"bottom\")\n", + " axes[1].text(\n", + " 4400,\n", + " 10.75,\n", + " \"Fit likelihood\",\n", + " ha=\"left\",\n", + " va=\"top\",\n", + " color=plt.get_cmap(\"winter_r\")(0.65),\n", + " )\n", + " axes[1].text(\n", + " 0.96,\n", + " 0.96,\n", + " r\"$\\bf{b)}$ Resolved line fit\",\n", + " ha=\"right\",\n", + " va=\"top\",\n", + " transform=axes[1].transAxes,\n", + " )\n", + " axes[1].text(\n", + " 4900,\n", + " 10.887,\n", + " r\"1$\\sigma$\",\n", + " va=\"center\",\n", + " ha=\"center\",\n", + " color=plt.get_cmap(\"winter_r\")(0.55),\n", + " fontsize=9,\n", + " )\n", + " axes[1].text(\n", + " 4120,\n", + " 10.765,\n", + " r\"2$\\sigma$\",\n", + " va=\"center\",\n", + " ha=\"center\",\n", + " color=plt.get_cmap(\"winter_r\")(0.45),\n", + " fontsize=9,\n", + " )\n", + " axes[1].set_yticks(np.arange(10.6, 11.41, 0.1), minor=True)\n", + "\n", " #######\n", - " \n", - " plot_joint_constraint_unresolved(dT, sigmaT, nsig_fit, posterior_unresolved, bounds_T0=(4000,7000), \n", - " bounds_Mdot = (10.5, 11.5), fig=fig, ax=axes[2], post_uptosigma=2,\n", - " show_colorbar=False)\n", - " axes[2].scatter(5100, 10.95, marker='x', color='blueviolet', s=100, zorder=100) #the true model\n", - " axes[2].text(4870, 11.05, 'True model', color='blueviolet', ha='left', va='bottom')\n", - " axes[2].text(4550,11.4, 'Prior', ha='left', va='top', color=plt.get_cmap('autumn')(0.35))\n", - " axes[2].text(6100,10.86, 'Fit likelihood', ha='left', va='top', color=plt.get_cmap('winter_r')(0.65))\n", - " axes[2].text(4500,10.73, r'Posterior', ha='left', va='top', color='black')\n", - " axes[2].text(6300, 10.972, r'1$\\sigma$', va='center', ha='center', color=plt.get_cmap('winter_r')(0.55), fontsize=9)\n", - " axes[2].text(6300, 10.913, r'2$\\sigma$', va='center', ha='center', color=plt.get_cmap('winter_r')(0.45), fontsize=9)\n", - " axes[2].text(4680, 11.3, r'1$\\sigma$', va='center', ha='center', color=plt.get_cmap('autumn')(0.45), fontsize=9)\n", - " axes[2].text(5000, 11.3, r'2$\\sigma$', va='center', ha='center', color=plt.get_cmap('autumn')(0.55), fontsize=9)\n", - " axes[2].text(4850, 10.866, r'1$\\sigma$', va='center', ha='center', color='black', fontsize=9)\n", - " axes[2].text(4500, 10.8, r'2$\\sigma$', va='center', ha='center', color='black', fontsize=9)\n", - " axes[2].text(0.96,0.96, r'$\\bf{c)}$ Equivalent width fit', ha='right', va='top', transform=axes[2].transAxes)\n", - " axes[2].set_yticks(np.arange(10.6,11.41, 0.1), minor=True)\n", - " \n", + "\n", + " plot_joint_constraint_unresolved(\n", + " dT,\n", + " sigmaT,\n", + " nsig_fit,\n", + " posterior_unresolved,\n", + " bounds_T0=(4000, 7000),\n", + " bounds_Mdot=(10.5, 11.5),\n", + " fig=fig,\n", + " ax=axes[2],\n", + " post_uptosigma=2,\n", + " show_colorbar=False,\n", + " )\n", + " axes[2].scatter(\n", + " 5100, 10.95, marker=\"x\", color=\"blueviolet\", s=100, zorder=100\n", + " ) # the true model\n", + " axes[2].text(4870, 11.05, \"True model\", color=\"blueviolet\", ha=\"left\", va=\"bottom\")\n", + " axes[2].text(\n", + " 4550, 11.4, \"Prior\", ha=\"left\", va=\"top\", color=plt.get_cmap(\"autumn\")(0.35)\n", + " )\n", + " axes[2].text(\n", + " 6100,\n", + " 10.86,\n", + " \"Fit likelihood\",\n", + " ha=\"left\",\n", + " va=\"top\",\n", + " color=plt.get_cmap(\"winter_r\")(0.65),\n", + " )\n", + " axes[2].text(4500, 10.73, r\"Posterior\", ha=\"left\", va=\"top\", color=\"black\")\n", + " axes[2].text(\n", + " 6300,\n", + " 10.972,\n", + " r\"1$\\sigma$\",\n", + " va=\"center\",\n", + " ha=\"center\",\n", + " color=plt.get_cmap(\"winter_r\")(0.55),\n", + " fontsize=9,\n", + " )\n", + " axes[2].text(\n", + " 6300,\n", + " 10.913,\n", + " r\"2$\\sigma$\",\n", + " va=\"center\",\n", + " ha=\"center\",\n", + " color=plt.get_cmap(\"winter_r\")(0.45),\n", + " fontsize=9,\n", + " )\n", + " axes[2].text(\n", + " 4680,\n", + " 11.3,\n", + " r\"1$\\sigma$\",\n", + " va=\"center\",\n", + " ha=\"center\",\n", + " color=plt.get_cmap(\"autumn\")(0.45),\n", + " fontsize=9,\n", + " )\n", + " axes[2].text(\n", + " 5000,\n", + " 11.3,\n", + " r\"2$\\sigma$\",\n", + " va=\"center\",\n", + " ha=\"center\",\n", + " color=plt.get_cmap(\"autumn\")(0.55),\n", + " fontsize=9,\n", + " )\n", + " axes[2].text(\n", + " 4850, 10.866, r\"1$\\sigma$\", va=\"center\", ha=\"center\", color=\"black\", fontsize=9\n", + " )\n", + " axes[2].text(\n", + " 4500, 10.8, r\"2$\\sigma$\", va=\"center\", ha=\"center\", color=\"black\", fontsize=9\n", + " )\n", + " axes[2].text(\n", + " 0.96,\n", + " 0.96,\n", + " r\"$\\bf{c)}$ Equivalent width fit\",\n", + " ha=\"right\",\n", + " va=\"top\",\n", + " transform=axes[2].transAxes,\n", + " )\n", + " axes[2].set_yticks(np.arange(10.6, 11.41, 0.1), minor=True)\n", + "\n", " #######\n", - " \n", + "\n", " plt.show()" ] }, @@ -8283,9 +1766,7 @@ "id": "a10c1b00", "metadata": {}, "source": [ - "# -------------------\n", - "\n", - "# Retrieval of the observed helium spectrum of TOI-2134 b\n", + "## Retrieval of the observed helium spectrum of TOI-2134 b\n", "\n", "Having seen how a typical analysis is performed, we now move on to interpreting the helium spectrum of a real planet: TOI-2134 b. We perform the analysis for two different atmospheric compositions. The steps in principle are the same as before, so we do not repeat much of the explanations. As we are working with spectrally resolved data, we use a flat prior here. However, we also calculate the model self-consistency like we did before, simply to demonstrate that there is interesting physics going on here, since the self-consistent temperature is very different from that indicated by the data fit. So in this case we do not convert that self-consistency measure into a prior." ] @@ -8338,1055 +1819,70 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "4937b2d6", "metadata": {}, "outputs": [], "source": [ "def gaussian(x, amplitude, mean, std_dev):\n", - " return amplitude * np.exp(-((x - mean) / std_dev) ** 2 / 2)" + " return amplitude * np.exp(-(((x - mean) / std_dev) ** 2) / 2)" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "id": "4459f3c1", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "There is a 0.1791344919038238 angstrom shift of the line from rest-frame, which we now shift back.\n" - ] - }, - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_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('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", - "\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.canvas_div.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", - "function 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", - " */\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", - " 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", - "\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" - } - ], + "outputs": [], "source": [ - "observed_spec_toi2134 = pd.read_table('materials/dbf2.txt', skiprows=13, \n", - " names=['wav', 'ea', 'sig_ea'], delim_whitespace=True)\n", + "observed_spec_toi2134 = pd.read_table(\n", + " \"materials/dbf2.txt\",\n", + " skiprows=13,\n", + " names=[\"wav\", \"ea\", \"sig_ea\"],\n", + " delim_whitespace=True,\n", + ")\n", "observed_spec_toi2134.dropna(inplace=True)\n", "\n", - "#fit a Gaussian to the peak of the data to obtain the line center\n", - "params, covariance = curve_fit(gaussian,\n", - " observed_spec_toi2134.wav[(observed_spec_toi2134.wav > 10832.5) & (observed_spec_toi2134.wav < 10833.8)],\n", - " observed_spec_toi2134.ea[(observed_spec_toi2134.wav > 10832.5) & (observed_spec_toi2134.wav < 10833.8)],\n", - " p0=[0.4, 10833., 0.5])\n", + "# fit a Gaussian to the peak of the data to obtain the line center\n", + "params, covariance = curve_fit(\n", + " gaussian,\n", + " observed_spec_toi2134.wav[\n", + " (observed_spec_toi2134.wav > 10832.5) & (observed_spec_toi2134.wav < 10833.8)\n", + " ],\n", + " observed_spec_toi2134.ea[\n", + " (observed_spec_toi2134.wav > 10832.5) & (observed_spec_toi2134.wav < 10833.8)\n", + " ],\n", + " p0=[0.4, 10833.0, 0.5],\n", + ")\n", "offset = params[1] - 10833.25\n", - "print(\"There is a\", offset, \"angstrom shift of the line from rest-frame, which we now shift back.\")\n", + "print(\n", + " \"There is a\",\n", + " offset,\n", + " \"angstrom shift of the line from rest-frame, which we now shift back.\",\n", + ")\n", "observed_spec_toi2134.wav = observed_spec_toi2134.wav - offset\n", "\n", "\n", - "#we will not fit the whole dataset, but only the part between 10831 and 10836 angstroms\n", - "obs_wav_toi2134 = observed_spec_toi2134.wav[(observed_spec_toi2134.wav > 10831) & (observed_spec_toi2134.wav < 10836)].values\n", - "obs_ea_toi2134 = observed_spec_toi2134.ea[(observed_spec_toi2134.wav > 10831) & (observed_spec_toi2134.wav < 10836)].values\n", - "obs_sig_ea_toi2134 = observed_spec_toi2134.sig_ea[(observed_spec_toi2134.wav > 10831) & (observed_spec_toi2134.wav < 10836)].values\n", + "# we will not fit the whole dataset, but only the part between 10831 and 10836 angstroms\n", + "obs_wav_toi2134 = observed_spec_toi2134.wav[\n", + " (observed_spec_toi2134.wav > 10831) & (observed_spec_toi2134.wav < 10836)\n", + "].values\n", + "obs_ea_toi2134 = observed_spec_toi2134.ea[\n", + " (observed_spec_toi2134.wav > 10831) & (observed_spec_toi2134.wav < 10836)\n", + "].values\n", + "obs_sig_ea_toi2134 = observed_spec_toi2134.sig_ea[\n", + " (observed_spec_toi2134.wav > 10831) & (observed_spec_toi2134.wav < 10836)\n", + "].values\n", "\n", "\n", "fig, ax = plt.subplots(1)\n", "ax.errorbar(obs_wav_toi2134, obs_ea_toi2134, yerr=obs_sig_ea_toi2134)\n", - "ax.axvline(10832.057472, color='k', linestyle='dotted')\n", - "ax.axvline(10833.216751, color='k', linestyle='dotted')\n", - "ax.axvline(10833.306444, color='k', linestyle='dotted')\n", - "ax.set_xlabel('Wavelength [Å]')\n", - "ax.set_ylabel('Excess absorption [%]')\n", - "ax.set_title('TOI-2134 b observations by Zhang et al. 2023 (shifted)')\n", + "ax.axvline(10832.057472, color=\"k\", linestyle=\"dotted\")\n", + "ax.axvline(10833.216751, color=\"k\", linestyle=\"dotted\")\n", + "ax.axvline(10833.306444, color=\"k\", linestyle=\"dotted\")\n", + "ax.set_xlabel(\"Wavelength [Å]\")\n", + "ax.set_ylabel(\"Excess absorption [%]\")\n", + "ax.set_title(\"TOI-2134 b observations by Zhang et al. 2023 (shifted)\")\n", "plt.show()" ] }, @@ -9400,35 +1896,39 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "id": "2a3b9cf2", "metadata": {}, "outputs": [], "source": [ - "#chisqs_z0 = calc_chisqs_He10830(tools.projectpath+'/sims/1D/TOI2134b/z_0/', \n", - "# obs_wav_toi2134, obs_ea_toi2134, obs_sig_ea_toi2134, \n", + "# chisqs_z0 = calc_chisqs_He10830(tools.projectpath+'/sims/1D/TOI2134b/z_0/',\n", + "# obs_wav_toi2134, obs_ea_toi2134, obs_sig_ea_toi2134,\n", "# instrument_R=32000, Mdotstep=0.02)\n", - "#chisqs_z0.to_csv('materials/TOI2134b_chisqs_fit_z0.csv') #overwrites the supplied file\n", + "# chisqs_z0.to_csv('materials/TOI2134b_chisqs_fit_z0.csv') #overwrites the supplied file\n", "#\n", - "#chisqs_z100 = calc_chisqs_He10830(tools.projectpath+'/sims/1D/TOI2134b/z_100/',\n", + "# chisqs_z100 = calc_chisqs_He10830(tools.projectpath+'/sims/1D/TOI2134b/z_100/',\n", "# obs_wav_toi2134, obs_ea_toi2134, obs_sig_ea_toi2134,\n", "# instrument_R=32000, Mdotstep=0.02)\n", - "#chisqs_z100.to_csv('materials/TOI2134b_chisqs_fit_z100.csv') #overwrites the supplied file" + "# chisqs_z100.to_csv('materials/TOI2134b_chisqs_fit_z100.csv') #overwrites the supplied file" ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "id": "0ed5d4f3", "metadata": {}, "outputs": [], "source": [ - "#read the chi-squared values from file\n", - "chisqs_z0 = pd.read_csv('materials/TOI2134b_chisqs_fit_z0.csv', index_col=0, dtype=float)\n", + "# read the chi-squared values from file\n", + "chisqs_z0 = pd.read_csv(\n", + " \"materials/TOI2134b_chisqs_fit_z0.csv\", index_col=0, dtype=float\n", + ")\n", "\n", - "chisqs_z100 = pd.read_csv('materials/TOI2134b_chisqs_fit_z100.csv', index_col=0, dtype=float)\n", + "chisqs_z100 = pd.read_csv(\n", + " \"materials/TOI2134b_chisqs_fit_z100.csv\", index_col=0, dtype=float\n", + ")\n", "\n", - "#from chi-squared, we can calculate the likelihood\n", + "# from chi-squared, we can calculate the likelihood\n", "likelihood_z0 = calc_likelihood_resolved(chisqs_z0)\n", "\n", "likelihood_z100 = calc_likelihood_resolved(chisqs_z100)" @@ -9444,1010 +1944,17 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "id": "73648232", "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_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('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", - "\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.canvas_div.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", - "function 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", - " */\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", - " 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", - "\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" - } - ], + "outputs": [], "source": [ - "plot_chisq_fit(chisqs_z0, bounds_T0=(2000,8000), bounds_Mdot=(8.5,10), title=\"TOI-2134 b, pure H/He\")" + "plot_chisq_fit(\n", + " chisqs_z0,\n", + " bounds_T0=(2000, 8000),\n", + " bounds_Mdot=(8.5, 10),\n", + " title=\"TOI-2134 b, pure H/He\",\n", + ")" ] }, { @@ -10480,33 +1987,35 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "id": "60e3c65c", "metadata": {}, "outputs": [], "source": [ - "#dT_z0, sigmaT_z0 = calc_dT_helium(tools.projectpath+'/sims/1D/TOI2134b/z_0', Mdotstep=0.02)\n", - "#dT_z0.to_csv('materials/TOI2134b_dT_z0.csv', float_format='%.3e') #overwrites the supplied files\n", - "#sigmaT_z0.to_csv('materials/TOI2134b_sigmaT_z0.csv', float_format='%.3e')\n", + "# dT_z0, sigmaT_z0 = calc_dT_helium(tools.projectpath+'/sims/1D/TOI2134b/z_0', Mdotstep=0.02)\n", + "# dT_z0.to_csv('materials/TOI2134b_dT_z0.csv', float_format='%.3e') #overwrites the supplied files\n", + "# sigmaT_z0.to_csv('materials/TOI2134b_sigmaT_z0.csv', float_format='%.3e')\n", "\n", - "#dT_z100, sigmaT_z100 = calc_dT_helium(tools.projectpath+'/sims/1D/TOI2134b/z_100', Mdotstep=0.02)\n", - "#dT_z100.to_csv('materials/TOI2134b_dT_z100.csv', float_format='%.3e') #overwrites the supplied files\n", - "#sigmaT_z100.to_csv('materials/TOI2134b_sigmaT_z100.csv', float_format='%.3e')" + "# dT_z100, sigmaT_z100 = calc_dT_helium(tools.projectpath+'/sims/1D/TOI2134b/z_100', Mdotstep=0.02)\n", + "# dT_z100.to_csv('materials/TOI2134b_dT_z100.csv', float_format='%.3e') #overwrites the supplied files\n", + "# sigmaT_z100.to_csv('materials/TOI2134b_sigmaT_z100.csv', float_format='%.3e')" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "id": "1087d9c1", "metadata": {}, "outputs": [], "source": [ - "#load the dT and sigmaT values from file\n", - "dT_z0 = pd.read_csv('materials/TOI2134b_dT_z0.csv', index_col=0, dtype=float)\n", - "sigmaT_z0 = pd.read_csv('materials/TOI2134b_sigmaT_z0.csv', index_col=0, dtype=float) \n", - "\n", - "dT_z100 = pd.read_csv('materials/TOI2134b_dT_z100.csv', index_col=0, dtype=float)\n", - "sigmaT_z100 = pd.read_csv('materials/TOI2134b_sigmaT_z100.csv', index_col=0, dtype=float)" + "# load the dT and sigmaT values from file\n", + "dT_z0 = pd.read_csv(\"materials/TOI2134b_dT_z0.csv\", index_col=0, dtype=float)\n", + "sigmaT_z0 = pd.read_csv(\"materials/TOI2134b_sigmaT_z0.csv\", index_col=0, dtype=float)\n", + "\n", + "dT_z100 = pd.read_csv(\"materials/TOI2134b_dT_z100.csv\", index_col=0, dtype=float)\n", + "sigmaT_z100 = pd.read_csv(\n", + " \"materials/TOI2134b_sigmaT_z100.csv\", index_col=0, dtype=float\n", + ")" ] }, { @@ -10519,30 +2028,17 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "id": "18bfd116", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Constraints from marginalized posteriors (not necessarily normally distributed!):\n", - "log10(Mdot) = 9.28 + 0.0600000000000005 - 0.03999999999999915\n", - "T0 = 5000.0 + 400.0 - 400.0\n", - "Constraints from marginalized posteriors (not necessarily normally distributed!):\n", - "log10(Mdot) = 9.68 + 0.040000000000000924 - 0.03999999999999915\n", - "T0 = 9700.0 + 700.0 - 700.0\n" - ] - } - ], + "outputs": [], "source": [ - "#we calculate the posterior with a flat prior\n", - "#we do this only so that calc_posterior() prints the constrained T0 and Mdot based on\n", - "#the likelihood alone, which we can then quote\n", - "posterior_z0 = calc_posterior(1., likelihood_z0)\n", + "# we calculate the posterior with a flat prior\n", + "# we do this only so that calc_posterior() prints the constrained T0 and Mdot based on\n", + "# the likelihood alone, which we can then quote\n", + "posterior_z0 = calc_posterior(1.0, likelihood_z0)\n", "\n", - "posterior_z100 = calc_posterior(1., likelihood_z100)" + "posterior_z100 = calc_posterior(1.0, likelihood_z100)" ] }, { @@ -10555,30 +2051,38 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "id": "230fec93", "metadata": {}, "outputs": [], "source": [ - "sim_z0_5000 = tools.Sim(tools.projectpath+'/sims/1D/TOI2134b/z_0/parker_5000_9.280/converged') #best-fit\n", - "sim_z0_2600 = tools.Sim(tools.projectpath+'/sims/1D/TOI2134b/z_0/parker_2600_8.800/converged') #self-consistent T\n", - "sim_z100_9700 = tools.Sim(tools.projectpath+'/sims/1D/TOI2134b/z_100/parker_9700_9.680/converged') #best-fit\n", - "sim_z100_4000 = tools.Sim(tools.projectpath+'/sims/1D/TOI2134b/z_100/parker_4000_9.100/converged') #self-consistent T\n", - "\n", - "#calculate spectra\n", + "sim_z0_5000 = tools.Sim(\n", + " tools.projectpath + \"/sims/1D/TOI2134b/z_0/parker_5000_9.280/converged\"\n", + ") # best-fit\n", + "sim_z0_2600 = tools.Sim(\n", + " tools.projectpath + \"/sims/1D/TOI2134b/z_0/parker_2600_8.800/converged\"\n", + ") # self-consistent T\n", + "sim_z100_9700 = tools.Sim(\n", + " tools.projectpath + \"/sims/1D/TOI2134b/z_100/parker_9700_9.680/converged\"\n", + ") # best-fit\n", + "sim_z100_4000 = tools.Sim(\n", + " tools.projectpath + \"/sims/1D/TOI2134b/z_100/parker_4000_9.100/converged\"\n", + ") # self-consistent T\n", + "\n", + "# calculate spectra\n", "wavsHe = np.linspace(10831, 10836, 200)\n", - "spec_z0_5000, _, _ = RT.FinFout(sim_z0_5000, wavsHe, 'He')\n", - "spec_z0_2600, _, _ = RT.FinFout(sim_z0_2600, wavsHe, 'He')\n", - "spec_z100_9700, _, _ = RT.FinFout(sim_z100_9700, wavsHe, 'He')\n", - "spec_z100_4000, _, _ = RT.FinFout(sim_z100_4000, wavsHe, 'He')\n", + "spec_z0_5000, _, _ = RT.FinFout(sim_z0_5000, wavsHe, \"He\")\n", + "spec_z0_2600, _, _ = RT.FinFout(sim_z0_2600, wavsHe, \"He\")\n", + "spec_z100_9700, _, _ = RT.FinFout(sim_z100_9700, wavsHe, \"He\")\n", + "spec_z100_4000, _, _ = RT.FinFout(sim_z100_4000, wavsHe, \"He\")\n", "\n", - "#convert Fin/Fout to excess absorption in %\n", + "# convert Fin/Fout to excess absorption in %\n", "ea_z0_5000 = (np.max(spec_z0_5000) - spec_z0_5000) * 100\n", "ea_z0_2600 = (np.max(spec_z0_2600) - spec_z0_2600) * 100\n", "ea_z100_9700 = (np.max(spec_z100_9700) - spec_z100_9700) * 100\n", "ea_z100_4000 = (np.max(spec_z100_4000) - spec_z100_4000) * 100\n", "\n", - "#convolve to instrument resolution\n", + "# convolve to instrument resolution\n", "ea_z0_5000 = RT.convolve_spectrum_R(wavsHe, ea_z0_5000, 32000)\n", "ea_z0_2600 = RT.convolve_spectrum_R(wavsHe, ea_z0_2600, 32000)\n", "ea_z100_9700 = RT.convolve_spectrum_R(wavsHe, ea_z100_9700, 32000)\n", @@ -10587,1049 +2091,138 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "id": "edb4de21", "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_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('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", - "\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.canvas_div.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", - "function 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", - " */\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", - " 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", - "\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" - } - ], + "outputs": [], "source": [ "with plt.rc_context({\"font.family\": \"serif\", \"mathtext.fontset\": \"dejavuserif\"}):\n", - " fig, axes = plt.subplots(ncols=1, nrows=3, figsize=(4.5,12))\n", + " fig, axes = plt.subplots(ncols=1, nrows=3, figsize=(4.5, 12))\n", "\n", " ##########\n", - " \n", - " plot_joint_constraint_resolved(dT_z0, sigmaT_z0, chisqs_z0, None, \n", - " bounds_T0=(2000,12000), bounds_Mdot = (8.5, 10), \n", - " fig=fig, ax=axes[0], show_colorbar=False)\n", - " \n", - " axes[0].text(0.96,0.96, r'$\\bf{a)}$'+' 91% H, 9% He', ha='right', va='top', transform=axes[0].transAxes)\n", - " axes[0].text(3600,9.7, 'Temperature self-consistency', ha='left', va='top', color=plt.get_cmap('autumn')(0.35))\n", - " axes[0].text(5400,9.24, 'Fit likelihood', ha='left', va='top', color=plt.get_cmap('winter_r')(0.65))\n", + "\n", + " plot_joint_constraint_resolved(\n", + " dT_z0,\n", + " sigmaT_z0,\n", + " chisqs_z0,\n", + " None,\n", + " bounds_T0=(2000, 12000),\n", + " bounds_Mdot=(8.5, 10),\n", + " fig=fig,\n", + " ax=axes[0],\n", + " show_colorbar=False,\n", + " )\n", + "\n", + " axes[0].text(\n", + " 0.96,\n", + " 0.96,\n", + " r\"$\\bf{a)}$\" + \" 91% H, 9% He\",\n", + " ha=\"right\",\n", + " va=\"top\",\n", + " transform=axes[0].transAxes,\n", + " )\n", + " axes[0].text(\n", + " 3600,\n", + " 9.7,\n", + " \"Temperature self-consistency\",\n", + " ha=\"left\",\n", + " va=\"top\",\n", + " color=plt.get_cmap(\"autumn\")(0.35),\n", + " )\n", + " axes[0].text(\n", + " 5400,\n", + " 9.24,\n", + " \"Fit likelihood\",\n", + " ha=\"left\",\n", + " va=\"top\",\n", + " color=plt.get_cmap(\"winter_r\")(0.65),\n", + " )\n", "\n", " ##########\n", - " \n", - " plot_joint_constraint_resolved(dT_z100, sigmaT_z100, chisqs_z100, None, \n", - " bounds_T0=(2000,12000), bounds_Mdot = (8.5, 10),\n", - " fig=fig, ax=axes[1], show_colorbar=False)\n", "\n", - " axes[1].text(0.96,0.96, r'$\\bf{b)}$'+' 100x solar metallicity', ha='right', va='top', transform=axes[1].transAxes)\n", - " axes[1].text(5100,8.7, 'Temperature self-consistency', ha='left', va='top', color=plt.get_cmap('autumn')(0.35))\n", - " axes[1].text(9000,9.58, 'Fit likelihood', ha='left', va='top', color=plt.get_cmap('winter_r')(0.65))\n", + " plot_joint_constraint_resolved(\n", + " dT_z100,\n", + " sigmaT_z100,\n", + " chisqs_z100,\n", + " None,\n", + " bounds_T0=(2000, 12000),\n", + " bounds_Mdot=(8.5, 10),\n", + " fig=fig,\n", + " ax=axes[1],\n", + " show_colorbar=False,\n", + " )\n", + "\n", + " axes[1].text(\n", + " 0.96,\n", + " 0.96,\n", + " r\"$\\bf{b)}$\" + \" 100x solar metallicity\",\n", + " ha=\"right\",\n", + " va=\"top\",\n", + " transform=axes[1].transAxes,\n", + " )\n", + " axes[1].text(\n", + " 5100,\n", + " 8.7,\n", + " \"Temperature self-consistency\",\n", + " ha=\"left\",\n", + " va=\"top\",\n", + " color=plt.get_cmap(\"autumn\")(0.35),\n", + " )\n", + " axes[1].text(\n", + " 9000,\n", + " 9.58,\n", + " \"Fit likelihood\",\n", + " ha=\"left\",\n", + " va=\"top\",\n", + " color=plt.get_cmap(\"winter_r\")(0.65),\n", + " )\n", "\n", " ##########\n", "\n", - " axes[2].errorbar(obs_wav_toi2134, obs_ea_toi2134, yerr=obs_sig_ea_toi2134, \n", - " fmt='o', color='black', zorder=-100, lw=2)\n", - " axes[2].plot(wavsHe, ea_z0_5000, label=r'H/He, $T_0$=5000', color='dodgerblue', lw=2)\n", - " axes[2].plot(wavsHe, ea_z100_9700, label=r'100x, $T_0$=9700', color='crimson', lw=2)\n", - " axes[2].plot(wavsHe, ea_z0_2600, label=r'H/He, $T_0$=2600', color='dodgerblue', linestyle='dashed', lw=2)\n", - " axes[2].plot(wavsHe, ea_z100_4000, label=r'100x, $T_0$=4000', color='crimson', linestyle='dashed', lw=2)\n", - " axes[2].text(0.96,0.04, r'$\\bf{c)}$', ha='right', va='bottom', transform=axes[2].transAxes)\n", - " axes[2].xaxis.set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, _: '{:g}'.format(x)))\n", - " axes[2].set_xlabel('Wavelength [Å]')\n", - " axes[2].set_ylabel('Excess absorption [%]')\n", - " axes[2].legend(loc=\"upper right\", edgecolor='none', facecolor='none', framealpha=0, ncols=2)\n", + " axes[2].errorbar(\n", + " obs_wav_toi2134,\n", + " obs_ea_toi2134,\n", + " yerr=obs_sig_ea_toi2134,\n", + " fmt=\"o\",\n", + " color=\"black\",\n", + " zorder=-100,\n", + " lw=2,\n", + " )\n", + " axes[2].plot(\n", + " wavsHe, ea_z0_5000, label=r\"H/He, $T_0$=5000\", color=\"dodgerblue\", lw=2\n", + " )\n", + " axes[2].plot(wavsHe, ea_z100_9700, label=r\"100x, $T_0$=9700\", color=\"crimson\", lw=2)\n", + " axes[2].plot(\n", + " wavsHe,\n", + " ea_z0_2600,\n", + " label=r\"H/He, $T_0$=2600\",\n", + " color=\"dodgerblue\",\n", + " linestyle=\"dashed\",\n", + " lw=2,\n", + " )\n", + " axes[2].plot(\n", + " wavsHe,\n", + " ea_z100_4000,\n", + " label=r\"100x, $T_0$=4000\",\n", + " color=\"crimson\",\n", + " linestyle=\"dashed\",\n", + " lw=2,\n", + " )\n", + " axes[2].text(\n", + " 0.96, 0.04, r\"$\\bf{c)}$\", ha=\"right\", va=\"bottom\", transform=axes[2].transAxes\n", + " )\n", + " axes[2].xaxis.set_major_formatter(\n", + " matplotlib.ticker.FuncFormatter(lambda x, _: \"{:g}\".format(x))\n", + " )\n", + " axes[2].set_xlabel(\"Wavelength [Å]\")\n", + " axes[2].set_ylabel(\"Excess absorption [%]\")\n", + " axes[2].legend(\n", + " loc=\"upper right\", edgecolor=\"none\", facecolor=\"none\", framealpha=0, ncols=2\n", + " )\n", " axes[2].set_ylim(-0.15, 0.55)\n", "\n", " ##########\n", - " \n", + "\n", " plt.show()" ] }, @@ -11640,6 +2233,14 @@ "source": [ "We see that the temperature obtained from the line fit is very different from the self-consistency constraint. In Linssen et al. (2024), we discuss the temperature discrepancy between the line fit and the self-consistency in more detail." ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a340366-3cc8-4764-8773-2222a540ec7d", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -11658,7 +2259,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.0" + "version": "3.12.7" } }, "nbformat": 4, diff --git a/examples/predict_UV.ipynb b/examples/predict_UV.ipynb index 61af898..47ea8e9 100644 --- a/examples/predict_UV.ipynb +++ b/examples/predict_UV.ipynb @@ -2,10 +2,35 @@ "cells": [ { "cell_type": "markdown", - "id": "f1846bd0", + "id": "28e6aaa4-3704-474d-a257-62ef4d0c052f", + "metadata": {}, + "source": [ + "# Example: Predict UV" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af8b8894-0d32-4158-ac8d-87fad3c7ad93", "metadata": {}, + "outputs": [], + "source": [ + "import sunbather\n", + "sunbather.firstrun(quiet=True)" + ] + }, + { + "cell_type": "markdown", + "id": "f1846bd0", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "source": [ - "# License\n", + "## License\n", "\n", "The code in this notebook is free to be used, edited and redistributed by anyone free of charge. Please cite Linssen et al. (in prep) when making use of _sunbather_ and/or the code in this notebook." ] @@ -15,7 +40,7 @@ "id": "d3b01a8a", "metadata": {}, "source": [ - "# Example goal\n", + "## Example goal\n", "\n", "In this example notebook, we predict the NUV spectrum of WASP-52 b to see if the signatures of escaping metal species are strong enough to be potentially observable with HST/STIS. In the *fit_helium.ipynb* example notebook, we constrained the mass-loss rate and thermospheric temperature of the planet based on metastable helium observations (the examples can be done in any order). Here, we use those constrained values and make NUV predictions. Since we do not know the (upper) atmospheric metallicity of WASP-52 b, we will explore three different models; one assuming solar metallicity, one assuming 10x solar metallicity, and one assuming 10x solar metallicity but a 100x solar magnesium abundance. " ] @@ -25,7 +50,7 @@ "id": "8603e0ac", "metadata": {}, "source": [ - "# Example layout\n", + "## Example layout\n", "\n", "The analysis consists of three main steps:\n", "\n", @@ -41,35 +66,82 @@ "id": "52a4caf3", "metadata": {}, "source": [ - "# Preparation\n", + "## Preparation\n", "\n", "For this exercise, we assume you have all codes set-up. That is; you have downloaded *sunbather* and installed its dependencies (the Python packages, including *p-winds*). You have installed *Cloudy v17.02* and have the path to it stored as your _\\$CLOUDY_PATH_ environmental variable. You have created your \"project\" folder, and have the path to it stored as your _\\$SUNBATHER_PROJECT_PATH_ environmental variable. You have copied the _planets.txt_ file to the project path. These steps are described in more detail in the \"installation\" section of the _sunbather_ wiki.\n", "\n", - "Before *sunbather* can create Parker wind profiles, we need to make sure the parameters of the system are available to the code. The parameters are stored in the _\\$SUNBATHER_PROJECT_PATH/planets.txt_ file, and the parameters of the WASP-52 b system have already been added. If you want to model additional planets, you can simply add lines in the _planets.txt_ file with their parameters, there is no need to replace previous planet parameters. The last column of the _planets.txt_ file specifies the **name** of the stellar SED that we want to use. The SED with exactly this name must be available to *Cloudy*, so it must be placed in its source folder, specifically: _\\$CLOUDY_PATH/data/SED/_. In the _/sunbather/stellar_SEDs/_ folder, we have provided the SED that we are going to use for WASP-52 b. This is the MUSCLES spectrum (France et al. 2016; Youngblood et al. 2016; Loyd et al. 2016) of eps Eri, which is a similar spectral type to WASP-52. The code is very specific about the format of the spectrum, so we refer to the wiki on how to prep your stellar SED for *sunbather*. \n", - "> **The only step you need to take here, is make sure the eps_Eri_binned.spec is in Cloudy's SED folder: $CLOUDY_PATH/data/SED/ (so copy/move it there).**" + "Before *sunbather* can create Parker wind profiles, we need to make sure the parameters of the system are available to the code. The parameters are stored in the _\\$SUNBATHER_PROJECT_PATH/planets.txt_ file, and the parameters of the WASP-52 b system have already been added. If you want to model additional planets, you can simply add lines in the _planets.txt_ file with their parameters, there is no need to replace previous planet parameters. The last column of the _planets.txt_ file specifies the **name** of the stellar SED that we want to use. The SED with exactly this name must be available to *Cloudy*, so it must be placed in its source folder, specifically: _\\$CLOUDY_PATH/data/SED/_. In the _/sunbather/stellar_SEDs/_ folder, we have provided the SED that we are going to use for WASP-52 b. This is the MUSCLES spectrum (France et al. 2016; Youngblood et al. 2016; Loyd et al. 2016) of eps Eri, which is a similar spectral type to WASP-52. The code is very specific about the format of the spectrum, so we refer to the wiki on how to prep your stellar SED for *sunbather*. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f3a65c4-8c80-4dc2-9da8-de8bb27e564c", + "metadata": {}, + "outputs": [], + "source": [ + "# The only step you need to take here, is to ensure the eps_Eri_binned.spec file\n", + "# is in Cloudy's SED folder:\n", + "import os.path\n", + "cloudypath = sunbather.tools.get_cloudy_path()\n", + "os.path.exists(f\"{cloudypath}/data/SED/eps_Eri_binned.spec\")" ] }, { "cell_type": "markdown", - "id": "0f1fd603", + "id": "b6b85abb-2118-4b17-8be6-eafe91bad824", "metadata": {}, "source": [ - "# Step 1: Create Parker wind profiles with p-winds/Cloudy\n", - "\n", - "This step can be done by calling `construct_parker.py` from the command-line with the proper arguments. Running `python construct_parker.py --help` will give an overview of the available arguments. In this module, the atmospheric composition/metallicity only affects the structure through the mean molecular weight $\\mu$. At solar metallicity, the metal content is low enough to not significantly affect $\\mu$, so we will make the Parker wind profile with *p-winds* standalone, assuming a pure H/He composition of 90/10. At 10x solar metallicity, $\\mu$ may be significantly affected by the metal content, so we will make the Parker wind profile with a hybrid *p-winds*/_Cloudy_ calculation. In Step 2 of this example, we will use this profile also for the run with an enhanced magnesium abundance, since $\\mu$ (and hence the structure we calculate here in step 1) will not change much when increasing the abundance of just one metal species.\n", - "\n", - "To make the profile with a 90% hydrogen, 10% helium composition, we pass `-fH 0.9`. We will only make a profile for the constrained temperature of 9200 K and mass-loss rate of $\\dot{M}=10^{11.3}$ g/s, so we pass `-T 9200` and `-Mdot 11.3`. Since we explore different compositions, `construct_parker.py` always expects you to give a folder name `-pdir` where we want to store our Parker profiles. We reccommend using a descriptive name, so in this case we will go with *fH_0.9* and the path where our profiles will be saved is then _$SUNBATHER_PROJECT_PATH/parker_profiles/WASP52b/fH_0.9/_.\n", + "## Step 1: Create Parker wind profiles with p-winds/Cloudy\n", "\n", - "> **The full command to create our first Parker wind model thus becomes - go ahead and run it**:

\n", - "> `python construct_parker.py -plname WASP52b -pdir fH_0.9 -T 9200 -Mdot 11.3 -fH 0.9`\n", + "This step can be done by calling `sunbather.construct_parker.run` with the proper keyword arguments. Calling `help(sunbather.construct_parker.run)` will give an overview of the available arguments. In this module, the atmospheric composition/metallicity only affects the structure through the mean molecular weight $\\mu$. At solar metallicity, the metal content is low enough to not significantly affect $\\mu$, so we will make the Parker wind profile with *p-winds* standalone, assuming a pure H/He composition of 90/10. At 10x solar metallicity, $\\mu$ may be significantly affected by the metal content, so we will make the Parker wind profile with a hybrid *p-winds*/_Cloudy_ calculation. In Step 2 of this example, we will use this profile also for the run with an enhanced magnesium abundance, since $\\mu$ (and hence the structure we calculate here in step 1) will not change much when increasing the abundance of just one metal species.\n", "\n", + "To make the profile with a 90% hydrogen, 10% helium composition, we pass `fraction_hydrogen=0.9`. We will only make a profile for the constrained temperature of 9200 K and mass-loss rate of $\\dot{M}=10^{11.3}$ g/s, so we pass `temp=9200` and `mdot=11.3`. Since we explore different compositions, `construct_parker` always expects you to give a folder name `pdir` where we want to store our Parker profiles. We reccommend using a descriptive name, so in this case we will go with *fH_0.9* and the path where our profiles will be saved is then _$SUNBATHER_PROJECT_PATH/parker_profiles/WASP52b/fH_0.9/_." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "76969515-c0a5-432e-af53-eee9d48934b5", + "metadata": {}, + "outputs": [], + "source": [ + "# The full command to create our first Parker wind model thus becomes - go ahead and run it:\n", + "import sunbather.construct_parker\n", + "sunbather.construct_parker.run(\n", + " plname=\"WASP52b\", pdir=\"fH_0.9\", temp=9200, mdot=11.3, fraction_hydrogen=0.9, overwrite=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "8e94c6ec-3826-48fd-b910-bd13c1f8571d", + "metadata": {}, + "source": [ "For this set of parameters, this command should take on the order of 1 second (but it depends on your machine).\n", "\n", - "To make the 10x solar metallicity profile, instead of the `-fH` argument, we use `-z 10`. We don't want this profile to overwrite the file we just saved for H/He only, so we provide a different `-pdir`. \n", - "\n", - "> **The full command to create our second Parker wind model thus becomes - go ahead and run it**:

\n", - "> `python construct_parker.py -plname WASP52b -pdir z_10 -T 9200 -Mdot 11.3 -z 10`\n", - "\n", + "To make the 10x solar metallicity profile, instead of the `-fH` argument, we use `-z 10`. We don't want this profile to overwrite the file we just saved for H/He only, so we provide a different `-pdir`. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2bab02aa-13cf-4485-a6fd-47aca1cdef46", + "metadata": {}, + "outputs": [], + "source": [ + "# The full command to create our second Parker wind model thus becomes - go ahead and run it:\n", + "zdict = sunbather.tools.get_zdict(z=10)\n", + "sunbather.construct_parker.run(\n", + " plname=\"WASP52b\", pdir=\"z_10\", temp=9200, mdot=11.3, zdict=zdict, overwrite=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "2530de2e-176f-4015-a50e-37767a62e074", + "metadata": {}, + "source": [ "For this set of parameters, this command should take on the order of 3 minutes (but it depends on your machine). If it exits with the error that the _Cloudy_ simulation went wrong (because of negative calcium abundance), try again while passing `-zelem Ca=0`.\n", "\n", "In the _$SUNBATHER_PROJECT_PATH/parker_profiles/WASP52b/_ folder, there should now be 2 subfolders, each containing a .txt file with the isothermal Parker wind structure, feel free to inspect them!" @@ -77,24 +149,77 @@ }, { "cell_type": "markdown", - "id": "74bf94f4", + "id": "e7f792ef-e15b-4374-8672-454fd471f168", "metadata": {}, "source": [ - "# Step 2: Run the Parker wind profiles through Cloudy\n", - "\n", - "This step can be done by calling `convergeT_parker.py` from the command-line with the proper arguments The $T_0$ and $\\dot{M}$ commands are the same as in Step 1 of this example. We need to specify a folder name where we want to save our *Cloudy* simulations. For the solar composition we will use `-dir z_1`. We also need to specify the folder where we want to read the Parker wind profiles from, so `-pdir fH_0.9`. The last thing we need to think about, is for which atomic/ionic species we want to save *Cloudy's* output. Since many different metal species absorb in the UV, we will save everything that's available, which is the default behavior of the `-save_sp` flag (so we do not need to specify it here), but does result in a rather large file size of ~5 MB.\n", - "\n", - "> **The command to run our solar composition Parker wind model through *Cloudy* thus becomes - go ahead and run it**:

\n", - "> `python convergeT_parker.py -plname WASP52b -dir z_1 -pdir fH_0.9 -T 9200 -Mdot 11.3`\n", - "\n", - "For the 10x solar metallicity model, we need to make sure we specify `-pdir z_10` to read the Parker wind profile from the correct folder. We will save the _Cloudy_ runs in `-dir z_10`, and we also need to tell _Cloudy_ to actually use a 10x solar metallicity with `-z 10`. \n", - "> **The command to run our 10x solar metallicity Parker wind model through *Cloudy* thus becomes - go ahead and run it**:

\n", - "> `python convergeT_parker.py -plname WASP52b -dir z_10 -pdir z_10 -T 9200 -Mdot 11.3 -z 10`\n", - "\n", - "Finally for the model with 10x solar metallicity, but 100x solar magnesium abundance, we choose a different output folder `-dir z_10_Mg10`, but we can use the same `-pdir` as before (see explanation under Step 1 of this example). Since we already have an overall scaling factor of 10 for all the metals, we have to pass `-zelem Mg=10` to scale magnesium by another factor of 10 to get a 100x solar abundance.\n", - "> **The command to run our 10x solar metallicity with enhanced magnesium Parker wind model through *Cloudy* thus becomes - go ahead and run it**:

\n", - "> `python convergeT_parker.py -plname WASP52b -dir z_10_Mg10 -pdir z_10 -T 9200 -Mdot 11.3 -z 10 -zelem Mg=10`\n", + "## Step 2: Run the Parker wind profiles through Cloudy\n", "\n", + "This step can be done by calling `convergeT_parker.py` from the command-line with the proper arguments The $T_0$ and $\\dot{M}$ commands are the same as in Step 1 of this example. We need to specify a folder name where we want to save our *Cloudy* simulations. For the solar composition we will use `-dir z_1`. We also need to specify the folder where we want to read the Parker wind profiles from, so `-pdir fH_0.9`. The last thing we need to think about, is for which atomic/ionic species we want to save *Cloudy's* output. Since many different metal species absorb in the UV, we will save everything that's available, which is the default behavior of the `-save_sp` flag (so we do not need to specify it here), but does result in a rather large file size of ~5 MB." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4785b7d6-0386-4abf-88e1-30bc2c95e53e", + "metadata": {}, + "outputs": [], + "source": [ + "# The command to run our solar composition Parker wind model through *Cloudy* thus becomes\n", + "# - go ahead and run it:\n", + "import sunbather.convergeT_parker\n", + "sunbather.convergeT_parker.run(\n", + " plname=\"WASP52b\", workingdir=\"z_1\", pdir=\"fH_0.9\", temp=9200, mdot=11.3, overwrite=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "9a58d9f3-0018-48fb-af55-c59415a53ec2", + "metadata": {}, + "source": [ + "For the 10x solar metallicity model, we need to make sure we specify `-pdir z_10` to read the Parker wind profile from the correct folder. We will save the _Cloudy_ runs in `-dir z_10`, and we also need to tell _Cloudy_ to actually use a 10x solar metallicity with `-z 10`. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aba44b46-fd01-4726-8253-fd171bbfaeb0", + "metadata": {}, + "outputs": [], + "source": [ + "# **The command to run our 10x solar metallicity Parker wind model through *Cloudy* thus becomes - go ahead and run it**:

\n", + "zdict = sunbather.tools.get_zdict(z=10)\n", + "sunbather.convergeT_parker.run(\n", + " plname=\"WASP52b\", workingdir=\"z_10\", pdir=\"z_10\", temp=9200, mdot=11.3, zdict=zdict,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "1aec36da-a707-4f61-879e-6469ad98f0f2", + "metadata": {}, + "source": [ + "Finally for the model with 10x solar metallicity, but 100x solar magnesium abundance, we choose a different output folder `-workingdir z_10_Mg10`, but we can use the same `-pdir` as before (see explanation under Step 1 of this example). Since we already have an overall scaling factor of 10 for all the metals, we have to pass `-zelem Mg=10` to scale magnesium by another factor of 10 to get a 100x solar abundance." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea96e73a-aa59-4cb8-9977-2753e6c0a5df", + "metadata": {}, + "outputs": [], + "source": [ + "# **The command to run our 10x solar metallicity with enhanced magnesium Parker wind model through *Cloudy* thus becomes - go ahead and run it**:

\n", + "sunbather.convergeT_parker.run(\n", + " plname=\"WASP52b\", workingdir=\"z_10_Mg10\", pdir=\"z_10\", temp=9200, mdot=11.3, z=10, zelem={\"Mg\": 10},\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "d63ec328-f8f6-4ca6-8b59-b5abb22749d3", + "metadata": {}, + "source": [ "For these parameters, all commands together should take on the order of 35 minutes (but it depends on your machine). In the *$SUNBATHER_PROJECT_PATH/sims/1D/WASP52b/fH_0.9/* and */.../z_10/* and */.../z_10_Mg10/* folders, there should now be a sub-folder (or more if you also did the _fit_helium.ipynb_ example notebook), with the output of the _Cloudy_ simulation, feel free to inspect the files! The _converged.png_ file shows the converged temperature structure, and the other _converged.*_ files are the _Cloudy_ output files." ] }, @@ -103,7 +228,7 @@ "id": "84fa611b", "metadata": {}, "source": [ - "# Step 3: Make NUV transit spectra\n", + "## Step 3: Make NUV transit spectra\n", "\n", "To make transit spectra, we can make use of the `FinFout()` function in the `RT.py` module. This code does not run from the command line, as you may want to process/plot/save the resulting transit spectrum in different ways.\n", "\n", @@ -112,19 +237,27 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "c6622346", "metadata": {}, "outputs": [], "source": [ - "import sys\n", - "sys.path.append('/Users/dion/src/sunbather/src/') #add your path to /sunbather/src/ here\n", - "\n", - "import tools\n", - "import RT\n", - "\n", "import matplotlib.pyplot as plt\n", - "import numpy as np" + "import numpy as np\n", + "\n", + "from sunbather import tools\n", + "from sunbather import RT" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5f9f8e7f-1d2e-4141-a877-fee93db5168d", + "metadata": {}, + "outputs": [], + "source": [ + "# Get the project path, and keep this constant during the example\n", + "projectpath = tools.get_sunbather_project_path()" ] }, { @@ -137,59 +270,28 @@ }, { "cell_type": "code", - "execution_count": 2, - "id": "e434fa77", + "execution_count": null, + "id": "2e1e0593-e082-455d-b69e-77f659b671fc", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Ti is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Ti is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Ti+ is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Ti+ is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species V is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all V is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species V+ is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all V+ is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species V+2 is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all V+2 is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Cr is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Cr is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Co is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Co is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Cu+ is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Cu+ is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Zn is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Zn is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ - "wavs = RT.constantR_wavs(2000,3000,100000) #set up wavelength grid at spectral resolution of 100,000\n", - "W52b_solar = tools.Sim(tools.projectpath+'/sims/1D/WASP52b/z_1/parker_9200_11.300/converged') #load simulation\n", - "#we can quickly get a list of all species as follows:\n", - "all_species = tools.get_specieslist(max_ion=2) #this includes all species up to doubly ionized - higher is not neccessary here\n", - "transit_spectrum_solar, _, _ = RT.FinFout(W52b_solar, wavs, all_species) #do RT\n", + "wavs = RT.constantR_wavs(\n", + " 2000, 3000, 100000\n", + ") # set up wavelength grid at spectral resolution of 100,000\n", + "W52b_solar = tools.Sim(\n", + " f\"{projectpath}/sims/1D/WASP52b/z_1/parker_9200_11.300/converged\"\n", + ") # load simulation\n", + "# we can quickly get a list of all species as follows:\n", + "all_species = tools.get_specieslist(\n", + " max_ion=2\n", + ") # this includes all species up to doubly ionized - higher is not neccessary here\n", + "transit_spectrum_solar, _, _ = RT.FinFout(W52b_solar, wavs, all_species) # do RT\n", "\n", - "fig, ax = plt.subplots(1, figsize=(12,7))\n", + "fig, ax = plt.subplots(1, figsize=(12, 7))\n", "ax.plot(wavs, transit_spectrum_solar)\n", - "ax.set_xlabel('Wavelength [Å]')\n", - "ax.set_ylabel(r'$F_{in} / F_{out}$')\n", - "ax.set_title(r'WASP-52 b with T=9200 and $\\dot{M}=10^{11.3}$, solar composition')\n", + "ax.set_xlabel(\"Wavelength [Å]\")\n", + "ax.set_ylabel(r\"$F_{in} / F_{out}$\")\n", + "ax.set_title(r\"WASP-52 b with T=9200 and $\\dot{M}=10^{11.3}$, solar composition\")\n", "plt.show()" ] }, @@ -203,58 +305,21 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "d25a07ca", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Ti is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Ti is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Ti+ is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Ti+ is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species V is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all V is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species V+ is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all V+ is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species V+2 is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all V+2 is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Cr is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Cr is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Mn+ is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Mn+ is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Co is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Co is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Cu+ is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Cu+ is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n", - "/Users/dion/src/sunbather/src/RT.py:508: UserWarning: Your requested species Zn is not resolved into multiple energy levels by Cloudy. I will make the spectrum assuming all Zn is in the ground-state.\n", - " warnings.warn(f\"Your requested species {spec} is not resolved into multiple energy levels by Cloudy. \" + \\\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ - "W52b_z_10 = tools.Sim(tools.projectpath+'/sims/1D/WASP52b/z_10/parker_9200_11.300/converged') #load simulation\n", - "transit_spectrum_z_10, _, _ = RT.FinFout(W52b_z_10, wavs, all_species) #do RT\n", + "W52b_z_10 = tools.Sim(\n", + " projectpath + \"/sims/1D/WASP52b/z_10/parker_9200_11.300/converged\"\n", + ") # load simulation\n", + "transit_spectrum_z_10, _, _ = RT.FinFout(W52b_z_10, wavs, all_species) # do RT\n", "\n", - "fig, ax = plt.subplots(1, figsize=(12,7))\n", + "fig, ax = plt.subplots(1, figsize=(12, 7))\n", "ax.plot(wavs, transit_spectrum_z_10)\n", - "ax.set_xlabel('Wavelength [Å]')\n", - "ax.set_ylabel(r'$F_{in} / F_{out}$')\n", - "ax.set_title(r'WASP-52 b with T=9200 and $\\dot{M}=10^{11.3}$, 10x solar metallicity')\n", + "ax.set_xlabel(\"Wavelength [Å]\")\n", + "ax.set_ylabel(r\"$F_{in} / F_{out}$\")\n", + "ax.set_title(r\"WASP-52 b with T=9200 and $\\dot{M}=10^{11.3}$, 10x solar metallicity\")\n", "plt.show()" ] }, @@ -270,37 +335,28 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "4c2128fc", "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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mcOhhx66fZWqw29/+1uOPPJI0uk0t912W9Wx7373u+y///7sv//+fPe73y2nP/rooxx22GHst99+XHrppcSCShu7ACYw2oAxmTEA/GnjnwCY2DGxlcXZ5dmZ0ObQ/PDmmzZtKocUeeaZZ7avMlthxowZXH/99bz73e+uSl+7di1XXnklDz/8MI888ghXXnkl69atA+Ciiy7iO9/5Trkev/jFL5pWHqP9sYl7bcDkzskAPLv22ap9A770yJfK7dIsDpp4EP90zD81lHd7Q5tD88Obn3XWWdxyyy1cdtll3HTTTZx77rnccMMNAPT29nL++efz1FNPceCBB7JixQrmzZvH3Llzt1nOmTNnAgyq1913381JJ53ExImu43LSSSfxi1/8ghNPPJGNGzdy3HHHAXDeeefx4x//mNNOO22b9zKSgQmMNmBS5yQEYdHaReV9o/XUhjaHnQs+uKPhzd/xjndwwQUXcNlll/HTn/6U73//+2WBcc011zBhwgQWLVrEU089xZw5c8rnnX322SxevHjQ9T7xiU9w3nnnbXc5ly9fzrRp0walG7sOJjDagEwqw8SOiazpX8PY7FhyQa7VRWobGtUEhoPa0ObQmvDmkyZNYsKECdx8880cfPDBdHVVfFy///3v+Yd/+AcADj30UA4//PDysUbiXhnG9mACo03YrWs31vSvMXNUm1AvtDm0Lrz52WefzUc+8hGuv/76hvKXztkRDWPq1Kncd999VeU88cQTmTp1KsuWLduh8hvJwARGm1ASFCYwWs9Qoc1h+MKbH3TQQTz77NC+mjPPPJOVK1dyyimnsGLFinL68ccfz6233sob3/hGFi1axJNPVpaz3VEN45RTTuEzn/lM2dH9y1/+ki984QtMnDiRnp4eHnroIY499li+973vcckll+zQPYzRiY2SahOmdE0BYHKHCYxWszOhzWH7w5uvXr16m8NTx44dyz/90z+RzWar0i+++GJWrVrF7Nmz+ed//mcOOeQQxo0b11A558+fz7Rp0/jBD37Ahz70IQ455BAAJk6cyGc/+1mOPvpojj76aK644oqyA/yaa67hAx/4APvttx/77ruvObx3MSSp46jnzp2rCxYsaHUxGubhlQ9z+3O3c/6h5zN70tBmjV2BZ555hoMPPrjVxRgxfvazn7FkyZK6IdG3RRRFFAoFOjo6ePHFF3nzm9/M4sWLBwmWkWZX+w6ThIg8qqp1h9mZSapNOHbPYzl2z2NbXQyjBbzlLW/Z4XN7e3t54xvfSKFQQFW55pprWi4sjOQyogJDRE4Fvg4EwH+p6hfr5DkL+DygwB9V9d0+PQJKBto/q+rbRqTQhtHGjB07ltGkSRujmxETGCISAPOAk4BlwHwRuUNVF8Xy7A9cDhyvqutEZLfYJfpUdc5IlddoLaqKiLS6GMYOkFQztzGyTu9jgBdUdYmq5oGbgTNq8nwQmKeq6wBU9dURLJ/RJnR0dLBmzRr74RmFqCpr1qyho6Oj1UUxhoGRNElNBZbG9pcBtUb7AwBE5A84s9XnVbUUrKZDRBYAIfBFVf3x8BbXaBWlEUarVq1qdVGMHaCjo6NqRriRHNrN6Z0G9gdOBKYBvxWRw1R1PbC3qi4XkX2A34jIk6r6YvxkEbkQuBAoh3IwRh+ZTIZZs2a1uhiGYdQwkiap5cD02P40nxZnGXCHqhZU9SXgOZwAQVWX+/9LgPuAQRHeVPVaVZ2rqnOnTJnS/BoYhmHswoykwJgP7C8is0QkC5wD3FGT58c47QIRmYwzUS0RkQkikoulHw8swjAMwxgxRswkpaqhiHwUuBvnn7hOVZ8WkauABap6hz92sogsAiLgk6q6RkReB/yniBRxQu6L8dFVhmEYxvCT2JneIrIK+FOrywFMBlZvM9eugbVFBWuLCtYWFdqhLfZW1bo2/cQKjHZBRBYMNc1+V8PaooK1RQVriwrt3hYWfNAwDMNoCBMYhmEYRkOYwBh+rm11AdoIa4sK1hYVrC0qtHVbmA/DMAzDaAjTMAzDMIyGMIFhGIZhNIQJjO1ERKaLyL0iskhEnhaRf/Dpt4jIQv95WUQW+vSsiPyPiDwpIn8UkRNj18qKyLUi8pyIPCsi72hJpXaQJrfFuT79CRH5hZ/RP2rYSlvMEZGHfFssEJFjfLqIyDdE5AVf5yNj13qfiDzvP+9rVZ12lGa1hc//oL/GEyJydivrtSM087nwx3tEZJmIfLMV9UFV7bMdH2BP4Ei/PRYX72p2TZ6vAFf47Y8A/+O3dwMeBVJ+/0rgX/12Cpjc6vq1oi1wEQdeLdUf+HdcpOKW13Fn2wL4JXCaTz8duC+2fRcgwHHAwz59IrDE/5/gtye0un4taosDgP399l7ASmB8q+vXiraIXe/rwI3AN1tRH9MwthNVXamqj/ntTcAzuNDtgOshAGcBN/mk2cBvfP5XgfVAaWLO3wNf8MeKqtrqGZ7bRRPbQvyn25/TA6wYmVo0h620heLqAzCOSr3OAL6njoeA8SKyJ3AKcI+qrlW3Lsw9wKkjWJWdplltoarPqerz/jorcJ2KURVVtInPBSJyFLA7Tti0hHYLbz6qEJGZuKi5D8eSTwBeKT3owB+Bt4nITbhovUcB00XkOX/8X7xp5kXgo6r6yggUvensTFuo6iMichFuCd4twPM4bWRUUtMWHwPuFpEv47Sp1/ls9daHmbqV9FHJTrbFyth1jgGyuPdkVLIzbSEir+C09fcCbx6hIg/CNIwdRETGALcDH1PVjbFD51LpUQNch/vSFwBfAx7ABVZM40K8P6CqRwIPAl8e/pI3n51tCxHJABfhXqa9gCdwS/WOOuq0xUXAx1V1OvBx4L9bWb6RpFlt4XvYNwAXqGpxuMo7nDShLS4G7lTVZcNb0m3QahvfaPwAGVxk3U/UpKeBV4BpWzn3AZxpRnC96ZI/YzrwdKvr1qK2OBr4dSz9r3AvR8vrt7NtAWygMt9JgI1++z+Bc2P5FuPs3ecC/xlLr8o3Wj7NaAu/3QM8Bryz1XVq8XPxfeDPwMu44IQbcVG7R7QupmFsJ97G/t/AM6r6HzWH3ww8q7FegIh0iUi33z4JCFV1kbqn4af49T+ANzHK1vhoVlvgFtKaLSIl+/RJOFvvqGErbbECeIPf/mucuQ3cWjDn+VExxwEbVHUllRD/E0RkAnCyTxs1NKstxK2b8yOcTf+2ESp+U2lWW6jqe1R1hqrOBC7DtcmnR6YWMVotfUfbB3g9zmH1BLDQf073x64HPlyTfyaul/AM8Ctc6ODSsb2B3/pr/RqY0er6tbAtPuzTn8AJ0kmtrl8z2sKnP4rz3zwMHOXzCzAPZ5N/Epgbu9bfAy/4zwWtrlur2gJnry/ErrEQmNPq+rXquYhd83xaNErKQoMYhmEYDWEmKcMwDKMhTGAYhmEYDWECwzAMw2gIExiGYRhGQ5jAMAzDMBrCBIZh7CL4uR2/EpF7RGRcq8tjjD5sWK1h7CKIyDtxoVcEWKqqP2xxkYxRhmkYRmIRka+KyMdi+3eLyH/F9r8iIp9o4v2u9z/KTUVEPhPbnikiTzVYlpdE5MOx5PuBz/rPfbG8HxeRP7dsjQVj1GACw0gyf8BHARWRFDAZOCR2/HW4eFbtzme2naUun1TVb8f2I2AdLqy8lBJV9avAFTtcOmOXwQSGkWQeAF7rtw8BngI2eVt+DjgYeExErhCR+SLylLgVEEVEDhKRR0oX8j37J/32USJyv4g86rWWPWtvPFQeEblPRL4kIo+IW2nxBJ/eJSK3iluZ7Uci8rCIzBWRLwKd4lZm+76/fCAi3xG3gtsvRaSzwfY4C/ghLmrqqFu9zmg9JjCMxKJu0Z1QRGbgtIkHcXF7XotbuOlJVc3j4vIcraqHAp3AW1T1WSArIrP85c4GbvGh2P8fLnrqUbiQ7VfH79tAnrSqHoNbE+FzPu1iYJ2qzsaZjI7ydfg00Keqc1T1PT7v/sA8VT0Epy00urTve3Hh5m8C3rONvIYxCFtAyUg6D+CExeuA/8AtUPM6XHjpP/g8bxSRTwFduKVRn8YFQLwVJyi+6P+fDRwIHArc4wKREhBb6MezrTwlZ/OjuICM4ILRfR1AVZ8SkSe2UqeXVHVhnWsMiV+8Z7yq/tHvTxCRWar60rbONYwSJjCMpFPyYxyGM0ktBf4Rt57A/4hIB3ANLiroUhH5PNDhz70F+IGI/BBQVX1eRA7DrVvyWoZGtpFnwP8vLaS1vQzEtiOcVrQt3oNbue1lvz8OeDc12pFhbA0zSRlJ5wHgLcBaVY1UdS0wHmeWeoCKcFjtV0Urj3JS1RdxP8ifxQkPcOHZp4jIa8GZn0Qk7khvNE8tf8D5GBCR2TgBV6LgzVw7w3uAY1R1pro1FY7CzFLGdmICw0g6T+JGRz1Uk7ZBVVer6nrgOzjt425gfs35t+Bs/7cCeJ/HO4EvicgfcesbvC5+QiN56nANTsgsAv4VZxbb4I9dCzwRc3pvFyJyJFDUytrqqOoSnCA6ckeuaeya2MQ9w2gDRCQAMqraLyL74haYOtALnx253vXAz7TBlepE5HycWe6jO3I/Y9fAfBiG0R50Afd605MAF++osPBsAP5FRCbXzMUYhIh8HLfi4e07cT9jF8A0DMMwDKMhzIdhGIZhNIQJDMMwDKMhTGAYhmEYDWECwzAMw2gIExiGYRhGQ/x/Y+nVNcCo3M0AAAAASUVORK5CYII=\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ - "wavs2 = np.linspace(2795, 2805, num=500) #set up a wav-grid around the Mg II doublet\n", - "W52b_z_10_Mg10 = tools.Sim(tools.projectpath+'/sims/1D/WASP52b/z_10_Mg10/parker_9200_11.300/converged') #load simulation\n", - "transit_spectrum_z_10_Mg10, _, _ = RT.FinFout(W52b_z_10_Mg10, wavs2, 'Mg+', width_fac=20.) #do RT\n", + "wavs2 = np.linspace(2795, 2805, num=500) # set up a wav-grid around the Mg II doublet\n", + "W52b_z_10_Mg10 = tools.Sim(\n", + " projectpath + \"/sims/1D/WASP52b/z_10_Mg10/parker_9200_11.300/converged\"\n", + ") # load simulation\n", + "transit_spectrum_z_10_Mg10, _, _ = RT.FinFout(\n", + " W52b_z_10_Mg10, wavs2, \"Mg+\", width_fac=20.0\n", + ") # do RT\n", "\n", "fig, ax = plt.subplots(1)\n", - "ax.plot(wavs, transit_spectrum_solar, label='Solar')\n", - "ax.plot(wavs, transit_spectrum_z_10, label='Z=10')\n", - "ax.plot(wavs2, transit_spectrum_z_10_Mg10, label='Z=10, Mg=100')\n", + "ax.plot(wavs, transit_spectrum_solar, label=\"Solar\")\n", + "ax.plot(wavs, transit_spectrum_z_10, label=\"Z=10\")\n", + "ax.plot(wavs2, transit_spectrum_z_10_Mg10, label=\"Z=10, Mg=100\")\n", "ax.set_xlim(wavs2[0], wavs2[-1])\n", - "ax.legend(loc='best')\n", - "ax.set_title(r'WASP-52 b Mg II doublet at different metallicities')\n", - "ax.set_xlabel('Wavelength [Å]')\n", - "ax.set_ylabel(r'$F_{in} / F_{out}$')\n", + "ax.legend(loc=\"best\")\n", + "ax.set_title(r\"WASP-52 b Mg II doublet at different metallicities\")\n", + "ax.set_xlabel(\"Wavelength [Å]\")\n", + "ax.set_ylabel(r\"$F_{in} / F_{out}$\")\n", "plt.show()" ] }, @@ -317,7 +373,7 @@ "id": "8385ea04", "metadata": {}, "source": [ - "### References\n", + "## References\n", "\n", "France, K., Loyd, R. O. P., Youngblood, A., et al. 2016, ApJ, 820, 89\n", "\n", @@ -343,7 +399,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.0" + "version": "3.12.7" } }, "nbformat": 4, diff --git a/src/sunbather/convergeT_parker.py b/src/sunbather/convergeT_parker.py index f30fc8c..2b12ecc 100644 --- a/src/sunbather/convergeT_parker.py +++ b/src/sunbather/convergeT_parker.py @@ -214,7 +214,7 @@ def run_s( # quit the whole Python code return else: - os.mkdir(path[:-1]) # make the folder + os.makedirs(path[:-1]) # make the folder # get profiles and parameters we need for the input file alt = pprof.alt.values @@ -377,6 +377,46 @@ def run_s( solveT.run_loop(path, itno, fc, save_sp, maxit) +def run( + plname, + mdot=None, + temp=None, + itno=1, + fc=1.1, + workingdir=None, + sedname="real", + overwrite=False, + start_temp="nearby", + pdir=None, + z=None, + zelem=None, + altmax=8, + save_sp=None, + constant_temp=False, + maxit=20, +): + if zelem is None: + zelem = {} + zdict = tools.get_zdict(z=z, zelem=zelem) + run_s( + plname, + mdot, + temp, + itno, + fc, + workingdir, + sedname, + overwrite, + start_temp, + pdir, + zdict=zdict, + altmax=altmax, + save_sp=save_sp, + constantT=constant_temp, + maxit=maxit, + ) + + def catch_errors_run_s(*args): """ Executes the run_s() function with provided arguments, while catching @@ -648,7 +688,7 @@ def __call__(self, parser, namespace, values, option_string=None): "abundance scale factor for specific elements, e.g. -zelem Fe=10 -zelem " "He=0.01. Can also be used to toggle elements off, e.g. -zelem Ca=0. " "Combines with -z argument. Using this command results in running p_winds " - "in an an iterative scheme where Cloudy updates the mu parameter." + "in an iterative scheme where Cloudy updates the mu parameter." ), ) parser.add_argument(