Ejemplo n.º 1
0
    def add_transits(self,planet_parameters,planet_name='b'):

        self.params = planet_parameters
        self.transits = True

        if not hasattr(self,'flux_transits'+planet_name):

            t0  = self.params[0] #mid-transit time
            p   = self.params[1] #orbital period
            b   = self.params[2] #impact parameter
            rho = self.params[3] #stellar density in cgs
            rp  = self.params[4] #scaled radius
            ldc = [self.params[5],self.params[6]] #LDC

            #Get the semi-major axis from the stellar density
            G_SI = 6.67408e-11 #SI
            rho = 1e3*rho #Go from cgs to SI
            a  = (rho*(p*24*3600)**2*G_SI/3./np.pi)**(1./3.)

            #Get the inclination angle from the impact parameter
            inc = np.arccos(b/a)

            #Let us use PyTransit to compute the transits
            tm = QuadraticModel(interpolate=False)
            tm.set_data(self.time)
            flux = tm.evaluate(k=rp, ldc=ldc, t0=t0, p=p, a=a, i=inc)
            #Set attribute to the class
            setattr(self,'flux_transits'+planet_name,flux)

            #self.flux = self.flux * self.flux_transits
            self.flux = self.flux * getattr(self,'flux_transits'+planet_name)
Ejemplo n.º 2
0
    def __init__(self, target: str, datasets: M2LCSet, filters: tuple, model='pb_independent_k',
                 use_oec: bool = False, period: float = 5.):
        assert (model in self.models), 'Model must be one of:\n\t' + ', '.join(self.models)
        self.model = model
        self.datasets = datasets
        self.use_oec = use_oec
        self.planet = None

        if datasets is not None:
            super().__init__(target, filters, datasets.btimes, datasets.bfluxes,
                             datasets.bwn, datasets.pbids, datasets.bcovariates,
                             tm = QuadraticModel(interpolate=True, klims=(0.01, 0.75), nk=512, nz=512))

        # Read the planet parameters from the OEC
        # ---------------------------------------
        if self.use_oec:
            with warnings.catch_warnings():
                warnings.simplefilter('ignore')
                import exodata
                exocat = exodata.OECDatabase(join(split(__file__)[0], '../ext/oec/systems/'))
            self.planet = exocat.searchPlanet(target)

        p = self.planet.P if self.planet else period
        t0 = datasets[0].time.mean() if datasets is not None else 0.0
        tce = datasets[0].time.ptp() / 10 if datasets is not None else 1e-5
        self.set_prior(0, N(t0, tce))
        self.set_prior(1, N( p, 1e-5))
Ejemplo n.º 3
0
    def __init__(self, setup: SimulationSetup, **kwargs):
        self.setup = self.s = s = setup
        self.t_exposure_d = Qty(kwargs.get('exptime', 60), 's').rescale('d')
        self.t_baseline_d = Qty(s.t_baseline, 'h').rescale('d')
        self.ldcs = s.ldcs
        self.tm = QuadraticModel(klims=(0.01, 0.99), nk=512)

        self.filters = "g' r' i' z'".split()
        self.npb = len(self.filters)
        self.k_apparent, self.p, self.a, self.b, self.i = s.orbital_parameters

        self.duration_d = Qty(
            duration_eccentric(self.p, self.k_apparent, self.a, self.i, 0, 0,
                               1), 'd')

        # Contamination
        # -------------
        qe_be = TabulatedFilter('1024B_eXcelon', [
            300, 325, 350, 400, 450, 500, 700, 800, 850, 900, 950, 1050, 1150
        ], [
            0.0, 0.1, 0.25, 0.60, 0.85, 0.92, 0.96, 0.85, 0.70, 0.50, 0.30,
            0.05, 0.0
        ])
        qe_b = TabulatedFilter(
            '2014B', [300, 350, 500, 550, 700, 800, 1000, 1050],
            [0.10, 0.20, 0.90, 0.96, 0.90, 0.75, 0.11, 0.05])
        qes = qe_be, qe_b, qe_be, qe_be

        self.instrument = instrument = Instrument(
            'MuSCAT2', (sdss_g, sdss_r, sdss_i, sdss_z), qes)
        self.contaminator = SMContamination(instrument, "i'")

        self.hteff = setup.hteff
        self.cteff = setup.cteff
        self.i_contamination = setup.c
        self.k_true = setup.k_apparent / sqrt(1 - self.i_contamination)
        self.contamination = self.contaminator.contamination(
            self.i_contamination, self.hteff, self.cteff)
Ejemplo n.º 4
0
    def test_evaluate_pvd(self):
        tm = QuadraticModel(interpolate=False)
        tm.set_data(self.time)

        pvp = array([[0.12, 0.00, 1.0, 3.0, 0.500*pi, 0.0, 0.0],
                     [0.11, 0.01, 0.9, 2.9, 0.495*pi, 0.0, 0.0]])

        ldc = [[0.1, 0.2],[0.3, 0.1]]
        flux = tm.evaluate_pv(pvp[0], ldc[0])
        assert flux.ndim == 1
        assert flux.size == self.time.size

        ldc = [[0.1, 0.2],[0.3, 0.1]]
        flux = tm.evaluate_pv(pvp, ldc)
        assert flux.ndim == 2
        assert flux.shape == (2, self.time.size)
Ejemplo n.º 5
0
  def get_light_curve(self, planet_sed, wavelength, timegrid, t0, trinsit_is_primary = True, apply_phase_curve = False):
    """ get_light_curve
    Calculate light curve models based on Mandel & MandelAgol
    
    Parameters
    ----------
    
    planet_sed         : array 
                     the planet CR
    wavelength         : array 
                         wavelength corresponding to the input CR
    timegrid           : array like the timegrid array (units of days) used to generate lightcurves
    t0                 : scalar The time at mid-transit in days
    trinsit_is_primary : boolean True for primary transit
    
    Returns
    -------
    lc         : 2D array 
                 dim=0 contains the wavelength dependence
                 dim=1 contains the time dependence
    z          : array
                 Normalised centre-centre distance
    i0, i1     : scalars
                 index of first and last contact (assuming max contrast ratio)
    
                 
                 
    """
    ##TODO REMOVE useNewCode and entire block when ready
    useNewCode = True
    setLdCoeffsToZero = not(trinsit_is_primary)
    isEclipse = not(trinsit_is_primary)
    
    u =  self.ldCoeffs.getCoeffs(self.planet.star.T, wavelength, forceZero=setLdCoeffsToZero)
    self.u = u ## required for outputing into fits file at the end
    m = QuadraticModel(is_secondary=isEclipse, klims=(0,1))
    m.set_data(timegrid.rescale(aq.day).magnitude)
    
    # m = pytransit.MandelAgol(eclipse=isEclipse )
    # z = m._calculate_z(timegrid.rescale(aq.day).magnitude,
    #             t0.rescale(aq.day), 
    #             self.planet.P.rescale(aq.day), 
    #             self.planet.a/self.planet.star.R.rescale(self.planet.a.units), 
    #             self.planet.i.rescale(aq.radians), 
    #             self.planet.e,
    #             0.0)
    lc = np.zeros( (planet_sed.size, timegrid.size) )
    k2 = (self.planet.R.rescale(aq.m)/ self.planet.a.rescale(aq.m))**2
    albedo = self.planet.albedo
    def apply_mandel_primary(i):
        # lc[i, ...] = m(z, np.sqrt(planet_sed[i]), u[i, ...]) + phase_function * (k2 * albedo) * apply_phase_curve
        lc[i, ...] = m.evaluate_ps(np.sqrt(planet_sed[i]),
                                   u[i, ...],
                                   t0.rescale(aq.day),
                                   self.planet.P.rescale(aq.day),
                                   self.planet.a/self.planet.star.R.rescale(self.planet.a.units),
                                   self.planet.i.rescale(aq.radians),
                                   self.planet.e,
                                   0.0) + phase_function * (k2 * albedo) * apply_phase_curve


    def apply_mandel_secondary(i):
        # f_e = (planet_sed[i] + (m(z, np.sqrt(planet_sed[i]), u[i, ...])-1.0))/planet_sed[i]
        # dtmp = phase_function * (k2 *albedo + planet_sed[i])  if apply_phase_curve else planet_sed[i]
        # lc[i, ...]  = 1.0 + f_e*dtmp

        f_e = (planet_sed[i] + (m.evaluate_ps(np.sqrt(planet_sed[i]),
                                              u[i, ...],
                                              t0.rescale(aq.day),
                                              self.planet.P.rescale(aq.day),
                                              self.planet.a/self.planet.star.R.rescale(self.planet.a.units),
                                              self.planet.i.rescale(aq.radians),
                                              self.planet.e,
                                              0.0)-1.0))/planet_sed[i]

        if apply_phase_curve:
            dtmp = phase_function * (k2 * albedo + planet_sed[i])
        else:
            dtmp = planet_sed[i]

        lc[i, ...] = 1.0 + f_e * dtmp


    if trinsit_is_primary:
        #phaseFactor1 = 1
        #phaseFactor2 = -1
        useMandelFunction = apply_mandel_primary
        phi = np.pi # phase in transit is pi for primari, zero for secondary
    
    else:
        #phaseFactor1 = 0
        #phaseFactor2 = 1
        useMandelFunction = apply_mandel_secondary
        phi = 0.0
            
    alpha = 2*np.pi*( timegrid.rescale(aq.day) - t0.rescale(aq.day) ) / \
                                    self.planet.P.rescale(aq.day) + phi
    ### Old - coded by Andreas
    # phase_function = (phaseFactor1 + phaseFactor2 *  np.cos(alpha))
    
    ### Lambert shpere, Seager's Exoplanet Atmospheres, eq. 3.58
    # phase_function = (np.sin(np.abs(alpha)) + (np.pi-np.abs(alpha))*np.cos(alpha))/np.pi
    
    ### Enzo's simple projection - this is the fraction of the dayside observed
    phase_function = (1+np.cos(alpha))/2.0

    # Calculate z (PyTransit no longer does this)
    # Assumes planet moves at a constant velocity (no eccentricity)
    # Calculate y component (impact parameter)
    z_y = self.planet.a.rescale(self.planet.star.R.units) / self.planet.star.R \
          * np.sin(np.pi/2 - self.planet.i.rescale(aq.radians))
    # Calculate distance of chord traveled
    d   = 2 * (((self.planet.R.rescale(self.planet.star.R.units) + \
                 self.planet.star.R) \
               / self.planet.star.R)**2 - z_y**2)**0.5
    # Velocity of planet across chord
    v   = d / self.t14.rescale(aq.day)
    # X component of z as a function of time
    z_x = v * (timegrid.rescale(aq.day) - t0.rescale(aq.day))
    # Total z vector as a function of time
    z = (z_x**2 + z_y**2)**0.5
    
    #map(useMandelFunction, np.arange(lc.shape[0]) )

    for i in np.arange(lc.shape[0]):
      useMandelFunction(i)
      
    z_12 = 1.0+planet_sed.max()
    idx = np.where(z < z_12)

    return lc, z, idx[0], idx[-1]
Ejemplo n.º 6
0
    def __init__(self,
                 target: str,
                 photometry: list,
                 tid: int,
                 cids: list,
                 filters: tuple,
                 aperture_lims: tuple = (0, inf),
                 use_opencl: bool = False,
                 n_legendre: int = 0,
                 use_toi_info=True,
                 with_transit=True,
                 with_contamination=False,
                 radius_ratio: str = 'achromatic'):
        assert radius_ratio in ('chromatic', 'achromatic')

        self.use_opencl = use_opencl
        self.planet = None

        self.photometry_frozen = False
        self.with_transit = with_transit
        self.with_contamination = with_contamination
        self.chromatic_transit = radius_ratio == 'chromatic'
        self.radius_ratio = radius_ratio
        self.n_legendre = n_legendre

        self.toi = None
        if self.with_transit and 'toi' in target.lower() and use_toi_info:
            self.toi = get_toi(float(target.lower().strip('toi')))

        # Set photometry
        # --------------
        self.phs = photometry
        self.nph = len(photometry)

        # Set the aperture ranges
        # -----------------------
        self.min_apt = amin = min(max(aperture_lims[0], 0),
                                  photometry[0].flux.aperture.size)
        self.max_apt = amax = max(
            min(aperture_lims[1], photometry[0].flux.aperture.size), 0)
        self.napt = amax - amin

        # Target and comparison star IDs
        # ------------------------------
        self.tid = atleast_1d(tid)
        if self.tid.size == 1:
            self.tid = tile(self.tid, self.nph)

        self.cids = atleast_2d(cids)
        if self.cids.shape[0] == 1:
            self.cids = tile(self.cids, (self.nph, 1))

        assert self.tid.size == self.nph
        assert self.cids.shape[0] == self.nph

        self.covnames = 'intercept sky airmass xshift yshift entropy'.split()

        times = [array(ph.bjd) for ph in photometry]
        fluxes = [
            array(ph.flux[:, tid, 1]) for tid, ph in zip(self.tid, photometry)
        ]
        fluxes = [f / nanmedian(f) for f in fluxes]
        self.apertures = ones(len(times)).astype('int')

        self.t0 = floor(times[0].min())
        times = [t - self.t0 for t in times]

        self._tmin = times[0].min()
        self._tmax = times[0].max()

        covariates = []
        for ph in photometry:
            covs = concatenate(
                [ones([ph._fmask.sum(), 1]),
                 array(ph.aux)[:, [1, 3, 4, 5]]], 1)
            covariates.append(covs)

        self.airmasses = [array(ph.aux[:, 2]) for ph in photometry]

        wns = [ones(ph.nframes) for ph in photometry]

        if use_opencl:
            import pyopencl as cl
            ctx = cl.create_some_context()
            queue = cl.CommandQueue(ctx)
            tm = QuadraticModelCL(klims=(0.005, 0.25),
                                  nk=512,
                                  nz=512,
                                  cl_ctx=ctx,
                                  cl_queue=queue)
        else:
            tm = QuadraticModel(interpolate=True,
                                klims=(0.005, 0.25),
                                nk=512,
                                nz=512)

        super().__init__(target,
                         filters,
                         times,
                         fluxes,
                         wns,
                         arange(len(photometry)),
                         covariates,
                         arange(len(photometry)),
                         tm=tm)

        self.legendre = [
            legvander((t - t.min()) / (0.5 * t.ptp()) - 1,
                      self.n_legendre)[:, 1:] for t in self.times
        ]

        # Create the target and reference star flux arrays
        # ------------------------------------------------
        self.ofluxes = [
            array(ph.flux[:, self.tid[i], amin:amax + 1] /
                  ph.flux[:, self.tid[i], amin:amax + 1].median('mjd'))
            for i, ph in enumerate(photometry)
        ]

        self.refs = []
        for ip, ph in enumerate(photometry):
            self.refs.append([
                pad(array(ph.flux[:, cid, amin:amax + 1]), ((0, 0), (1, 0)),
                    mode='constant') for cid in self.cids[ip]
            ])

        self.set_orbit_priors()
Ejemplo n.º 7
0
import numpy as np
from astropy import constants
from pytransit import QuadraticModel

Msun = constants.M_sun.cgs.value
Rsun = constants.R_sun.cgs.value
Rearth = constants.R_earth.cgs.value
G = constants.G.cgs.value
au = constants.au.cgs.value
pi = np.pi

tm = QuadraticModel(interpolate=False)


def simulate_TP_transit(time: np.ndarray,
                        R_p: float,
                        P_orb: float,
                        inc: float,
                        a: float,
                        R_s: float,
                        u1: float,
                        u2: float,
                        companion_fluxratio: float = 0.0,
                        companion_is_host: bool = False):
    """
    Simulates a transiting planet light curve using PyTransit.
    Args:
        time (numpy array): Time of each data point
                            [days from transit midpoint].
        R_p (float): Planet radius [Earth radii].
        P_orb (float): Orbital period [days].
Ejemplo n.º 8
0
class MockLC:
    pb_names = "g' r' i' z'".split()
    pb_centers = 1e-9 * array([470, 640, 780, 900])
    npb = len(pb_names)

    def __init__(self, setup: SimulationSetup, **kwargs):
        self.setup = self.s = s = setup
        self.t_exposure_d = Qty(kwargs.get('exptime', 60), 's').rescale('d')
        self.t_baseline_d = Qty(s.t_baseline, 'h').rescale('d')
        self.ldcs = s.ldcs
        self.tm = QuadraticModel(klims=(0.01, 0.99), nk=512)

        self.filters = "g' r' i' z'".split()
        self.npb = len(self.filters)
        self.k_apparent, self.p, self.a, self.b, self.i = s.orbital_parameters

        self.duration_d = Qty(
            duration_eccentric(self.p, self.k_apparent, self.a, self.i, 0, 0,
                               1), 'd')

        # Contamination
        # -------------
        qe_be = TabulatedFilter('1024B_eXcelon', [
            300, 325, 350, 400, 450, 500, 700, 800, 850, 900, 950, 1050, 1150
        ], [
            0.0, 0.1, 0.25, 0.60, 0.85, 0.92, 0.96, 0.85, 0.70, 0.50, 0.30,
            0.05, 0.0
        ])
        qe_b = TabulatedFilter(
            '2014B', [300, 350, 500, 550, 700, 800, 1000, 1050],
            [0.10, 0.20, 0.90, 0.96, 0.90, 0.75, 0.11, 0.05])
        qes = qe_be, qe_b, qe_be, qe_be

        self.instrument = instrument = Instrument(
            'MuSCAT2', (sdss_g, sdss_r, sdss_i, sdss_z), qes)
        self.contaminator = SMContamination(instrument, "i'")

        self.hteff = setup.hteff
        self.cteff = setup.cteff
        self.i_contamination = setup.c
        self.k_true = setup.k_apparent / sqrt(1 - self.i_contamination)
        self.contamination = self.contaminator.contamination(
            self.i_contamination, self.hteff, self.cteff)

    @property
    def t_total_d(self):
        return self.duration_d + 2 * self.t_baseline_d

    @property
    def duration_h(self):
        return self.duration_d.rescale('h')

    @property
    def n_exp(self):
        return int(self.t_total_d // self.t_exposure_d)

    def __call__(self,
                 rseed=0,
                 ldcs=None,
                 wnsigma=None,
                 rnsigma=None,
                 rntscale=0.5):
        return self.create(rseed, ldcs, wnsigma, rnsigma, rntscale)

    def create(self,
               rseed=0,
               ldcs=None,
               wnsigma=None,
               rnsigma=None,
               rntscale=0.5,
               nights=1):
        ldcs = ldcs if ldcs is not None else self.ldcs
        seed(rseed)

        self.time = linspace(-0.5 * float(self.t_total_d),
                             0.5 * float(self.t_total_d), self.n_exp)
        self.time = (tile(self.time, [nights, 1]) +
                     (self.p * arange(nights))[:, newaxis]).ravel()
        self.npt = self.time.size
        self.tm.set_data(self.time)

        self.transit = zeros([self.npt, 4])
        for i, (ldc, c) in enumerate(zip(ldcs, self.contamination)):
            self.transit[:, i] = self.tm.evaluate_ps(self.k_true, ldc, 0,
                                                     self.p, self.a, self.i)
            self.transit[:, i] = c + (1 - c) * self.transit[:, i]

        # White noise
        # -----------
        if wnsigma is not None:
            self.wnoise = multivariate_normal(
                zeros(atleast_2d(self.transit).shape[1]),
                diag(wnsigma)**2, self.npt)
        else:
            self.wnoise = zeros_like(self.transit)

        # Red noise
        # ---------
        if rnsigma and with_george:
            self.gp = GP(rnsigma**2 * ExpKernel(rntscale))
            self.gp.compute(self.time)
            self.rnoise = self.gp.sample(self.time, self.npb).T
            self.rnoise -= self.rnoise.mean(0)
        else:
            self.rnoise = zeros_like(self.transit)

        # Final light curve
        # -----------------
        self.time_h = Qty(self.time, 'd').rescale('h')
        self.flux = self.transit + self.wnoise + self.rnoise
        return self.lcdataset

    @property
    def lcdataset(self):
        return LCDataSet([
            LCData(self.time, flux, pb)
            for pb, flux in zip(self.pb_names, self.flux.T)
        ], self.instrument)

    def plot(self, figsize=(13, 4), yoffset=0.01):
        fig, axs = pl.subplots(1,
                               3,
                               figsize=figsize,
                               sharex='all',
                               sharey='all')
        yshift = yoffset * arange(4)
        axs[0].plot(self.time_h, self.flux + yshift)
        axs[1].plot(self.time_h, self.transit + yshift)
        axs[2].plot(self.time_h, 1 + self.rnoise + yshift)
        pl.setp(axs, xlabel='Time [h]', xlim=self.time_h[[0, -1]])
        pl.setp(axs[0], ylabel='Normalised flux')
        [
            pl.setp(ax, title=title) for ax, title in zip(
                axs, 'Transit model + noise, Transit model, Red noise'.split(
                    ', '))
        ]
        fig.tight_layout()
        return fig, axs

    def plot_color_difference(self, figsize=(13, 4)):
        fig, axs = pl.subplots(2,
                               3,
                               figsize=figsize,
                               sharex='all',
                               sharey='all')
        [
            ax.plot(self.time_h, 100 * (fl - self.transit[:, -1]))
            for ax, fl in zip(axs[0], self.transit[:, :-1].T)
        ]
        [
            ax.plot(self.time_h, 100 * (fl - self.flux[:, -1]))
            for ax, fl in zip(axs[1], self.flux[:, :-1].T)
        ]
        [
            pl.setp(ax, title='F$_{}$ - F$_z$'.format(pb))
            for ax, pb in zip(axs[0], self.pb_names[:-1])
        ]
        pl.setp(axs[:, 0], ylabel='$\Delta F$ [%]')
        pl.setp(axs[1, :], xlabel='Time [h]')
        pl.setp(axs, xlim=self.time_h[[0, -1]])
        fig.tight_layout()
        return fig
Ejemplo n.º 9
0
def get_light_curve(opt, planet_sed, wavelength, obs_type):

    wavelength = wavelength.value
    timegrid = opt.z_params[0]
    t0 = opt.z_params[1]
    per = opt.z_params[2]
    ars = opt.z_params[3]
    inc = opt.z_params[4]
    ecc = opt.z_params[5]
    omega = opt.z_params[6]

    if opt.observation.obs_type.val == 2:
        opt.timeline.useLDC.val = 0

    if opt.timeline.useLDC.val == 0:  # linear ldc
        jexosim_msg('LDCs set to zero', 1)
        u0 = np.zeros(len(wavelength))
        u1 = np.zeros(len(wavelength))
        ldc = np.vstack((wavelength, u0, u1))
    elif opt.timeline.useLDC.val == 1:  # use to get ldc from filed values
        u0, u1 = getLDC_interp(opt, opt.planet.planet, wavelength)
        ldc = np.vstack((wavelength, u0, u1))

    gamma = np.zeros((ldc.shape[1], 2))
    gamma[:, 0] = ldc[1]
    gamma[:, 1] = ldc[2]
    jexosim_plot('ldc', opt.diagnostics, ydata=ldc[1])
    jexosim_plot('ldc', opt.diagnostics, ydata=ldc[2])
    tm = QuadraticModel(interpolate=False)
    tm.set_data(timegrid)

    lc = np.zeros((len(planet_sed), len(timegrid)))

    if obs_type == 1:  #primary transit
        for i in range(len(planet_sed)):
            k = np.sqrt(planet_sed[i]).value
            lc[i, ...] = tm.evaluate(k=k,
                                     ldc=gamma[i, ...],
                                     t0=t0,
                                     p=per,
                                     a=ars,
                                     i=inc,
                                     e=ecc,
                                     w=omega)
            jexosim_plot('light curve check',
                         opt.diagnostics,
                         ydata=lc[i, ...])
    elif obs_type == 2:  # secondary eclipse
        for i in range(len(planet_sed)):
            k = np.sqrt(planet_sed[i])  # planet star radius ratio
            lc_base = tm.evaluate(k=k,
                                  ldc=[0, 0],
                                  t0=t0,
                                  p=per,
                                  a=ars,
                                  i=inc,
                                  e=ecc,
                                  w=omega)
            jexosim_plot('light curve check', opt.diagnostics, ydata=lc_base)
            # f_e = (planet_sed[i] + (   lc_base  -1.0))/planet_sed[i]
            # lc[i, ...]  = 1.0 + f_e*(planet_sed[i])

            lc[i, ...] = lc_base + planet_sed[i]
            jexosim_plot('light curve check',
                         opt.diagnostics,
                         ydata=lc[i, ...])

    return lc, ldc
Ejemplo n.º 10
0
 def test_evaluate_3i(self):
     tm = QuadraticModel(interpolate=True)
     tm.set_data(self.time, self.lcids, self.pbids)
     flux = tm.evaluate(self.radius_ratios[0], self.ldc[0], self.zero_epochs[0], self.periods[0], self.smas[0], self.inclinations[0])
     assert flux.ndim == 1
     assert flux.size == self.time.size
Ejemplo n.º 11
0
    def test_set_data(self):
        tm = QuadraticModel(interpolate=False)
        tm.set_data(self.time)
        assert tm.npb == 1

        tm.set_data(self.time, lcids=self.lcids)
        assert tm.npb == 1

        tm.set_data(self.time, lcids=self.lcids, pbids=self.pbids)
        assert tm.npb == 2

        tm = QuadraticModel(interpolate=True)
        tm.set_data(self.time)
        assert tm.npb == 1

        tm.set_data(self.time, lcids=self.lcids)
        assert tm.npb == 1

        tm.set_data(self.time, lcids=self.lcids, pbids=self.pbids)
        assert tm.npb == 2
Ejemplo n.º 12
0
 def test_init(self):
     QuadraticModel()
     QuadraticModel(interpolate=True)
     QuadraticModel(interpolate=False)
Ejemplo n.º 13
0
 def test_evaluate_psd(self):
     tm = QuadraticModel(interpolate=False)
     tm.set_data(self.time)
     flux = tm.evaluate(0.1, [0.2, 0.3], 0.0, 1.0, 3.0, 0.5*pi)
     assert flux.ndim == 1
     assert flux.size == self.time.size
    G = 6.674e-11
    period_seconds = period * 24. * 3600.
    mass_kg = star_mass * 2.e30
    a1 = (G * mass_kg * period_seconds**2 / 4. / (np.pi**2))**(1. / 3.)
    return a1 / 1.496e11


a_au = calculate_semi_major_axis(0.5, M_s)
a_Rs = a_au / (R_s * 0.00465047)
# TODO start with rp_rs that causes twice depth than curve RMS
curve_rms = np.std(flux)
min_depth = 2 * curve_rms
initial_rp = (min_depth * (R_s**2))**(1 / 2)
rp_rs = initial_rp / R_s
from pytransit import QuadraticModel
tm = QuadraticModel()
time_model = np.arange(0, 1, 0.0001)
tm.set_data(time_model)
# k is the radius ratio, ldc is the limb darkening coefficient vector, t0 the zero epoch, p the orbital period, a the
# semi-major axis divided by the stellar radius, i the inclination in radians, e the eccentricity, and w the argument
# of periastron. Eccentricity and argument of periastron are optional, and omitting them defaults to a circular orbit.
model = tm.evaluate(k=rp_rs,
                    ldc=ld_coefficients,
                    t0=0.5,
                    p=1.0,
                    a=a_Rs,
                    i=0.5 * np.pi)
model = model[model < 1]
baseline_model = np.full(len(model), 1)
model = np.append(baseline_model, model)
model = np.append(model, baseline_model)
Ejemplo n.º 15
0
    def __call__(self, npop: int = 40, de_niter: int = 1000, mcmc_niter: int = 200, mcmc_repeats: int = 3, initialize_only: bool = False):
        self.logger = getLogger(f"{self.name}:{self.ts.name.lower().replace('_','-')}")
        self.logger.info(f"Fitting {self.mode} transits")
        self.ts.transit_fits[self.mode] = self

        epochs = epoch(self.ts.time, self.ts.zero_epoch, self.ts.period)

        if self.mode == 'all':
            mask = ones(self.ts.time.size, bool)
        elif self.mode == 'even':
            mask = epochs % 2 == 0
        elif self.mode == 'odd':
            mask = epochs % 2 == 1
        else:
            raise NotImplementedError

        mask &= abs(self.ts.phase - 0.5*self.ts.period) < 4 * 0.5 * self.ts.duration

        self.ts.transit_fit_masks[self.mode] = self.mask = mask

        self.epochs = epochs = epochs[mask]
        self.time = self.ts.time[mask]
        self.fobs = self.ts.flux[mask]

        tref = floor(self.time.min())
        tm = QuadraticModelCL(klims=(0.01, 0.60)) if self.use_opencl else QuadraticModel(interpolate=False)
        self.lpf = lpf = SearchLPF(times=self.time, fluxes=self.fobs, epochs=epochs, tm=tm,
                        nsamples=self.nsamples, exptimes=self.exptime, tref=tref)

        # TODO: V-shaped transits are not always modelled well. Need to set smarter priors (or starting population)
        #       for the impact parameter and stellar density.
        lpf.set_prior('rho', 'UP', 0.01, 25)
        if self.mode == 'all':
            d  = min(self.ts.depth, 0.75)
            lpf.set_prior('tc', 'NP', self.ts.zero_epoch, 0.01)
            lpf.set_prior('p',  'NP', self.ts.period, 0.001)
            lpf.set_prior('k2', 'UP', max(0.01**2, 0.5*d), min(max(0.08**2, 4*d), 0.75**2))
        else:
            pr = self.ts.tf_all.parameters
            lpf.set_prior('tc', 'NP', pr.tc.med, 5*pr.tc.err)
            lpf.set_prior('p',  'NP', pr.p.med, pr.p.err)
            lpf.set_prior('k2', 'UP', max(0.01**2, 0.5 * pr.k2.med), max(0.08**2, min(0.6**2, 2 * pr.k2.med)))
            lpf.set_prior('q1', 'NP', pr.q1.med, pr.q1.err)
            lpf.set_prior('q2', 'NP', pr.q2.med, pr.q2.err)

        # TODO: The limb darkening table has been computed for TESS. Needs to be made flexible.
        if self.ts.teff is not None:
            ldcs = Table.read(Path(__file__).parent / "data/ldc_table.fits").to_pandas()
            ip = interp1d(ldcs.teff, ldcs[['q1', 'q2']].T)
            q1, q2 = ip(clip(self.ts.teff, 2000., 12000.))
            lpf.set_prior('q1', 'NP', q1, 1e-5)
            lpf.set_prior('q2', 'NP', q2, 1e-5)

        if initialize_only:
            return
        else:
            lpf.optimize_global(niter=de_niter, npop=npop, use_tqdm=self.use_tqdm, plot_convergence=False)
            lpf.sample_mcmc(mcmc_niter, repeats=mcmc_repeats, use_tqdm=self.use_tqdm, leave=False)
            df = lpf.posterior_samples(derived_parameters=True)
            df = pd.DataFrame((df.median(), df.std()), index='med err'.split())
            pv = lpf.posterior_samples(derived_parameters=False).median().values
            self.phase = fold(self.time, pv[1], pv[0], 0.5) * pv[1] - 0.5 * pv[1]
            self.fmod = lpf.flux_model(pv)
            self.ftra = lpf.transit_model(pv)
            self.fbase = lpf.baseline(pv)

            # Calculate the per-orbit log likelihood differences
            # --------------------------------------------------
            ues = unique(epochs)
            lnl = zeros(ues.size)
            err = 10 ** pv[7]

            def lnlike_normal(o, m, e):
                npt = o.size
                return -npt * log(e) - 0.5 * npt * log(2. * pi) - 0.5 * sum((o - m) ** 2 / e ** 2)

            for i, e in enumerate(ues):
                m = epochs == e
                lnl[i] = lnlike_normal(self.fobs[m], self.fmod[m], err) - lnlike_normal(self.fobs[m], 1.0, err)

            self.parameters = df
            self.dll_epochs = ues
            self.dll_values = lnl

            self.zero_epoch = df.tc.med
            self.period = df.p.med
            self.duration = df.t14.med
            self.depth = df.k2.med

            if self.mode == 'all':
                self.delta_bic = self.ts.dbic = delta_bic(lnl.sum(), 0, 9, self.time.size)
                self.ts.update_ephemeris(self.zero_epoch, self.period, self.duration, self.depth)
Ejemplo n.º 16
0
    def add_transits(self,pars,ldc):
        """
        This method includes the planets to the instance detrending
        It assumes all orbits are circular
        pars -> [T0, P, a/R*,b, Rp/R*] x Number of planets
        ldc  -> u1, u2
        """

        #Initialise the planet-related fluxes
        #this attribute contains only the planetary models for each self.time
        self.flux_planet = np.ones(len(self.time))
        #this attribute contains only the planetary models for each self.time_bin
        self.flux_planet_bin = np.ones(len(self.time_bin))
        #this attribute contains only the planetary models for each self.time_model
        self.flux_planet_model = np.ones(len(self.time_model))

        #Add parameters to the class
        #This attribute constains all the parameters for all the planets
        self.planet_pars = pars
        #this attribute constains the limb darkening coefficients following a Mandel & Agol model
        self.ldc = ldc

        #number of planets to be added
        npl = int(len(pars)/5)
        #Save the number of planets as an attribute
        self.nplanets = npl
        #We compute the model with pytransit for self.time
        tm = QuadraticModel()
        tm.set_data(self.time)
        #We compute the model with pytransit for self.time_bin
        tm_bin = QuadraticModel()
        tm_bin.set_data(self.time_bin)
        #We compute the model with pytransit for self.time_model
        tm_model = QuadraticModel()
        tm_model.set_data(self.time_model)
        #Compute the models for all the time-series
        for i in range(npl):
            incl = np.arccos(pars[3+5*i]/pars[2+5*i])
            self.flux_planet        *= tm.evaluate(t0=pars[0+5*i], p=pars[1+5*i], a=pars[2+5*i], i=incl,k=pars[4+5*i], ldc=ldc)
            self.flux_planet_bin    *= tm_bin.evaluate(t0=pars[0+5*i], p=pars[1+5*i], a=pars[2+5*i], i=incl,k=pars[4+5*i], ldc=ldc)
            self.flux_planet_model *= tm_model.evaluate(t0=pars[0+5*i], p=pars[1+5*i], a=pars[2+5*i], i=incl,k=pars[4+5*i], ldc=ldc)

        #Remove the planet model from the no_planet and no_planet_bin models in order to have a light curve with no planets
        self.flux_no_planet = self.flux / self.flux_planet
        self.flux_no_planet_bin = self.flux_bin / self.flux_planet_bin