Commit 373499ac authored by dblain's avatar dblain
Browse files

Add comments in python files, update licence, fix typos in readme.

parent f2b42760
......@@ -4,12 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com)
and this project adheres to [Semantic Versioning](http://semver.org).
## [2.0.0b1] - 2020-10-30
## [2.0.0b2] - 2020-11-10
### Added
- Cloud module.
- Condensation of Al2O3, Cr, Cr2O3, MnS, ZnS and NH3.
- Eddy diffusion coefficient mode as input.
- Output of the transmission spectrum (with and without clouds) and of its derivative.
- Output of elements total VMR.
- Output of all gaseous species VMR (not only of the absorbers).
......
MIT License
Copyright (c) 2019 Blain Doriann, Bruno Bézard and Jean-Loup Baudino #TODO WIP
Copyright (c) 2020 Jean-Loup Baudino, Bruno Bezard, Benjamin Charnay and Blain Doriann #TODO WIP
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
......@@ -2,7 +2,7 @@
## Synopsis
Exo-REM is a 1D radiative-equilibrium model first developed for the simulation of young gas giants far from their star and brown dwarfs. Fluxes are calculated using the two-stream approximation assuming hemispheric closure. The radiative-convective equilibrium is solved assuming that the net flux (radiative + convective) is conservative. The conservation of flux over the pressure grid is solved iteratively using a constrained linear inversion method. Rayleigh scattering from H2, He and H2O, as well as absorption and scattering by clouds (calculated from extinction coefficient, single scattering albedo, and asymmetry factor interpolated from precomputed tables for a set of wavelengths and particle radii) are also taken into account.
Exo-REM contains also two side-programs used to generate the k-coefficients files:
Exo-REM contains also three side-programs used to generate the k-coefficients files:
- CAXS (Calculate Absorption Cross Sections), capable of calculating the absorption cross
sections of any species over a wide range of wavenumbers. Individual species can be combined together (for example
using isotopic ratios). The cross sections can be calculated either using a pressure-temperature profile or a grid of
......@@ -169,7 +169,7 @@ Example:
Most of the files in *Exo-REM* uses the same data format:
- The data are organized in columns.
- The first line contains the labels of the columns, separated by whitespaces or tabs.
This line can also contains additional informations or comments by adding a "!" after all the labels.
This line can also contains additional information or comments by adding a "!" after all the labels.
This can be used for example in stellar spectra to add the effective temperature of the spectrum.
- The second line contains the units of the columns, separated by whitespaces or tabs.
- The following lines contains the actual data, the columns are separated by whitespaces or tabs.
......
......@@ -35,7 +35,7 @@ module exorem_interface
implicit none
character(len=*), parameter :: exorem_version = '2.0.0-beta1'
character(len=*), parameter :: exorem_version = '2.0.0-beta2'
logical :: &
load_vmr_profiles, &
......
"""
Functions to calculate condensation profiles.
"""
import numpy as np
......@@ -8,15 +8,26 @@ from src.python.interface import path_to_results, load_result
def get_condensation_vmr(species, file_suffix, vmr_prefix='vmr', temperature_profile_prefix='temperature_profile',
path=path_to_results):
"""
Get the VMR of a species approximately at its condensation level based on cloud information.
:param species: species to get the condensation VMR
:param file_suffix: file suffix
:param vmr_prefix: vmr files prefix
:param temperature_profile_prefix: temperature profile files prefix
:param path: path to the files
:return: the VMR at the condensation level
"""
species_vmr = load_result(f'{path}{vmr_prefix}_{file_suffix}')[f'volume_mixing_ratio_{species}']
try:
species_cloud_vmr = \
load_result(f'{path}{temperature_profile_prefix}_{file_suffix}')[f'cloud_opacity_{species}']
except KeyError:
# The cloud opacity was not detected, find the latest level the VMR profile was constant
wh = np.where(species_vmr[1:] - species_vmr[:-1] == 0)[0]
if np.size(wh) == 0:
# The profile is never constant, take the VMR at the top of the atmosphere
wh = 0
else:
wh = wh[-1]
......@@ -28,7 +39,7 @@ def get_condensation_vmr(species, file_suffix, vmr_prefix='vmr', temperature_pro
if np.size(wh) > 0:
wh = np.max(np.min((np.size(species_vmr) - 1, wh[0][-1] - 1)), 0)
return species_vmr[wh]
else: # cloud has not condensed, return the upper value
else: # cloud has not condensed, return the VMR at the top of the atmosphere
return species_vmr[0]
......@@ -88,6 +99,11 @@ def get_h2o_saturation_pressure(temperature):
def get_h2o_melting_pressure(temperature):
"""
Calculate the melting perssure of H2O.
:param temperature: (K) temperature
:return: (bar) array containing the melting pressure of ice-1 and ice-3, 5, 6 and 7 at the given temperature
"""
temperature_triple_point = 273.16 # (K) temperature of H2O triple point (Fray & Schmitt 2009)
pressure_triple_point = 6.11657e-3 # (bar) pressure of H2O triple point (Fray & Schmitt 2009)
......@@ -132,6 +148,11 @@ def get_h2o_melting_pressure(temperature):
def get_nh3_saturation_pressure(temperature):
"""
Get the NH3 saturation pressure.
:param temperature: (K) temp
:return: (bar) saturation pressure of NH3 at the given temperature
"""
temperature_triple_point = 195.41 # (K) temperature of H2O triple point (Fray & Schmitt 2009)
pressure_triple_point = 6.09e-2 # (bar) pressure of H2O triple point (Fray & Schmitt 2009)
......@@ -176,10 +197,17 @@ def get_nh3_saturation_pressure(temperature):
elif temperature <= temperature_critical_point:
return np.exp(np.interp(np.log(temperature), np.log(temperatures_ref), np.log(saturation_pressures_ref)))
else:
return 1e10
return 1e10 # arbitrary value
def get_h2o_saturation_temperature(pressures, file_suffix, **kwargs):
"""
Get the H2O saturation temperatures at given pressures.
:param pressures: (bar) pressures
:param file_suffix: VMR file suffix
:param kwargs: keyword arguments for get_condensation_vmr
:return: (K) array of H2O condensation temperatures
"""
condensation_pressure = []
condensation_temperature_h2o = []
temperature_grid = np.linspace(1, 3000, 3000)
......@@ -199,6 +227,13 @@ def get_h2o_saturation_temperature(pressures, file_suffix, **kwargs):
def get_h2o_melting_temperature(pressures, file_suffix, **kwargs):
"""
Get the H2O melting temperature.
:param pressures: (bar) list of pressures
:param file_suffix: VMR file suffix
:param kwargs: keyword arguments for get_condensation_vmr
:return:
"""
melting_pressure_ice1 = []
melting_pressure = []
melting_temperature_ice1 = []
......@@ -231,6 +266,13 @@ def get_h2o_melting_temperature(pressures, file_suffix, **kwargs):
def get_nh3_saturation_temperature(pressures, file_suffix, **kwargs):
"""
Get the NH3 saturation temperatures at given pressures.
:param pressures: (bar) pressures
:param file_suffix: VMR file suffix
:param kwargs: keyword arguments for get_condensation_vmr
:return: (K) array of NH3 condensation temperatures
"""
condensation_pressure = []
condensation_temperature_nh3 = []
temperature_grid = np.linspace(1, 3000, 3000)
......@@ -248,6 +290,15 @@ def get_nh3_saturation_temperature(pressures, file_suffix, **kwargs):
def get_condensation_temperatures(pressure, species, file_suffix, metallicity, **kwargs):
"""
Get the condensation temperatures of a given species.
:param pressure: (bar) pressure
:param species: species name (e.g. 'H2O')
:param file_suffix: VMR file suffix
:param metallicity: atmospheric metallicity
:param kwargs: keyword arguments for H2O and NH3 get_saturation_temperature
:return: the condensation temperature of the given species
"""
if species == 'H2O':
condensation_temperature = get_h2o_saturation_temperature(
pressure, file_suffix, **kwargs
......@@ -278,6 +329,12 @@ def get_condensation_temperatures(pressure, species, file_suffix, metallicity, *
def get_h2o_triple_point(pressure, condensation_temperature_h2o):
"""
Return the partial pressure of the H2O ice1-liquid-gas triple point.
:param pressure: (bar) list of pressures
:param condensation_temperature_h2o: (K) list of H2O condensation temperatures
:return: (bar) the partial pressure of the H2O ice1-liquid-gas triple point
"""
for i, t in enumerate(condensation_temperature_h2o):
if t > 273.16:
pressure_h2o_triple_point = np.interp(
......@@ -291,6 +348,13 @@ def get_h2o_triple_point(pressure, condensation_temperature_h2o):
def get_h2o_condensation_pressure(pressure, temperature, condensation_temperature_h2o):
"""
Return the pressure of condensation of H2O
:param pressure: (bar) array of pressures
:param temperature: (K) array of temperatures
:param condensation_temperature_h2o: (K) H2O condensation temperatures at the corresponding pressures
:return: (bar) the pressure of condensation of H2O
"""
wh = np.where(condensation_temperature_h2o > temperature)
if np.size(wh) > 0:
......
......@@ -20,16 +20,6 @@ T_eff_sol = 5772 # (K) effective temperature of the Sun (IAU 2015)
rho_sol = 1408.0 # (kg.m-3) density of the Sun
Z_sol = -4.33 # (log(N_Fe / N_H)) metallicity of the Sun
M_H_fusion = 0.079 * M_sol # (kg) minimum mass for convective H-fusion
M_radiative_H_fusion = 0.43 * M_sol # (kg) minimum mass for radiative H-fusion (effect on luminosity)(0.43)
M_CNO_H_fusion = 2.0 * M_sol # (kg) minimum mass for convective CNO cycle H-fusion (effect on luminosity)
M_C_fusion = 5.0 * M_sol # (kg) minimum mass for C-fusion
M_Ne_fusion = 8.0 * M_sol # (kg) minimum mass for Ne-fusion
M_Eddington = 55.0 * M_sol # (kg) minimum mass for Eddington luminosity law
M_star_min = M_H_fusion # (kg) minimum star mass
M_star_max = 1000 * M_sol # (kg) maximum star mass
M_chandrasekhar = 2.018236 / 2 * (3 * pi) ** 0.5 * \
(h / (2 * pi) * c / G) ** 1.5 / (2 * m_hydrogen) ** 2 # (kg) Chandrasekhar mass limit
......
......@@ -38,6 +38,12 @@ def load_cia(file):
def load_matrix(file, path=path_to_results):
"""
Loaf a (n, n) matrix data file.
:param file: matrix file
:param path: path of the file
:return: the matrix data
"""
with open(path + file, 'r') as f:
header = f.readline()
unit_line = f.readline()
......@@ -56,6 +62,12 @@ def load_matrix(file, path=path_to_results):
def load_result(file, **kwargs):
"""
Load an Exo-REM data file.
:param file: data file
:param kwargs: keyword arguments for loadtxt
:return: the data
"""
with open(file, 'r') as f:
header = f.readline()
unit_line = f.readline()
......@@ -75,6 +87,12 @@ def load_result(file, **kwargs):
def load_rectangular_matrix(file, path=path_to_results):
"""
Load a (n, m) matrix data file.
:param file: matrix data file
:param path: path to the file
:return: the rectangular matrix data
"""
with open(path + file, 'r') as f:
header = f.readline()
unit_line = f.readline()
......
"""
Functions to plot useful figures.
"""
import re
import matplotlib.pyplot as plt
......@@ -7,31 +10,6 @@ from src.python.condensations import *
import src.python.constants as cst
from src.python.interface import *
# Matplotlib sizes
TINY_FIGURE_FONT_SIZE = 40 # 0.5 text width 16/9
SMALL_FIGURE_FONT_SIZE = 22 # 0.25 text width
MEDIUM_FIGURE_FONT_SIZE = 16 # 0.5 text width
LARGE_FIGURE_FONT_SIZE = 22 # 1.0 text width
large_figsize = [19.20, 10.80] # 1920 x 1080 for 100 dpi (default)
def update_figure_font_size(font_size):
plt.rc('font', size=font_size) # controls default text sizes
plt.rc('axes', titlesize=font_size) # fontsize of the axes title
plt.rc('axes', labelsize=font_size) # fontsize of the x and y labels
plt.rc('axes.formatter', use_mathtext=True) # fontsize of the x and y labels
plt.rc('xtick', labelsize=font_size) # fontsize of the tick labels
plt.rc('xtick', direction='in') # fontsize of the tick labels
plt.rc('xtick.major', width=font_size / 10 * 0.8, size=font_size / 10 * 3.5) # fontsize of the tick labels
plt.rc('xtick.minor', width=font_size / 10 * 0.6, size=font_size / 10 * 2) # fontsize of the tick labels
plt.rc('ytick', labelsize=font_size) # fontsize of the tick labels
plt.rc('ytick', direction='in') # fontsize of the tick labels
plt.rc('ytick.major', width=font_size / 10 * 0.8, size=font_size / 10 * 3.5) # fontsize of the tick labels
plt.rc('ytick.minor', width=font_size / 10 * 0.6, size=font_size / 10 * 2) # fontsize of the tick labels
plt.rc('legend', fontsize=font_size) # legend fontsize
plt.rc('figure', titlesize=font_size) # fontsize of the figure title
# Units
wavenumber_units = r'cm$^{-1}$'
......@@ -111,8 +89,44 @@ cloud_color = {
}
# Matplotlib sizes
TINY_FIGURE_FONT_SIZE = 40 # 0.5 text width 16/9
SMALL_FIGURE_FONT_SIZE = 22 # 0.25 text width
MEDIUM_FIGURE_FONT_SIZE = 16 # 0.5 text width
LARGE_FIGURE_FONT_SIZE = 22 # 1.0 text width
large_figsize = [19.20, 10.80] # 1920 x 1080 for 100 dpi (default)
def update_figure_font_size(font_size):
"""
Update the figure font size in a nice way.
:param font_size: new font size
"""
plt.rc('font', size=font_size) # controls default text sizes
plt.rc('axes', titlesize=font_size) # fontsize of the axes title
plt.rc('axes', labelsize=font_size) # fontsize of the x and y labels
plt.rc('axes.formatter', use_mathtext=True) # fontsize of the x and y labels
plt.rc('xtick', labelsize=font_size) # fontsize of the tick labels
plt.rc('xtick', direction='in') # fontsize of the tick labels
plt.rc('xtick.major', width=font_size / 10 * 0.8, size=font_size / 10 * 3.5) # fontsize of the tick labels
plt.rc('xtick.minor', width=font_size / 10 * 0.6, size=font_size / 10 * 2) # fontsize of the tick labels
plt.rc('ytick', labelsize=font_size) # fontsize of the tick labels
plt.rc('ytick', direction='in') # fontsize of the tick labels
plt.rc('ytick.major', width=font_size / 10 * 0.8, size=font_size / 10 * 3.5) # fontsize of the tick labels
plt.rc('ytick.minor', width=font_size / 10 * 0.6, size=font_size / 10 * 2) # fontsize of the tick labels
plt.rc('legend', fontsize=font_size) # legend fontsize
plt.rc('figure', titlesize=font_size) # fontsize of the figure title
# Utils
def get_species_string(string):
"""
Get the string of a species from an Exo-REM data label.
Example: volume_mixing_ratio_H2O -> H2O
:param string: an Exo-REM data label
:return: the species string
"""
subscripts = re.findall(r'\d+', string)
string = re.sub(r'\d+', '$_%s$', string)
......@@ -175,6 +189,15 @@ def plot_all(file_suffix, path_outputs, path_inputs='outputs/exorem/',
def plot_kernel(file, path=path_to_results, cmap='inferno', vmin=None, vmax=None):
"""
Plot an Exo-REM kernel.
:param file: file containing the kernel
:param path: path to the file
:param cmap: colormap to use
:param vmin: minimal value for the colorbar
:param vmax: maximal value for the colorbar
:return: the kernel data
"""
data = load_matrix(file, path)
pressures = data['pressure']
kernel = data['kernel']
......@@ -188,8 +211,18 @@ def plot_kernel(file, path=path_to_results, cmap='inferno', vmin=None, vmax=None
return data
def plot_transmission_spectrum_derivative(file, path=path_to_results, level_deriv=False, wvn2wvl=False, cmap='inferno',
log_k=False, x_normalize=False, ppu2ppm=False, **kwargs):
def plot_transmission_spectrum_derivative(file, path=path_to_results, wvn2wvl=False, cmap='inferno',
ppu2ppm=False, **kwargs):
"""
Plot the derivative of the transmission spectrum.
:param file: file containing the derivative
:param path: path to the file
:param wvn2wvl: convert wavenumbers (cm-1) into wavelegths (m)
:param cmap: colormap to use
:param ppu2ppm: convert part per units into part per millions
:param kwargs: keyword arguments for pcolormesh
:return: the derivative data
"""
data = load_rectangular_matrix(file, path)
pressures = data['pressure']
wavenumbers = data['wavenumber']
......@@ -203,18 +236,7 @@ def plot_transmission_spectrum_derivative(file, path=path_to_results, level_deri
else:
deriv_unit = ''
if log_k:
kernel = np.log10(kernel)
if level_deriv:
kernel[:-1, :] = kernel[1:, :] - kernel[:-1, :]
kernel[-2:, :] = 0
deriv_str = r'$\partial\mathcal{T}/\partial z$'
else:
deriv_str = r'$\mathcal{T}$'
if x_normalize:
kernel = kernel / np.sum(kernel, axis=0)
deriv_str = r'$\mathcal{T}$'
if wvn2wvl:
wavenumbers = 1e-2 / wavenumbers
......@@ -233,21 +255,6 @@ def plot_transmission_spectrum_derivative(file, path=path_to_results, level_deri
return data
def plot_sum_kernel(file, path=path_to_results, **kwargs):
data = load_matrix(file, path)
pressures = data['pressure']
kernel = data['kernel']
plt.semilogy(np.sum(kernel, axis=1), pressures, **kwargs)
plt.xlim([0, None])
plt.ylim([np.max(pressures), np.min(pressures)])
plt.xlabel(r'$\partial$E/$\partial$T (W.m$^{-2}$)')
plt.ylabel('Pressure (Pa)')
return data
def plot_condensation_profiles(
pressure, file_suffix, metallicity, exclude=None, plot_h2o_triple_point=False, legend=False, bar2pa=False,
markersize=1, vmr_prefix='vmr', temperature_profile_prefix='temperature_profile', path=path_to_results, **kwargs
......@@ -265,7 +272,6 @@ def plot_condensation_profiles(
:param vmr_prefix: prefix of the VMR file
:param temperature_profile_prefix: prefix of the temperature profile file
:param path: path to the files
:return:
"""
if exclude is None:
exclude = [exclude]
......@@ -370,6 +376,14 @@ def plot_emission_contribution_spectra(
file, include_clouds=False, wvn2wvl=False, legend=False,
**kwargs
):
"""
Plot the different contributions of the emission spectrum.
:param file: spectrum file
:param include_clouds: include the cloud contribution
:param wvn2wvl: convert wavenumbers (cm-1) into wavelengths (m)
:param legend: plot the legend
:param kwargs: keyword arguments for plot
"""
data_dict = load_result(file)
x_axis = None
x_axis_label = None
......@@ -421,6 +435,20 @@ def plot_contribution_transmission_spectra(file, wvn2wvl=False, legend=False, ex
xmin=None, xmax=None, offset=1.0, star_radius=None, planet_radius=1.0,
cloud_altitude=None,
**kwargs):
"""
Plot the different contributions in the transmission spectrum.
:param file: spectrum file
:param wvn2wvl: convert wavenumbers (cm-1) into wavelengths (m)
:param legend: plot the legend
:param exclude: list of label to exclude (e.g. ['H2O', 'clouds'])
:param xmin: minimum x-axis value
:param xmax: maximum x-axis value
:param offset: (m) altitude offset of the transmission spectrum
:param star_radius: (m) radius of the star
:param planet_radius: (m) radius of the planet
:param cloud_altitude: (m) add an opaque cloud deck at the given altitude
:param kwargs: keyword arguments for plot
"""
if exclude is None:
exclude = np.array([None])
else:
......@@ -529,11 +557,10 @@ def plot_contribution_transmission_spectra(file, wvn2wvl=False, legend=False, ex
def plot_emission_spectrum(file, legend=False, wvn2wvl=False, **kwargs):
"""
Plot the emission spectrum.
:param file:
:param legend:
:param wvn2wvl:
:param kwargs:
:return:
:param file: spectrum file
:param legend: plot the legend
:param wvn2wvl: convert wavenumbers (cm-1) into wavelengths (m)
:param kwargs: keyword arguments for plot
"""
data_dict = load_result(file)
......@@ -560,10 +587,31 @@ def plot_temperature_profile(
file_suffix, path=path_to_results, metallicity=1, pa2bar=False,
plot_convective_layer=True, plot_photosphere=True, plot_condensation=True,
photosphere_wavelength_range=None, exclude=None, legend=True,
color='k', ls_condensation=':', linewidth=1,
vmr_prefix='vmr', temperature_profile_prefix='temperature_profile', **kwargs
color='k', ls_condensation=':', linewidth=2,
vmr_prefix='vmr', spectrum_prefix='spectra', temperature_profile_prefix='temperature_profile', **kwargs
):
file = path + 'temperature_profile_' + file_suffix
"""
Plot a model temperature profile.
:param file_suffix: suffix of the model files
:param path: path to the file
:param metallicity: metallicity for the condensation profiles, except H2O
:param pa2bar: convert Pascals into bars
:param plot_convective_layer: plot the convective layers
:param plot_photosphere: plot the photosphere from the model spectrum file
:param plot_condensation: plot the condensation profiles
:param photosphere_wavelength_range: set the wavelength range of the photosphere (e.g. [1e-6, 5e-6])
:param exclude: list of condensation profiles to exclude (e.g. ['H2O', 'NH3'])
:param legend: plot the legend
:param color: color of the temperature profile
:param ls_condensation: linestyle of the condensation profiles
:param linewidth: linewidth of the temperature profile
:param vmr_prefix: prefix of the model vmr file
:param spectrum_prefix: prefix of the model spectrum file
:param temperature_profile_prefix: prefix of the model temperature profile file
:param kwargs: keyword arguments for plot
:return:
"""
file = path + temperature_profile_prefix + '_' + file_suffix
data_dict = load_result(file)
pressure = np.asarray(data_dict['pressure'])
......@@ -571,7 +619,7 @@ def plot_temperature_profile(
# plot cloud condensation curves
if plot_condensation:
file_vmr = path + 'vmr_' + file_suffix
file_vmr = path + vmr_prefix + '_' + file_suffix
vmr_dict = load_result(file_vmr)
......@@ -610,7 +658,7 @@ def plot_temperature_profile(
# Photosphere
if plot_photosphere:
file_spectrum = path + 'spectra_' + file_suffix
file_spectrum = path + spectrum_prefix + '_' + file_suffix
if photosphere_wavelength_range is None:
photosphere_wavelength_range = [5e-6, 25e-6]
......@@ -663,6 +711,17 @@ def plot_temperature_profile(
def plot_transmission_spectrum(file, wvn2wvl=False, offset=1, star_radius=None, xlim=None,
normalize=False, cloud_coverage=None, **kwargs):
"""
Plot a transmission spectrum.
:param file: spectrum file
:param wvn2wvl: convert wavenumbers (cm-1) into wavelengths (m)
:param offset: (m) altitude offset of the transmission spectrum
:param star_radius: (m) radius of the star
:param xlim: x-axis limits (i.e. [min, max])
:param normalize: normalize the transmission spectrum
:param cloud_coverage: cloud coverage, between 0 (no cloud) and 1 (full converage)
:param kwargs: keyword arguments for plot
"""
data_dict = load_result(file)
try:
......@@ -749,6 +808,25 @@ def plot_vmr_profile(
legend=False, pa2bar=False, exclude=None,
xlim=None, ylim=None, **kwargs
):
"""
Plot the volume mixing ratio profiles of a model
:param file: vmr file
:param plot_other_gases: list of non-absorbant gases to plot (e.g. ['H2, He'])
:param plot_elements: list of gaseous elemental abundance to plot (e.g. ['N', 'O'])
:param plot_saturation: list of saturation profiles to plot (e.g. ['Mg'])
:param ls_other: linestyle of the non-absorbant gases
:param color_other: list of color of the non-absorbant gases (e.g. ['C0', 'red'])
:param ls_elements: linestyle of element abundance profiles
:param color_elements: list of color of the element abundance profiles
:param ls_saturation: linestyle of the saturation profiles
:param color_saturation: color of the saturation profiles
:param legend: plot the legend
:param pa2bar: convert Pascals into bars
:param exclude: list of absorbant gases to exclude
:param xlim: x-axis limits ([min, max])
:param ylim: y-axis limits ([min, max])
:param kwargs: keyword arguments for plot
"""
if exclude is None:
exclude = [None]
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment