TransformerPayne Integration

The TransformerPayne model is our recommended model for spectra emulation. It is a neural network that can be used to predict spectra from a given set of parameters, including individual abundances. To read more about TransformerPayne, see the arXiv paper

Downloading TransformerPayne

To download the TransformerPayne model, use the following code:

from transformer_payne import TransformerPayne

tp = TransformerPayne.download()

Make sure to have the transformer-payne and huggingface-hub packages installed to use this function.

Creating a Mesh Model

TranformerPayne has much more parameters, for example, individual abundances:

Warning

Note that TransformerPayne expects temperature in log10 scale (logteff) rather than linear scale (teff). For example, for a star with Teff = 8340K, you would need to provide logteff=np.log10(8340) ≈ 3.92.

from spice.models import IcosphereModel
import jax.numpy as jnp

m = IcosphereModel.construct(1000, 1., 1.,
                             tp.to_parameters(dict(logteff=jnp.log10(7000), logg=4.3, O=8.0, Si=6.0)),
                             tp.stellar_parameter_names)

Spectrum Calculation

Currently, TransformerPayne contains GALAH DR3 lines.

An example of a spectrum generated for a rotating model is shown below:

from spice.models.mesh_transform import add_rotation, evaluate_rotation
from spice.spectrum.spectrum import simulate_observed_flux

mt = add_rotation(m, 100, jnp.array([0., 0., 1.]))
mt = evaluate_rotation(mt, 0.)

vws = np.linspace(4670, 4960, 2000)
spec_no_rot = simulate_observed_flux(tp.intensity, m, jnp.log10(vws))
spec_rot = simulate_observed_flux(tp.intensity, mt, jnp.log10(vws))

The spectrum can be plotted using the following code:

_, ax = plt.subplots(figsize=(12, 6))
plt.plot(vws, spec_no_rot[:, 0], color='black', linewidth=1, label='No rotation')
plt.plot(vws, spec_rot[:, 0], color='royalblue', linewidth=3, label='25 km/s')
ax.set_xlabel(r'Wavelength [$\AA$]')
ax.set_ylabel(r'Normalized Flux [erg/s/cm$^2$/$\AA$]');
plt.legend()
plt.show()
TransformerPayne spectrum with and without rotation TransformerPayne spectrum with and without rotation

Line Profiles

Line profiles for spotted star models can be calculated using the following code:

from spice.models.spots import add_spot
import numpy as np

timestamps = np.linspace(0, 48*3600, 100)

m_spotted = add_spot(m, spot_center_theta=1., spot_center_phi=1., spot_radius=30., parameter_delta=5.0, parameter_index=tp.parameter_names.index('Mn'))
m_spotted = [evaluate_rotation(add_rotation(m_spotted, 25.), t) for t in timestamps]

Models for various phases can be visualized using the following code:

from spice.plots import plot_3D

fig, plot_ax = plot_3D(m_spotted[0], property_label='Mn abundance', property=tp.parameter_names.index('Mn'))
Magnesium spot at phase 0 Magnesium spot at phase 0
fig, plot_ax = plot_3D(m_spotted[50], property_label='Mn abundance', property=tp.parameter_names.index('Mn'))
Magnesium spot at phase 50 Magnesium spot at phase 50

Magnesium spot was chosen because of its spectral lines within one of the GALAH DR3 windows.

The spectra can be calculated using the following code:

vws = np.linspace(4762, 4769, 2000)
spec_rot_spotted = [simulate_observed_flux(tp.intensity, _m_spotted, jnp.log10(vws)) for _m_spotted in m_spotted]

The line profiles can be plotted using the following code:

_, ax = plt.subplots(figsize=(12, 6))
# Plot the spectra with colors based on timesteps
# Create color map for different timesteps using magma
colors = plt.cm.cool(np.linspace(0, 1, len(spec_rot_spotted)))

# Plot each spectrum with color based on timestep
for i, spectrum in enumerate(spec_rot_spotted):
    plt.plot(vws, spectrum[:, 0], color=colors[i], linewidth=1, alpha=0.5)

# Create a ScalarMappable for the colorbar
sm = plt.cm.ScalarMappable(cmap=plt.cm.cool, norm=plt.Normalize(vmin=0, vmax=timestamps[-1]/(3600)))
plt.colorbar(sm, ax=ax, label='Time [h]')

# Add a colorbar
ax.set_xlabel(r'Wavelength [$\AA$]')
ax.set_ylabel(r'Flux [erg/s/cm$^2$/$\AA$]')
plt.show()
Magnesium line profiles Magnesium line profiles

Similarly, line profiles can be calculated for pulsating models. For example, a very simple pulsating model with a period of 5 days:

m = IcosphereModel.construct(5000, 1., 1.,
                            tp.to_parameters(dict(logteff=np.log10(8340), logg=4.3)), tp.stellar_parameter_names)
mp = add_pulsation(m, 0, 0, 5., jnp.array([[1e-4, 0.]]))

TIMESTAMPS = jnp.linspace(0., 5., 20)

mps = [evaluate_pulsations(m, t) for t in tqdm(TIMESTAMPS)]

for which we can calculate spectra with TransformerPayne:

vws = np.linspace(4762, 4769, 2000)
specs = [simulate_observed_flux(tp.intensity, _m_pulsating, jnp.log10(vws)) for _m_pulsating in mps]

and plot them using the following code:

import cmasher as cmr

# Create a colormap based on the timestamps
cmap = cmr.bubblegum
norm = plt.Normalize(TIMESTAMPS.min(), TIMESTAMPS.max())
fig, ax = plt.subplots()

# Plot the spectra with colors corresponding to timestamps
for spec, timestamp in zip(specs, TIMESTAMPS):
    ax.plot(vws, spec[:, 0], color=cmap(norm(timestamp)))

# Add a colorbar
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])  # This line is necessary for the colorbar to work correctly
cbar = plt.colorbar(sm, ax=ax, ticks=TIMESTAMPS)
cbar.set_label('Time [d]')

# Set the colorbar tick labels to the timestamp values
cbar.set_ticklabels([f'{t:.2f}' for t in TIMESTAMPS])

plt.gca().set_xlabel(r'Wavelength [$\AA$]')
plt.gca().set_ylabel(r'Intensity [erg/s/cm$^2$/$\AA$]')
plt.gca().tick_params(axis='x', rotation=45)
Pulsation line profiles Pulsation line profiles