In [ ]:
%matplotlib inline
%load_ext autoreload
%autoreload 2

In [ ]:
# import batman
import corner
# import datetime
# import emcee3
import emcee
# import jdcal
from os import environ, path
import pywt
# import spiderman as sp

from batman    import TransitModel, TransitParams
from spiderman import ModelParams as sp_ModelParams

from functools import partial
from pylab     import *
from pandas    import DataFrame

from scipy.spatial           import cKDTree
from sklearn.externals       import joblib
from sklearn.model_selection import train_test_split
from sklearn.decomposition   import PCA, FastICA

from astropy.io import fits
from glob import glob


from tqdm import tqdm_notebook

# from scipy.optimize    import leastsq, minimize
from scipy.interpolate import CubicSpline
# from scipy.signal      import medfilt
# from scipy.stats       import binned_statistic

from lmfit import Parameters, Minimizer, report_errors

from statsmodels.robust.scale import mad
from sklearn.preprocessing    import scale

from time import time

# from sys import argv

# from photutils import CircularAperture, CircularAnnulus, EllipticalAperture
# from photutils import aperture_photometry

# from statsmodels.robust import scale
from datetime import datetime

from exoparams import PlanetParams

from numpy import cos, pi, abs

# from sklearn.svm import SVR
from sklearn.cluster import DBSCAN

from sklearn.preprocessing import StandardScaler

from multiprocessing import cpu_count, Pool

from astropy.constants import R_sun, au

from wanderer import wanderer

from spitzer_helper_functions import clipOutliers, bin_array, b2inc, deltaphase_eclipse
from spitzer_helper_functions import extract_PLD_components, de_median, savePickleOut, spiderman_lmfit_model
from spitzer_helper_functions import phase_cos_curve, phase_cos_sin_curve, inc2b, batman_lmfit_model
# from spitzer_helper_functions import pixel_level_decorrelation_instrument_profile

stdScaler = StandardScaler()
stime = time()

In [ ]:
from matplotlib import rcParams
rcParams["savefig.dpi"] = 200
rcParams["figure.dpi"] = 200

In [ ]:
print("\n**DONE LOADING LIBRARIES AND DEFINING FUNCTIONS**\n")

List of Function Definitions


In [ ]:
def batman_lmfit_model(period, tCenter, inc, aprs, edepth, tdepth, ecc, omega, times, u1=None, u2=None,
                       ldtype = 'uniform', transittype="primary", bm_params=None):
    
    if tdepth is not 0.0 or edepth is not 0.0:
        if bm_params is None:
            bm_params = TransitParams() # object to store transit parameters
        
        bm_params.per       = period  # orbital period
        bm_params.t0        = tCenter # time of inferior conjunction
        bm_params.a         = aprs    # semi-major axis (in units of stellar radii)
        bm_params.fp        = edepth  # f
        bm_params.tdepth    = tdepth  # from Fraine et al. 2014s
        bm_params.rp        = sqrt(tdepth) # planet radius (in units of stellar radii)
        bm_params.ecc       = ecc     # eccentricity
        bm_params.w         = omega   # longitude of periastron (in degrees)
        bm_params.inc       = inc     # orbital inclination (in degrees)
        bm_params.limb_dark = ldtype  # limb darkening model # NEED TO FIX THIS
        bm_params.u         = []      # limb darkening coefficients # NEED TO FIX THIS
        
        if u1 is not None and ldtype is not 'uniform':
            bm_params.u.append(u1)
        elif u1 is not None and ldtype is 'uniform':
            raise ValueError('If you set `u1`, you must also set `ldtype` to either linear or quadratic')
        if u2 is not None and ldtype is 'quadratic':
            bm_params.u.append(u2)
        elif u2 is not None and ldtype is not 'quadratic':
            raise ValueError('If you set `u2`, you must also set `ldtype` quadratic')
        
        bm_params.delta_phase = deltaphase_eclipse(bm_params.ecc, bm_params.w) if bm_params.ecc is not 0.0 else 0.5
        bm_params.t_secondary = bm_params.t0 + bm_params.per*bm_params.delta_phase
        
        m_eclipse = TransitModel(bm_params, times, transittype=transittype).light_curve(bm_params)
    else:
        return ones(times.size)
    
    return m_eclipse

In [ ]:
def spiderman_lmfit_model(period, tCenter, inc, aprs, tdepth, ecc, omega, times, u1, u2, xi, T_night, delta_T, 
                         nspiders=1000, nCores = cpu_count(),
                         spider_params=None, n_layers=20, stellar_radius = 1.0, stellar_temperature=5500.,
                         wave_low = 4.0, wave_hi = 5.0, brightness_model='zhang', if_eclipse=False):
    
    if tdepth is not 0.0:
        # if spider_params is None:
        #     spider_params                = sp_ModelParams(brightness_model=brightness_model)
        #     spider_params.n_layers       = n_layers
        #     spider_params.stellar_radius = stellar_radius
        #     spider_params.T_s            = stellar_temperature
        #     spider_params.l1             = wave_low
        #     spider_params.l2             = wave_hi
        #     spider_params.eclipse        = if_eclipse
        
        a_au  = aprs * spider_params.stellar_radius * R_sun.value / au.value
        # inc   = b2inc(bImpact, aprs, ecc, omega)*180/pi
        
        spider_params.t0      = tCenter      # Central time of PRIMARY transit [days]
        spider_params.per     = period       # Period [days]
        spider_params.a_abs   = a_au         # The absolute value of the semi-major axis [AU]
        spider_params.inc     = inc # orbital inclination (in degrees)
        spider_params.ecc     = ecc          # Eccentricity
        spider_params.w       = omega        # Argument of periastron
        spider_params.rp      = sqrt(tdepth) # planet radius (in units of stellar radii)
        spider_params.a       = aprs         # Semi-major axis scaled by stellar radius
        spider_params.p_u1    = u1           # Planetary limb darkening parameter
        spider_params.p_u2    = u2           # Planetary limb darkening parameter
        
        spider_params.xi      = xi           # Ratio of radiative to advective timescale             
        spider_params.T_n     = T_night      # Temperature of nightside
        spider_params.delta_T = delta_T      # Day-night temperature contrast
        
        nskips            = times.size // nspiders
        times_subsampled  = times[::nskips]
        spider_lightcurve = spider_params.lightcurve(times_subsampled)
        spider_lightcurve = CubicSpline(times_subsampled, spider_lightcurve)
        
        return spider_lightcurve(times)
    else:
        return ones(times.size)
    
    raise Exception('Something Weird happened')

In [ ]:
def find_qhull_one_point(point, x0, y0, np0, inds, sm_num):
    # ind         = kdtree.query(kdtree.data[point],sm_num+1)[1][1:]
    ind = inds[point]
    dx  = x0[ind] - x0[point]
    dy  = y0[ind] - y0[point]
    
    if np0.sum() != 0.0:
        dnp         = np0[ind] - np0[point]
    
    sigx  = np.std(dx )
    sigy  = np.std(dy )
    
    if dnp.sum() != 0.0:
                
        signp   = np.std(dnp)
        gw_temp = np.exp(-dx**2./(2.0*sigx**2.)) * \
                      np.exp(-dy**2./(2.*sigy**2.))  * \
                      np.exp(-dnp**2./(2.*signp**2.))
    else:
        gw_temp = np.exp(-dx**2./(2.0*sigx**2.)) * \
                  np.exp(-dy**2./(2.*sigy**2.))
    
    gw_sum  = gw_temp.sum()
    
    return gw_temp/gw_sum#, ind

In [ ]:
def mp_find_nbr_qhull(xpos, ypos, npix = None, inds = None, n_nbr = 50, returnInds=False,
                      a = 1.0, b = 0.7, c = 1.0, expansion = 1000., nCores=cpu_count()):
    '''
        Python Implimentation of N. Lewis method, described in Lewis etal 2012, Knutson etal 2012, Fraine etal 2013
        
        Taken from N. Lewis IDL code:
            
            Construct a 3D surface (or 2D if only using x and y) from the data
            using the qhull.pro routine.  Save the connectivity information for
            each data point that was used to construct the Delaunay triangles (DT)
            that form the grid.  The connectivity information allows us to only
            deal with a sub set of data points in determining nearest neighbors
            that are either directly connected to the point of interest or
            connected through a neighboring point
        
        Python Version:
            J. Fraine    first edition, direct translation from IDL 12.05.12
    '''
    #The surface fitting performs better if the data is scattered about zero
    if npix is not None and bool(c):
        np0 = np.sqrt(npix)
        np0 = (np0 - np.median(np0))/c
        features  = np.transpose((y0, x0, np0))
    else:
        features  = np.transpose((y0, x0))
        
        if np.sum(np0) == 0.0:
            print('SKIPPING Noise Pixel Sections of Gaussian Kernel because Noise Pixels are Zero')
        if c == 0:
            print('SKIPPING Noise Pixel Sections of Gaussian Kernel because c == 0')
    
    x0  = (xpos - np.median(xpos))/a
    y0  = (ypos - np.median(ypos))/b
    
    k   = sm_num                           # This is the number of nearest neighbors you want
    n   = x0.size                          # This is the number of data points you have
    gw  = np.zeros((k,n),dtype=np.float64) # This is the gaussian weight for each data point determined from the nearest neighbors
    
    if inds is None:
        kdtree    = cKDTree(features * expansion) #Multiplying `features` by 1000.0 avoids precision problems
        inds      = kdtree.query(kdtree.data, n_nbr+1)[1][:,1:]
        
        print('WARNING: Because `inds` was not provided, we must now compute and return it here')
        returnInds= True
    
    func  = partial(find_qhull_one_point, x0=x0, y0=y0, np0=np0, inds=inds, sm_num=sm_num)
    
    pool  = Pool(nCores)
    
    gw_pool = pool.starmap(func, zip(range(n)))
    
    pool.close()
    pool.join()
    
    if returnInds:
        return np.array(gw_pool), inds
    else:
        return np.array(gw_pool)

In [ ]:
from scipy.spatial      import cKDTree

def find_nbr_qhull(xpos, ypos, npix, sm_num = 100, a = 1.0, b = 0.7, c = 1.0, print_space = 10000.):
    '''
        Python Implimentation of N. Lewis method, described in Lewis etal 2012, Knutson etal 2012, Fraine etal 2013
        
        Taken from N. Lewis IDL code:
            
            Construct a 3D surface (or 2D if only using x and y) from the data
            using the qhull.pro routine.  Save the connectivity information for
            each data point that was used to construct the Delaunay triangles (DT)
            that form the grid.  The connectivity information allows us to only
            deal with a sub set of data points in determining nearest neighbors
            that are either directly connected to the point of interest or
            connected through a neighboring point
        
        Python Version:
            J. Fraine    first edition, direct translation from IDL 12.05.12
    '''
    from scipy import spatial
    #The surface fitting performs better if the data is scattered about zero
    
    npix    = np.sqrt(npix)
    
    x0  = (xpos - np.median(xpos))/a
    y0  = (ypos - np.median(ypos))/b
    
    if np.sum(npix) != 0.0 and c != 0:
        np0 = (npix - np.median(npix))/c
    else:
        if np.sum(npix) == 0.0:
            print('SKIPPING Noise Pixel Sections of Gaussian Kernel because Noise Pixels are Zero')
        if c == 0:
            print('SKIPPING Noise Pixel Sections of Gaussian Kernel because c == 0')
    
    k            = sm_num                           # This is the number of nearest neighbors you want
    n            = x0.size                          # This is the number of data points you have
    nearest      = np.zeros((k,n),dtype=np.int64)   # This stores the nearest neighbors for each data point
    
    #Multiplying by 1000.0 avoids precision problems
    if npix.sum() != 0.0 and c != 0:
        kdtree  = cKDTree(np.transpose((y0*1000., x0*1000., np0*1000.)))
    else:
        kdtree  = cKDTree(np.transpose((y0*1000., x0*1000.)))
    
    gw  = np.zeros((k,n),dtype=np.float64) # This is the gaussian weight for each data point determined from the nearest neighbors
    
    start   = time()
    for point in tqdm_notebook(range(n),total=n):
        ind         = kdtree.query(kdtree.data[point],sm_num+1)[1][1:]
        dx          = x0[ind] - x0[point]
        dy          = y0[ind] - y0[point]
        
        if npix.sum() != 0.0 and c != 0:
            dnp         = np0[ind] - np0[point]
        
        sigx        = np.std(dx )
        sigy        = np.std(dy )
        if npix.sum() != 0.0 and c != 0:
            signp       = np.std(dnp)
        if npix.sum() != 0.0 and c != 0:
            gw_temp     = np.exp(-dx**2./(2.0*sigx**2.)) * \
                          np.exp(-dy**2./(2.*sigy**2.))  * \
                          np.exp(-dnp**2./(2.*signp**2.))
        else:
            gw_temp     = np.exp(-dx**2./(2.0*sigx**2.)) * \
                          np.exp(-dy**2./(2.*sigy**2.))
        
        gw_sum      = gw_temp.sum()
        gw[:,point] = gw_temp/gw_sum
        
        #if (gw_sum == 0.0) or ~np.isfinite(gw_sum):
        #    raise Exception('(gw_sum == 0.0) or ~isfinite(gw_temp))')
        
        nearest[:,point]  = ind
    
    return gw.transpose(), nearest.transpose() # nearest  == nbr_ind.transpose()

In [ ]:
def pixel_level_decorrelation_instrument_profile(times, input_features, 
                              pld1_l, pld2_l, pld3_l, pld4_l, pld5_l, pld6_l, pld7_l, pld8_l, pld9_l,
                              pld1_q, pld2_q, pld3_q, pld4_q, pld5_q, pld6_q, pld7_q, pld8_q, pld9_q):# ,
                              # intcpt=1.0, slope=0.0, crvtur=0.0):
    
    feature_coeffs   = [pld1_l, pld2_l, pld3_l, pld4_l, pld5_l, pld6_l, pld7_l, pld8_l, pld9_l, \
                        pld1_q, pld2_q, pld3_q, pld4_q, pld5_q, pld6_q, pld7_q, pld8_q, pld9_q]
    
    instrumental  = dot(input_features, feature_coeffs) # This is now quadratic
    
    return instrumental

In [ ]:
def clipOutlier2D(arr2D, nSig=10):
    arr2D     = arr2D.copy()
    medArr2D  = median(arr2D,axis=0)
    sclArr2D  = np.sqrt(((mad(arr2D)**2.).sum()))
    outliers  = abs(arr2D - medArr2D) >  nSig*sclArr2D
    inliers   = abs(arr2D - medArr2D) <= nSig*sclArr2D
    arr2D[outliers] = median(arr2D[inliers],axis=0)
    return arr2D

In [ ]:
def plot_MAD_AperRads(instance, minRad=None, maxRad=None, varRadFlag=True):
    color_cycle = cycler(rcParams['axes.prop_cycle']).by_key()['color']
    
    quad_width= instance.quadrature_widths.values
    vrad_dist = quad_width - np.median(quad_width)
    vrad_dist = clipOutlier2D(vrad_dist, nSig=5)
    vrad_dist_med = np.median(vrad_dist)
    
    betaColor = 7
    quadColor = 8
    
    ax = figure().add_subplot(111)
    
    for key in instance.flux_TSO_df.keys():
        staticRad = float(key.split('_')[-2])
        varRad    = float(key.split('_')[-1])
        aperRad   = staticRad + varRad*vrad_dist_med
        colorNow  = color_cycle[int(varRad*4)]
        
        if 'betaRad' in key:
            aperRad    = median(sqrt(instance.effective_widths))
            colorNow  = color_cycle[int(betaColor)]
        
        if 'quadRad' in key:
            aperRad   = 2*sqrt(2*log(2))*median(instance.quadrature_widths.values)
            colorNow  = color_cycle[int(quadColor)]
        
        if minRad is not  None and maxRad is not None:
            if aperRad > minRad and aperRad < maxRad:
                ax.scatter(aperRad, mad(np.diff(instance.flux_TSO_df[key])), color=colorNow, zorder=int(varRad*4))
        else:
            ax.scatter(aperRad, mad(np.diff(instance.flux_TSO_df[key])), color=colorNow, zorder=int(varRad*4))
    
    for varRad in [0.,0.25, 0.5, 0.75, 1.0, 1.25, 1.5]:
        colorNow  = color_cycle[int(varRad*4)]
        ax.scatter([],[], color=colorNow, label=varRad)
    
    ax.scatter([],[],color=color_cycle[int(betaColor)], label='Beta')
    ax.scatter([],[],color=color_cycle[int(quadColor)], label='Quad')
    
    ax.set_xlabel('StaticRad + Average(varRad)')
    ax.set_ylabel('MAD( Diff ( Flux ) )')
    ax.legend(loc=0,fontsize=10)
    
    ax.set_title('' if not hasattr(instance, '__name__') else instance.__name__)

In [ ]:
def plot_model_over_reduced_lc_half_PLDsq_universal(times, phots, phots_err, input_features, in_eclipse, fit_values,
                                                    spider_params = None, refTime=0.0, figsize=None, nbins=200, 
                                                    plotRawData=False, alpha=1.0, phase_method='fourier', 
                                                    baseline='PLD',ax = None, returnAx = False, 
                                                    model_color=0, data_color=1):
    
    color_cycle = cycler(rcParams['axes.prop_cycle']).by_key()['color']
    model_color = color_cycle[model_color] if isinstance(model_color, int) else model_color
    data_color  = color_cycle[data_color]  if isinstance(data_color , int) else data_color 
    
    # print('model:{}\tdata:{}'.format(model_color, data_color))
    
    clean_model = model_selector(fit_values, times, input_features, in_eclipse, spider_params=spider_params, 
                                 phase_method=phase_method, baseline=baseline, model_only=True)
    
    model_params_keys = np.sort(list(fit_values.keys()))
    
    feature_coeffs  = [fit_values[key].value for key in model_params_keys if 'pld' in key and '_l' in key] + \
                      [fit_values[key].value for key in model_params_keys if 'pld' in key and '_q' in key]
    
    # Check if line fit parameters exist, then allocate them; or use defaults
    intcpt  = fit_values['intcpt'] if 'intcpt' in fit_values.keys() else 1.0
    slope   = fit_values['slope']  if 'slope'  in fit_values.keys() else 0.0
    crvtur  = fit_values['crvtur'] if 'crvtur' in fit_values.keys() else 0.0
    
    instrumental = intcpt * np.ones(times.size)
    if slope  != 0.0:
        instrumental += slope * (times-times.mean())
    if crvtur != 0.0:
        instrumental += crvtur * (times-times.mean())**2.
    
    if baseline == 'PLD':
        instrumental += pixel_level_decorrelation_instrument_profile(times, input_features, 
                        *feature_coeffs)#, intcpt=intcpt, slope=slope, crvtur=crvtur)
    
    if baseline == 'KRData':
        phots_now, gk, nbr_ind = input_features
        instrumental *= np.sum((phots_now/clean_model)[nbr_ind]*gk,axis=1)
    
    # clean_model  = whole_model / instrumental 
    
    binsize = phots.size // nbins
    
    reduced = phots/instrumental
    diff_dm = 0.0#np.median(reduced - clean_model)
    
    print('Diff DM: {:0f}'.format(diff_dm*ppm))
    
    bin_flux    , _ = bin_array((reduced - diff_dm), binsize=binsize)
    bin_flux_err, _ = bin_array(phots_err, binsize=binsize)
    
    bin_time    , _  = bin_array(times, binsize=binsize)
    
    bin_flux_err     = bin_flux_err/sqrt(binsize)
    
    if ax is None:
        fig= figure() if figsize is None else figure(figsize=figsize)
        ax = fig.add_subplot(111)
    
    if plotRawData:
        ax.plot(times, phots/ instrumental, '.', ms=1, label='data', alpha=alpha)
    
    ingress   = np.where(in_eclipse)[0].min()
    egress    = np.where(in_eclipse)[0].max()
    IT_mean   = np.mean([clean_model[ingress:egress]])
    gap       = IT_mean - 1.0
    
    print('Gap: {:0f}'.format(gap*ppm))
    
    ax.errorbar(bin_time-refTime, bin_flux    - gap, bin_flux_err, color=color_cycle[0], \
                    fmt='o', label='binned data', ms=1, zorder=0, lw=1,alpha=alpha)
    ax.plot(times-refTime, clean_model - gap, color=color_cycle[1], \
                lw=2,label='best fit model', zorder=1)
    
    ax.legend(loc=0)
    
    # ax.axhline(1.0, ls='--', lw=0.5)
    
    if returnAx:
        return ax

In [ ]:
def plot_model_over_reduced_lc_full_PLDsq_universal(times_0, times_1, phots_0, phots_1, phots_err_0, phots_err_1, 
                                                    input_features_0, input_features_1, in_eclipse_0, in_eclipse_1, 
                                                    fit_values, refTime=0.0, planetName='', figsize=None, 
                                                    nbins=200, alpha=1.0, plotRawData=False, 
                                                    phase_method='fourier', baseline='PLD', 
                                                    ax = None, returnAx = False, model_color=0, data_color=1):
    
    none_to_inf  = lambda x, sign=1: sign*np.inf if x is None else x
    
    _params_names = ['period', 'tCenter', 'inc', 'aprs', 'edepth', 'tdepth', 'ecc', 'omega', 'u1', 'u2', 
                     'amp1', 'amp2', 'amp3', 'amp4', 'amp5', 'amp6', 'amp7', 'amp8', # 'mean', 
                     'pld1_l', 'pld2_l', 'pld3_l', 'pld4_l', 'pld5_l', 'pld6_l', 'pld7_l', 'pld8_l', 'pld9_l', 
                     'pld1_q', 'pld2_q', 'pld3_q', 'pld4_q', 'pld5_q', 'pld6_q', 'pld7_q', 'pld8_q', 'pld9_q']#, 
                     # 'intcpt', 'slope', 'crvtur']
    
    fit_values_0 = Parameters()
    fit_values_1 = Parameters()
    
    for pname in _params_names:
        if 'pld' not in pname:
            valu = fit_values[pname].value
            vary = fit_values[pname].vary
            rmin = none_to_inf(fit_values[pname].min, -1)
            rmax = none_to_inf(fit_values[pname].max,  1)
            
            fit_values_0.add(pname, valu, vary, rmin, rmax)
            fit_values_1.add(pname, valu, vary, rmin, rmax)
        else:
            pname_0 = pname + '_1'
            valu = fit_values[pname_0].value
            vary = fit_values[pname_0].vary
            rmin = none_to_inf(fit_values[pname_0].min, -1)
            rmax = none_to_inf(fit_values[pname_0].max,  1)
            
            fit_values_0.add(pname, valu, vary, rmin, rmax)
            
            pname_1 = pname + '_2'
            valu = fit_values[pname_1].value
            vary = fit_values[pname_1].vary
            rmin = none_to_inf(fit_values[pname_1].min, -1)
            rmax = none_to_inf(fit_values[pname_1].max,  1)
            fit_values_1.add(pname, valu, vary, rmin, rmax)
    
    fit_values_0['mean'] = fit_values['mean_0']
    fit_values_1['mean'] = fit_values['mean_1']
    
    # nPeriods = int((times_0.mean() - fit_values_0['tCenter'])/fit_values_0['period'])
    
    ax_0 = plot_model_over_reduced_lc_half_PLDsq_universal(times_0, phots_0, phots_err_0,
                                                           input_features_0, in_eclipse_0, 
                                                           fit_values_0, refTime=refTime, 
                                                           figsize=figsize, nbins=nbins, plotRawData=plotRawData,
                                                           phase_method=phase_method, baseline=baseline,
                                                           ax = ax, returnAx = True, alpha=alpha, 
                                                           model_color=model_color, data_color=data_color)
    
    ax_0.set_title(planetName + ' E-depth: {:.0f}'.format(fit_values['edepth'].value*ppm))
    
    return plot_model_over_reduced_lc_half_PLDsq_universal(times_1, phots_1, phots_err_1,
                                                           input_features_1, in_eclipse_1, 
                                                           fit_values_1, refTime=refTime, alpha=alpha,  
                                                           figsize=figsize, nbins=nbins, plotRawData=plotRawData,
                                                           phase_method=phase_method, baseline=baseline, 
                                                           ax = ax_0, returnAx = returnAx,
                                                           model_color=model_color, data_color=data_color)

EMCEE Setup


In [ ]:
def create_prior(params):
    """
    emccee uses a uniform prior for every variable.
    Here we create a functions which checks the bounds
    and returns np.inf if a value is outside of its
    allowed range. WARNING: A uniform prior may not be
    what you want!
    """
    none_to_inf  = lambda x, sign=1: sign*np.inf if x is None else x
    lower_bounds = np.array([none_to_inf(i.min, -1) for i in params.values() if i.vary])
    upper_bounds = np.array([none_to_inf(i.max,  1) for i in params.values() if i.vary])
    
    def bounds_prior(values):
        values = np.asarray(values)
        is_ok = np.all((lower_bounds < values) & (values < upper_bounds))
        return 0 if is_ok else -np.inf
    
    return bounds_prior

def create_lnliklihood(mini, sigma=None):
    """create a normal-likihood from the residuals"""
    def lnprob(vals, sigma=sigma):
        for v, p in zip(vals, [p for p in mini.params.values() if p.vary]):
            p.value = v
        
        # residuals = mini.residual
        
        if not sigma:
            # sigma is either the RMS estimate or it will
            # be part of the sampling.
            sigma = vals[-1]
        
        val = -0.5*np.sum(np.log(2*np.pi*sigma**2) + (partial_residuals(mini.params)/sigma)**2)
        
        return val
    
    return lnprob

def starting_guess(mini, estimate_sigma=True):
    """
    Use best a fit as a starting point for the samplers.
    If no sigmas are given, it is assumed that
    all points have the same uncertainty which will
    be also part of the sampled parameters.
    """
    vals = [i.value for i in mini.params.values() if i.vary]
    
    if estimate_sigma:
        vals.append(mini.residual.std())
    
    return vals

def create_all(mini, sigma=None):
    """
    creates the log-poposterior function from a minimizer.
    sigma should is either None or an array with the
    1-sigma uncertainties of each residual point. If None,
    sigma will be assumed the same for all residuals and
    is added to the sampled parameters.
    """
    sigma_given = not sigma is None
    
    lnprior = create_prior(mini.params)
    lnprob  = create_lnliklihood(mini, sigma=sigma)
    guess   = starting_guess(mini, not sigma_given)
    
    if sigma_given:
        func = lambda x: lnprior(x[:]) + lnprob(x)
    else:
        func = lambda x: lnprior(x[:-1]) + lnprob(x)
    
    return func, guess

In [ ]:
def model_selector(model_params, times, input_features, in_eclipse, 
                   spider_params=None, phase_method='fourier', 
                   baseline = 'PLD', simple=False, model_only=False):
    """Identifies the phase curve + noise model to use from `method`, allocates 
        then model specific params and returns the model
    
    Args:
        model_params    : set of model parmaeters  -- named to avoid global / local confusion
        times           : temporal array to use with model
        input_features  : basis vectors for linear fitting to noise array
        in_eclipse      : boolean array to identify the eclipse location from initial guess
        method          : string to identify if residuals should be taken over 
                            `fourier` or `spiderman` phase curve models
    
    Returns:
        Returns the current model, which is phase_curve x transit x eclipse x normalization
    """
    
    # Grab list of pld1..9 linear, then add list of pld1..9 quadratic
    model_params_keys      = np.sort(list(model_params.keys()))
    
    feature_coeffs  = [model_params[key].value for key in model_params_keys if 'pld' in key and '_l' in key] + \
                      [model_params[key].value for key in model_params_keys if 'pld' in key and '_q' in key]
    
    # Check if line fit parameters exist, then allocate them; or use defaults
    intcpt  = model_params['intcpt'].value if 'intcpt' in model_params.keys() else 1.0
    slope   = model_params['slope'].value  if 'slope'  in model_params.keys() else 0.0
    crvtur  = model_params['crvtur'].value if 'crvtur' in model_params.keys() else 0.0
    
    # Transit Parameters
    period  = model_params['period'].value
    tCenter = model_params['tCenter'].value
    inc     = model_params['inc'].value
    aprs    = model_params['aprs'].value
    edepth  = model_params['edepth'].value
    tdepth  = model_params['tdepth'].value
    ecc     = model_params['ecc'].value
    omega   = model_params['omega'].value
    u1      = model_params['u1'].value
    u2      = model_params['u2'].value
    
    delta_phase = deltaphase_eclipse(ecc, omega) if ecc is not 0.0 else 0.5
    t_secondary = tCenter + period*delta_phase
    
    # Create phase curve model -- including PLD noise parameters
    if phase_method == 'spiderman':
        # Siderman Phase Curve Parameters
        xi      = model_params['xi'].value
        T_night = model_params['T_night'].value
        delta_T = model_params['delta_T'].value
        mean    = model_params['mean'].value
        
        spider_model  = partial(spiderman_lmfit_model, period=period, tCenter=tCenter, inc=inc, aprs=aprs, 
                                           tdepth=tdepth, ecc=ecc, omega=omega, u1=u1, u2=u2, 
                                           spider_params=spider_params, 
                                           xi=xi, T_night=T_night, delta_T=delta_T, if_eclipse=False)
        
        phase_curve   = spider_model(times=times) + mean
    
    if phase_method == 'fourier':
        mean = model_params['mean'].value
        amp1 = model_params['amp1'].value
        amp2 = model_params['amp2'].value
        amp3 = model_params['amp3'].value
        amp4 = model_params['amp4'].value
        # amp5 = model_params['amp5'].value
        # amp6 = model_params['amp6'].value
        # amp7 = model_params['amp7'].value
        # amp8 = model_params['amp8'].value
        
        angphase       = 2 * pi / period * (times-t_secondary)
        
        phase_curve   = mean + amp1*cos(angphase)   \
                             + amp2*sin(angphase)   \
                             + amp3*cos(2*angphase) \
                             + amp4*sin(2*angphase) # \
                             # + amp5*cos(4*angphase) \
                             # + amp6*sin(4*angphase) \
                             # + amp7*cos(6*angphase) \
                             # + amp8*sin(6*angphase)  
    
    if phase_method == 'kbs':
        mean = model_params['mean'].value
        amp1 = model_params['amp1'].value
        amp2 = model_params['amp2'].value
        
        angphase      = 2 * pi / period * (times - t_secondary - amp2)
        phase_curve   = mean + amp1*cos(angphase)
    
    instrumental = intcpt * np.ones(times.size)
    if slope  != 0.0:
        instrumental += slope * (times-times.mean())
    if crvtur != 0.0:
        instrumental += crvtur * (times-times.mean())**2.
    
    batman_model  = partial(batman_lmfit_model, period=period, tCenter=tCenter, inc=inc, aprs=aprs  , 
                                       times=times, edepth=edepth, tdepth=tdepth  , ecc=ecc, omega=omega)
    
    transit       = batman_model(transittype="primary"  , ldtype='quadratic', u1=u1, u2=u2)
    eclipse       = batman_model(transittype="secondary", ldtype='uniform') - edepth
    
    # eclipse_1     = (eclipse == 1 - edepth)#*()
    # eclipse_2     = (eclipse == 1 - edepth)#*()
    # in_eclipse    = eclipse != 1# - edepth
    #if in_eclipse.any():
    #    # midpoint = int(np.where(in_eclipse)[0].mean())
    #    phase_curve[eclipse_1] = 1.0#phase_curve[in_eclipse]#np.mean([phase_curve[in_eclipse]])#eclipse[in_eclipse]#
    
    phase_curve[eclipse == 1.0 - edepth] = 1.0#np.mean(phase_curve[eclipse == 1.0 - edepth])
    clean_model = transit * eclipse * phase_curve
    
    if baseline == 'PLD':
        instrumental += pixel_level_decorrelation_instrument_profile(times, input_features, 
                        *feature_coeffs)#, intcpt=intcpt, slope=slope, crvtur=crvtur)
    
    if baseline == 'KRData':
        phots_now, gk, nbr_ind = input_features
        instrumental *= np.sum((phots_now/clean_model)[nbr_ind]*gk,axis=1)
    
    if model_only:
        return clean_model
    else:
        return clean_model * instrumental

In [ ]:
def residuals_func(model_params, data, times, input_features, in_eclipse, simple=True, 
                   spider_params=None, phase_method='fourier', baseline='PLD'):
    """Returns residuals of current model estimate with input `data`
    
    Args:
        model_params    : set of model parmaeters  -- named to avoid global / local confusion
        data            : data to be fit
        times           : temporal array to use with model
        input_features  : basis vectors for linear fitting to noise array
        in_eclipse      : boolean array to identify the eclipse location from initial guess
        method          : string to identify if residuals should be taken over 
                            `fourier` or `spiderman` phase curve models
    
    Returns:
        Returns the array of residuals, that is the data - model
    """
    # Return residuals between this model and the `data` allocated above
    model_now = model_selector(model_params, times, input_features, in_eclipse, 
                               spider_params, phase_method, baseline, simple=simple)
    return model_now - data

In [ ]:
def load_aor_from_phot_pipeline(planet_dir_name, channel, AORNow, PLD_order=1):
    loadfiledir         = environ['HOME']+'/Research/Planets/PhaseCurves/'+planet_dir_name+'/saveFiles/' + channel 
    loadFileNameHeader  = planet_dir_name+'_'+ AORNow +'_Median'
    loadFileType        = '.pickle.save'
    
    print()
    print('Loading from ' + loadfiledir + loadFileNameHeader + loadFileType)
    print()
    
    instance = wanderer(fitsFileDir=loadfitsdir, filetype=filetype, telescope='Spitzer', 
                                                yguess=yguess, xguess=xguess, method='median', nCores=cpu_count())
    
    instance.load_data_from_save_files(savefiledir=loadfiledir, \
                                                      saveFileNameHeader=loadFileNameHeader,\
                                                      saveFileType='.pickle.save')
    
    if PLD_order > 1: instance.extract_PLD_components(order=PLD_order)
    
    timeCubeLocal       = instance.timeCube
    photsLocal          = instance.flux_TSO_df.values
    PLDFeatureLocal     = instance.PLD_components.T
    
    try:
        inliers_Phots_local = instance.inliers_Phots.values()
    except:
        inliers_Phots_local = np.ones(photsLocal.shape)
    
    try:
        inliers_PLD_local = instance.inliers_PLD.values()
    except:
        inliers_PLD_local = np.ones(PLDFeatureLocal.shape)
    
    return timeCubeLocal, photsLocal, PLDFeatureLocal, inliers_Phots_local, inliers_PLD_local, instance

Load Planet Params


In [ ]:
ppm             = 1e6
y,x             = 0,1

yguess, xguess  = 15., 15.   # Specific to Spitzer circa 2010 and beyond
filetype        = 'bcd.fits' # Specific to Spitzer Basic Calibrated Data

Starting Position


In [ ]:
planet_params_name = 'Planet-Name b'# 'HAT-P-23 b'# 
planet_dir_name    = 'planetName'# 'hat23'# 
channel = 'ch1/'

if   'ch1' in channel:
    spitzer_waves_low  = 3.0
    spitzer_waves_high = 4.0
elif 'ch2' in channel:
    spitzer_waves_low  = 4.0
    spitzer_waves_high = 5.0
else:
    raise Exception("`channel` must be either `'ch1'` or `'ch2'`")

In [ ]:
np.random.randint?

In [ ]:
planet_params = PlanetParams(planet_params_name)

iPeriod   = planet_params.per.value
iTCenter  = planet_params.tt.value-2400000.5
# iBImpact  = planet_params.b.value
iApRs     = planet_params.ar.value
iInc      = planet_params.i.value
# iRsAp     = 1.0/planet_params.ar.value
iEdepth   = 3000/ppm # blind guess
iTdepth   = planet_params.depth.value
iEcc      = planet_params.ecc.value
iOmega    = planet_params.om.value*pi/180

stellar_radius = planet_params.rstar.value
stellar_temp   = planet_params.teff.value

Pixel Level Decorrelation


In [ ]:
planetDirectory = '/Research/Planets/PhaseCurves/'

dataSub = 'bcd/'

dataDir     = environ['HOME'] + planetDirectory + planet_dir_name + '/data/raw/' + channel + '/big/'
print(dataDir + '*')
AORs = []
for dirNow in glob(dataDir + '*'):
    AORs.append(dirNow.split('/')[-1])

fileExt = '*bcd.fits'
uncsExt = '*bunc.fits'

iAOR        = 1
AORNow      = AORs[iAOR]
loadfitsdir = dataDir + AORNow + '/' + channel + dataSub
print(loadfitsdir)

In [ ]:
timeCubeStack       = {}
photsStack          = {}
PLDFeatureStack     = {}
inliers_PhotsStack  = {}
inliers_PLDStack    = {}
instanceStack       = {}

for AORNow in AORs:
    timesNow, photsNow, PLDFeaturesNow, inliers_PhotsNow, inliers_PLDNow, instanceNow = \
        load_aor_from_phot_pipeline(planet_dir_name, channel, AORNow, PLD_order=2)
                                
    timeCubeStack[AORNow]       = timesNow
    photsStack[AORNow]          = photsNow
    PLDFeatureStack[AORNow]     = PLDFeaturesNow
    inliers_PhotsStack0[AORNow] = inliers_PhotsNow
    inliers_PLDStack[AORNow]    = inliers_PLDNow
    instanceStack[AORNow]       = instanceNow
for aor_now in instanceStack.keys(): print('Working on AOR {}'.format(aorNow)) instanceStack[aor_now].mp_lmfit_gaussian_centering()
for aor_now in instanceStack.keys(): print('Saving `example_wanderer_median` to a set of pickles for various Image Cubes and the Storage Dictionary') savefiledir = environ['HOME']+'/Research/Planets/PhaseCurves/'+planet_dir_name+'/SaveFiles/' + channel saveFileNameHeader = planet_dir_name+'_'+ aor_now +'_Median' saveFileType = '.pickle.save' if not path.exists(environ['HOME']+'/Research/Planets/PhaseCurves/'+planet_dir_name+'/SaveFiles/'): mkdir(environ['HOME']+'/Research/Planets/PhaseCurves/'+planet_dir_name+'/SaveFiles/') if not path.exists(savefiledir): print('Creating ' + savefiledir) mkdir(savefiledir) print() print('Saving to ' + savefiledir + saveFileNameHeader + saveFileType) print() instanceStack[aor_now].save_data_to_save_files(savefiledir=savefiledir, \ saveFileNameHeader=saveFileNameHeader, \ saveFileType=saveFileType)

In [ ]:
# Gaussian_Fit_AnnularMask_rad_1.0_0.0

staticRad   = '2.0'
varRad      = '0.0'
phot_select = np.where(instance_0.flux_TSO_df.keys() == 'Gaussian_Fit_AnnularMask_rad_'+staticRad+'_'+varRad)[0][0]

In [ ]:
try:
    aor_0, aor_1 = timeCubeStack.keys();
except:
    aor_0, aor_1, aor_2 = timeCubeStack.keys();
    print('NEED TO ADJUST FOR 3 AORs')

if timeCubeStack[aor_0].min() > timeCubeStack[aor_1].min():
    print('Reversing AOR Labels to be Time Ordered')
    aor_0, aor_1 = aor_1, aor_0

In [ ]:
inliersMaster = {}
inliersMaster[aor_0]  = array(list(inliers_PhotsStack0[aor_0])).all(axis=0) # Need to Switch `axis=0` for Planet-Name
inliersMaster[aor_1]  = array(list(inliers_PhotsStack0[aor_1])).all(axis=0) # Need to Switch `axis=0` for Planet-Name

inliersMaster[aor_0]  = inliersMaster[aor_0] * inliers_PLDStack[aor_0].all(axis=1)
inliersMaster[aor_1]  = inliersMaster[aor_1] * inliers_PLDStack[aor_1].all(axis=1)

In [ ]:
instance_0  = instanceStack[aor_0]
instance_1  = instanceStack[aor_1]

instance_0.__name__ = aor_0
instance_1.__name__ = aor_1

In [ ]:
nSig=6
for aorNow in inliersMaster.keys():
    if inliersMaster[aorNow].all():
        print('Working on AOR {}'.format(aorNow))
        cy_now, cx_now        = instanceStack[aorNow].centering_GaussianFit.T
        phots_now             = photsStack[aorNow][:,phot_select]
        phots_clipped         = clipOutlier2D(phots_now, nSig=nSig)
        cy_clipped, cx_clipped= clipOutlier2D(transpose([cy_now, cx_now]),nSig=nSig).T
        arr2D_clipped         = transpose([phots_clipped, cy_clipped, cx_clipped])
        inliersMaster[aorNow] = (phots_clipped == phots_now)*(cy_clipped==cy_now)*(cx_clipped==cx_now)

In [ ]:
times_0 = timeCubeStack[aor_0]#[inliersMaster[aor_0]]
times_1 = timeCubeStack[aor_1]#[inliersMaster[aor_1]]

phots_0 = photsStack[aor_0][:, phot_select]#[inliersMaster[aor_0], phot_select]
phots_1 = photsStack[aor_1][:, phot_select]#[inliersMaster[aor_1], phot_select]

PLDfeatures_0 = PLDFeatureStack[aor_0]#[inliersMaster[aor_0]]
PLDfeatures_1 = PLDFeatureStack[aor_1]#[inliersMaster[aor_1]]

phots_0_err = np.sqrt(abs(phots_0))
phots_1_err = np.sqrt(abs(phots_1))

In [ ]:
y_centers_stack = hstack([instance_0.centering_GaussianFit.T[y][inliersMaster[aor_0]], \
                          instance_1.centering_GaussianFit.T[y][inliersMaster[aor_1]]])
x_centers_stack = hstack([instance_0.centering_GaussianFit.T[x][inliersMaster[aor_0]], \
                          instance_1.centering_GaussianFit.T[x][inliersMaster[aor_1]]])

# planetName_range_ch2 = [[15.65,15.95],[15.85,16.15]]
# planetName_range_ch1 = [[15.25,16.0],[15.95,16.2]]
wasp77_range_ch1 = [[14.9,15.25],[14.95,15.3]]
plt.hist2d(x_centers_stack, y_centers_stack, bins=50, cmap=plt.cm.jet);#, range=wasp77_range_ch1);

In [ ]:
# plt.plot(*(transpose([instance_0.centering_GaussianFit.T[x],instance_0.centering_GaussianFit.T[y]])).T,'.',ms=1,alpha=0.25);
plt.plot(*(transpose([instance_0.centering_GaussianFit.T[x][inliersMaster[aor_0]],\
                      instance_0.centering_GaussianFit.T[y][inliersMaster[aor_0]]])).T,'.',ms=1,alpha=0.25);
plt.plot(*(transpose([instance_1.centering_GaussianFit.T[x][inliersMaster[aor_1]],\
                      instance_1.centering_GaussianFit.T[y][inliersMaster[aor_1]]])).T,'.',ms=1,alpha=0.25);

Setup Initial Parameters


In [ ]:
init_eclipse_params = TransitParams()

init_eclipse_params.per         = iPeriod
init_eclipse_params.t0          = iTCenter#+0.0025
init_eclipse_params.inc         = iInc
init_eclipse_params.a           = iApRs
init_eclipse_params.fp          = iEdepth
init_eclipse_params.rp          = sqrt(iTdepth)
init_eclipse_params.ecc         = iEcc
init_eclipse_params.w           = iOmega

init_eclipse_params.delta_phase = deltaphase_eclipse(init_eclipse_params.ecc, init_eclipse_params.w) \
                                    if init_eclipse_params.ecc is not 0.0 else 0.5
init_eclipse_params.t_secondary = init_eclipse_params.t0 + init_eclipse_params.per*init_eclipse_params.delta_phase

# init_eclipse_params.t_secondary = init_eclipse_params.t0 + iPeriod * 0.5
init_eclipse_params.limb_dark   = 'uniform'
init_eclipse_params.u           = []

In [ ]:
init_1st_eclipse_model          = TransitModel(init_eclipse_params, times_0, transittype="secondary")
init_1st_eclipse_lightcurve     = init_1st_eclipse_model.light_curve(init_eclipse_params)

init_1st_transit_model          = TransitModel(init_eclipse_params, times_0, transittype="primary")
init_1st_transit_lightcurve     = init_1st_transit_model.light_curve(init_eclipse_params)

In [ ]:
in_1st_eclipse = init_1st_eclipse_lightcurve == 1

In [ ]:
(in_1st_eclipse == (init_1st_eclipse_lightcurve == init_1st_transit_lightcurve)).all()

In [ ]:
skip = 1000
plot(photsStack[aor_0][:,phot_select]);
plot(np.arange(phots_0.shape[0])[skip:], phots_0[skip:],'.',ms=2);
plot(np.arange(phots_0.shape[0])[:skip], phots_0[:skip],'.',ms=2);

med_phots_0 = median(phots_0[inliersMaster[aor_0]])
std_phots_0 = std(phots_0[inliersMaster[aor_0]])

plot(np.arange(init_1st_eclipse_lightcurve.size), init_1st_transit_lightcurve*med_phots_0);
plot(np.arange(init_1st_eclipse_lightcurve.size), init_1st_eclipse_lightcurve*med_phots_0);
plot(np.arange(init_1st_eclipse_lightcurve.size)[in_1st_eclipse], \
     init_1st_eclipse_lightcurve[in_1st_eclipse]*med_phots_0);

ylim(med_phots_0 - 5*std_phots_0, med_phots_0 + 5*std_phots_0);

Choose to Skip First ~30 Minutes or Not


In [ ]:
SKIP_30_MIN = False
if SKIP_30_MIN:
    nskip   = 1000 # with 2s integrations, 1000 frames ~ 33 minutes
    inliersMaster[aor_0][:nskip] = False
pca = PCA() ica = FastICA()
pca_pld_0 = pca.fit_transform(PLDfeatures_0) ica_pld_0 = ica.fit_transform(PLDfeatures_0) pca_scl_pld_0 = pca.fit_transform(scale(PLDfeatures_0)) ica_scl_pld_0 = ica.fit_transform(scale(PLDfeatures_0)) ica_pca_pld_0 = ica.fit_transform(pca_pld_0) pca_ica_pld_0 = pca.fit_transform(ica_pld_0) ica_pca_scl_pld_0 = ica.fit_transform(pca_scl_pld_0) pca_ica_scl_pld_0 = pca.fit_transform(ica_scl_pld_0)
input_feature_set_0 = PLDfeatures_0 # input_feature_set_0 = scale(PLDfeatures_0) # input_feature_set_0 = pca_pld_0 # input_feature_set_0 = ica_pld_0 # input_feature_set_0 = pca_scl_pld_0 # input_feature_set_0 = ica_scl_pld_0 # input_feature_set_0 = ica_pca_pld_0 # input_feature_set_0 = pca_ica_pld_0 # input_feature_set_0 = ica_pca_scl_pld_0 # input_feature_set_0 = pca_ica_scl_pld_0

In [ ]:
ypos_0, xpos_0  = clipOutlier2D(transpose([instance_0.centering_GaussianFit.T[y][inliersMaster[aor_0]], \
                                           instance_0.centering_GaussianFit.T[x][inliersMaster[aor_0]]])).T
                                          # instance_0.centering_GaussianFit[inliersMaster[aor_0]].T
ypos_1, xpos_1  = clipOutlier2D(transpose([instance_1.centering_GaussianFit.T[y][inliersMaster[aor_1]], \
                                           instance_1.centering_GaussianFit.T[x][inliersMaster[aor_1]]])).T
                                          # instance_1.centering_GaussianFit[inliersMaster[aor_1]].T

npix_0          = sqrt(instance_0.effective_widths[inliersMaster[aor_0]])
npix_1          = sqrt(instance_1.effective_widths[inliersMaster[aor_1]])

In [ ]:
fig = figure(figsize=(30,10));
ax1 = fig.add_subplot(1,3,1);
ax2 = fig.add_subplot(1,3,2);
ax3 = fig.add_subplot(1,3,3);
ax1.plot(xpos_0, ypos_0,'.',ms=1,alpha=0.25);
ax2.plot(xpos_0, npix_0,'.',ms=1,alpha=0.25);
ax3.plot(ypos_0, npix_0,'.',ms=1,alpha=0.25);
ax1.plot(xpos_1, ypos_1,'.',ms=1,alpha=0.25);
ax2.plot(xpos_1, npix_1,'.',ms=1,alpha=0.25);
ax3.plot(ypos_1, npix_1,'.',ms=1,alpha=0.25);
start = time() gw_0, nbr_0 = mp_find_nbr_qhull(xpos_0, ypos_0, npix_0, sm_num = 100, a = 1.0, b = 0.7, c = 1.0, print_space = 10000., nCores=cpu_count()) print(time() - start)
start = time() gw_1, nbr_1 = mp_find_nbr_qhull(xpos_1, ypos_1, npix_1, sm_num = 100, a = 1.0, b = 0.7, c = 1.0, print_space = 10000., nCores=cpu_count()) print(time() - start)
gw_0, nbr_0 = find_nbr_qhull(xpos_0, ypos_0, npix_0, sm_num = 100, a = 1.0, b = 0.7, c = 1.0, print_space = 10000.)
gw_1, nbr_1 = find_nbr_qhull(xpos_1, ypos_1, npix_1, sm_num = 100, a = 1.0, b = 0.7, c = 1.0, print_space = 10000.)

In [ ]:
xpos_c  = np.hstack([xpos_0, xpos_1])
ypos_c  = np.hstack([ypos_0, ypos_1])
npix_c  = np.hstack([npix_0, npix_1])

In [ ]:
start = time()
gw_c, nbr_c = mp_find_nbr_qhull(xpos_c, ypos_c, npix_c, sm_num = 100, a = 1.0, b = 0.7, c = 1.0, print_space = 10000.)
print(time() - start)
gw_c, nbr_c = find_nbr_qhull(xpos_c, ypos_c, npix_c, sm_num = 100, a = 1.0, b = 0.7, c = 1.0, print_space = 10000.)

In [ ]:
color_cycle = cycler(rcParams['axes.prop_cycle']).by_key()['color']

In [ ]:
med_eclipse_1 = median(phots_0[in_1st_eclipse == 1.0])
coeffs = pywt.wavedec(phots_0 / med_eclipse_1, 'db4', level=1)

In [ ]:
i_u1, i_u2 = 0.1, 0.1
xi_0, T_night_0, delta_T_0 = 1e-5, 750.0, 500.0

SPIDERMAN Fitting Procedure Fit Spiderman Model with PLD to 1st AOR


In [ ]:
spider_params_hoststar                = sp_ModelParams(brightness_model='zhang')
spider_params_hoststar.n_layers       = 20
spider_params_hoststar.stellar_radius = stellar_radius
spider_params_hoststar.T_s            = stellar_temp
spider_params_hoststar.l1             = spitzer_waves_low  # Spitzer IRAC-1 or IRAC-2
spider_params_hoststar.l2             = spitzer_waves_high # Spitzer IRAC-1 or IRAC-2

stellar_a_au  = iApRs * stellar_radius * R_sun.value / au.value

spider_params_hoststar.t0      = iTCenter       # Central time of PRIMARY transit [days]
spider_params_hoststar.per     = iPeriod        # Period [days]
spider_params_hoststar.a_abs   = stellar_a_au   # The absolute value of the semi-major axis [AU]
spider_params_hoststar.inc     = iInc          # orbital inclination (in degrees)
spider_params_hoststar.ecc     = iEcc          # Eccentricity
spider_params_hoststar.w       = iOmega        # Argument of periastron
spider_params_hoststar.rp      = sqrt(iTdepth) # planet radius (in units of stellar radii)
spider_params_hoststar.a       = iApRs         # Semi-major axis scaled by stellar radius
spider_params_hoststar.p_u1    = i_u1          # Planetary limb darkening parameter
spider_params_hoststar.p_u2    = i_u2          # Planetary limb darkening parameter

spider_params_hoststar.eclipse = False
spider_params_hoststar.xi      = 0.0           # Ratio of radiative to advective timescale             
spider_params_hoststar.T_n     = 1000.0        # Temperature of nightside
spider_params_hoststar.delta_T = 500.0         # Day-night temperature contrast

Global Fitting Procedure

initialParams_KRData_half_Fourier_PhaseCurve_ch2 = initialParams_KRData_half_Fourier_PhaseCurve del initialParams_KRData_half_Fourier_PhaseCurve

In [ ]:
i_u1, i_u2, iEdepth = 0.1, 0.0, 2000/ppm
xi_0, T_night_0, delta_T_0 = 1e-5, 750.0, 500.0

initialParams_KRData_half_Fourier_PhaseCurve = Parameters()

# c1a, c1o, c = 7.8915e-04, 2.9006e-02, 1.0000e+00

initialParams_KRData_half_Fourier_PhaseCurve.add_many(
    # Planetary Parameters
    ('period' , iPeriod  , False),
    ('tCenter', iTCenter+0.00565 , True , iTCenter-0.01, iTCenter+0.02),
    ('inc'    , iInc     , False, 0.0 ,  90.),
    ('aprs'   , iApRs    , False, 0.0 , 100.),
    ('edepth' , iEdepth  , True , 0.0 , 1.0 ),
    ('tdepth' , iTdepth  , True , 0.0 , 1.0 ),
    ('ecc'    , 0.0     , False , 0.0 , 1.0 ),
    ('omega'  , iOmega   , False, 0.0 , 360.),
    ('u1'     , i_u1     , False, 0.0 , 1.0 ),
    ('u2'     , i_u2     , False, 0.0 , 1.0 ),
    ('amp1'   , 1e-3     , True ),
    ('amp2'   , 1e-3     , True ), # for non-KBS only
    # ('amp2'   , 1e-4     , True , 0.0, 0.25*iPeriod ), # for KBS only
    ('amp3'   , 1e-4    , True ),
    ('amp4'   , 1e-4    , True ),
    ('amp5'   , 0.0      , False),
    ('amp6'   , 0.0      , False),
    ('amp7'   , 0.0      , False),
    ('amp8'   , 0.0      , False),
    ('mean'   , 1.0      , False),
    ('xi'     , xi_0     , False, 0.0, inf),
    ('delta_T', delta_T_0, False, 0.0, inf),
    ('T_night', T_night_0, False, 0.0, inf),
    # Out of transit linear baselines
    ('intcpt' , 1.0      , True ),
    ('slope'  , 0.0      , True ),
    ('crvtur' , 0.0      , False)
)

Test KR-Data on Whole System


In [ ]:
phots_c = np.hstack([phots_0[inliersMaster[aor_0]], phots_1[inliersMaster[aor_1]]])
times_c = np.hstack([times_0[inliersMaster[aor_0]], times_1[inliersMaster[aor_1]]])
# phots_c = np.hstack([phots_0, phots_1])
# times_c = np.hstack([times_0, times_1])

In [ ]:
phase_method   = 'fourier'
baseline       = 'KRData'
partial_residuals = partial(residuals_func, 
                            data           = phots_c / median(phots_c),
                            times          = times_c, 
                            input_features = [phots_c / median(phots_c), gw_c, nbr_c],#input_feature_set_c, 
                            in_eclipse     = in_1st_eclipse,
                            spider_params  = spider_params_hoststar,
                            phase_method   = phase_method,
                            baseline       = baseline)

In [ ]:
mini = Minimizer(partial_residuals, initialParams_KRData_half_Fourier_PhaseCurve)
#fitResults_KRData_half_Fourier_PhaseCurve.params)#
start = time()
fitResults_KRData_half_Fourier_PhaseCurve = mini.leastsq()
print("Full phase curve fitting operation took {} seconds".format(time()-start))

In [ ]:
report_errors(fitResults_KRData_half_Fourier_PhaseCurve.params)

In [ ]:
var_i_care = ['edepth', 'ecc', 'omega', 'amp1', 'amp2', 'amp3', 'amp4', 'amp5', 'amp6', 'amp7', 'amp8']
ppm_or_not = [ppm, 1.0, 1.0, ppm, ppm, ppm,ppm, ppm, ppm, ppm, ppm]
unit_list  = ['ppm', ' ', 'deg', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm']

for varname in var_i_care:
    if varname in fitResults_KRData_half_Fourier_PhaseCurve.var_names:
        print('{}:\t{:.0f}\tppm'.format(varname, fitResults_KRData_half_Fourier_PhaseCurve.params[varname]*ppm))

print('mean-1:\t{:.0f}\tppm'.format((fitResults_KRData_half_Fourier_PhaseCurve.params['mean']-1)*ppm))

In [ ]:
ax = plot_model_over_reduced_lc_half_PLDsq_universal(times_c, 
                                                phots_c / median(phots_c), 
                                                sqrt(phots_c) / median(phots_c), 
                                                # input_feature_set_c, 
                                                [phots_c / median(phots_c), gw_c, nbr_c], 
                                                in_1st_eclipse, 
                                                # initialParams_KRData_half_Fourier_PhaseCurve, 
                                                fitResults_KRData_half_Fourier_PhaseCurve.params,
                                                spider_params=spider_params_hoststar,
                                                figsize=None, nbins=200, plotRawData=False,
                                                phase_method=phase_method, baseline=baseline,
                                                ax = None, returnAx = True)

ax.set_title('{} - {} - {:.0f} ppm'.format(planet_params_name, channel[:-1].upper(), \
                                  fitResults_KRData_half_Fourier_PhaseCurve.params['edepth']*ppm));

fig   = gcf()
# baseline     = 'KRData'
# phase_method = 'Fourier4'
fig_save_name= planet_params_name.replace(' ','_') + '_full_phase_curve_' \
                                                   + channel.replace('/', '') \
                                                   + '_observations_' \
                                                   + phase_method+'_' \
                                                   + baseline + '.png'

axhline(1.0, ls='--')
# print('Saving tigure to '  + 'figure_results/' + fig_save_name)

# fig = gcf()
# fig.savefig('figure_results/' + fig_save_name)

In [ ]:
ax = plot_model_over_reduced_lc_half_PLDsq_universal(times_c, 
                                                phots_c / median(phots_c), 
                                                sqrt(phots_c) / median(phots_c), 
                                                # input_feature_set_c, 
                                                [phots_c / median(phots_c), gw_c, nbr_c], 
                                                in_1st_eclipse, 
                                                # initialParams_KRData_half_Fourier_PhaseCurve, 
                                                fitResults_KRData_half_Fourier_PhaseCurve.params,
                                                spider_params=spider_params_hoststar,
                                                figsize=None, nbins=200, plotRawData=False,
                                                phase_method=phase_method, baseline=baseline,
                                                ax = None, returnAx = True)

ax.set_title('{} - {} - {:.0f} ppm'.format(planet_params_name, channel[:-1].upper(), \
                                  fitResults_KRData_half_Fourier_PhaseCurve.params['edepth']*ppm));

ax.set_ylim(0.999,1.003)
fig   = gcf()
# baseline     = 'KRData'
# phase_method = 'Fourier4'
fig_save_name= planet_params_name.replace(' ','_') + '_top_full_phase_curve_' \
                                                   + channel.replace('/', '') \
                                                   + '_observations_' \
                                                   + phase_method+'_' \
                                                   + baseline + '.png'
axhline(1.0, ls='--')


# print('Saving tigure to '  + 'figure_results/' + fig_save_name)

# fig = gcf()
# fig.savefig('figure_results/' + fig_save_name)

In [ ]:
joblib.dump(fitResults_KRData_half_Fourier_PhaseCurve, 'lmfit_save_files/' + \
            planet_params_name.replace(' ','_') + '_full_phase_curve_' \
                                                + channel.replace('/', '') \
                                                + '_observations_' \
                                                + phase_method+'_' \
                                                + baseline + '.pickle.save')

In [ ]:
ls lmfit_save_files/

END TEST


In [ ]:
# create lnfunc and starting distribution.
lnfunc, guess = create_all(fitResults_KRData_half_Fourier_PhaseCurve)
nwalkers, ndim = 100, len(guess)
p0 = emcee.utils.sample_ball(guess, 0.1*np.array(guess), nwalkers)
sampler = emcee.EnsembleSampler(nwalkers, ndim, lnfunc)
n_steps = 1

start = time()
sampler.run_mcmc(p0, n_steps)
print("Full phase curve fitting operation took {} seconds".format(time()-start))

In [ ]:
params      = fitResults_KRData_half_Fourier_PhaseCurve_ch1.params
lmfit_vals  = [i.value for i in params.values() if i.vary] + [0.0]
lmfit_names = [i.name  for i in params.values() if i.vary] + ['sigma']

In [ ]:
fig, axes = plt.subplots(len(guess), 1, sharex=True, figsize=(8, 2*len(guess)))
for (i, name, rv) in zip(range(len(guess)), lmfit_names, lmfit_vals):
    # axes[i].hist(sampler.chain[:, :, i].T.ravel(),  alpha=0.05, bins=sampler.chain[:, :, i].T.size//100);
    axes[i].plot(sampler.chain[:, :, i].T, color="k", alpha=0.05);
    axes[i].yaxis.set_major_locator(plt.MaxNLocator(5));
    axes[i].axhline(rv, color="#888888", lw=2);
    axes[i].set_ylabel("$%s$" % name);

axes[-1].set_xlabel("Steps");

In [ ]:
i_use, corner_vals, corner_names = np.transpose([(k, val, name) \
                                                 for k, (val, name) in enumerate(zip(lmfit_vals, lmfit_names)) \
                                                 if 'pld' not in name])
i_use = int32(i_use)

In [ ]:
print(corner_names, len(corner_names))

In [ ]:
corner_names=[r'tCenter', r'inc', r'aprs', r'edepth', r'tdepth', r'u1', r'u2',
              r'amp1', r'amp2', r'amp3', r'amp4', r'mean', r'intcpt', r'slope', r'sigma']

In [ ]:
samples.shape, dims, len(i_use), len(corner_names)

In [ ]:
burnin  = int(n_steps * 0.2)
samples = sampler.chain[:, burnin:, i_use].reshape((-1, len(i_use)));
# corner.corner(samples, labels=corner_names, truths=corner_vals);

In [ ]:
#Stairstep Plot
# labels = corner_names

plt.rc('font',size=8)
dims = len(corner_names)
# fig,axL = plt.subplots(nrows=dims,ncols=dims,figsize=(15,15))

corner_kw = dict(
    truths=corner_vals,
    labels=corner_names,
    levels=[0.68,0.95],
    plot_datapoints=False,
    smooth=True,
    bins=30,
    )

corner.corner(samples, **corner_kw)
# plt.show()
# fig.savefig('ch'+str(ch)+'_visit'+str(visit)+'_stairstep_indiv_fit_linreg'+exp_opt_name+'.eps')
# fit the data with lmfit partial_residuals = partial(residuals_func, data = phots_0 / med_eclipse_1, times = times_0, input_features = [phots_0 / med_eclipse_1, gw_0, nbr_0],#input_feature_set_0, in_eclipse = in_1st_eclipse, phase_method = 'fourier', baseline = 'KRData')
mini = Minimizer(partial_residuals, initialParams_1st_half_Fourier_PhaseCurve) start = time() fitResults_1st_half_Fourier_PhaseCurve = mini.leastsq() print("Full phase curve fitting operation took {} seconds".format(time()-start))
report_errors(fitResults_1st_half_Fourier_PhaseCurve.params)
var_i_care = ['edepth', 'ecc', 'omega', 'amp1', 'amp2', 'amp3', 'amp4', 'amp5', 'amp6', 'amp7', 'amp8'] ppm_or_not = [ppm, 1.0, 1.0, ppm, ppm, ppm,ppm, ppm, ppm, ppm, ppm] unit_list = ['ppm', ' ', 'deg', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm'] for varname in var_i_care: if varname in fitResults_1st_half_Fourier_PhaseCurve.var_names: print('{}:\t{:.0f}\tppm'.format(varname, fitResults_1st_half_Fourier_PhaseCurve.params[varname]*ppm)) print('mean-1:\t{:.0f}\tppm'.format((fitResults_1st_half_Fourier_PhaseCurve.params['mean']-1)*ppm))
plot_model_over_reduced_lc_half_PLDsq_universal(times_0, phots_0 / med_eclipse_1, sqrt(phots_0) / med_eclipse_1, # input_feature_set_0, [phots_0 / med_eclipse_1, gw_0, nbr_0], in_1st_eclipse, fitResults_1st_half_Fourier_PhaseCurve.params, figsize=None, nbins=2000, plotRawData=False, phase_method='fourier', baseline='KRData', ax = None, returnAx = False) # ylim(.975,1.01)
plot_model_over_reduced_lc_half_PLDsq_universal(times_0, phots_0 / med_eclipse_1, sqrt(phots_0) / med_eclipse_1, # input_feature_set_0, [phots_0 / med_eclipse_1, gw_0, nbr_0], in_1st_eclipse, fitResults_1st_half_Fourier_PhaseCurve.params, figsize=None, nbins=2000, plotRawData=False, phase_method='fourier', baseline='KRData', ax = None, returnAx = False) # ylim(.975,1.01)

Test PLD Correlations

i_use_pld, corner_vals_pld, corner_names_pld = np.transpose([(k, val, name) \ for k, (val, name) in enumerate(zip(lmfit_vals, lmfit_names)) \ if 'pld' in name]) i_use_pld = int32(i_use_pld)
corner_names_pld
for k in range(len(corner_names_pld)): corner_names_pld[k] = corner_names_pld[k].replace('_','-') corner_names_pld
burnin = int(n_steps * 0.2) samples = sampler.chain[:, burnin:, i_use_pld].reshape((-1, len(i_use_pld))); # corner.corner(samples, labels=corner_names, truths=corner_vals); #Stairstep Plot # labels = corner_names plt.rc('font',size=8) dims = len(corner_names_pld) # fig,axL = plt.subplots(nrows=dims,ncols=dims,figsize=(15,15)) corner_kw = dict( truths=corner_vals_pld, labels=corner_names_pld, levels=[0.68,0.95], plot_datapoints=False, smooth=True, bins=30, ) corner.corner(samples, fig=fig,**corner_kw) # plt.show() # fig.savefig('ch'+str(ch)+'_visit'+str(visit)+'_stairstep_indiv_fit_linreg'+exp_opt_name+'.eps')

2nd AOR Fourier


In [ ]:
init_2nd_eclipse_model          = TransitModel(init_eclipse_params, times_1, transittype="secondary")
init_2nd_eclipse_lightcurve     = init_2nd_eclipse_model.light_curve(init_eclipse_params)

in_2nd_eclipse = init_2nd_eclipse_lightcurve == 1
med_eclipse_2  = median(phots_1[in_2nd_eclipse == 1.0])

In [ ]:
pca_pld_1         = pca.fit_transform(PLDfeatures_1)
ica_pld_1         = ica.fit_transform(PLDfeatures_1)

pca_scl_pld_1     = pca.fit_transform(scale(PLDfeatures_1))
ica_scl_pld_1     = ica.fit_transform(scale(PLDfeatures_1))

ica_pca_pld_1     = ica.fit_transform(pca_pld_1)
pca_ica_pld_1     = pca.fit_transform(ica_pld_1)

ica_pca_scl_pld_1 = ica.fit_transform(pca_scl_pld_1)
pca_ica_scl_pld_1 = pca.fit_transform(ica_scl_pld_1)

In [ ]:
# input_feature_set_1   = PLDfeatures_1
# input_feature_set_1   = scale(PLDfeatures_1)
# input_feature_set_1   = pca_pld_1
# input_feature_set_1   = ica_pld_1
# input_feature_set_1   = pca_scl_pld_1
# input_feature_set_1   = ica_scl_pld_1
# input_feature_set_1   = ica_pca_pld_1
# input_feature_set_1   = pca_ica_pld_1
input_feature_set_1   = ica_pca_scl_pld_1
# input_feature_set_1   = pca_ica_scl_pld_1

In [ ]:
fitResults_1st_half_Fourier_PhaseCurve.params.keys()

In [ ]:
i_u1, i_u2 = 0.1, 0.1

fit_params = fitResults_1st_half_Fourier_PhaseCurve.params

initialParams_2nd_half_Fourier_PhaseCurve = Parameters()

initialParams_2nd_half_Fourier_PhaseCurve.add_many(
    # Planetary Parameters
    ('period' , iPeriod              , False),
    ('tCenter', fit_params['tCenter'], False , iTCenter-0.01, iTCenter+0.01),
    ('inc'    , iInc                 , False, 0.0 ,  90.),
    ('aprs'   , iApRs                , False, 0.0 , 100.),
    ('edepth' , fit_params['edepth'] , False, 0.0 , 1.0 ),
    ('tdepth' , fit_params['tdepth'] , False, 0.0 , 1.0 ),
    ('ecc'    , iEcc                 , False, 0.0 , 1.0 ),
    ('omega'  , iOmega               , False, 0.0 , 360.),
    ('u1'     , fit_params['u1']     , False, 0.0 , 1.0 ),
    ('u2'     , fit_params['u2']     , False, 0.0 , 1.0 ),
    ('amp1'   , fit_params['amp1']   , True ),
    ('amp2'   , fit_params['amp2']   , True , 0.0, inf), # for KBS only
    ('amp3'   , fit_params['amp3']   , False),
    ('amp4'   , fit_params['amp4']   , False),
    ('amp5'   , 0.0                  , False),
    ('amp6'   , 0.0                  , False),
    ('amp7'   , 0.0                  , False),
    ('amp8'   , 0.0                  , False),
    ('mean'   , fit_params['mean']   , True ),
    
    # PLD Coefficients for the 0th AOR - Linear
    ('pld1_l' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld2_l' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld3_l' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld4_l' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld5_l' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld6_l' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld7_l' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld8_l' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld9_l' , 0.0      , True ),# , -10.0, 10.0   ),
    
    # PLD Coefficients for the 0th AOR - Quadratic
    ('pld1_q' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld2_q' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld3_q' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld4_q' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld5_q' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld6_q' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld7_q' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld8_q' , 0.0      , True ),# , -10.0, 10.0   ),
    ('pld9_q' , 0.0      , True ),# , -10.0, 10.0   ),
    
    # Out of transit linear baselines
    ('intcpt' , fit_params['intcpt'], True ),
    ('slope'  , fit_params['slope'] , True ),
    ('crvtur' , fit_params['crvtur'], False))

In [ ]:
# fit the data with lmfit
partial_residuals = partial(residuals_func, data           = phots_1 / med_eclipse_2,
                                            times          = times_1, 
                                            input_features = input_feature_set_1, 
                                            in_eclipse     = in_2nd_eclipse,
                                            method         = 'kbs')

In [ ]:
mini = Minimizer(partial_residuals, initialParams_2nd_half_Fourier_PhaseCurve)
start = time()
fitResults_2nd_half_Fourier_PhaseCurve = mini.leastsq()
print("Full phase curve fitting operation took {} seconds".format(time()-start))

In [ ]:
report_errors(fitResults_2nd_half_Fourier_PhaseCurve.params)

In [ ]:
var_i_care = ['edepth', 'ecc', 'omega', 'amp1', 'amp2', 'amp3', 'amp4', 'amp5', 'amp6', 'amp7', 'amp8']
ppm_or_not = [ppm, 1.0, 1.0, ppm, ppm, ppm,ppm, ppm, ppm, ppm, ppm]
unit_list  = ['ppm', ' ', 'deg', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm']

In [ ]:
for varname in var_i_care:
    if varname in fitResults_2nd_half_Fourier_PhaseCurve.var_names:
        print('{}:\t{:.0f}\tppm'.format(varname, fitResults_2nd_half_Fourier_PhaseCurve.params[varname]*ppm))

print('mean-1:\t{:.0f}\tppm'.format((fitResults_2nd_half_Fourier_PhaseCurve.params['mean']-1)*ppm))

In [ ]:
plot_model_over_reduced_lc_half_PLDsq_universal(times_1, phots_1 / med_eclipse_2, 
                                                sqrt(phots_1) / med_eclipse_2, 
                                                input_feature_set_1, 
                                                in_2nd_eclipse, 
                                                fitResults_2nd_half_Fourier_PhaseCurve.params, 
                                                figsize=None, nbins=2000, plotRawData=False,
                                                method='kbs', ax = None, returnAx = False)

Fit Full Phase Curve


In [ ]:
fit_params_0  = fitResults_1st_half_Fourier_PhaseCurve.params
fit_params_1  = fitResults_2nd_half_Fourier_PhaseCurve.params

initialParams_Full_Fourier_PhaseCurve = Parameters()

initialParams_Full_Fourier_PhaseCurve.add_many(
    # Planetary Parameters
    ('period' , iPeriod              , False),
    ('tCenter', fit_params['tCenter'], True , iTCenter-0.01, iTCenter+0.01),
    ('inc'    , iInc                 , False, 0.0 ,  90.),
    ('aprs'   , iApRs                , False, 0.0 , 100.),
    ('edepth' , fit_params['edepth'] , True , 0.0 , 1.0 ),
    ('tdepth' , fit_params['tdepth'] , True , 0.0 , 1.0 ),
    ('ecc'    , iEcc                 , False, 0.0 , 1.0 ),
    ('omega'  , iOmega               , False, 0.0 , 360.),
    ('u1'     , fit_params['u1']     , True , 0.0 , 1.0 ),
    ('u2'     , fit_params['u2']     , True , 0.0 , 1.0 ),
    ('amp1'   , fit_params['amp1']   , True ),#,-0.01, 0.01 ),
    ('amp2'   , fit_params['amp2']   , True , 0.0, inf),#,-0.01, 0.01 ), # For KBS Only
    ('amp3'   , fit_params['amp3']   , False),#,-0.01, 0.01 ),
    ('amp4'   , fit_params['amp4']   , False),#,-0.01, 0.01 ),
    ('amp5'   , 0.0                  , False),#,-0.01, 0.01 ),
    ('amp6'   , 0.0                  , False),#,-0.01, 0.01 ),
    ('amp7'   , 0.0                  , False),#,-0.01, 0.01 ),
    ('amp8'   , 0.0                  , False),#,-0.01, 0.01 ),
    ('mean_0' , fit_params_0['mean'] , True ),#,1-1e-3, 1+1e-3 ),
    ('mean_1' , fit_params_1['mean'] , True ),#,1-1e-3, 1+1e-3 ),
    
    # PLD Coefficients for the 0th AOR - Linear
    ('pld1_l_1' , fit_params_0['pld1_l'], True ),# , -10.0, 10.0   ),
    ('pld2_l_1' , fit_params_0['pld2_l'], True ),# , -10.0, 10.0   ),
    ('pld3_l_1' , fit_params_0['pld3_l'], True ),# , -10.0, 10.0   ),
    ('pld4_l_1' , fit_params_0['pld4_l'], True ),# , -10.0, 10.0   ),
    ('pld5_l_1' , fit_params_0['pld5_l'], True ),# , -10.0, 10.0   ),
    ('pld6_l_1' , fit_params_0['pld6_l'], True ),# , -10.0, 10.0   ),
    ('pld7_l_1' , fit_params_0['pld7_l'], True ),# , -10.0, 10.0   ),
    ('pld8_l_1' , fit_params_0['pld8_l'], True ),# , -10.0, 10.0   ),
    ('pld9_l_1' , fit_params_0['pld9_l'], True ),# , -10.0, 10.0   ),
    
    # PLD Coefficients for the 0th AOR - Quadratic
    ('pld1_q_1' , fit_params_0['pld1_q'], True ),# , -10.0, 10.0   ),
    ('pld2_q_1' , fit_params_0['pld2_q'], True ),# , -10.0, 10.0   ),
    ('pld3_q_1' , fit_params_0['pld3_q'], True ),# , -10.0, 10.0   ),
    ('pld4_q_1' , fit_params_0['pld4_q'], True ),# , -10.0, 10.0   ),
    ('pld5_q_1' , fit_params_0['pld5_q'], True ),# , -10.0, 10.0   ),
    ('pld6_q_1' , fit_params_0['pld6_q'], True ),# , -10.0, 10.0   ),
    ('pld7_q_1' , fit_params_0['pld7_q'], True ),# , -10.0, 10.0   ),
    ('pld8_q_1' , fit_params_0['pld8_q'], True ),# , -10.0, 10.0   ),
    ('pld9_q_1' , fit_params_0['pld9_q'], True ),# , -10.0, 10.0   ),
    
    # PLD Coefficients for the 0th AOR - Linear
    ('pld1_l_2' , fit_params_1['pld1_l'], True ),# , -10.0, 10.0   ),
    ('pld2_l_2' , fit_params_1['pld2_l'], True ),# , -10.0, 10.0   ),
    ('pld3_l_2' , fit_params_1['pld3_l'], True ),# , -10.0, 10.0   ),
    ('pld4_l_2' , fit_params_1['pld4_l'], True ),# , -10.0, 10.0   ),
    ('pld5_l_2' , fit_params_1['pld5_l'], True ),# , -10.0, 10.0   ),
    ('pld6_l_2' , fit_params_1['pld6_l'], True ),# , -10.0, 10.0   ),
    ('pld7_l_2' , fit_params_1['pld7_l'], True ),# , -10.0, 10.0   ),
    ('pld8_l_2' , fit_params_1['pld8_l'], True ),# , -10.0, 10.0   ),
    ('pld9_l_2' , fit_params_1['pld9_l'], True ),# , -10.0, 10.0   ),
    
    # PLD Coefficients for the 0th AOR - Quadratic
    ('pld1_q_2' , fit_params_1['pld1_q'], True ),# , -10.0, 10.0   ),
    ('pld2_q_2' , fit_params_1['pld2_q'], True ),# , -10.0, 10.0   ),
    ('pld3_q_2' , fit_params_1['pld3_q'], True ),# , -10.0, 10.0   ),
    ('pld4_q_2' , fit_params_1['pld4_q'], True ),# , -10.0, 10.0   ),
    ('pld5_q_2' , fit_params_1['pld5_q'], True ),# , -10.0, 10.0   ),
    ('pld6_q_2' , fit_params_1['pld6_q'], True ),# , -10.0, 10.0   ),
    ('pld7_q_2' , fit_params_1['pld7_q'], True ),# , -10.0, 10.0   ),
    ('pld8_q_2' , fit_params_1['pld8_q'], True ),# , -10.0, 10.0   ),
    ('pld9_q_2' , fit_params_1['pld9_q'], True ),# , -10.0, 10.0   ),
    
    # Out of transit linear baselines
    ('intcpt' , fit_params_0['intcpt'], True ),
    ('slope'  , fit_params_0['slope'] , True ),
    ('crvtur' , fit_params_0['crvtur'], False)
)
#     # Out of transit linear baselines
#     ('intcpt_0' , fit_params_0['intcpt'], True ),
#     ('slope_0'  , fit_params_0['slope'] , True ),
#     ('crvtur_0' , fit_params_0['crvtur'], True ),
    
#     ('intcpt_1' , fit_params_1['intcpt'], True ),
#     ('slope_1'  , fit_params_1['slope'] , True ),
#     ('crvtur_1' , fit_params_1['crvtur'], True ))

In [ ]:
phots_c = hstack([phots_0 / med_eclipse_1, phots_1 / med_eclipse_2])

In [ ]:
# fit the data with lmfit
partial_residuals_full = partial(residuals_func_full, data        = phots_c,
                                                 times_0          = times_0, 
                                                 times_1          = times_1,
                                                 input_features_0 = input_feature_set_0, 
                                                 input_features_1 = input_feature_set_1, 
                                                 in_eclipse_0     = in_1st_eclipse,
                                                 in_eclipse_1     = in_2nd_eclipse,
                                                 method           = 'kbs')

In [ ]:
mini = Minimizer(partial_residuals_full, initialParams_Full_Fourier_PhaseCurve)
start = time()
fitResults_Full_Fourier_PhaseCurve = mini.leastsq()
print("Full phase curve fitting operation took {} seconds".format(time()-start))

In [ ]:
report_errors(fitResults_Full_Fourier_PhaseCurve.params)

In [ ]:
var_i_care = ['edepth', 'ecc', 'omega', 'amp1', 'amp2', 'amp3', 'amp4', 'amp5', 'amp6', 'amp7', 'amp8']
ppm_or_not = [ppm, 1.0, 1.0, ppm, ppm, ppm,ppm, ppm, ppm, ppm, ppm]
unit_list  = ['ppm', ' ', 'deg', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm', 'ppm']

In [ ]:
for varname in var_i_care:
    if varname in fitResults_Full_Fourier_PhaseCurve.var_names:
        print('{}:\t{:.0f}\tppm'.format(varname, fitResults_Full_Fourier_PhaseCurve.params[varname]*ppm))

print('mean-1:\t{:.0f}\tppm'.format((fitResults_Full_Fourier_PhaseCurve.params['mean_0']-1)*ppm))
print('mean-1:\t{:.0f}\tppm'.format((fitResults_Full_Fourier_PhaseCurve.params['mean_1']-1)*ppm))

In [ ]:
plot_model_over_reduced_lc_full_PLDsq_universal(times_0, 
                                                times_1, 
                                                phots_0 / med_eclipse_1,
                                                phots_1 / med_eclipse_2, 
                                                sqrt(phots_0) / med_eclipse_1, 
                                                sqrt(phots_1) / med_eclipse_2, 
                                                input_feature_set_0, 
                                                input_feature_set_1, 
                                                in_1st_eclipse, 
                                                in_2nd_eclipse, 
                                                fitResults_Full_Fourier_PhaseCurve.params, 
                                                # initialParams_Full_Fourier_PhaseCurve,
                                                refTime = times_0.min(),
                                                planetName=planet_params_name,figsize=None, 
                                                nbins=1000, plotRawData=False, 
                                                model_color=0, data_color=1, alpha=1.0,
                                                method='kbs', ax = None, returnAx = False)

# fig_save_name = planet_params_name.replace(' ','_') + '_full_phase_curve_'+channel.replace('/', '')+'_observations.png'

# print('Saving tigure to '  + 'figure_results/' + fig_save_name)

# fig = gcf()
# fig.savefig('figure_results/' + fig_save_name)