예제 #1
0
def transit_model(theta, t, exp_time=0.002):
    params = TransitParams()
    t0, p, k, r, b, q1, q2 = theta[:7]
    u1, u2 = q_to_u(q1, q2)
    a = arstar(p, r)
    i = inclination(a, b)
    params.t0 = t0  #time of inferior conjunction
    params.per = p  #orbital period
    params.rp = k  #planet radius (in units of stellar radii)
    params.a = a  #semi-major axis (in units of stellar radii)
    params.inc = i  #orbital inclination (in degrees)
    params.ecc = 0.  #eccentricity
    params.w = 90.  #longitude of periastron (in degrees)
    params.u = [u1, u2]  #limb darkening coefficients
    params.limb_dark = "quadratic"
    m = TransitModel(params, t, supersample_factor=1, exp_time=exp_time)
    # m = TransitModel(params, t)
    return m.light_curve(params)
예제 #2
0
    def light_curve(self,
                    spot_lons,
                    spot_lats,
                    spot_radii,
                    inc_stellar,
                    planet=None,
                    times=None,
                    fast=False,
                    time_ref=None,
                    return_spots_occulted=False,
                    transit_model_kwargs={}):
        """
        Generate a(n ensemble of) light curve(s).

        Light curve output will have shape ``(n_phases, len(inc_stellar))`` or
        ``(len(times), len(inc_stellar))``.

        Parameters
        ----------
        spot_lons : `~numpy.ndarray`
            Spot longitudes
        spot_lats : `~numpy.ndarray`
            Spot latitudes
        spot_radii : `~numpy.ndarray`
            Spot radii
        inc_stellar : `~numpy.ndarray`
            Stellar inclinations
        planet : `~batman.TransitParams`, optional
            Transiting planet parameters
        times : `~numpy.ndarray`, optional
            Times at which to compute the light curve
        fast : bool, optional
            When `True`, use approximation that spots are fixed on the star
            during a transit event. When `False`, account for motion of
            starspots on stellar surface due to rotation during transit event.
            Default is `False`.
        time_ref : float, optional
            Reference time used as the initial rotational phase of the star,
            such that the sub-observer point is at zero longitude at
            ``time_ref``.
        return_spots_occulted : bool, optional
            Return whether or not spots have been occulted.

        Returns
        -------
        light_curves : `~numpy.ndarray`
            Stellar light curves of shape ``(n_phases, len(inc_stellar))`` or
            ``(len(times), len(inc_stellar))``
        """
        if time_ref is None:
            if times is not None:
                time_ref = 0
            else:
                time_ref = self.phases[0]

        # Compute the spot positions in cartesian coordinates:
        tilted_spots = self.spherical_to_cartesian(spot_lons,
                                                   spot_lats,
                                                   inc_stellar,
                                                   times=times,
                                                   planet=planet,
                                                   time_ref=time_ref)

        # Compute the distance of each spot from the stellar centroid, mask
        # any spots that are "behind" the star, in other words, x < 0
        r = np.ma.masked_array(np.hypot(tilted_spots.y.value,
                                        tilted_spots.z.value),
                               mask=tilted_spots.x.value < 0)
        ld = limb_darkening_normed(self.u_ld, r)

        # Compute the out-of-transit flux missing due to each spot
        f_spots = (np.pi * spot_radii**2 * (1 - self.spot_contrast) * ld *
                   np.sqrt(1 - r**2))

        if planet is None:
            # If there is no transiting planet, skip the transit routine:
            lambda_e = np.zeros((len(self.phases), 1))
        else:
            if not inc_stellar.isscalar:
                raise ValueError('Transiting exoplanets are implemented for '
                                 'planets transiting single stars only, but '
                                 '``inc_stellar`` has multiple values. ')
            # Compute a transit model
            from batman import TransitModel

            n_spots = len(spot_lons)
            m = TransitModel(planet, times, **transit_model_kwargs)
            lambda_e = 1 - m.light_curve(planet)[:, np.newaxis]
            # Compute the true anomaly of the planet at each time, f:
            f = m.get_true_anomaly()

            # Compute the position of the planet in cartesian coordinates using
            # Equations 53-55 of Murray & Correia (2010). Note that these
            # coordinates are different from the cartesian coordinates used for
            # the spot positions. In this system, the observer is at X-> -inf.
            I = np.radians(90 - planet.inc)
            Omega = np.radians(planet.w)  # this is 90 deg by default
            omega = np.pi / 2
            X = planet.a * (np.cos(Omega) * np.cos(omega + f) -
                            np.sin(Omega) * np.sin(omega + f) * np.cos(I))
            Y = planet.a * (np.sin(Omega) * np.cos(omega + f) +
                            np.cos(Omega) * np.sin(omega + f) * np.cos(I))
            Z = planet.a * np.sin(omega + f) * np.sin(I)

            # Create a shapely circle object for the planet's silhouette only
            # when the planet is in front of the star, otherwise append `None`
            planet_disk = [
                circle([-Y[i], -Z[i]], planet.rp) if
                (np.abs(Y[i]) < 1 + planet.rp) and (X[i] < 0) else None
                for i in range(len(f))
            ]

            if fast:
                spots_occulted = self._planet_spot_overlap_fast(
                    planet, planet_disk, tilted_spots, spot_radii, n_spots, X,
                    Y, lambda_e)
            else:
                spots_occulted = self._planet_spot_overlap_slow(
                    planet, planet_disk, tilted_spots, spot_radii, n_spots, X,
                    Y, lambda_e)

        # Return the flux missing from the star at each time due to spots
        # (f_spots/self.f0) and due to the transit (lambda_e):
        if return_spots_occulted:
            return (1 - np.sum(f_spots.filled(0) / self.f0, axis=1) - lambda_e,
                    spots_occulted)

        else:
            return 1 - np.sum(f_spots.filled(0) / self.f0, axis=1) - lambda_e