Spectral Line Profile Models

Redback provides a comprehensive suite of spectral line profile models for analyzing supernova spectra and other transients with expanding photospheres. These models are particularly useful for Type Ia supernovae, core-collapse supernovae, and other events showing P-Cygni profiles.

Line Profile Functions

Voigt Profile

The Voigt profile is a convolution of Gaussian (thermal broadening) and Lorentzian (natural/pressure broadening) components:

from redback.transient_models import spectral_models
import numpy as np

wavelength = np.linspace(6560, 6570, 1000)
flux = spectral_models.voigt_profile(
    wavelength,
    lambda_center=6563.0,  # H-alpha
    amplitude=1.0,
    sigma_gaussian=0.5,    # Thermal broadening
    gamma_lorentz=0.2,     # Natural/pressure broadening
    continuum=0.0
)

This uses the Faddeeva function for accurate computation.

Gaussian and Lorentzian Profiles

Pure Gaussian and Lorentzian profiles are also available:

# Gaussian profile (thermal broadening only)
flux_gauss = spectral_models.gaussian_line_profile(
    wavelength, lambda_center=6563, amplitude=-0.5, sigma=2.0, continuum=1.0
)

# Lorentzian profile (natural line shape)
flux_lorentz = spectral_models.lorentzian_line_profile(
    wavelength, lambda_center=6563, amplitude=-0.3, gamma=1.5, continuum=1.0
)

P-Cygni Profiles

P-Cygni profiles are the characteristic signature of expanding atmospheres, showing blueshifted absorption and emission near the rest wavelength.

Physical P-Cygni Model

Based on the Sobolev approximation (valid when thermal velocity << expansion velocity):

wavelength = np.linspace(5000, 7000, 1000)

flux = spectral_models.p_cygni_profile(
    wavelength,
    lambda_rest=6355,      # Si II rest wavelength
    tau_sobolev=3.0,       # Optical depth
    v_phot=11000,          # Photospheric velocity in km/s
    continuum_flux=1.0,
    source_function='thermal',  # or 'scattering' or float
    v_max=16500            # Optional: max velocity (default 1.5*v_phot)
)

Parameters:

  • tau_sobolev: Sobolev optical depth (0.1-100). Higher values give deeper absorption.

  • v_phot: Photospheric velocity in km/s. Determines the absorption minimum position.

  • source_function: ‘thermal’ (LTE), ‘scattering’ (electron scattering), or custom float.

Elementary P-Cygni Model

A simpler parameterization using Gaussian components, useful for quick fitting:

flux = spectral_models.elementary_p_cygni_profile(
    wavelength,
    lambda_rest=6355,
    v_absorption=11000,      # Velocity of absorption minimum
    absorption_depth=0.4,    # Fractional depth (0-1)
    emission_strength=0.2,   # Emission above continuum
    v_width=1500,            # Velocity width in km/s
    continuum_flux=1.0
)

Multi-Line Spectra

Generate realistic supernova spectra with multiple P-Cygni features:

# Define line list for Type Ia SN
line_list = [
    {'ion': 'Ca II H&K', 'lambda': 3945, 'tau': 5.0},
    {'ion': 'Si II', 'lambda': 6355, 'tau': 3.0},
    {'ion': 'S II', 'lambda': 5640, 'tau': 2.0},
    {'ion': 'Fe II', 'lambda': 5169, 'tau': 2.5}
]

wavelength = np.linspace(3500, 8500, 3000)

# With blackbody continuum
spectrum = spectral_models.blackbody_spectrum_with_p_cygni_lines(
    angstroms=wavelength,
    redshift=0.01,
    rph=1e15,              # Photosphere radius in cm
    temp=11000,            # Temperature in K
    line_list=line_list,
    v_phot=11000           # km/s
)

# Or with custom continuum
spectrum = spectral_models.multi_line_p_cygni_spectrum(
    wavelength=wavelength,
    redshift=0.01,
    continuum_model='blackbody',  # or 'powerlaw' or callable
    line_list=line_list,
    v_phot=11000,
    r_phot=1e15,
    temperature=11000
)

SYNOW-Style Models

For direct analysis following the SYNOW methodology:

transmission = spectral_models.synow_line_model(
    wavelength,
    lambda_rest=6355,
    tau_ref=5.0,           # Reference optical depth
    v_phot=10000,          # Photospheric velocity
    v_max=25000,           # Maximum velocity
    n_power=7              # Power-law index (default 7)
)

Voigt Absorption Lines

Add multiple Voigt absorption lines to any continuum:

line_params = [
    {'lambda': 6563, 'depth': 0.3, 'sigma': 2.0, 'gamma': 0.5},
    {'lambda': 6583, 'depth': 0.1, 'sigma': 1.5, 'gamma': 0.3}
]

flux = spectral_models.spectrum_with_voigt_absorption_lines(
    wavelength, continuum_flux=1.0, line_params_list=line_params
)

Velocity Measurements

The SpectralVelocityFitter class provides tools for measuring expansion velocities from spectral features.

Basic Usage

from redback.analysis import SpectralVelocityFitter

# Create fitter from wavelength and flux arrays
fitter = SpectralVelocityFitter(wavelength, flux)

# Or from a spectrum object
# fitter = SpectralVelocityFitter.from_spectrum_object(spectrum)

# Measure Si II 6355 velocity
v, v_err = fitter.measure_line_velocity(6355, method='min')
print(f"Si II velocity: {v:.0f} +/- {v_err:.0f} km/s")

Measurement Methods

Several methods are available:

  • min: Find minimum flux (standard method)

  • centroid: Flux-weighted centroid

  • gaussian: Fit Gaussian to absorption

  • fit: Fit full P-Cygni profile

# Compare methods
for method in ['min', 'centroid', 'gaussian', 'fit']:
    v, err = fitter.measure_line_velocity(6355, method=method)
    print(f"{method}: {v:.0f} +/- {err:.0f} km/s")

Additional parameters:

v, err = fitter.measure_line_velocity(
    6355,
    method='min',
    v_window=5000,            # Search window in km/s
    continuum_percentile=90   # For continuum estimation
)

Multiple Line Measurements

Measure velocities for multiple ions simultaneously:

lines = {
    'Si II 6355': 6355,
    'Ca II H&K': 3934,
    'Fe II 5169': 5169,
    'S II': 5640
}

velocities = fitter.measure_multiple_lines(lines, method='min')

for ion_name, (v, verr) in velocities.items():
    print(f"{ion_name}: {v:.0f} +/- {verr:.0f} km/s")

Velocity Evolution

Track photospheric velocity evolution across a time series of spectra:

# wavelength_list: list of wavelength arrays
# flux_list: list of flux arrays
# times: observation times in days

times, velocities, errors = SpectralVelocityFitter.photospheric_velocity_evolution(
    wavelength_list, flux_list, times,
    line_wavelength=6355,  # Si II
    method='min'
)

# Plot velocity evolution
import matplotlib.pyplot as plt
plt.errorbar(times, -velocities/1000, yerr=errors/1000, fmt='o-')
plt.xlabel('Days since explosion')
plt.ylabel('Velocity (1000 km/s)')

Velocity Gradient

Measure the velocity decline rate (dv/dt):

gradient, gradient_err = fitter.measure_velocity_gradient(
    wavelength_list, flux_list, times, line_wavelength=6355
)

print(f"Velocity gradient: {gradient:.1f} +/- {gradient_err:.1f} km/s/day")

Typical values for normal SNe Ia are -50 to -100 km/s/day.

High-Velocity Features

Detect high-velocity features (HVFs) in spectra:

has_hvf, v_hvf, v_hvf_err = fitter.identify_high_velocity_features(
    line_rest_wavelength=6355,
    v_phot_expected=11000,   # Expected photospheric velocity
    threshold_factor=1.3     # Factor above v_phot for HVF classification
)

if has_hvf:
    print(f"HVF detected at {-v_hvf:.0f} +/- {v_hvf_err:.0f} km/s")

Example Workflow

Complete workflow for Type Ia SN spectral analysis:

import numpy as np
from redback.transient_models import spectral_models
from redback.analysis import SpectralVelocityFitter

# 1. Load or simulate spectrum
wavelength = np.linspace(3500, 9000, 3000)
lines = [
    {'ion': 'Si II', 'lambda': 6355, 'tau': 3.0},
    {'ion': 'Ca II', 'lambda': 3945, 'tau': 5.0}
]
spectrum = spectral_models.blackbody_spectrum_with_p_cygni_lines(
    wavelength, redshift=0.01, rph=1e15, temp=11000,
    line_list=lines, v_phot=11500
)

# 2. Measure velocities
fitter = SpectralVelocityFitter(wavelength, spectrum)

lines_to_measure = {
    'Si II 6355': 6355,
    'Ca II H&K': 3934
}
velocities = fitter.measure_multiple_lines(lines_to_measure)

# 3. Check for HVFs
has_hvf, v_hvf, _ = fitter.identify_high_velocity_features(6355, 11000)

# 4. Print results
print("Photospheric Velocities:")
for ion, (v, err) in velocities.items():
    print(f"  {ion}: {-v:.0f} +/- {err:.0f} km/s")

if has_hvf:
    print(f"  HVF Si II: {-v_hvf:.0f} km/s")

High-Energy Spectral Models

For X-ray and gamma-ray spectral analysis (keV–MeV range), redback also provides models for fitting photon count spectra from instruments such as Swift/XRT, XMM-Newton, Chandra, and Fermi/GBM. These are described in the X-ray and Gamma-ray Spectral Fitting documentation.

References

The spectral models are based on:

  • Kasen & Branch 2001 (ApJ, 560, 439) - Analytic inversion of P-Cygni profiles

  • Jeffery & Branch 1990 - P-Cygni atlas

  • Branch et al. 2002 (ApJ, 566, 1005) - Direct analysis of SN spectra (SYNOW)

  • Fisher et al. 1997 (ApJ, 481, L89) - SYNOW introduction

  • Schreier 2018 (JQSRT, 213, 13) - Voigt function review

See the API documentation for complete function signatures and additional options.