Ejemplo n.º 1
0
def learn_map(high_snr=False):
    """
    In this case, we know the spectrum and the baseline
    perfectly. The problem is linear in the map, so solving
    the Doppler problem is easy!

    """
    # High or low SNR?
    if high_snr:
        ferr = 1e-4
        name = "learn_map_high_snr"
    else:
        ferr = 1e-3
        name = "learn_map_low_snr"

    # Generate data
    dop = pp.Doppler(ydeg=15)
    dop.generate_data(ferr=ferr)

    # Compute the true baseline (assumed to be known exactly)
    dop.u = dop.u_true
    baseline = dop.baseline()

    # Reset all coefficients
    dop.vT = dop.vT_true
    dop.u = None

    # Solve!
    loss, cho_u, cho_vT = dop.solve(vT=dop.vT, baseline=baseline)
    plot_results(dop, name=name, loss=loss, cho_u=cho_u, cho_vT=cho_vT)
Ejemplo n.º 2
0
def learn_map_and_baseline(high_snr=False):
    """
    In this case, we know the rest frame spectrum, but we don't
    know the map coefficients or the baseline flux. The problem
    can be linearized to solve for the coefficients, and then
    refined with the non-linear solver.

    """
    # High or low SNR?
    if high_snr:
        # At high SNR, we need to do a bit of refinement
        # with the non-linear solver.
        ferr = 1e-4
        niter = 50
        lr = 1e-4
        name = "learn_map_baseline_high_snr"
    else:
        # At low SNR, a single run of the bi-linear solver
        # gets us to the optimum!
        ferr = 1e-3
        niter = 0
        lr = None
        name = "learn_map_baseline_low_snr"

    # Generate data
    dop = pp.Doppler(ydeg=15)
    dop.generate_data(ferr=ferr)

    # Reset all coefficients
    dop.vT = dop.vT_true
    dop.u = None

    # Solve!
    loss, cho_u, cho_vT = dop.solve(vT=dop.vT, niter=niter, lr=lr)
    plot_results(dop, name=name, loss=loss, cho_u=cho_u, cho_vT=cho_vT)
Ejemplo n.º 3
0
def flux(lam, t, A, ydeg=5, vsini=40.0, inc=60.0, P=1.0):
    N = (ydeg + 1) ** 2
    doppler = pp.Doppler(lam, ydeg=ydeg, vsini=vsini, inc=inc, P=P)
    G = doppler._g()
    map = starry.Map(ydeg, nw=len(doppler.lam_padded))
    axis = map.ops.get_axis(inc * np.pi / 180.0, 0.0)
    theta = (2 * np.pi / P * t) % (2 * np.pi)
    F = tt.as_tensor_variable(
        [
            convdot(map.ops.rotate(axis, th, A), G, N)
            for n, th in enumerate(theta)
        ]
    )
    return F
Ejemplo n.º 4
0
def learn_everything(high_snr=False):
    """
    In this case, we know nothing: we're going to learn
    both the map and the spectrum. We're not giving the
    algorithm an initial guess, either: the spectrum is
    learned by deconvolving the data, and the initial
    guess for the map is computed via the linearized
    problem.

    """
    # High or low SNR?
    if high_snr:
        # We rely heavily on tempering here. Once we get
        # a good initial guess via the bilinear solver,
        # we run the non-linear solver with a slow learning
        # rate.
        ferr = 1e-4
        T = 5000.0
        niter = 1000
        lr = 1e-4
        name = "learn_everything_high_snr"
    else:
        # This case is easier; just a little tempering for
        # good measure, followed by a fast non-linear
        # refinement.
        ferr = 1e-3
        T = 10.0
        niter = 250
        lr = 2e-3
        name = "learn_everything_low_snr"

    # Generate data
    dop = pp.Doppler(ydeg=15)
    dop.generate_data(ferr=ferr)

    # Reset all coefficients
    dop.u = None
    dop.vT = None

    # Solve!
    loss, cho_u, cho_vT = dop.solve(niter=niter, lr=lr, T=T)
    plot_results(dop, name=name, loss=loss, cho_u=cho_u, cho_vT=cho_vT)
Ejemplo n.º 5
0
 def load_data(self, t, lam, F, ferr=1.e-4):
     """Load a dataset.
     
     Args:
         t (ndarray): Time array in days.
         lam (ndarray): Uniformly spaced log-wavelength array.
         F (ndarray): Matrix of observed spectra of shape `(nt, nlam)`.
         ferr (float, optional): Uncertainty on the flux. Defaults to 1.e-4.
     """
     doppler = pp.Doppler(lam, ydeg=self.ydeg, 
                          vsini=self.vsini, 
                          inc=self.inc)
     self.theta = (360.0 * t) % 360.0
     self.D = doppler.D(theta=self.theta)
     self.lam_padded = doppler.lam_padded
     self.t = t
     self.lam = lam
     self.F = F
     self.ferr = ferr
     self.M, self.K = self.F.shape
     self.Kp = self.D.shape[1] // self.N
     self._loaded = True
Ejemplo n.º 6
0
guess for the map is computed via the linearized
problem.

"""
import paparazzi as pp
import numpy as np
from utils.spot import plot_results

np.random.seed(13)

# Let's plot the high SNR case for the paper
ferr = 1e-4
T = 5000.0
niter = 3000
lr = 2.5e-5
dlogT = -0.04

# Generate data
dop = pp.Doppler(ydeg=15, u=[0.5, 0.25])
dop.generate_data(ferr=ferr)

# Reset all coefficients
dop.y1 = None
dop.s = None

# Solve!
loss, cho_y1, cho_s = dop.solve(niter=niter, lr=lr, T=T, dlogT=dlogT)

# Plot the results
plot_results(dop, name="spot_y1bs", loss=loss, cho_y1=cho_y1, cho_s=cho_s)
Ejemplo n.º 7
0
# Get the Ylm expansion of a Gaussian spot
ydeg = 20
N = (ydeg + 1)**2
map = starry.Map(ydeg)
map.add_spot(amp=-0.03, sigma=0.05, lat=30, lon=0)
y1 = np.array(map.y.eval())[1:]

# Check that the specific intensity is positive everywhere
assert np.nanmin(map.render().eval()) > 0

# Generate the dataset
vsini = 40.0  # km/s
nt = 15
theta = np.append([-180], np.linspace(-90, 90, nt))
dop = pp.Doppler(ydeg, vsini=vsini, inc=90)
dop.generate_data(y1=y1,
                  R=3.0e5,
                  nlam=149,
                  sigma=2.0e-5,
                  nlines=1,
                  theta=theta,
                  ferr=0.0)
lnlam = dop.lnlam
F0 = dop.F[0]
F = dop.F[1:]

# Render the images
img = map.render(theta=theta[1:], res=100).eval()

# Set up the plot
Ejemplo n.º 8
0
    def generate_data(self, R=3e5, nlam=200, sigma=7.5e-6, nlines=20, nt=11, 
                      ferr=1.e-4, image="vogtstar.jpg"):
        """Generate a synthetic dataset.
        
        Args:
            R (float, optional): The spectral resolution. Defaults to 3e5.
            nlam (int, optional): Number of observed wavelength bins. 
                Defaults to 200.
            sigma (float, optional): Line width in log space. Defaults to 7.5e-6,
                equivalent to ~0.05A at 6430A.
            nlines (int, optional): Number of additional small lines to include. 
                Defaults to 20.
            nt (int, optional): Number of spectra. Defaults to 11.
            ferr (float, optional): Gaussian error to add to the fluxes. 
                Defaults to 1.e-3
            image (string, optional): Path to the image to expand in Ylms.
                Defaults to "vogtstar.jpg"
        """
        # The time array in units of the period
        t = np.linspace(-0.5, 0.5, nt + 1)[:-1]

        # The log-wavelength array
        dlam = np.log(1.0 + 1.0 / R)
        lam = np.arange(-(nlam // 2), nlam // 2 + 1) * dlam

        # Pre-compute the Doppler basis
        doppler = pp.Doppler(lam, ydeg=self.ydeg, 
                             vsini=self.vsini, 
                             inc=self.inc)
        theta = (360.0 * t) % 360.0
        D = doppler.D(theta=theta)

        # Now let's generate a synthetic spectrum. We do this on the
        # *padded* wavelength grid to avoid convolution edge effects.
        lam_padded = doppler.lam_padded

        # A deep line at the center of the wavelength range
        vT = 1 - 0.5 * np.exp(-0.5 * lam_padded ** 2 / sigma ** 2)

        # Scatter some smaller lines around for good measure
        for _ in range(nlines):
            amp = 0.1 * np.random.random()
            mu = 2.1 * (0.5 - np.random.random()) * lam_padded.max()
            vT -= amp * np.exp(-0.5 * (lam_padded - mu) ** 2 / sigma ** 2)

        # Now generate our "Vogtstar" map
        self.map.load(image)
        u = np.array(self.map.y.eval())

        # Compute the map matrix & the flux matrix
        A = u.reshape(-1, 1).dot(vT.reshape(1, -1))
        F = D.dot(A.reshape(-1)).reshape(nt, -1)

        # Let's divide out the baseline flux. This is a bummer,
        # since it contains really important information about
        # the map, but unfortunately we can't typically
        # measure it with a spectrograph.
        b = self.map.flux(theta=theta).eval()
        F /= b.reshape(-1, 1)

        # Finally, we add some noise
        F += ferr * np.random.randn(*F.shape)

        # Store the dataset
        self.u_true = u[1:]
        self.vT_true = vT
        self.b_true = b
        self.D = D
        self.t = t
        self.theta = theta
        self.lam_padded = lam_padded
        self.lam = lam
        self.F = F
        self.ferr = ferr
        self.M, self.K = self.F.shape
        self.Kp = self.D.shape[1] // self.N
        self._loaded = True
Ejemplo n.º 9
0
# -*- coding: utf-8 -*-
"""
Plots the basis of `g` kernels.

"""
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import paparazzi as pp

# Get the `kT` functions at high res
ydeg = 10
dop = pp.Doppler(ydeg=ydeg)
dop.generate_data(R=1e6, nlam=99, y1=np.zeros(dop.N - 1))
kT = dop.kT()

# Set up the plot
fig, ax = plt.subplots(ydeg + 1,
                       2 * ydeg + 1,
                       figsize=(16, 10),
                       sharex=True,
                       sharey=True)
fig.subplots_adjust(hspace=0)
for axis in ax.flatten():
    axis.spines["top"].set_visible(False)
    axis.spines["right"].set_visible(False)
    axis.spines["bottom"].set_visible(False)
    axis.spines["left"].set_visible(False)
    axis.set_xticks([])
    axis.set_yticks([])
Ejemplo n.º 10
0
CLIGHT = 3.0e5

# Get the Ylm expansion of a Gaussian spot
ydeg = 20
N = (ydeg + 1)**2
map = starry.Map(ydeg)
map.add_spot(amp=-0.03, sigma=0.05, lat=30, lon=30)
y1 = np.array(map.y.eval())[1:]

# Check that the specific intensity is positive everywhere
assert np.nanmin(map.render().eval()) > 0

# This work
vsini = 40.0  # km/s
dop = pp.Doppler(ydeg, vsini=vsini, inc=map.inc.eval())
dop.generate_data(y1=y1,
                  R=3.0e6,
                  nlam=1999,
                  sigma=2.0e-5,
                  nlines=1,
                  theta=[0.0],
                  ferr=0.0)
F = dop.F[0] / dop.F[0][0]

# The rest frame spectrum
s = dop.s_true
lnlam = dop.lnlam
lnlam_padded = dop.lnlam_padded
obs = (lnlam_padded >= lnlam[0]) & (lnlam_padded <= lnlam[-1])
Ejemplo n.º 11
0
# Settings for this figure
ydeg = 2
ntheta = 11
inc = 40.0
vsini = 35.0
nlam = 151
u = []

#
# Compute stuff!
#

# Compute the `D` matrix
theta = np.linspace(0, 360, ntheta)
theta[-1] = 0.0
dop = pp.Doppler(ydeg=ydeg, vsini=vsini, inc=inc, u=u)
dop.generate_data(theta=theta, nlam=nlam)
D = dop.D().todense()

# Plot it
fig, ax = plt.subplots(1, figsize=(11, 9.25))
fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
cmap = plt.get_cmap("inferno")
vmax = np.nanmax(np.abs(D))
D[D == 0] = -99
cmap.set_under((0.9, 0.9, 0.9))
ax.imshow(D, cmap=cmap, vmin=-vmax, vmax=vmax)
ax.axis("off")

# Plot the Ylms
x0 = 0.0
Ejemplo n.º 12
0
Archivo: kT.py Proyecto: rodluger/talks
# -*- coding: utf-8 -*-
"""
Plots the basis of `g` kernels.

"""
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import paparazzi as pp

# Get the `kT` functions at high res
ydeg = 10
dop = pp.Doppler(ydeg=ydeg, inc=60)
dop.generate_data(R=1e6, nlam=99, y1=np.zeros(dop.N - 1))
kT = dop.kT()

# Set up the plot
fig, ax = plt.subplots(ydeg + 1,
                       2 * ydeg + 1,
                       figsize=(16, 10),
                       sharex=True,
                       sharey=True)
fig.subplots_adjust(hspace=0)
for axis in ax.flatten():
    axis.spines["top"].set_visible(False)
    axis.spines["right"].set_visible(False)
    axis.spines["bottom"].set_visible(False)
    axis.spines["left"].set_visible(False)
    axis.set_xticks([])
    axis.set_yticks([])
Ejemplo n.º 13
0
    """
    Return ``True`` if any of ``objs`` is a ``Theano`` object.

    """
    for obj in objs:
        for c in getmro(type(obj)):
            if c is theano.gof.graph.Node:
                return True
    return False


# Initialize some stuff
np.random.seed(13)
ferr = 1.0e-4
res = 300
dop = pp.Doppler(ydeg=15)
dop.generate_data(ferr=ferr)
D = dop.D()
kT = dop.kT()
theta = dop.theta
K = dop.K
Kp = dop.Kp
W = dop.W
N = dop.N
M = dop.M
lnlam = dop.lnlam
lnlam_padded = dop.lnlam_padded
B1 = dop._map.X(theta=dop.theta).eval()[:, 1:]
B1 = np.repeat(B1, K, axis=0)

# Get the Ylm decomposition & the baseline
Ejemplo n.º 14
0
    return F


# Linear
R = 3e5
nlam = 199
nt = 3
P = 1
inc = 90.0
ydeg = 5
vsini = 40.0
sigma = 7.5e-6
dlam = np.log(1.0 + 1.0 / R)
lam = np.arange(-(nlam // 2), nlam // 2 + 1) * dlam
t = np.linspace(-0.5 * P, 0.5 * P, nt + 1)[:-1]
doppler = pp.Doppler(lam, ydeg=ydeg, vsini=vsini, inc=inc, P=P)
D = doppler.D(t=t)
lam_padded = doppler.lam_padded
vT = np.ones_like(lam_padded)
vT = 1 - 0.5 * np.exp(-0.5 * lam_padded ** 2 / sigma ** 2)
map = starry.Map(ydeg)
map.load("vogtstar.jpg")
u = np.array(map.y.eval())
A = u.reshape(-1, 1).dot(vT.reshape(1, -1))

for i in tqdm(range(100)):
    F = D.dot(A.reshape(-1)).reshape(nt, -1)

# Conv
A_t = tt.dmatrix()
F_t = theano.function(