Spectral Template Matching

The SpectralTemplateMatcher class in redback.analysis provides functionality for matching observed spectra against template libraries, similar to tools like SNID (Supernova Identification). This is useful for classifying transients based on their spectral features and estimating redshifts.

Quick Start

from redback.analysis import SpectralTemplateMatcher
from redback.transient.transient import Spectrum
import numpy as np

# Create a matcher with default templates
matcher = SpectralTemplateMatcher()

# Create or load your observed spectrum
spectrum = Spectrum(
    angstroms=wavelength_array,
    flux_density=flux_array,
    flux_density_err=flux_err_array,
    name="My_SN"
)

# Match to find best template
result = matcher.match_spectrum(spectrum, redshift_range=(0, 0.3))

print(f"Type: {result['type']}, Redshift: {result['redshift']:.3f}")

Template Sources

Available sources include:

1. Built-in sncosmo templates (default) — realistic spectra at multiple phases 3. Super-SNID — expanded library with 841 templates (Magill et al. 2025), downloaded automatically via from_super_snid_templates() 4. SESNtemple — stripped-envelope SN templates from the METAL collaboration, downloaded automatically via from_sesn_templates() 5. Custom CSV/DAT files — your own template library

If you use external template libraries, please cite the relevant sources.

Loading Templates

Default Templates (Built-in)

The default templates are drawn from sncosmo spectral models at multiple phases:

matcher = SpectralTemplateMatcher()

This loads realistic spectral templates from:

  • SALT2 (Type Ia, phases −10 to +20 d)

  • v19-1998bw (Ic-BL / SN 1998bw-like, phases −5 to +20 d)

  • nugent-sn1bc (Ib/c, phases 0 to +30 d)

  • nugent-sn2p (IIP, phases 0 to +80 d)

  • nugent-sn2n (IIn, phases 0 to +60 d)

  • s11-2004hx (generic Type II, phases 0 to +50 d)

Super-SNID Templates (auto-download)

Download and load the full Super-SNID library (841 templates, Magill et al. 2025) in one call:

matcher = SpectralTemplateMatcher.from_super_snid_templates(
    cache_dir='~/my_templates'  # optional; defaults to ~/.redback/spectral_templates/
)

This downloads https://github.com/dkjmagill/QUB-SNID-Templates, extracts the inner templates.zip, and loads all .lnw files. The result is cached locally so subsequent calls are instant.

SESNtemple Templates (auto-download)

Download stripped-envelope SN templates from the METAL collaboration:

matcher = SpectralTemplateMatcher.from_sesn_templates(
    cache_dir='my_templates'
)

From a Local SNID Template Directory

If you already have SNID template files (.lnw format) on disk, e.g. from the official SNID v2.0 release:

matcher = SpectralTemplateMatcher.from_snid_template_directory(
    '/path/to/snid/templates/templates-2.0/'
)

The parser automatically extracts type and phase information from the .lnw header.

Custom Template Library

Load templates from your own CSV or DAT files:

matcher = SpectralTemplateMatcher(template_library_path='/path/to/my/templates/')

Files should have two columns: wavelength (Angstroms) and flux. Naming convention: {type}_{phase}.csv (e.g., Ia_+5.csv). Type and phase can also be specified in header comments:

# Type: Ia
# Phase: +5.0
3500  0.82
3510  0.84
...

Matching Methods

The default matching method is 'rlap' — a SNID-style cross-correlation in log-wavelength (velocity) space that is shift-invariant and robust to continuum shape differences. A good match has rlap > 5; an excellent match has rlap > 8.

Basic Matching

result = matcher.match_spectrum(
    spectrum,
    redshift_range=(0, 0.5),  # Search redshift range
    method='rlap'             # 'rlap' (default), 'correlation', 'chi2', or 'both'
)

The result dictionary contains:

  • type — Supernova type classification

  • phase — Phase in days from maximum light

  • redshift — Best-fit redshift

  • rlap — SNID-style cross-correlation quality metric

  • correlation — Pearson correlation coefficient at best-fit redshift

  • chi2 — Chi-squared value (if using chi2 method)

  • template_name — Name of the matched template

Classification with Probabilities

classification = matcher.classify_spectrum(
    spectrum,
    redshift_range=(0, 0.3),
    top_n=10  # Consider top 10 matches
)

print(classification.summary())
# or access as a dict:
print(f"Best type: {classification['best_type']}")
print(f"Confidence: {classification['confidence']}")
print(f"Type probabilities: {classification['type_probabilities']}")

classify_spectrum returns a ClassificationResult object, which also behaves as a plain dictionary for backward compatibility.

Getting All Matches

all_matches = matcher.match_spectrum(
    spectrum,
    return_all_matches=True
)

for match in all_matches[:10]:
    print(f"{match['type']} z={match['redshift']:.3f} rlap={match['rlap']:.1f}")

Visualization

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(10, 6))
matcher.plot_match(spectrum, result, axes=ax)
plt.savefig('template_match.png')

Working with Templates

Adding Custom Templates

matcher.add_template(
    wavelength=wave_array,
    flux=flux_array,
    sn_type='Ia-pec',
    phase=+3.5,
    name='SN2011fe_near_max'
)

Filtering Templates

# Only Type Ia templates near maximum light
ia_matcher = matcher.filter_templates(
    types=['Ia'],
    phase_range=(-10, 15)
)

Saving Templates

matcher.save_templates('./my_template_library/', format='csv')

Templates are saved with # Type: and # Phase: metadata in the header so they can be reloaded with SpectralTemplateMatcher(template_library_path=...).

Advanced Usage

Chi-squared Matching

When flux errors are available, chi-squared matching provides an optimal flux scaling:

result = matcher.match_spectrum(spectrum, method='chi2')
print(f"Reduced chi2: {result['reduced_chi2']:.2f}")
print(f"Scale factor: {result['scale_factor']:.4f}")

Generating Templates from sncosmo

You can generate templates from any sncosmo source at custom phases:

templates = SpectralTemplateMatcher.generate_sncosmo_templates(
    sources=[
        ('salt2',      'Ia',   [-10, -5, 0, 5, 10, 15, 20]),
        ('v19-1998bw', 'Ic-BL', [0, 5, 10, 15]),
    ]
)
matcher = SpectralTemplateMatcher(templates=templates)

Example Scripts

A complete example is available at:

examples/spectral_template_matching_example.py

Citing Template Sources

When using spectral templates, please cite the appropriate sources:

  • SNID: Blondin & Tonry 2007, ApJ, 666, 1024

  • SALT2: Guy et al. 2007, A&A, 466, 11

  • SN 1998bw / v19: Vincenzi et al. 2019

  • Nugent templates: Nugent et al. 2002

  • Super-SNID: Magill et al. 2025 (Zenodo DOI: 10.5281/zenodo.15167198)

API Reference

Key methods on SpectralTemplateMatcher:

  • match_spectrum() — Find best-matching template

  • classify_spectrum() — Full classification with probabilities

  • plot_match() — Visualize matches

  • add_template() — Add a custom template

  • filter_templates() — Create a filtered sub-matcher

  • save_templates() — Export templates to CSV/DAT

  • from_snid_template_directory() — Load a directory of .lnw files

  • from_super_snid_templates() — Download and load Super-SNID library

  • from_sesn_templates() — Download and load SESNtemple library

  • download_github_templates() — Download any GitHub template repo

  • generate_sncosmo_templates() — Generate templates from sncosmo sources

  • get_available_template_sources() — List known external template libraries

Please check the API docs for full details on parameters and return values and any newer methods.