SNCosmo¶

SNCosmo is a Python library for supernova cosmology analysis. It aims to make such analysis both as flexible and clear as possible.
Installation¶
SNCosmo works on Python 2.7 and Python 3.4+ and requires the following Python packages:
Install using conda (recommended)¶
If you are using Anaconda or the conda package manager, you can install SNCosmo from the astropy channel:
conda install -c astropy sncosmo
The release of the conda version may lag behind the pip release, so
you may want to check the available conda version. You can do this
at the link above, or by running conda search -c astropy sncosmo
.
Install using pip¶
Using pip:
pip install --no-deps extinction sncosmo
Note
The --no-deps
flag is optional, but highly recommended if you
already have numpy, scipy and astropy installed, since otherwise
pip will sometimes try to “help” you by upgrading your Numpy
installation, which may not always be desired.
Note
If you get a PermissionError
this means that you do not have
the required administrative access to install new packages to your
Python installation. In this case you may consider using the
--user
option to install the package into your home directory.
You can read more about how to do this in the pip documentation.
Do not install sncosmo or other third-party packages using
sudo
unless you are fully aware of the risks.
Note
You will need a C compiler (e.g. gcc
or clang
) to be
installed for the installation to succeed.
Install latest development version¶
SNCosmo is being developed on github. To get the latest development
version using git
:
git clone git://github.com/sncosmo/sncosmo.git
cd sncosmo
then:
./setup.py install
As with the pip install instructions, you may want to use either
setup.py install --user
or setup.py develop
to alter where the
package is installed.
Optional dependencies¶
Several additional packages are recommended for enabling optional functionality in SNCosmo.
- matplotlib for plotting functions.
- iminuit for light curve
fitting using the Minuit minimizer in
sncosmo.fit_lc
. - emcee for MCMC light curve parameter
estimation in
sncosmo.mcmc_lc
. - nestle for nested sampling
light curve parameter estimation in
sncosmo.nest_lc
.
iminuit, emcee and nestle can be installed using pip.
The corner package is also
recommended for plotting results from the samplers sncosmo.mcmc_lc
and sncosmo.nest_lc
, but is not used by any part of sncosmo.
Supernova Models¶
Getting Started¶
Create a model using the built-in “source” named 'hsiao'
:
>>> import sncosmo
>>> model = sncosmo.Model(source='hsiao')
Set the redshift, time-of-zero-phase and the amplitude:
>>> model.set(z=0.5, t0=55000., amplitude=1.e-10)
Generate synthetic photometry through an observer-frame bandpass:
>>> model.bandmag('desr', 'ab', [54990., 55000., 55020.])
array([ 24.82381795, 24.41496701, 25.2950865 ])
Equivalent values in photons / s / cm^2:
>>> model.bandflux('desr', [54990., 55000., 55020.])
array([ 7.22413301e-05, 1.05275209e-04, 4.68034980e-05])
Equivalent values scaled so that 1 is equivalent to an AB magnitude of 25:
>>> model.bandflux('desr', [54990., 55000., 55020.], zp=25., zpsys='ab')
array([ 1.17617737, 1.71400939, 0.7620183 ])
Generate an observer-frame spectrum at a given time and wavelengths (in ergs/s/cm^2/Angstrom):
>>> model.flux(54990., [4000., 4100., 4200.])
array([ 4.31210900e-20, 7.46619962e-20, 1.42182787e-19])
Creating a model using a built-in source¶
A Model in sncosmo consists of
- One “source” A model of the spectral evolution of the source (e.g., a supernova).
- Zero or more “propagation effects” Models of how intervening structures (e.g., host galaxy dust, milky way dust) affect the spectrum.
In the above example, we created a model with no propagation effects,
using one of the built-in Source
instances that sncosmo knows
about: 'hsiao'
. See the full List of Built-in Sources that
sncosmo knows about.
Note
In fact, the data for “built-in” sources are hosted
remotely, downloaded as needed, and cached locally. So the
first time you load a given model, you need to be connected
to the internet. You will see a progress bar as the data
are downloaded. By default, SNCosmo will use a subdirectory
of the AstroPy cache directory for this purpose, e.g.,
$HOME/.astropy/cache/sncosmo
, but this can be changed
by setting the data_dir
configuration parameter in
$HOME/.astropy/config/sncosmo.cfg
. See Directory Configuration
for more information.
Some built-in source models have multiple versions, which can
be explicitly retrieved using the get_source
function:
>>> source = sncosmo.get_source('hsiao', version='2.0')
>>> model = sncosmo.Model(source=source)
Model parameters¶
Each model has a set of parameter names and values:
>>> model.param_names
['z', 't0', 'amplitude']
>>> model.parameters
array([ 0., 0., 1.])
These can also be retrieved as:
>>> model.get('z')
0.0
>>> model['z']
0.0
Parameter values can be set by any of the following methods:
>>> model.parameters[0] = 0.5
>>> model.parameters = [0.5, 0., 1.] # set the entire array
>>> model['z'] = 0.5
>>> model.set(z=0.5)
>>> model.set(z=0.5, amplitude=2.0) # Can specify multiple parameters
>>> model.update({'z': 0.5, 'amplitude': 2.0})
What do these parameters mean? The first two, z
and t0
are
common to all Model
instances:
z
is the redshift of the source.t0
is the observer-frame time corresponding to the source’s phase=0.
Note that in some sources phase=0 might be at explosion while others
might be at max: the definition of phase is arbitrary. However,
observed time is always related to phase via time = t0 + phase *
(1 + z)
The next, amplitude
, is specific to the particular type of
source. In this case, the source is a simple spectral timeseries that
can only be scaled up and down. Other sources could have other
parameters that affect the shape of the spectrum at each phase.
For a given model, you can set the amplitude
(or x0
in case you
are using a SALT model) according to a desired absolute magnitude in a
specific band by using the method
set_source_peakabsmag()
. Note that the redshift z
affects
your result. Therefore, you could specify:
>>> model.set(z=1.6)
>>> model.set_source_peakabsmag(-19.0, 'bessellb', 'ab')
Specifically, for SALT models, it is recommended to call
set_source_peakabsmag()
after setting the other model
parameters, such as x1
and c
. It probably won’t make a
difference if you are using the 'bessellb'
bandpass, but if you
were setting the absolute magnitude in another band, it would make a
small difference.
The reason for this peculiarity is that “absolute magnitude” is not a
parameter in the SALT2 model, per se. The parameters are x0
, x1
,
c
, t0
, and z
. x0
is a simple multiplicative scaling factor on
the whole spectral timeseries. The set_source_peakabsmag()
method is a
convenience for setting x0
such that the integrated flux through a
given bandpass is as desired. Since the integrated flux depends on the
spectral shape, it will depend on x1
and c
.
Creating a model with a source and effect(s)¶
Let’s create a slightly more complex model. Again we will use the Hsiao spectral time series as a source, but this time we will add host galaxy dust.
>>> dust = sncosmo.CCM89Dust()
>>> model = sncosmo.Model(source='hsiao',
... effects=[dust],
... effect_names=['host'],
... effect_frames=['rest'])
The model now has additional parameters that describe the dust, hostebv
and hostr_v
:
>>> model.param_names
['z', 't0', 'amplitude', 'hostebv', 'hostr_v']
>>> model.parameters
array([ 0. , 0. , 1. , 0. , 3.1])
These are the parameters of the CCM89Dust
instance we created:
>>> dust.param_names
['ebv', 'r_v']
In the model, the parameter names are prefixed with the name of the effect
(host
).
At any time you can print the model to get a nicely formatted string representation of its components and current parameter values:
>>> print(model)
<Model at 0x...>
source:
class : TimeSeriesSource
name : hsiao
version : 3.0
phases : [-20, .., 85] days (22 points)
wavelengths: [1000, .., 25000] Angstroms (481 points)
effect (name='host' frame='rest'):
class : CCM89Dust
wavelength range: [1250, 33333] Angstroms
parameters:
z = 0.0
t0 = 0.0
amplitude = 1.0
hostebv = 0.0
hostr_v = 3.1000000000000001
Also, str(model)
will return this string rather than printing it.
Adding Milky Way dust¶
Dust in the Milky Way will affect the shape of an observed supernova spectrum. It is important to take this into account in our model when fitting the model to observed data. As with host galaxy dust treated above, we can model Milky Way dust as a “propagation effect”. The only difference is that Milky Way dust is in the observer frame rather than the supernova rest frame. Here, we create a model with dust in both the SN rest frame and the observer frame:
>>> dust = sncosmo.CCM89Dust()
>>> model = sncosmo.Model(source='hsiao',
... effects=[dust, dust],
... effect_names=['host', 'mw'],
... effect_frames=['rest', 'obs'])
We can see that the model includes four extra parameters (two describing the host galaxy dust and two describing the milky way dust):
>>> model.param_names
['z', 't0', 'amplitude', 'hostebv', 'hostr_v', 'mwebv', 'mwr_v']
>>> model.parameters # default values
array([ 0. , 0. , 1. , 0. , 3.1, 0. , 3.1])
The host galaxy dust parameters are prefixed with 'host'
and the
Milky Way dust parameters are prefixed with 'mw'
. These are just
the names we supplied when constructing the model. The effect names
have no significance beyond this. The effect frames, on the other
hand, are significant. The only allowed values are 'rest'
(rest
frame) and 'obs'
(observer frame).
A typical use pattern is to get an estimate of the amount of Milky Way dust at the location of the supernova from a dust map, and then to fix that amount of dust in the model. The following example illustrates how to do this using the Schlegel, Finkbeiner and Davis (1998) dust map with the sfdmap package. First, load the dust map (do this only once):
>>> import sfdmap
>>> dustmap = sfdmap.SFDMap("/path/to/dust/maps")
Now, for each SN you wish to fit, get the amount of dust at the SN location
and set the mwebv
model parameter appropriately. For example, if the SN is
located at RA=42.8 degrees, Dec=0 degrees:
>>> ebv = dustmap.ebv(42.8, 0.0)
>>> model.set(mwebv=ebv)
>>> # proceed with fitting the other model parameters to the data.
Note that we wish to fix the mwebv
model parameter rather than
fitting it to the data like the other parameters: We’re supposing that
this value is perfectly known from the dust map. Therefore, when using
a function such as fit_lc
to fit the parameters, be sure not to
include 'mwebv'
in the list of parameters to vary.
Model spectrum¶
To retrieve a spectrum (in ergs / s / cm^2 / Angstrom) at a given observer-frame time and set of wavelengths:
>>> wave = np.array([3000., 3500., 4000., 4500., 5000., 5500.])
>>> model.flux(-5., wave)
array([ 5.29779465e-09, 7.77702880e-09, 7.13309678e-09,
5.68369041e-09, 3.06860759e-09, 2.59024291e-09])
We can supply a list or array of times and get a 2-d array back, representing the spectrum at each time:
>>> model.flux([-5., 2.], wave)
array([[ 5.29779465e-09, 7.77702880e-09, 7.13309678e-09,
5.68369041e-09, 3.06860759e-09, 2.59024291e-09],
[ 2.88166481e-09, 6.15186858e-09, 7.87880448e-09,
6.93919846e-09, 3.59077596e-09, 3.27623932e-09]])
Changing the model parameters changes the results:
>>> model.parameters
array([0., 0., 1., 0., 3.1])
>>> model.flux(-5., [4000., 4500.])
array([ 7.13309678e-09, 5.68369041e-09])
>>> model.set(amplitude=2., hostebv=0.1)
>>> model.flux(-5., [4000., 4500.])
array([ 9.39081327e-09, 7.86972003e-09])
Synthetic photometry¶
To integrate the spectrum through a bandpass, use the bandflux method:
>>> model.bandflux('sdssi', -5.)
180213.72886169454
Here we are using the SDSS I band, at time -5. days. The return value is in photons / s / cm^2. It is also possible to supply multiple times or bands:
>>> model.bandflux('sdssi', [-5., 2.])
array([ 180213.72886169, 176662.68287381])
>>> model.bandflux(['sdssi', 'sdssz'], [-5., -5.])
array([ 180213.72886169, 27697.76705621])
Instead of returning flux in photons / s / cm^2, the flux can be normalized
to a desired zeropoint by specifying the zp
and zpsys
keywords,
which can also be scalars, lists, or arrays.
>>> model.bandflux(['sdssi', 'sdssz'], [-5., -5.], zp=25., zpsys='ab')
array([ 5.01036850e+09, 4.74414435e+09])
Instead of flux, magnitude can be returned. It works very similarly to flux:
>>> model.bandmag('sdssi', 'ab', [0., 1.])
array([ 22.6255077 , 22.62566363])
>>> model.bandmag('sdssi', 'vega', [0., 1.])
array([ 22.26843273, 22.26858865])
We have been specifying the bandpasses as strings ('sdssi'
and
'sdssz'
). This works because these bandpasses are in the sncosmo
“registry”. However, this is merely a convenience. In place of
strings, we could have specified the actual Bandpass
objects to which the strings correspond. See Bandpasses
for more on how to directly create Bandpass
objects.
The magnitude systems work similarly to bandpasses: 'ab'
and
'vega'
refer to built-in MagSystem
objects, but you can
also directly supply custom MagSystem
objects. See
Magnitude Systems for details.
Initializing Sources directly¶
You can initialize a source directly from your own template rather than using the built-in source templates.
Initializing a TimeSeriesSource
¶
These sources are created directly from numpy arrays. Below, we build a very simple model, of a source with a flat spectrum at all times, rising from phase -50 to 0, then declining from phase 0 to +50.
>>> import numpy as np
>>> phase = np.linspace(-50., 50., 11)
>>> disp = np.linspace(3000., 8000., 6)
>>> flux = np.repeat(np.array([[0.], [1.], [2.], [3.], [4.], [5.],
... [4.], [3.], [2.], [1.], [0.]]),
... 6, axis=1)
>>> source = sncosmo.TimeSeriesSource(phase, disp, flux)
Typically, you would then include this source in a Model
:
>>> model = sncosmo.Model(source)
Initializing a SALT2Source
¶
The SALT2 model is initialized directly from data files representing the model. You can initialize it by giving it a path to a directory containing the files.
>>> source = sncosmo.SALT2Source(modeldir='/path/to/dir')
By default, the initializer looks for files with names like
'salt2_template_0.dat'
, but this behavior can be altered with keyword
parameters:
>>> source = sncosmo.SALT2Source(modeldir='/path/to/dir',
... m0file='mytemplate0file.dat')
See SALT2Source
for more details.
Bandpasses¶
Constructing a Bandpass¶
Bandpass objects represent the transmission fraction of an astronomical filter as a function of dispersion (photon wavelength, frequency or energy). They are basically simple containers for arrays of these values, with a couple special features. To get a bandpass that is in the registry (built-in):
>>> import sncosmo
>>> band = sncosmo.get_bandpass('sdssi')
>>> band
<Bandpass 'sdssi' at 0x...>
To create a Bandpass directly, you can supply arrays of wavelength and transmission values:
>>> wavelength = [4000., 5000.]
>>> transmission = [1., 1.]
>>> sncosmo.Bandpass(wavelength, transmission, name='tophatg')
<Bandpass 'tophatg' at 0x...>
By default, the first argument is assumed to be wavelength in Angstroms.
To specify a different dispersion unit, use a unit from the
astropy.units
package:
>>> import astropy.units as u
>>> wavelength = [400., 500.]
>>> transmission = [1., 1.]
>>> Bandpass(wavelength, transmission, wave_unit=u.nm)
<Bandpass 'tophatg' at 0x...>
Using a Bandpass¶
A Bandpass acts like a continuous 1-d function, returning the transmission at supplied wavelengths (always in Angstroms):
>>> band([4100., 4250., 4300.])
array([ 0., 1., 1.])
Note that the transmission is zero outside the defined wavelength range. Linear interpolation is used between the defined wavelengths.
Bnadpasses have a few other useful properties. You can get the range of wavelengths where the transmission is non-zero:
>>> band.minwave(), band.maxwave()
(4000.0, 5000.0)
Or the transmission-weighted effective wavelength:
>>> band.wave_eff
4500.0
Or the name:
>>> band.name
'tophatg'
Adding Bandpasses to the Registry¶
You can create your own bandpasses and use them like built-ins by adding them to the registry. Suppose we want to register the ‘tophatg’ bandpass we created:
>>> sncosmo.register(band, 'tophatg')
Or if band.name
has been set:
>>> sncosmo.register(band) # registers band under band.name
After doing this, we can get the bandpass object by doing
>>> band = sncosmo.get_bandpass('tophatg')
Also, we can pass the string 'tophatg'
to any function that
takes a Bandpass
object. This means that you can create
and register bandpasses at the top of a script, then just keep track
of string identifiers throughout the rest of the script.
Magnitude Systems¶
SNCosmo has facilities for converting synthetic model photometry to
magnitudes in a variety of magnitude systems (or equivalently, scaling
fluxes to a given zeropoint in a given magnitude system). For example,
in the following code snippet, the string 'ab'
specifies that we
want magnitudes on the AB magnitude system:
>>> model.bandmag('desr', 'ab', [54990., 55000., 55020.])
The string 'ab'
here refers to a built-in magnitude system
('vega'
is another option). Behind the scenes magnitude systems
are represented with MagSystem
objects. As with
Bandpass
objects, most places in SNCosmo that require a
magnitude system can take either the name of a magnitude system in the
registry or an actual MagSystem
instance. You can access
these objects directly or create your own.
MagSystem
objects represent the spectral flux density
corresponding to magnitude zero in the given system and can be used to
convert physical fluxes (in photons/s/cm^2) to magnitudes. Here’s an
example:
>>> ab = sncosmo.get_magsystem('ab')
>>> ab.zpbandflux('sdssg')
546600.83408598113
This example gives the number of counts (in photons) when integrating the AB spectrum (which happens to be F_nu = 3631 Jansky at all wavelengths) through the SDSS g band. This works similarly for other magnitude systems:
>>> vega = sncosmo.get_magsystem('vega')
>>> vega.zpbandflux('sdssg')
597541.25707788975
You can see that the Vega spectrum is a bit brighter than the AB spectrum in this particular bandpass. Therefore, SDSS g magnitudes given in Vega will be larger than if given in AB.
There are convenience methods for converting an observed flux in a bandpass to a magnitude:
>>> ab.band_flux_to_mag(1., 'sdssg')
14.344175725172901
>>> ab.band_mag_to_flux(14.344175725172901, 'sdssg')
0.99999999999999833
So, one count per second in this band is equivalent to an AB magnitude of about 14.34.
“Composite” magnitude systems¶
Sometimes, photometric data is reported in “magnitude systems” that
don’t correspond directly to any spectrophotometric standard. One
example is “SDSS magnitudes” which are like AB magnitudes but with an
offset in each band. These are represented in SNCosmo with the
CompositeMagSystem
class. For example:
>>> magsys = sncosmo.CompositeMagSystem(bands={'sdssg': ('ab', 0.01),
... 'sdssr': ('ab', 0.02)})
This defines a new magnitude system that knows about only two bandpasses. In this magnitude system, an object with magnitude zero in AB would have a magntide of 0.01 in SDSS g and 0.02 in SDSS r. Indeed, you can see that the flux corresponding to magnitude zero is slightly higher in this magnitude system than in AB:
>>> magsys.zpbandflux('sdssr')
502660.28545283229
>>> ab.zpbandflux('sdssr')
493485.70128115633
Since we’ve only defined the offsets for this magnitude system in a couple bands, using other bandpasses results in an error:
>>> magsys.zpbandflux('bessellb')
ValueError: band not defined in composite magnitude system
Photometric Data¶
Photometric data stored in AstroPy Table¶
In sncosmo, photometric data for a supernova is stored in an astropy
Table
: each row in the table is a photometric
observation. The table must contain certain columns. To see what such
a table looks like, you can load an example with the following
function:
>>> data = sncosmo.load_example_data()
>>> print data
time band flux fluxerr zp zpsys
------------- ----- ----------------- -------------- ---- -----
55070.0 sdssg 0.813499900062 0.651728140824 25.0 ab
55072.0512821 sdssr -0.0852238865812 0.651728140824 25.0 ab
55074.1025641 sdssi -0.00681659003089 0.651728140824 25.0 ab
55076.1538462 sdssz 2.23929135407 0.651728140824 25.0 ab
55078.2051282 sdssg -0.0308977349373 0.651728140824 25.0 ab
55080.2564103 sdssr 2.35450321853 0.651728140824 25.0 ab
... etc ...
This example data table above has the minimum six columns necessary for sncosmo’s light curve fitting and plotting functions to interpret the data. (There’s no harm in having more columns for other supplementary data.)
Additionally, metadata about the photometric data can be stored with
the table: data.meta
is an OrderedDict
of the metadata.
Including Covariance¶
If your table contains a column 'fluxcov'
(or any similar name;
see below) it will be interpreted as covariance between the data
points and will be used instead of the 'fluxerr'
column when
calculating a \(\chi^2\) value in fitting functions. For each row,
the 'fluxcov'
column should be a length N array, where N is the
number of rows in the table. In other, words, table['fluxcov']
should
have shape (N, N)
, where other columns like table['time']
have shape
(N,)
.
As an example, let’s add a 'fluxcov'
column to the example data
table above.
>>> data['fluxcov'] = np.diag(data['fluxerr']**2)
>>> len(data)
40
>>> data['fluxcov'].shape
(40, 40)
# diagonal elements are error squared:
>>> data['fluxcov'][0, 0]
0.45271884317377648
>>> data['fluxerr'][0]
0.67284384754100002
# off diagonal elements are zero:
>>> data['fluxcov'][0, 1]
0.0
As is, this would be completely equivalent to just having the
'fluxerr'
column. But now we have the flexibility to represent
non-zero off-diagonal covariance.
Note
When sub-selecting data from a table with covariance, be sure to
use sncosmo.select_data
. For example, rather than
table[mask]
, use sncosmo.select_data(table, mask)
. This
ensures that the covariance column is sliced appropriately! See the
documentation for select_data
for details.
Flexible column names¶
What if you’d rather call the time column 'date'
, or perhaps
'mjd'
? Good news! SNCosmo is flexible about the column names. For
each column, it accepts a variety of alias names:
Column | Acceptable aliases (case-independent) | Description | Type |
---|---|---|---|
time | ‘mjd’, ‘mjdobs’, ‘date’, ‘time’, ‘jd’, ‘mjd_obs’ | Time of observation in days | float |
band | ‘filter’, ‘band’, ‘flt’, ‘bandpass’ | Bandpass of observation | str |
flux | ‘flux’, ‘f’ | Flux of observation | float |
fluxerr | ‘flux_error’, ‘fluxerr’, ‘fluxerror’, ‘flux_err’, ‘fe’ | Gaussian uncertainty on flux | float |
zp | ‘zp’, ‘zeropoint’, ‘zpt’, ‘zero_point’ | Zeropoint corresponding to flux | float |
zpsys | ‘zpsys’, ‘magsys’, ‘zpmagsys’ | Magnitude system for zeropoint | str |
fluxcov | ‘fluxcov’, ‘covar’, ‘covmat’, ‘covariance’, ‘cov’ | Covariance between observations (array; optional) | ndarray |
Note that each column must be present in some form or another, with no
repeats. For example, you can have either a 'flux'
column or a
'f'
column, but not both.
The units of the flux and flux uncertainty are effectively given by
the zeropoint system, with the zeropoint itself serving as a scaling
factor: For example, if the zeropoint is 25.0
and the zeropoint
system is 'vega'
, a flux of 1.0 corresponds to 10**(-25/2.5)
times the integrated flux of Vega in the given bandpass.
Reading and Writing photometric data from files¶
SNCosmo strives to be agnostic with respect to file format. In
practice there are a plethora of different file formats, both standard
and non-standard, used to represent tables. Rather than picking a
single supported file format, or worse, creating yet another new
“standard”, we choose to leave the file format mostly up to the user:
A user can use any file format as long as they can read their data
into an astropy Table
.
That said, SNCosmo does include a couple convenience functions for
reading and writing tables of photometric data: sncosmo.read_lc
and
sncosmo.write_lc
:
>>> data = sncosmo.load_example_data()
>>> sncosmo.write_lc(data, 'test.txt')
This creates an output file test.txt
that looks like:
@x1 0.5
@c 0.2
@z 0.5
@x0 1.20482820761e-05
@t0 55100.0
time band flux fluxerr zp zpsys
55070.0 sdssg 0.36351153597 0.672843847541 25.0 ab
55072.0512821 sdssr -0.200801295864 0.672843847541 25.0 ab
55074.1025641 sdssi 0.307494232981 0.672843847541 25.0 ab
55076.1538462 sdssz 1.08776103656 0.672843847541 25.0 ab
55078.2051282 sdssg -0.43667895645 0.672843847541 25.0 ab
55080.2564103 sdssr 1.09780966779 0.672843847541 25.0 ab
... etc ...
Read the file back in:
>>> data2 = sncosmo.read_lc('test.txt')
There are a few other available formats, which can be specified using
the format
keyword:
>>> data = sncosmo.read_lc('test.json', format='json')
The supported formats are listed below. If your preferred format is not included, use a standard reader/writer from astropy or the Python universe.
Format name | Description | Notes |
---|---|---|
ascii (default) | ASCII with metadata lines marked by ‘@’ | Not readable by standard ASCII table parsers due to metadata lines. |
json | JavaScript Object Notation | Good performance, but not as human-readable as ascii |
salt2 | SALT2 new-style data files | |
salt2-old | SALT2 old-style data files |
Manipulating data tables¶
Because photometric data tables are astropy Tables, they can be manipulated any way that Tables can. Here’s a few things you might want to do.
Rename a column:
>>> data.rename_column('oldname', 'newname')
Add a column:
>>> data['zp'] = 26.
Add a constant value to all the entries in a given column:
>>> data['zp'] += 0.03
See the documentation on astropy tables for more information.
Applying Cuts¶
It is useful to be able to apply “cuts” to data before trying to fit a
model to the data. This is particularly important when using some of
the “guessing” algorithms in fit_lc
and nest_lc
that use a minimum signal-to-noise ratio to pick “good” data
points. These algorithms will raise an exception if there are no data
points meeting the requirements, so it is advisable to check if the
data meets the requirements beforehand.
Signal-to-noise ratio cuts¶
Require at least one datapoint with signal-to-noise ratio (S/N) greater than 5 (in any band):
>>> passes = np.max(data['flux'] / data['fluxerr']) > 5.
>>> passes
True
Require two bands each with at least one datapoint having S/N > 5:
>>> mask = data['flux'] / data['fluxerr'] > 5.
>>> passes = len(np.unique(data['band'][mask])) >= 2
>>> passes
True
Simulation¶
First, define a set of “observations”. These are the properties of our observations: the time, bandpass and depth.
import sncosmo
from astropy.table import Table
obs = Table({'time': [56176.19, 56188.254, 56207.172],
'band': ['desg', 'desr', 'desi'],
'gain': [1., 1., 1.],
'skynoise': [191.27, 147.62, 160.40],
'zp': [30., 30., 30.],
'zpsys':['ab', 'ab', 'ab']})
print obs
skynoise zpsys band gain time zp
-------- ----- ---- ---- --------- ----
191.27 ab desg 1.0 56176.19 30.0
147.62 ab desr 1.0 56188.254 30.0
160.4 ab desi 1.0 56207.172 30.0
Suppose we want to simulate a SN with the SALT2 model and the following parameters:
model = sncosmo.Model(source='salt2')
params = {'z': 0.4, 't0': 56200.0, 'x0':1.e-5, 'x1': 0.1, 'c': -0.1}
To get the light curve for this single SN, we’d do:
lcs = sncosmo.realize_lcs(obs, model, [params])
print lcs[0]
time band flux fluxerr zp zpsys
--------- ---- ------------- ------------- ---- -----
56176.19 desg 96.0531272705 191.27537908 30.0 ab
56188.254 desr 456.360196623 149.22627064 30.0 ab
56207.172 desi 655.40885611 162.579572369 30.0 ab
Note that we’ve passed the function a one-element list, [params]
,
and gotten back a one-element list in return. (The realize_lcs
function is designed to operate on lists of SNe for convenience.)
Generating SN parameters¶
We see above that it is straightforward to simulate SNe once we already know the parameters of each one. But what if we want to pick SN parameters from some defined distribution?
Suppose we want to generate SN parameters for all the SNe we would find in a given search area over a defined period of time. We start by defining an area and time period, as well as a maximum redshift to consider:
area = 1. # area in square degrees
tmin = 56175. # minimum time
tmax = 56225. # maximum time
zmax = 0.7
First, we’d like to get the number and redshifts of all SNe that occur over our 1 square degree and 50 day time period:
redshifts = list(sncosmo.zdist(0., zmax, time=(tmax-tmin), area=area))
print len(redshifts), "SNe"
print "redshifts:", redshifts
9 SNe
redshifts: [0.4199710008856507, 0.3500118339133868, 0.5915676316485601, 0.5857452631151785, 0.49024466410556855, 0.5732679644841575, 0.6224436826380927, 0.5853477892182203, 0.5522300320124105]
Generate a list of SN parameters using these redshifts, drawing x1
and c
from normal distributions:
from numpy.random import uniform, normal
params = [{'x0':1.e-5, 'x1':normal(0., 1.), 'c':normal(0., 0.1),
't0':uniform(tmin, tmax), 'z': z}
for z in redshifts]
for p in params:
print p
{'z': 0.4199710008856507, 'x0': 1e-05, 'x1': -0.9739877070754421, 'c': -0.1465835504611458, 't0': 56191.57686616353}
{'z': 0.3500118339133868, 'x0': 1e-05, 'x1': 0.04454878604727126, 'c': -0.04920811869083081, 't0': 56222.76963606611}
{'z': 0.5915676316485601, 'x0': 1e-05, 'x1': -0.26765265677262423, 'c': -0.06456008680932701, 't0': 56211.706219411404}
{'z': 0.5857452631151785, 'x0': 1e-05, 'x1': 0.8255953341731204, 'c': 0.08520083775049729, 't0': 56209.33583211229}
{'z': 0.49024466410556855, 'x0': 1e-05, 'x1': -0.12051827966517584, 'c': -0.09490756669333822, 't0': 56189.37571007927}
{'z': 0.5732679644841575, 'x0': 1e-05, 'x1': 0.3051310078192594, 'c': -0.10967604820261241, 't0': 56198.04368422346}
{'z': 0.6224436826380927, 'x0': 1e-05, 'x1': -0.6329407028587257, 'c': -0.009789183239376284, 't0': 56179.88133113836}
{'z': 0.5853477892182203, 'x0': 1e-05, 'x1': 0.6373371286596669, 'c': 0.05151693090038232, 't0': 56212.04579735962}
{'z': 0.5522300320124105, 'x0': 1e-05, 'x1': 0.04762095339856289, 'c': -0.005018877828783951, 't0': 56182.14827040906}
So far so good. The only problem is that x0
doesn’t vary. We’d like
it to be randomly distributed with some scatter around the Hubble line,
so it should depend on the redshift. Here’s an alternative:
params = []
for z in redshifts:
mabs = normal(-19.3, 0.3)
model.set(z=z)
model.set_source_peakabsmag(mabs, 'bessellb', 'ab')
x0 = model.get('x0')
p = {'z':z, 't0':uniform(tmin, tmax), 'x0':x0, 'x1': normal(0., 1.), 'c': normal(0., 0.1)}
params.append(p)
for p in params:
print p
{'c': -0.060104568346581566, 'x0': 2.9920355958896461e-05, 'z': 0.4199710008856507, 'x1': -0.677121283126299, 't0': 56217.93979718883}
{'c': 0.10405991801014292, 'x0': 2.134500759148091e-05, 'z': 0.3500118339133868, 'x1': 1.6034252041294512, 't0': 56218.008314206476}
{'c': -0.14777109151711296, 'x0': 7.9108889725043354e-06, 'z': 0.5915676316485601, 'x1': -2.2082282760850993, 't0': 56218.013686428785}
{'c': 0.056034777154805086, 'x0': 6.6457371815973038e-06, 'z': 0.5857452631151785, 'x1': 0.675413080007434, 't0': 56189.03517395757}
{'c': -0.0709158052635228, 'x0': 1.2228145655148946e-05, 'z': 0.49024466410556855, 'x1': 0.5449847454420981, 't0': 56198.02895700289}
{'c': -0.22101146234021096, 'x0': 7.4299221264917702e-06, 'z': 0.5732679644841575, 'x1': -1.543245858395605, 't0': 56189.04585414441}
{'c': 0.06964843664572477, 'x0': 9.7121906557832662e-06, 'z': 0.6224436826380927, 'x1': 1.7419604610283943, 't0': 56212.827270197355}
{'c': 0.07320513053870191, 'x0': 3.22205341646521e-06, 'z': 0.5853477892182203, 'x1': -0.39658066375434153, 't0': 56200.421464066916}
{'c': 0.18555773972769227, 'x0': 7.5955258508017471e-06, 'z': 0.5522300320124105, 'x1': -0.24463691193386283, 't0': 56190.492271332616}
Now we can generate the lightcurves for these parameters:
lcs = sncosmo.realize_lcs(obs, model, params)
print lcs[0]
time band flux fluxerr zp zpsys
--------- ---- ------------- ------------ ---- -----
56176.19 desg 6.70520005464 191.27 30.0 ab
56188.254 desr 106.739113709 147.62 30.0 ab
56207.172 desi 1489.7521011 164.62420476 30.0 ab
Note that the “true” parameters are saved in the metadata of each SN:
lcs[0].meta
{'c': -0.060104568346581566,
't0': 56217.93979718883,
'x0': 2.9920355958896461e-05,
'x1': -0.677121283126299,
'z': 0.4199710008856507}
Registry¶
What is it?¶
The registry (sncosmo.registry
) is responsible for translating
string identifiers to objects, for user convenience. For example, it is
used in sncosmo.get_bandpass
and sncosmo.get_source
to return a
Bandpass
or sncosmo.Model
object based on the name of
the bandpass or model:
>>> sncosmo.get_bandpass('sdssi')
<Bandpass 'sdssi' at 0x28e7c90>
It is also used in methods like bandflux
to
give it the ability to accept either a Bandpass
object or
the name of a bandpass:
>>> model = sncosmo.Model(source='hsiao')
>>> model.bandflux('sdssg', 0.) # works, thanks to registry.
Under the covers, the bandflux
method retrieves the Bandpass
corresponding to 'sdssg'
by calling the
sncosmo.get_bandpass
function.
The registry is actually quite simple: it basically amounts to a dictionary and a few functions for accessing the dictionary. Most of the time, a user doesn’t need to know anything about the registry. However, it is useful if you want to add your own “built-ins” or change the name of existing ones.
Using the registry to achieve custom “built-ins”¶
There are a small set of “built-in” models, bandpasses, and magnitude systems. But what if you want additional ones?
Create a file mydefs.py
that registers all your custom definitions:
# contents of mydefs.py
import numpy as np
import sncosmo
wave = np.array([4000., 4200., 4400., 4600., 4800., 5000.])
trans = np.array([0., 1., 1., 1., 1., 0.])
band = sncosmo.Bandpass(wave, trans, name='tophatg')
sncosmo.registry.register(band)
Make sure mydefs.py
is somewhere in your $PYTHONPATH
or the
directory you are running your main script from. Now in your script
import your definitions at the beginning:
>>> import sncosmo
>>> import mydefs
>>> # ... proceed as normal
>>> # you can now use 'tophatg' as a built-in
Changing the name of built-ins¶
To change the name of the 'sdssg'
band to 'SDSS_G'
:
# contents of mydefs.py
import sncosmo
band = sncosmo.get_bandpass('sdssg')
band.name = 'SDSS_G'
sncosmo.register(band)
Large built-ins¶
What if your built-ins are really big or you have a lot of them? You
might only want to load them as they are needed, rather than having to
load everything into memory when you do import mydefs
. You can use
the sncosmo.registry.register_loader
function. Suppose we have a
bandpass that requires a huge data file (In reality it is unlikely
that loading bandpasses would take a noticeable amount of time, but it
might for models or spectra.):
# contents of mydefs.py
import sncosmo
def load_bandpass(filename, name=None, version=None):
# ...
# read data from filename, create a Bandpass object, "band"
# ...
return band
filename = 'path/to/datafile/for/huge_tophatg'
sncosmo.register_loader(
sncosmo.Bandpass, # class of object returned.
'huge_tophatg', # name
load_bandpass, # function that does the loading
[filename] # arguments to pass to function
)
Now when you import mydefs
the registry will know how to load the
Bandpass
named 'huge_tophatg'
when it is needed. When
loaded, it will be saved in memory so that subsequent operations don’t
need to load it again.
Directory Configuration¶
The “built-in” Sources and Spectra in SNCosmo depend on some sizable data files. These files are hosted remotely, downloaded as needed, and cached locally. This all happens automatically, but it is helpful to know where the files are stored if you want to inspect them or share a common download directory between multiple users.
By default, SNCosmo will create and use an sncosmo
subdirectory in
the AstroPy cache directory for this purpose. For example,
$HOME/.astropy/cache/sncosmo
. After using a few models and spectra
for the first time, here is what that directory might look like:
$ tree ~/.astropy/cache/sncosmo
/home/kyle/.astropy/cache/sncosmo
├── models
│ ├── hsiao
│ │ └── Hsiao_SED_V3.fits
│ └── sako
│ ├── S11_SDSS-000018.SED
│ ├── S11_SDSS-001472.SED
│ └── S11_SDSS-002000.SED
└── spectra
├── alpha_lyr_stis_007.fits
└── bd_17d4708_stisnic_005.fits
You can see that within the top-level $HOME/.astropy/cache/sncosmo
directory, a particular directory structure is created. This directory
structure is fixed in the code, so it’s best not to move things around
within the top-level directory. If you do, sncosmo will think the data
have not been downloaded and will re-download them.
Configuring the Directories¶
What if you would rather use a different directory to store downloaded data? Perhaps you’d rather the data not be in a hidden directory, or perhaps there are multiple users who wish to use a shared data directory. There are two options:
Set the environment variable
SNCOSMO_DATA_DIR
to the directory you wish to use. For example, in bash:export SNCOSMO_DATA_DIR=/home/user/data/sncosmo
If this environment variable is set, it takes precedence over the second option (below).
Set the
data_dir
variable in the sncosmo configuartion file. This file is found in the astropy configuration directory, e.g.,$HOME/.astropy/config/sncosmo.cfg
. When youimport sncosmo
it checks for this file and creates a default one if it doesn’t exist. The default one looks like this:$ cat ~/.astropy/config/sncosmo.cfg ## Directory containing SFD (1998) dust maps, with names: ## 'SFD_dust_4096_ngp.fits' and 'SFD_dust_4096_sgp.fits' ## Example: sfd98_dir = /home/user/data/sfd98 # sfd98_dir = None ## Directory where sncosmo will store and read downloaded data resources. ## If None, ASTROPY_CACHE_DIR/sncosmo will be used. ## Example: data_dir = /home/user/data/sncosmo # data_dir = None
To change the data directory, simply uncomment the last line and set it to the desired directory. You can even move the data directory around, as long as you update this configuration parameter accordingly.
orphan: |
---|
Examples¶
Fitting a light curve¶
This example shows how to fit the parameters of a SALT2 model to photometric light curve data.
First, we’ll load an example of some photometric data.
from __future__ import print_function
import sncosmo
data = sncosmo.load_example_data()
print(data)
Out:
time band flux fluxerr zp zpsys
------------- ----- --------------- -------------- ---- -----
55070.0 sdssg 0.36351153597 0.672843847541 25.0 ab
55072.0512821 sdssr -0.200801295864 0.672843847541 25.0 ab
55074.1025641 sdssi 0.307494232981 0.672843847541 25.0 ab
55076.1538462 sdssz 1.08776103656 0.672843847541 25.0 ab
55078.2051282 sdssg -0.43667895645 0.672843847541 25.0 ab
55080.2564103 sdssr 1.09780966779 0.672843847541 25.0 ab
55082.3076923 sdssi 3.7562685627 0.672843847541 25.0 ab
55084.3589744 sdssz 5.34858894966 0.672843847541 25.0 ab
55086.4102564 sdssg 2.82614187269 0.672843847541 25.0 ab
55088.4615385 sdssr 7.56547045054 0.672843847541 25.0 ab
... ... ... ... ... ...
55129.4871795 sdssr 2.6597485586 0.672843847541 25.0 ab
55131.5384615 sdssi 3.99520404021 0.672843847541 25.0 ab
55133.5897436 sdssz 5.73989458094 0.672843847541 25.0 ab
55135.6410256 sdssg 0.330702283107 0.672843847541 25.0 ab
55137.6923077 sdssr 0.565286726579 0.672843847541 25.0 ab
55139.7435897 sdssi 3.04318346795 0.672843847541 25.0 ab
55141.7948718 sdssz 5.62692686384 0.672843847541 25.0 ab
55143.8461538 sdssg -0.722654789013 0.672843847541 25.0 ab
55145.8974359 sdssr 1.12091764262 0.672843847541 25.0 ab
55147.9487179 sdssi 2.1246695264 0.672843847541 25.0 ab
55150.0 sdssz 5.3482175645 0.672843847541 25.0 ab
Length = 40 rows
An important additional note: a table of photometric data has a
band
column and a zpsys
column that use strings to identify
the bandpass (e.g., 'sdssg'
) and zeropoint system ('ab'
) of
each observation. If the bandpass and zeropoint systems in your data
are not built-ins known to sncosmo, you must register the
corresponding Bandpass
or MagSystem
to the
right string identifier using the registry.
# create a model
model = sncosmo.Model(source='salt2')
# run the fit
result, fitted_model = sncosmo.fit_lc(
data, model,
['z', 't0', 'x0', 'x1', 'c'], # parameters of model to vary
bounds={'z':(0.3, 0.7)}) # bounds on parameters (if any)
Out:
Downloading http://supernovae.in2p3.fr/salt/lib/exe/fetch.php?media=salt2_model_data-2-4.tar.gz [Done]
Downloading http://sncosmo.github.io/data/bandpasses/sdss/sdss_g.dat [Done]
Downloading http://sncosmo.github.io/data/bandpasses/sdss/sdss_r.dat [Done]
Downloading http://sncosmo.github.io/data/bandpasses/sdss/sdss_i.dat [Done]
Downloading http://sncosmo.github.io/data/bandpasses/sdss/sdss_z.dat [Done]
The first object returned is a dictionary-like object where the keys
can be accessed as attributes in addition to the typical dictionary
lookup like result['ncall']
:
print("Number of chi^2 function calls:", result.ncall)
print("Number of degrees of freedom in fit:", result.ndof)
print("chi^2 value at minimum:", result.chisq)
print("model parameters:", result.param_names)
print("best-fit values:", result.parameters)
print("The result contains the following attributes:\n", result.keys())
Out:
('Number of chi^2 function calls:', 133)
('Number of degrees of freedom in fit:', 35)
('chi^2 value at minimum:', 33.809882360763005)
('model parameters:', ['z', 't0', 'x0', 'x1', 'c'])
('best-fit values:', array([ 5.15154859e-01, 5.51004778e+04, 1.19625368e-05,
4.67270999e-01, 1.93951997e-01]))
('The result contains the following attributes:\n', ['errors', 'parameters', 'success', 'data_mask', 'ndof', 'covariance', 'vparam_names', 'chisq', 'nfit', 'param_names', 'message', 'ncall'])
The second object returned is a shallow copy of the input model with the parameters set to the best fit values. The input model is unchanged.
sncosmo.plot_lc(data, model=fitted_model, errors=result.errors)

Suppose we already know the redshift of the supernova we’re trying to
fit. We want to set the model’s redshift to the known value, and then
make sure not to vary z
in the fit.
model.set(z=0.5) # set the model's redshift.
result, fitted_model = sncosmo.fit_lc(data, model,
['t0', 'x0', 'x1', 'c'])
sncosmo.plot_lc(data, model=fitted_model, errors=result.errors)

Total running time of the script: ( 0 minutes 4.565 seconds)
Using a custom fitter or sampler¶
How to use your own minimizer or MCMC sampler for fitting light curves.
SNCosmo has three functions for model parameter estimation based on
photometric data: sncosmo.fit_lc
, sncosmo.mcmc_lc
and
sncosmo.nest_lc
. These are wrappers around external minimizers or
samplers (respectively: iminuit, emcee and nestle). However, one may
wish to experiment with a custom fitting or sampling method.
Here, we give a minimal example of using the L-BFGS-B minimizer from scipy.
from __future__ import print_function
import numpy as np
from scipy.optimize import fmin_l_bfgs_b
import sncosmo
model = sncosmo.Model(source='salt2')
data = sncosmo.load_example_data()
# Define an objective function that we will pass to the minimizer.
# The function arguments must comply with the expectations of the specfic
# minimizer you are using.
def objective(parameters):
model.parameters[:] = parameters # set model parameters
# evaluate model fluxes at times/bandpasses of data
model_flux = model.bandflux(data['band'], data['time'],
zp=data['zp'], zpsys=data['zpsys'])
# calculate and return chi^2
return np.sum(((data['flux'] - model_flux) / data['fluxerr'])**2)
# starting parameter values in same order as `model.param_names`:
start_parameters = [0.4, 55098., 1e-5, 0., 0.] # z, t0, x0, x1, c
# parameter bounds in same order as `model.param_names`:
bounds = [(0.3, 0.7), (55080., 55120.), (None, None), (None, None),
(None, None)]
parameters, val, info = fmin_l_bfgs_b(objective, start_parameters,
bounds=bounds, approx_grad=True)
print(parameters)
Out:
[ 4.25825914e-01 5.50980000e+04 1.10729251e-05 -4.88206597e-03
3.54030794e-01]
The built-in parameter estimation functions in sncosmo take care of setting up the likelihood function in the way that the underlying fitter or sampler expects. Additionally, they set guesses and bounds and package results up in a way that is as consistent as possible. For users wishing use a custom minimizer or sampler, it can be instructive to look at the source code for these functions.
Total running time of the script: ( 0 minutes 1.021 seconds)
Creating a new Source class¶
Extending sncosmo with a custom type of Source.
A Source
is something that specifies a spectral timeseries as
a function of an arbitrary number of parameters. For example, the SALT2
model has three parameters (x0
, x1
and c
) that determine a
unique spectrum as a function of phase. The SALT2Source
class implements
the behavior of the model: how the spectral time series depends on those
parameters.
If you have a spectral timeseries model that follows the behavior of one of
the existing classes, such as TimeSeriesSource
, great! There’s no need to
write a custom class. However, suppose you want to implement a model that
has some new parameterization. In this case, you need a new class that
implements the behavior.
In this example, we implement a new type of source model. Our model is a linear
combination of two spectral time series, with a parameter w
that
determines the relative weight of the models.
from __future__ import print_function
import numpy as np
from scipy.interpolate import RectBivariateSpline
import sncosmo
class ComboSource(sncosmo.Source):
_param_names = ['amplitude', 'w']
param_names_latex = ['A', 'w'] # used in plotting display
def __init__(self, phase, wave, flux1, flux2, name=None, version=None):
self.name = name
self.version = version
self._phase = phase
self._wave = wave
# ensure that fluxes are on the same scale
flux2 = flux1.max() / flux2.max() * flux2
self._model_flux1 = RectBivariateSpline(phase, wave, flux1, kx=3, ky=3)
self._model_flux2 = RectBivariateSpline(phase, wave, flux2, kx=3, ky=3)
self._parameters = np.array([1., 0.5]) # initial parameters
def _flux(self, phase, wave):
amplitude, w = self._parameters
return amplitude * ((1.0 - w) * self._model_flux1(phase, wave) +
w * self._model_flux2(phase, wave))
… and that’s all that we need to define!: A couple class attributes
(_param_names
and param_names_latex
, an __init__
method,
and a _flux
method. The _flux
method is guaranteed to be passed
numpy arrays for phase and wavelength.
We can now initialize an instance of this source from two spectral time series:
#Just as an example, we'll use some undocumented functionality in
# sncosmo to download the Nugent Ia and 2p templates. Don't rely on this
# the `DATADIR` object, or these paths in your code though, as these are
# subject to change between version of sncosmo!
from sncosmo.builtins import DATADIR
phase1, wave1, flux1 = sncosmo.read_griddata_ascii(
DATADIR.abspath('models/nugent/sn1a_flux.v1.2.dat'))
phase2, wave2, flux2 = sncosmo.read_griddata_ascii(
DATADIR.abspath('models/nugent/sn2p_flux.v1.2.dat'))
# In our __init__ method we defined above, the two fluxes need to be on
# the same grid, so interpolate the second onto the first:
flux2_interp = RectBivariateSpline(phase2, wave2, flux2)(phase1, wave1)
source = ComboSource(phase1, wave1, flux1, flux2_interp, name='sn1a+sn2p')
Out:
Downloading http://c3.lbl.gov/nugent/templates/sn1a_flux.v1.2.dat.gz [Done]
Downloading http://c3.lbl.gov/nugent/templates/sn2p_flux.v1.2.dat.gz [Done]
We can get a summary of the Source we created:
print(source)
Out:
class : ComboSource
name : 'sn1a+sn2p'
version : None
phases : [0, .., 90] days
wavelengths: [1000, .., 25000] Angstroms
parameters:
amplitude = 1.0
w = 0.5
Get a spectrum at phase 10 for different parameters:
from matplotlib import pyplot as plt
wave = np.linspace(2000.0, 10000.0, 500)
for w in (0.0, 0.2, 0.4, 0.6, 0.8, 1.0):
source.set(w=w)
plt.plot(wave, source.flux(10., wave), label='w={:3.1f}'.format(w))
plt.legend()
plt.show()

The w=0 spectrum is that of the Ia model, the w=1 spectrum is that of the IIp model, while intermediate spectra are weighted combinations.
We can even fit the model to some data!
model = sncosmo.Model(source=source)
data = sncosmo.load_example_data()
result, fitted_model = sncosmo.fit_lc(data, model,
['z', 't0', 'amplitude', 'w'],
bounds={'z': (0.2, 1.0),
'w': (0.0, 1.0)})
sncosmo.plot_lc(data, model=fitted_model, errors=result.errors)

The fact that the fitted value of w is closer to 0 than 1 indicates that the light curve looks more like the Ia template than the IIp template. This is generally what we expected since the example data here was generated from a Ia template (although not the Nugent template!).
Total running time of the script: ( 0 minutes 3.964 seconds)
Gallery generated by Sphinx-Gallery
Reference / API¶
Model & Components¶
Model (source[, effects, effect_names, …]) |
An observer-frame model, composed of a Source and zero or more effects. |
Source component of Model
Source () |
An abstract base class for transient models. |
TimeSeriesSource (phase, wave, flux[, …]) |
A single-component spectral time series model. |
StretchSource (phase, wave, flux[, name, version]) |
A single-component spectral time series model, that “stretches” in time. |
SALT2Source ([modeldir, m0file, m1file, …]) |
The SALT2 Type Ia supernova spectral timeseries model. |
Effect components of Model: interstellar dust extinction
PropagationEffect |
Abstract base class for propagation effects. |
CCM89Dust () |
Cardelli, Clayton, Mathis (1989) extinction model dust. |
OD94Dust () |
O’Donnell (1994) extinction model dust. |
F99Dust ([r_v]) |
Fitzpatrick (1999) extinction model dust with fixed R_V. |
Bandpass & Magnitude Systems¶
Bandpass (wave, trans[, wave_unit, …]) |
Transmission as a function of spectral wavelength. |
AggregateBandpass (transmissions[, …]) |
Bandpass defined by multiple transmissions in series. |
BandpassInterpolator (transmissions, …[, …]) |
Bandpass generator defined as a function of focal plane position. |
MagSystem ([name]) |
An abstract base class for magnitude systems. |
ABMagSystem ([name]) |
Magnitude system where a source with F_nu = 3631 Jansky at all frequencies has magnitude 0 in all bands. |
SpectralMagSystem (refspectrum[, name]) |
A magnitude system defined by a fundamental spectrophotometric standard. |
CompositeMagSystem ([bands, families, name]) |
A magnitude system defined in a specific set of bands. |
I/O¶
Functions for reading and writing photometric data, gridded data, extinction maps, and more.
read_lc (file_or_dir[, format]) |
Read light curve data for a single supernova. |
write_lc (data, fname[, format]) |
Write light curve data. |
read_bandpass (fname[, fmt, wave_unit, …]) |
Read bandpass from two-column ASCII file containing wavelength and transmission in each line. |
load_example_data () |
Load an example photometric data table. |
read_snana_ascii (fname[, default_tablename]) |
Read an SNANA-format ascii file. |
read_snana_fits (head_file, phot_file[, snids, n]) |
Read the SNANA FITS format: two FITS files jointly representing metadata and photometry for a set of SNe. |
read_snana_simlib (fname) |
Read an SNANA ‘simlib’ (simulation library) ascii file. |
read_griddata_ascii (name_or_obj) |
Read 2-d grid data from a text file. |
read_griddata_fits (name_or_obj[, ext]) |
Read a multi-dimensional grid of data from a FITS file, where the grid coordinates are encoded in the FITS-WCS header keywords. |
write_griddata_ascii (x0, x1, y, name_or_obj) |
Write 2-d grid data to a text file. |
write_griddata_fits (x0, x1, y, name_or_obj) |
Write a 2-d grid of data to a FITS file |
Fitting Photometric Data¶
Estimate model parameters from photometric data
fit_lc (data, model, vparam_names[, bounds, …]) |
Fit model parameters to data by minimizing chi^2. |
mcmc_lc (data, model, vparam_names[, bounds, …]) |
Run an MCMC chain to get model parameter samples. |
nest_lc (data, model, vparam_names, bounds[, …]) |
Run nested sampling algorithm to estimate model parameters and evidence. |
Convenience functions
select_data (data, index) |
Convenience function for indexing photometric data with covariance. |
chisq (data, model[, modelcov]) |
Calculate chisq statistic for the model, given the data. |
flatten_result (res) |
Turn a result from fit_lc into a simple dictionary of key, value pairs. |
Plotting¶
Convenience functions for quick standard plots (requires matplotlib)
plot_lc ([data, model, bands, zp, zpsys, …]) |
Plot light curve data or model light curves. |
Simulation¶
zdist (zmin, zmax[, time, area, ratefunc, …]) |
Generate a distribution of redshifts. |
realize_lcs (observations, model, params[, …]) |
Realize data for a set of SNe given a set of observations. |
Registry¶
Register and retrieve custom built-in sources, bandpasses, and magnitude systems
register (instance[, name, data_class, force]) |
Register a class instance. |
register_loader (data_class, name, func[, …]) |
Register a data reading function. |
get_source (name[, version, copy]) |
Retrieve a Source from the registry by name. |
get_bandpass (name, *args) |
Get a Bandpass from the registry by name. |
get_magsystem (name) |
Get a MagSystem from the registry by name. |
List of Built-in Sources¶
[Rb0467a492107-N02] | Nugent, Kim & Permutter 2002 |
[Rb0467a492107-S04] | Stern, et al. 2004 |
[Rb0467a492107-L05] | Levan et al. 2005 |
[Rb0467a492107-G99] | Gilliland, Nugent & Phillips 1999 |
[Rb0467a492107-S11] | Sako et al. 2011 |
[Rb0467a492107-H07] | Hsiao et al. 2007 |
[Rb0467a492107-G10] | Guy et al. 2010 |
[Rb0467a492107-B14b] | Betoule et al. 2014 |
[Rb0467a492107-H17] | Hounsell et al. 2017 |
[Rb0467a492107-P13] | Pereira et al. 2013 |
[Rb0467a492107-Whalen13] | Whalen et al. 2013 |
[Rb0467a492107-Jha07] | Jha, Riess and Kirshner 2007 |
[Rb0467a492107-1] | extracted from SNANA’s SNDATA_ROOT on 29 March 2013. |
[Rb0467a492107-2] | extracted from the SNooPy package on 21 Dec 2012. |
[Rb0467a492107-3] | extracted from SNANA’s SNDATA_ROOT on 15 August 2013. |
[Rb0467a492107-4] | extracted from SNANA’s SNDATA_ROOT on 24 April 2018. SALT2 model with wide wavelength range, Hounsell et al. 2017 |
[Rb0467a492107-5] | extracted from SNANA’s SNDATA_ROOT on 5 August 2014. |
[Rb0467a492107-6] | private communication (D.Whalen, May 2014). |
[Rb0467a492107-7] | In MLCS2k2 language, this version corresponds to “MLCS2k2 v0.07 rv19-early-smix vectors” |
List of Built-in Bandpasses¶
snls3-landolt¶
[R98e64ca268e7-B14a] | Betoule et al. (2014), Footnote 21 |
(Source code, png, hires.png, pdf)

des¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘desg’ | Dark Energy Camera grizy filter set at airmass 1.3 | 22 March 2013 | ||
‘desr’ | Dark Energy Camera grizy filter set at airmass 1.3 | 22 March 2013 | ||
‘desi’ | Dark Energy Camera grizy filter set at airmass 1.3 | 22 March 2013 | ||
‘desz’ | Dark Energy Camera grizy filter set at airmass 1.3 | 22 March 2013 | ||
‘desy’ | Dark Energy Camera grizy filter set at airmass 1.3 | 22 March 2013 |
(Source code, png, hires.png, pdf)

acs¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘f435w’ | Hubble Space Telescope ACS WFC filters | b | direct download | |
‘f475w’ | Hubble Space Telescope ACS WFC filters | b | direct download | |
‘f555w’ | Hubble Space Telescope ACS WFC filters | b | direct download | |
‘f606w’ | Hubble Space Telescope ACS WFC filters | b | direct download | |
‘f625w’ | Hubble Space Telescope ACS WFC filters | b | direct download | |
‘f775w’ | Hubble Space Telescope ACS WFC filters | b | direct download | |
‘f850lp’ | Hubble Space Telescope ACS WFC filters | b | direct download |
(Source code, png, hires.png, pdf)

nicmos-nic2¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘nicf110w’ | Hubble Space Telescope NICMOS2 filters | c | 05 Aug 2014 | |
‘nicf160w’ | Hubble Space Telescope NICMOS2 filters | c | 05 Aug 2014 |
(Source code, png, hires.png, pdf)

wfc3-ir¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘f098m’ | Hubble Space Telescope WFC3 IR filters | d | direct download | |
‘f105w’ | Hubble Space Telescope WFC3 IR filters | d | direct download | |
‘f110w’ | Hubble Space Telescope WFC3 IR filters | d | direct download | |
‘f125w’ | Hubble Space Telescope WFC3 IR filters | d | direct download | |
‘f127m’ | Hubble Space Telescope WFC3 IR filters | d | direct download | |
‘f139m’ | Hubble Space Telescope WFC3 IR filters | d | direct download | |
‘f140w’ | Hubble Space Telescope WFC3 IR filters | d | direct download | |
‘f153m’ | Hubble Space Telescope WFC3 IR filters | d | direct download | |
‘f160w’ | Hubble Space Telescope WFC3 IR filters | d | direct download |
(Source code, png, hires.png, pdf)

wfc3-uvis¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘f218w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘f225w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘f275w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘f300x’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘f336w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘f350lp’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘f390w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘f689m’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘f763m’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘f845m’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘f438w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘uvf475w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘uvf555w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘uvf606w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘uvf625w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘uvf775w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘uvf814w’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download | |
‘uvf850lp’ | Hubble Space Telescope WFC3 UVIS filters (CCD 2) | d | direct download |
(Source code, png, hires.png, pdf)

kepler¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘kepler’ | Bandpass for the Kepler spacecraft | e | direct download |
csp¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘cspb’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘csphs’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘csphd’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspjs’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspjd’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspv3009’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspv3014’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspv9844’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspys’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspyd’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspg’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspi’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspk’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspr’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 | |
‘cspu’ | Carnegie Supernova Project filters (Swope+DuPont Telescopes) updated 6 Oct 2016 | f | 8 Feb 2017 |
(Source code, png, hires.png, pdf)

jwst-nircam¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘f070w’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f090w’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f115w’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f150w’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f200w’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f277w’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f356w’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f444w’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f140m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f162m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f182m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f210m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f250m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f300m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f335m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f360m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f410m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f430m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f460m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 | |
‘f480m’ | James Webb Space Telescope NIRCAM Wide+Medium filters | g | 09 Sep 2014 |
(Source code, png, hires.png, pdf)

jwst-miri¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘f560w’ | James Webb Space Telescope MIRI filters | h | 16 Feb 2017 | |
‘f770w’ | James Webb Space Telescope MIRI filters | h | 16 Feb 2017 | |
‘f1000w’ | James Webb Space Telescope MIRI filters | h | 16 Feb 2017 | |
‘f1130w’ | James Webb Space Telescope MIRI filters | h | 16 Feb 2017 | |
‘f1280w’ | James Webb Space Telescope MIRI filters | h | 16 Feb 2017 | |
‘f1500w’ | James Webb Space Telescope MIRI filters | h | 16 Feb 2017 | |
‘f1800w’ | James Webb Space Telescope MIRI filters | h | 16 Feb 2017 | |
‘f2100w’ | James Webb Space Telescope MIRI filters | h | 16 Feb 2017 | |
‘f2550w’ | James Webb Space Telescope MIRI filters | h | 16 Feb 2017 |
(Source code, png, hires.png, pdf)

jwst-miri-tophat¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘f1065c’ | James Webb Space Telescope MIRI filters (idealized tophat) | i | 09 Sep 2014 | |
‘f1140c’ | James Webb Space Telescope MIRI filters (idealized tophat) | i | 09 Sep 2014 | |
‘f1550c’ | James Webb Space Telescope MIRI filters (idealized tophat) | i | 09 Sep 2014 | |
‘f2300c’ | James Webb Space Telescope MIRI filters (idealized tophat) | i | 09 Sep 2014 |
(Source code, png, hires.png, pdf)

lsst¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘lsstu’ | LSST baseline total throughputs, v1.1. | j | 16 Nov 2016 | |
‘lsstg’ | LSST baseline total throughputs, v1.1. | j | 16 Nov 2016 | |
‘lsstr’ | LSST baseline total throughputs, v1.1. | j | 16 Nov 2016 | |
‘lssti’ | LSST baseline total throughputs, v1.1. | j | 16 Nov 2016 | |
‘lsstz’ | LSST baseline total throughputs, v1.1. | j | 16 Nov 2016 | |
‘lssty’ | LSST baseline total throughputs, v1.1. | j | 16 Nov 2016 |
(Source code, png, hires.png, pdf)

keplercam¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘keplercam::us’ | Keplercam transmissions as used in JLA | a | 13 Feb 2017 | |
‘keplercam::b’ | Keplercam transmissions as used in JLA | a | 13 Feb 2017 | |
‘keplercam::v’ | Keplercam transmissions as used in JLA | a | 13 Feb 2017 | |
‘keplercam::r’ | Keplercam transmissions as used in JLA | a | 13 Feb 2017 | |
‘keplercam::i’ | Keplercam transmissions as used in JLA | a | 13 Feb 2017 |
(Source code, png, hires.png, pdf)

4shooter2¶
Name | Description | Reference | Data URL | Retrieved |
---|---|---|---|---|
‘4shooter2::us’ | 4Shooter filters as used in JLA | a | 13 Feb 2017 | |
‘4shooter2::b’ | 4Shooter filters as used in JLA | a | 13 Feb 2017 | |
‘4shooter2::v’ | 4Shooter filters as used in JLA | a | 13 Feb 2017 | |
‘4shooter2::r’ | 4Shooter filters as used in JLA | a | 13 Feb 2017 | |
‘4shooter2::i’ | 4Shooter filters as used in JLA | a | 13 Feb 2017 |
(Source code, png, hires.png, pdf)

megacampsf¶
These are radially-variable bandpasses. To get a Bandpass at a given radius, use band = sncosmo.get_bandpass('megacampsf::g', 13.0)
(Source code, png, hires.png, pdf)

List of Built-in Magnitude Systems¶
Name | Description | Subclass | Spectrum Source |
---|---|---|---|
‘jla1’ | JLA1 magnitude system based on BD+17 STIS v003 spectrum | CompositeMagSystem |
a |
‘ab’ | Source of 3631 Jy has magnitude 0 in all bands | ABMagSystem |
|
‘vega’ | Vega (alpha lyrae) has magnitude 0 in all bands. | SpectralMagSystem |
b |
‘bd17’ | BD+17d4708 has magnitude 0 in all bands. | SpectralMagSystem |
b |
‘csp’ | Carnegie Supernova Project magnitude system. | CompositeMagSystem |
c |
‘ab-b12’ | Betoule et al (2012) calibration of SDSS system. | CompositeMagSystem |
a |
More…¶
Version History¶
Note: SNCosmo uses Semantic Versioning for its version numbers. Specifically, this means that code written for sncosmo v1.0 will continue to work with any v1.x version. However, exact results may differ between versions in the 1.x series. (For example, due to changes in integration method.)
v1.6.0 (2018-04-27)¶
- Add Hounsell et al. (2017) SALT2 model to built-ins.
- Add
remote_timeout
configuration option. - Build system: remove build-time dependency on astropy helpers.
- Bugfixes:
- Correctly delete empty files created when a download fails.
- Use pseudo-inverse when inverting covariance matrix for increased stability.
- Fix an issue with pickling on Cython 0.26+.
- Fixed problem where
data['fluxcov']
was unintentionally being modified in-place when passed tofit_lc
. - Fixed problem where
'fluxcov'
not recognized as a valid name for covariance column in data infit_lc
.
v1.5.0 (2017-04-20)¶
This is a major new release. The highlight is really close compatibility of
the SALT2 model and fitting procedure with snfit
, the “official” SALT2
fitter.
SALT2Source
: Internal interpolation scheme ofSALT2Source
updated to matchsnfit
implementation exactly. Test suite now tests againstsnfit
implementation.fit_lc()
:- Handling of model covariance updated to match that of
snfit
: model covariance is fixed for each fit and fit is repeated until convergence. - New arguments
phase_range
andwave_range
. If given, data outside this range will be discarded after an initial fit and additional fits will be performed until convergence. Withphase_range=(-15., 45.)
andwave_range=(3000., 7000.)
, behavior approximates that of snfit with default arguments. - Added support for covariance in photometric data measurements, and
this covariance is used in
fit_lc()
if present. Covariance is stored as a'fluxcov'
column in the table of measurements. - Result includes two new attributes:
data_mask
, a boolean array indicating which rows in the input data were used in the final fit (since multiple fits might be performed), andnfit
, the number of fits performed. - New argument
warn
can be set to False to turn off warnings about dropping bands outside model wavelength range.
- Handling of model covariance updated to match that of
read_lc()
:Added support for reading snfit-format “covmat” files into a table of photometry:
>>> data = read_lc('filename', format='salt2', read_covmat=True) >>> data['Fluxcov'].shape == (len(data), len(data)) True
New keyword argument
expand_bands
. When True, the returned band column will containBandpass
objects instead of strings. (Strings converted to bandpass objects usingsncosmo.get_bandpass()
.) This is particularly useful for position-dependent bandpasses in the salt2 file format, such asmegacampsf
:read_lc()
reads the position from the header and feeds the position toget_bandpass()
to get a Bandpass object for the correct position.
Built-in bandpasses and magnitude systems: Many new built-in bandpasses and magnitude systems.
Configuration: The environment variable
SNCOSMO_DATA_DIR
can be used to set the path to the data directory. If set, it takes precedence over thedata_dir
variable in the configuration file ($HOME/.astropy/config/sncosmo.cfg
).
v1.4.0 (2016-11-16)¶
SFD98Map
andget_ebv_from_map
deprecated in favor of separate package sfdmap which has vastly improved performance (200x faster) for the typical case of scalar coordinates in ICRS frame.animate_source()
deprecated. This is a “fun extra” that is difficult to test and no longer seems to work.- Cython implementation of extinction functions has been factored out into
a separate Python module called
extinction
, which is now a dependency. Model.bandflux()
andSource.bandflux()
now integrate on a fixed wavelength grid of 5 angstroms regardless of the wavelength grid of the bandpass. This will result in small differences in results from previous sncosmo versions.- The internal (publicly undocumented)
Spectrum
class now acts more likeModel
; in particular, itsbandflux()
method now behaves the same way. AsSpectrum
backsSpectralMagSystem
, this makes the integration of models and zeropoint spectra more consistent. - Experimental (non-public) support for aliases for bandpasses,
such as
'SDSS::g'
for'sdssg'
. - Sources now use cubic rather than quadratic spline interpolation internally.
Model.source_peakmag()
andModel.set_source_peakmag()
added as convenience functions forModel.source.peakmag()
andModel.source.set_peakmag()
respectively.- [Bugfix] Fixed missing import of
math
module inmcmc_lc()
when using thepriors
keyword. [Backported to v1.3.1] [#143]
v1.3.0 (2016-06-30)¶
This is mostly a bugfix release, but it also drops support for Python 2.6. Python 2.7 is now the minimum supported Python version.
Updates for compatibility with AstroPy 1.2.
The registry now handles subclasses more robustly. For example, if
magsys
is an instance ofSpectralMagSystem
, the following used to fail:sncosmo.register(magsys, 'name') sncosmo.get_magsystem('name')
Now this works. [#132]
[Bugfix]
SALT2Source
had a bug under Python 3 (only) yielding drastically wrong fluxes. Python 2 was not affected. [#138]
v1.2.0 (2015-12-01)¶
[API change] Registry functions moved to the top-level namespace, as follows:
sncosmo.registry.register()
->sncosmo.register()
sncosmo.registry.register_loader()
->sncosmo.register_loader()
sncosmo.registry.retrieve()
-> deprecated, use class-specific functions such assncosmo.get_bandpass()
.
The old import paths will still work for backwards compatibility.
nest_lc()
now uses thenestle
module under the hood. A new keywordmethod
is available which selects different sampling methods implemented bynestle
. The new methods provide potential efficiency gains.The MLCS2k2 model is now available as a built-in Source, with the name
'mlcs2k2'
.Bandpasses from the Carnegie Supernova Project added to built-ins.
In
realize_lcs()
, a newscatter
keyword makes adding noise optional.[Bugfix] Fix built-in Bessell bandpass definitions, which were wrong by a term proportional to inverse wavelength. This was due to misinterpretation of the trasmission units. [backported to v1.1.1] [#111]
v1.1.0 (2015-08-12)¶
This is a mostly bugfix release with more solid support for Python 3.
- Added
Model.color()
method. - Remove
loglmax
from result ofnest_lc()
, which was not officially documented or supported. Usenp.max(res.logl)
instead. - Fixed bug that caused non-reproducible behavior in
nest_lc()
even whennumpy.random.seed()
was called directly beforehand. [#102] - Fixed file I/O problems on Python 3 related to string encoding. [#83, #85]
- Fixed problem with SDSS bandpasses being stored as integers internally, preventing them from being used with models with dust. [#100, #101]
- Fixed problem where built-in source name and version strings were being dropped. [#82]
- Minor doc fixes.
v1.0.0 (2015-02-23)¶
- [API change] The API of
mcmc_lc
has changed significantly - (the function was marked experimental in previous release).
- [API change] The API of
- [Deprecation] In result of
fit_lc
,res.cov_names
changed tores.vparam_names
. - [Deprecation] In result of
nest_lc
,res.param_names
changed tores.vparam_names
. This is for compatibility between the results offit_lc
andnest_lc
. [#30] - [Deprecation] Deprecate
flatten
keyword argument infit_lc()
in favor of explicit use offlatten_result()
function. - Many new built-in models.
- Many new built-in bandpasses.
- New remote data fetching system.
- SALT2 model covariance available via
Model.bandfluxcov()
method andmodelcov=True
keyword argument passed tofit_lc
. - New simulation function,
zdist
, generates a distribution of redshifts given a volumetric rate function and cosmology. - New simulation function,
realize_lcs
, simulates light curve data given a model, parameters, and observations. - Add color-related keyword arguments to
plot_lc()
. - Add
tighten_ylim
keyword argument toplot_lc()
. - Add
chisq()
function and use internally infit_lc()
. - Add
SFD98Map
class for dealing with SFD (1998) dust maps persistently so that the underlying FITS files are opened only once. - Update
get_ebv_from_map()
to work with new SkyCoord class inastropy.coordinates
available in astropy v0.3 onward. Previously, this function did not work with astropy v0.4.x (where older coordinates classes had been removed). - Update to new configuration system available in astropy v0.4 onward. This makes this release incompatible with astropy versions less than 0.4.
- Now compatible with Python 3.
- Increased test coverage.
- Numerous minor bugfixes.
v0.4.0 (2014-03-26)¶
This is non-backwards-compatible release, due to changes in the way models are defined. These changes were made after feedback on the initial design.
The most major change is a new central class Model
used throughout
the pacakge. A Model
instance encompasses a Source
and zero or
more PropagationEffect
instances. This is so that different
source models (e.g., SALT2 or spectral time series models) can be
combined with arbitrary dust models. The best way to think about this
is Source
and PropagationEffect
define the rest-frame behavior
of a SN and dust, and a Model
puts these together to determine the
observer-frame behavior.
- New classes:
sncosmo.Model
: new main container classsncosmo.Source
: replaces existingModel
sncosmo.TimeSeriesSource
: replaces existingTimeSeriesModel
sncosmo.StretchSource
: replaces existingStretchModel
sncosmo.SALT2Source
: replaces existingSALT2Model
sncosmo.PropagationEffect
sncosmo.CCM89Dust
sncosmo.OD94Dust
sncosmo.F99Dust
- New public functions:
sncosmo.read_griddata_ascii
: Read file withphase wave flux
rowssncosmo.read_griddata_fits
sncosmo.write_griddata_fits
sncosmo.nest_lc
: Nested sampling parameter estimation of SN modelsncosmo.simulate_vol
(EXPERIMENTAL): simulation convenience function.
- Built-ins:
- updated SALT2 model URLs
- added SALT2 version 2.4 (Betoule et al 2014)
- Improvements to
sncosmo.plot_lc
: flexibility and layout - Many bugfixes
v0.3.0 (2013-11-07)¶
This is a release with mostly bugfixes but a few new features, designed to be backwards compatible with v0.2.0 ahead of API changes coming in the next version.
New Functions:
sncosmo.get_ebv_from_map
: E(B-V) at given coordinates from SFD map.sncosmo.read_snana_ascii
: Read SNANA ascii format files.sncosmo.read_snana_fits
: Read SNANA FITS format files.sncosmo.read_snana_simlib
: Read SNANA ascii “SIMLIB” files.
registry is now case-independent. All of the following now work:
sncosmo.get_magsystem('AB') sncosmo.get_magsystem('Ab') sncsomo.get_magsystem('ab')
Photometric data can be unordered in time. Internally, the data are sorted before being used in fitting and typing.
Numerous bugfixes.
v0.2.0 (2013-08-20)¶
Added SN 2011fe Nearby Supernova Factory data to built-in models as
'2011fe'
Previously “experimental” functions now included:
sncosmo.fit_lc
(previouslysncosmo.fit_model
)sncosmo.read_lc
(previouslysncosmo.readlc
)sncosmo.write_lc
(previouslysncosmo.writelc
)sncosmo.plot_lc
(previouslysncosmo.plotlc
)
New functions:
sncosmo.load_example_data
: Example photometric data.sncosmo.mcmc_lc
: Markov Chain Monte Carlo parameter estimation.sncosmo.animate_model
: Model animation using matplotlib.animation.
Fitting:
sncosmo.fit_lc
now uses the iminuit package for minimization by default. This requires the iminuit package to be installed, but the old minimizer (from scipy) can still be used by setting the keywordmethod='l-bfgs-b'
.Plotting: Ability to plot model synthetic photometry without observed data, using the syntax:
>>> sncosmo.plot_lc(model=model, bands=['band1', 'band2'])
Photometric data format: Photometric data format is now more flexible, allowing various names for table columns.
v0.1.0 (2013-07-15)¶
Initial release.
About SNCosmo¶
Package Features¶
- SN models: Synthesize supernova spectra and photometry from SN models.
- Fitting and sampling: Functions for fitting and sampling SN model parameters given photometric light curve data.
- Dust laws: Fast implementations of several commonly used extinction laws; can be used to construct SN models that include dust.
- I/O: Convenience functions for reading and writing peculiar data formats used in other packages and getting dust values from SFD (1998) maps.
- Built-in supernova models such as SALT2, MLCS2k2, Hsiao, Nugent, PSNID, SNANA and Whalen models, as well as a variety of built-in bandpasses and magnitude systems.
- Extensible: New models, bandpasses, and magnitude systems can be defined, using an object-oriented interface.
Relation to other SN cosmology software¶
There are several other publicly available software packages for supernova cosmology. These include (but are not limited to) snfit (SALT fitter), SNANA and SNooPy (or snpy).
- snfit and SNANA both provide functionality overlapping with this package to some extent. The key difference is that these packages provide several (or many) executable applications, but do not provide an API for writing new programs building on the functionality they provide. This package, in contrast, provides no executables; instead it is a library of functions and classes designed to provide the building blocks commonly used in many aspects of SN analyses.
- SNooPy (or snpy) is also a Python library for SN analysis, but with a (mostly) different feature set. SNCosmo is based on spectral timeseries models whereas SNooPy is more focussed on models of light curves in given bands.
The name SNCosmo¶
A natural choice, “snpy”, was already taken (SNooPy) so I tried to be a little more descriptive. The package is really specific to supernova cosmology, as it doesn’t cover other types of supernova science (radiative transfer simulations for instance). Hence “sncosmo”.
Contributors¶
Alphabetical by last name:
- Stephen Bailey
- Kyle Barbary
- Tom Barclay
- Rahul Biswas
- Matt Craig
- Ulrich Feindt
- Brian Friesen
- Danny Goldstein
- Saurabh Jha
- Steve Rodney
- Caroline Sofiatti
- Rollin C. Thomas
- Michael Wood-Vasey
Contributing¶
Overview¶
SNCosmo follows the same general development workflow as astropy and many other open-source software projects. The astropy development workflow page documents the process in some detail. While you should indeed read that page, it can seem a bit overwhelming at first. So, we present here a rough outline of the process, and try to explain the reasoning behind it.
The process is centered around git and GitHub, so you need to know how to use basic git commands and also have a GitHub account. There is a “blessed” copy of the repository at https://github.com/sncosmo/sncosmo. Individual contributors make changes to their own copy (or “fork” or “clone” in git parlance) of the repository, e.g., https://github.com/kbarbary/sncosmo, then ask that their changes be merged into the “blessed” copy via a Pull Request (PR) on GitHub. A maintainer (currently Kyle) will review the changes in the PR, possibly ask for alterations, and then eventually merge the change.
This seems overly complex at first glance, but there are two main benefits to this process: (1) Anyone is free to try out any crazy change they want and share it with the world on their own GitHub account, without affecting the “blessed” repository, and (2) Any proposed changes are reviewed and discussed by at least one person (the maintainer) before being merged in.
Detailed steps¶
Do once:¶
Hit the “fork” button in the upper right hand corner of the https://github.com/sncosmo/sncosmo page. This creates a clone of the repository on your personal github account.
Get it onto your computer (replace username with your GitHub username):
git clone git@github.com:username/sncosmo.git
Add the “blessed” version as a remote:
git remote add upstream git@github.com:sncosmo/sncosmo.git
This will allow you to update your version to reflect new changes to the blessed repository that others have made).
Check that everything is OK:
$ git remote -v origin git@github.com:username/sncosmo.git (fetch) origin git@github.com:username/sncosmo.git (push) upstream git@github.com:sncosmo/sncosmo.git (fetch) upstream git@github.com:sncosmo/sncosmo.git (push)
You can call the remotes anything you want. “origin” and “upstream” have no intrinsic meaning for git; they’re just nicknames. The astropy documentation calls them “your-github-username” and “astropy” respectively.
Every time you want to make a contribution:¶
Ensure that the clone of the repository on your local machine is up-to-date with the latest upstream changes by doing
git fetch upstream
. This updates your local “remote tracking branch”, calledupstream/master
.Create a “topic branch” for the change you want to make. If you plan to make enhancements to the simulation code, name the branch something like “simulation-enhancements”:
git branch simulation-enhancements upstream/master
(
upstream/master
is where the branch branches off from.)Move to the branch you just created:
git checkout simulation-enhancements
Make changes, ensure that they work, etc. Make commits as you go.
Once you’re happy with the state of your branch, push it to your GitHub account for the world to see:
git push origin simulation-enhancements
Create a PR: Go to your copy on github (https://github.com/username/sncosmo) select the branch you just pushed in the upper left-ish of the page, and hit the green button next to it. (It has a mouse-over “compare, review, create a pull request”)
What happens when the upstream branch is updated?¶
Suppose that you are following the above workflow: you created a topic
branch simulation-enhancements
and made a few commits on that
branch. You now want to create a pull request, but there’s a problem:
while you were working, more commmits were added to the
upstream/master
branch on GitHub. The history of your branch has
now diverged from the main development branch! What to do?
Fetch the changes made to the upstream branch on so that you can deal with the changes locally:
git fetch upstream
This will update your local branch
upstream/master
(and any otherupstream
branches) to the match the state of the upstream branch on GitHub. It doesn’t do any merging or resolving, it just makes the new changes toupstream/master
visible locally.There are two options for this next step:
merge
orrebase
with the latter being preferred for this purpose. Assuming you are on your branchsimulation-enhancements
, you could dogit merge upstream/master
. This would create a merge commit that merges the diverged histories back together. This works, but it can end up creating a confusing commit history, particularly if you repeat this process several times while working on your new branch. Instead, you can do:git rebase upstream/master
This actually rewrites your commits to make it look like they started from where
upstream/master
now is, rather than where it was when you started work on yoursimulation-enhancements
branch. Your branch will have the exact same contents as if you had usedgit merge
, but the history will be different than it would have been if you had merged. In particular, there is no merge commit created, because the history has been rewritten so that your branch starts whereupstream/master
ends, and there is no divergent history to resolve. This means you can rebase again and again without creating a convoluted history full of merges back and forth between the branches.
Trying out new ideas¶
git branches are the best way to try out new ideas for code
modifications or additions. You don’t even have to tell anyone about
your bad ideas, since branches are local! They only become world
visible when you push them to GitHub. If, after making several
commits, you decide that your new branch simulation-enhancements
sucks, you can just create a new branch starting from upstream/master
again. If it is a really terrible idea you never want to see again,
you can delete it by doing git branch -D simulation-enhancements
.
Obviously this isn’t a complete guide to git, but hopefully it jump-starts the git learning process.
Developer’s documentation: release procedure¶
These are notes mainly for the one person that manages releases. Yes, this could be more automated, but it isn’t done very often, and involves some human verification.
- Update
docs/history.rst
with a summary of the new version’s changes. - Bump version in
setup.py
. - Check copyright year in
docs/conf.py
. - Build package and docs and check that docs look good.
- Commit.
git clean -dfx
setup.py sdist
- Check that the tarball in
dist/
can be unpacked and thatsetup.py test
succeeds. Bonus: create a fresh conda environment (or virtual environment) with minimal requirements and install and test in that. setup.py register
setup.py sdist upload
Post-release steps:
- If not a bugfix release, create a feature branch. For example,
git branch v1.1.x
. - Tag the release. For example,
git tag v1.1.0
. - On master, bump version in
setup.py
to the next development version and add the next development version todocs/whatsnew.rst
. - Commit.
- Push repo changes to GitHub. For example:
git push upstream master v1.1.x v1.1.0
.
Docs and conda
- On readthedocs.org, set the new feature branch to “active”.
- To trigger new conda build, edit version number in requirements.txt in https://github.com/astropy/conda-builder-affiliated and submit a pull request.
- Once conda build succeeds, make the new feature branch the default on readthedocs.org.
- Check out the source code: https://github.com/sncosmo/sncosmo
- Report bugs, request features: https://github.com/sncosmo/sncosmo/issues
- User & developer mailing list: https://groups.google.com/forum/#!forum/sncosmo