diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000..327f5fb
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,6 @@
+[flake8]
+max-line-length = 88
+per-file-ignores =
+ # imported but unused
+ __init__.py: F401
+
diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml
new file mode 100644
index 0000000..fccf9ac
--- /dev/null
+++ b/.github/workflows/pylint.yml
@@ -0,0 +1,24 @@
+name: Pylint
+
+on: [push]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ python-version: ["3.9", "3.10", "3.11"]
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install pylint
+ pip install -e .
+ - name: Analysing the code with pylint
+ run: |
+ pylint -d C0301,C0103,C0209 --fail-under 8.5 $(git ls-files '*.py')
diff --git a/.gitignore b/.gitignore
index f86f759..a87e2cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,15 +1,11 @@
.DS_Store
-src/.DS_Store
-src/RT_tables/.DS_Store
-examples/.DS_Store
-examples/materials/.DS_Store
-tests/.DS_Store
-tests/materials/.DS_Store
-src/__pycache__/
-examples/.ipynb_checkpoints
+__pycache__/
+*.ipynb_checkpoints
+*.egg-info
+*.swp
examples/WASP52b_dT.csv
examples/WASP52b_sigmaT.csv
examples/WASP52b_nsig_fit.csv
env/
-src/sunbather
-*.egg-info
\ No newline at end of file
+dist/
+src/sunbather/cloudy
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..31dbf0d
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,35 @@
+# Read the Docs configuration file for Sphinx projects
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Set the OS, Python version and other tools you might need
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.12"
+ # You can also specify other tool versions:
+ # nodejs: "20"
+ # rust: "1.70"
+ # golang: "1.20"
+
+# Build documentation in the "docs/" directory with Sphinx
+sphinx:
+ configuration: docs/conf.py
+ # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
+ # builder: "dirhtml"
+ # Fail on all warnings to avoid broken references
+ # fail_on_warning: true
+
+# Optionally build your docs in additional formats such as PDF and ePub
+# formats:
+# - pdf
+# - epub
+
+# Optional but recommended, declare the Python requirements required
+# to build your documentation
+# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
+python:
+ install:
+ - requirements: docs/requirements.txt
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..0629df0
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+recursive-include src/sunbather *
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..d4bb2cb
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = .
+BUILDDIR = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/api.rst b/docs/api.rst
new file mode 100644
index 0000000..f4f7565
--- /dev/null
+++ b/docs/api.rst
@@ -0,0 +1,8 @@
+API
+===
+
+.. autosummary::
+ :toctree: generated
+ :recursive:
+
+ sunbather
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..f2d9419
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,43 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# For the full list of built-in configuration values, see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+import sys
+import os
+from pathlib import Path
+
+sys.path.insert(0, str(Path('..', 'src').resolve()))
+
+# -- Project information -----------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = "sunbather"
+copyright = "2024, Dion Linssen"
+author = "Dion Linssen"
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = [
+ "sphinx_rtd_theme",
+ "sphinx.ext.autodoc",
+ "sphinx.ext.autosummary",
+ #"myst_parser",
+ "myst_nb",
+]
+
+templates_path = ["_templates"]
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
+
+
+# -- Options for HTML output -------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+# html_theme = 'alabaster'
+html_theme = "sphinx_rtd_theme"
+html_static_path = ["_static"]
+
+
+# Configuration for Read the Docs
+html_baseurl = os.environ.get("READTHEDOCS_CANONICAL_URL", "/")
diff --git a/docs/faq.md b/docs/faq.md
new file mode 100644
index 0000000..ee8a284
--- /dev/null
+++ b/docs/faq.md
@@ -0,0 +1,92 @@
+# FAQ
+
+## How do I create Parker wind profiles?
+
+Add the parameters of the planet/star system to the *$SUNBATHER_PROJECT_PATH/planets.txt* file. Make sure the SED you specify in _planets.txt_ is present in the _$CLOUDY_PATH/data/SED/_ folder in the right format. Then run the `construct_parker.py` module in your terminal (use `-help` to see the arguments).
+
+## How do I choose the composition of the atmosphere?
+
+The composition usually has to be specified at two stages:
+
+1. When creating the Parker wind profiles with the `construct_parker.py` module: You can choose to use a pure H/He composition (which uses `p-winds` standalone) by specifying the hydrogen fraction by number with the `-fH` argument. You can also choose an arbitrary composition that includes metal species (which uses `p-winds` and _Cloudy_ in tandem) with the `-z` and `-zelem` arguments. In this case, `-z` specifies a metallicity relative to solar and is thus a scaling factor for all metal species. `-zelem` can be used to scale the abundance of individual elements, for example as `-zelem Na=3 Mg+=10 Fe+2=0.5 K=0`. Note that `-z` and `-zelem` can be used together and are **multiplicative**. In `construct_parker.py`, the composition only affects the wind structure through the mean molecular weight. Therefore, using `-z` and `-zelem` is only needed for (highly) supersolar metallicities; using `-fH 0.9` will usually suffice for a solar composition atmosphere.
+
+2. When simulating Parker wind profiles with _Cloudy_ with the `convergeT_parker.py` module: You can specify the composition with the `-z` and `-zelem` arguments as explained under point 1. The default is a solar composition, so `-z 1`. If you want to simulate a pure H/He composition with _Cloudy_, you can pass `-z 0` (and specify the He abundance through `-zelem He=...)`. Contrary to point 1 however, in `convergeT_parker.py`, the metal content directly affects the thermal structure and XUV absorption, so we recommend using `-z 1` even when you only make hydrogen and helium spectra.
+
+## How do I calculate the transmission spectrum?
+
+Create the Parker wind profile with `construct_parker.py` and simulate it with _Cloudy_ with `convergeT_parker.py` while making sure you specify for which species you want to save output with the `-save_sp` argument (if unsure, just pass `-save_sp all`). Then, load the _Cloudy_ output in your Python script with the `tools.Sim` class (see FAQ below), and use the `RT.FinFout()` function to make the transit spectrum. At minimum, `RT.FinFout()` expects the `Sim` object, a wavelength array, and a list of species for which to calculate the spectrum. See the _sunbather/examples/fit_helium.ipynb_ notebook for an example.
+
+## How do I simulate one planet with different stellar SEDs?
+
+The safest way is to add another entry in the *$SUNBATHER_PROJECT_PATH/planets.txt* file, with the same parameter values, but a different "name" and "SEDname" (the "full name" can be the same).
+
+Alternatively and more prone to mistakes, the `construct_parker.py` and `convergeT_parker.py` modules also has the `-SEDname` argument which allows you to specify a different name of the SED file without making a new entry in the _planets.txt_ file. In this case, it is **strongly advised** to use a different `-pdir` and `-dir` (that references the SED type) as well.
+
+## Why do I have to specify a `-pdir` and a `-dir`?
+
+Generally, for one planet you may want to create Parker wind profiles with different temperatures, mass-loss rates, but also different atmospheric compositions. The `-pdir` and `-dir` correspond to actual folders on your machine. Each folder groups together profiles with different $T$ and $\dot{M}$, so the `-pdir` and `-dir` effectively allow you to separate the profiles by composition. `-pdir` corresponds to the folder where the Parker wind **structure** (i.e. density and velocity as a function of radius) is stored: *$SUNBATHER_PROJECT_PATH/parker_profiles/planetname/pdir/*, and `-dir` corresponds to the folder where the _Cloudy_ simulations of the profiles are stored: *$SUNBATHER_PROJECT_PATH/sims/1D/planetname/dir/*.
+
+For example, you can make one `-pdir` which stores a grid of $T-\dot{M}$ profiles at a H/He ratio of 90/10, and another which stores a grid of profiles at a ratio of 99/01. The reason that the `-dir` argument is not the exact same as the `-pdir` argument, is that you may want to create your Parker wind structure profile only once (in one `-pdir` folder) but then run it multiple times with _Cloudy_ while changing the abundance of one particular trace element (in multiple `-dir` folders). The latter would usually not really change the atmospheric structure, but could produce a very different spectral feature.
+
+## How do I read / plot the output of Cloudy in Python?
+
+The `Sim` class in the `tools.py` module can be used to read in simulations by giving the full path to the simulation. _Cloudy_ output is separated into different output files, which all have the same name but a different extension. The bulk structure of the atmosphere (including temperature and density) is stored in the ".ovr" file. The radiative heating and cooling rates as a function of radius are stored in the ".heat" and ".cool" files. The densities of different energy levels of different atomic/ionic species are stored in the ".den" file. These files are all read in as a Pandas dataframe and can be accessed as follows:
+
+``` python
+import sys
+sys.path.append("/path/to/sunbather/src/")
+import tools
+
+mysimulation = tools.Sim(tools.projectpath+"/sims/1D/planetname/dir/parker_T_Mdot/converged")
+
+#to get the planet parameters of this simulation:
+mysimulation.p.R #radius
+mysimulation.p.Mstar #mass of host star
+
+#to get Cloudy output
+mysimulation.ovr.alt #radius grid of the following profiles:
+mysimulation.ovr.rho #density profile
+mysimulation.ovr.Te #temperature profile
+mysimulation.ovr.v #velocity profile
+mysimulation.cool.ctot #total radiative cooling
+mysimulation.den['H[1]'] #density of ground-state atomic hydrogen
+mysimulation.den['He[2]'] #density of metastable helium
+mysimulation.den['Fe+2[10]'] #density of the tenth energy level of Fe 2+
+```
+
+## Can I run a Parker wind profile through Cloudy while using the isothermal temperature profile?
+
+Yes, you can pass the `-constantT` flag to `convergeT_parker.py` to simulate the Parker wind profile without converging on a nonisothermal temperature structure. This will save a _Cloudy_ simulation called "constantT" and the folder structure works the same way as for converged simulations: you again need to pass a `-dir` where the simulation is saved, and you can in principle use the same directory that you use for converged profiles (but you will need to pass the `-overwrite` flag if the converged nonisothermal simulation already exists - nothing will be overwritten in this case though!).
+
+## I forgot to specify for which species I want Cloudy output with the `-save_sp` argument. Do I need to run `convergeT_parker.py` again from scratch?
+
+You can use the `tools.insertden_Cloudy_in()` function to add species to a (converged) Cloudy simulation file and run it again, without having to go through the temperature convergence scheme again. If you want to do this for a grid of Parker wind models, you will have to set up a loop over the correct filepaths yourself.
+
+## Can I run an atmospheric profile other than an (isothermal) Parker wind?
+
+You can "trick" the code into running an arbitrary outflow profile by saving your density and velocity profile in the expected file format in the *$SUNBATHER_PROJECT_PATH/parker_profiles/* folder. For example, you can create a simple density and velocity profile in Python:
+
+``` python
+p = tools.Planet('generic_planet') #make sure you add the parameters in planets.txt
+
+r = np.linspace(1, 10, num=1000) * p.R #in cm
+rho = 1e-15 / np.linspace(1, 10, num=1000)**3 #falls with r^3
+v = 5e4 * np.linspace(1, 10, num=1000) #starts at 0.5km/s, increases linearly with r so that Mdot = 4 pi rho v r^2 is constant
+mu = np.repeat(np.nan, 1000) #mu is not used by convergeT_parker.py
+
+print("log(Mdot) =", np.log10(4*np.pi*r[0]**2*rho[0]*v[0]))
+
+np.savetxt(tools.projectpath+'/parker_profiles/'+p.name+'/geometric/pprof_'+p.name+'_T=0_M=0.000.txt', np.column_stack((r, rho, v, mu)), delimiter='\t')
+```
+
+You can then solve the temperature structure of this profile with: `python convergeT_parker.py -plname generic_planet -pdir geometric -dir geometric -T 0 -Mdot 0`
+
+Similarly, you could for example postprocess the density and velocity profile of an _ATES_ simulation (Caldiroli et al. 2021) with _sunbather_ to produce a transmission spectrum.
+
+## How do I stop the simulation at the Roche radius / choose the maximum radius?
+
+The `construct_parker.py` module always creates a profile up until 20 $R_p$ and this can only be changed by editing the source code.
+
+The `convergeT_parker.py` module by default simulates the atmosphere with *Cloudy* up until 8 $R_p$ and this can be changed with the `-altmax` argument.
+
+The `RT.FinFout()` function by default makes a transit spectrum based on the full *Cloudy* simulation (so up until 8 $R_p$), but you can give an upper boundary in cm with the `cut_at` argument. For example, if you want to include only material up until the planet's Roche radius when making the transit spectrum, it generally doesn't hurt to leave `construct_parker.py` and `convergeT_parker.py` at the default values, and just pass `cut_at=mysimulation.p.Rroche` to `RT.FinFout()` (assuming `mysimulation` is the `tools.Sim` object of your *Cloudy* simulation).
diff --git a/docs/glossary.md b/docs/glossary.md
new file mode 100644
index 0000000..070a9e3
--- /dev/null
+++ b/docs/glossary.md
@@ -0,0 +1,46 @@
+# Glossary
+This wiki page is a glossary that provides additional information on various modules/classes/functionalities included in _sunbather_. We also refer to "Hazy", which is the official documentation of _Cloudy_ and can be found in your _$CLOUDY_PATH/docs/_ folder.
+
+
+## The `tools.py` module
+This module contains many basic functions and classes that are used by the other _sunbather_ modules, and can also be used when postprocessing/analyzing _sunbather_ output.
+
+This module is not intended to be run from the command line, but rather imported into other scripts in order to use its functions.
+
+
+## The `RT.py` module
+This module contains functions to perform radiative transfer calculations of the planet transmission spectrum.
+
+This module is not intended to be run from the command line, but rather imported into other scripts in order to use its functions.
+
+
+## The `construct_parker.py` module
+This module is used to create Parker wind profiles. The module can make pure H/He profiles, in which case it is basically a wrapper around the [`p-winds` code](https://github.com/ladsantos/p-winds) (dos Santos et al. 2022). The code can however also make Parker wind profiles for an arbitrary composition (e.g. at a given scaled solar metallicity), which is much more computationally expensive, because it then iteratively runs `p-winds` and _Cloudy_. In this mode, _Cloudy_ is used to obtain the mean molecular weight structure of the atmosphere for the given composition, which `p-winds` uses to calculate the density and velocity structure.
+
+This module is intended to be run from the command line while supplying arguments. Running `python construct_parker.py --help` will give an explanation of each argument.
+
+Example use: `python construct_parker.py -plname WASP52b -pdir z_10 -T 8000 -Mdot 11.0 -z 10`. This creates a Parker wind profile for the planet WASP52b (must be defined in *planets.txt*) for a temperature of 8000 K, mass-loss rate of 10^11 g s-1 and a 10x solar metallicity composition, and saves the atmospheric structure as a .txt file in *$SUNBATHER_PROJECT_PATH/parker_profiles/WASP52b/z_10/*.
+
+
+## The `convergeT_parker.py` module
+This module is used to run Parker wind profiles through _Cloudy_ to (iteratively) solve for a non-isothermal temperature structure. Additionally, the "converged" simulation can then be postprocessed with functionality of the `RT.py` module in order to make transmission spectra. This module is basically a convenience wrapper which sets up the necessary folder structure and input arguments for the `solveT.py` module that actually performs the iterative scheme described in Linssen et al. (2022).
+
+This module is intended to be run from the command line while supplying arguments. Running `python convergeT_parker.py --help` will give an explanation of each argument.
+
+Example use: `python convergeT_parker.py -plname HATP11b -pdir fH_0.99 -dir fiducial -T 5000 10000 200 -Mdot 9.0 11.0 0.1 -zelem He=0.1 -cores 4 -save_sp H He Ca+`. This simulates Parker wind models with Cloudy for the planet HATP11b (must be defined in *planets.txt*) for a grid of temperatures between 5000 K and 10000 K in steps of 200 K, mass-loss rates between 10^9 g s-1 and 10^11 g s-1 in steps of 0.1 dex. It looks for the density and velocity structure of these models in the folder *$SUNBATHER_PROJECT_PATH/parker_profiles/HATP11b/fH_0.99/* (so these models have to be created first in that folder using `construct_parker.py`) and saves the _Cloudy_ simulations in the folder *$SUNBATHER_PROJECT_PATH/sims/1D/HATP11b/fiducial/*. It scales the abundance of helium (which is solar by default in _Cloudy_, i.e. ~10% by number) by a factor 0.1 so that it becomes 1% by number. 4 different calculations of the $T$-$\dot{M}$-grid are done in parallel, and the atomic hydrogen, helium and singly ionized calcium output are saved by _Cloudy_, so that afterwards we can use `RT.FinFout()` to make Halpha, metastable helium and Ca II infrared triplet spectra.
+
+
+## The `solveT.py` module
+This module contains the iterative scheme described in Linssen et al. (2022) to solve for a non-isothermal temperature structure of a given atmospheric profile. It is called by `convergeT_parker.py`. As long as you're simulating Parker wind profiles (and not some other custom profile), you should be fine using `convergeT_parker.py` instead of this module.
+
+
+## The *\$SUNBATHER_PROJECT_PATH* (or internally: *tools.projectpath*) directory
+This is the directory on your machine where all Parker wind profiles and _Cloudy_ simulations are saved. You can choose any location and name you like, as long as it doesn't contain any spaces. The full path to this directory must be set as your `$SUNBATHER_PROJECT_PATH` environmental variable (see installation instructions). The reason _sunbather_ uses a project path is to keep all output from simulations (i.e. user-specific files) separate from the source code.
+
+
+## The _planets.txt_ file
+This file stores the bulk parameters of the planets that are simulated. A template of this file is provided in the _sunbather_ base directory, but you must copy it to your _$SUNBATHER_PROJECT_PATH_ in order for it to work. Every time you want to simulate a new planet/star system, you must add a line to this file with its parameters. You can add comments at the end of the line with a # (for example referencing where the values are from). The first column specifies the "name", which is a tag for this system that cannot contain spaces and is used for the `-plname` argument of `construct_parker.py` and `convergeT_parker.py`, as well as for the `tools.Planet` class to access the system parameters in Python. The second column specifies the "full name", which can be any string you like and can be used e.g. when plotting results. The third column is the radius of the planet in Jupiter radii (7.1492e9 cm). The fourth column is the radius of the star in solar radii (6.9634e10 cm). The fifth column is the semi-major axis of the system in AU (1.49597871e13 cm). The sixth column is the mass of the planet in Jupiter masses (1.898e30 g). The seventh column is the mass of the star in solar masses (1.9891e33 g). The eighth column is the transit impact parameter (dimensionless, 0 is across the center of the stellar disk, 1 is grazing the stellar limb). The ninth column is the name of the stellar SED - see "Stellar SED handling" below in this glossary.
+
+
+## Stellar SED handling
+When running _sunbather_, the spectral energy distribution (SED) of the host star has to be available to _Cloudy_, which looks for it in its _$CLOUDY_PATH/data/SED/_ folder. Therefore, every SED you want to use has be **copied to that folder, and requires a specific format**: the first column must be wavelengths in units of Å and the second column must be the $\lambda F_{\lambda} = \nu F_{\nu}$ flux **at a distance of 1 AU** in units of erg s-1 cm-2. Additionally, on the first line, after the first flux value, the following keywords must appear: "units angstrom nuFnu". In the */sunbather/stellar_SEDs/* folder, we have provided a few example SEDs in the correct format. Even though _Cloudy_ in principle supports other units, _sunbather_ doesn't, so please stick to the units as described. Normalization of the flux to the planet orbital distance is done automatically by *sunbather* based on the semi-major axis value given in the *planets.txt* file.
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..611d013
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,16 @@
+# sunbather documentation
+
+Welcome to the _sunbather_ docs! On the left side, you\'ll find the
+table of contents.
+
+![Sunbather logo](logo_text.png)
+
+```{toctree} Table of Contents
+:maxdepth: 2
+installation
+glossary
+faq
+api
+fit_helium
+predict_UV
+```
diff --git a/docs/installation.md b/docs/installation.md
new file mode 100644
index 0000000..3e00f25
--- /dev/null
+++ b/docs/installation.md
@@ -0,0 +1,29 @@
+# Installing _sunbather_
+
+1. Clone _sunbather_ from Github. The code runs entirely in Python. It was developed using Python 3.9.0 and the following packages are prerequisites: `numpy (v1.24.3), pandas (v1.1.4), matplotlib (v3.7.1), scipy (v1.8.0), astropy (v5.3), p-winds (v1.3.4)`. _sunbather_ also succesfully ran with the newest versions (as of Sep. 18, 2023) of these packages. We have however not yet thoroughly tested all of its functionality with these newer versions, so we currently cannot guarantee that it works, but feel free to try! In any case, we recommend making a Python [virtual environment](https://realpython.com/python-virtual-environments-a-primer/) to run _sunbather_ in.
+2. Create a directory anywhere on your machine where the code will save all models/simulations/etc. This will be the "project" folder, and you can give it any name you like. This is to keep the output of _sunbather_ separate from the _sunbather_ source code.
+3. Set an environmental variable `$CLOUDY_PATH` to your _Cloudy_ installation base directory, and set `$SUNBATHER_PROJECT_PATH` to the "project" folder. We recommend setting these in your _~/.bashrc_ or _~/.zshrc_ file:
+ ```
+ export CLOUDY_PATH="/full/path/to/c23.01/"
+ export SUNBATHER_PROJECT_PATH="/full/path/to/project/folder/"
+ ```
+4. Copy the */sunbather/planets.txt* file to your project folder.
+5. Copy the stellar spectra from _/sunbather/stellar_SEDs/_ to _$CLOUDY_PATH/data/SED/_ . These include the [MUSCLES](https://archive.stsci.edu/prepds/muscles/) spectra.
+6. Test your _sunbather_ installation: run _/sunbather/tests/test.py_, which should print "Success". If the test fails, feel free to open an issue or contact d.c.linssen@uva.nl with your error.
+
+## Installing _Cloudy_
+
+_sunbather_ has been developed and tested with _Cloudy v17.02_ and _v23.01_. Newer versions of _Cloudy_ are likely also compatible with _sunbather_, but this has not been thoroughly tested. Therefore, we currently recommend using _v23.01_. Complete _Cloudy_ download and installation instructions can be found [here](https://gitlab.nublado.org/cloudy/cloudy/-/wikis/home). In short, for most Unix systems, the steps are as follows:
+
+1. Go to the [v23 download page](https://data.nublado.org/cloudy_releases/c23/) and download the "c23.01.tar.gz" file (or go to the [v17 download page](https://data.nublado.org/cloudy_releases/c17/old/) and download the "c17.02.tar.gz" file).
+2. Extract it in a location where you want to install _Cloudy_.
+3. `cd` into the _/c23.01/source/_ or _/c17.02/source/_ folder and compile the code by running `make`.
+4. Quickly test the _Cloudy_ installation: in the source folder, run `./cloudy.exe`, type "test" and hit return twice. It should print "Cloudy exited OK" at the end.
+
+If you have trouble installing _Cloudy_, we refer to the download instructions linked above, as well as the _Cloudy_ [help forum](https://cloudyastrophysics.groups.io/g/Main/topics).
+
+
+## Getting started
+
+1. To get familiar with _sunbather_, we recommend you go through the Jupyter notebooks in the _/sunbather/examples/_ folder, where example use cases (such as creating atmospheric profiles, calculating transmission spectra and fitting observational data) are worked out and explained.
+2. For more details on how to use the code, check out the Glossary and FAQ pages on this wiki. We specifically recommend you read the glossary sections "The _planets.txt_ file" and "Stellar SED handling".
diff --git a/docs/logo_text.png b/docs/logo_text.png
new file mode 120000
index 0000000..7e00e04
--- /dev/null
+++ b/docs/logo_text.png
@@ -0,0 +1 @@
+../logo/Logo + text.png
\ No newline at end of file
diff --git a/docs/requirements.in b/docs/requirements.in
new file mode 100644
index 0000000..3e815de
--- /dev/null
+++ b/docs/requirements.in
@@ -0,0 +1,3 @@
+sphinx == 7.1.2
+sphinx-rtd-theme == 3.0.2
+myst_parser == 4.0.0
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000..86716b2
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,133 @@
+#
+# This file is autogenerated by pip-compile with Python 3.12
+# by the following command:
+#
+# pip-compile --output-file=requirements.txt --strip-extras ../pyproject.toml requirements.in
+#
+alabaster==0.7.16
+ # via sphinx
+astropy==6.1.6
+ # via
+ # p-winds
+ # sunbather (../pyproject.toml)
+astropy-iers-data==0.2024.11.18.0.35.2
+ # via astropy
+babel==2.16.0
+ # via sphinx
+certifi==2024.8.30
+ # via requests
+charset-normalizer==3.4.0
+ # via requests
+contourpy==1.3.1
+ # via matplotlib
+cycler==0.12.1
+ # via matplotlib
+docutils==0.20.1
+ # via
+ # myst-parser
+ # sphinx
+ # sphinx-rtd-theme
+flatstar==0.2.1a0
+ # via p-winds
+fonttools==4.55.0
+ # via matplotlib
+idna==3.10
+ # via requests
+imagesize==1.4.1
+ # via sphinx
+jinja2==3.1.4
+ # via
+ # myst-parser
+ # sphinx
+kiwisolver==1.4.7
+ # via matplotlib
+markdown-it-py==3.0.0
+ # via
+ # mdit-py-plugins
+ # myst-parser
+markupsafe==3.0.2
+ # via jinja2
+matplotlib==3.9.2
+ # via sunbather (../pyproject.toml)
+mdit-py-plugins==0.4.2
+ # via myst-parser
+mdurl==0.1.2
+ # via markdown-it-py
+myst-parser==4.0.0
+ # via -r requirements.in
+numpy==2.1.3
+ # via
+ # astropy
+ # contourpy
+ # flatstar
+ # matplotlib
+ # p-winds
+ # pandas
+ # pyerfa
+ # scipy
+ # sunbather (../pyproject.toml)
+p-winds==1.4.7
+ # via sunbather (../pyproject.toml)
+packaging==24.2
+ # via
+ # astropy
+ # matplotlib
+ # sphinx
+pandas==2.2.3
+ # via sunbather (../pyproject.toml)
+pillow==11.0.0
+ # via
+ # flatstar
+ # matplotlib
+pyerfa==2.0.1.5
+ # via astropy
+pygments==2.18.0
+ # via sphinx
+pyparsing==3.2.0
+ # via matplotlib
+python-dateutil==2.9.0.post0
+ # via
+ # matplotlib
+ # pandas
+pytz==2024.2
+ # via pandas
+pyyaml==6.0.2
+ # via
+ # astropy
+ # myst-parser
+requests==2.32.3
+ # via sphinx
+scipy==1.13.1
+ # via
+ # p-winds
+ # sunbather (../pyproject.toml)
+six==1.16.0
+ # via python-dateutil
+snowballstemmer==2.2.0
+ # via sphinx
+sphinx==7.1.2
+ # via
+ # -r requirements.in
+ # myst-parser
+ # sphinx-rtd-theme
+ # sphinxcontrib-jquery
+sphinx-rtd-theme==3.0.2
+ # via -r requirements.in
+sphinxcontrib-applehelp==2.0.0
+ # via sphinx
+sphinxcontrib-devhelp==2.0.0
+ # via sphinx
+sphinxcontrib-htmlhelp==2.1.0
+ # via sphinx
+sphinxcontrib-jquery==4.1
+ # via sphinx-rtd-theme
+sphinxcontrib-jsmath==1.0.1
+ # via sphinx
+sphinxcontrib-qthelp==2.0.0
+ # via sphinx
+sphinxcontrib-serializinghtml==2.0.0
+ # via sphinx
+tzdata==2024.2
+ # via pandas
+urllib3==2.2.3
+ # via requests
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": [
- "