# Overview¶

There are two basic kinds of spectra in synphot, those with and without flux units. The former is used to construct Source Spectrum and Observation, while the latter for Bandpass, extinction curve, and Thermal. In the center of them all are Astropy models, which are used to represent the data, to create composite spectra, and to evaluate the results.

For simplicity and to be consistent with ASTROLIB PYSYNPHOT, a spectrum object stores its wavelength internally in Angstrom. A source spectrum stores flux in PHOTLAM, while a unitless spectrum stores throughput as dimensionless_unscaled. Despite this, most of the functionalities in synphot are unit-aware; i.e., you can pass in Quantity and specify the desired output units via optional keywords (see relevant API documentation).

File I/O in synphot is handled by its specio module, which uses Astropy FITS and Astropy ASCII, but read (both FITS and ASCII) and write (FITS only) spectrum data in a way that is backward-compatible with ASTROLIB PYSYNPHOT. In most cases, this module does not need to be accessed directly, but rather via from_file() and to_fits() methods of a spectrum object.

## synphot and Astropy Models¶

Note

The interactions between synphot and astropy.models might change in the future as the latter support more features, such as Quantity. When that happens, the existing API will issue deprecation warnings, where appropriate.

synphot takes advantage of the analytical nature of Astropy models, except for tabular data, which are interpolated using Scipy. This is very different from ASTROLIB PYSYNPHOT that relied heavily on interpolation of internal lookup tables. But similar to ASTROLIB PYSYNPHOT, each individual model that goes into a compound (composite) model is stored separately and the final result is only calculated on evaluation. For simplicity, only 1D models and single model set (n_models=1) are supported.

At the time that this package was developed, some features needed for spectra manipulation were not (yet) available in Astropy models (e.g., Quantity parameters and sampleset that provides an array of values that best samples the model). In addition, some models (e.g., Empirical1D) are simply too specialized for our use case to be in Astropy. For those reasons, models exists to bridge that gap. For instance, a synphot.models.Gaussian1D is just like astropy.modeling.functional_models.Gaussian1D but with the extra sampleset. Still, some models can be used straight from Astropy (e.g., PowerLaw1D where sampleset is infinite, thus does not apply).

The following table lists the models allowed to be used for spectrum construction (with flux unit or unitless), where they reside, and special notes:

Model

Package

Notes

BlackBody1D

synphot

Calculate flux in PHOTLAM per steradian.

BlackBodyNorm1D

synphot

Calculate flux in PHOTLAM.

Box1D

synphot

Like astropy.modeling.functional_models.Box1D but with sampleset.

BrokenPowerLaw1D

Astropy

Flux handling might be incorrect unless amplitude is in PHOTLAM when creating a source spectrum using this model.

Const1D

Astropy

Flux handling might be incorrect unless amplitude is in PHOTLAM when creating a source spectrum using this model.

ConstFlux1D

synphot

Constant flux in a given unit might not be constant in other flux units. This handles flux unit conversion properly.

Empirical1D

synphot

Like Tabular1D but with extra features specific to spectrum (e.g., option to keep negative flux) and different default values.

ExponentialCutoffPowerLaw1D

Astropy

Flux handling might be incorrect unless amplitude is in PHOTLAM when creating a source spectrum using this model.

Gaussian1D

synphot

Like astropy.modeling.functional_models.Gaussian1D but with sampleset.

GaussianAbsorption1D

synphot

This is 1 - Gaussian1D model.

GaussianFlux1D

synphot

Like Gaussian1D but allows backward-compatible parameters like total flux and FWHM.

LogParabola1D

Astropy

Flux handling might be incorrect unless amplitude is in PHOTLAM when creating a source spectrum using this model.

Lorentz1D

synphot

Like astropy.modeling.functional_models.Lorentz1D but with sampleset and bounding_box.

RickerWavelet1D

synphot

Like astropy.modeling.functional_models.RickerWavelet1D but with sampleset and bounding_box.

PowerLaw1D

Astropy

Flux handling might be incorrect unless amplitude is in PHOTLAM when creating a source spectrum using this model.

PowerLawFlux1D

synphot

Like PowerLaw1D but handles flux unit conversion properly by evaluating in user flux unit instead of internal unit of PHOTLAM.

Trapezoid1D

synphot

Like astropy.modeling.functional_models.Trapezoid1D but with sampleset.

## Spectrum Arithmetic¶

When spectrum objects are added to, subtracted from, multiplied with, or divided by each other, the resultant spectrum contains a compound model derived from the operands. If the operands themselves also contain compound models, then the final compound model is a compound of the input compound models.

Operations that do not make sense (e.g., multiplying two source spectra or adding a bandpass to a source spectrum) are prohibited. The type of output spectrum depends on the operation. In the table below, unitless spectrum can be a bandpass or extinction curve:

Operand 1

Operation

Operand 2

Result

Commutative

Source Spectrum

$$+$$

Source Spectrum

Source Spectrum

Yes

Source Spectrum

$$-$$

Source Spectrum

Source Spectrum

No

Source Spectrum

$$\times$$

Unitless Spectrum

Source Spectrum

Yes

Source Spectrum

$$\times$$

Scalar number

Source Spectrum

Yes

Source Spectrum

$$\times$$

Unitless Quantity

Source Spectrum

No

Source Spectrum

$$/$$

Source Spectrum

Unitless Spectrum

No

Source Spectrum

$$/$$

Unitless Spectrum

Source Spectrum

No

Source Spectrum

$$/$$

Scalar number

Source Spectrum

No

Source Spectrum

$$/$$

Unitless Quantity

Source Spectrum

No

Unitless Spectrum

$$\times$$

Unitless Spectrum

Unitless Spectrum

Yes

Unitless Spectrum

$$\times$$

Scalar number

Unitless Spectrum

Yes

Unitless Spectrum

$$\times$$

Unitless Quantity

Unitless Spectrum

No

Unitless Spectrum

$$/$$

Unitless Spectrum

Unitless Spectrum

No

Unitless Spectrum

$$/$$

Scalar number

Unitless Spectrum

No

Unitless Spectrum

$$/$$

Unitless Quantity

Unitless Spectrum

No

## Quick Guide¶

The tables below summarize some main functionality of synphot. The variables, where appropriate, can be numbers (assumed to be in certain units) or Quantity. These are only for quick reference. Detailed explanations are available in their respective sections in the other parts of this document.

### Create Bandpass¶

Description

Command

bp = SpectralElement.from_file(filename)

bp = SpectralElement.from_filter(filtername)

Create from wavelength and throughput arrays.

bp = SpectralElement(Empirical1D, points=wavelength, lookup_table=throughput)

Box centered at mu with given width.

bp = SpectralElement(Box1D, x_0=mu, width=width)

Create from tapering existing bandpass.

bp2 = bp.taper()

### Calculate Bandpass Parameters¶

Description

Command

Average wavelength and associated throughput.

bp.avgwave()

bp.tlambda()

Peak throughput and associated wavelength.

bp.tpeak()

bp.wpeak()

Dimensionless efficiency.

bp.efficiency()

Equivalent width.

bp.equivwidth()

Rectangular width.

bp.rectwidth()

RMS band width as in Koornneef et al. 1986 (page 836).

bp.rmswidth()

RMS band width as in IRAF SYNPHOT.

bp.photbw()

FWHM of equiv. Gaussian.

bp.fwhm()

Pivot wavelength.

bp.pivot()

Mean log wavelength.

bp.barlam()

Unit response; flux that produces 1 count/s in the bandpass, for given telescope area.

bp.unit_response(area)

Equiv. monochromatic flux.

bp.emflx(area)

Check if bandpass fully overlaps a source spectrum.

bp.check_overlap(sp)

### Create Other Unitless Spectrum¶

Description

Command

Reddening law from extinction model. Creation using Astropy model and from file also possible but not shown.

redlaw = ReddeningLaw.from_extinction_model( extinction_model_name)

Extinction curve from reddening law at given $$E(B-V)$$

extcurve = redlaw.extinction_curve(ebv)

Extinction for Lyman-alpha

Bandpass with thermal properties (from model).

thbp = ThermalSpectralElement(modelclass, temperature, **kwargs)

Bandpass with thermal properties (from file).

thbp = ThermalSpectralElement.from_file( filename)

### Create Source Spectrum¶

Description

Command

sp = SourceSpectrum.from_file(filename)

sp = SourceSpectrum.from_vega()

Create from wavelength and flux arrays.

sp = SourceSpectrum(Empirical1D, points=wavelength, lookup_table=flux)

Blackbody with temperature, teff, and flux normalized to a star of solar radius at a distance of 1 kpc.

sp = SourceSpectrum(BlackBodyNorm1D, temperature=teff)

Flat spectrum with constant flux.

sp = SourceSpectrum(ConstFlux1D, amplitude=flux)

Powerlaw spectrum with flux of 1 in given unit at x and power of -a.

sp = SourceSpectrum(PowerLawFlux1D, amplitude=1*unit, x_0=x, alpha=a)

Gaussian emission line centered on mu with given FWHM and total flux.

sp = SourceSpectrum(GaussianFlux1D, mean=mu, fwhm=fwhm, total_flux=total_flux)

Thermal source spectrum from thermal bandpass.

sp = thbp.thermal_source()

### Modify Source Spectrum¶

New source spectrum is created as a result unless stated otherwise.

Description

Command

Taper flux to zero on ends.

sp2 = sp.taper()

Normalize to given value over given bandpass. Count and VEGAMAG unit requires extra inputs.

sp2 = sp.normalize(value, band=bp)

sp2 = sp.normalize(value_count, band=bp, area=area)

sp2 = sp.normalize(value_vegamag, band=bp, vegaspec=SourceSpectrum.from_vega())

Apply extinction curve.

sp2 = sp * extcurve

Apply redshift (models modified in-place).

sp.z = z

sp.z_type = …

Apply redshift (new source spectrum).

sp2 = SourceSpectrum(sp.model, z=z, z_type=…)

sp = SourceSpectrum(modelclass, z=z, z_type=…, **kwargs)

### Create Observation and Calculate¶

Observation has binned and unbinned components. Most methods accept an optional binned keyword to indicate which component you want to calculate for. Only the default binning option is listed below.

Description

Command

Observe a source spectrum through given bandpass.

obs = Observation(sp, bp)

Sample observed flux.

flux = obs(wavelength) # Unbinned

flux = obs.sample_binned(wavelength)

Effective wavelength.

obs.effective_wavelength() # Binned

Effective stimulus in given unit.

obs.effstim(flux_unit=unit) # Unbinned

Count rate for given area.

obs.countrate(area) # Binned

Convert into simple source spectrum.

sp = obs.as_spectrum() # Binned

### Miscellaneous¶

Description

Command

Generate wavelength array.

wavelength = generate_wavelengths()

Quick-look plot.

obj.plot() # Any spectrum object

Write to FITS table.

bp.to_fits(filename); redlaw.to_fits(); sp.to_fits(filename)

## FITS Table Format¶

The FITS table format supported here is the same as that in ASTROLIB PYSYNPHOT for backward compatibility with existing data files. Data is extracted from Extension 1, where the first column contains wavelength values, and the second flux (for source spectrum) or throughput (for bandpass). The extension header must contain the following keywords (unless you overwrite them with non-default values in read_fits_spec()):

• TUNIT1 set to supported wavelength unit name.

• TUNIT2 set to supported flux unit name (source spectrum only).

• TTYPE1 set to “WAVELENGTH”.

• TTYPE2 set to “FLUX” (for source spectrum) or “THROUGHPUT” (for bandpass).

For writing out FITS table, many options can be set to non-default as acceptable by write_fits_spec().

## ASCII Table Format¶

The ASCII table format supported here is the same as that in ASTROLIB PYSYNPHOT for backward compatibility with existing data files. Wavelength and flux/throughput values must be in the first and the second columns, respectively. By default, wavelength is assumed to be in Angstrom; For source spectrum, flux is assumed to be in FLAM. All values will be read in as double-precision floating points. The file may contain blank or comment lines (any lines starting with "#"), which are ignored.

By default, Astropy’s ASCII reader will attempt to guess the format of your file (e.g., space- or tab-delimited). If guessing fails, you can pass in additional keywords to the reader, as well as specifying non-default wavelength and flux units, via synphot.specio.read_ascii_spec().

## Result Accuracy¶

This is indirectly discussed in a similar section within stsynphot documentation as it is heavily built upon synphot machinery.