name: sagan description: Use this skill when the user asks to use SAGAN to fit a spectrum, do spectral fitting with SAGAN, or fit AGN or galaxy emission-line or absorption-line spectra with SAGAN. version: 1.0.0
SAGAN Spectral Fitting
SAGAN is a local Python package for fitting astronomical spectra, especially AGN and galaxy spectra with emission and absorption lines.
SAGAN should be available as the Python package sagan.
If code or local package inspection is needed, first locate the installed package with Python, for example:
python -c "import inspect, pathlib, sagan; print(pathlib.Path(inspect.getfile(sagan)).resolve())"
This skill helps with:
- fitting spectra with SAGAN
- building spectral models
- choosing line-profile components
- fitting AGN broad and narrow lines
- fitting absorption troughs
- using LSQ, MCMC, or nested sampling
- tying parameters between components
- applying instrumental LSF convolution
- measuring physical parameters from fitted spectra
When to use this skill
Use this skill when the user asks for things like:
- “Use SAGAN to fit the spectrum”
- “Fit this spectrum with SAGAN”
- “Use SAGAN for spectral fitting”
- “Fit the AGN spectrum with SAGAN”
- “Fit the emission lines with SAGAN”
- “Use SAGAN to model the absorption lines”
- “Use SAGAN to fit a Type 1 AGN spectrum”
- “Use SAGAN to fit BAL features”
Also use this skill when the user asks to:
- fit AGN or galaxy spectra
- decompose continuum, broad lines, narrow lines, and absorption
- fit Balmer lines, Fe II, or forbidden-line doublets
- run MCMC or Bayesian spectral fitting with SAGAN
Supported use cases
- Type 1 AGN
- BAL QSOs
- Type 2 AGN
- galaxies with stellar continua
- spectra with emission and/or absorption lines
Required routing before planning
Before proposing a fitting plan, first identify the task type and read the relevant documentation.
Read fitting_strategies/narrow_line_template.md first if the request mentions:
[S II],S II[N II],N II[O III],O IIIdoubletnarrow line templateLSFline spread functioninstrumental profileinstrumental broadening6716,6731, or6716/6731
Read fitting_strategies/type1_agn.md first if the request mentions:
Type 1 AGNbroad line AGNbroad Hαbroad Hbetabroad HβBalmerBALBAL QSOabsorption troughbroad absorption line
Read function_reference/line_profile_models.md first if the request is about:
- a simple single emission line
- choosing a line-profile class
- line model syntax
- basic component behavior
Read function_reference/parameter_tying.md first if the request is about:
- tying parameters
- shared velocities or widths
- doublet ratios
- linking absorption parameters across lines
Only after reading the relevant file should you propose a model or workflow.
General workflow
When this skill is used:
- Determine the science case and spectral region.
- Read the relevant routing document above before making a plan.
- Inspect the spectrum setup:
- wavelength range
- flux and uncertainty arrays
- rest frame or observed frame
- redshift
- instrumental resolution or LSF information
- Choose model components appropriate for the task.
- Start with an LSQ fit to obtain reasonable initial parameters.
- Refine with MCMC or dynesty if uncertainty estimation is needed.
- Clearly report:
- model components
- parameter ties
- assumptions
- priors or bounds
- measurements derived from the fit
Key modeling guidance
- Use
Line_MultiGauss_doubletfor forbidden-line doublets such as[S II],[N II], and[O III]. - Use
Line_templatefor narrow-line template fitting. - Use
Line_MultiGaussfor broad permitted lines such as Hα and Hβ. - Use
Line_Absorptionfor absorption components. - Apply LSF convolution when required by the instrument or data product.
- Prefer LSQ initialization before MCMC unless the user explicitly asks otherwise.
- Tie parameters where physically justified to reduce degeneracy.
Quick reference
Basic example
import numpy as np
import sagan
from sagan.utils import line_wave_dict
from astropy.modeling import fitting
# Load your spectrum
wave, flux, ferr = load_your_spectrum()
# Continuum + one Gaussian line
cont = sagan.WindowedPowerLaw1D(
amplitude=1.0,
x_0=5000,
alpha=-1.0,
x_min=4500,
x_max=5500,
)
line = sagan.Line_Gaussian(
amplitude=1.0,
dv=0,
sigma=500,
wavec=line_wave_dict["Halpha"],
)
model = cont + line
# LSQ fit
fitter = fitting.LevMarLSQFitter()
model_lsq = fitter(model, wave, flux, weights=1 / ferr**2)
# MCMC fit
mcmc = sagan.MCMC_Fit(model_lsq, wave, flux, ferr, nwalkers=50, nsteps=1000)
samples, model_fit, param_names = mcmc.fit()