Forward Model

Single Spot

Perhaps the best way to learn how dot works is to experiment with it, which we will do in this tutorial. Let’s suppose first we have a star with a single spot, defined its latitude, longitude, and radius. We’ll place the star on the prime meridian (zero point in longitude) and the equator. We’ll give the star a rotation period of 0.5 days, and the spot will have contrast 0.3. To do this, we’ll first need to generate an instance of the Model object:

import pymc3 as pm
import numpy as np
from lightkurve import LightCurve

from dot import Model

times = np.linspace(-1, 1, 1000)
fluxes = np.zeros_like(times)
errors = np.ones_like(times)

rotation_period = 0.5  # days
stellar_inclination = 90  # deg

m = Model(
    light_curve=LightCurve(times, fluxes, errors),
    rotation_period=rotation_period,
    n_spots=1,
    contrast=0.3
)

Now that our Model is specified and the time points are defined in the LightCurve object, we can specify the spot properties:

# Create a starting point for the dot model
start_params = {
    "dot_R_spot": np.array([0.1]),
    "dot_lat": np.array([np.pi/2]),
    "dot_lon": np.array([0]),
    "dot_comp_inc": np.radians(90 - stellar_inclination),
    "dot_ln_shear": -3,
    "dot_P_eq": rotation_period,
    "dot_f0": 1
}

# Need to call this to validate ``start``
pm.util.update_start_vals(start, m.pymc_model.test_point, m.pymc_model)

We specify spot properties with a dictionary which contains the spot radii, latitudes, longitudes, the complementary angle to the stellar inclination, the natural log of the shear rate, the equatorial rotation period and the baseline flux of the star. We then call update_start_vals on the dictionary with our Model object, which translates the user-facing, human-friendly coordinates into the optimizer-friendly transformed coordinates.

We can now call our model on the start dictionary, and plot it like so:

import matplotlib.pyplot as plt

forward_model_start = m(start_params)

plt.plot(m.lc.time[m.mask], m.lc.flux[m.mask], m.lc.flux_err[m.mask],
         color='k', fmt='.', ecolor='silver')
plt.plot(m.lc.time[m.mask][::m.skip_n_points], forward_model_start,
         color='DodgerBlue')
plt.show()

(Source code, png, hires.png, pdf)

../_images/forwardmodel-1.png

In the above plot, we see the forward model for the spot modulation of a single spot on a rotating star.

Differentially rotating spots

The syntax is similar for multiple spots, we just add extra elements to the numpy arrays which determine the spot parameters, like so:

m = Model(
    light_curve=LightCurve(times, fluxes, errors),
    rotation_period=rotation_period,
    n_spots=2,
    contrast=0.3
)

# Create a starting point for the dot model
two_spot_params = {
    "dot_R_spot": np.array([[0.1, 0.05]]),
    "dot_lat": np.array([[np.pi/2, np.pi/4]]),
    "dot_lon": np.array([[0, np.pi]]),
    "dot_comp_inc": np.radians(90 - stellar_inclination),
    "dot_ln_shear": np.log(0.2),
    "dot_P_eq": rotation_period,
    "dot_f0": 1
}

Note this time that we’ve set the shear rate to 0.2, which is the solar shear rate. This time when we plot the result we’ll see a more complicated model:

(Source code, png, hires.png, pdf)

../_images/forwardmodel-2.png

Now you can see the effect of differential rotation on the light curve – the smaller, higher latitude spot is rotating around the stellar surface with a different rate than the large, equatorial spot.