#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# This file is part of the CASCADe package which has been
# developed within the ExoplANETS-A H2020 program.
#
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2020, 2021 Jeroen Bouwman
"""
Created on Mon May 4 19:08:58 2020
@author: Jeroen Bouwman
"""
# import copy
import os
import ast
import warnings
import numpy as np
import astropy.units as u
from astropy.visualization import quantity_support
from matplotlib import pyplot as plt
import seaborn as sns
from skimage import exposure
import statsmodels.distributions
import copy
from ..initialize import cascade_default_save_path
from ..initialize import cascade_configuration
from ..exoplanet_tools import transit_to_eclipse
__all__ = ["load_data_verbose",
"subtract_background_verbose",
"filter_dataset_verbose",
"determine_source_movement_verbose",
"check_wavelength_solution_verbose",
"correct_wavelengths_verbose",
"set_extraction_mask_verbose",
"extract_1d_spectra_verbose",
"calibrate_timeseries_verbose",
"Verbose"]
def _get_plot_parameters():
try:
verbose = ast.literal_eval(cascade_configuration.cascade_verbose)
save_verbose = \
ast.literal_eval(cascade_configuration.cascade_save_verbose)
except AttributeError:
warnings.warn("Verbose flags not defined. Assuming False")
verbose = False
save_verbose = False
try:
save_path = cascade_configuration.cascade_save_path
if not os.path.isabs(save_path):
save_path = os.path.join(cascade_default_save_path, save_path)
os.makedirs(save_path, exist_ok=True)
except AttributeError:
warnings.warn("No save path defined. Not saving plots")
save_verbose = False
try:
observations_id = cascade_configuration.observations_id
observations_target_name = \
cascade_configuration.observations_target_name
if observations_id not in observations_target_name:
save_name_base = observations_target_name+'_'+observations_id
else:
save_name_base = observations_target_name
except AttributeError:
warnings.warn("No uniue id or target name set"
"save name not unique.")
save_name_base = 'verbose'
return (verbose, save_verbose, save_path, save_name_base)
[docs]def load_data_verbose(*args, **kwargs):
"""
Make verbose plots for load_data step.
Parameters
----------
args : 'tuple'
Input varables for plot output.
kwargs : 'dict'
Named varables for plot output. Included should be the following:
verbose_par, plot_data
Returns
-------
None.
"""
(verbose, save_verbose, save_path, save_name_base) = kwargs["verbose_par"]
if not verbose:
return
if "plot_data" not in kwargs.keys():
return
sns.set_context("talk", font_scale=1.5, rc={"lines.linewidth": 2.5})
sns.set_style("white", {"xtick.bottom": True, "ytick.left": True})
data = kwargs["plot_data"].dataset.return_masked_array("data")
wavelength = kwargs["plot_data"].dataset.return_masked_array("wavelength")
try:
scaling = kwargs["plot_data"].dataset.return_masked_array("scaling")
if scaling is None:
scaling = 1.0
except:
scaling=1.0
data=data/scaling
fig, ax = plt.subplots(figsize=(12, 12), nrows=1, ncols=1)
if data.ndim == 3:
cmap = plt.cm.viridis
cmap.set_bad("white", 1.)
im_scaled = exposure.rescale_intensity(data[..., 0].filled(0.0))
img_adapteq = exposure.equalize_adapthist(im_scaled, clip_limit=0.03)
img_adapteq = np.ma.array(img_adapteq, mask=data[..., 0].mask)
p = ax.imshow(img_adapteq,
origin="lower", aspect="auto",
cmap=cmap, interpolation="none", vmin=0.0, vmax=1.0)
plt.colorbar(p, ax=ax).set_label("Normalized Intensity")
ax.set_ylabel("Pixel Position Dispersion Direction")
ax.set_xlabel("Pixel Position Cross-Dispersion Direction")
fig_name_extension = "a"
else:
ax.plot(wavelength[:, 0], data[:, 0], lw=3, color="b")
ax.set_ylabel("Siganl")
ax.set_xlabel("Wavelength")
fig_name_extension = "b"
ax.set_title("First Integration {}.".format(save_name_base))
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_load_data_step_figure1{}.png".
format(fig_name_extension)),
bbox_inches="tight")
if not hasattr(kwargs["plot_data"].instrument_calibration,
"calibration_images"):
return
fig, ax = plt.subplots(figsize=(12, 12), nrows=1, ncols=1)
cmap = plt.cm.viridis
cmap.set_bad("white", 1.)
image = \
kwargs["plot_data"].instrument_calibration.calibration_images[0, ...]
source_pos = kwargs["plot_data"].instrument_calibration.\
calibration_source_position[0]
expected_source_pos = kwargs["plot_data"].instrument_calibration.\
expected_calibration_source_position[0]
im_scaled = exposure.rescale_intensity(image)
img_adapteq = exposure.equalize_adapthist(im_scaled, clip_limit=0.03)
p = ax.imshow(img_adapteq,
origin="lower", aspect="auto",
cmap=cmap, interpolation="none", vmin=0.0, vmax=1.0)
plt.colorbar(p, ax=ax).set_label("Normalized Intensity")
ax.scatter(*source_pos, s=430,
edgecolor="white", facecolor='none',
label="Fitted position ({0:3.2f},{1:3.2f})".
format(*source_pos))
ax.scatter(*expected_source_pos, s=380,
edgecolor="r", facecolor="none",
label="Expected position ({0:3.2f},{1:3.2f})".
format(*expected_source_pos))
ax.set_title("Acquisition Image "
"Position {}".format(save_name_base))
ax.legend()
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_load_data_step_figure2a.png"),
bbox_inches="tight")
[docs]def subtract_background_verbose(*args, **kwargs):
"""
Make verbose plots for the subtract_background step.
Parameters
----------
args : 'tuple'
Input varables for plot output.
kwargs : 'dict'
Named varables for plot output. Included should be the following:
verbose_par, plot_data
Returns
-------
None.
"""
(verbose, save_verbose, save_path, save_name_base) = kwargs["verbose_par"]
if not verbose:
return
if "plot_data" not in kwargs.keys():
return
sns.set_context("talk", font_scale=1.5, rc={"lines.linewidth": 2.5})
sns.set_style("white", {"xtick.bottom": True, "ytick.left": True})
data = kwargs["plot_data"].dataset.return_masked_array("data")
wavelength = kwargs["plot_data"].dataset.return_masked_array("wavelength")
time = kwargs["plot_data"].dataset.return_masked_array("time")
roi = kwargs["plot_data"].instrument_calibration.roi
try:
scaling = kwargs["plot_data"].dataset.return_masked_array("scaling")
if scaling is None:
scaling = 1.0
except:
scaling=1.0
data=data/scaling
if data.ndim == 3:
roi_cube = np.tile(roi.T, (time.shape[-1], 1, 1)).T
else:
roi_cube = np.tile(roi.T, (time.shape[-1], 1)).T
data_with_roi = \
np.ma.array(data,
mask=np.ma.mask_or(data.mask, roi_cube))
wavelength_with_roi = \
np.ma.array(wavelength,
mask=np.ma.mask_or(wavelength.mask, roi_cube))
total_data = np.ma.sum(data_with_roi, axis=-1)/time.shape[-1]
total_wavelength = np.ma.sum(wavelength_with_roi, axis=-1)/time.shape[-1]
if data.ndim == 3:
lightcurve = np.ma.sum(data_with_roi, axis=(0, 1))
time = time[0, 0, :].data
else:
lightcurve = np.ma.sum(data_with_roi, axis=(0))
time = time[0, :].data
fig, ax = plt.subplots(figsize=(12, 12))
if total_data.ndim == 2:
cmap = plt.cm.viridis
cmap.set_bad("white", 1.)
im_scaled = exposure.rescale_intensity(total_data.filled(0.0))
img_adapteq = exposure.equalize_adapthist(im_scaled, clip_limit=0.03)
img_adapteq = np.ma.array(img_adapteq, mask=total_data.mask)
p = ax.imshow(img_adapteq,
origin="lower", aspect="auto",
cmap=cmap, interpolation="none", vmin=0.0, vmax=1.0)
plt.colorbar(p, ax=ax).set_label("Normalized Average Intensity")
ax.set_ylabel("Pixel Position Dispersion Direction")
ax.set_xlabel("Pixel Position Cross-Dispersion Direction")
fig_name_extension = "a"
else:
ax.plot(total_wavelength, total_data)
ax.set_xlabel("Wavelength")
ax.set_ylabel("Average Signal")
fig_name_extension = "b"
ax.set_title("Background subtracted averaged "
"data {}.".format(save_name_base))
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_subtract_background_step_figure1{}.png".
format(fig_name_extension)),
bbox_inches='tight')
fig, ax = plt.subplots(figsize=(12, 12))
ax.plot(time, lightcurve, ".")
ax.set_xlabel("Orbital phase")
ax.set_ylabel("Total Signal")
ax.set_title("Background subtracted data {}.".format(save_name_base))
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_subtract_background_step_figure2{}.png".
format(fig_name_extension)),
bbox_inches="tight")
[docs]def filter_dataset_verbose(*args, **kwargs):
"""
Make verbose plots.
Returns
-------
None.
"""
pass
[docs]def determine_source_movement_verbose(*args, **kwargs):
"""
Make verbose plots.
Returns
-------
None.
"""
pass
[docs]def correct_wavelengths_verbose(*args, **kwargs):
"""
Make verbose plots.
Returns
-------
None.
"""
pass
[docs]def check_wavelength_solution_verbose(*args, **kwargs):
"""
Make verbose plots for the check_wavelength_solution step.
Parameters
----------
args : 'tuple'
Input varables for plot output.
kwargs : 'dict'
Named varables for plot output. Included should be the following:
verbose_par, modeled_observations, corrected_observations
Returns
-------
None.
"""
(verbose, save_verbose, save_path, save_name_base) = kwargs["verbose_par"]
if not verbose:
return
if "modeled_observations" not in kwargs.keys():
return
if "corrected_observations" not in kwargs.keys():
return
if "stellar_model" not in kwargs.keys():
return
if "extension" not in kwargs.keys():
extension=""
else:
extension = kwargs["extension"]
modeled_observations = kwargs["modeled_observations"]
corrected_observations = kwargs["corrected_observations"]
stellar_model = kwargs["stellar_model"]
sns.set_context("talk", font_scale=2.0, rc={"lines.linewidth": 5.5})
sns.set_style("white", {"xtick.bottom": True, "ytick.left": True})
wavelength_unit = modeled_observations[0].data.unit
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
ax0.plot(modeled_observations[0],
modeled_observations[1]*modeled_observations[2] , label='Model')
ax0.plot(corrected_observations[0],
corrected_observations[1], label='Corrected Observations')
ax0.plot(corrected_observations[0]-corrected_observations[2],
corrected_observations[1], label='Un-Corrected Observations')
plt.plot([], [], ' ',
label="Used scaling: {:10.4f}".format(modeled_observations[2]))
plt.plot([], [], ' ',
label="Wavelength shift: {:10.4f}".format(corrected_observations[2]))
ax0.set_xlabel('Wavelength [{}]'.format(wavelength_unit))
ax0.set_ylabel('Normalized Signal')
ax0.set_title("Comparison Model with Observed Mean Spectrum")
ax0.legend(loc='best', fancybox=True, framealpha=1.0,
ncol=1, bbox_to_anchor=(0.2, 0.10, 0.8, 0.8), shadow=True,
handleheight=1.5, labelspacing=0.05, fontsize=20).set_zorder(11)
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_check_wavelength_solution" +
extension + ".png"),
bbox_inches="tight")
[docs]def calibrate_timeseries_verbose(*args, **kwargs):
"""
Make verbose plots for the calibrate_timeserie step.
Parameters
----------
args : 'tuple'
Input varables for plot output.
kwargs : 'dict'
Named varables for plot output. Included should be the following:
verbose_par, model, dataset, cleaned_dataset, exoplanet_spectrum,
calibration_results.
Returns
-------
None.
"""
(verbose, save_verbose, save_path, save_name_base) = kwargs["verbose_par"]
if not verbose:
return
if "exoplanet_spectrum" not in kwargs.keys():
return
if "calibration_results" not in kwargs.keys():
return
if "model" not in kwargs.keys():
return
if "dataset" not in kwargs.keys():
return
if "cleaned_dataset" not in kwargs.keys():
return
if "stellar_modeling" not in kwargs.keys():
has_stellar_model = False
else:
has_stellar_model = True
exoplanet_spectrum = kwargs["exoplanet_spectrum"]
calibration_results = kwargs["calibration_results"]
model = kwargs["model"]
dataset = kwargs["dataset"]
cleaned_dataset = kwargs["cleaned_dataset"]
if has_stellar_model:
stellar_modeling = kwargs["stellar_modeling"]
#######################################
# Fit quality and regularization
########################################
sns.set_context("talk", font_scale=2.0, rc={"lines.linewidth": 4.5})
sns.set_style("white", {"xtick.bottom": True, "ytick.left": True})
wavelength_unit = exoplanet_spectrum.spectrum.wavelength_unit
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
ax0.plot(calibration_results.wavelength_normed_fitted_spectrum[0, :],
np.log10(calibration_results.regularization))
ax0.set_xlabel('Wavelength [{}]'.format(wavelength_unit))
ax0.set_ylabel('log10 Alpha')
ax0.set_title("Regularization Strength")
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_calibrate_timeseries_regularization.png"),
bbox_inches="tight")
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
ax0.plot(calibration_results.wavelength_normed_fitted_spectrum[0, :],
np.mean(calibration_results.dof[1:, :], axis=0))
ax0.set_xlabel('Wavelength [{}]'.format(wavelength_unit))
ax0.set_ylabel('DOF')
ax0.set_title("Degrees of Freedom")
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_calibrate_timeseries_dof.png"),
bbox_inches="tight")
sigma_mse_cut = ast.literal_eval(cascade_configuration.cpm_sigma_mse_cut)
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
ax0.plot(calibration_results.wavelength_normed_fitted_spectrum[0, :],
calibration_results.mse[1, :]*10000)
plt.axhline(np.median(calibration_results.mse[1, :]*10000)*sigma_mse_cut,
linestyle='dashed', color='black', label='rejection threshold')
ax0.set_xlabel('Wavelength [{}]'.format(wavelength_unit))
ax0.set_ylabel('MSE [x 10000]')
ax0.set_title("MSE regression fit")
ax0.legend(loc='lower left', fancybox=True, framealpha=1.0,
ncol=1,
bbox_to_anchor=(0, 0.90, 1, 0.2), shadow=True,
handleheight=1.5, labelspacing=0.05,
fontsize=20).set_zorder(11)
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_calibrate_timeseries_mse.png"),
bbox_inches="tight")
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
ax0.plot(calibration_results.wavelength_normed_fitted_spectrum[0, :],
np.mean(calibration_results.aic[1:, :], axis=0))
ax0.set_xlabel('Wavelength [{}]'.format(wavelength_unit))
ax0.set_ylabel('AIC')
ax0.set_title("AIC regression fit")
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_calibrate_timeseries_aic.png"),
bbox_inches="tight")
########################################
# PDF
########################################
from astropy.stats import knuth_bin_width
from scipy.stats import loggamma
sns.set_context("talk", font_scale=2.0, rc={"lines.linewidth": 4.5})
sns.set_style("white", {"xtick.bottom": True, "ytick.left": True})
transittype = model.transittype
depth = (u.Quantity(cascade_configuration.object_radius) /
u.Quantity(cascade_configuration.object_radius_host_star))
depth = depth.decompose().value**2
depth = depth*100
nboot = int(cascade_configuration.cpm_nbootstrap)
spectrum_data_unit = exoplanet_spectrum.spectrum_bootstrap.data_unit
bad_wavelength_mask = exoplanet_spectrum.spectrum_bootstrap.mask
bad_wavelength_mask = \
np.repeat(bad_wavelength_mask[np.newaxis, :],
nboot+1,
axis=0)
normed_spectrum = \
np.ma.array(calibration_results.normed_fitted_spectra.copy(),
mask=bad_wavelength_mask.copy())
if transittype == "secondary":
normed_spectrum = transit_to_eclipse(normed_spectrum)
normed_spectrum.data[...] = normed_spectrum.data*100
mean_norm = np.ma.median(normed_spectrum[1:, :], axis=1)
dx, bins = knuth_bin_width(mean_norm, return_bins=True)
height, bin_edges = np.histogram(mean_norm, bins=bins, density=False)
f = np.sum(height*np.diff(bins))
distribution_function = loggamma
distribution_variables = distribution_function.fit(mean_norm)
TD_min_loggamma, TD_loggamma, TD_max_loggamma = \
distribution_function(*distribution_variables).ppf([0.05, 0.5, 0.95])
TD005, TD, TD095 = exoplanet_spectrum.spectrum_bootstrap.TDDEPTH
x_kde = np.linspace(mean_norm.min(), mean_norm.max(), len(mean_norm))
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
_ = ax0.hist(mean_norm, bins=bins, density=False, alpha=0.5)
ax0.plot(x_kde,
distribution_function(*distribution_variables).pdf(x_kde)*f,
label='log gamma')
ax0.axvline(TD, linestyle='dashed', color='blue', label='Median Depth')
ax0.fill_betweenx([0, height.max()], TD005, TD095, color='g', alpha=0.1,
label='95% confidence')
ax0.set_title("PDF")
if transittype == 'secondary':
ax0.set_xlabel('Fplanet/Fstar [{}]'.format(spectrum_data_unit))
else:
plt.axvline(depth, linestyle='dashed', color='black')
ax0.set_xlabel('Transit Depth [{}]'.format(spectrum_data_unit))
ax0.set_ylabel('Number of bootstrap samples')
ax0.legend(loc='lower left', fancybox=True, framealpha=1.0,
ncol=1,
bbox_to_anchor=(0, 0.90, 1, 0.2), shadow=True,
handleheight=1.5, labelspacing=0.05,
fontsize=20).set_zorder(11)
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_calibrate_timeseries_pdf.png"),
bbox_inches="tight")
# ##################### CDF ###########################
sns.set_context("talk", font_scale=2.0, rc={"lines.linewidth": 6.5})
sns.set_style("white", {"xtick.bottom": True, "ytick.left": True})
ecdf = statsmodels.distributions.ECDF(mean_norm)
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
ax0.plot(x_kde, ecdf(x_kde), label="Empirical CDF")
ax0.plot(x_kde, distribution_function(*distribution_variables).cdf(x_kde),
label="log gamma CDF")
if transittype == 'secondary':
ax0.set_xlabel('Fplanet/Fstar [{}]'.format(spectrum_data_unit))
else:
ax0.set_xlabel('Transit Depth [{}]'.format(spectrum_data_unit))
ax0.set_title("CDF of Band Avaraged Transit Depth")
ax0.set_ylabel('Cumulative Fraction')
ax0.legend(loc='lower left', fancybox=True, framealpha=1.0,
ncol=1,
bbox_to_anchor=(0, 0.80, 1, 0.2), shadow=True,
handleheight=1.5, labelspacing=0.05,
fontsize=20).set_zorder(11)
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_calibrate_timeseries_cdf.png"),
bbox_inches="tight")
# ############# QQ ######################
sns.set_context("talk", font_scale=1.0, rc={"lines.linewidth": 3.5})
sns.set_style("white", {"xtick.bottom": True, "ytick.left": True})
from scipy.stats import probplot
try:
probplot(mean_norm, dist=distribution_function(*distribution_variables),
plot=plt.figure(dpi=200).add_subplot(111))
except ValueError:
pass
plt.title("QQ-plot of mean transit depth")
plt.show()
if save_verbose:
fig.savefig(os.path.join(save_path, save_name_base +
"_calibrate_timeseries_qq.png"),
bbox_inches="tight")
#################################
# Spectrum
#################################
sns.set_context("talk", font_scale=2.0, rc={"lines.linewidth": 3.5})
sns.set_style("white", {"xtick.bottom": True, "ytick.left": True})
transittype = model.transittype
spectrum0 = exoplanet_spectrum.spectrum.return_masked_array('data')
wave0 = exoplanet_spectrum.spectrum.return_masked_array('wavelength')
error0 = exoplanet_spectrum.spectrum.return_masked_array('uncertainty')
spectrum_data_unit = exoplanet_spectrum.spectrum.data_unit
wavelength_unit = exoplanet_spectrum.spectrum.wavelength_unit
spectrum_boot = \
exoplanet_spectrum.spectrum_bootstrap.return_masked_array('data')
wave_boot = \
exoplanet_spectrum.spectrum_bootstrap.return_masked_array('wavelength')
error_boot = \
exoplanet_spectrum.spectrum_bootstrap.return_masked_array('uncertainty')
TD005, TD, TD095 = exoplanet_spectrum.spectrum_bootstrap.TDDEPTH
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
ax0.errorbar(wave_boot, spectrum_boot, yerr=error_boot,
fmt=".", color='brown', lw=5, alpha=0.9, ecolor='brown',
markerfacecolor='brown', label='Bootstrap',
markeredgecolor='brown', fillstyle='full', markersize=15)
ax0.errorbar(wave0, spectrum0, yerr=error0,
fmt=".", color='blue', lw=5, alpha=0.9, ecolor='blue',
markerfacecolor='blue', label='Single fit',
markeredgecolor='blue', fillstyle='full', markersize=15)
plt.axhline(TD, linestyle='dashed', color='black')
plt.fill_between([wave0.data[0], wave0.data[-1]],
TD005, TD095, color='g', alpha=0.1)
if transittype == 'secondary':
ax0.axes.set_ylim([0, 2.5*TD])
ax0.axes.set_xlim([wave0.data[0], wave0.data[-1]])
#ax0.set_ylabel('Fplanet/Fstar [{}]'.format(spectrum_data_unit))
ax0.set_ylabel(f'F$_\mathrm{{p}}$ / F$_\mathrm{{s}}$ '
f'[{spectrum_data_unit.to_string(format="latex")}]')
else:
ax0.axes.set_ylim([TD*0.9, TD*1.1])
ax0.axes.set_xlim([wave0.data[0], wave0.data[-1]])
#ax0.set_ylabel('Transit Depth [{}]'.format(spectrum_data_unit))
ax0.set_ylabel(f'R$^2_\mathrm{{p}}$ / R$^2_\mathrm{{s}}$ '
f'[{spectrum_data_unit.to_string(format="latex")}]')
ax0.set_xlabel(f'Wavelength [{wavelength_unit.to_string(format="latex")}]')
ax0.legend(loc='lower left', fancybox=True, framealpha=1.0,
ncol=1,
bbox_to_anchor=(0, 0.90, 1, 0.2), shadow=True,
handleheight=1.5, labelspacing=0.05,
fontsize=20).set_zorder(11)
plt.show()
if save_verbose:
fig.savefig(
os.path.join(save_path, save_name_base +
"_calibrate_timeseries_exoplanet_spectrum.png"),
bbox_inches="tight")
if transittype == "secondary":
with quantity_support():
mask = copy.deepcopy(exoplanet_spectrum.brightness_temperature.mask)
mask += ~np.isfinite(exoplanet_spectrum.brightness_temperature.
uncertainty.data.value)
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
ax0.errorbar(exoplanet_spectrum.brightness_temperature.
wavelength.data[~mask].to(u.cm**-1,
equivalencies=u.spectral()),
exoplanet_spectrum.brightness_temperature.
data.data[~mask],
yerr=exoplanet_spectrum.brightness_temperature.
uncertainty.data[~mask],
fmt=".", color='blue', lw=5, alpha=0.9, ecolor='blue',
markerfacecolor='blue', markeredgecolor='blue',
fillstyle='full', markersize=20
)
ax0.set_ylabel(f'Brightness Temperature [{ax0.yaxis.units.to_string(format="latex")}]')
ax0.set_xlabel(f'Wavelength [{ax0.xaxis.units.to_string(format="latex")}]')
plt.show()
if save_verbose:
fig.savefig(
os.path.join(save_path, save_name_base +
"_calibrate_timeseries_brightness_temperature_spectrum.png"),
bbox_inches="tight")
####################################
# residual plot
##################################
sns.set_context("talk", font_scale=1.3, rc={"lines.linewidth": 3.5})
sns.set_style("white", {"xtick.bottom": True, "ytick.left": True})
residual_unit = u.percent
image_res = calibration_results.fitted_residuals_bootstrap.data * 100
wave0 = calibration_results.fitted_residuals_bootstrap.wavelength
wavelength_unit = calibration_results.fitted_residuals_bootstrap.wavelength_unit
wave0_min = np.ma.min(wave0).data.value
wave0_max = np.ma.max(wave0).data.value
fig, ax = plt.subplots(figsize=(7, 6), dpi=200)
for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] +
ax.get_xticklabels() + ax.get_yticklabels()):
item.set_fontsize(20)
p = ax.imshow(image_res,
origin='lower',
cmap='hot',
interpolation='nearest',
aspect='auto',
extent=[0, image_res.shape[1], wave0_min, wave0_max])
plt.colorbar(p, ax=ax).set_label("Residual ({})".format(residual_unit))
ax.set_xlabel("Integration Number")
ax.set_ylabel('Wavelength [{}]'.format(wavelength_unit))
ax.set_title('Residual Image')
plt.show()
if save_verbose:
fig.savefig(
os.path.join(save_path, save_name_base +
"_calibrate_timeseries_fit_residual.png"),
bbox_inches="tight")
############################################################
# Systematics model
############################################################
sns.set_context("talk", font_scale=2.0, rc={"lines.linewidth": 5.5})
sns.set_style("white", {"xtick.bottom": True, "ytick.left": True})
TD005, TD, TD095 = exoplanet_spectrum.spectrum_bootstrap.TDDEPTH
systematics_model = calibration_results.fitted_systematics_bootstrap
systematics = systematics_model.return_masked_array('data')
time_systematics = systematics_model.return_masked_array('time')
roi_cube = cleaned_dataset.data.mask
uncal_data = \
dataset.return_masked_array('data').copy()[~np.all(roi_cube,
axis=1), ...]
uncal_data.mask = np.ma.logical_or(uncal_data.mask, systematics.mask)
cal_data = uncal_data/systematics
# Bug Fix
TD_temp = TD/100 # *np.mean(model.limbdarkning_correction)
if transittype == 'secondary':
from cascade.exoplanet_tools import eclipse_to_transit
TD_temp = eclipse_to_transit(TD_temp)
model_lc = np.mean(model.light_curve_interpolated /
model.dilution_correction*TD_temp, axis=0) + 1
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
ax0.plot(np.ma.mean(time_systematics, axis=0),
np.ma.mean(systematics, axis=0), '.',
markersize=20, label='Bootstraped Systematics Model')
ax0.set_xlabel('Orbital Phase')
ax0.set_ylabel('Mean Signal [{}]'.format(systematics_model.data_unit))
ax0.set_title("Band Averaged Instrument Systematics")
ax0.legend(loc='lower left', fancybox=True, framealpha=1.0,
ncol=1,
bbox_to_anchor=(0, 0.23, 1, 0.2), shadow=True,
handleheight=1.5, labelspacing=0.05,
fontsize=20).set_zorder(11)
plt.show()
if save_verbose:
fig.savefig(
os.path.join(save_path, save_name_base +
"_calibrate_timeseries_systematics.png"),
bbox_inches="tight")
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
ax0.plot(np.ma.mean(time_systematics, axis=0),
np.ma.mean(cal_data[:, :], axis=0), '.',
zorder=6, markersize=25, label='Calibrated Data')
ax0.plot(np.ma.mean(time_systematics, axis=0),
np.ma.mean(uncal_data, axis=0)/np.ma.mean(systematics),
'.', zorder=5, markersize=25, label='Uncalibrated Data')
ax0.plot(np.ma.mean(time_systematics, axis=0), model_lc, '.',
zorder=8, markersize=20, label='Fitted Lightcurve Model')
ax0.axes.set_ylim([1-1.3*TD/100, 1+0.8*TD/100])
ax0.set_xlabel('Orbital Phase')
ax0.set_ylabel('Mean Signal [{}]'.format(systematics_model.data_unit))
ax0.set_title("Band Averaged Calibrated Timeseries")
ax0.legend(loc='lower left', fancybox=True, framealpha=1.0,
ncol=1,
bbox_to_anchor=(0, 0.83, 1, 0.2), shadow=True,
handleheight=1.5, labelspacing=0.05,
fontsize=20).set_zorder(11)
plt.show()
if save_verbose:
fig.savefig(
os.path.join(save_path, save_name_base +
"_calibrate_timeseries_calibrated_lightcurve.png"),
bbox_inches="tight")
#########################################################################
# Stellar Spetrum
#########################################################################
if has_stellar_model:
with quantity_support():
scaling = exoplanet_spectrum.flux_calibrated_stellar_model.SCALING
mask = copy.deepcopy(exoplanet_spectrum.flux_calibrated_stellar_spectrum.mask)
fig, axes = plt.subplots(figsize=(18, 12), nrows=1, ncols=1, dpi=200)
ax0 = axes
ax0.errorbar(exoplanet_spectrum.flux_calibrated_stellar_spectrum.
wavelength.data[~mask],
exoplanet_spectrum.flux_calibrated_stellar_spectrum.
data.data[~mask],
yerr=exoplanet_spectrum.flux_calibrated_stellar_spectrum.
uncertainty.data[~mask],
fmt=".", color='brown', lw=5, alpha=0.9, ecolor='brown',
markerfacecolor='brown', markeredgecolor='brown',
fillstyle='full', markersize=20, zorder=7,
label="Observed Stellar Spectrum"
)
ax0.plot(exoplanet_spectrum.flux_calibrated_stellar_model.
wavelength.data[~mask],
exoplanet_spectrum.flux_calibrated_stellar_model.
data.data[~mask]*scaling, label="Stellar Model",
color="b", lw=8, zorder=8)
plt.plot([], [], ' ',
label="Used scaling: {:10.4f}".format(scaling))
ax0.set_ylabel(f'Flux [{ax0.yaxis.units.to_string(format="latex")}]')
ax0.set_xlabel(f'Wavelength [{ax0.xaxis.units.to_string(format="latex")}]')
ax0.set_title("Comparison Model with Observed Stellar Spectrum")
ax0.legend(loc='lower left', fancybox=True, framealpha=1.0,
ncol=1, bbox_to_anchor=(0.1, 0.80, 1, 0.3), shadow=True,
handleheight=1.5, labelspacing=0.05,
fontsize=20).set_zorder(11)
plt.show()
if save_verbose:
fig.savefig(
os.path.join(save_path, save_name_base +
"_calibrate_timeseries_calibrated_stellar_spectrum.png"),
bbox_inches="tight")
####################3
# Check distribution
######################
from scipy import stats
sns.set_context("talk", font_scale=1.0, rc={"lines.linewidth": 2.5})
sns.set_style("white", {"xtick.bottom": True, "ytick.left": True})
def normal(mean, std, histmax=False, color="black", label=''):
x = np.linspace(mean-4*std, mean+4*std, 200)
p = stats.norm.pdf(x, mean, std)
if histmax:
p = p*histmax/max(p)
z = plt.plot(x, p, color, linewidth=2, label=label)
spectrum_boot = \
exoplanet_spectrum.spectrum_bootstrap.return_masked_array('data')
wave_boot = \
exoplanet_spectrum.spectrum_bootstrap.return_masked_array('wavelength')
error_boot = \
exoplanet_spectrum.spectrum_bootstrap.return_masked_array('uncertainty')
indx = (wave_boot > np.ma.min(wave_boot)*1.05) & (wave_boot < np.ma.max(wave_boot)*0.95)
data = spectrum_boot[indx]*1.e4
median_data = np.ma.median(data)
data -= median_data
error = error_boot[indx]*1.e4
av_std = []
for i in range(300):
av_std.append(np.std(np.random.normal(loc=0.0, scale=error)))
av_std = np.mean(av_std)
fig, ax = plt.subplots(figsize=(8, 5), ncols=1, nrows=1, dpi=200)
his = sns.histplot(x=data, stat="probability", ax=ax)
normal(data.mean(), data.std(), histmax=ax.get_ylim()[1],
label=f'Fit to distribution, $\sigma$={data.std(): .2f}')
normal(0.0, av_std, histmax=ax.get_ylim()[1], color='red',
label=f'Expected distribution from errors, $\sigma$={av_std: .2f}')
ax.set_xlabel('Deviation from median depth [ppm]')
ax.legend(loc='upper left', fancybox=False, framealpha=0.5,
ncol=1, bbox_to_anchor=(0.0, 0.01, 1, 1), shadow=False,
handleheight=1.4, labelspacing=0.1,
fontsize=10).set_zorder(11)
plt.show()
if save_verbose:
fig.savefig(
os.path.join(save_path, save_name_base +
"_distribution_from_median_depth.png"),
bbox_inches="tight")
data = np.diff(spectrum_boot[indx]*1.e4)
median_data = np.median(data)
data -= median_data
av_std = []
for i in range(300):
av_std.append(np.std(np.diff(
np.random.normal(loc=0.0, scale=error))))
av_std = np.mean(av_std)
fig, ax = plt.subplots(figsize=(8, 5), ncols=1, nrows=1, dpi=200)
his = sns.histplot(x=data, stat="probability", ax=ax)
normal(data.mean(), data.std(), histmax=ax.get_ylim()[1],
label=f'Fit to distribution, $\sigma$={data.std(): .2f}')
normal(0.0, av_std, histmax=ax.get_ylim()[1], color='red',
label=f'Expected distribution from errors, $\sigma$={av_std: .2f}')
ax.set_xlabel('Pairwise difference [ppm]')
ax.legend(loc='upper left', fancybox=False, framealpha=0.5,
ncol=1, bbox_to_anchor=(0.0, 0.01, 1, 1), shadow=False,
handleheight=1.4, labelspacing=0.1,
fontsize=10).set_zorder(11)
plt.show()
if save_verbose:
fig.savefig(
os.path.join(save_path, save_name_base +
"_pairwise_differences_distribution.png"),
bbox_inches="tight")
[docs]class Verbose:
"""The Class handels verbose output vor the cascade pipeline."""
def __init__(self):
self.verbose_par = _get_plot_parameters()
@property
def __valid_commands(self):
"""
All valid pipeline commands.
This function returns a dictionary with all the valid commands
which can be parsed to the instance of the TSO object.
"""
return {"load_data": load_data_verbose,
"subtract_background": subtract_background_verbose,
"filter_dataset": filter_dataset_verbose,
"determine_source_movement": determine_source_movement_verbose,
"correct_wavelengths": correct_wavelengths_verbose,
"check_wavelength_solution": check_wavelength_solution_verbose,
"set_extraction_mask": set_extraction_mask_verbose,
"extract_1d_spectra": extract_1d_spectra_verbose,
"calibrate_timeseries": calibrate_timeseries_verbose,
}
[docs] def execute(self, command, *args, **kwargs):
"""
Excecute the pipeline commands.
This function checks if a command is valid and excecute it if True.
Parameters
----------
command : `str`
Command to be excecuted. If valid the method corresponding
to the command will be excecuted
Raises
------
ValueError
error is raised if command is not valid
Examples
--------
Example how to run the command to reset a tso object:
>>> vrbs.execute('load_data')
"""
if command not in self.__valid_commands:
raise ValueError("Command not recognized, "
"check your data reduction command for the "
"following valid commands: {}. Aborting "
"command".format(self.__valid_commands.keys()))
self.__valid_commands[command](*args, **kwargs,
verbose_par=self.verbose_par)