Esempio n. 1
0
def get_fold_fit(dt_tra, f_tra, depth, period, window, fig=None):
    """Uses lmfit to get a good estimate of the Mandel-Agol parameters from the folded light curve. The curve fitting
    routine will then be rerun using these better parameters.

    :param dt_tra: array of selected dt that fall within transit windows.
    :param f_tra: array of selected fluxes that fall within transit windows.
    :param depth: estimate of transit depth obtained from sech fit. Defined as negative.
    :param period: estimate of transit period (days).
    :param window: approximate length of transit window (days). Include at least half a transit's worth of out-of-transit
        light curve on either side of dip.
    :param fig: plot handle indicating desired plot dimensions. e.g. fig = plt.figure(figsize=(10,4)).
    No plots will be made if set to None.

    :return:
        fit - best-fit Mandel-Agol parameters from lmfit.minimise(). Contains the following params:
            tc - midtransit time. Centred at 0.
            b - impact parameter.
            Rs_a - radius of star/semimajor axis.
            F - out-of-transit flux, fixed at 1.
            gamma1, gamma2 - quadratic limb darkening parameters from Mandel & Agol (2002)
        fig - plot handle of folded transit with best-fit model.
    """
    # plotting can always be skipped now unless you want to debug
    params = Parameters()
    params.add('tc', value=0, vary=False, min=-0.1, max=0.1)
    params.add('b', value=0.7, vary=True)
    params.add('Rs_a', value=0.1, vary=True, min=0., max=0.5)
    params.add('Rp_Rs', value=(-depth)**0.5, vary=True)
    params.add('F', value=1, vary=False)
    params.add('gamma1', value=0.3, vary=True, min=0,
               max=0.5)  # should I let these float?
    params.add('gamma2', value=0.3, vary=True, min=0, max=0.5)
    params.add('a0', value=1, vary=False)
    params.add('a1', value=0, vary=False)

    fit = minimize(residual, params, args=(dt_tra, f_tra, period, False))
    tarr = np.linspace(min(dt_tra), max(dt_tra), 100)
    fmod = model_transits.modeltransit([
        fit.params['tc'].value, fit.params['b'].value,
        fit.params['Rs_a'].value, fit.params['Rp_Rs'].value, 1,
        fit.params['gamma1'].value, fit.params['gamma2'].value
    ], model_transits.occultquad, period, tarr)

    if fig is not None:
        plt.close('all')
        plt.plot(dt_tra, f_tra, lw=0, marker='.')
        plt.plot(tarr, fmod, color='r')
        plt.axvline(x=-window, color='k', ls='--')
        plt.axvline(x=window, color='k', ls='--')
        plt.xlabel('Time from midtransit (days)')
        plt.ylabel('Relative flux')
    if fig is not None:
        return fit, fig
    else:
        return fit
Esempio n. 2
0
def residual(params,t,data,period):
	#residual function for fitting for midtransit times
	vals = params.valuesdict()
	t0 = vals['t0']
	b = vals['b']
	r_a = vals['r_a']
	Rp_Rs = vals['Rp_Rs']
	F = vals['F']
	gamma1 = vals['gamma1']
	gamma2 = vals['gamma2']
	model = model_transits.modeltransit([t0,b,r_a,Rp_Rs,F,gamma1,gamma2],model_transits.occultquad,period,t)
	return (data-model)
Esempio n. 3
0
def transit_likelihoodfunc(params,period,times,dt_new,n_ev,data,sigma,priors_info):
	# PARAMS:
	# params[0, 1, 2, 3, 5] = ['T0', 'b', 'R/a', 'Rp/Rs', 'Fstar']  , for i = 0 ... len(a)-2 ---- the last ones are the limb darkening, so len(params) = 1 + len(data)
	# params[len(params)-1] = ['q1','q2']

	u1_param = params[-2]
	u2_param = params[-1]

	# check physical boundaries for LD parameters and return -inf if they exceed those boundaries
	if ( (u1_param + u2_param) > 1.) or ( u1_param < 0. ) or ( u2_param < 0. ):
		print 'unphysical limb darkening coeffs', u1_param, u2_param
		return -inf

	if (params[3]<0):
		print 'Rp/Rs<0'
		return -inf

	if (params[2]<0):
		print 'Rs/a<0'
		return -inf

	params[1] = abs(params[1])

	# calculate the likelihoods for all different transit models and sum them together
	log_likelihood = []
	prior = []

	prior.append( logp(array([params[0],params[1],params[2],params[3],params[4],u1_param,u2_param]),priors_info) ) # the prior has to be evaluated for q1 and q2, NOT u1 and u2
		
	if not isfinite(prior[0]):
	  	return -inf

	new_params = array([params[0],params[1],params[2],params[3],params[4],u1_param,u2_param])
	model_oversamp = model_transits.modeltransit(new_params,model_transits.occultquad,period,dt_new)
	if type(model_oversamp) is int:
		return -inf

	transit_model = []
	for i in range(0,len(times)):
		mean_f = mean(model_oversamp[i*n_ev:i*n_ev+n_ev-1])
		transit_model.append(mean_f)

	log_likelihood.append( -sum( ((array(transit_model)-array(data))**2. / ((2.**0.5)*array(sigma)**2) ) + (log(array(sigma)) * (2.*pi)**0.5  ) ) )

	#print 'prior / likelihood'
	#print prior
	#print log_likelihood
	return sum(array(prior)) + sum(array(log_likelihood))
Esempio n. 4
0
def residual(params, t, data, period=1, sech=True):
    """Residual function for fitting for midtransit times.

    INPUTS:
        params - lmfit.Parameters() object containing parameters to be fitted.
        t - nd array of light curve times (days).
        data - nd array of normalized light curve fluxes. Median out-of-transit flux should be set to 1.
        period - period of transit (days).
        sech - boolean. If True, will use sech model. Otherwise will fit Mandel-Agol model instead.
        The params argument must match the format of the model chosen.

    RETURNS:
        res - residual of data - model, to be used in lmfit.
    """

    if sech:
        vals = params.valuesdict()
        tc = vals['tc']
        b = vals['b']
        w = vals['w']
        a0 = vals['a0']
        a1 = vals['a1']
        model = rect_sechmod(t, b, tc, w, a0, a1)
    else:
        vals = params.valuesdict()
        tc = vals['tc']
        b = vals['b']
        r_a = vals['Rs_a']
        Rp_Rs = vals['Rp_Rs']
        F = vals['F']
        gamma1 = vals['gamma1']
        gamma2 = vals['gamma2']
        a0 = vals['a0']
        a1 = vals['a1']
        model = model_transits.modeltransit(
            [tc, b, r_a, Rp_Rs, F, gamma1, gamma2], model_transits.occultquad,
            period, t)
        model *= (a0 + a1 * t)
    return data - model
Esempio n. 5
0
def get_period(t,f_t,get_mandelagolmodel=True,outputpath='',starname=''):
  #
  # here we use a BLS algorithm to create a periodogram and find the best periods. The BLS is implemented in Python by Ruth Angus and Dan Foreman-Macey
  #

  outputfolder = os.path.join(outputpath,str(starname))

  fmin = 0.03 # minimum frequency. we can't find anything longer than 90 days obviously
  nf = 60000 # amount of frequencies to try
  df = 0.00001 # frequency step

  qmi = 0.0005 # min relative length of transit (in phase unit)
  qma = 0.1 # max relative length of transit (in phase unit)
  nb = 200 # number of bins in folded LC

  u = np.linspace(fmin,fmin + nf*df,nf)
  v = np.array(0)
  t = np.array(t)
  print t[0]
  f_t = np.array(f_t)

  t_orig = np.copy(t)
  f_t_orig = f_t
  results = bls.eebls(t,f_t,t,f_t,nf,fmin,df,nb,qmi,qma)
  freqlist = u
  powers = results[0]
  period = results[1]

  folded,f_t_folded = fold_data(t,f_t,period)

  np.savetxt(os.path.join(outputfolder, 'folded_P' + str(period) + 'star_' + str(starname) + '.txt'),np.transpose([folded,f_t_folded]),header='Time, Flux')

  t_foldbin,f_t_foldbin,stdv_foldbin = rebin_dataset(folded,f_t_folded,15)
  f_t_smooth = savitzky_golay(f_t_folded,29,1)
  pl.figure('my data folded bls')
  pl.plot(folded,f_t_folded+1.,'.',color='black',label='K2 photometry')
  pl.xlabel('Time [d]')
  pl.ylabel('Relative Flux')

  if get_mandelagolmodel:
    # this is not a core part of the module and uses a transit model by Mandel & Agol, implemented in Python by Ian Crossfield.

    #[T0,b,R_over_a,Rp_over_Rstar,flux_star,gamma1,gamma2]
    transit_params = np.array([4.11176,0.9,0.104,np.sqrt(0.0036),1.,0.2,0.2])
    import model_transits
    times_full = np.linspace(0.,period,10000)
    model = model_transits.modeltransit(transit_params,model_transits.occultquad,period,times_full)

    pl.figure('Transit model')
    pl.scatter((folded-transit_params[0])*24.,f_t_folded+1.,color='black',label='K2 photometry',s=10.)

    pl.plot((times_full-transit_params[0])*24.,model,color='grey',lw=4,label='Transit model')
    pl.xlabel('Time from mid-transit [hr]',fontsize=17)
    pl.ylabel('Relative flux',fontsize=17)
    legend = pl.legend(loc='upper center',numpoints=1,scatterpoints=1,fontsize=15,prop={'size':15},title='EPIC 205071984')
    pl.tick_params(labelsize=17)
    pl.tick_params(axis='both', which='major', width=1.5)

    pl.tight_layout()
    pl.setp(legend.get_title(),fontsize=17)
  pl.savefig(os.path.join(outputfolder, 'folded_P_' + 'star_' + str(starname) +str(period) + '.png'))

  # unravel again
  n_start = int(np.round(t[0] / period))
  n_end = np.round(t[-1] / period) + 1
  i = n_start
  pl.figure()
  pl.plot(t_orig,f_t,'*')

  t_unravel = []
  f_t_unravel = []
  while i < n_end:
    t_unravel.append(np.array(folded) + i*period + t_orig[0])
    f_t_unravel.append(np.array(f_t_smooth))

    pl.plot(t_unravel[i],f_t_unravel[i],color='black',lw='1.5')
    i = i + 1

  print 'best period is '
  print period

  return folded,f_t_folded,period,freqlist,powers
Esempio n. 6
0
def run_mcmc(epic,transit_params,period,times,data,sigma,nwalkers=50,nthread=1,burnintime=100,iterations=400,saveacc=200,saveval=200,thin=100):
	# Parameters are [T0,b,R_over_a,Rp_over_Rstar,flux_star,gamma1,gamma2]
	T0_prior = ['gauss', 0, 0.1] # should be around 0.
	b_prior = ['flat', -1, 1]
	R_over_a_prior = ['flat', 0.01, 0.4]
	Rp_over_Rstar_prior = ['flat',0.0001, 0.3]
	flux_star_prior = ['flat', 0.999, 1.001] # should be normalised to one #FIXME
	gamma1_prior = ['flat',0.1,0.5]
	gamma2_prior = ['flat',0.1,0.5]

	priors_info = [T0_prior, b_prior, R_over_a_prior, Rp_over_Rstar_prior, flux_star_prior, gamma1_prior, gamma2_prior] 
	ndim = 7

	cad = 29.4/60./24. #cadence in days
	n_pt = len(times)

	n_ev = 25
	n_tot = n_ev*n_pt
	dt_new = zeros(n_tot)

	for i,this_t in enumerate(times):
		for i_ev in range(0,n_ev-1):
			dt_new[i*n_ev+i_ev] = this_t + 1.0/n_ev *cad*(i_ev-ceil(n_ev/2))

	# Initialize sampler:
  	sampler = emcee.EnsembleSampler(nwalkers, ndim, transit_likelihoodfunc, args=[period,times,dt_new,n_ev,data,sigma,priors_info], threads=nthread)
  	starting_pos = [transit_params + 1e-6*random.randn(ndim) for i in range(nwalkers)] # all start out in more or less the location of our best guess.
  	pos,prob,state = sampler.run_mcmc(starting_pos,1000)

	samples = sampler.chain[:, burnintime:, :].reshape((-1, ndim))

	fig = corner.corner(samples,labels=['t0','b','R/a','Rp/Rs','F_norm','gamma1','gamma2'])
	fig.savefig('outputs/'+epic+'_triangle.png')

	parnames = ['t0','b','R/a','Rp/Rs','F','gamma1','gamma2']
	for i in range(0,7):
		print parnames[i], percentile(array(samples[:,i]),[(100-68.3)/2,50,50+68.3/2])

	params = median(samples,axis=0)
	timearr = linspace(times[0],times[-1],100)
	model_oversamp = model_transits.modeltransit(params,model_transits.occultquad,period,dt_new)
	model = []
	for i in range(0,len(times)):
		mean_f = mean(model_oversamp[i*n_ev:i*n_ev+n_ev-1])
		model.append(mean_f)

	model2 = interp(timearr,times,model)

	dt = linspace(min(times),max(times),100)
	model = model_transits.modeltransit(params,model_transits.occultquad,period,dt)

	plt.close('all')
	fig = plt.figure(figsize=(11,5))
	plt.plot(times*24,data,lw=0,marker='.')
	plt.plot(dt*24.,model,color='g',ls='--',lw=1.5)
	plt.plot(timearr*24.,model2,color='r',lw=1.5)

	plt.xlabel('Time from midtransit (hours)')
	plt.ylabel('Relative flux')
	plt.savefig('outputs/'+epic+'_7final.pdf',dpi=150,bbox_inches='tight')


	return params 
Esempio n. 7
0
def odd_even(dt_tra, f_tra, epochs_tra, window, period, p0):
    """Plots odd vs. even transits and calculates difference in depth.

    :param dt_tra: see get_fold_fit.
    :param f_tra: see get_fold_fit.
    :param epochs_tra: see get_fold_fit.
    :param window: see get_fold_fit.
    :param period: see get_fold_fit.
    :param p0: good estimate of Mandel-Agol parameters from get_fold_fit. p0 = [b, Rs_a, Rp_Rs, gamma1, gamma2]

    :return:
        fig - plot handle for odd-even comparison plot.
    """
    #
    odd = np.where(epochs_tra % 2 != 0)[0]
    even = np.where(epochs_tra % 2 == 0)[0]

    params = Parameters()
    params.add('tc', value=0, vary=False)
    params.add('b', value=p0[0], vary=True)
    params.add('Rs_a', value=p0[1], vary=True, min=0., max=0.5)
    params.add('Rp_Rs', value=p0[2], vary=True)
    params.add('F', value=1, vary=False)
    params.add('gamma1', value=p0[3], vary=False)
    params.add('gamma2', value=p0[4], vary=False)
    params.add('a0', value=1, vary=False)
    params.add('a1', value=0, vary=False)

    fit_odd = minimize(residual,
                       params,
                       args=(dt_tra[odd], f_tra[odd], period, False))
    fit_even = minimize(residual,
                        params,
                        args=(dt_tra[even], f_tra[even], period, False))

    oot = np.where(abs(dt_tra) > window)[0]
    sigma = np.std(dt_tra[oot])

    tarr = np.linspace(min(dt_tra), max(dt_tra), 200)
    oddmod = model_transits.modeltransit([
        fit_odd.params['tc'].value, fit_odd.params['b'].value,
        fit_odd.params['Rs_a'].value, fit_odd.params['Rp_Rs'].value, 1,
        fit_odd.params['gamma1'].value, fit_odd.params['gamma2'].value
    ], model_transits.occultquad, period, tarr)
    evenmod = model_transits.modeltransit([
        fit_even.params['tc'].value, fit_even.params['b'].value,
        fit_even.params['Rs_a'].value, fit_even.params['Rp_Rs'].value, 1,
        fit_even.params['gamma1'].value, fit_even.params['gamma2'].value
    ], model_transits.occultquad, period, tarr)
    odd_depth = min(oddmod)
    even_depth = min(evenmod)
    diff = abs(odd_depth - even_depth) / sigma

    plt.close('all')
    fig, (ax1, ax2) = plt.subplots(1, 2, sharey=True, figsize=(13, 5))
    plt.subplots_adjust(wspace=0, hspace=0)
    ax1.plot(dt_tra[odd] * 24., f_tra[odd], lw=0, marker='.')
    ax1.plot(tarr * 24., oddmod, color='r')
    ax1.axhline(y=odd_depth, color='k', ls='--')
    ax1.set_xlabel('Time from midtransit (hours)')
    ax1.set_ylabel('Relative flux')
    ax1.set_xlim(min(dt_tra) * 24, max(dt_tra) * 24)
    ax1.annotate('Odd', xy=(0.75, 0.15), xycoords='axes fraction', size=15)

    ax2.plot(dt_tra[even] * 24., f_tra[even], lw=0, marker='.')
    ax2.plot(tarr * 24., evenmod, color='r')
    ax2.axhline(y=even_depth, color='k', ls='--')
    ax2.set_xlabel('Time from midtransit (hours)')
    ax2.set_xlim(min(dt_tra) * 24, max(dt_tra) * 24)
    ax2.annotate('Even', xy=(0.75, 0.15), xycoords='axes fraction', size=15)
    ax2.annotate('Diff: %.3f sigma' % diff,
                 xy=(0.62, 0.05),
                 xycoords='axes fraction',
                 size=15)
    # plt.savefig('outputs/' + name + '_oddeven.pdf', dpi=150, bbox_inches='tight')
    return fig
Esempio n. 8
0
def plot_indiv_trans(name,
                     t,
                     f,
                     p,
                     t0,
                     window,
                     p0,
                     plotbad=True,
                     plots=True,
                     sech=True):
    """ Plot individual transits with a choice of sech or Mandel-Agol fit.

    INPUTS:
        t - nd array of light curve times.
        f - nd array of normalized light curve fluxes.
        window - approximate length of transit window (days). Include at least half a transit's worth of out-of-transit
        light curve on either side of dip.
        p0 - best guess of fit parameters. If sech, p0 = [w0, depth]. w0 is fractional width of transit from read_lc.
        If Mandel-Agol, p0 = [b,Rs_a,Rp_Rs,gamma1,gamma2].
        plotbad - set to True if you want to plot incomplete or misshapen transits along with good ones.
        sech - set to True if you want a sech fit. Otherwise use Mandel-Agol model.

    RETURNS:
        dt_all - nd array showing the time (days) to the nearest transit for each point.
        epochs - nd array of epoch number of each point.
        midpts - nd array of midtransit times associated with all points.
        err - array of errors on each midtransit time.
    """

    end = int(floor((t[-1] - t0) / p) + 1)
    start = int(floor((t[0] - t0) / p))
    cnt = 0
    epochs = []
    dt_all = []
    midpts = []
    err = []
    valid_trans = []

    params = Parameters()
    if sech:
        w0 = p0[0]
        depth = p0[1]
        params.add('tc', value=0, vary=True, min=-0.1, max=0.1)
        params.add('b', value=depth * 2, vary=False)
        params.add('w', value=w0 * p, vary=False)
        params.add('a0', value=1)
        params.add('a1', value=0)
    else:
        depth = -p0[2]**2
        params.add('tc', value=0, vary=True, min=-0.1, max=0.1)
        params.add('b', value=p0[0], vary=False)
        params.add('Rs_a', value=p0[1], vary=False)
        params.add('Rp_Rs', value=p0[2], vary=False)
        params.add('F', value=1, vary=False)
        params.add('gamma1', value=p0[3],
                   vary=False)  # should I let these float?
        params.add('gamma2', value=p0[4], vary=False)
        params.add('a0', value=1, vary=True)
        params.add('a1', value=0, vary=True)

    for i in range(start, end):
        print 'Transit number ' + str(cnt)
        midt = i * p + t0

        dt = t - midt
        oot = np.where((abs(dt) > window) & (abs(dt) < window + 0.2 * p))[0]
        if len(oot) <= 1:
            continue

        fn = f / np.median(f[oot])

        select = np.where(
            abs(dt) < (window + 0.1 * p))[0]  # select single transit
        good = np.where(
            abs(dt) <= p / 2)[0]  # all points belonging to current transit

        if plots:
            if cnt % 8 == 0:
                plt.close('all')
                fig, ax = plt.subplots(8, figsize=(6, 12), sharex=True)

            if plotbad or (len(select) > 5):
                ax[cnt % 8].plot(dt[select], fn[select], lw=0, marker='.')
                ax[cnt % 8].axvline(x=0, color='k', ls='--')
                ax[cnt % 8].set_xlabel('Time from midtransit (days)')
                ax[cnt % 8].set_ylabel('Relative flux')
                ax[cnt % 8].set_ylim(1 + depth - 0.0003, 1 + 0.0003)
                ax[cnt % 8].set_xlim(-0.3, 0.3)
                ax[cnt % 8].locator_params(axis='y', nbins=5)
                ax[cnt %
                   8].get_yaxis().get_major_formatter().set_useOffset(False)
                ax[cnt % 8].annotate(str(cnt),
                                     xy=(0.85, 0.1),
                                     xycoords='axes fraction',
                                     size=15)

        dt_all += list(dt[good])

        if len(select) > 5:
            # fit sech to each transit

            try:
                fit = minimize(residual,
                               params,
                               args=(dt[select], fn[select], p, sech))
                fiterr = np.sqrt(fit.covar[0][0])
                err.append(fiterr)

                midpts += len(good) * [fit.params['tc'].value + i * p + t0]
                epochs += len(good) * [i]

                if plots:
                    tc = fit.params['tc'].value
                    a0 = fit.params['a0'].value
                    a1 = fit.params['a1'].value
                    tarr = np.linspace(dt[select][0], dt[select][-1], 200)
                    if sech:
                        fmod = rect_sechmod(tarr, depth * 2, tc, w0 * p, a0,
                                            a1)
                    else:
                        fmod = model_transits.modeltransit([
                            fit.params['tc'].value, fit.params['b'].value,
                            fit.params['Rs_a'].value,
                            fit.params['Rp_Rs'].value, 1,
                            fit.params['gamma1'].value,
                            fit.params['gamma2'].value
                        ], model_transits.occultquad, p, tarr)
                        fmod *= (fit.params['a0'].value +
                                 fit.params['a1'].value * tarr)
                    ax[cnt % 8].plot(tarr, fmod, color='r')

                valid_trans.append(i)
            except TypeError:
                midpts += len(good) * [np.nan]
                epochs += len(good) * [np.nan]
                err.append(np.nan)
                print 'Fit failed'
                pass
        else:
            midpts += len(good) * [np.nan]
            err.append(np.nan)
            epochs += len(good) * [np.nan]
            print 'Too few data points'

        if plots and ((cnt % 8 == 7) or (i == end - 1)):
            plt.savefig('outputs/' + name + 'alltrans' +
                        str(ceil(cnt / 8. + 0.01)) + '.pdf',
                        dpi=150,
                        bbox_inches='tight')
        if plotbad or (len(select) > 5):
            cnt += 1

    print 'total transits:', cnt
    epochs = np.array(epochs)
    print 'good transits:', np.unique(epochs[np.where(~np.isnan(epochs))[0]])

    return np.array(dt_all), epochs, np.array(midpts), np.array(err)