class Application(object): def __init__( self, ydeg=15, npix=100, npts=300, nmaps=5, throttle_time=0.40, load_timeout=1.0, nosmooth=False, ): self.ydeg = ydeg self.npix = npix self.npts = npts self.nmaps = nmaps self.throttle_time = throttle_time self.load_timeout = load_timeout self.nosmooth = nosmooth self._compiled = False def compile(self): # Compile the GP print("Compiling. This may take up to one minute...") r = tt.dscalar() a = tt.dscalar() b = tt.dscalar() c = tt.dscalar() n = tt.dscalar() self.gp = StarryProcess(ydeg=self.ydeg, r=r, a=a, b=b, c=c, n=n) self.gp.random.seed(238) self.sample_function = theano.function( [r, a, b, c, n], [self.gp.sample_ylm(nsamples=self.nmaps)], no_default_updates=True, ) self._compiled = True print("Done!") def run(self, doc=None): # Get current document if needed if doc is None: doc = curdoc() doc.title = "starry process" doc.template = TEMPLATE # Show the loading screen self.layout = Div(text=LOADING_SCREEN, css_classes=["body-wrapper"]) doc.add_root(self.layout) # Set a delay timer for safety; when it's done, load the widgets doc.add_timeout_callback(lambda: self._run(doc), int(1000 * self.load_timeout)) def _run(self, doc=None): # Get current document if needed if doc is None: doc = curdoc() # Compile if needed if not self._compiled: self.compile() print("Rendering...") # The GP samples self.Samples = Samples( self.ydeg, self.npix, self.npts, self.nmaps, self.throttle_time, self.nosmooth, self.gp, self.sample_function, ) # The integrals sp = StarryProcess(ydeg=self.ydeg) pdf = lambda x, mu, sigma: sp.latitude._pdf(x, *gauss2beta(mu, sigma)) pdf_gauss = lambda x, mu, sigma: 0.5 * (Normal.pdf(x, -mu, sigma) + Normal.pdf(x, mu, sigma)) npts = 300 T = spot_transform(self.ydeg, npts) self.Latitude = Integral( params["latitude"], self.Samples.callback, funcs=[pdf, pdf_gauss], labels=["pdf", "laplace"], xlabel="latitude distribution", ylabel="probability", distribution=True, legend_location="top_left", ) self.Size = Integral( params["size"], self.Samples.callback, funcs=[ lambda x, r: T @ (1 / (1 + np.exp(-300 * np.pi / 180 * (np.abs(x) - r))) - 1), lambda x, r: (1 / (1 + np.exp(-300 * np.pi / 180 * (np.abs(x) - r))) - 1), ], labels=["ylm", "true"], xlabel="spot profile", ylabel="intensity", npts=npts, ) self.Contrast = Integral(params["contrast"], self.Samples.callback) # Tell the GP about the sliders self.Samples.Latitude = self.Latitude self.Samples.Size = self.Size self.Samples.Contrast = self.Contrast # Settings ControlPanel = column( Div(text="<h1>settings</h1>", css_classes=["control-title"]), self.Contrast.layout, self.Samples.slider, row( self.Samples.smooth_button, self.Samples.auto_button, self.Samples.seed_button, self.Samples.reset_button, sizing_mode="scale_both", css_classes=["button-row"], ), Div(text=description, css_classes=["control-description"]), sizing_mode="scale_both", ) # Full layout layout = column( row( self.Latitude.layout, self.Size.layout, ControlPanel, sizing_mode="scale_both", ), self.Samples.layout, style(), sizing_mode="scale_both", ) print("Done rendering.") # Remove the loading screen doc.remove_root(self.layout) # Add the interface self.layout = layout doc.add_root(self.layout)
}, ) # Draw samples from a sum of two StarryProcess instances sp = StarryProcess(marginalize_over_inclination=False, r=10, mu=60, sigma=3, c=0.15) sp += StarryProcess(marginalize_over_inclination=False, r=20, mu=0, sigma=3, n=5, c=0.1) y = sp.sample_ylm(nsamples=nsamples).eval() # Normalize so that the background photosphere # has unit intensity (for plotting) y[:, 0] += 1 y *= np.pi for k in range(nsamples): map[:, :] = y[k] map.show(ax=ax[0, k], projection="moll", norm=norm) ax[0, k].set_ylim(-1.5, 2.25) ax[0, k].set_rasterization_zorder(1) for i, inc in enumerate(incs): map.inc = inc flux = map.flux(theta=360.0 * t) flux -= np.mean(flux)
def plot_samples(): # Settings nsamples = 5 norm = Normalize(vmin=0.5, vmax=1.1) incs = [15, 30, 45, 60, 75, 90] t = np.linspace(0, 4, 1000) cmap = plt.get_cmap("plasma_r") color = lambda i: cmap(0.1 + 0.8 * i / (len(incs) - 1)) map = starry.Map(15, lazy=False) kwargs = [ dict(r=10, a=0.40, b=0.27, c=0.1, n=10, seed=0), dict(r=10, a=0.31, b=0.36, c=0.1, n=10, seed=1), dict(r=30, a=0.28, b=0.0, c=0.05, n=10, seed=2), dict(r=10, a=0.06, b=0.0, c=0.1, n=20, seed=3), ] # One figure per `kwargs` for n in range(len(kwargs)): # Set up the plot fig, ax = plt.subplots( 2, nsamples + 1, figsize=(12, 2.5), gridspec_kw={ "height_ratios": np.array([1, 0.5]), "width_ratios": np.append(np.ones(nsamples), 0.1), }, ) # Draw samples sp = StarryProcess(marginalize_over_inclination=False, **kwargs[n]) y = sp.sample_ylm(nsamples=nsamples).eval() # Normalize so that the background photosphere # has unit intensity (for plotting) y[:, 0] += 1 y *= np.pi # Visualize each sample for k in range(nsamples): map[:, :] = y[k] map.show(ax=ax[0, k], projection="moll", norm=norm) ax[0, k].set_ylim(-1.5, 2.25) ax[0, k].set_rasterization_zorder(1) for i, inc in enumerate(incs): map.inc = inc flux = map.flux(theta=360.0 * t) flux -= np.mean(flux) flux *= 1e3 ax[1, k].plot(t, flux, color=color(i), lw=0.75) if k == 0: ax[1, k].spines["top"].set_visible(False) ax[1, k].spines["right"].set_visible(False) ax[1, k].set_xlabel("rotations", fontsize=8) ax[1, k].set_ylabel("flux [ppt]", fontsize=8) ax[1, k].set_xticks([0, 1, 2, 3, 4]) for tick in (ax[1, k].xaxis.get_major_ticks() + ax[1, k].yaxis.get_major_ticks()): tick.label.set_fontsize(6) ax[1, k].tick_params(direction="in") else: ax[1, k].axis("off") # Appearance tweaks cax = inset_axes(ax[0, -1], width="70%", height="50%", loc="lower center") cbar = fig.colorbar(ax[0, k].images[0], cax=cax, orientation="vertical") cbar.set_label("intensity", fontsize=8) cbar.set_ticks([0.5, 0.75, 1]) cbar.ax.tick_params(labelsize=6) ax[0, -1].axis("off") lax = inset_axes(ax[1, -1], width="80%", height="100%", loc="center right") for i, inc in enumerate(incs): lax.plot(0, 0, color=color(i), lw=1, label=r"{}$^\circ$".format(inc)) lax.legend(loc="center left", fontsize=5, frameon=False) lax.axis("off") ax[1, -1].axis("off") dy = max([max(np.abs(ax[1, k].get_ylim())) for k in range(nsamples)]) for k in range(nsamples): ax[1, 0].set_ylim(-dy, dy) # We're done fig.savefig("samples_{}.png".format(n), bbox_inches="tight", dpi=100)