API

pyratbay

class pyratbay.Pyrat(cfile, no_logfile=False, mute=False)[source]
Main Pyrat object.


Parse the command-line arguments into the pyrat object.

Parameters
----------
cfile: String
    A Pyrat Bay configuration file.
no_logfile: Bool
    If True, enforce not to write outputs to a log file
    (e.g., to prevent overwritting log of a previous run).
mute: Bool
    If True, enforce verb to take a value of -1.

Examples
--------
>>> import pyratbay as pb
>>> # Initialize and execute task:
>>> pyrat = pb.run('spectrum_transmission.cfg')

>>> # Initialize only:
>>> pyrat = pb.Pyrat('spectrum_transmission.cfg')
>>> # Then, setup internal varible for spectra evaluation:
>>> pyrat.setup_spectrum()
band_integrate(spectrum=None)[source]
Band-integrate transmission spectrum (transit) or planet-to-star
flux ratio (eclipse) over transmission band passes.
eval(params, retmodel=True, verbose=False)[source]
Fitting routine for MCMC.

Parameters
----------
params: 1D float iterable
   Array of fitting parameters that define the atmosphere.
retmodel: Bool
   Flag to include the model spectra in the return.
verbose: Bool
   Flag to print out if a run failed.

Returns
-------
spectrum: 1D float ndarray
   The output model spectra.  Returned only if retmodel=True.
bandflux: 1D float ndarray
   The waveband-integrated spectrum values.
get_ec(layer)[source]
Extract extinction-coefficient contribution (in cm-1) from each
component of the atmosphere at the requested layer.

Parameters
----------
layer: Integer
   The index of the atmospheric layer where to extract the EC.

Returns
-------
ec: 2D float ndarray
   An array of shape [ncomponents, nwave] with the EC spectra
   (in cm-1) from each component of the atmosphere.
label: List of strings
   The names of each atmospheric component that contributed to EC.
hydro(pressure, temperature, mu, g, mass, p0, r0)[source]
Hydrostatic-equilibrium driver.
Depending on self.atm.rmodelname, select between the g=GM/r**2
(hydro_m) or constant-g (hydro_g) formula to compute
the hydrostatic-equilibrium radii of the planet layers.

Parameters
----------
pressure: 1D float ndarray
   Atmospheric pressure for each layer (in barye).
temperature: 1D float ndarray
   Atmospheric temperature for each layer (in K).
mu: 1D float ndarray
   Mean molecular mass for each layer (in g mol-1).
g: Float
   Atmospheric gravity (in cm s-2).
mass: Float
   Planetary mass (in g).
p0: Float
   Reference pressure level (in barye) where radius(p0) = r0.
r0: Float
   Reference radius level (in cm) corresponding to p0.
percentile_spectrum(nmax=None)[source]
Compute spectrum posterior percentiles.
plot_spectrum(spec='model', **kwargs)[source]
Plot spectrum.

Parameters
----------
spec: String
    Flag indicating which model to plot.  By default plot the
    latest evaulated model (spec='model').  Other options are
    'best' or 'median' to plot the posterior best-fit or median
    model, in which case, the code will plot the 1- and 2-sigma
    boundaries if they have been computed (see
    self.percentile_spectrum).
kwargs: dict
    Dictionary of arguments to pass into plots.spectrum().
    See help(pyratbay.plots.spectrum).

Returns
-------
ax: AxesSubplot instance
    The matplotlib Axes of the figure.
plot_temperature(**kwargs)[source]
Plot temperature profile.
If self.ret.posterior exitst, plot the best fit, median, and
the '1sigma/2sigma' boundaries of the temperature posterior
distribution.

Parameters
----------
kwargs: dict
    Dictionary of arguments to pass into plots.temperature().
    See help(pyratbay.plots.temperature).

Returns
-------
ax: AxesSubplot instance
    The matplotlib Axes of the figure.
radiative_equilibrium(nsamples=None, continue_run=False, convection=False)[source]
Compute radiative-thermochemical equilibrium atmosphere.
Currently there is no convergence criteria implemented,
some 100--300 iterations are typically sufficient to converge
to a stable temperature-profile solution.

Parameters
----------
nsamples: Integer
    Number of radiative-equilibrium iterations to run.
continue_run: Bool
    If True, continue from a previous radiative-equilibrimu run.
convection: Bool
    If True, skip convective flux calculation in the radiative
    equilibrium calculation.

Returns
-------
There are no returned values, but this method updates the
temperature profile (self.atm.temp) and abundances (self.atm.q)
with the values from the last radiative-equilibrium iteration.

This method also defines pyrat.atm.radeq_temps, a 2D array
containing all temperature-profile iterations.
run(temp=None, abund=None, radius=None)[source]
Evaluate a Pyrat spectroscopic model

Parameters
----------
temp: 1D float ndarray
    Updated atmospheric temperature profile in Kelvin, of size nlayers.
abund: 2D float ndarray
    Updated atmospheric abundances profile by number density, of
    shape [nlayers, nmol].
radius: 1D float ndarray
    Updated atmospheric altitude profile in cm, of size nlayers.
set_filters()[source]
Set observational variables (pyrat.obs) based on given parameters.
pyratbay.run(cfile, run_step='run', no_logfile=False)[source]
Pyrat Bay initialization driver.

Parameters
----------
cfile: String
    A Pyrat Bay configuration file.
run_step: String
    If 'dry': only read the configuration file into a Pyrat object
    If 'init': initialize a Pyrat object (but no spectra calculation).
    If 'run': run all the way (default).
no_logfile: Bool
    If True, enforce not to write outputs to a log file
    (e.g., to prevent overwritting log of a previous run).

pyratbay.constants

pyratbay.constants.h
6.62607015e-27
pyratbay.constants.k
1.380649e-16
pyratbay.constants.c
29979245800.0
pyratbay.constants.G
6.674299999999999e-08
pyratbay.constants.sigma
5.670374419e-05
pyratbay.constants.eV
8065.49179
pyratbay.constants.A
1e-08
pyratbay.constants.nm
1e-07
pyratbay.constants.um
0.0001
pyratbay.constants.mm
0.1
pyratbay.constants.cm
1.0
pyratbay.constants.m
100.0
pyratbay.constants.km
100000.0
pyratbay.constants.au
14959787070000.0
pyratbay.constants.pc
3.0856775814913674e+18
pyratbay.constants.rearth
637810000.0
pyratbay.constants.rjup
7149200000.0
pyratbay.constants.rsun
69570000000.0
pyratbay.constants.barye
1.0
pyratbay.constants.mbar
1000.0
pyratbay.constants.pascal
10.0
pyratbay.constants.bar
1000000.0
pyratbay.constants.atm
1010000.0
pyratbay.constants.gram
1.0
pyratbay.constants.kg
1000.0
pyratbay.constants.mearth
5.9724e+27
pyratbay.constants.mjup
1.8982e+30
pyratbay.constants.msun
1.9885e+33
pyratbay.constants.amu
1.6605390666e-24
pyratbay.constants.me
9.1093837015e-28
pyratbay.constants.kelvin
1.0
pyratbay.constants.sec
1.0
pyratbay.constants.min
60.0
pyratbay.constants.hour
3600.0
pyratbay.constants.day
86400.0
pyratbay.constants.amagat
2.686780111e+19
pyratbay.constants.e
4.803205e-10
pyratbay.constants.percent
0.01
pyratbay.constants.ppt
0.001
pyratbay.constants.ppm
1e-06
pyratbay.constants.none
1
pyratbay.constants.C1
1129583353135.2844
pyratbay.constants.C2
1.4387768775039338
pyratbay.constants.C3
8.852821681767784e-13
pyratbay.constants.ROOT
os.path.realpath(os.path.dirname(__file__) + '/../..') + '/'
pyratbay.constants.tlireclen
26
pyratbay.constants.dreclen
8
pyratbay.constants.ireclen
4
pyratbay.constants.sreclen
2
pyratbay.constants.dbases
['Hitran', 'Exomol', 'Repack', 'Pands', 'Tioschwenke', 'Voplez', 'Vald']
pyratbay.constants.rmodes
['tli', 'atmosphere', 'opacity', 'spectrum', 'radeq', 'mcmc']
pyratbay.constants.transmission_rt
['transit']
pyratbay.constants.emission_rt
['emission', 'emission_two_stream']
pyratbay.constants.rt_paths
['transit', 'emission', 'emission_two_stream']
pyratbay.constants.retflags
['temp', 'rad', 'press', 'mol', 'ray', 'cloud', 'patchy', 'mass']
pyratbay.constants.tmodels
['isothermal', 'guillot', 'madhu']
pyratbay.constants.chemmodels
['uniform', 'tea']
pyratbay.constants.radmodels
['hydro_m', 'hydro_g']
pyratbay.constants.molmodels
['vert', 'scale', 'equil']
pyratbay.constants.amodels
['sodium_vdw', 'potassium_vdw']
pyratbay.constants.rmodels
['dalgarno_H', 'dalgarno_H2', 'dalgarno_He', 'lecavelier']
pyratbay.constants.cmodels
['deck', 'ccsgray']

pyratbay.io

pyratbay.io.save_pyrat(pyrat, pfile=None)[source]
Save a pyrat instance into a pickle file.

Parameters
----------
pyrat: A Pyrat instance
    Object to save.
pfile: String
    Name of output file.  Default to the pyrat logname (changing
    the extension to '.pickle').
pyratbay.io.load_pyrat(pfile)[source]
Load a pyrat instance from a pickle file.

Parameters
----------
pfile: String
    Name of input pickle file.

Returns
-------
pyrat: A Pyrat instance
    Loaded object.
pyratbay.io.write_atm(atmfile, pressure, temperature, species=None, abundances=None, radius=None, punits='bar', runits=None, header=None)[source]
Write an atmospheric file following the Pyrat format.

Parameters
----------
atmfile: String
    Name of output atmospheric file.
pressure: 1D float ndarray
    Monotonously decreasing pressure profile (in barye).
temperature: 1D float ndarray
    Temperature profile for pressure layers (in Kelvin).
species: 1D string ndarray
    List of atmospheric species.
abundances: 2D float ndarray
    The species mole mixing ratio (of shape [nlayers,nspecies]).
radius: 1D float ndarray
    Monotonously increasing radius profile (in cm).
punits:  String
    Pressure units of output.
runits:  String
    Radius units of output.
header:  String
    Header message (comment) to include at the top of the file.

Examples
--------
>>> import numpy as np
>>> import pyratbay.io as io
>>> import pyratbay.atmosphere as pa

>>> atmfile = 'WASP-00b.atm'
>>> nlayers = 5
>>> pressure    = pa.pressure('1e-8 bar', '1e2 bar', nlayers)
>>> temperature = pa.tmodels.Isothermal(nlayers)(1500.0)
>>> species     = "H2 He H2O".split()
>>> abundances  = [0.8499, 0.15, 1e-4]
>>> qprofiles = pa.uniform(pressure, temperature, species, abundances)
>>> io.write_atm(atmfile, pressure, temperature, species, qprofiles,
>>>     punits='bar', header='# Example atmospheric file:\n')
>>> # Print output file:
>>> with open(atmfile, 'r') as f:
>>>     print(f.read())
# Example atmospheric file:
# Pressure units:
@PRESSURE
bar
# Temperatures units:
@TEMPERATURE
kelvin
# Abundance units (mixing ratio):
@ABUNDANCE
volume

# Atmospheric composition:
@SPECIES
H2  He  H2O

# Pressure  Temperature  H2            He            H2O
@DATA
1.0000e-08     1500.000  8.499000e-01  1.500000e-01  1.000000e-04
3.1623e-06     1500.000  8.499000e-01  1.500000e-01  1.000000e-04
1.0000e-03     1500.000  8.499000e-01  1.500000e-01  1.000000e-04
3.1623e-01     1500.000  8.499000e-01  1.500000e-01  1.000000e-04
1.0000e+02     1500.000  8.499000e-01  1.500000e-01  1.000000e-04
pyratbay.io.read_atm(atmfile)[source]
Read a Pyrat atmospheric file.

Parameters
----------
atmfile: String
   File path to a Pyrat Bay's atmospheric file.

Returns
-------
units: 4-element string tuple
    Units for pressure, temperature, abundance, and radius as given
    in the atmospheric file.
species: 1D string ndarray
    The list of species names read from the atmospheric file (of
    size nspec).
press: 1D float ndarray
    The atmospheric pressure profile (of size nlayers). The
    file's @PRESSURE keyword indicates the ouptput units.
temp: 1D float ndarray
    The atmospheric temperature profile (of size nlayers). The
    file's @TEMPERATURE keyword indicates the ouptput units.
q: 2D float ndarray
    The mixing ratio profiles of the atmospheric species (of size
    [nlayers,nspec]).  The file's @ABUNDANCE indicates the output
    units.
radius: 1D float ndarray
    The atmospheric altiture profile (of size nlayers).  None if the
    atmospheric file does not contain a radius profile.
    The file's @RADIUS keyword indicates the output units.

Examples
--------
>>> # Continuing example from io.write_atm():
>>> import pyratbay.io as io

>>> atmfile = 'WASP-00b.atm'
>>> units, specs, pressure, temp, q, rad = io.read_atm(atmfile)
>>> print(units, specs, pressure, temp, q, rad, sep='\n')
('bar', 'kelvin', 'number', None)
['H2' 'He' 'H2O']
[1.0000e-08 3.1623e-06 1.0000e-03 3.1623e-01 1.0000e+02]
[1500. 1500. 1500. 1500. 1500.]
[[8.499e-01 1.500e-01 1.000e-04]
 [8.499e-01 1.500e-01 1.000e-04]
 [8.499e-01 1.500e-01 1.000e-04]
 [8.499e-01 1.500e-01 1.000e-04]
 [8.499e-01 1.500e-01 1.000e-04]]
None
pyratbay.io.write_spectrum(wl, spectrum, filename, type, wlunits='um')[source]
Write a spectrum to file.

Parameters
----------
wl: 1D float iterable
    Wavelength array in cm units.
spectrum: 1D float iterable
    Spectrum array. (rp/rs)**2 for transmission (unitless),
    planetary flux for emission (erg s-1 cm-2 cm units).
filename: String
    Output file name.
type: String
    Data type:
    - 'transit' for transmission
    - 'emission' for emission
    - 'filter' for a instrumental filter transmission
wlunits: String
    Output units for wavelength.

Examples
--------
>>> # See read_spectrum() examples.
pyratbay.io.read_spectrum(filename, wn=True)[source]
Read a Pyrat spectrum file, a plain text file with two-columns: the
wavelength and signal.  If wn is true, this function converts
wavelength to wavenumber in cm-1.  The very last comment line sets
the wavelength units (the first string following a blank, e.g., the
string '# um' sets the wavelength units as microns).
If the units are not defined, assume wavelength units are microns.

Parameters
----------
filename: String
   Path to output Transit spectrum file to read.
wn: Boolean
   If True convert wavelength to wavenumber.

Return
------
wave: 1D float ndarray
   The spectrum's wavenumber (in cm units) or wavelength array (in
   the input file's units).
spectrum: 1D float ndarray
   The spectrum in the input file.

Examples
--------
>>> import pyratbay.io as io
>>> # Write a spectrum to file:
>>> nwave = 7
>>> wl = np.linspace(1.1, 1.7, nwave) * 1e-4
>>> spectrum = np.ones(nwave)
>>> io.write_spectrum(wl, spectrum,
>>>     filename='sample_spectrum.dat', type='transit', wlunits='um')
>>> # Take a look at the output file:
>>> with open('sample_spectrum.dat', 'r') as f:
>>>     print("".join(f.readlines()))
# Wavelength        (Rp/Rs)**2
#         um          unitless
     1.10000   1.000000000e+00
     1.20000   1.000000000e+00
     1.30000   1.000000000e+00
     1.40000   1.000000000e+00
     1.50000   1.000000000e+00
     1.60000   1.000000000e+00
     1.70000   1.000000000e+00
>>> # Now, read from file (getting wavenumber array):
>>> wn, flux = io.read_spectrum('sample_spectrum.dat')
>>> print(wn)
[9090.90909091 8333.33333333 7692.30769231 7142.85714286 6666.66666667
 6250.         5882.35294118]
>>> print(flux)
[1. 1. 1. 1. 1. 1. 1.]
>>> # Read from file (getting wavelength array):
>>> wl, flux = io.read_spectrum('sample_spectrum.dat', wn=False)
>>> print(wl)
[1.1 1.2 1.3 1.4 1.5 1.6 1.7]
>>> print(flux)
[1. 1. 1. 1. 1. 1. 1.]
pyratbay.io.write_opacity(ofile, species, temp, press, wn, opacity)[source]
Write an opacity table as a binary file.

Parameters
----------
ofile: String
    Output filename where to save the opacity data.
    File extension must be .npz
species: 1D string iterable
    Species names.
temp: 1D float ndarray
    Temperature array (Kelvin degree).
press: 1D float ndarray
    Pressure array (barye).
wn: 1D float ndarray
    Wavenumber array (cm-1).
opacity: 4D float ndarray
    Tabulated opacities (cm2 molecule-1) of shape
    [nspec, ntemp, nlayers, nwave].
pyratbay.io.read_opacity(ofile)[source]
Read an opacity table from file.

Parameters
----------
ofile: String
    Path to a Pyrat Bay opacity file.

Returns
-------
sizes: 4-element integer tuple
    Sizes of the dimensions of the opacity table:
    (nspec, ntemp, nlayers, nwave)
arrays: 4-element 1D ndarray tuple
    The dimensions of the opacity table:
    - species     (string, the species names)
    - temperature (float, Kelvin)
    - pressure    (float, barye)
    - wavenumber  (float, cm-1)
opacity: 4D float ndarray tuple
    The tabulated opacities (cm2 molecule-1), of shape
    [nspec, ntemp, nlayers, nwave].
pyratbay.io.write_pf(pffile, pf, isotopes, temp, header=None)[source]
Write a partition-function file in Pyrat Bay format.

Parameters
----------
pffile: String
    Output partition-function file.
pf: 2D float iterable
    Partition-function data (of shape [niso, ntemp]).
isotopes: 1D string iterable
    Isotope names.
temp: 1D float iterable
    Temperature array.
header: String
    A header for the partition-function file (must be as comments).

Examples
--------
>>> # See read_pf() examples.
pyratbay.io.read_pf(pffile)[source]
Read a partition-function file.

Parameters
----------
pffile: String
    Partition function file to read.

Returns
-------
pf: 2D float ndarray
    The partition function data (of shape [niso, ntemp]).
isotopes: List of strings
     The names of the tabulated isotopes.
temp: 1D float ndarray
    Array with temperature sample.

Examples
--------
>>> import pyratbay.io as io
>>> # Generate some mock PF data and write to file:
>>> pffile = 'PF_Exomol_NH3.dat'
>>> isotopes = ['4111', '5111']
>>> temp   = np.linspace(10,100,4)
>>> pf     = np.array([np.logspace(0,3,4),
>>>                    np.logspace(1,4,4)])
>>> header = '# Mock partition function for NH3.\n'
>>> io.write_pf(pffile, pf, isotopes, temp, header)

>>> # Now, read it back:
>>> pf, iso, temp = io.read_pf(pffile)
>>> for item in [iso, temp, pf]:
>>>     print(item)
['4111' '5111']
[ 10.  40.  70. 100.]
[[1.e+00 1.e+01 1.e+02 1.e+03]
 [1.e+01 1.e+02 1.e+03 1.e+04]]
pyratbay.io.write_cs(csfile, cs, species, temp, wn, header=None)[source]
Write a cross-section file in Pyrat Bay format.

Parameters
----------
csfile: String
    Output cross-section file.
cs: 2D float iterable
    Cross-section opacity in units of cm-1 amagat^-N, with N the
    number of species, of shape [ntemp, nwave].
species: 1D string iterable
    Species names.
temp: 1D float iterable
    Temperature array in Kelvin degree.
wn: 1D float iterable
    Wavenumber array in cm-1.
header: String
    A header for the cross-section file (must be as comments).

Examples
--------
>>> # See read_cs() examples.
pyratbay.io.read_cs(csfile)[source]
Read a cross-section file.

Parameters
----------
csfile: String
    Partition function file to read.

Returns
-------
cs: 2D float ndarray
    Cross-section opacity in units of cm-1 amagat^-N, with N the
    number of species, of shape [ntemp, nwave].
species: 1D string list
    Species names.
temp: 1D float ndarray
    Temperature array in Kelvin degree.
wn: 1D float ndarray
    Wavenumber array in cm-1.

Examples
--------
>>> import pyratbay.io as io
>>> # Generate some mock PF data and write to file:
>>> csfile = 'CS_Mock-HITRAN_H2-H2.dat'
>>> species = ['H2', 'H2']
>>> temp = np.linspace(100, 1000, 3)
>>> wn   = np.arange(10, 15, 1.0)
>>> cs   = np.array([np.logspace( 0,-4,5),
>>>                  np.logspace(-1,-5,5),
>>>                  np.logspace(-2,-6,5)])
>>> header = '# Mock cross-section for H2-H2.\n'
>>> io.write_cs(csfile, cs, species, temp, wn, header)
>>> # Now, read it back:
>>> cs, species, temp, wn = io.read_cs(csfile)
>>> for item in [species, temp, wn, cs]:
>>>     print(item)
['H2', 'H2']
[ 100.  550. 1000.]
[10. 11. 12. 13. 14.]
[[1.e+00 1.e-01 1.e-02 1.e-03 1.e-04]
 [1.e-01 1.e-02 1.e-03 1.e-04 1.e-05]
 [1.e-02 1.e-03 1.e-04 1.e-05 1.e-06]]
pyratbay.io.read_pt(ptfile)[source]
Read a pressure and temperature profile from a file.

Parameters
----------
ptfile: String
    Input file with pressure (in bars, first column) and temperature
    profiles (in Kelvin degree, second column).

Returns
-------
pressure: 1D float ndarray
    Pressure profile in barye.
temperature: 1D float ndarray
    Temperature profile in Kelvin.

Examples
--------
>>> import pyratbay.io as io
>>> ptfile = 'pt_profile.dat'
>>> temp  = np.array([100.0, 150.0, 200.0, 175.0, 150.0])
>>> press = np.array([1e-6,  1e-4,  1e-2,  1e0,   1e2])
>>> with open(ptfile, 'w') as f:
>>>     for p,t in zip(press, temp):
>>>         f.write('{:.3e}  {:5.1f}\n'.format(p, t))
>>> pressure, temperature = io.read_pt(ptfile)
>>> for p,t in zip(pressure, temperature):
>>>     print('{:.1e} barye  {:5.1f} K'.format(p, t))
1.0e+00 barye  100.0 K
1.0e+02 barye  150.0 K
1.0e+04 barye  200.0 K
1.0e+06 barye  175.0 K
1.0e+08 barye  150.0 K
pyratbay.io.read_observations(obs_file)[source]
Read an observations file.

Parameters
----------
obs_file: String
    Path to file containing observations info, see Notes below.

Returns
-------
filters: List
    Filter passband objects.
data: 1D string list
    The transit or eclipse depths for each filter.
uncert: 1D float ndarray
    The depth uncertainties.

Notes
-----
An obs_file contains passband info (indicated by a '@DATA' flag),
one line per passband. The passband info could be:
(1) a path to a file containing the spectral response, or
(2) a tophat filter defined by a central wavelength, half-width,
and optionally a name.

A @DEPTH_UNITS flag sets the depth and uncert units (which can be
set to: none, percent, ppt, ppm).
This flag also indicates that there's data and uncerts to read
as two columns before the passband info.

Comment and blank lines are ignored,
central-wavelength and half-width units are always microns.

Examples
--------
>>> import pyratbay.io as io
>>> # File including depths and uncertainties:
>>> obs_file = 'observations.dat'
>>> bands, data, uncert = io.read_observations(obs_file)

>>> # File including only the passband info:
>>> obs_file = 'filters.dat'
>>> bands = io.read_observations(obs_file)
pyratbay.io.read_atomic(afile)[source]
Read an elemental (atomic) composition file.

Parameters
----------
afile: String
    File with atomic composition.

Returns
-------
atomic_num: 1D integer ndarray
    Atomic number (except for Deuterium, which has anum=0).
symbol: 1D string ndarray
    Elemental chemical symbol.
dex: 1D float ndarray
    Logarithmic number-abundance, scaled to log(H) = 12.
name: 1D string ndarray
    Element names.
mass: 1D float ndarray
    Elemental mass in amu.

Uncredited developers
---------------------
Jasmina Blecic
pyratbay.io.read_molecs(file)[source]
Read a molecules file to extract their names, masses, and radii.
The output also includes the ions denoted by a '-' and '+'
character appended at the end of the species names.

Parameters
----------
file: String
    The molecule file path.

Returns
-------
names: 1D string ndarray
    The molecules' names.
masses: 1D float ndarray
    The mass of the molecules (in g mol-1).
radii: 1D float ndarray
    The collisional radius of the molecules (in angstrom).

Notes
-----
In all truthfulness, these are species, not only molecules, as the
file also contain elemental particles.

Examples
--------
>>> import pyratbay.io as io
>>> import pyratbay.constants as pc
>>> names, masses, radii = io.read_molecs(
>>>     pc.ROOT+'pyratbay/data/molecules.dat')
>>> names = list(names)
>>> print(f"H2O: mass = {masses[names.index('H2O')]} g mol-1, "
>>>       f"radius = {radii[names.index('H2O')]} angstrom.")
H2O: mass = 18.015 g mol-1, radius = 1.6 Angstrom.
pyratbay.io.read_isotopes(file)[source]
Read an isotopes file to extract their molecule, hitran name,
exomol name, isotopic ratio, and mass.

Parameters
----------
file: String
    The isotope file path.

Returns
-------
mol_ID: 1D integer ndarray
    HITRAN molecule ID.
mol: 1D string ndarray
    Molecule names.
hitran_iso: 1D string ndarray
    Isotope name as in HITRAN database.
exomol_iso: 1D string ndarray
    Isotope name based on exomol database.
iso_ratio: 1D float ndarray
    Isotopic ratios.
iso_mass: 1D float ndarray
    The mass of the molecules (in g mol-1).

Examples
--------
>>> import pyratbay.io as io
>>> import pyratbay.constants as pc
>>> ID, mol, hit_iso, exo_iso, ratio, mass = \
>>>     io.read_isotopes(pc.ROOT+'pyratbay/data/isotopes.dat')
>>> print("H2O isotopes:\n iso    iso    isotopic  mass"
>>>                    "\n hitran exomol ratio     g/mol")
>>> for i in range(len(mol)):
>>>     if mol[i] == 'H2O':
>>>         print(f" {hit_iso[i]:6} {exo_iso[i]:6} "
>>>               f"{ratio[i]:.3e} {mass[i]:.4f}")
H2O isotopes:
iso    iso    isotopic  mass
hitran exomol ratio     g/mol
161    116    9.973e-01 18.0106
181    118    1.999e-03 20.0148
171    117    3.719e-04 19.0148
162    126    3.107e-04 19.0168
182    000    6.230e-07 21.0211
172    000    1.158e-07 20.0211
262    226    2.420e-08 20.0210
282    000    0.000e+00 22.0000
272    000    0.000e+00 21.0000
pyratbay.io.import_xs(filename, source, read_all=True, ofile=None)[source]
Read a cross-section opacity file from an external source.

Parameters
----------
filename: String
    The opacity pickle file to read.
source: String
    The cross-section source: exomol or taurex (see note below).
read_all: Bool
    If True, extract all contents in the file: cross-section,
    pressure, temperature, and wavenumber.
    If False, extract only the cross-section data.
ofile: String
    If not None, store Exomol XS data into a Pyratbay opacity
    format.

Returns
-------
xs: 3D float ndarray
    Opacity cross-section in cm2 molecule-1.
    with shape [npress, ntemp, nwave].
pressure: 1D float ndarray
    Pressure sample of the opacity file (in barye units)
temperature: 1D float ndarray
    Temperature sample of the opacity file (in Kelvin degrees units).
wavenumber: 1D float ndarray
    Wavenumber sample of the opacity file (in cm-1 units).
species: String
    The species name.

Notes
-----
- exomol cross sections (Chubb et al. 2020, AA) can be found here:
http://www.exomol.com/data/data-types/opacity/
- taurex cross sections (Al-Refaie et al. 2019) can be found here:
https://taurex3-public.readthedocs.io/en/latest/user/taurex/quickstart.html

Examples
--------
>>> # For this example, you'll need to have/download the following
>>> # file into the current folder:
>>> # http://www.exomol.com/db/H2O/1H2-16O/POKAZATEL/1H2-16O__POKAZATEL__R15000_0.3-50mu.xsec.TauREx.h5
>>> import pyratbay.io as io
>>> filename = '1H2-16O__POKAZATEL__R15000_0.3-50mu.xsec.TauREx.h5'
>>> xs_H2O, press, temp, wn, species = io.import_xs(filename, 'exomol')
pyratbay.io.import_tea(teafile, atmfile, req_species=None)[source]
Format a TEA atmospheric file into a Pyrat atmospheric file.

Paramters
---------
teafile:  String
    Input TEA atmospheric file.
atmfile:  String
    Output Pyrat atmospheric file.
req_species: List of strings
    The requested species for output.  If None, request all species
    in teafile.
pyratbay.io.export_pandexo(pyrat, baseline, transit_duration, Vmag=None, Jmag=None, Hmag=None, Kmag=None, metal=0.0, instrument=None, n_transits=1, resolution=None, noise_floor=0.0, sat_level=80.0, save_file=True)[source]
Parameters
----------
pyrat: A Pyrat instance
    Pyrat object from which to extract the system physical properties.
baseline: Float or string
    Total observing time in sec (float) or with given units (string).
transit_duration: Float or string
    Transit/eclipse duration in sec (float) or with given units (string).
metal: Float
    Stellar metallicity as log10(Fe/H).
Vmag: Float
    Stellar magnitude in the Johnson V band.
    Only one of Vmag, Jmag, Hmag, or Kmag should be defined.
Jmag: Float
    Stellar magnitude in the Johnson J band.
    Only one of Vmag, Jmag, Hmag, or Kmag should be defined.
Hmag: Float
    Stellar magnitude in the Johnson H band.
    Only one of Vmag, Jmag, Hmag, or Kmag should be defined.
Kmag: Float
    Stellar magnitude in the Johnson Kband.
    Only one of Vmag, Jmag, Hmag, or Kmag should be defined.
instrument: String or list of strings or dict
    Observing instrument to simulate.
    If None, this function returns the input dictionary.
n_transits: Integer
    Number of transits/eclipses.
resolution: Float
    Approximate output spectral sampling R = 0.5*lambda/delta-lambda.
sat_level: Float
    Saturation level in percent of full well.
noise_floor: Float or string
    Noise-floor level in ppm at all wavelengths (if float) or
    wavelength dependent (if string, filepath).
save_file: Bool or string
    If string, store pandexo output pickle file with this filename.
    If True, store pandexo output with default name based on
    the pyrat object's output filename.

Returns
-------
pandexo_sim: dict
    Output from pandexo.engine.justdoit.run_pandexo().
    Note this dict has R=None, noccultations=1 (as suggested in pandexo).
wavelengths: List of 1D float arrays
    Wavelengths of simulated observed spectra for each instrument.
    Returned only if instrument is not None.
spectra: List of 1D float arrays
    Simulated observed spectra for each instrument.
    Returned only if instrument is not None.
uncertainties: List of 1D float arrays
    Uncertainties of simulated observed spectra for each instrument.
    Returned only if instrument is not None.

Examples
--------
>>> import pyratbay as pb
>>> import pyratbay.io as io

>>> pyrat = pb.run('demo_spectrum-transmission.cfg')
>>> instrument = 'NIRCam F322W2'
>>> #instrument = jdi.load_mode_dict(instrument)
>>> baseline = '4.0 hour'
>>> transit_duration = '2.0 hour'
>>> resolution = 100.0
>>> n_transits = 2
>>> Jmag = 8.0
>>> metal = 0.0

>>> pandexo_sim, wls, spectra, uncerts = io.export_pandexo(
>>>     pyrat, baseline, transit_duration,
>>>     n_transits=n_transits,
>>>     resolution=resolution,
>>>     instrument=instrument,
>>>     Jmag=Jmag,
>>>     metal=metal)

pyratbay.tools

pyratbay.tools.log_error(log=None, error=None)[source]
Capture exceptions into a log.error() call.
pyratbay.tools.cd(newdir)[source]
Context manager for changing the current working directory.
Taken from here: https://stackoverflow.com/questions/431684/
pyratbay.tools.tmp_reset(obj, *attrs, **tmp_attrs)[source]
Temporarily remove attributes from an object.

Examples
--------
>>> import pyratbay.tools as pt
>>> o   = type('obj', (object,), {'x':1.0, 'y':2.0})
>>> obj = type('obj', (object,), {'z':3.0, 'w':4.0, 'o':o})
>>> # All listed arguments are set to None:
>>> with pt.tmp_reset(obj, 'o.x', 'z'):
>>>     print(obj.o.x, obj.o.y, obj.z, obj.w)
(None, 2.0, None, 4.0)
>>> # Keyword arguments can be set to a value, but cannot be recursive:
>>> with pt.tmp_reset(obj, 'o.x', z=10):
>>>     print(obj.o.x, obj.o.y, obj.z, obj.w)
(None, 2.0, 10, 4.0)
pyratbay.tools.binsearch(tli, wnumber, rec0, nrec, upper=True)[source]
Do a binary+linear search in TLI dbfile for record with wavenumber
immediately less equal to wnumber (if upper is True), or greater
equal to wnumber (if upper) is False (considering duplicate values
in tli file).

Parameters
----------
tli: File object
    TLI file where to search.
wnumber: Scalar
    Target wavenumber in cm-1.
rec0: Integer
    File position of first wavenumber record.
nrec: Integer
    Number of wavenumber records.
upper: Boolean
    If True, consider wnumber as an upper boundary. If False,
    consider wnumber as a lower boundary.

Returns
-------
irec: Integer
    Index of record nearest to target. Return -1 if out of bounds.

Examples
--------
>>> import pyratbay.tools as pt
>>> import struct
>>> # Mock a TLI file:
>>> wn = [0.0, 1.0, 1.0, 1.0, 2.0, 2.0]
>>> with open('tli_demo.dat', 'wb') as tli:
>>>     tli.write(struct.pack(str(len(wn))+"d", *wn))
>>> # Now do bin searches for upper and lower boundaries:
>>> with open('tli_demo.dat', 'rb') as tli:
>>>     bs_lower = [pt.binsearch(tli, target, 0, len(wn), upper=False)
>>>                 for target in [-1.0, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5]]
>>>     bs_upper = [pt.binsearch(tli, target, 0, len(wn), upper=True)
>>>                 for target in [-1.0, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5]]
>>> print(bs_lower, bs_upper, sep='\n')
[0, 0, 1, 1, 4, 4, -1]
[-1, 0, 0, 3, 3, 5, 5]
pyratbay.tools.divisors(number)[source]
Find all the integer divisors of number.
pyratbay.tools.unpack(file, n, dtype)[source]
Wrapper for struct unpack.

Parameters
----------
file: File object
    File object to read from.
n: Integer
    Number of elements to read from file.
dtype: String
    Data type of the bytes read.

Returns
-------
output: Scalar, tuple, or string
    If dtype is 's' return the string (decoded as UTF-8).
    If there is a single element to read, return the scalar value.
    Else, return a tuple with the elements read.

Examples
--------
>>> import pyratbay.tools as pt
>>> import struct
>>> import numpy as np
>>> # Store a string and numbers in a binary file:
>>> with open('delete_me.dat', 'wb') as bfile:
>>>     bfile.write(struct.pack('3s', 'H2O'.encode('utf-8')))
>>>     bfile.write(struct.pack('h', 3))
>>>     bfile.write(struct.pack('3f', np.pi, np.e, np.inf))

>>> # Unpack them:
>>> with open('delete_me.dat', 'rb') as bfile:
>>>     string = pt.unpack(bfile, 3, 's')
>>>     number = pt.unpack(bfile, 1, 'h')
>>>     values = pt.unpack(bfile, 3, 'f')

>>> # See outputs:
>>> print(string, number, values, sep='\n')
H2O
3
(3.1415927410125732, 2.7182817459106445, inf)
pyratbay.tools.u(units)[source]
Get the conversion factor (to the CGS system) for units.

Parameters
----------
units: String
    Name of units.

Returns
-------
value: Float
    Value of input units in CGS units.

Examples
--------
>>> import pyratbay.tools as pt
>>> for units in ['cm', 'm', 'rearth', 'rjup', 'au']:
>>>     print(f'{units} = {pt.u(units)} cm')
cm = 1.0 cm
m = 100.0 cm
rearth = 637810000.0 cm
rjup = 7149200000.0 cm
au = 14959787069100.0 cm
pyratbay.tools.get_param(param, units='none', gt=None, ge=None)[source]
Read a parameter that may or may not have units.
If it doesn't, default to the 'units' input argument.

Parameters
----------
param: String, Float, integer, or ndarray
    The parameter value (which may contain the units).
units: String
    The default units for the parameter.
gt: Float
    If not None, check output is greater than gt.
ge: Float
    If not None, check output is greater-equal than gt.

Returns
-------
value: Float or integer

Examples
--------
>>> import pyratbay.tools as pt
>>> # One meter in cm:
>>> pt.get_param('1.0 m')
100.0

>>> # Alternatively, specify units in second argument:
>>> pt.get_param(1.0, 'm')
100.0

>>> # Units in 'param' take precedence over 'unit':
>>> pt.get_param('1.0 m', 'km')
100.0

>>> # Request returned value to be positive:
>>> pt.get_param('-30.0 kelvin', gt=0.0)
ValueError: Value -30.0 must be > 0.0.
pyratbay.tools.ifirst(data, default_ret=-1)[source]
Get the first index where data is True or 1.

Parameters
----------
data: 1D bool/integer iterable
    An array of bools or integers.
default_ret: Integer
    Default returned value when no value in data is True or 1.

Returns
-------
first: integer
   First index where data == True or 1.  Return default_ret otherwise.

Examples
--------
>>> import pyratbay.tools as pt
>>> import numpy as np
>>> print(pt.ifirst([1,0,0]))
0
>>> print(pt.ifirst(np.arange(5)>2.5))
3
>>> print(pt.ifirst([False, True, True]))
1
>>> print(pt.ifirst([False, False, False]))
-1
>>> print(pt.ifirst([False, False, False], default_ret=0))
0
pyratbay.tools.ilast(data, default_ret=-1)[source]
Get the last index where data is 1 or True.

Parameters
----------
data: 1D bool/integer iterable
    An array of bools or integers.
default_ret: Integer
    Default returned value when no value in data is True or 1.

Returns
-------
last: integer
   Last index where data == 1 or True.  Return default_ret otherwise.

Examples
--------
>>> import pyratbay.tools as pt
>>> import numpy as np
>>> print(pt.ilast([1,0,0]))
0
>>> print(pt.ilast(np.arange(5)<2.5))
2
>>> print(pt.ilast([False, True, True]))
2
>>> print(pt.ilast([False, False, False]))
-1
>>> print(pt.ilast([False, False, False], default_ret=0))
0
pyratbay.tools.isfile(path)[source]
Check whether a path (or list of paths) is a regular file.

Parameters
----------
path:  String or list
    Path(s) to check.

Returns
-------
status: Integer
    If path is None, return -1.
    If any path is not a regular file, return 0.
    If all paths are a regular file, return 1.

Examples (for Python 2.7, import from pathlib2)
--------
>>> import pyratbay.tools as pt
>>> from pathlib import Path
>>> # Mock couple files:
>>> file1, file2 = './tmp_file1.deleteme', './tmp_file2.deleteme'
>>> Path(file1).touch()
>>> Path(file2).touch()
>>> # Input is None:
>>> print(pt.isfile(None))
-1
>>> # All input files exist:
>>> print(pt.isfile(file1))
1
>>> print(pt.isfile([file1]))
1
>>> print(pt.isfile([file1, file2]))
1
>>> # At least one input does not exist:
>>> print(pt.isfile('nofile'))
0
>>> print(pt.isfile(['nofile']))
0
>>> print(pt.isfile([file1, 'nofile']))
0
pyratbay.tools.file_exists(pname, desc, value)[source]
Check that a file or list of files (value) exist.  If not None
and file(s) do not exist, raise a ValueError.

Parameters
----------
pname: String
    Parameter name.
desc: String
    Parameter description.
value: String or list of strings
    File path(s) to check.

Examples (for Python 2.7, import from pathlib2)
--------
>>> import pyratbay.tools as pt
>>> from pathlib import Path
>>> # None is OK:
>>> pt.file_exists('none', 'None input', None)
>>> # Create a file, check it exists:
>>> Path('./new_tmp_file.dat').touch()
>>> pt.file_exists('testfile', 'Test', 'new_tmp_file.dat')
>>> # Non-existing file throws error:
>>> pt.file_exists('testfile', 'Test', 'no_file.dat')
ValueError: Test file (testfile) does not exist: 'no_file.dat'
pyratbay.tools.path(filename)[source]
Ensure file names have non-null path

Parameters
----------
filename: String
    A file name.

Examples
--------
>>> import pyratbay.tools as pt
>>> print(pt.path('file.txt'))
./file.txt
>>> print(pt.path('./file.txt'))
./file.txt
>>> print(pt.path('/home/user/file.txt'))
/home/user/file.txt
class pyratbay.tools.Formatted_Write(indent=0, si=4, fmt=None, edge=None, lw=80, prec=None)[source]
Write (and keep) formatted, wrapped text to string.

Following PEP3101, this class subclasses Formatter to handle
None when a specific format is set.

Examples
--------
>>> import numpy as np
>>> import pyratbay.tools as pt
>>> fmt = pt.Formatted_Write()
>>> rstar = np.pi/3.14
>>> fmt.write('Stellar radius (rstar, rsun):  {:.2f}', rstar)
>>> fmt.write('Stellar radius (rstar, rsun):  {:.2f}', None)
>>> fmt.write('Stellar radius (rstar, rsun):  {}',     rstar)
>>> fmt.write('Stellar radius (rstar, rsun):  {}',     None)
>>> print(fmt.text)
Stellar radius (rstar, rsun):  1.00
Stellar radius (rstar, rsun):  None
Stellar radius (rstar, rsun):  1.0005072145190423
Stellar radius (rstar, rsun):  None


Parameters
----------
indent: Integer
    Number of blanks for indentation in first line.
si: Integer
    Number of blanks for indentation in subsequent lines.
fmt: dict of callables.
    Default formatting for numpy arrays (as in formatting in
    np.printoptions).
edge: Integer
    Default number of array items in summary at beginning/end
    (as in edgeitems in np.printoptions).
lw: Integer
    Default number of characters per line (as in linewidth in
    np.printoptions).
prec: Integer
    Default precision for floating point values (as in precision
    in np.printoptions).
write(text, *format, **numpy_fmt)[source]
Write formatted text.
See __init__ arguments for avaiable numpy_fmt items.
class pyratbay.tools.Timer[source]
Timer to get the time (in seconds) since the last call.


Initialize self.  See help(type(self)) for accurate signature.
pyratbay.tools.get_exomol_mol(dbfile)[source]
Parse an exomol file to extract the molecule and isotope name.

Parameters
----------
dbfile: String
    An exomol line-list file (must follow ExoMol naming convention).

Returns
-------
molecule: String
    Name of the molecule.
isotope: String
    Name of the isotope (See Tennyson et al. 2016, jmosp, 327).

Examples
--------
>>> import pyratbay.tools as pt
>>> filenames = [
>>>     '1H2-16O__POKAZATEL__00400-00500.trans.bz2',
>>>     '1H-2H-16O__VTT__00250-00500.trans.bz2',
>>>     '12C-16O2__HITEMP.pf',
>>>     '12C-16O-18O__Zak.par',
>>>     '12C-1H4__YT10to10__01100-01200.trans.bz2',
>>>     '12C-1H3-2H__MockName__01100-01200.trans.bz2'
>>>    ]
>>> for db in filenames:
>>>     print(pt.get_exomol_mol(db))
('H2O', '116')
('H2O', '126')
('CO2', '266')
('CO2', '268')
('CH4', '21111')
('CH4', '21112')
pyratbay.tools.cia_hitran(ciafile, tstep=1, wstep=1)[source]
Re-write a HITRAN CIA file into Pyrat Bay format.
See Richard et al. (2012) and https://www.cfa.harvard.edu/HITRAN/

Parameters
----------
ciafile: String
    A HITRAN CIA file.
tstep: Integer
    Slicing step size along temperature dimension.
wstep: Integer
    Slicing step size along wavenumber dimension.

Examples
--------
>>> import pyratbay.tools as pt
>>> # Before moving on, download a HITRAN CIA files from the link above.
>>> ciafile = 'H2-H2_2011.cia'
>>> pt.cia_hitran(ciafile, tstep=2, wstep=10)
pyratbay.tools.cia_borysow(ciafile, species1, species2)[source]
Re-write a Borysow CIA file into Pyrat Bay format.
See http://www.astro.ku.dk/~aborysow/programs/

Parameters
----------
ciafile: String
    A HITRAN CIA file.
species1: String
    First CIA species.
species2: String
    Second CIA species.

Examples
--------
>>> import pyratbay.tools as pt
>>> # Before moving on, download a HITRAN CIA files from the link above.
>>> ciafile = 'ciah2he_dh_quantmech'
>>> pt.cia_borysow(ciafile, 'H2', 'He')
pyratbay.tools.radius_to_depth(rprs, rprs_err)[source]
Compute transit depth (and uncertainties) from input
planet=to-star radius-ratio, with error propagation.

Parameters
----------
rprs: Float or float iterable
    Planet-to-star radius ratio.
rprs_err: Float or float iterable
    Uncertainties of the radius ratios.

Returns
-------
depth: Float or float ndarray
    Transit depth for given radius ratio.
depth_err: Float or float ndarray
    Uncertainties of the transit depth.

Examples
--------
>>> import numpy as np
>>> import pyratbay.tools as pt
>>> rprs = 1.2
>>> rprs_err = 0.25
>>> depth, depth_err = pt.radius_to_depth(rprs, rprs_err)
>>> print(f'Depth = {depth} +/- {depth_err}')
Depth = 1.44 +/- 0.6

>>> rprs = [1.2, 1.5]
>>> rprs_err = [0.25, 0.3]
>>> depth, depth_err = pt.radius_to_depth(rprs, rprs_err)
>>> print('Depth    Uncert\n' +
>>>     '\n'.join([f'{d} +/- {de:.1f}' for d,de in zip(depth, depth_err)]))
Depth    Uncert
1.44 +/- 0.6
2.25 +/- 0.9
pyratbay.tools.depth_to_radius(depth, depth_err)[source]
Compute planet-to-star radius ratio (and uncertainties) from
input transit depth, with error propagation.

Parameters
----------
depth: Float or float iterable
    Transit depth.
depth_err: Float or float iterable
    Uncertainties of the transit depth.

Returns
-------
rprs: Float or float ndarray
    Planet-to-star radius ratio.
rprs_err: Float or float ndarray
    Uncertainties of the radius ratio rprs.

Examples
--------
>>> import numpy as np
>>> import pyratbay.tools as pt
>>> depth = 1.44
>>> depth_err = 0.6
>>> rprs, rprs_err = pt.depth_to_radius(depth, depth_err)
>>> print(f'Rp/Rs = {rprs} +/- {rprs_err}')
Rp/Rs = 1.2 +/- 0.25

>>> depth = [1.44, 2.25]
>>> depth_err = [0.6, 0.9]
>>> rprs, rprs_err = pt.depth_to_radius(depth, depth_err)
>>> print('Rp/Rs   Uncert\n'
>>>     + '\n'.join([f'{r} +/- {re}' for r,re in zip(rprs, rprs_err)]))
Rp/Rs   Uncert
1.2 +/- 0.25
1.5 +/- 0.3
pyratbay.tools.ignore_system_exit(func)[source]
Decorator to ignore SystemExit exceptions.
class pyratbay.tools.Namespace(args=None, log=None)[source]
A container object to hold variables.


Initialize self.  See help(type(self)) for accurate signature.
get_default(pname, desc, default=None, wflag=False, gt=None, ge=None, lt=None, le=None)[source]
Extract pname variable from Namespace; if None, return
default.  If any of gt, ge, lt, or le is not None, run
greater/lower/equal checks.

Parameters
----------
pname: String
    Parameter name.
desc: String
    Parameter description.
default: Any
    Parameter default value.
gt: Float
    If not None, check output is greater than gt.
ge: Float
    If not None, check output is greater-equal than gt.
lt: Float
    If not None, check output is lower than gt.
le: Float
    If not None, check output is lower-equal than gt.
get_path(pname, desc='', exists=False)[source]
Extract pname file path (or list of paths) from Namespace,
return the canonical path.

Examples
--------
>>> import pyratbay.tools as pt
>>> ns = pt.Namespace({'f1':'file1', 'f23':['file2', 'file3']})
>>> # Get path of a single file:
>>> ns.get_path('f1')
>>> # Get path of a list of files:
>>> ns.get_path('f23')
>>> # Attempt to get non-existing file:
>>> ns.get_path('f1', desc='Configuration', exists=True)
get_units(pname)[source]
Extract units from a value input.
Return None if value does not have units or has an invalid format.

Parameters
----------
pname: String
    Parameter name.

Returns
-------
units: String
pyratbay.tools.parse(pyrat, cfile, no_logfile=False, mute=False)[source]
Read the command line arguments.

Parameters
----------
cfile: String
    A Pyrat Bay configuration file.
no_logfile: Bool
    If True, enforce not to write outputs to a log file
    (e.g., to prevent overwritting log of a previous run).
mute: Bool
    If True, enforce verb to take a value of -1.
pyratbay.tools.parse_str(args, param)[source]
Parse a string parameter into args.
pyratbay.tools.parse_int(args, param)[source]
Convert a dictionary's parameter from string to integer.
Raise ValueError if the operation is not possible.
Set parameter to None if it was not in the dictinary.

Parameters
----------
args: dict
    Dictionary where to operate.
param: String
    Parameter to cast to int.

Examples
--------
>>> import pyratbay.tools as pt
>>> inputs = ['10', '-10', '+10', '10.0', '1e1',
>>>           '10.5', 'None', 'True', 'inf', '10 20']
>>> args = {f'par{i}':val for i,val in enumerate(inputs)}
>>> for i,var in enumerate(inputs):
>>>     try:
>>>         par = f'par{i}'
>>>         pt.parse_int(args, par)
>>>         print(f"{par}: '{var}' -> {args[par]}")
>>>     except ValueError as e:
>>>         print(e)
par0: '10' -> 10
par1: '-10' -> -10
par2: '+10' -> 10
par3: '10.0' -> 10
par4: '1e1' -> 10
Invalid data type for par5, could not convert string to integer: '10.5'
Invalid data type for par6, could not convert string to integer: 'None'
Invalid data type for par7, could not convert string to integer: 'True'
Invalid data type for par8, could not convert string to integer: 'inf'
Invalid data type for par9, could not convert string to integer: '10 20'
pyratbay.tools.parse_float(args, param)[source]
Convert a dictionary's parameter from string to float.
Raise ValueError if the operation is not possible.
Set parameter to None if it was not in the dictinary.

Parameters
----------
args: dict
    Dictionary where to operate.
param: String
    Parameter to cast to float.

Examples
--------
>>> import pyratbay.tools as pt
>>> inputs = ['10', '-10', '+10', '10.5', '1e1', 'inf', 'nan',
>>>           'None', 'True', '10 20']
>>> args = {f'par{i}':val for i,val in enumerate(inputs)}
>>> for i,var in enumerate(inputs):
>>>     try:
>>>         par = f'par{i}'
>>>         pt.parse_float(args, par)
>>>         print(f"{par}: '{var}' -> {args[par]}")
>>>     except ValueError as e:
>>>         print(e)
par0: '10' -> 10.0
par1: '-10' -> -10.0
par2: '+10' -> 10.0
par3: '10.5' -> 10.5
par4: '1e5' -> 10.0
par5: 'inf' -> inf
par6: 'nan' -> nan
Invalid data type for par7, could not convert string to float: 'None'
Invalid data type for par8, could not convert string to float: 'True'
Invalid data type for par9, could not convert string to float: '10 20'
pyratbay.tools.parse_array(args, param)[source]
Convert a dictionary's parameter from string to iterable.
If possible cast into a float numpy array; otherwise,
set as a list of strings.
Assume any blank character delimits the elements in the string.
Set parameter to None if it was not in the dictinary.

Parameters
----------
args: dict
    Dictionary where to operate.
param: String
    Parameter to cast to array.

Examples
--------
>>> import pyratbay.tools as pt
>>> inputs = ['10 20', '10.0 20.0', 'a b', 'a\n b']
>>> args = {f'par{i}':val for i,val in enumerate(inputs)}
>>> for i,var in enumerate(inputs):
>>>     par = f'par{i}'
>>>     pt.parse_array(args, par)
>>>     print(f"{par}: {repr(var)} -> {repr(args[par])}")
par0: '10 20' -> array([10., 20.])
par1: '10.0 20.0' -> array([10., 20.])
par2: 'a b' -> ['a', 'b']
par3: 'a\n b' -> ['a', 'b']

pyratbay.opacity

pyratbay.opacity.make_tli(dblist, pflist, dbtype, tlifile, wllow, wlhigh, wlunits, log)[source]
Create a transition-line-information (TLI) file.

Parameters
----------
dblist: List of strings
    Opacity databases to read.
pflist: List of strings
    Partition function for each of the databases.
dbtype: List of strings
    Database type of each database.
tlifile: String
    Output TLI file name.
wllow: String or float
    Lower wavelength boundary to consider. If float, assume units
    from wlunits input.  Otherwise, wllow sets the value and units
    (for example: '1.0 um').
wlhigh: String or float
    High wavelength boundary to consider. If float, assume units
    from wlunits input.  Otherwise, wlhigh sets the value and units.
wlunits: String
    Wavelength units (when not specified in wllow nor wlhigh).
log: Log object
    An mc3.utils.Log instance to log screen outputs to file.

pyratbay.opacity.linelist

class pyratbay.opacity.linelist.Hitran(dbfile, pffile, log)[source]
HITRAN/HITEMP database reader.


Initialize HITRAN database object.

Parameters
----------
dbfile: String
    File with the Database line-transition info.
pffile: String
    File with the partition function.
log: Log object
    An mc3.utils.Log instance to log screen outputs to file.
binsearch(dbfile, wave, ilo, ihi, searchup=True)
Do a binary (and then linear) search for wavelength/wavenumber in
file 'dbfile' between record positions ilo and ihi.

Parameters
----------
dbfile: File object
   File where to search.
wave: Scalar
   Target wavelength/wavenumber (as given in each specific database).
ilo: Integer
   Lowest index record to search.
ihi: Integer
   highest index record to search.
searchup: Boolean
   Search up (True) or down (False) the records for duplicate results
   after the binary search.

Returns:
--------
irec:  Integer
   Record index for wave.
dbread(iwn, fwn, verb)[source]
Read line-transition info between wavenumbers iwn and fwn.

Parameters
----------
iwn: Float
    Lower wavenumber boundary in cm-1.
fwn: Float
    Upper wavenumber boundary in cm-1.
verb: Integer
    Verbosity threshold.

Returns
-------
wnumber: 1D float ndarray
    Line-transition central wavenumber (cm-1).
gf: 1D float ndarray
    gf value (unitless).
elow: 1D float ndarray
    Lower-state energy (cm-1).
isoID: 1D integer ndarray
    Isotope index.
get_iso(molname, dbtype)
Get isotopic info from isotopes.dat file.

Parameters
----------
mol: String
    If not None, extract data based on this molecule name.
dbtype: String
    Database type (for isotope names).

Returns
-------
molID: Integer
    HITRAN molecule ID.
isotopes: List of strings
    Isotopes names.
mass: List of floats
    Masses for each isotope.
isoratio: List of integers
    Isotopic terrestrial abundance ratio.
getpf(verbose=0)
Compute partition function for specified source.

Returns
-------
temp: 1D float ndarray
    Array with temperature sample.
PF: 2D float ndarray
    The partition function data for each isotope at each temperature.
isotopes: List of strings
    The names of the tabulated isotopes
readwave(dbfile, irec)[source]
Read irec-th wavenumber record from FILE dbfile.

Parameters
----------
dbfile: File object
    File where to extract the wavenumber.
irec: Integer
    Index of record.

Returns
-------
wavenumber: Float
    Wavenumber value in cm-1.
class pyratbay.opacity.linelist.Exomol(dbfile, pffile, log)[source]
Exomol database reader.


Initialize Exomol database object.

Parameters
----------
dbfile: String
    File with the Database line-transition info.
pffile: String
    File with the partition function.
log: Log object
    An mc3.utils.Log instance to log screen outputs to file.
binsearch(dbfile, wave, ilo, ihi, searchup=True)
Do a binary (and then linear) search for wavelength/wavenumber in
file 'dbfile' between record positions ilo and ihi.

Parameters
----------
dbfile: File object
   File where to search.
wave: Scalar
   Target wavelength/wavenumber (as given in each specific database).
ilo: Integer
   Lowest index record to search.
ihi: Integer
   highest index record to search.
searchup: Boolean
   Search up (True) or down (False) the records for duplicate results
   after the binary search.

Returns:
--------
irec:  Integer
   Record index for wave.
dbread(iwn, fwn, verb)[source]
Read line-transition info between wavenumbers iwn and fwn.

Parameters
----------
iwn: Float
    Lower wavenumber boundary in cm-1.
fwn: Float
    Upper wavenumber boundary in cm-1.
verb: Integer
    Verbosity threshold.

Returns
-------
wnumber: 1D float ndarray
    Line-transition central wavenumber (cm-1).
gf: 1D float ndarray
    gf value (unitless).
elow: 1D float ndarray
    Lower-state energy (cm-1).
isoID: 1D integer ndarray
    Isotope index.
get_iso(molname, dbtype)
Get isotopic info from isotopes.dat file.

Parameters
----------
mol: String
    If not None, extract data based on this molecule name.
dbtype: String
    Database type (for isotope names).

Returns
-------
molID: Integer
    HITRAN molecule ID.
isotopes: List of strings
    Isotopes names.
mass: List of floats
    Masses for each isotope.
isoratio: List of integers
    Isotopic terrestrial abundance ratio.
getpf(verbose=0)
Compute partition function for specified source.

Returns
-------
temp: 1D float ndarray
    Array with temperature sample.
PF: 2D float ndarray
    The partition function data for each isotope at each temperature.
isotopes: List of strings
    The names of the tabulated isotopes
readwave(dbfile, irec)[source]
Read irec-th wavenumber record from FILE dbfile.

Parameters
----------
dbfile: File object
    File where to extract the wavenumber.
irec: Integer
    Index of record.

Returns
-------
wavenumber: Float
    Wavenumber value in cm-1.
class pyratbay.opacity.linelist.Repack(dbfile, pffile, log)[source]
Repack database reader.


Initialize Exomol database object.

Parameters
----------
dbfile: String
    File with the Database line-transition info.
pffile: String
    File with the partition function.
log: Log object
    An mc3.utils.Log instance to log screen outputs to file.
binsearch(dbfile, wave, ilo, ihi, searchup=True)
Do a binary (and then linear) search for wavelength/wavenumber in
file 'dbfile' between record positions ilo and ihi.

Parameters
----------
dbfile: File object
   File where to search.
wave: Scalar
   Target wavelength/wavenumber (as given in each specific database).
ilo: Integer
   Lowest index record to search.
ihi: Integer
   highest index record to search.
searchup: Boolean
   Search up (True) or down (False) the records for duplicate results
   after the binary search.

Returns:
--------
irec:  Integer
   Record index for wave.
dbread(iwn, fwn, verb)[source]
Read line-transition info between wavenumbers iwn and fwn.

Parameters
----------
iwn: Float
    Lower wavenumber boundary in cm-1.
fwn: Float
    Upper wavenumber boundary in cm-1.
verb: Integer
    Verbosity threshold.

Returns
-------
wnumber: 1D float ndarray
    Line-transition central wavenumber (cm-1).
gf: 1D float ndarray
    gf value (unitless).
elow: 1D float ndarray
    Lower-state energy (cm-1).
isoID: 1D integer ndarray
    Isotope index.
get_iso(molname, dbtype)
Get isotopic info from isotopes.dat file.

Parameters
----------
mol: String
    If not None, extract data based on this molecule name.
dbtype: String
    Database type (for isotope names).

Returns
-------
molID: Integer
    HITRAN molecule ID.
isotopes: List of strings
    Isotopes names.
mass: List of floats
    Masses for each isotope.
isoratio: List of integers
    Isotopic terrestrial abundance ratio.
getpf(verbose=0)
Compute partition function for specified source.

Returns
-------
temp: 1D float ndarray
    Array with temperature sample.
PF: 2D float ndarray
    The partition function data for each isotope at each temperature.
isotopes: List of strings
    The names of the tabulated isotopes
readwave(dbfile, irec)[source]
Read irec-th wavenumber record from FILE dbfile.

Parameters
----------
dbfile: File object
    File where to extract the wavenumber.
irec: Integer
    Index of record.

Returns
-------
wavenumber: Float
    Wavenumber value in cm-1.
class pyratbay.opacity.linelist.Pands(dbfile, pffile, log)[source]
Partridge & Schwenke (1997) H2O database reader.


Initialize P&S database object.

Parameters
----------
dbfile: String
    File with the Database line-transition info.
pffile: String
    File with the partition function.
log: Log object
    An mc3.utils.Log instance to log screen outputs to file.
binsearch(dbfile, wave, ilo, ihi, searchup=True)
Do a binary (and then linear) search for wavelength/wavenumber in
file 'dbfile' between record positions ilo and ihi.

Parameters
----------
dbfile: File object
   File where to search.
wave: Scalar
   Target wavelength/wavenumber (as given in each specific database).
ilo: Integer
   Lowest index record to search.
ihi: Integer
   highest index record to search.
searchup: Boolean
   Search up (True) or down (False) the records for duplicate results
   after the binary search.

Returns:
--------
irec:  Integer
   Record index for wave.
dbread(iwn, fwn, verb)[source]
Read line-transition info between wavenumbers iwn and fwn.

Parameters
----------
iwn: Float
    Lower wavenumber boundary in cm-1.
fwn: Float
    Upper wavenumber boundary in cm-1.
verb: Integer
    Verbosity threshold.

Returns
-------
wnumber: 1D float ndarray
    Line-transition central wavenumber (cm-1).
gf: 1D float ndarray
    gf value (unitless).
elow: 1D float ndarray
    Lower-state energy (cm-1).
isoID: 1D integer ndarray
    Isotope index.
get_iso(molname, dbtype)
Get isotopic info from isotopes.dat file.

Parameters
----------
mol: String
    If not None, extract data based on this molecule name.
dbtype: String
    Database type (for isotope names).

Returns
-------
molID: Integer
    HITRAN molecule ID.
isotopes: List of strings
    Isotopes names.
mass: List of floats
    Masses for each isotope.
isoratio: List of integers
    Isotopic terrestrial abundance ratio.
getpf(verbose=0)
Compute partition function for specified source.

Returns
-------
temp: 1D float ndarray
    Array with temperature sample.
PF: 2D float ndarray
    The partition function data for each isotope at each temperature.
isotopes: List of strings
    The names of the tabulated isotopes
readwave(dbfile, irec)[source]
Read irec-th wavelength record from FILE dbfile.

Parameters
----------
dbfile: File object
    File where to extract the wavelength.
irec: Integer
    Index of record.

Returns
-------
recwl: Unsigned integer
    Wavelength value as given in the P&S binary file.
class pyratbay.opacity.linelist.Tioschwenke(dbfile, pffile, log)[source]
Notes:
------
Linelist and partition function downloaded from:
  http://kurucz.harvard.edu/molecules/tio/tioschwenke.bin
  http://kurucz.harvard.edu/molecules/tio/tiopart.dat

There might be a problem with the linebreak character of the partition
function.  One way to fix is, on vim do: :%s/
/
/g


Initialize self.  See help(type(self)) for accurate signature.
binsearch(dbfile, wave, ilo, ihi, searchup=True)
Do a binary (and then linear) search for wavelength/wavenumber in
file 'dbfile' between record positions ilo and ihi.

Parameters
----------
dbfile: File object
   File where to search.
wave: Scalar
   Target wavelength/wavenumber (as given in each specific database).
ilo: Integer
   Lowest index record to search.
ihi: Integer
   highest index record to search.
searchup: Boolean
   Search up (True) or down (False) the records for duplicate results
   after the binary search.

Returns:
--------
irec:  Integer
   Record index for wave.
dbread(iwn, fwn, verb)[source]
Read the Schwenke TiO database.

Parameters
----------
iwn: Scalar
    Initial wavenumber limit (in cm-1).
fwn: Scalar
    Final wavenumber limit (in cm-1).
verb: Integer
    Verbosity threshold.

Returns
-------
wnumber: 1D float ndarray
    Line-transition central wavenumber (centimeter-1).
gf: 1D float ndarray
    gf value (unitless).
elow: 1D float ndarray
    Lower-state energy (centimeter-1).
isoID: 2D integer ndarray
    Isotope index (0, 1, 2, 3, ...).
get_iso(molname, dbtype)
Get isotopic info from isotopes.dat file.

Parameters
----------
mol: String
    If not None, extract data based on this molecule name.
dbtype: String
    Database type (for isotope names).

Returns
-------
molID: Integer
    HITRAN molecule ID.
isotopes: List of strings
    Isotopes names.
mass: List of floats
    Masses for each isotope.
isoratio: List of integers
    Isotopic terrestrial abundance ratio.
getpf(verbose=0)
Compute partition function for specified source.

Returns
-------
temp: 1D float ndarray
    Array with temperature sample.
PF: 2D float ndarray
    The partition function data for each isotope at each temperature.
isotopes: List of strings
    The names of the tabulated isotopes
readwave(dbfile, irec)[source]
Read wavelength parameter from irec record in dbfile database.

Parameters
----------
dbfile: File object
   File where to extract the wavelength.
irec: Integer
   Index of record.

Returns
-------
rec_wl: integer
   Wavelength value at record irec, as given in dbfile database.
class pyratbay.opacity.linelist.Voplez(dbfile, pffile, log)[source]
Download the linelist from:


Initializer.
binsearch(dbfile, wave, ilo, ihi, searchup=True)
Do a binary (and then linear) search for wavelength/wavenumber in
file 'dbfile' between record positions ilo and ihi.

Parameters
----------
dbfile: File object
   File where to search.
wave: Scalar
   Target wavelength/wavenumber (as given in each specific database).
ilo: Integer
   Lowest index record to search.
ihi: Integer
   highest index record to search.
searchup: Boolean
   Search up (True) or down (False) the records for duplicate results
   after the binary search.

Returns:
--------
irec:  Integer
   Record index for wave.
dbread(iwn, fwn, verb)[source]
Read the B. Plez VO database between the wavelengths iwl and fwl.

Parameters:
-----------
iwn: Scalar
   Initial wavenumber limit (in cm-1).
fwn: Scalar
   Final wavenumber limit (in cm-1).
verb: Integer
   Verbosity threshold.

Returns:
--------
wnumber: 1D float ndarray
  Line-transition central wavenumber (centimeter-1).
gf: 1D float ndarray
  gf value (unitless).
elow: 1D float ndarray
  Lower-state energy (centimeter-1).
isoID: 2D integer ndarray
  Isotope index (0, 1, 2, 3, ...).

Developers:
-----------
Patricio Cubillos (UCF).
Sarah Blumenthal (UCF).

Notes:
------
The Plez VO database is an ASCII format.
The line transitions are sorted in increasing wavelength (micron) order.
get_iso(molname, dbtype)
Get isotopic info from isotopes.dat file.

Parameters
----------
mol: String
    If not None, extract data based on this molecule name.
dbtype: String
    Database type (for isotope names).

Returns
-------
molID: Integer
    HITRAN molecule ID.
isotopes: List of strings
    Isotopes names.
mass: List of floats
    Masses for each isotope.
isoratio: List of integers
    Isotopic terrestrial abundance ratio.
getpf(verbose=0)
Compute partition function for specified source.

Returns
-------
temp: 1D float ndarray
    Array with temperature sample.
PF: 2D float ndarray
    The partition function data for each isotope at each temperature.
isotopes: List of strings
    The names of the tabulated isotopes
readwave(dbfile, irec)[source]
Extract the wavelength from record irec.

Parameters:
-----------
dbfile: File pointer
   Pointer to file being read.
irec: Integer
   Index of record to read.

Returns:
--------
wl: Float
   The wavelength in microns for record irec.
class pyratbay.opacity.linelist.Vald(dbfile, pffile, log)[source]
Notes
-----
  Download linelist from: http://vald.astro.uu.se/~vald/php/vald.php
     Selecting 'Extract Element' and 'Short format'.
  Download partition functions from:


Initialize Basic data for the Database.

Parameters
----------
dbfile: String
    File with the Database line-transition info.
pffile: String
    File with the partition function.
log: File
    File object to store the log.
binsearch(dbfile, wave, ilo, ihi, searchup=True)
Do a binary (and then linear) search for wavelength/wavenumber in
file 'dbfile' between record positions ilo and ihi.

Parameters
----------
dbfile: File object
   File where to search.
wave: Scalar
   Target wavelength/wavenumber (as given in each specific database).
ilo: Integer
   Lowest index record to search.
ihi: Integer
   highest index record to search.
searchup: Boolean
   Search up (True) or down (False) the records for duplicate results
   after the binary search.

Returns:
--------
irec:  Integer
   Record index for wave.
dbread(iwn, fwn, verb)[source]
Read a VALD database.

Parameters
----------
iwn: Scalar
    Initial wavenumber limit (in cm-1).
fwn: Scalar
    Final wavenumber limit (in cm-1).
verb: Integer
    Verbosity threshold.

Returns
-------
wnumber: 1D float ndarray
    Line-transition central wavenumber (cm-1).
gf: 1D float ndarray
    gf value (unitless).
elow: 1D float ndarray
    Lower-state energy (cm-1).
isoID: 2D integer ndarray
  Isotope index.
get_iso(molname, dbtype)
Get isotopic info from isotopes.dat file.

Parameters
----------
mol: String
    If not None, extract data based on this molecule name.
dbtype: String
    Database type (for isotope names).

Returns
-------
molID: Integer
    HITRAN molecule ID.
isotopes: List of strings
    Isotopes names.
mass: List of floats
    Masses for each isotope.
isoratio: List of integers
    Isotopic terrestrial abundance ratio.
getinfo()[source]
Doc me.
getpf(verbose=0)
Compute partition function for specified source.

Returns
-------
temp: 1D float ndarray
    Array with temperature sample.
PF: 2D float ndarray
    The partition function data for each isotope at each temperature.
isotopes: List of strings
    The names of the tabulated isotopes
readwave(dbfile, irec)[source]
Read irec-th wavenumber record from FILE dbfile.

Parameters
----------
dbfile: File object
    File where to extract the wavelength.
irec: Integer
    Index of record.

Returns
-------
wavenumber: Unsigned integer
    Wavenumber value in cm-1.

pyratbay.opacity.partitions

pyratbay.opacity.partitions.get_tips_molname(molID)[source]
Get the TIPS molecule name for given molecule ID.

Parameters
----------
molID: Integer
    HITRAN molecule ID. See for example: https://hitran.org/lbl/

Returns
-------
molname: String
    Name of molecule.

Examples
--------
>>> import pyratbay.opacity.partitions as pf
>>> print(pf.get_tips_molname(1), pf.get_tips_molname(6))
H2O CH4
pyratbay.opacity.partitions.tips(molecule, isotopes=None, outfile=None, db_type='as_tips')[source]
Extract TIPS 2021 partition-function values for given molecule.
If requested, write the partition-function into a file for use
with Pyrat Bay.
References:
    Gamache et al. (2017), JQSRT, 203, 70.
    Gamache et al. (2021), JQSRT, 271, 107713.

Parameters
----------
molecule: String
    Name of the molecule.
isotopes: String or list of strings
    If not None, only extract the requested isotopes.
outfile: String
    If not None, save output to file.
    If outfile == 'default', save output to file named as
    PF_tips_molecule.dat
db_type: String
    If db_type == 'as_exomol', return isotopic names following
    the exomol notation.

Returns
-------
pf: 2D float ndarray
    TIPS partition function for input molecule.
isotopes: 1D string list
    List of isotopes.
temp: 1D float ndarray
    Partition-function temperature samples (K).

Examples
--------
>>> import pyratbay.opacity.partitions as pf
>>> pf_data, isotopes, temp = pf.tips('H2O', outfile='default')

Written partition-function file:
  'PF_tips_H2O.dat'
for molecule H2O, with isotopes ['161', '181', '171', '162', '182', '172', '262', '282', '272'],
and temperature range 1--5000 K.
pyratbay.opacity.partitions.exomol(pf_files, outfile=None)[source]
Extract ExoMol partition-function values from input files.
If requested, write the partition-function into a file for use
with Pyrat Bay.

Parameters
----------
pf_files: String or List of strings
    Input Exomol partition-function filenames.  If there are
    multiple isotopes, all of them must correspond to the same
    molecule.
outfile: String
    If not None, save output to file.
    If outfile == 'default', save output to file named as
    PF_exomol_molecule.dat

Returns
-------
pf: 2D float ndarray
    TIPS partition function for input molecule.
isotopes: 1D string list
    List of isotopes.
temp: 1D float ndarray
    Partition-function temperature samples (K).

Examples
--------
>>> # First, download ExoMol data to current dictory, e.g.:
>>> # wget http://www.exomol.com/db/NH3/14N-1H3/BYTe/14N-1H3__BYTe.pf
>>> # wget http://www.exomol.com/db/NH3/15N-1H3/BYTe-15/15N-1H3__BYTe-15.pf
>>> import pyratbay.opacity.partitions as pf
>>> # A single file:
>>> pf_data, isotopes, temp = pf.exomol('14N-1H3__BYTe.pf',
>>>     outfile='default')
Written partition-function file:
  'PF_exomol_NH3.dat'
for molecule NH3, with isotopes ['4111'],
and temperature range 1--1600 K.

>>> # Multiple files (isotopes) for a molecule:
>>> pf_data, isotopes, temp = pf.exomol(
>>>     ['14N-1H3__BYTe.pf', '15N-1H3__BYTe-15.pf'], outfile='default')

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  Warning:
    Length of PF files do not match.  Trimming to shorter size.
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Written partition-function file:
  'PF_exomol_NH3.dat'
for molecule NH3, with isotopes ['4111', '5111'],
and temperature range 1--1600 K.
pyratbay.opacity.partitions.kurucz(pf_file, outfile=None, type_flag='as_exomol')[source]
Extract Kurucz partition-function values from input file.
If requested, write the partition-function into a file for use
with Pyrat Bay.

Parameters
----------
pf_file: String
    Input partition-function from Kurucz webpage.  Currently only H2O
    and TiO are available (probably there's no need for any other support).
    Files can be downloaded from these links:
      http://kurucz.harvard.edu/molecules/h2o/h2opartfn.dat
      http://kurucz.harvard.edu/molecules/tio/tiopart.dat
outfile: String
    If not None, save output to file.
    If outfile == 'default', save output to file named as
    PF_kurucz_molecule.dat

Returns
-------
pf: 2D float ndarray
    TIPS partition function for input molecule.
isotopes: 1D string list
    List of isotopes.
temp: 1D float ndarray
    Partition-function temperature samples (K).

Examples
--------
>>> # First, download kurucz data to current dictory, e.g.:
>>> # wget http://kurucz.harvard.edu/molecules/h2o/h2opartfn.dat
>>> # wget http://kurucz.harvard.edu/molecules/tio/tiopart.dat

>>> import pyratbay.opacity.partitions as pf
>>> pf_data, isotopes, temp = pf.kurucz('h2opartfn.dat', outfile='default')

Written partition-function file:
  'PF_kurucz_H2O.dat'
for molecule H2O, with isotopes ['1H1H16O', '1H1H17O', '1H1H18O', '1H2H16O'],
and temperature range 10--6000 K.

>>> pf_data, isotopes, temp = pf.kurucz('tiopart.dat', outfile='default')

Written partition-function file:
  'PF_kurucz_TiO.dat'
for molecule TiO, with isotopes ['66', '76', '86', '96', '06'],
and temperature range 10--6000 K.

pyratbay.opacity.broadening

class pyratbay.opacity.broadening.Lorentz(x0=0.0, hwhm=1.0, scale=1.0)[source]
1D Lorentz profile model.

Parameters
----------
x0: Float
   Profile center location.
hwhm: Float
   Profile's half-width at half maximum.
scale: Float
   Scale of the profile (scale=1 returns a profile with integral=1.0).

Examples
--------
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> import pyratbay.opacity.broadening as b
>>> lor = b.Lorentz(x0=0.0, hwhm=2.5, scale=1.0)
>>> # Half-width at half maximum is ~2.5:
>>> x = np.linspace(-10.0, 10.0, 100001)
>>> print(0.5 * np.ptp(x[lor(x)>0.5*np.amax(lor(x))]))
2.4998
>>> # Integral is ~ 1.0:
>>> x = np.linspace(-5000.0, 5000.0, 100001)
>>> print(np.trapz(lor(x), x))
0.999681690140321
>>> # Take a look at a Lorenzt profile:
>>> x = linspace(-10, 10, 101)
>>> plt.plot(x, lor(x))


Initialize self.  See help(type(self)) for accurate signature.
eval(x)[source]
Compute Lorentz profile over the specified coordinates range.

Parameters
----------
x: 1D float ndarray
   Input coordinates where to evaluate the profile.

Returns
-------
l: 1D float ndarray
   The line profile at the x locations.
class pyratbay.opacity.broadening.Gauss(x0=0.0, hwhm=1.0, scale=1.0)[source]
1D Gaussian profile model.

Parameters
----------
x0: Float
   Profile center location.
hwhm: Float
   Profile's half-width at half maximum.
scale: Float
   Scale of the profile (scale=1 returns a profile with integral=1.0).

Examples
--------
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> import pyratbay.opacity.broadening as b
>>> gauss = b.Gauss(x0=0.0, hwhm=2.5, scale=1.0)
>>> # Half-width at half maximum is ~2.5:
>>> x = np.linspace(-10.0, 10.0, 100001)
>>> print(0.5 * np.ptp(x[gauss(x)>0.5*np.amax(gauss(x))]))
2.4998
>>> # Integral is ~ 1.0:
>>> x = np.linspace(-5000.0, 5000.0, 100001)
>>> print(np.trapz(gauss(x), x))
1.0
>>> # Take a look at a Lorenzt profile:
>>> x = linspace(-10, 10, 101)
>>> plt.plot(x, gauss(x))


Initialize self.  See help(type(self)) for accurate signature.
eval(x)[source]
Compute Gaussian profile over the specified coordinates range.

Parameters
----------
x: 1D float ndarray
   Input coordinates where to evaluate the profile.

Returns
-------
g: 1D float ndarray
   The line profile at the x locations.
class pyratbay.opacity.broadening.Voigt(x0=0.0, hwhm_L=1.0, hwhm_G=1.0, scale=1.0)[source]
1D Voigt profile model.

Parameters
----------
x0: Float
    Line center location.
hwhm_L: Float
    Half-width at half maximum of the Lorentz distribution.
hwhm_G: Float
    Half-width at half maximum of the Gaussian distribution.
scale: Float
    Scale of the profile (scale=1 returns a profile with integral=1.0).

Examples
--------
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> import pyratbay.opacity.broadening as b

>>> hwhm_G = 1.0
>>> hwhm_L = 1.0
>>> voigt = b.Voigt(x0=0.0, hwhm_L=hwhm_L, hwhm_G=hwhm_G)

>>> plt.figure('A Voigt profile', (6,4))
>>> plt.clf()
>>> ax = plt.subplot(1, 1, 1)
>>> x = np.linspace(-15.0, 15.0, 3001)
>>> plt.plot(x, voigt(x), lw=2.0, color="orange")
>>> plt.xlim(np.amin(x), np.amax(x))
>>> plt.xlabel(r"x", fontsize=12)
>>> plt.ylabel(r"Voigt profile", fontsize=12)

>>> # Compare a range of Voigt, Lorentz, and Doppler profiles:
>>> lorentz = b.Lorentz(x0=0.0, hwhm=hwhm_L)
>>> doppler = b.Gauss(x0=0.0, hwhm=hwhm_G)
>>> nplots = 5
>>> HWHM_L = np.logspace(-2, 2, nplots)
>>> nwidths = 10.0
>>> plt.figure(11, (6,6))
>>> plt.clf()
>>> plt.subplots_adjust(0.15, 0.1, 0.95, 0.95, wspace=0, hspace=0)
>>> for i,hwhm_L in enumerate(HWHM_L):
>>>     ax = plt.subplot(nplots, 1, 1+i)
>>>     voigt.hwhm_L = lorentz.hwhm = hwhm_L
>>>     width = 0.5346*hwhm_L + np.sqrt(0.2166*hwhm_L**2+hwhm_G**2)
>>>     x = np.arange(-nwidths*width, nwidths*width, width/1000.0)
>>>     plt.plot(x/width, lorentz(x), lw=2.0, color="blue", label="Lorentz")
>>>     plt.plot(
>>>         x/width, doppler(x), lw=2.0, color="limegreen", label="Doppler")
>>>     plt.plot(
>>>         x/width, voigt(x), lw=2.0, color="orange", label="Voigt",
>>>         dashes=(4,1))
>>>     ymin = np.amin([lorentz(x), voigt(x)])
>>>     ymax = np.amax([lorentz(x), voigt(x), doppler(x)])
>>>     plt.ylim(ymin, 3*ymax)
>>>     ax.set_yscale("log")
>>>     plt.text(
>>>         0.025, 0.75, rf"$\rm HWHM_L/HWHM_G={hwhm_L/hwhm_G:4g}$",
>>>         transform=ax.transAxes)
>>>     plt.xlim(-nwidths, nwidths)
>>>     plt.xlabel(r"$\rm x/HWHM_V$", fontsize=12)
>>>     plt.ylabel("Profile")
>>>     if i != nplots-1:
>>>         ax.set_xticklabels([])
>>>     if i == 0:
>>>         plt.legend(loc="upper right", fontsize=11)


Initialize self.  See help(type(self)) for accurate signature.
eval(x)[source]
Evaluate the Voigt profile at the specified coordinates range.

Parameters
----------
x: 1D float ndarray
    Input coordinates where to evaluate the profile.

Returns
-------
v: 1D float ndarray
    The line profile at the x locations.
pyratbay.opacity.broadening.doppler_hwhm(temperature, mass, wn)[source]
Get Doppler half-width at half maximum broadening.

Parameters
----------
temperature: Float scalar or ndarray
    Atmospheric temperature (Kelvin degree).
mass: Float scalar or ndarray
    Mass of the species (AMU).
wn: Float scalar or ndarray
    Wavenumber (cm-1).

Returns
-------
dop_hwhm: Float scalar or ndarray
    The Doppler half-width at half maximum broadening (cm-1).

Note
----
All inputs must have compatible data shapes to be broadcastable.

Examples
--------
>>> import pyratbay.opacity.broadening as b
>>> # Doppler HWHM at 1000K and 1 micron, for H2O and CO2:
>>> temperature = 1000.0
>>> wn = 10000.0
>>> mass = np.array([18.0, 44.0])
>>> dop_hw = b.doppler_hwhm(temperature, mass, wn)
>>> print(f'Doppler broadening:\n H2O        CO2\n{dop_hw}')
Doppler broadening:
 H2O        CO2
[0.02669241 0.01707253]
pyratbay.opacity.broadening.lorentz_hwhm(temperature, pressure, masses, radii, vol_mix_ratio, imol)[source]
Get Lorentz half-width at half maximum broadening.

Parameters
----------
temperature: Float scalar or ndarray
    Atmospheric temperature (Kelvin degree).
pressure: Float scalar or ndarray
    Atmospheric pressure (barye).
masses: 1D float ndarray
    Masses of atmospheric species (AMU).
radii: 1D float ndarray
    Collision radius of atmospheric species (cm).
vol_mix_ratio: 1D float ndarray
    Volume mixing ratio of atmospheric species.
imol: Integer
    Index of species to calculate the HWHM (in masses/radii arrays).

Returns
-------
lor_hwhm: Float scalar or ndarray
    The Lorentz half-width at half maximum broadening (cm-1).

Note
----
The temperature, pressure, and imol inputs must have compatible
shapes to be broadcastable.

Examples
--------
>>> import pyratbay.opacity.broadening as b
>>> import pyratbay.constants as pc
>>> # Lorenz HWHM at 1000K and 1 bar, for H2O and CO2:
>>> temperature = 1000.0
>>> pressure = 1.0 * pc.bar
>>> #                  H2O   CO2   H2    He
>>> masses = np.array([18.0, 44.0, 2.0,  4.0])
>>> radii  = np.array([1.6,  1.9,  1.45, 1.4]) * pc.A
>>> vmr    = np.array([1e-4, 1e-4, 0.85, 0.15])
>>> imol = np.array([0, 1])
>>> lor_hw = b.lorentz_hwhm(temperature, pressure, masses, radii, vmr, imol)
>>> print(f'Lorentz broadening:\n H2O        CO2\n{lor_hw}')
Lorentz broadening:
 H2O        CO2
[0.03691111 0.04308068]
pyratbay.opacity.broadening.min_widths(min_temp, max_temp, min_wn, max_mass, min_rad, min_press)[source]
  Estimate the minimum Doppler and Lorentz half-widths at half maximum
  (cm-1) for an H2-dominated atmosphere.

  Parameters
  ----------
  min_temp: Float
      Minimum atmospheric tmperature (Kelvin degrees).
  max_temp: Float
      Maximum atmospheric tmperature (Kelvin degrees).
  min_wn: Float
      Minimum spectral wavenumber (cm-1).
  max_mass: Float
      Maximum mass of molecule/isotope (amu).
  min_rad: Float
      Minimum collisional radius (cm).
  min_press: Float
      Minimum atmospheric pressure (barye).

  Returns
  -------
  dmin: Float
      Minimum Doppler HWHM (cm-1).
  lmin: Float
      Minimum Lorentz HWHM (cm-1).

  Examples
  --------
  >>> import pyratbay.opacity.broadening as b
  >>> import pyratbay.constants as pc
  >>> min_temp =  100.0
  >>> max_temp = 3000.0
  >>> min_wn   = 1.0/(10.0*pc.um)
  >>> max_mass = 18.015    # H2O molecule
  >>> min_rad  = 1.6*pc.A  # H2O molecule
  >>> min_press = 1e-5 * pc.bar
  >>> dmin, lmin = b.min_widths(min_temp, max_temp, min_wn, max_mass,
  >>>     min_rad, min_press)
  >>> print('Minimum Doppler half width: {:.2e} cm-1
'
  >>>       'Minimum Lorentz half width: {:.2e} cm-1'.format(dmin,lmin))
pyratbay.opacity.broadening.max_widths(min_temp, max_temp, max_wn, min_mass, max_rad, max_press)[source]
  Estimate the maximum Doppler and Lorentz half-widths at half maximum
  (cm-1) for an H2-dominated atmosphere.

  Parameters
  ----------
  min_temp: Float
      Minimum atmospheric tmperature (Kelvin degrees).
  max_temp: Float
      Maximum atmospheric tmperature (Kelvin degrees).
  max_wn: Float
      Maximum spectral wavenumber (cm-1).
  min_mass: Float
      Minimum mass of molecule/isotope (amu).
  max_rad: Float
      Maximum collisional radius (cm).
  max_press: Float
      Maximum atmospheric pressure (barye).

  Returns
  -------
  dmax: Float
      Maximum Doppler HWHM (cm-1).
  lmax: Float
      Maximum Lorentz HWHM (cm-1).

  Examples
  --------
  >>> import pyratbay.opacity.broadening as b
  >>> import pyratbay.constants as pc
  >>> min_temp =  100.0
  >>> max_temp = 3000.0
  >>> max_wn   = 1.0/(1.0*pc.um)
  >>> min_mass = 18.015    # H2O molecule
  >>> max_rad  = 1.6*pc.A  # H2O molecule
  >>> max_press = 100.0*pc.bar
  >>> dmax, lmax = b.max_widths(min_temp, max_temp, max_wn, min_mass,
  >>>     max_rad, max_press)
  >>> print('Maximum Doppler half width: {:.2e} cm-1
'
  >>>       'Maximum Lorentz half width: {:.2e} cm-1'.format(dmax,lmax))

pyratbay.plots

pyratbay.plots.alphatize(colors, alpha, bg='w')[source]
Get rgb representation of a color as if it had the specified alpha.

Parameters
----------
colors: color or iterable of colors
    The color to alphatize.
alpha: Float
    Alpha value to apply.
bg: color
    Background color.

Returns
-------
rgb: RGB or list of RGB color arrays
    The RGB representation of the alphatized color (or list of colors).

Examples
--------
>>> import pyrabay.plots as pp
>>> pp.alphatize('r', 0.5)
array([1. , 0.5, 0.5])
>>> pp.alphatize(['r', 'b'], 0.8)
[array([1. , 0.2, 0.2]), array([0.2, 0.2, 1. ])]
pyratbay.plots.spectrum(spectrum, wavelength, rt_path, data=None, uncert=None, bandwl=None, bandflux=None, bandtrans=None, bandidx=None, starflux=None, rprs=None, label='model', bounds=None, logxticks=None, gaussbin=2.0, yran=None, filename=None, fignum=501, axis=None)[source]
Plot a transmission or emission model spectrum with (optional) data
points with error bars and band-integrated model.

Parameters
----------
spectrum: 1D float ndarray
    Planetary spectrum evaluated at wavelength.
wavelength: 1D float ndarray
    The wavelength of the model in microns.
rt_path: String
    Radiative-transfer observing geometry (transit, eclipse, or emission).
data: 1D float ndarray
    Observing data points at each bandwl.
uncert: 1D float ndarray
    Uncertainties of the data points.
bandwl: 1D float ndarray
    The mean wavelength for each band/data point.
bandflux: 1D float ndarray
    Band-integrated model spectrum at each bandwl.
bandtrans: List of 1D float ndarrays
    Transmission curve for each band.
bandidx: List of 1D float ndarrays.
    The indices in wavelength for each bandtrans.
starflux: 1D float ndarray
    Stellar spectrum evaluated at wavelength.
rprs: Float
    Planet-to-star radius ratio.
label: String
    Label for spectrum curve.
bounds: Tuple
    Tuple with -2, -1, +1, and, +2 sigma boundaries of spectrum.
    If not None, plot shaded area between +/-1sigma and +/-2sigma
    boundaries.
logxticks: 1D float ndarray
    If not None, switch the X-axis scale from linear to log, and set
    the X-axis ticks at the locations given by logxticks.
gaussbin: Integer
    Standard deviation for Gaussian-kernel smoothing (in number of samples).
yran: 1D float ndarray
    Figure's Y-axis boundaries.
filename: String
    If not None, save figure to filename.
fignum: Integer
    Figure number.
axis: AxesSubplot instance
    The matplotlib Axes of the figure.

Returns
-------
ax: AxesSubplot instance
    The matplotlib Axes of the figure.
pyratbay.plots.contribution(contrib_func, wl, rt_path, pressure, radius, rtop=0, filename=None, filters=None, fignum=-21)[source]
Plot the band-integrated normalized contribution functions
(emission) or transmittance (transmission).

Parameters
----------
contrib_func: 2D float ndarray
    Band-integrated contribution functions [nfilters, nlayers].
wl: 1D float ndarray
    Mean wavelength of the bands in microns.
rt_path: String
    Radiative-transfer observing geometry (emission or transit).
pressure: 1D float ndarray
    Layer's pressure array (barye units).
radius: 1D float ndarray
    Layer's impact parameter array (cm units).
rtop: Integer
    Index of topmost valid layer.
filename: String
    Filename of the output figure.
filters: 1D string ndarray
    Name of the filter bands (optional).
fignum: Integer
    Figure number.

Returns
-------
ax: AxesSubplot instance
    The matplotlib Axes of the figure.

Notes
-----
- The dashed lines denote the 0.16 and 0.84 percentiles of the
  cumulative contribution function or the transmittance (i.e.,
  the boundaries of the central 68% of the respective curves).
- If there are more than 80 filters, this code will thin the
  displayed filter names.
pyratbay.plots.temperature(pressure, profiles=None, labels=None, colors=None, bounds=None, punits='bar', ax=None, filename=None, theme='blue', alpha=[0.8, 0.6], fs=13, lw=2.0, fignum=504)[source]
Plot temperature profiles.

Parameters
----------
pressure: 1D float ndarray
    The atmospheric pressure profile in barye.
profiles: iterable of 1D float ndarrays
    Temperature profiles to plot.
labels: 1D string iterable
    Labels for temperature profiles.
colors: 1D string iterable.
    Colors for temperature profiles.
bounds: Tuple
    Tuple with -1sigma, +1sigma, -2sigma, and +2sigma temperature
    boundaries.
    If not None, plot shaded area between +/-1sigma and +/-2sigma
    boundaries.
punits: String
    Pressure units for output plot (input units are always barye).
ax: AxesSubplot instance
    If not None, plot into the given axis.
filename: String
    If not None, save plot to given file name.
theme: String
    The histograms' color theme for bounds regions.
    Only 'blue' and 'orange' themes are valid at the moment.
    Alternatively, provide a two-element iterable to provide the colors.
alpha: 2-element float iterable
    Alpha transparency for bounds regions.
fs: Float
    Labels font sizes.
lw: Float
    Lines width.
fignum: Integer
    Figure's number (ignored if axis is not None).

Returns
-------
ax: AxesSubplot instance
    The matplotlib Axes of the figure.
pyratbay.plots.abundance(vol_mix_ratios, pressure, species, highlight=None, xlim=None, punits='bar', colors=None, dashes=None, filename=None, lw=2.0, fignum=505, fs=13, legend_fs=None, ax=None)[source]
Plot atmospheric volume-mixing-ratio abundances.

Parameters
----------
vol_mix_ratios: 2D float ndarray
    Atmospheric volume mixing ratios to plot [nlayers,nspecies].
pressure: 1D float ndarray
    Atmospheric pressure [nlayers], units are given by punits argument.
species: 1D string iterable
    Atmospheric species names [nspecies].
highlight: 1D string iterable
    List of species names to highlight.  Non-highlighed species are
    plotted with alpha=0.4, below the highligted species, and are
    not considered to set the default xlim (e.g., might not be shown
    if their abundances are too low).
    If None, all input species are highlighted.
xlim: 2-element float iterable
    Volume mixing ratio plotting boundaries.
punits: String
    Pressure units.
colors: 1D string iterable
    List of colors to use.
    - If len(colors) >= len(species), colors are assigned to each
      species irrespective of highlight.
    - If len(colors) < len(species), the display will cycle the
      color list using solid, long-dashed, short-dashed, and dotted
      line styles (all highlight species being displayed before the rest).
    - If colors == 'default', use pyratbay.plots.default_colors
      dict to assign colors.
    - If colors is None, use matplotlib's default color cycler.
dashes: 1D dash-sequence iterable
    List of line-styles for each species, irrespective of highlight.
    len(dashes) has to be equal to len(species).
    Alternatively, dashes can by a dash-sequence Cycler.
filename: String
    If not None, save plot to given file name.
lw: Float
    Lines width.
fignum: Integer
    Figure's number (ignored if axis is not None).
fs: Float
    Labels font sizes.
legend_fs: Float
    Legend font size.  If legend_fs is None, default to fs-2.
    If legend_fs <= 0, do not plot a legend.
ax: AxesSubplot instance
    If not None, plot into the given axis.

Returns
-------
ax: AxesSubplot instance
    The matplotlib Axes of the figure.

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> import pyratbay.plots as pp

>>> nlayers = 51
>>> pressure = pa.pressure('1e-6 bar', '1e2 bar', nlayers)
>>> temperature = pa.temperature('isothermal', pressure,  params=1000.0)
>>> species = 'H2O CH4 CO CO2 NH3 C2H2 C2H4 HCN N2 TiO VO H2 H He Na K'.split()
>>> vmr = pa.chemistry('tea', pressure, temperature, species).vmr
>>> ax = pp.abundance(
>>>     vmr, pressure, species, colors='default',
>>>     highlight='H2O CH4 CO CO2 NH3 HCN H2 H He'.split())
pyratbay.plots.default_colors
{'H2O': 'navy', 'CO2': 'red', 'CO': 'limegreen', 'CH4': 'orange', 'H2': 'deepskyblue', 'He': 'seagreen', 'HCN': '0.7', 'NH3': 'magenta', 'C2H2': 'brown', 'C2H4': 'pink', 'N2': 'gold', 'H': 'olive', 'TiO': 'black', 'VO': 'peru', 'Na': 'darkviolet', 'K': 'cornflowerblue'}

pyratbay.spectrum

pyratbay.spectrum.blackbody_wn(...)
Calculate the Planck emission function in wavenumber space:
   Bnu(T) = 2 h c**2 nu**3 / (exp(hc*nu/kT)-1),
with units of erg s-1 sr-1 cm-2 cm.

Parameters
----------
wn: 1D float ndarray
    Wavenumber spectrum (cm-1).
temp: Float
    Temperature (Kelvin).
B: 1D float ndarray [optional]
    Array to store the Planck emission.

Returns
-------
(If B was not provided as input:)
B: 1D float ndarray
    Planck emission function at wn (erg s-1 sr-1 cm-2 cm).
pyratbay.spectrum.blackbody_wn_2D(...)
Compute the Planck emission function in wavenumber space:
   Bnu(T) = 2 h c**2 nu**3 / (exp(hc*nu/kT)-1),
with units of erg s-1 sr-1 cm-2 cm.

Parameters
----------
wn: 1D float ndarray
    Wavenumber spectrum (cm-1).
temp: 1D float ndarray
    Temperature at each layer (K).
B: 2D float ndarray [optional]
    Array to store the Planck emission of shape [nlayers, nwave].
last: 1D integer ndarray [optional]
    Indices of last layer to evaluate at each wavenumber.

Returns
-------
(If B was not provided as input:)
B: 2D float ndarray
    Planck emission function at wn (erg s-1 sr-1 cm-2 cm).
pyratbay.spectrum.bbflux(wn, teff)[source]
Compute the emission flux of a blackbody at temperature Teff
in wavenumber space.

Parameters
----------
wn: 1D float iterable
   Wavenumber array where to evaluate the flux (cm-1).
teff: Float
   The effective temperature (Kelvin).

Return
------
flux: 1D float ndarray
   blackbody flux (erg s-1 cm-2 cm) at wn.

Examples
--------
>>> import pyratbay.spectrum as ps
>>> import pyratbay.constants as pc
>>> import numpy as np
>>> tsun = 5772.0
>>> wn = np.logspace(-1, 5, 30000)
>>> flux = ps.bbflux(wn, tsun)
>>> # Solar constant:
>>> s = np.trapz(flux, wn) * (pc.rsun/pc.au)**2
>>> print("Solar constant (Teff={:.0f}K): S = {:.1f} W m-2\n"
>>>       "Wien's displacement law: wn(flux_max) = {:.1f} cm-1\n"
>>>       "             5.879E10 Hz/K * Teff / c = {:.1f} cm-1".
>>>       format(tsun, s*1e-3, wn[np.argmax(flux)], 5.879e10*tsun/pc.c))
Solar constant (Teff=5772K): S = 1361.2 W m-2
Wien's displacement law: wn(flux_max) = 11318.0 cm-1
             5.879E10 Hz/K * Teff / c = 11319.0 cm-1
pyratbay.spectrum.read_kurucz(filename, temp=None, logg=None)[source]
Extract stellar flux models from a Kurucz file.
Kurucz model files can be found at http://kurucz.harvard.edu/grids.html

Parameters
----------
filename: String
    Name of a Kurucz model file.
temp: Float
    Requested surface temperature for the Kurucz model.
    If temp and logg are not None, return the model with the closest
    surface temperature and gravity.
logg: Float
    Requested log10 of the surface gravity for the Kurucz model
    (where g is in cgs units).

Returns
-------
flux: 1D or 2D float ndarray
    If temp and logg are not None, a 1D array with the kurucz surface
    flux per unit wavenumber (erg s-1 cm-2 cm) of the closest model to
    the input temperature and gravity.
    Else, a 2D array with all kurucz models in file, of shape
    [nmodels, nwave].
wavenumber: 1D ndarray
    Wavenumber sampling of the flux models (in cm-1 units).
ktemp: Scalar or 1D float ndarray
    Surface temperature of the output models (in Kelvin degrees).
klogg: Scalar or 1D float ndarray
    log10 of the stellar surface gravity of the output models (in cm s-2).
continuum: 2D ndarray
    The models' fluxes with no line absorption.  Same units and
    shape of flux. Returned only if temp and logg are None.

Examples
--------
>>> import pyratbay.spectrum as ps
>>> import pyratbay.constants as pc
>>> import numpy as np
>>> # Download a Kurucz stellar model file from:
>>> # http://kurucz.harvard.edu/grids/gridp00odfnew/fp00k0odfnew.pck
>>> # Read a single model from the kurucz file:
>>> kfile = 'fp00k0odfnew.pck'
>>> tsun = 5770.0  # Sun's surface temperature
>>> gsun = 4.44    # Sun's surface gravity (log)
>>> flux, wn, ktemp, klogg = ps.read_kurucz(kfile, tsun, gsun)
>>> # Compute brightness at 1 AU from a 1 Rsun radius star:
>>> s = np.trapz(flux, wn) * (pc.rsun/pc.au)**2
>>> print("Solar constant [T={:.0f} K, logg={:.1f}]:  S = {:.1f} W m-2".
>>>       format(ktemp, klogg, s * 1e-3))
Solar constant [T=5750 K, logg=4.5]:  S = 1340.0 W m-2
>>> # Pretty close to the solar constant: ~1361 W m-2

>>> # Read the whole set of models in file:
>>> # (in this case, ktemp and klogg are 1D arrays)
>>> fluxes, wn, ktemp, klogg, continua = ps.read_kurucz(kfile)
class pyratbay.spectrum.PassBand(filter_file, wn=None)[source]
A Filter passband object.


Parameters
----------
filter_file: String
    Path to filter file containing wavelength (um) and passband
    response in two columns.
    Comment and blank lines are ignored.

Examples
--------
>>> import pyratbay.spectrum as ps
>>> import pyratbay.constants as pc
>>> import matplotlib.pyplot as plt
>>> import numpy as np

>>> filter_file = f'{pc.ROOT}pyratbay/data/filters/spitzer_irac2_sa.dat'
>>> band = ps.PassBand(filter_file)

>>> # Evaluate over a wavelength array (um):
>>> wl = np.arange(3.5, 5.5, 0.001)
>>> out_wl, out_response = band(wl)

>>> plt.figure(1)
>>> plt.clf()
>>> plt.plot(out_wl, out_response)
>>> plt.plot(band.wl, band.response)  # Same variables
>>> # Note wl differs from band.wl, but original array can be used as:
>>> plt.plot(wl[band.idx], band.response)

>>> # Evaluate over a wavenumber array:
>>> wn = 1e4 / wl
>>> band(wn=wn)
>>> plt.figure(1)
>>> plt.clf()
>>> plt.plot(band.wn, band.response, dashes=(5,3))
>>> plt.plot(wn[band.idx], out_response)
save_filter(save_file)[source]
Write filter response function data to file, into two columns
the wavelength (um) and the response function.

Parameters
----------
save_file: String
    File where to save the filter data.
class pyratbay.spectrum.Tophat(wl0, half_width, name='tophat')[source]
A Filter passband object with a tophat-shaped passband.


Parameters
----------
wl0: Float
    The passband's central wavelength (um units).
half_width: Float
    The passband's half-width (um units).
name: Str
    A user-defined name for the filter when calling str(self),
    e.g., to identify the instrument provenance of this filter.

Examples
--------
>>> import pyratbay.spectrum as ps
>>> import matplotlib.pyplot as plt
>>> import numpy as np

>>> hat = ps.Tophat(4.5, 0.5)

>>> # Evaluate over a wavelength array (um units):
>>> wl = np.arange(3.5, 5.5, 0.001)
>>> out_wl, out_response = hat(wl)

>>> plt.figure(1)
>>> plt.clf()
>>> plt.plot(out_wl, out_response)
>>> plt.plot(hat.wl, hat.response)  # Same variables
>>> # Note wl differs from hat.wl, but original array can be used as:
>>> plt.plot(wl[hat.idx], hat.response)

>>> # Evaluate over a wavenumber array:
>>> wn = 1e4 / wl
>>> hat(wn=wn)
>>> plt.figure(1)
>>> plt.clf()
>>> plt.plot(hat.wn, hat.response, dashes=(5,3))
>>> plt.plot(wn[hat.idx], out_response)
save_filter(save_file)
Write filter response function data to file, into two columns
the wavelength (um) and the response function.

Parameters
----------
save_file: String
    File where to save the filter data.
pyratbay.spectrum.tophat(wl0, width, margin=None, dlambda=None, resolution=None, ffile=None)[source]
Generate a top-hat filter function, with transmission = 1.0 from
wl0-width/2 to wl0+width/2, and an extra margin with transmission
= 0.0 at each end.

Parameters
----------
ffile: String
    Name of the output file.
wl0:  Float
    Filter central wavelength in microns.
width: Float
    Filter width in microns.
margin: Float
    Margin (in microns) with zero-valued transmission, to append
    at each end of the filter.
dlambda: Float
    Spectral sampling rate in microns.
resolution: Float
    Spectral sampling resolution (used if dlambda is None).
ffile: String
    If not None, save filter to file.

Examples
--------
>>> import pyratbay.spectrum as ps
>>> wl0     = 1.50
>>> width   = 0.50
>>> margin  = 0.10
>>> dlambda = 0.05
>>> wl, trans = ps.tophat(wl0, width, margin, dlambda)
>>> print(wl, trans, sep='\n')
[1.15 1.2  1.25 1.3  1.35 1.4  1.45 1.5  1.55 1.6  1.65 1.7  1.75 1.8
 1.85]
[0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0.]
pyratbay.spectrum.resample(signal, wn, specwn, normalize=False)[source]
Resample signal from wn to specwn wavenumber sampling using a linear
interpolation.

Parameters
----------
signal: 1D ndarray
    A spectral signal sampled at wn.
wn: 1D ndarray
    Signal's wavenumber sampling, in cm-1 units.
specwn: 1D ndarray
    Wavenumber sampling to resample into, in cm-1 units.
normalize: Bool
    If True, normalized the output resampled signal to integrate to
    1.0 (note that a normalized curve when specwn is a decreasing
    function results in negative values for resampled).

Returns
-------
resampled: 1D ndarray
    The interpolated signal.
wnidx: 1D ndarray
    The indices of specwn covered by the input signal.

Examples
--------
>>> import pyratbay.spectrum as ps
>>> import numpy as np
>>> wn     = np.linspace(1.3, 1.7, 11)
>>> signal = np.array(np.abs(wn-1.5)<0.1, np.double)
>>> specwn = np.linspace(1, 2, 51)
>>> resampled, wnidx = ps.resample(signal, wn, specwn)
>>> print(wnidx, specwn[wnidx], resampled, sep='\n')
[16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34]
[1.32 1.34 1.36 1.38 1.4  1.42 1.44 1.46 1.48 1.5  1.52 1.54 1.56 1.58
 1.6  1.62 1.64 1.66 1.68]
[0.  0.  0.  0.  0.5 1.  1.  1.  1.  1.  1.  1.  1.  1.  0.5 0.  0.  0.
 0. ]
pyratbay.spectrum.band_integrate(spectrum, specwn, bandtrans, bandwn)[source]
Integrate a spectrum over the band transmission.

Parameters
----------
spectrum: 1D float iterable
    Spectral signal to be integrated.
specwn: 1D float iterable
    Wavenumber of spectrum in cm-1.
bandtrans: 1D float iterable
    List of normalized interpolated band transmission values in each filter.
bandwn: 1D float iterable

Returns
-------
bflux: 1D float list
    Band-integrated values.

Examples
--------
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> import pyratbay.io as io
>>> import pyratbay.spectrum as ps
>>> import pyratbay.constants as pc
>>> # Load Spitzer IRAC filters:
>>> wn1, irac1 = io.read_spectrum(
>>>     pc.ROOT+'pyratbay/data/filters/spitzer_irac1_sa.dat')
>>> wn2, irac2 = io.read_spectrum(
>>>     pc.ROOT+'pyratbay/data/filters/spitzer_irac2_sa.dat')
>>> # Spectrum to integrate:
>>> wn = np.arange(1500, 5000.1, 1.0)
>>> sflux = ps.bbflux(wn, 1800.0)
>>> # Integrate over single filter:
>>> bandflux = ps.band_integrate(sflux, wn, irac1, wn1)
>>> # Integrate over multiple:
>>> bandfluxes = ps.band_integrate(sflux, wn, [irac1,irac2], [wn1, wn2])
>>> # Plot the results:
>>> meanwn = [np.mean(wn1), np.mean(wn2)]
>>> width = 0.5*(np.amax(wn1)-np.amin(wn1)), 0.5*(np.amax(wn2)-np.amin(wn2))
>>> plt.figure(1)
>>> plt.clf()
>>> plt.semilogy(wn, sflux, 'k')
>>> plt.plot(wn1, (irac1+1)*4e4, 'red')
>>> plt.plot(wn2, (irac2+1)*4e4, 'blue')
>>> plt.errorbar(meanwn[0], bandflux, xerr=width[0], fmt='o', color='red')
>>> plt.errorbar(meanwn, bandfluxes, xerr=width, fmt='o', color='none',
>>>              mec='k', ecolor='k')
>>> plt.xlim(np.amin(wn), np.amax(wn))
>>> plt.ylim(4e4, 1.2e5)
>>> plt.xlabel('Wavenumber  (cm$^{-1}$)')
>>> plt.ylabel(r'Flux  (erg s$^{-1}$ cm$^{-2}$ cm)')
pyratbay.spectrum.contribution_function(optdepth, pressure, B)[source]
Evaluate the contribution function equation as in Knutson et al. (2009)
ApJ, 690, 822; Equation (2).

Parameters
----------
optdepth: 2D float ndarray
    Optical depth at each layer and wavenumber [nlayers, nwave].
pressure: 1D float ndarray
    Atmospheric pressure array [nlayers].
B: 2D float ndarray
    Plank emission at each layer and wavenumber [nlayers, nwave].

Returns
-------
cf: 2D float ndarray
    The contribution function at each layer and wavenumber
    of shape [nlayers, nwave].
pyratbay.spectrum.transmittance(optdepth, ideep)[source]
Compute the transmittance spectrum for the impact-parameter
raypaths of a transmission model.

Parameters
----------
optdepth: 2D float ndarray
    Optical depth at each layer and wavenumber [nlayers, nwave].
ideep: 1D integer ndarray
    Impact-parameter indices of deepest-calculated optical depth
    at each wavenumber.
pyratbay.spectrum.band_cf(cf, bandtrans, wn, bandidx)[source]
Compute band-averaged contribution functions or transmittances.

Parameters
----------
cf: 2D float ndarray
    The contribution function or transmittance of
    shape [nlayers, nwave].
bandtrans: List of 1D ndarrays
    List of band transmission curves.
wn: 1D float ndarray
    The wavenumber sampling (in cm-1).
bandidx: List of 1D ndarrays
    List of wavenumber-index arrays for each band transmission curve.

Returns
-------
bandcf: 2D float ndarray
    The band-integrated contribution functions of
    shape [nlayers, nbands].
pyratbay.spectrum.convective_flux(pressure, temperature, cp, gravity, mu, rho, alpha=1.0, beta=1.0)[source]
Estimate the convective flux for an atmosphere following mixing-
length theory as described in 'Modern Astrophysics (Carrol & Ostlie).

Parameters
----------
pressure: 1D float array
    Atmospheric pressure profile (barye).
temperature: 1D float array
    Atmospheric temperature profile (kelvin degree).
cp: 1D float array
    Atmospheric specific heat capacity at constant pressure
    (erg K-1 mol-1).
gravity: 1D float array
    Atmospheric gravity profile (cm s-2).
mu: 1D float array
    Atmospheric mean molecular mass profile (g mol-1).
rho: 1D float array
    Atmospheric mass-density profile (g cm-3).
alpha: Float
    Mixing-length scaling parameter: alpha = l/H, with l the
    mixing length and H the pressure scale height.
beta: Float
    Free parameter from the average kinetic energy velocity
    estimation. Should take a value between 0 and 1.

Returns
-------
F_conv: 1D float array
    Estimated convective flux (erg s-1 cm-2).
    This is not zero only where the actual temperature gradient
    is larger than the adiabatic gradient.
pyratbay.spectrum.radiative_equilibrium(pressure, temperature, nsamples, chem_model, two_stream_rt, wavenumber, spec, atm, radeq_temps=None, convection=False, tmin=0.0, tmax=6000.0, f_scale=None, mplanet=None, mol_mass=None)[source]
Compute radiative-thermochemical equilibrium atmosphere.
Currently there is no convergence criteria implemented,
some 100--300 iterations are typically sufficient to converge
to a stable temperature-profile solution.

Parameters
----------
nsamples: Integer
    Number of radiative-equilibrium iterations to run.
continue_run: Bool
    If True, continue from a previous radiative-equil. run.
no_convection: Bool
    If True, skip convective flux calculation in the radiative
    equilibrium calculation.

Returns
-------
There are no returned values, but this method updates the
temperature profile (self.atm.temp) and abundances (self.atm.q)
with the values from the last radiative-equilibrium iteration.

This method also defines pyrat.atm.radeq_temps, a 2D array
containing all temperature-profile iterations.

pyratbay.atmosphere

pyratbay.atmosphere.pressure(ptop, pbottom, nlayers, units='bar', log=None, verb=0)[source]
Compute a log-scale pressure profile.

Parameters
----------
ptop: String or Float
    Pressure at the top of the atmosphere. If string, may contain units.
pbottom: String or Float
   Pressure at the bottom of the atmosphere. If string, may contain units.
nlayers: Integer
   Number of pressure layers.
units: String
   Pressure input units (if not defined in ptop, pbottom).
   Available units are: barye, mbar, pascal, bar (default), and atm.
log: Log object
   Screen-output log handler.
verb: Integer
   Verbosity level (when log is None). Print out when verb > 0.

Returns
-------
press: 1D float ndarray
   The pressure profile (in barye units).

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> import pyratbay.constants as pc

>>> nlayers = 9
>>> # These are all equivalent:
>>> p1 = pa.pressure(ptop=1e-6, pbottom=1e2, nlayers=nlayers)
>>> p2 = pa.pressure(1e-6, 1e2, nlayers, 'bar')
>>> p3 = pa.pressure('1e-6 bar', '1e2 bar', nlayers)
>>> p4 = pa.pressure(1e-6*pc.bar, 1e2*pc.bar, nlayers, 'barye')
>>> print(p1/pc.bar)
[1.e-06 1.e-05 1.e-04 1.e-03 1.e-02 1.e-01 1.e+00 1.e+01 1.e+02]
pyratbay.atmosphere.temperature(tmodel, pressure=None, nlayers=None, log=None, params=None)[source]
Temperature profile wrapper.

Parameters
----------
tmodel: String
    Name of the temperature model.
pressure: 1D float ndarray
    Atmospheric pressure profile in barye units.
nlayers: Integer
    Number of pressure layers.
log: Log object
    Screen-output log handler.
params: 1D float ndarray
    Temperature model parameters. If None, return a tuple with the
    temperature model, its arguments, and the number or required parameters.

Returns
-------
If params is not None:
    temperature: 1D float ndarray
        The evaluated atmospheric temperature profile.
If params is None:
    temp_model: Callable
        The atmospheric temperature model.

Examples
--------
>>> import pyratbay.atmosphere as pa

>>> nlayers = 11
>>> # Isothermal profile:
>>> temp_iso = pa.temperature("isothermal", params=1500.0, nlayers=nlayers)
>>> print(temp_iso)
[1500. 1500. 1500. 1500. 1500. 1500. 1500. 1500. 1500. 1500. 1500.]

>>> # Three-channel Eddington-approximation profile:
>>> pressure = pa.pressure(1e-8, 1e2, nlayers, "bar")
>>> params = np.array([-4.84, -0.8, -0.8, 0.5, 1200.0, 100.0])
>>> temp = pa.temperature('guillot', pressure, params=params)
>>> print(temp)
[1046.89057381 1046.89090056 1046.89433798 1046.93040895 1047.30779086
 1051.21739055 1088.76131307 1312.57904127 1640.18896334 1659.78818839
 1665.09706555]
pyratbay.atmosphere.chemistry(chem_model, pressure, temperature, species, metallicity=0.0, e_abundances={}, e_scale={}, e_ratio={}, q_uniform=None, solar_file=None, log=None, verb=1, atmfile=None, punits='bar')[source]
Compute atmospheric abundaces for given pressure and
temperature profiles with either uniform abundances or TEA.

Parameters
----------
chem_model: String
    Name of chemistry model.
pressure: 1D float ndarray
    Atmospheric pressure profile (barye).
temperature: 1D float ndarray
    Atmospheric temperature profile (Kelvin).
species: 1D string list
    Output atmospheric composition.
metallicity: Float
    Metallicity enhancement factor in dex units relative to solar.
e_abundances: Dictionary
    Custom elemental abundances.
    The dict contains the name of the element and their custom
    abundance in dex units relative to H=12.0.
    These values override metallicity.
e_scale: Dictionary
    Scaling abundance factor for specified atoms by the respective
    values (in dex units, in addition to metallicity scaling).
    E.g. (3x solar): e_scale = {'C': np.log10(3.0)}
e_ratio: Dictionary
    Custom elemental abundances scaled relative to another element.
    The dict contains the pair of elements joined by an underscore
    and their ratio in dex units, e.g., for a C/O ratio of 0.8 set
    e_ratio = {'C_O': 0.8}.
    These values modify the abundances after metallicity and
    e_scale have been applied.
solar_file: String
    Input solar elemental abundances file (default Asplund et al. 2021).
log: Log object
    Screen-output log handler.
verb: Integer
    Verbosity level.
atmfile: String
    If not None, output file where to save the atmospheric model.
punits: String
    Output pressure units.

Returns
-------
model: Callable
    The atmospheric chemistry-network model.

Example
-------
>>> import pyratbay.atmosphere as pa
>>> import matplotlib.pyplot as plt
>>> import pyratbay.plots as pp

>>> nlayers = 100
>>> T0 = 1500.0
>>> pressure = pa.pressure('1e-8 bar', '1e3 bar', nlayers)
>>> temperature = pa.temperature('isothermal', pressure, nlayers, params=T0)
>>> species = 'H2O CH4 CO CO2 NH3 C2H2 C2H4 HCN N2 H2 H He H+ e-'.split()
>>> # Equilibrium abundances model:
>>> chem_model = 'tea'
>>> chem_network = pa.chemistry(
>>>     chem_model, pressure, temperature, species,)

>>> q_uniform = np.array([
>>>     5e-4, 3e-5, 2e-4, 1e-8,  1e-6, 1e-14, 1e-13, 5e-10,
>>>     1e-4, 0.85, 5e-3, 0.14,  3e-23, 1e-23])
>>> chem_model = 'uniform'
>>> chem_network_unif = pa.chemistry(
>>>     chem_model, pressure, temperature, species, q_uniform=q_uniform)

>>> # Plot the results:
>>> ax1 = pp.abundance(
>>>     chem_network.vmr, pressure, chem_network.species,
>>>     colors='default', xlim=[1e-30, 3.0])

>>> ax2 = pp.abundance(
>>>     chem_network_unif.vmr, pressure, chem_network_unif.species,
>>>     colors='default', xlim=[1e-30, 3.0], fignum=506)
pyratbay.atmosphere.uniform(pressure, temperature, species, abundances, punits='bar', log=None, atmfile=None)[source]
Generate an atmospheric file with uniform abundances.
Save it into atmfile.

Parameters
----------
pressure: 1D float ndarray
    Monotonously decreasing pressure profile (in punits).
temperature: 1D float ndarray
    Temperature profile for pressure layers (in Kelvin).
species: 1D string ndarray
    List of atmospheric species.
abundances: 1D float ndarray
    The species mole mixing ratio.
punits:  String
   Pressure units.
log: Log object
    Screen-output log handler.
atmfile: String
    If not None, filename to save atmospheric model.

Returns
-------
qprofiles: 2D Float ndarray
    Abundance profiles of shape [nlayers,nspecies]

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> nlayers = 11
>>> punits = 'bar'
>>> pressure = pa.pressure(1e-8, 1e2, nlayers, punits)
>>> tmodel = pa.tmodels.Isothermal(nlayers)
>>> species    = ["H2", "He", "H2O", "CO", "CO2", "CH4"]
>>> abundances = [0.8496, 0.15, 1e-4, 1e-4, 1e-8, 1e-4]
>>> qprofiles = pa.uniform(pressure, tmodel(1500.0), species,
>>>     abundances=abundances, punits=punits)
>>> print(qprofiles)
[[8.496e-01 1.500e-01 1.000e-04 1.000e-04 1.000e-08 1.000e-04]
 [8.496e-01 1.500e-01 1.000e-04 1.000e-04 1.000e-08 1.000e-04]
 [8.496e-01 1.500e-01 1.000e-04 1.000e-04 1.000e-08 1.000e-04]
 [8.496e-01 1.500e-01 1.000e-04 1.000e-04 1.000e-08 1.000e-04]
 [8.496e-01 1.500e-01 1.000e-04 1.000e-04 1.000e-08 1.000e-04]
 [8.496e-01 1.500e-01 1.000e-04 1.000e-04 1.000e-08 1.000e-04]
 [8.496e-01 1.500e-01 1.000e-04 1.000e-04 1.000e-08 1.000e-04]
 [8.496e-01 1.500e-01 1.000e-04 1.000e-04 1.000e-08 1.000e-04]
 [8.496e-01 1.500e-01 1.000e-04 1.000e-04 1.000e-08 1.000e-04]
 [8.496e-01 1.500e-01 1.000e-04 1.000e-04 1.000e-08 1.000e-04]
 [8.496e-01 1.500e-01 1.000e-04 1.000e-04 1.000e-08 1.000e-04]]
pyratbay.atmosphere.abundance(pressure, temperature, species, elements=None, quniform=None, atmfile=None, punits='bar', metallicity=0.0, e_abundances={}, e_scale={}, e_ratio={}, solar_file=None, log=None, verb=1, ncpu=None, xsolar=None, escale=None)[source]
Compute atmospheric abundaces for given pressure and
temperature profiles with either uniform abundances or TEA.

Parameters
----------
pressure: 1D float ndarray
    Atmospheric pressure profile (barye).
temperature: 1D float ndarray
    Atmospheric temperature profile (Kelvin).
species: 1D string list
    Output atmospheric composition.
elements: 1D strings list
    Input elemental composition (default to minimum list of elements
    required to form species).
quniform: 1D float ndarray
    If not None, the output species abundances (isobaric).
atmfile: String
    If not None, output file where to save the atmospheric model.
punits: String
    Output pressure units.
metallicity: Float
    Metallicity enhancement factor in dex units relative to solar.
e_abundances: Dictionary
    Custom elemental abundances.
    The dict contains the name of the element and their custom
    abundance in dex units relative to H=12.0.
    These values override metallicity.
e_scale: Dict
    Scaling abundance factor for specified atoms by the respective
    values (in dex units, in addition to metallicity scaling).
    E.g. (3x solar): e_scale = {'C': np.log10(3.0)}
solar_file: String
    Input solar elemental abundances file (default Asplund et al. 2021).
log: Log object
    Screen-output log handler.
verb: Integer
    Verbosity level.

ncpu: Integer [DEPRECATED]
    Number of parallel CPUs to use in TEA calculation.
xsolar: Float [DEPRECATED]
    Metallicity enhancement factor.  Deprecated, use metallicity instead.
escale: Dict [DEPRECATED]
    Multiplication factor for specified atoms (dict's keys)
    by the respective values (on top of the xsolar scaling).
    Deprecated, use e_scale instead.

Returns
-------
vmr: 2D float ndarray
   Atmospheric volume mixing fraction abundances of shape
   [nlayers, nspecies].

Example
-------
>>> import pyratbay.atmosphere as pa
>>> import pyratbay.constants as pc

>>> nlayers = 100
>>> press = np.logspace(-8, 3, nlayers) * pc.bar
>>> temp  = np.tile(900.0, nlayers)
>>> species = 'H2O CH4 CO CO2 NH3 C2H2 C2H4 HCN N2 H2 H He'.split()
>>> # Thermochemical equilibrium abundances for requested species:
>>> vmr = pa.abundance(press, temp, species)
pyratbay.atmosphere.hydro_g(pressure, temperature, mu, g, p0=None, r0=None)[source]
Calculate radii using the hydrostatic-equilibrium equation considering
a constant gravity.

Parameters
----------
pressure: 1D float ndarray
    Atmospheric pressure for each layer (in barye).
temperature: 1D float ndarray
    Atmospheric temperature for each layer (in K).
mu: 1D float ndarray
    Mean molecular mass for each layer (in g mol-1).
g: Float
    Atmospheric gravity (in cm s-2).
p0: Float
    Reference pressure level (in barye) where radius(p0) = r0.
r0: Float
    Reference radius level (in cm) corresponding to p0.

Returns
-------
radius: 1D float ndarray
    Radius for each layer (in cm).

Notes
-----
If the reference values (p0 and r0) are not given, set radius = 0.0
at the bottom of the atmosphere.

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> import pyratbay.constants as pc
>>> nlayers = 11
>>> pressure = pa.pressure(1e-8, 1e2, nlayers, units='bar')
>>> temperature = pa.tmodels.Isothermal(nlayers)(1500.0)
>>> mu = np.tile(2.3, nlayers)
>>> g = pc.G * pc.mjup / pc.rjup**2
>>> r0 = 1.0 * pc.rjup
>>> p0 = 1.0 * pc.bar
>>> # Radius profile in Jupiter radii:
>>> radius = pa.hydro_g(pressure, temperature, mu, g, p0, r0) / pc.rjup
>>> print(radius)
[1.0563673  1.04932138 1.04227547 1.03522956 1.02818365 1.02113774
 1.01409182 1.00704591 1.         0.99295409 0.98590818]
pyratbay.atmosphere.hydro_m(pressure, temperature, mu, mass, p0, r0)[source]
Calculate radii using the hydrostatic-equilibrium equation considering
a variable gravity: g(r) = G*mass/r**2

Parameters
----------
pressure: 1D float ndarray
    Atmospheric pressure for each layer (in barye).
temperature: 1D float ndarray
    Atmospheric temperature for each layer (in K).
mu: 1D float ndarray
    Mean molecular mass for each layer (in g mol-1).
mass: Float
    Object's mass (in g).
p0: Float
    Reference pressure level (in barye) where radius(p0) = r0.
r0: Float
    Reference radius level (in cm) corresponding to p0.

Returns
-------
radius: 1D float ndarray
    Radius for each layer (in cm).

Notes
-----
It is possible that this hydrostatic solution diverges when an
atmosphere is too puffy.  In such cases, some returned radii
will have np.inf values (at the top layers).

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> import pyratbay.constants  as pc

>>> nlayers = 11
>>> pressure = pa.pressure(1e-8, 1e2, nlayers, units='bar')
>>> temperature = pa.tmodels.Isothermal(nlayers)(1500.0)
>>> mu = np.tile(2.3, nlayers)
>>> mplanet = 1.0 * pc.mjup
>>> r0 = 1.0 * pc.rjup
>>> p0 = 1.0 * pc.bar
>>> # Radius profile in Jupiter radii:
>>> radius = pa.hydro_m(pressure, temperature, mu, mplanet, p0, r0)/pc.rjup
>>> print(radius)
[1.05973436 1.05188019 1.04414158 1.036516   1.029001   1.02159419
 1.01429324 1.00709591 1.         0.99300339 0.986104  ]
pyratbay.atmosphere.rhill(smaxis, mplanet, mstar)[source]
Compute the Hill radius.  If any argument is None, return inf.

Parameters
----------
smaxis: Float
    Orbital semi-major axis (in cm).
mplanet: Float
    Planetary mass (in g).
mstar: Float
    Stellar mass (in g).

Returns
-------
rhill: Float
    Hill radius of planet.
pyratbay.atmosphere.stoich(species)[source]
    Extract the elemental composition from a list of species.

    Parameters
    ----------
    species: 1D string list
        List of species.

    Returns
    -------
    elements: 1D string list
        List of elements contained in species list.
    stoich: 2D integer ndarray
        Stoichiometric elemental values for each species (number of elements).

    Examples
    --------
    >>> import pyratbay.atmosphere as pa
    >>> species = ['H2', 'He', 'H2O', 'CO', 'CO2', 'CH4']
    >>> elements, stoichs = pa.stoich(species)
    >>> print(f'{elements}
{stoichs}')
    ['C', 'H', 'He', 'O']
    [[0 2 0 0]
     [0 0 1 0]
     [0 2 0 1]
     [1 0 0 1]
     [1 0 0 2]
     [1 4 0 0]]
pyratbay.atmosphere.mean_weight(abundances, species=None, molfile=None, mass=None)[source]
Calculate the mean molecular weight (a.k.a. mean molecular mass)
for the given abundances composition.

Parameters
----------
abundances: 2D float iterable
    Species volume mixing fraction, of shape [nlayers,nmol].
species: 1D string iterable
    Species names.
molfile: String
    A molecules file with the species info.  If None, use
    pyratbay's default molecules.dat file.
mass: 1D float ndarray
    The mass for each one of the species (g mol-1).
    If not None, this variable takes precedence over molfile.

Returns
-------
mu: 1D float ndarray
    Mean molecular weight at each layer for the input abundances.

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> species = 'H2 He H2O CO CO2 CH4'.split()
>>> abundances = [[0.8496, 0.15, 1e-4, 1e-4, 1e-8, 1e-4]]
>>> mu = pa.mean_weight(abundances, species)
>>> print(mu)
[2.31939114]
pyratbay.atmosphere.ideal_gas_density(abundances, pressure, temperature)[source]
Use the Ideal gas law to calculate number density in molecules cm-3.

Parameters
----------
abundances: 2D float ndarray
    Species volume mixing fraction, of shape [nlayers,nmol].
pressure: 1D ndarray
    Atmospheric pressure profile (in barye units).
temperature: 1D ndarray
    Atmospheric temperature profile (in kelvin).

Returns
-------
density: 2D float ndarray
    Atmospheric density in molecules cm-3.

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> atmfile = "uniform_test.atm"
>>> nlayers = 11
>>> pressure    = pa.pressure(1e-8, 1e2, nlayers, units='bar')
>>> temperature = np.tile(1500.0, nlayers)
>>> species     = ["H2", "He", "H2O", "CO", "CO2", "CH4"]
>>> abundances  = [0.8496, 0.15, 1e-4, 1e-4, 1e-8, 1e-4]
>>> qprofiles = pa.uniform(pressure, temperature, species, abundances)
>>> dens = pa.ideal_gas_density(qprofiles, pressure, temperature)
>>> print(dens[0])
[4.10241993e+10 7.24297303e+09 4.82864869e+06 4.82864869e+06
 4.82864869e+02 4.82864869e+06]
pyratbay.atmosphere.equilibrium_temp(tstar, rstar, smaxis, A=0.0, f=1.0, tstar_unc=0.0, rstar_unc=0.0, smaxis_unc=0.0)[source]
Calculate equilibrium temperature and uncertainty.

Parameters
----------
tstar: Scalar
    Effective temperature of host star (in kelvin degrees).
rstar: Scalar
    Radius of host star (in cm).
smaxis: Scalar
    Orbital semi-major axis (in cm).
A: Scalar
    Planetary bond albedo.
f: Scalar
    Planetary energy redistribution factor:
    f=0.5  no redistribution (total dayside reemission)
    f=1.0  good redistribution (4pi reemission)
tstar_unc: Scalar
    Effective temperature uncertainty (in kelvin degrees).
rstar_unc: Scalar
    Stellar radius uncertainty (in cm).
smaxis_unc: Scalar
    Semi-major axis uncertainty (in cm).

Returns
-------
teq: 1D ndarray
    Planet equilibrium temperature in kelvin degrees.
teq_unc: 1D ndarray
    Equilibrium temperature uncertainty.

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> import pyratbay.constants as pc
>>> import numpy as np
>>> # HD 209458b (Stassun et al. 2017):
>>> tstar  = 6091.0
>>> rstar  = 1.19 * pc.rsun
>>> smaxis = 0.04747 * pc.au
>>> tstar_unc  = 10.0
>>> rstar_unc  = 0.02 * pc.rsun
>>> smaxis_unc = 0.00046 * pc.au
>>> A = 0.3
>>> f = np.array([1.0, 0.5])
>>> teq, teq_unc = pa.equilibrium_temp(tstar, rstar, smaxis, A, f,
>>>     tstar_unc, rstar_unc, smaxis_unc)
>>> print(f'HD 209458b T_eq =\n    '
>>>    f'{teq[0]:.1f} +/- {teq_unc[0]:.1f} K (day--night redistributed)\n'
>>>    f'    {teq[1]:.1f} +/- {teq_unc[1]:.1f} K (instant re-emission)')
HD 209458b T_eq =
    1345.1 +/- 13.2 K (day--night redistribution)
    1599.6 +/- 15.7 K (instant re-emission)
pyratbay.atmosphere.transit_path(radius, nskip=0)[source]
Calculate the distances between layers for a set of rays grazing
an atmosphere defined by concentric spheres at radii radius.
Assume that the grazing rays have an impact parameter = radius.
See for example, Fig 1 of Molliere et al. (2019), AA, 627, 67.

Parameters
----------
radius: 1D float ndarray
    Atmospheric radius profile array (from top to bottom).
nskip: Integer
    Number of layers to skip from the top of the atmosphere.

Returns
-------
path: List of 1D float ndarrays
    List where each element is a 1D array of the paths at an
    impact parameter defined.

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> nlayers = 5
>>> radius = np.linspace(5.0, 1.0, nlayers)
>>> path = pa.transit_path(radius)
>>> # First path grazes the outer layer (thus, empty path)
>>> # Second path is sqrt(5.0**2 - 4.0**2), and so on
>>> for p in path:
>>>     print(p)
[]
[3.]
[1.35424869 2.64575131]
[1.11847408 1.22803364 2.23606798]
[1.02599614 1.04455622 1.09637632 1.73205081]
>>> # Now, ignore the top layer:
>>> path = pa.transit_path(radius, nskip=1)
>>> for p in path:
>>>     print(p)
[]
[]
[2.64575131]
[1.22803364 2.23606798]
[1.04455622 1.09637632 1.73205081]
pyratbay.atmosphere.temperature_posterior(posterior, tmodel, tpars, ifree, pressure)[source]
Compute the median and inter-quantiles regions (68% and 95%)
of a temperature profile posterior.

Parameters
----------
posterior: 2D float ndarray [nsamples, nfree]
    A posterior distribution for tmodel.
tmodel: Callable
    Temperature-profile model.
tpars: 1D float iterable [npars]
    Temperature-profile parameters (including fixed parameters).
ifree: 1D bool iterable [npars]
    Mask of free (True) and fixed (False) parameters in tpars.
    The number of free parameters must match nfree in posterior.
pressure: 1D float ndarray [nlayers]
    The atmospheric pressure profile in barye.

Returns
-------
median: 1D float ndarray [nlayers]
    The matplotlib Axes of the figure.
low1: 1D float ndarray [nlayers]
    Lower temperature boundary of the 68%-interquantile range.
high1: 1D float ndarray [nlayers]
    Upper temperature boundary of the 68%-interquantile range.
low2: 1D float ndarray [nlayers]
    Lower temperature boundary of the 95%-interquantile range.
high2: 1D float ndarray [nlayers]
    Upper temperature boundary of the 95%-interquantile range.

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> import pyratbay.constants as pc
>>> import pyratbay.plots as pp
>>> import numpy as np

>>> # Non-inverted temperature profile:
>>> pressure = pa.pressure('1e-6 bar', '1e2 bar', nlayers=100)
>>> tmodel = pa.tmodels.Guillot(pressure)
>>> tpars = np.array([-4.0, -1.0, 0.0, 0.0, 1000.0, 0.0])
>>> # Simulate posterior where kappa' and gamma are variable:
>>> nsamples = 5000
>>> ifree = [True, True, False, False, False, False]
>>> posterior = np.array([
>>>     np.random.normal(tpars[0], 0.5, nsamples),
>>>     np.random.normal(tpars[1], 0.1, nsamples)]).T
>>> tpost = pa.temperature_posterior(
>>>     posterior, tmodel, tpars, ifree, pressure)
>>> ax = pp.temperature(pressure, profiles=tpost[0], bounds=tpost[1:])
pyratbay.atmosphere.qcapcheck(vmr, qcap, ibulk)[source]
Check if the cummulative abundance of traces exceed qcap.

Parameters
----------
vmr: 2D float ndarray
    Volume mixing ratio of atmospheric species [nlayers, nspecies].
qcap: Float
    Cap threshold for cummulative trace abundances.
ibulk: 1D integer ndarray
    Indices of the bulk species to calculate the mixing ratio.

Returns
-------
vmr_cap_flag: Bool
    Flag indicating whether trace abundances sum more than qcap.

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> # Make an atmosphere:
>>> pressure = pa.pressure(ptop=1e-8, pbottom=1e2, nlayers=11, units='bar')
>>> temperature = np.tile(1500.0, 11)
>>> species = ["H2", "He", "H2O"]
>>> abundances = [0.8495, 0.15, 5e-4]
>>> qprofiles = pa.uniform(pressure, temperature, species, abundances)
>>> ibulk = [0,1]
>>> # Sum of all metals (H2O) does not exceed qcap:
>>> qcap = 1e-3
>>> print(pa.qcapcheck(qprofiles, qcap, ibulk))
False
>>> # Sum of all metals (H2O) exceedes qcap:
>>> qcap = 1e-4
>>> print(pa.qcapcheck(qprofiles, qcap, ibulk))
True
pyratbay.atmosphere.balance(vmr, ibulk, ratio, invsrat)[source]
Balance the volume mixing ratios of bulk species, vmr[ibulk],
such that sum(vmr) = 1.0 at each level.

Parameters
----------
vmr: 2D float ndarray
    Volume mixing ratio of atmospheric  species [nlayers, nspecies].
ibulk: 1D integer ndarray
    Indices of the bulk species to calculate the mixing ratio.
ratio: 2D float ndarray
    Abundance ratio between species indexed by ibulk.
invsrat: 1D float ndarray
    Inverse of the sum of the ratios (at each layer).

Notes
-----
Let the bulk abundance species be the remainder of the sum of the trace
species:
    vmr_bulk = sum vmr_j = 1.0 - sum vmr_trace.
This code assumes that the abundance ratio among bulk species
remains constant in each layer:
    {\rm ratio}_j = vmr_j/vmr_0.
The balanced abundance of the bulk species is then:
    vmr_j = \frac{{\rm ratio}_j * vmr_{\rm bulk}} {\sum {\rm ratio}}.

Examples
--------
>>> import pyratbay.atmosphere as pa
>>>
>>> vmr = np.tile([0.8, 0.2, 0.1], (5,1))
>>> ibulk = [0, 1]
>>> bratio, invsrat = pa.ratio(vmr, ibulk)
>>> pa.balance(vmr, ibulk, bratio, invsrat)
>>> # Balanced VMRs:
>>> print(vmr[0])
[0.72 0.18 0.1 ]
>>> # Sum of VMRs equals one at each layer:
>>> print(np.sum(vmr, axis=1))
[1. 1. 1. 1. 1.]
>>> # Ratio of 'bulk' species remains constant:
>>> print(vmr[:,1]/vmr[:,0])
[0.25 0.25 0.25 0.25 0.25]
pyratbay.atmosphere.ratio(vmr, ibulk)[source]
Calculate the abundance ratios of the species indexed by ibulk, relative
to the first species in the list.

Parameters
----------
vmr: 2D float ndarray
    Volume mixing ratio of atmospheric species [nlayers, nspecies].
ibulk: 1D integer ndarray
    Indices of the species to calculate the ratio.

Returns
-------
bratio: 2D float ndarray
    Abundance ratio between species indexed by ibulk.
invsrat: 1D float ndarray
    Inverse of the sum of the ratios (at each layer).

Examples
--------
>>> import pyratbay.atmosphere as pa
>>> vmr = np.tile([0.8, 0.2], (5,1))
>>> ibulk = [0, 1]
>>> bratio, invsrat = pa.ratio(vmr, ibulk)
>>> print(bratio)
[[ 1.    0.25]
 [ 1.    0.25]
 [ 1.    0.25]
 [ 1.    0.25]
 [ 1.    0.25]]
>>> print(invsrat)
[ 0.8  0.8  0.8  0.8  0.8]
pyratbay.atmosphere.qscale(vmr, species, molmodel, molfree, molpars, bulk, qsat=None, iscale=None, ibulk=None, bratio=None, invsrat=None)[source]
Scale specified species abundances and balance bulk abundances to
conserve sum(vmr)=1 in each layer.

Parameters
----------
vmr: 2D float ndarray
    Volume mixing ratio of atmospheric species [nlayers, nspecies].
species: 1D string ndarray
    Names of the species in the atmosphere.
molmodel: 1D string ndarray
    Model to vary the species abundances.
molfree: 1D string ndarray
    Names of the species to vary their abundances.
molpars: 1D float ndarray
    Scaling factor (dex) for each species in molfree.
bulk: 1D string ndarray
    Names of the bulk (dominant) species.
qsat: Float
    Maximum allowed combined abundance for trace species.
iscale: 1D integer ndarray
    Indices of molfree species in vmr.
ibulk: 1D integer ndarray
    Indices of bulk species in vmr.
bratio: 2D float ndarray
    Abundance ratios between the bulk species (relative to bulk[0]).
invsrat: 1D float ndarray
    Inverse of the sum of the ratios (at each layer).

Returns
-------
scaled_vmr: 2D float ndarray
   The modified atmospheric VMR profiles.

Notes
-----
iscale, ibulk, bratio, and invsrat are optional parameters to
speed up the routine.

Examples
--------
>>> import pyratbay.atmosphere as pa

>>> nlayers = 2
>>> vmr = np.tile([0.85, 0.15, 1e-4, 1e-4], (nlayers,1))
>>> species = ['H2', 'He' ,'H2O', 'CH4']
>>> # Set the H2O abundance to 1.0e-3:
>>> molmodel = ['vert']
>>> molfree = ['H2O']
>>> molpars = [-3.0]
>>> bulk = ['H2', 'He']
>>> scaled_vmr = pa.qscale(
>>>     vmr, species, molmodel, molfree, molpars, bulk,
>>> )
>>> print(scaled_vmr)
[[8.49065e-01 1.49835e-01 1.00000e-03 1.00000e-04]
 [8.49065e-01 1.49835e-01 1.00000e-03 1.00000e-04]]

pyratbay.atmosphere.tmodels

class pyratbay.atmosphere.tmodels.Isothermal(pressure)[source]
Isothermal temperature profile model.


Parameters
----------
pressure: 1D float iterable
    Pressure array where to evaluate the temperature profile.
class pyratbay.atmosphere.tmodels.Guillot(pressure, gravity=None)[source]
Guillot (2010) temperature profile based on the three-channel
Eddington approximation, as described Line et al. (2013)


Parameters
----------
pressure: 1D float ndarray
    Atmospheric pressure profile (barye).
gravity: 1D float ndarray or scalar
    Atmospheric gravity profile (cm s-2).
    If None, assume a constant gravity of 1 cm s-2, in which
    case, one should regard the kappa parameter as
    kappa' = kappa/gravity.

Note that the input gravity can be a scalar value used at all
atmospheric pressures (as it has been used so far in the
literature.  However, from a parametric point of view, this is
redundant, as it only acts as a scaling factor for kappa.
Ideally, one would wish to input a pressure-dependent gravity,
but such profile would need to be derived from a hydrostatic
equilibrium calculation, for example.  Unfortunately, HE cannot
be solved without knowing the temperature, thus making this a
circular problem (shrug emoji).
class pyratbay.atmosphere.tmodels.Guillot(pressure, gravity=None)[source]
Guillot (2010) temperature profile based on the three-channel
Eddington approximation, as described Line et al. (2013)


Parameters
----------
pressure: 1D float ndarray
    Atmospheric pressure profile (barye).
gravity: 1D float ndarray or scalar
    Atmospheric gravity profile (cm s-2).
    If None, assume a constant gravity of 1 cm s-2, in which
    case, one should regard the kappa parameter as
    kappa' = kappa/gravity.

Note that the input gravity can be a scalar value used at all
atmospheric pressures (as it has been used so far in the
literature.  However, from a parametric point of view, this is
redundant, as it only acts as a scaling factor for kappa.
Ideally, one would wish to input a pressure-dependent gravity,
but such profile would need to be derived from a hydrostatic
equilibrium calculation, for example.  Unfortunately, HE cannot
be solved without knowing the temperature, thus making this a
circular problem (shrug emoji).
class pyratbay.atmosphere.tmodels.Madhu(pressure)[source]
Temperature profile model by Madhusudhan & Seager (2009)


Parameters
----------
pressure: 1D float ndarray
    Pressure array in barye.
pyratbay.atmosphere.tmodels.get_model(name, *args, **kwargs)[source]
Get a temperature-profile model by its name.

pyratbay.atmosphere.clouds

class pyratbay.atmosphere.clouds.CCSgray[source]
Constant cross-section gray cloud model.


Initialize self.  See help(type(self)) for accurate signature.
extinction(wn, pressure)[source]
Calculate a uniform gray-cloud cross section in cm2 molec-1:
   cross section = s0 * 10**pars[0],
between layers with pressure 10**pars[1] -- 10**pars[2] bar
(top and bottom layers, respectively).
s0 is the H2 Rayleigh cross section at 0.35 um.

Parameters
----------
wn:  1D float ndarray
   Wavenumber array in cm-1.
class pyratbay.atmosphere.clouds.Deck[source]
Instantly opaque gray cloud deck at given pressure.


Initialize self.  See help(type(self)) for accurate signature.
extinction(pressure, radius, temp)[source]
Calculate gray-cloud deck model that's optically thin
above ptop, and becomes instantly opaque at ptop, with
ptop (bar) = 10**pars[0].

Parameters
----------
pressure: 1D float ndarray
    Atmospheric pressure profile (in barye).
radius: 1D float ndarray
    Atmospheric radius profile (in cm).
temp: 1D float ndarray
    Atmospheric temperature profile (in Kelvin degree).
pyratbay.atmosphere.clouds.get_model(name)[source]
Get a cloud model by its name.

pyratbay.atmosphere.rayleigh

class pyratbay.atmosphere.rayleigh.Dalgarno(mol)[source]
Rayleigh-scattering model from Dalgarno (1962), Kurucz (1970), and
Dalgarno & Williams (1962).


Parameters
----------
mol: String
   The species, which can be H, He, or H2.
class pyratbay.atmosphere.rayleigh.Lecavelier[source]
Rayleigh-scattering model from Lecavelier des Etangs et al. (2008).
AA, 485, 865.


Initialize self.  See help(type(self)) for accurate signature.
extinction(wn)[source]
Calculate the Rayleigh cross section in cm2 molec-1:
    cross section = f_ray * s0 * (lambda/l0)**alpha_ray,
parameterized as params = [log10(f_ray), alpha_ray).

Parameters
----------
wn:  1D float ndarray
    Wavenumber array in cm-1.
pyratbay.atmosphere.rayleigh.get_model(name)[source]
Get a Rayleigh model by its name.

pyratbay.atmosphere.alkali

class pyratbay.atmosphere.alkali.SodiumVdW(cutoff=4500.0)[source]
Sodium Van der Waals model (Burrows et al. 2000, ApJ, 531).


Initialize self.  See help(type(self)) for accurate signature.
absorption(press, temp, wn)
Evaluate alkali model's opacity cross section (cm2 molecule-1).
class pyratbay.atmosphere.alkali.PotassiumVdW(cutoff=4500.0)[source]
Potassium Van der Waals model (Burrows et al. 2000, ApJ, 531).


Initialize self.  See help(type(self)) for accurate signature.
absorption(press, temp, wn)
Evaluate alkali model's opacity cross section (cm2 molecule-1).
pyratbay.atmosphere.alkali.get_model(name, *args)[source]
Get an alkali model by its name.

pyratbay.pyrat.read_atm

pyratbay.pyrat.crosssec

pyratbay.pyrat.clouds

pyratbay.pyrat.rayleigh

pyratbay.pyrat.alkali

pyratbay.pyrat.optical_depth

pyratbay.pyrat.spectrum

pyratbay.pyrat.spectrum.spectrum(pyrat)[source]
Spectrum calculation driver.
pyratbay.pyrat.spectrum.modulation(pyrat)[source]
Calculate modulation spectrum for transit geometry.
pyratbay.pyrat.spectrum.intensity(pyrat)[source]
Calculate the intensity spectrum [units] for eclipse geometry.
pyratbay.pyrat.spectrum.flux(pyrat)[source]
Calculate the hemisphere-integrated flux spectrum [units] for eclipse
geometry.
pyratbay.pyrat.spectrum.two_stream(pyrat)[source]
Two-stream approximation radiative transfer
following Heng et al. (2014)

This function defines downward (flux_down) and uppward fluxes
(flux_up) into pyrat.spec, and sets the emission spectrum as the
uppward flux at the top of the atmosphere (flux_up[0]):

flux_up: 2D float ndarray
    Upward flux spectrum through each layer under the two-stream
    approximation (erg s-1 cm-2 cm).
flux_down: 2D float ndarray
    Downward flux spectrum through each layer under the two-stream
    approximation (erg s-1 cm-2 cm).