Welcome to PLATON’s documentation!¶
Introduction¶
PLATON (PLanetary Atmospheric Transmission for Observer Noobs) is a fast and easy to use forward modelling and retrieval tool for exoplanet atmospheres. It is based on ExoTransmit by Eliza Kempton. The two main modules are:
TransitDepthCalculator
: computes a transit spectrum for an exoplanetRetriever
: retrieves atmospheric properties of an exoplanet, given the observed transit spectrum. The properties that can be retrieved are metallicity, C/O ratio, cloudtop pressure, scattering strength, and scattering slope
The transit spectrum is calculating from 300 nm to 30 um, taking into
account gas absorption, collisionally induced gas absorption, and
Rayleigh scattering. TransitDepthCalculator
is written
entirely in Python and is designed for performance. By default, it
calculates transit depths on a fine wavelength grid (λ/Δλ = 1000 with
4616 wavelength points), which takes ~170 milliseconds on a midrange
consumer computer. The user can instead specify bins which are
directly relevant to matching observational data, in which case the
code avoids computing depths for irrelevant wavelengths and is many
times faster.
Retriever
uses TransitDepthCalculator as a forward model, and
can retrieve atmospheric properties using either MCMC or nested sampling.
Typically, nestled sampling finishes in < 10 min. MCMC relies on the user to
specify the number of iterations, but typically reaches convergence in less
than an hour.
Install¶
Before installing PLATON, it is highly recommended to have a fast linear algebra library (BLAS) and verify that numpy is linked to it. This is because the heart of the radiative transfer code is a matrix multiplication operation conducted through numpy.dot, which in turn calls a BLAS library if it can find one. If it can’t find one, your code will be many times slower.
On Linux, a good choice is OpenBLAS. You can install it on Ubuntu with:
sudo apt install libopenblas-dev
On OS X, a good choice is Accelerate/vecLib, which should already be installed by default.
To check if your numpy is linked to BLAS, do:
numpy.__config__.show()
If blas_opt_info mentions OpenBLAS or vecLib, that’s a good sign. If it says “NOT AVAILABLE”, that’s a bad sign.
Once you have a BLAS installed and linked to numpy, download PLATON, install the requirements, and install PLATON itself:
git clone https://github.com/ideasrule/platon.git
cd platon/
pip install -r requirements.txt
python setup.py install
That’s it! To run unit tests to make sure everything runs:
python setup.py test
The unit tests should also give you a good idea of how fast the code will be. On a decent Ubuntu machine with OpenBLAS, it takes 2 minutes.
Quick start¶
The fastest way to get started is to look at the examples/ directory, which has examples on how to compute transit depths from planetary parameters, and on how to retrieve planetary parameters from transit depths. This page is a short summary of the more detailed examples.
To compute transit depths, look at transit_depth_example.py, then go to
TransitDepthCalculator
for more info. In short:
from plato.transit_depth_calculator import TransitDepthCalculator
star_radius = 7e8 # all quantities in SI
planet_g = 9.8
planet_radius = 7e7
planet_temperature = 1200
calculator = TransitDepthCalculator(star_radius, planet_g)
calculator.compute_depths(planet_radius, planet_temperature, logZ=0, CO_ratio=0.53)
You can adjust a variety of parameters, including the metallicity (Z) and C/O ratio. By default, logZ = 0 and C/O = 0.53. Any other value for logZ and C/O in the range -1 < logZ < 3 and 0.2 < C/O < 2 can also be used. You can use a dictionary of numpy arrays to specify abundances as well (See the API). You can also specify custom abundances, such as by providing the filename or one of the abundance files included in the package (from ExoTransmit). The custom abundance files specified by the user must be compatible with the ExoTransmit format:
calculator.compute_depths(planet_radius, planet_temperature, logZ=None,
CO_ratio=None, custom_abundances = filename)
To retrieve atmospheric parameters, look at retrieve_example.py, then go to
Retriever
for more info. In short:
from plato.fit_info import FitInfo
from plato.retriever import Retriever
# Set your best guess
fit_info = retriever.get_default_fit_info(star_radius, planet_g, planet_radius,
planet_temperature, logZ=0)
# Decide what you want to fit for, then set the lower and upper limits for
# those quantities
fit_info.add_fit_param('R', 0.9*planet_radius, 1.1*planet_radius)
fit_info.add_fit_param('T', 0.5*planet_temperature, 1.5*planet_temperature)
fit_info.add_fit_param("logZ", -1, 2)
#Fit using Nested Sampling
result = retriever.run_multinest(bins, depths, errors, fit_info)
Here, bins is a N x 2 array representing the start and end wavelengths of the bins, in metres; depths is a list of N transit depths; and errors is a list of N errors on those transit depths.
The example above retrieves the planetary radius (at a base pressures of 100,000 Pa), the temperature of the isothermal atmosphere, and the metallicity. Other parameters you can retrieve for are the C/O ratio, the cloudtop pressure, the scattering factor, the scattering slope, and the error multiple–which multiplies all errors by a constant.
Once you get the result object, you can make a corner plot:
fig = corner.corner(result.samples, weights=result.weights,
range=[0.99] * result.samples.shape[1],
labels=fit_info.fit_param_names)
Additionally, result.logl stores the log likelihoods of the points in result.samples.
If you prefer using MCMC instead of Nested Sampling in your retrieval, you can use the run_emcee method instead of the run_multinest method. Do note that Nested Sampling tends to be much faster and it does not require specification of a termination point:
result = retriever.run_emcee(bins, depths, errors, fit_info)
For MCMC, the number of walkers and iterations/steps can also be specified. The result object returned by run_emcee is slighly different from that returned by run_multinest. To make a corner plot with the result of run_emcee:
fig = corner.corner(result.flatchain, range=[0.99] * result.flatchain.shape[1],
labels=fit_info.fit_param_names)
platon¶
platon package¶
Submodules¶
platon.abundance_getter module¶
-
class
platon.abundance_getter.
AbundanceGetter
(include_condensates=True)¶ -
static
from_file
()¶ Reads abundances file in the ExoTransmit format (called “EOS” files in ExoTransmit), returning a dictionary mapping species name to an abundance array of dimension
-
get
(logZ, CO_ratio=0.53)¶
-
is_in_bounds
(logZ, CO_ratio, T)¶
-
static
platon.constants module¶
platon.fit_info module¶
-
class
platon.fit_info.
FitInfo
(guesses_dict)¶ -
add_fit_param
(name, low_guess, high_guess, low_lim=None, high_lim=None, value=None)¶
-
freeze_fit_param
(name, value=None)¶
-
generate_rand_param_arrays
(num_arrays)¶
-
get
(name)¶
-
get_guess_bounds
(index)¶
-
get_num_fit_params
()¶
-
get_param_array
()¶
-
interpret_param_array
(array)¶
-
within_limits
(array)¶
-
platon.retriever module¶
-
class
platon.retriever.
Retriever
¶ -
static
get_default_fit_info
(g, Rp, T, logZ=0, CO_ratio=0.53, cloudtop_P=1000.0, log_scatt_factor=0, scatt_slope=4, error_multiple=1, add_fit_params=False)¶
-
run_emcee
(wavelength_bins, depths, errors, fit_info, nwalkers=50, nsteps=10000, include_condensates=True, plot_best=False)¶ Runs affine-invariant MCMC to retrieve atmospheric parameters.
Parameters: - wavelength_bins (array_like, shape (N,2)) – Wavelength bins, where wavelength_bins[i][0] is the start wavelength and wavelength_bins[i][1] is the end wavelength for bin i.
- depths (array_like, length N) – Measured transit depths for the specified wavelength bins
- errors (array_like, length N) – Errors on the aforementioned transit depths
- fit_info (
FitInfo
object) – Tells the method what parameters to freely vary, and in what range those parameters can vary. Also sets default values for the fixed parameters. - nwalkers (int, optional) – Number of walkers to use
- nsteps (int, optional) – Number of steps that the walkers should walk for
- include_condensates (bool, optional) – When determining atmospheric abundances, whether to include condensation.
- plot_best (bool, optional) – If True, plots the best fit model with the data
Returns: result – This returns emcee’s EnsembleSampler object. The most useful attributes in this item are result.chain, which is a (W x S X P) array where W is the number of walkers, S is the number of steps, and P is the number of parameters; and result.lnprobability, a (W x S) array of log probabilities. For your convenience, this object also contains result.flatchain, which is a (WS x P) array where WS = W x S is the number of samples; and result.flatlnprobability, an array of length WS
Return type: EnsembleSampler object
-
run_multinest
(wavelength_bins, depths, errors, fit_info, maxiter=None, include_condensates=True, plot_best=False)¶ Runs nested sampling to retrieve atmospheric parameters.
Parameters: - wavelength_bins (array_like, shape (N,2)) – Wavelength bins, where wavelength_bins[i][0] is the start wavelength and wavelength_bins[i][1] is the end wavelength for bin i.
- depths (array_like, length N) – Measured transit depths for the specified wavelength bins
- errors (array_like, length N) – Errors on the aforementioned transit depths
- fit_info (
FitInfo
object) – Tells us what parameters to freely vary, and in what range those parameters can vary. Also sets default values for the fixed parameters. - maxiter (bool, optional) – If not None, run at most this many iterations of nestled sampling
- include_condensates (bool, optional) – When determining atmospheric abundances, whether to include condensation.
- plot_best (bool, optional) – If True, plots the best fit model with the data
Returns: result – This returns the object returned by nestle.sample The object is dictionary-like and has many useful items. For example, result.samples (or alternatively, result[“samples”]) are the parameter values of each sample, result.weights contains the weights, and result.logl contains the log likelihoods. result.logz is the natural logarithm of the evidence.
Return type: Result object
-
static
platon.transit_depth_calculator module¶
-
class
platon.transit_depth_calculator.
TransitDepthCalculator
(star_radius, g, include_condensates=True, min_P_profile=0.1, max_P_profile=100000.0, num_profile_heights=400)¶ -
__init__
(star_radius, g, include_condensates=True, min_P_profile=0.1, max_P_profile=100000.0, num_profile_heights=400)¶ All physical parameters are in SI.
Parameters: - star_radius (float) – Radius of the star
- g (float) – Acceleration due to gravity of the planet at a pressure of max_P_profile
- include_condensates (bool) – Whether to use equilibrium abundances that take condensation into account.
- min_P_profile (float) – For the radiative transfer calculation, the atmosphere is divided into zones. This is the pressure at the topmost zone.
- max_P_profile (float) – The pressure at the bottommost zone of the atmosphere
- num_profile_heights (int) – The number of zones the atmosphere is divided into
-
change_wavelength_bins
(bins)¶ Specify wavelength bins, instead of using the full wavelength grid in self.lambda_grid. This makes the code much faster, as compute_depths will only compute depths at wavelengths that fall within a bin.
Parameters: bins (array_like, shape (N,2)) – Wavelength bins, where bins[i][0] is the start wavelength and bins[i][1] is the end wavelength for bin i. Raises: NotImplementedError
– Raised when change_wavelength_bins is called more than once, which is not supported.
-
compute_depths
(planet_radius, temperature, logZ=0, CO_ratio=0.53, add_scattering=True, scattering_factor=1, scattering_slope=4, scattering_ref_wavelength=1e-06, add_collisional_absorption=True, cloudtop_pressure=inf, custom_abundances=None)¶ Computes transit depths at a range of wavelengths, assuming an isothermal atmosphere. To choose bins, call change_wavelength_bins().
Parameters: - planet_radius (float) – radius of the planet at self.max_P_profile (by default, 100,000 Pa). Must be in metres.
- temperature (float) – Temperature of the isothermal atmosphere, in Kelvin
- logZ (float) – Base-10 logarithm of the metallicity, in solar units
- CO_ratio (float, optional) – C/O atomic ratio in the atmosphere. The solar value is 0.53.
- add_scattering (bool, optional) – whether Rayleigh scattering is taken into account
- scattering_factor (float, optional) – if add_scattering is True, make scattering this many times as strong. If scattering_slope is 4, corresponding to Rayleigh scattering, the absorption coefficients are simply multiplied by scattering_factor. If slope is not 4, scattering_factor is defined such that the absorption coefficient is that many times as strong as Rayleigh scattering at scattering_ref_wavelength.
- scattering_slope (float, optional) – Wavelength dependence of scattering, with 4 being Rayleigh.
- scattering_ref_wavelength (float, optional) – Scattering is scattering_factor as strong as Rayleigh at this wavelength, expressed in metres.
- add_collisional_absorption (float, optional) – Whether collisionally induced absorption is taken into account
- cloudtop_pressure (float, optional) – Pressure level (in Pa) below which light cannot penetrate. Use np.inf for a cloudless atmosphere.
- custom_abundances (str or dict of np.ndarray, optional) – If specified, overrides logZ and CO_ratio. Can specify a filename, in which case the abundances are read from a file in the format of the EOS/ files. These are identical to ExoTransmit’s EOS files. It is also possible, though highly discouraged, to specify a dictionary mapping species names to numpy arrays, so that custom_abundances[‘Na’][3,4] would mean the fractional number abundance of Na at a pressure of self.P_grid[3] and temperature of self.T_grid[4].
Returns: - wavelengths (array of float) – Central wavelengths, in metres
- transit_depths (array of float) – Transit depths at wavelengths
-
is_in_bounds
(logZ, CO_ratio, T, cloudtop_P)¶ Tests whether a certain combination of parameters is within the bounds of the data files. The arguments are the same as those in compute_depths.
-