def test_sturm(): mu = [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0.0] I = [1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1] guess = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] u, _ = curve_fit(IofMu, mu, I, guess) map = Map(10) map[:] = u[1:] assert map.is_physical() is False
def static(lmax=5, res=300): """Plot a static PDF figure.""" # Set up the plot fig, ax = pl.subplots(lmax + 1, 2 * lmax + 1, figsize=(9, 6)) fig.subplots_adjust(hspace=0) for axis in ax.flatten(): axis.set_xticks([]) axis.set_yticks([]) axis.spines['top'].set_visible(False) axis.spines['right'].set_visible(False) axis.spines['bottom'].set_visible(False) axis.spines['left'].set_visible(False) for l in range(lmax + 1): ax[l, 0].set_ylabel(r"$l = %d$" % l, rotation='horizontal', labelpad=30, y=0.38, fontsize=12) for j, m in enumerate(range(-lmax, lmax + 1)): if m < 0: ax[-1, j].set_xlabel(r"$m {=} \mathrm{-}%d$" % -m, labelpad=30, fontsize=11) else: ax[-1, j].set_xlabel(r"$m = %d$" % m, labelpad=30, fontsize=11) # Plot it x = np.linspace(-1, 1, res) y = np.linspace(-1, 1, res) X, Y = np.meshgrid(x, y) map = Map(lmax) # Loop over the orders and degrees for i, l in enumerate(range(lmax + 1)): for j, m in enumerate(range(-l, l + 1)): # Offset the index for centered plotting j += lmax - l # Compute the spherical harmonic # with no rotation map.reset() map[l, m] = 1 flux = [map(x=X[j], y=Y[j]) for j in range(res)] # Plot the spherical harmonic ax[i, j].imshow(flux, cmap='plasma', interpolation="none", origin="lower", extent=(-1, 1, -1, 1)) ax[i, j].set_xlim(-1.1, 1.1) ax[i, j].set_ylim(-1.1, 1.1) # Save! fig.savefig("ylms.pdf", bbox_inches="tight") pl.close()
def generate_starry_model(times, planet_info, fpfs, lmax=1, lambda0=90.0, Y_1_0=0.5): ''' Instantiate Kepler STARRY model; taken from HD 189733b example''' # Star star = kepler.Primary() # Planet planet = kepler.Secondary(lmax=lmax) planet.lambda0 = lambda0 # Mean longitude in degrees at reference time planet_info.Rp_Rs = planet_info.Rp_Rs or None # for later if not hasattr(planet_info, 'Rp_Rs') or planet_info.Rp_Rs is None: print('[WARNING] Rp_Rs does not exist in `planet_info`') print('Assuming Rp_Rs == sqrt(transit_depth)') planet_info.Rp_Rs = np.sqrt(planet_info.transit_depth) planet.r = planet_info.Rp_Rs # planetary radius in stellar radius planet.L = 0.0 # flux from planet relative to star planet.inc = planet_info.inclination # orbital inclination planet.a = planet_info.a_Rs # orbital distance in stellar radius planet.prot = planet_info.orbital_period # synchronous rotation planet.porb = planet_info.orbital_period # synchronous rotation planet.tref = planet_info.transit_time # MJD for transit center time planet.ecc = planet_info.eccentricity # eccentricity of orbit planet.Omega = planet_info.omega # argument of the ascending node # System system = kepler.System(star, planet) # Instantiate the system system = kepler.System(star, planet) # Specific plottings # Blue Curve # NOTE: Prevent negative luminosity on the night side # Green Curve # Compute the normalization map = Map(1) map[0, 0] = 1 map[1, 0] = Y_1_0 norm = map.flux() planet.L = fpfs / norm planet[1, 0] = Y_1_0 system.compute(times) return 1.0 + planet.lightcurve
def test_occultations(): """Test occultation light curves.""" # Let's do the l = 3 Earth map = Map(3) map.load_image('earth') # Rotate the map about a random axis ux = np.random.random() uy = np.random.random() * (1 - ux) uz = np.sqrt(1 - ux**2 - uy**2) axis = [ux, uy, uz] npts = 30 theta = np.linspace(0, 360, npts, endpoint=False) # Small occultor ro = 0.3 xo = np.linspace(-1 - ro - 0.1, 1 + ro + 0.1, npts) yo = 0 # Analytical and numerical fluxes map.axis = axis sF = np.array(map.flux(theta=theta, xo=xo, yo=yo, ro=ro)) nF = np.array(map.flux(theta=theta, xo=xo, yo=yo, ro=ro, numerical=True)) # Compute the (relative) error error = np.max(np.abs(sF - nF)) # Our numerical integration scheme isn't the most accurate, # so let's be lenient here! assert error < 0.03
def test_rotations(): """Test some elementary rotations.""" # Instantiate m = Map(1) m.set_coeff(1, 0, 1) assert np.allclose(m.y, np.array([0, 0, 1, 0])) # Rotations and evaluations m.rotate([1, 0, 0], -90) assert np.allclose(m.y, np.array([0, 1, 0, 0])) assert np.allclose(m.p, np.array([0, 0, 0, np.sqrt(3 / (4 * np.pi))])) m.rotate([0, 0, 1], -90) assert np.allclose(m.y, np.array([0, 0, 0, 1])) assert np.allclose(m.p, np.array([0, np.sqrt(3 / (4 * np.pi)), 0, 0])) m.rotate([0, 1, 0], -90) assert np.allclose(m.y, np.array([0, 0, 1, 0])) assert np.allclose(m.p, np.array([0, 0, np.sqrt(3 / (4 * np.pi)), 0]))
def test_phasecurves(): """Test transit light curve generation.""" # Let's do the l = 3 Earth m = Map(3) m.load_image('earth') # Compute the starry phase curve about a random axis ux = np.random.random() uy = np.random.random() * (1 - ux) uz = np.sqrt(1 - ux**2 - uy**2) axis = [ux, uy, uz] theta = np.linspace(0, 360, 25, endpoint=False) sF = m.flux(axis=axis, theta=theta) # Compute the flux numerically nF = [NumericalFlux(m, axis, t) for t in theta] # Compute the error error = np.max(np.abs((sF - nF) / sF)) # We're computing the numerical integral at very low precision # so that this test doesn't take forever, so let's be lenient here! assert error < 1e-4
def test_small(benchmark=0.1): """Small occultor.""" # Let's do the l = 5 Earth map = Map(5) map.load_image('earth') # Occultation properties npts = 10550 ro = 0.1 xo = np.linspace(-1 - ro, 1 + ro, npts) yo = np.linspace(-0.1, 0.1, npts) theta = np.linspace(0, 90, npts) map.axis = [1, 1, 1] / np.sqrt(3) # Analytical and numerical fluxes t = np.zeros(10) for i in range(10): tstart = time.time() map.flux(theta=theta, xo=xo, yo=yo, ro=ro) t[i] = time.time() - tstart t = np.mean(t) # Print print("Time [Benchmark]: %.3f [%.3f]" % (t, benchmark))
"""Smiley spherical harmonic example.""" from starry import Map import matplotlib.pyplot as pl import numpy as np # Generate a sample starry map map = Map(5) map[5, -3] = -2 map[5, 0] = 2 map[5, 4] = 1 map.axis = [0, 1, 0] # Render it under consecutive rotations nax = 9 fig, ax = pl.subplots(1, nax, figsize=(3 * nax, 3)) theta = np.linspace(-90, 90, nax, endpoint=True) x = np.linspace(-1, 1, 300) y = np.linspace(-1, 1, 300) x, y = np.meshgrid(x, y) for i in range(nax): I = [map(theta=theta[i], x=x[j], y=y[j]) for j in range(300)] ax[i].imshow(I, origin="lower", interpolation="none", cmap='plasma') ax[i].axis('off') # Save pl.savefig('smiley.pdf', bbox_inches='tight')
def __init__(self, lmax=5, res=300, dpi=100, fps=10, frames=50, axis=[0., 1., 0.]): """Initialize.""" self.lmax = lmax self.map = Map(lmax) self.res = res self.axis = axis self.frames = frames x = np.linspace(-1, 1, res) y = np.linspace(-1, 1, res) self.X, self.Y = np.meshgrid(x, y) # Set up the plot self.fig, self.ax = pl.subplots(self.lmax + 1, 2 * self.lmax + 1, figsize=(9, 6)) self.fig.subplots_adjust(hspace=0) for axis in self.ax.flatten(): axis.set_xticks([]) axis.set_yticks([]) axis.spines['top'].set_visible(False) axis.spines['right'].set_visible(False) axis.spines['bottom'].set_visible(False) axis.spines['left'].set_visible(False) for l in range(self.lmax + 1): self.ax[l, 0].set_ylabel(r"$l = %d$" % l, rotation='horizontal', labelpad=30, y=0.38, fontsize=12) for j, m in enumerate(range(-self.lmax, self.lmax + 1)): self.ax[-1, j].set_xlabel(r"$m = %d$" % m, labelpad=30, fontsize=12) # Loop over the orders and degrees self.img = [] for i, l in enumerate(range(self.lmax + 1)): for j, m in enumerate(range(-l, l + 1)): # Offset the index for centered plotting j += self.lmax - l # Compute the spherical harmonic self.map.reset() self.map[l, m] = 1 flux = [ self.map(theta=0, x=self.X[j], y=self.Y[j]) for j in range(res) ] # Plot the spherical harmonic img = self.ax[i, j].imshow(flux, cmap='plasma', interpolation="none", origin="lower") self.img.append(img) # Set up the animation self.theta = np.linspace(0, 360, frames, endpoint=False) self.animation = animation.FuncAnimation(self.fig, self.animate, frames=self.frames, interval=50, repeat=True, blit=True) # Save self.animation.save('ylms.gif', writer='imagemagick', fps=fps, dpi=dpi) pl.close()
"""Earth spherical harmonic example.""" from starry import Map import matplotlib.pyplot as pl import numpy as np # Generate a sample starry map m = Map(10) m.load_image('earth') # Start centered at longitude 180 W m.rotate([0, 1, 0], -180) # Render it under consecutive rotations nax = 8 res = 300 fig, ax = pl.subplots(1, nax, figsize=(3 * nax, 3)) theta = np.linspace(0, 360, nax, endpoint=False) x, y = np.meshgrid(np.linspace(-1, 1, res), np.linspace(-1, 1, res)) for i in range(nax): # starry functions accept vector arguments, but not matrix arguments, # so we need to iterate below: I = [ m.evaluate(axis=[0, 1, 0], theta=-theta[i], x=x[j], y=y[j]) for j in range(res) ] ax[i].imshow(I, origin="lower", interpolation="none", cmap='plasma') ax[i].axis('off') # Save pl.savefig('earth.pdf', bbox_inches='tight')
ax = pl.subplot2grid((5, nim), (1, 0), colspan=nim, rowspan=4) theta = np.linspace(0, 360, npts, endpoint=True) thetanum = np.linspace(0, 360, nptsnum, endpoint=True) total = np.zeros(npts, dtype=float) # Compute the phase curves for each continent base = 0.65 continents = [ 'asia.jpg', 'africa.jpg', 'southamerica.jpg', 'northamerica.jpg', 'oceania.jpg', 'europe.jpg', 'antarctica.jpg' ] labels = [ 'Asia', 'Africa', 'S. America', 'N. America', 'Oceania', 'Europe', 'Antarctica' ] map = Map(10) map.axis = [0, 1, 0] for continent, label in zip(continents, labels): map.load_image(continent) map.rotate(-180) F = map.flux(theta=theta) F -= np.nanmin(F) ax.plot(theta - 180, F, label=label) # Compute and plot the total phase curve map.load_image('earth.jpg') map.rotate(-180) total = map.flux(theta=theta) total /= np.max(total) ax.plot(theta - 180, total, 'k-', label='Total')
u_quad, _ = curve_fit(IofMu, mu, I, np.zeros(3)) # Now let's fit for the coefficients that fit our model *exactly* u_exact, _ = curve_fit(IofMu, mu, I, np.zeros_like(mu)) # Plot our two models mu_hires = np.linspace(0, 1, 100) ax[1].plot(mu_hires, IofMu(mu_hires, *u_quad), label='Quadratic') ax[1].plot(mu_hires, IofMu(mu_hires, *u_exact), label='Exact') # Compute and plot the starry flux in transit for both models npts = 500 r = 0.1 b = np.linspace(-1.5, 1.5, npts) for u, label in zip([u_quad, u_exact], ['Quadratic', 'Exact']): map = Map(len(u) - 1) for l in range(1, len(u)): map[l] = u[l] sF = map.flux(xo=b, yo=0, ro=r) ax[0].plot(b, sF, '-') # Appearance ax[0].set_xlim(-1.5, 1.5) ax[0].set_ylabel('Normalized flux', fontsize=16) ax[0].set_xlabel('Impact parameter', fontsize=16) ax[1].set_ylabel('Specific Intensity', fontsize=16, labelpad=10) ax[1].legend(loc='lower left') ax[1].invert_xaxis() ax[1].set_xlim(1, 0) ax[1].set_xlabel(r'$\mu$', fontsize=16)
ax = pl.subplot2grid((5, nim), (1, 0), colspan=nim, rowspan=4) theta = np.linspace(0, 360, npts, endpoint=True) thetanum = np.linspace(0, 360, nptsnum, endpoint=True) total = np.zeros(npts, dtype=float) # Compute the phase curves for each continent base = 0.65 continents = [ 'asia.jpg', 'africa.jpg', 'southamerica.jpg', 'northamerica.jpg', 'oceania.jpg', 'europe.jpg', 'antarctica.jpg' ] labels = [ 'Asia', 'Africa', 'S. America', 'N. America', 'Oceania', 'Europe', 'Antarctica' ] m = Map(10) for continent, label in zip(continents, labels): m.load_image(continent) m.rotate([0, 1, 0], -180) F = m.flux(axis=[0, 1, 0], theta=theta) F -= np.nanmin(F) ax.plot(theta - 180, F, label=label) # Compute and plot the total phase curve m.load_image('earth.jpg') m.rotate([0, 1, 0], -180) total = m.flux(axis=[0, 1, 0], theta=theta) total /= np.max(total) ax.plot(theta - 180, total, 'k-', label='Total') # Compute and plot the total phase curve (numerical)
axis.spines['right'].set_visible(False) axis.spines['bottom'].set_visible(False) axis.spines['left'].set_visible(False) for l in range(lmax + 1): ax[l, 0].set_ylabel(r"$l = %d$" % l, rotation='horizontal', labelpad=30, y=0.38, fontsize=12) for j, m in enumerate(range(lmax + 1)): ax[-1, j].set_xlabel(r"$m = %d$" % m, labelpad=30, fontsize=12) # Rotate about this vector ux = np.array([1., 0., 0.]) uy = np.array([0., 1., 0.]) map = Map(lmax) theta = np.linspace(0, 360, nt, endpoint=False) thetan = np.linspace(0, 360, nn, endpoint=False) for i, l in enumerate(range(lmax + 1)): for j, m in enumerate(range(l + 1)): nnull = 0 for axis, zorder, color in zip([ux, uy], [1, 0], ['C0', 'C1']): map.reset() map[0, 0] = 0 map[l, m] = 1 map.axis = axis flux = map.flux(theta=theta) ax[i, j].plot(theta, flux, lw=1, zorder=zorder, color=color) fluxn = map.flux(theta=thetan, numerical=True) ax[i, j].plot(thetan, fluxn, '.', ms=2, zorder=zorder, color=color) if np.max(np.abs(flux)) < 1e-10:
axis.set_xticks([]) axis.set_yticks([]) axis.spines['top'].set_visible(False) axis.spines['right'].set_visible(False) axis.spines['bottom'].set_visible(False) axis.spines['left'].set_visible(False) for l in range(lmax + 1): ax[l, 0].set_ylabel(r"$l = %d$" % l, rotation='horizontal', labelpad=30, y=0.38, fontsize=12) for j, m in enumerate(range(lmax + 1)): ax[-1, j].set_xlabel(r"$m = %d$" % m, labelpad=30, fontsize=12) # Occultation params map = Map(lmax) ro = 0.25 xo = np.linspace(-1.5, 1.5, nt) xon = np.linspace(-1.5, 1.5, nn) for yo, zorder, color in zip([0.25, 0.75], [1, 0], ['C0', 'C1']): for i, l in enumerate(range(lmax + 1)): for j, m in enumerate(range(l + 1)): map.reset() map[0, 0] = 0 map[l, m] = 1 flux = map.flux(theta=0, xo=xo, yo=yo, ro=ro) ax[i, j].plot(xo, flux, lw=1, zorder=zorder, color=color) fluxn = map.flux(theta=0, xo=xon, yo=yo, ro=ro, numerical=True) ax[i, j].plot(xon, fluxn, '.', ms=2, zorder=zorder, color=color) # Hack a legend
"""Earth occultation example.""" from starry import Map import matplotlib.pyplot as pl import numpy as np # Set up the plot nim = 12 npts = 100 nptsnum = 10 res = 300 fig = pl.figure(figsize=(12, 5)) ax_im = [pl.subplot2grid((4, nim), (0, n)) for n in range(nim)] ax_lc = pl.subplot2grid((4, nim), (1, 0), colspan=nim, rowspan=3) # Instantiate the earth m = Map(10) m.load_image('earth') # Moon params ro = 0.273 yo = np.linspace(-0.5, 0.5, npts) yonum = np.linspace(-0.5, 0.5, nptsnum) xo = np.linspace(-1.5, 1.5, npts) xonum = np.linspace(-1.5, 1.5, nptsnum) # Say the occultation occurs over ~1 radian of the Earth's rotation # That's equal to 24 / (2 * pi) hours # (Remember, though, that `starry` accepts **DEGREES** as input!) time = np.linspace(0, 24 / (2 * np.pi), npts) timenum = np.linspace(0, 24 / (2 * np.pi), nptsnum) theta0 = 0
axis.spines['right'].set_visible(False) axis.spines['bottom'].set_visible(False) axis.spines['left'].set_visible(False) for l in range(lmax + 1): ax[l, 0].set_ylabel(r"$l = %d$" % l, rotation='horizontal', labelpad=30, y=0.38, fontsize=12) for j, m in enumerate(range(lmax + 1)): ax[-1, j].set_xlabel(r"$m = %d$" % m, labelpad=30, fontsize=12) # Rotate about this vector ux = np.array([1., 0., 0.]) uy = np.array([0., 1., 0.]) y = Map(lmax) theta = np.linspace(0, 360, nt, endpoint=False) thetan = np.linspace(0, 360, nn, endpoint=False) for i, l in enumerate(range(lmax + 1)): for j, m in enumerate(range(l + 1)): nnull = 0 for axis, zorder, color in zip([ux, uy], [1, 0], ['C0', 'C1']): y.reset() y.set_coeff(l, m, 1) flux = y.flux(axis=axis, theta=theta) ax[i, j].plot(theta, flux, lw=1, zorder=zorder, color=color) fluxn = y._flux_numerical(axis=axis, theta=thetan, tol=1e-5) ax[i, j].plot(thetan, fluxn, '.', ms=2, zorder=zorder, color=color) if np.max(np.abs(flux)) < 1e-10: nnull += 1 # If there's no light curve, make sure our plot range
"""Earth occultation example.""" from starry import Map import matplotlib.pyplot as pl import numpy as np # Set up the plot nim = 12 npts = 100 nptsnum = 10 res = 300 fig = pl.figure(figsize=(12, 5)) ax_im = [pl.subplot2grid((4, nim), (0, n)) for n in range(nim)] ax_lc = pl.subplot2grid((4, nim), (1, 0), colspan=nim, rowspan=3) # Instantiate the earth map = Map(10) map.load_image('earth') map.axis = [0, 1, 0] # Moon params ro = 0.273 yo = np.linspace(-0.5, 0.5, npts) yonum = np.linspace(-0.5, 0.5, nptsnum) xo = np.linspace(-1.5, 1.5, npts) xonum = np.linspace(-1.5, 1.5, nptsnum) # Say the occultation occurs over ~1 radian of the Earth's rotation # That's equal to 24 / (2 * pi) hours # (Remember, though, that `starry` accepts **DEGREES** as input!) time = np.linspace(0, 24 / (2 * np.pi), npts) timenum = np.linspace(0, 24 / (2 * np.pi), nptsnum)
"""Smiley spherical harmonic example.""" from starry import Map import matplotlib.pyplot as pl import numpy as np # Generate a sample starry map m = Map(5) m.set_coeff(5, -3, -2) m.set_coeff(5, 0, 2) m.set_coeff(5, 4, 1) # Render it under consecutive rotations nax = 9 fig, ax = pl.subplots(1, nax, figsize=(3 * nax, 3)) theta = np.linspace(-90, 90, nax, endpoint=True) x = np.linspace(-1, 1, 300) y = np.linspace(-1, 1, 300) x, y = np.meshgrid(x, y) for i in range(nax): I = [ m.evaluate(axis=[0, 1, 0], theta=theta[i], x=x[j], y=y[j]) for j in range(300) ] ax[i].imshow(I, origin="lower", interpolation="none", cmap='plasma') ax[i].axis('off') # Save pl.savefig('smiley.pdf', bbox_inches='tight')
axis.set_xticks([]) axis.set_yticks([]) axis.spines['top'].set_visible(False) axis.spines['right'].set_visible(False) axis.spines['bottom'].set_visible(False) axis.spines['left'].set_visible(False) for l in range(lmax + 1): ax[l, 0].set_ylabel(r"$l = %d$" % l, rotation='horizontal', labelpad=30, y=0.38, fontsize=12) for j, m in enumerate(range(lmax + 1)): ax[-1, j].set_xlabel(r"$m = %d$" % m, labelpad=30, fontsize=12) # Occultation params y = Map(lmax) ro = 0.25 xo = np.linspace(-1.5, 1.5, nt) xon = np.linspace(-1.5, 1.5, nn) for yo, zorder, color in zip([0.25, 0.75], [1, 0], ['C0', 'C1']): for i, l in enumerate(range(lmax + 1)): for j, m in enumerate(range(l + 1)): y.reset() y.set_coeff(l, m, 1) flux = y.flux(axis=[1, 0, 0], theta=0, xo=xo, yo=yo, ro=ro) ax[i, j].plot(xo, flux, lw=1, zorder=zorder, color=color) fluxn = y._flux_numerical(axis=[1, 0, 0], theta=0, xo=xon, yo=yo, ro=ro, tol=1e-5) ax[i, j].plot(xon, fluxn, '.', ms=2, zorder=zorder, color=color) # Hack a legend
"""Earth spherical harmonic example.""" from starry import Map import matplotlib.pyplot as pl import numpy as np # Generate a sample starry map m = Map(10) m.load_image('earth') # Start centered at longitude 180 W m.axis = [0, 1, 0] m.rotate(-180) # Render it under consecutive rotations nax = 8 res = 300 fig, ax = pl.subplots(1, nax, figsize=(3 * nax, 3)) theta = np.linspace(0, 360, nax, endpoint=False) x, y = np.meshgrid(np.linspace(-1, 1, res), np.linspace(-1, 1, res)) for i in range(nax): # starry functions accept vector arguments, but not matrix arguments, # so we need to iterate below: I = [m(theta=-theta[i], x=x[j], y=y[j]) for j in range(res)] ax[i].imshow(I, origin="lower", interpolation="none", cmap='plasma') ax[i].axis('off') # Save pl.savefig('earth.pdf', bbox_inches='tight')