Source code for SPCA.make_plots

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm
from matplotlib.ticker import MaxNLocator
from matplotlib import gridspec

import os,sys
lib_path = os.path.abspath(os.path.join('../MCcubed/rednoise/'))
sys.path.append(lib_path)

try:
    from mc3.stats import time_avg
except ImportError:
    print('Warning: time_avg from mc3.stats failed to import. To install it, run the getMCcubed.sh script.')

# SPCA libraries
from . import bliss
from . import helpers


[docs]def plot_photometry(time0, flux0, xdata0, ydata0, psfxw0, psfyw0, time, flux, xdata, ydata, psfxw, psfyw, breaks=[], savepath=None, peritime=''): """Makes a multi-panel plot from photometry outputs. Args: time0 (1D array): Array of time stamps. Discarded points not removed. flux0 (1D array): Array of flux values for each time stamps. Discarded points not removed. xdata0 (1D array): Initial modelled the fluxes for each time stamps. Discarded points not removed. ydata0 (1D array): Initial modelled astrophysical flux variation for each time stamps. Discarded points not removed. psfxw0 (1D array): Point-Spread-Function (PSF) width along the x-direction. Discarded points not removed. psfyw0 (1D array): Point-Spread-Function (PSF) width along the x-direction. Discarded points not removed. time (1D array): Array of time stamps. Discarded points removed. flux (1D array): Array of flux values for each time stamps. Discarded points removed. xdata (1D array): Initial modelled the fluxes for each time stamps. Discarded points removed. ydata (1D array): Initial modelled astrophysical flux variation for each time stamps. Discarded points removed. psfxw (1D array): Point-Spread-Function (PSF) width along the x-direction. Discarded points removed. psfyw (1D array): Point-Spread-Function (PSF) width along the x-direction. Discarded points removed. break (1D array): Time of the breaks from one AOR to another. savepath (string): Path to directory where the plot will be saved pertime (float): Time of periapsis Returns: None or figure if savepath is None """ fig, axes = plt.subplots(5, 1, sharex=True, figsize=(10, 12)) axes[0].plot(time0, flux0, 'r.', markersize=1, alpha = 0.7) axes[0].plot(time, flux, 'k.', markersize=2, alpha = 1.0) axes[0].set_ylabel("Relative Flux $F$") axes[0].set_xlim((np.min(time0), np.max(time0))) axes[1].plot(time0, xdata0, 'r.', markersize=1, alpha = 0.7) axes[1].plot(time, xdata, 'k.', markersize=2, alpha = 1.0) axes[1].set_ylabel("x-centroid $x_0$") axes[2].plot(time0, ydata0, 'r.', markersize=1, alpha = 0.7) axes[2].plot(time, ydata, 'k.', markersize=2, alpha = 1.0) axes[2].set_ylabel("y-centroid $y_0$") axes[3].plot(time0, psfxw0, 'r.', markersize=1, alpha = 0.7) axes[3].plot(time, psfxw, 'k.', markersize=2, alpha = 1.0) axes[3].set_ylabel("x PSF-width $\sigma _x$") axes[4].plot(time0, psfyw0, 'r.', markersize=1, alpha = 0.7) axes[4].plot(time, psfyw, 'k.', markersize=2, alpha = 1.0) axes[4].set_ylabel("y PSF-width $\sigma _y$") axes[4].set_xlabel('Time (BMJD)') for i in range(5): for j in range(len(breaks)): axes[i].axvline(x=breaks[j], color ='k', alpha=0.3, linestyle = 'dashed') fig.subplots_adjust(hspace=0) if savepath!=None: pathplot = savepath + '01_Raw_data.pdf' fig.savefig(pathplot, bbox_inches='tight') plt.close() return else: return fig
[docs]def plot_centroids(xdata0, ydata0, xdata, ydata, savepath=''): """Makes a multi-panel plot from photometry outputs. Args: xdata0 (1D array): Initial modelled the fluxes for each time stamps. Discarded points not removed. ydata0 (1D array): Initial modelled astrophysical flux variation for each time stamps. Discarded points not removed. xdata (1D array): Initial modelled the fluxes for each time stamps. Discarded points removed. ydata (1D array): Initial modelled astrophysical flux variation for each time stamps. Discarded points removed. savepath (string): Path to directory where the plot will be saved Returns: None or figure if savepath is None """ fig = plt.figure(figsize=(6, 6)) ax = plt.gca() ax.set_title('Distribution of centroids') ax.plot(xdata0, ydata0, 'r.', markersize=1, alpha = 0.7) ax.plot(xdata, ydata, 'k.', markersize=2, alpha = 1.0) ax.set_ylabel("$y$") ax.set_xlabel("$x$") fig.subplots_adjust(hspace=0) if savepath is not None: pathplot = savepath + 'Centroids.pdf' fig.savefig(pathplot, bbox_inches='tight') plt.close() return else: return fig
[docs]def plot_knots(xdata, ydata, flux, astroModel, knot_nrst_lin, tmask_good_knotNdata, knots_x, knots_y, knots_x_mesh, knots_y_mesh, nBin, knotNdata, savepath=None): '''Plot the Bliss map''' fB_avg = bliss.map_flux_avgQuick(flux, astroModel, knot_nrst_lin, nBin, knotNdata) delta_xo, delta_yo = knots_x[1] - knots_x[0], knots_y[1] - knots_y[0] star_colrs = knotNdata[tmask_good_knotNdata] plt.figure(figsize=(12,6)) plt.subplot(121) plt.scatter(xdata, ydata,color=(0,0,0),alpha=0.2,s=2,marker='.') plt.gca().set_aspect((knots_x[-1]-knots_x[0])/(knots_y[-1]-knots_y[0])) plt.xlabel('Pixel x',size='x-large'); plt.ylabel('Pixel y',size='x-large'); plt.title('Knot Mesh',size='large') plt.xlim([knots_x[0] - 0.5*delta_xo, knots_x[-1] + 0.5*delta_xo]) plt.ylim([knots_y[0] - 0.5*delta_yo, knots_y[-1] + 0.5*delta_yo]) plt.locator_params(axis='x',nbins=8) plt.locator_params(axis='y',nbins=8) my_stars = plt.scatter(knots_x_mesh[tmask_good_knotNdata], knots_y_mesh[tmask_good_knotNdata], c=star_colrs, cmap=matplotlib.cm.Purples, edgecolor='k',marker='*',s=175,vmin=1) plt.colorbar(my_stars, label='Linked Centroids',shrink=0.75) plt.scatter(knots_x_mesh[tmask_good_knotNdata == False], knots_y_mesh[tmask_good_knotNdata == False], color=(1,0.75,0.75), marker='x',s=35) legend = plt.legend(('Centroids','Good Knots','Bad Knots'), loc='lower right',bbox_to_anchor=(0.975,0.025), fontsize='small',fancybox=True) legend.legendHandles[1].set_color(matplotlib.cm.Purples(0.67)[:3]) legend.legendHandles[1].set_edgecolor('black') if savepath!=None: pathplot = savepath+'BLISS_Knots.pdf' plt.savefig(pathplot, bbox_inches='tight') plt.close() return else: return plt.gcf()
[docs]def plot_init_guess(time, data, astro, detec_full, savepath=None): """Makes a multi-panel plots for the initial light curve guesses. Args: time (1D array): Time stamps. data (1D array): Flux values for each time stamps. astro (1D array): Initial modelled astrophysical flux variation for each time stamps. detec_full (1D array): Initial modelled flux variation due to the detector for each time stamps. savepath (str): Path to directory where the plot will be saved. Returns: None or figure if savepath is None """ fig, axes = plt.subplots(nrows=4, ncols=1, sharex=True, figsize=(10,9)) axes[0].plot(time, data, '.', label='data') axes[0].plot(time, astro*detec_full, '.', label='guess') axes[1].plot(time, data/detec_full, '.', label='Corrected') axes[1].plot(time, astro, '.', label='Astrophysical') axes[2].plot(time, data/detec_full, '.', label='Corrected') axes[2].plot(time, astro, '.', label='Astrophysical') axes[2].set_ylim(0.998, 1.005) axes[3].plot(time, data/detec_full-astro, '.', label='residuals') axes[3].axhline(y=0, linewidth=2, color='black') axes[0].set_ylabel('Relative Flux') axes[2].set_ylabel('Relative Flux') axes[2].set_xlabel('Time (BMJD)') axes[0].legend(loc=3) axes[1].legend(loc=3) axes[2].legend(loc=3) axes[3].legend(loc=3) axes[3].set_xlim(np.min(time), np.max(time)) fig.subplots_adjust(hspace=0) if savepath is not None: pathplot = savepath + '02_Initial_Guess.pdf' fig.savefig(pathplot, bbox_inches='tight') plt.close() return else: return fig
[docs]def plot_bestfit(x, flux, astro, detec, mode, breaks, savepath=None, showplot=True, peritime=-np.inf, nbin=None, fontsize=10): if nbin is not None: x_binned, _ = helpers.binValues(x, x, nbin) calibrated_binned, calibrated_binned_err = helpers.binValues(flux/detec, x, nbin, assumeWhiteNoise=True) residuals_binned, residuals_binned_err = helpers.binValues(flux/detec-astro, x, nbin, assumeWhiteNoise=True) fig, axes = plt.subplots(ncols = 1, nrows = 4, sharex = True, figsize=(8, 14)) axes[0].set_xlim(np.nanmin(x), np.nanmax(x)) axes[0].plot(x, flux, '.', color = 'k', markersize = 4, alpha = 0.15) axes[0].plot(x, astro*detec, '.', color = 'r', markersize = 2.5, alpha = 0.4) axes[0].set_ylabel('Raw Flux', fontsize=fontsize) axes[1].plot(x, flux/detec, '.', color = 'k', markersize = 4, alpha = 0.15) axes[1].plot(x, astro, color = 'r', linewidth=2) if nbin is not None: axes[1].errorbar(x_binned, calibrated_binned, yerr=calibrated_binned_err, fmt='.', color = 'blue', markersize = 10, alpha = 1) axes[1].set_ylabel('Calibrated Flux', fontsize=fontsize) axes[2].axhline(y=1, color='k', linewidth = 2, linestyle='dashed', alpha = 0.5) axes[2].plot(x, flux/detec, '.', color = 'k', markersize = 4, alpha = 0.15) axes[2].plot(x, astro, color = 'r', linewidth=2) if nbin is not None: axes[2].errorbar(x_binned, calibrated_binned, yerr=calibrated_binned_err, fmt='.', color = 'blue', markersize = 10, alpha = 1) axes[2].set_ylabel('Calibrated Flux', fontsize=fontsize) axes[2].set_ylim(ymin=1-3*np.nanstd(flux/detec - astro)) axes[3].plot(x, flux/detec - astro, 'k.', markersize = 4, alpha = 0.15) axes[3].axhline(y=0, color='r', linewidth = 2) if nbin is not None: axes[3].errorbar(x_binned, residuals_binned, yerr=residuals_binned_err, fmt='.', color = 'blue', markersize = 10, alpha = 1) axes[3].set_ylabel('Residuals', fontsize=fontsize) axes[3].set_xlabel('Time (BMJD)', fontsize=fontsize) for i in range(len(axes)): axes[i].xaxis.set_tick_params(labelsize=fontsize) axes[i].yaxis.set_tick_params(labelsize=fontsize) axes[i].axvline(x=peritime, color ='C1', alpha=0.8, linestyle = 'dashed') for j in range(len(breaks)): axes[i].axvline(x=(breaks[j]), color ='k', alpha=0.3, linestyle = 'dashed') fig.align_ylabels() fig.subplots_adjust(hspace=0) if savepath is not None: plotname = savepath + 'MCMC_'+mode+'_2.pdf' fig.savefig(plotname, bbox_inches='tight') plt.close(fig) return else: return fig
[docs]def plot_rednoise(residuals, minbins, ingrDuration, occDuration, intTime, mode, savepath=None, showplot=True, showtxt=True, savetxt=False, fontsize=10): maxbins = int(np.rint(residuals.size/minbins)) rms, rmslo, rmshi, stderr, binsz = time_avg(residuals, maxbins) plt.clf() ax = plt.gca() ax.set_yscale('log') ax.set_xscale('log') ax.errorbar(binsz, rms, yerr=[rmslo, rmshi], fmt="k-", ecolor='0.5', capsize=0, label="Data RMS") ax.plot(binsz, stderr, c='red', label="Gaussian std.") ylim = ax.get_ylim() ax.plot([ingrDuration,ingrDuration],ylim, color='black', ls='--', alpha=0.6) ax.plot([occDuration,occDuration],ylim, color='black', ls='-.', alpha=0.6) ax.set_ylim(ylim) ax.xaxis.set_tick_params(labelsize=fontsize) ax.yaxis.set_tick_params(labelsize=fontsize) plt.xlabel(r'N$_{\rm binned}$', fontsize=fontsize) plt.ylabel('RMS', fontsize=fontsize) plt.legend(loc='best', fontsize=fontsize) if savepath is not None: plotname = savepath + 'MCMC_'+mode+'_RedNoise.pdf' plt.savefig(plotname, bbox_inches='tight') if showplot: plt.show() plt.close() #Ingress Duration sreal = rms[np.where(binsz<=ingrDuration)[0][-1]]*1e6 s0 = stderr[np.where(binsz<=ingrDuration)[0][-1]]*1e6 outStr = 'Over Ingress ('+str(round(ingrDuration*intTime*24*60, 1))+' min):\n' outStr += 'Expected Noise (ppm)\t'+'Observed Noise (ppm)\n' outStr += str(s0)+'\t'+str(sreal)+'\n' outStr += 'Observed/Expected\n' outStr += str(sreal/s0)+'\n\n' #Occultation Duration sreal = rms[np.where(binsz<=occDuration)[0][-1]]*1e6 s0 = stderr[np.where(binsz<=occDuration)[0][-1]]*1e6 outStr += 'Over Transit/Eclipse ('+str(round(occDuration*intTime*24*60, 1))+' min):\n' outStr += 'Expected Noise (ppm)\t'+'Observed Noise (ppm)\n' outStr += str(s0)+'\t'+str(sreal)+'\n' outStr += 'Observed/Expected\n' outStr += str(sreal/s0) if showtxt: print(outStr) if savetxt: fname = savepath + 'MCMC_'+mode+'_RedNoise.txt' with open(fname,'w') as file: file.write(outStr) return
[docs]def triangle_colors(all_data, firstEcl_data, transit_data, secondEcl_data, fname=None): """Make a triangle plot like figure to help look for any residual correlations in the data. Args: all_data (list): A list of the all of the xdata, ydata, psfxw, psfyw, flux, residuals. firstEcl_data (list): A list of the xdata, ydata, psfxw, psfyw, flux, residuals during the first eclipse. transit_data (list): A list of the xdata, ydata, psfxw, psfyw, flux, residuals during the transit. secondEcl_data (list): A list of the xdata, ydata, psfxw, psfyw, flux, residuals during the second eclipse. fname (string, optional): The savepath for the plot (or None if you want to return the figure instead). Returns: None or figure if name is None """ label = [r'$x_0$', r'$y_0$', r'$\sigma _x$', r'$\sigma _y$', r'$F$', r'Residuals'] fig = plt.figure(figsize = (8,8)) gs = gridspec.GridSpec(len(all_data)-1,len(all_data)-1) i = 0 for k in range(np.sum(np.arange(len(all_data)))): j= k - np.sum(np.arange(i+1)) ax = fig.add_subplot(gs[i,j]) ax.plot(all_data[j], all_data[i+1],'k.', markersize = 0.2) l1 = ax.plot(firstEcl_data[j], firstEcl_data[i+1],'.', color = '#66ccff', markersize = 0.7, label='$1^{st}$ secondary eclipse') l2 = ax.plot(transit_data[j], transit_data[i+1],'.', color = '#ff9933', markersize = 0.7, label='transit') l3 = ax.plot(secondEcl_data[j], secondEcl_data[i+1],'.', color = '#0066ff', markersize = 0.7, label='$2^{nd}$ secondary eclipse') if (j == 0): plt.setp(ax.get_yticklabels(), rotation = 45) ax.yaxis.set_major_locator(MaxNLocator(5, prune = 'both')) ax.set_ylabel(label[i+1]) else: plt.setp(ax.get_yticklabels(), visible=False) if (i == len(all_data)-2): plt.setp(ax.get_xticklabels(), rotation = 45) plt.axhline(y=0, color='k', linestyle='dashed') ax.xaxis.set_major_locator(MaxNLocator(5, prune = 'both')) ax.set_xlabel(label[j]) else: plt.setp(ax.get_xticklabels(), visible=False) if(i == j): i += 1 handles = [l1,l2,l3] fig.subplots_adjust(hspace=0) fig.subplots_adjust(wspace=0) if fname is not None: fig.savefig(fname, bbox_inches='tight') plt.close(fig) return else: return fig