<<

speclite Documentation Release 0.14dev391

Speclite Developers

Jan 18, 2021

Contents

I Overview 3

II Installation7

III Filter Response Curves 11

IV Reference/API 37

i ii speclite Documentation, Release 0.14dev391

This package provides a set of lightweight utilities for working with spectroscopic data in astronomy.

Contents 1 speclite Documentation, Release 0.14dev391

2 Contents Part I

Overview

3

speclite Documentation, Release 0.14dev391

Speclite is a lightweight package for performing basic operations on spectral data contained in numpy arrays. The basic philosophy of this package is to: • Use spectral data in numpy arrays “as-is” rather than requiring users to reformat their data or wrap it in objects. • Minimize the number of assumptions about what quantities are used to define a spectrum. For example, we do not assume that spectra are sampled in wavelength rather than frequency. • Support operations on masked arrays and correctly propagate the effects of invalid samples. • Use per-sample weights (inverse variances) when these are available. • Do not introduce any dependencies beyond numpy, , and astropy. • Be compatible with python versions 2.6, 2.7, 3.3, 3.4 and numpy versions >= 1.8. • Be fully documented and unit tested, with 100% test coverage. • Use the astropy affiliated package template to benefit from its sophisticated configuration and integration with other services (TravisCI, coveralls.io, readthedocs.io) and for possible future distribution with astropy. Speclite provides functions to perform the following basic manipulations of spectroscopic data: • redshift(): transforms from one redshift to another. • resample(): resamples from one sampling grid to another using interpolation. • downsample(): downsamples by combining bins in consecutive groups. • accumulate(): combines two spectra on the same grid, and can efficiently stack many spectra. • filters module: convolutions and magnitude calculations for some reference filters. Operations that are planned for future versions include: • Signal-to-noise estimation. The results of the redshift, resample, downsample and accumulate operations are always numpy structured arrays and these operations also accept structured arrays these as inputs. Some operations also accept un-structured arrays as inputs, but structured arrays should generally be preferred since they have negligible overhead and significantly reduce the burden on users to keep track of which columns correspond to which quantities. In cases where the source data is not already in a structured array, the necessary metadata can be added without copying the underlying array data, for example:

>>> import numpy as np >>> data= np.arange(9, dtype=float).reshape(3,3) >>> sdata= data.view([( 'wlen', float), ('flux', float), ... ('ivar', float)]).reshape(3) >>> np.all(sdata == ... np.array([(0.0, 1.0, 2.0), (3.0, 4.0, 5.0), (6.0, 7.0, 8.0)], ... dtype=[('wlen', '>> sdata.base is data.base True

You should normally use dictionary notation to refer to individual fields of a structured array:

>>> sdata['wlen'][1] 3.0

You can also use the more convenient dot notation using this recarray recipe. However, this is generally slower so speclite results are not automatically converted to numpy recarrays. Examples of using speclite with BOSS data are included with the bossdata package.

5 speclite Documentation, Release 0.14dev391

6 Part II

Installation

7

speclite Documentation, Release 0.14dev391

Install the latest stable release using: pip install speclite

Alternatively, you can install the latest developer version from github: github clone https://github.com/dkirkby/speclite.git cd speclite python setup.py install

9 speclite Documentation, Release 0.14dev391

10 Part III

Filter Response Curves

11

speclite Documentation, Release 0.14dev391

The data/filters/ subdirectory contains small files with tabulated filter response curves. All files contain a single curve stored in the ASCII enhanced character-separated value format, which is used to specify the wavelength units and provide the following metadata:

Key Description group_name Name of the group that this filter response belongs to, e.g., sdss2010. band_name Name of the filter pass band, e.g., r. airmass Airmass used for atmospheric transmission, or zero for no atmosphere. url URL with more details on how this filter response was obtained. description Brief description of this filter response.

The following sections summarize the standard filters included with the speclite code distribution. Refer to the filters module API docs for details and examples of how to load an use these filters. See below for instructions on working with your own custom filters.

13 speclite Documentation, Release 0.14dev391

14 CHAPTER 1

SDSS Filters

SDSS filter responses are taken from Table 4 of Doi et al, “Photometric Response Functions of the SDSS Imager”, The Astronomical Journal, Volume 139, Issue 4, pp. 1628-1648 (2010), and calculated as the reference response multiplied by the reference APO atmospheric transmission at an airmass 1.3. See the paper for details. The group name sdss2010 is used to identify these response curves in speclite. The plot below shows the output of: sdss= speclite.filters.load_filters( 'sdss2010-*') speclite.filters.plot_filters(sdss, wavelength_limits=(3000, 11000))

15 speclite Documentation, Release 0.14dev391

16 Chapter 1. SDSS Filters CHAPTER 2

DECam DR1 Filters

The DECam DR1 filter curves are documented in T. M. . Abbott et al 2018 ApJS 239 18 and available from this NOAO DECam page. These represent the total system throughput and average instrumental response across the science CCDs. The official curves have arbitrary normalization, but the values used here have reasonable normalization factors applied for throughput calculations, provided Douglas Tucker (Jan 2021, private communication). There are two versions of the DR1 curves: decamDR1 with an airmass 1.2 reference atmosphere, and decamDR1noatm with no atmospheric extinction:

with_atm= speclite.filters.load_filters( 'decamDR1-*') speclite.filters.plot_filters(with_atm) without_atm= speclite.filters.load_filters( 'decamDR1noatm-*') speclite.filters.plot_filters(without_atm)

17 speclite Documentation, Release 0.14dev391

18 Chapter 2. DECam DR1 Filters CHAPTER 3

DECam 2014 Filters

The DECam 2014 filter responses are taken from this Excel spreadsheet created by William Wester in September 2014 and linked to this NOAO DECam page. Throughputs include a reference atmosphere with airmass 1.3 provided by Ting Li. These are the most recent publicly available DECam throughputs as of Feb 2016. The group name decam2014 is used to identify these response curves in speclite. The plot below shows the output of:

decam= speclite.filters.load_filters( 'decam2014-*') speclite.filters.plot_filters( decam, wavelength_limits=(3000, 11000), legend_loc='upper left')

19 speclite Documentation, Release 0.14dev391

20 Chapter 3. DECam 2014 Filters CHAPTER 4

WISE Filters

WISE filter responses are taken from files linked to this page containing the weighted mean relative spectral responses described in Wright et al, “The Wide-field Infrared Survey Explorer (WISE): Mission Description and Initial On-orbit Performance”, The Astronomical Journal, Volume 140, Issue 6, pp. 1868-1881 (2010). Note that these responses are based on pre-flight measurements but the in-flight responses of the W3 and W4 filters are observed to have effective wavelengths that differ by -(3-5)% and +(2-3)%, respectively. Refer to Section 2.2 of Wright 2010 for details. See also Section 2.1.3 of Brown 2014 for further details about W4. The group name wise2010 is used to identify these response curves in speclite. The plot below shows the output of the command below, and matches Figure 6 of the paper:

wise= speclite.filters.load_filters( 'wise2010-*') speclite.filters.plot_filters(wise, wavelength_limits=(2, 30), wavelength_unit=astropy.units.micron, wavelength_scale='log') plt.gca().set_xticks([2,5, 10, 20, 30]) plt.gca().set_xticklabels([2,5, 10, 20, 30])

21 speclite Documentation, Release 0.14dev391

22 Chapter 4. WISE Filters CHAPTER 5

HSC Filters

HSC filter responses are taken from here. These throughputs include a reference atmosphere with airmass 1.2. Refer to Kawanamoto et al. 2017 (in prep). The group name hsc2017 is used to identify these curves in speclite. The plot below shows the output of the following command: hsc= speclite.filters.load_filters( 'hsc2017-*') speclite.filters.plot_filters(hsc)

23 speclite Documentation, Release 0.14dev391

24 Chapter 5. HSC Filters CHAPTER 6

LSST Filters

LSST filter responses are taken from tag 12.0 of the LSST simulations throughputs package and include a standard atmosphere with airmass 1.2 that is also tabulated in the same package. The group name lsst2016 is used to identify these response curves in speclite. The plot below shows the output of the command below, and matches Figure 6 of the paper:

lsst= speclite.filters.load_filters( 'lsst2016-*') speclite.filters.plot_filters( lsst, wavelength_limits=(3000, 11000), legend_loc='upper left')

25 speclite Documentation, Release 0.14dev391

26 Chapter 6. LSST Filters CHAPTER 7

Johnson/Cousins Filters

Reference definitions of the Johnson/Cousins “standard” filters are taken from Table 2 of Bessell, M. S., “UBVRI passbands,” PASP, vol. 102, Oct. 1990, p. 1181-1199. We use the band name “U” for the response that Table 2 refers to as “UX”. Note that these do not represent the response of any actual instrument. Response values are normalized to have a maximum of one in each band. The group name bessell is used to identify these response curves in speclite. The plot below shows the output of the command below:

bessell= speclite.filters.load_filters( 'bessell-*') speclite.filters.plot_filters(bessell, wavelength_limits=(2900, 9300))

27 speclite Documentation, Release 0.14dev391

28 Chapter 7. Johnson/Cousins Filters CHAPTER 8

DESI Imaging Survey Filters

The DESI spectroscopic survey used imaging from the DECam, BASS and MzLS instruments to build its target catalog. The relevant BASS and MzLS filters are:

desi_imaging= speclite.filters.load_filters( 'BASS-g', 'BASS-r', 'MzLS-z') speclite.filters.plot_filters(desi_imaging)

29 speclite Documentation, Release 0.14dev391

30 Chapter 8. DESI Imaging Survey Filters CHAPTER 9

Euclid Filters

The current best end-of-life estimates for the “VIS”, “Y”, “H”, and “J” total throughputs for Euclid, i.e., “Y”, “H”, and “J” have been convolved by the “NISP” throughput. The original tables can be found here. The group name Euclid is used to identify these curves in speclite. The command below produces the figure: euclid= speclite.filters.load_filters( 'Euclid-VIS', 'Euclid-Y', 'Euclid-H', 'Euclid-J') speclite.filters.plot_filters(euclid)

31 speclite Documentation, Release 0.14dev391

32 Chapter 9. Euclid Filters CHAPTER 10

Gaia Filters

The (revised) filters from DR2 documented here. The command below produces the figure: gaiadr2= speclite.filters.load_filters( 'gaiadr2-*') speclite.filters.plot_filters(gaiadr2)

33 speclite Documentation, Release 0.14dev391

34 Chapter 10. Gaia Filters CHAPTER 11

Custom Filters

In addition to the standard filters included with the speclite code distribution, you can create and read your own custom filters. For example to define a new filter group called “fangs” with “g” and “r” bands, you will first need to define your filter responses with new speclite.filters.FilterResponse objects: fangs_g= speclite.filters.FilterResponse( wavelength=[3800, 4500, 5200]*u.Angstrom, response=[0, 0.5,0], meta=dict(group_name= 'fangs', band_name='g')) fangs_r= speclite.filters.FilterResponse( wavelength=[4800, 5500, 6200]*u.Angstrom, response=[0, 0.5,0], meta=dict(group_name= 'fangs', band_name='r'))

Your metadata dictionary must include the group_name and band_name keys, but all of the keys listed above are recommended. You can now load and use these filters with their canonical names, although the group wildcard fangs-* is not supported. For example: fangs= speclite.filters.load_filters( 'fangs-g', 'fangs-r') speclite.filters.plot_filters(fangs)

35 speclite Documentation, Release 0.14dev391

Next, save these filters in the correct format to any directory:

directory_name= '.' fg_name= fangs_g.save(directory_name) fr_name= fangs_r.save(directory_name)

Note that the file name in the specified directory is determined automatically based on the filter’s group and band names. Finally, you can now read these custom filters from other programs by calling speclite.filters.load_filter() with paths:

directory_name= '.' fg_name= os.path.join(directory_name, 'fangs-g.ecsv') fr_name= os.path.join(directory_name, 'fangs-r.ecsv') fangs_g= speclite.filters.load_filter(fg_name) fangs_r= speclite.filters.load_filter(fr_name)

Note that load_filter and load_filters look for the “.ecsv” extension in the name to recognize a custom filter.

36 Chapter 11. Custom Filters Part IV

Reference/API

37

CHAPTER 12

Operations on Spectroscopic Data

12.1 speclite.accumulate Module

Stack spectra on the same wavelength grid using weighted accumulation.

12.1.1 Functions

accumulate(data1_in, data2_in[, data_out, . . . ]) Combine the data from two spectra. accumulate speclite.accumulate.accumulate(data1_in, data2_in, data_out=None, join=None, add=None, weight=None) Combine the data from two spectra. Values x1 and x2 with corresponding weights w1 and w2 are combined as:

x12= (w1*x1+ w2*x2)/(w1+ w2)

If no weight field is present for either input, a weight of one is used. If either input array is masked, weights for masked entries will be set to zero. The output contains values for x12 and the accumulated weight: w12 = w1 + w2 For example:

>>> data1= np.ones((10,), dtype=[( 'flux', float), ('ivar', float)]) >>> data2= np.ones((10,), dtype=[( 'flux', float), ('ivar', float)]) >>> result= accumulate(data1, data2, add= 'flux', weight='ivar') >>> np.all(result[:3] == ... np.array([(1.0, 2.0), (1.0, 2.0), (1.0, 2.0)], ... dtype=[('flux', '

39 speclite Documentation, Release 0.14dev391

Any fields common to both inputs can also be copied to the output:

>>> data1= np.ones((10,), dtype=[( 'wlen', float), ('flux', float)]) >>> data2= np.ones((10,), dtype=[( 'wlen', float), ('flux', float)]) >>> result= accumulate(data1, data2, join= 'wlen', add='flux') >>> np.all(result[:3] == ... np.array([(1.0, 1.0), (1.0, 1.0), (1.0, 1.0)], ... dtype=[('wlen', '

The actual calculation of x12 uses the expression:

x12= x1+ (x2- x1)*w2/(w1+ w2)

which has better numerical properties when many spectra are iteratively accumulated using the following pat- tern:

>>> result= None >>> data= np.ones((10,100), ... dtype=[('wlen', float), ('flux', float), ('ivar', float)]) >>> for row in data: ... result= accumulate(data1_in=result, data2_in=row, data_out=result, ... join='wlen', add='flux', weight='ivar') >>> np.all(result[:3] == ... np.array([(1.0, 1.0, 10.0), (1.0, 1.0, 10.0), (1.0, 1.0, 10.0)], ... dtype=[('wlen', '

With this pattern, the result array is allocated on the first iteration and then re-used for all subsequent iterations. Parameters

data1_in [numpy.ndarray or numpy.ma.MaskedArray or None] First structured numpy array of input spectral data. data2_in [numpy.ndarray or numpy.ma.MaskedArray] Second structured numpy array of input spec- tral data. data_out [numpy.ndarray or None] Structured numpy array where output spectrum data should be written. If None is specified, then an appropriately sized array will be allocated and returned. Use this method to take control of the memory allocation and, for example, re-use the same output array for iterative accumulation. join: string or iterable of strings or None. A field name or a list of field names that are present in both inputs with identical values, and should be included in the output. add [string or iterable or None.] A field name or a list of field names that are present in both inputs and whose values, x1 and x2, should be accumulated as x12 in the output. weight [string or None.] The name of a field whose values provide the weights w1 and w2 used to calculate the accumulated x12 = w1*x1 + w2*x2. If the named field is not present in either input a weight value of one will be used. The output array will contain a field with this name, if it is not None, containing values for w12.

40 Chapter 12. Operations on Spectroscopic Data speclite Documentation, Release 0.14dev391

Returns

numpy.ndarray Structured numpy array of accumulated result, containing all fields listed in the join, add, and weight arguments. Any values associated with a zero weight sample should be consid- ered invalid.

12.2 speclite.downsample Module

Downsample spectra by combining adjacent pixels.

12.2.1 Functions

downsample(data_in, downsampling[, weight, . . . ]) Downsample spectral data by a constant factor.

downsample

speclite.downsample.downsample(data_in, downsampling, weight=None, axis=-1, start_index=0, auto_trim=True, data_out=None) Downsample spectral data by a constant factor. Downsampling consists of dividing the input data into fixed-size groups of consecutive bins, then calculated downsampled values as weighted averages within each group. The basic usage is:

>>> data= np.ones((6,), dtype=[( 'flux', float), ('ivar', float)]) >>> out= downsample(data, downsampling=2, weight= 'ivar') >>> np.all(out == ... np.array([(1.0, 2.0), (1.0, 2.0), (1.0, 2.0)], ... dtype=[('flux', '

Any partial group at the end of the input data will be silently ignored unless auto_trim=False:

>>> out= downsample(data, downsampling=4, weight= 'ivar') >>> np.all(out == ... np.array([(1.0, 4.0)], dtype=[('flux', '>> out= downsample(data, downsampling=4, weight= 'ivar', auto_trim=False) Traceback (most recent call last): ... ValueError: Input data does not evenly divide with downsampling = 4.

A multi-dimensional array of spectra with the same binning can be downsampled in a single operation, for example:

>>> data= np.ones((2,16,3,), dtype=[( 'flux', float), ('ivar', float)]) >>> results= downsample(data,4, axis=1) >>> results.shape (2, 4, 3)

If no axis is specified, the last axis of the input array is assumed.

12.2. speclite.downsample Module 41 speclite Documentation, Release 0.14dev391

If the input data is masked, only unmasked entries will be used to calculate the weighted averages for each downsampled group and the output will also be masked:

>>> data= ma.ones((6,), dtype=[( 'flux', float), ('ivar', float)]) >>> data.mask[3:]= True >>> out= downsample(data,2, weight= 'ivar') >>> type(out) == ma.core.MaskedArray True

If the input fields have different masks, their logical OR will be used for all output fields since, otherwise, each output field would require its own output weight field. As a consequence, masking a single input field is equivalent to masking all input fields. Parameters

data_in [numpy.ndarray or numpy.ma.MaskedArray] Structured numpy array containing input spec- trum data to downsample. downsampling [int] Number of consecutive bins to combine into each downsampled bin. Must be at least one and not larger than the input data size. weight [string or None.] The name of a field whose values provide the weights to use for down- sampling. When None, a weight value of one will be used. The output array will contain a field with this name, unless it is None, containing values of the downsampled weights. All weights must be non-negative. start_index [int] Index of the first bin to use for downsampling. Any bins preceeding the start bin will not be included in the downsampled results. Negative indices are not allowed. axis [int] Index of the axis to perform downsampling in. The default is to use the last index of the input data array. auto_trim [bool] When True, any bins at the end of the input data that do not fill a complete down- sampled bin will be automatically (and silently) trimmed. When False, a ValueError will be raised. data_out [numpy.ndarray or None] Structured numpy array where output spectrum data should be written. If none is specified, then an appropriately sized array will be allocated and returned. Use this method to take control of the memory allocation and, for example, re-use the same output array for a sequence of downsampling operations. Returns

numpy.ndarray or numpy.ma.MaskedArray Structured numpy array of downsampled result, containing the same fields as the input data and the same shape except along the specified downsampling axis. If the input data is masked, the output data will also be masked, with each output field’s mask determined by the combination of the optional weight field mask and the corresponding input field mask.

42 Chapter 12. Operations on Spectroscopic Data speclite Documentation, Release 0.14dev391

12.3 speclite.resample Module

Resample spectra using interpolation.

12.3.1 Functions

resample(data_in, x_in, x_out, y[, . . . ]) Resample the data of one spectrum using interpolation. resample speclite.resample.resample(data_in, x_in, x_out, y, data_out=None, kind=’linear’) Resample the data of one spectrum using interpolation. Dependent variables y1, y2, . . . in the input data are resampled in the independent variable x using interpolation models y1(x), y2(x), . . . evaluated on a new grid of x values. The independent variable will typically be a wavelength or frequency and the independent variables can be fluxes, inverse variances, etc. Interpolation is intended for cases where the input and output grids have comparable densities. When neigh- boring samples are correlated, the resampling process should be essentially lossless. When the output grid is sparser than the input grid, it may be more appropriate to “downsample”, i.e., average dependent variables over consecutive ranges of input samples. The basic usage of this function is:

>>> data= np.ones((5,), ... [('wlen', float), ('flux', float), ('ivar', float)]) >>> data['wlen']= np.arange(4000, 5000, 200) >>> wlen_out= np.arange(4100, 4700, 200) >>> out= resample(data, 'wlen', wlen_out, ('flux', 'ivar')) >>> np.all(out == ... np.array([(4100, 1.0, 1.0), (4300, 1.0, 1.0), (4500, 1.0, 1.0)], ... dtype=[('wlen', '

The input grid can also be external to the structured array of spectral data, for example:

>>> data= np.ones((5,), [( 'flux', float), ('ivar', float)]) >>> wlen_in= np.arange(4000, 5000, 200) >>> wlen_out= np.arange(4100, 4900, 200) >>> out= resample(data, wlen_in, wlen_out, ( 'flux', 'ivar')) >>> np.all(out == ... np.array([(1.0, 1.0), (1.0, 1.0), (1.0, 1.0), (1.0, 1.0)], ... dtype=[('flux', '

If the output grid extends beyond the input grid, a masked array will be returned with any values requiring extrapolation masked:

>>> wlen_out= np.arange(3500, 5500, 500) >>> out= resample(data, wlen_in, wlen_out, 'flux') >>> np.all(out.mask == ... np.array([(True,), (False,), (False,), (True,)], ... dtype=[('flux', 'bool')])) True

12.3. speclite.resample Module 43 speclite Documentation, Release 0.14dev391

If the input data is masked, any output interpolated values that depend on an input masked value will be masked in the output:

>>> data= ma.ones((5,), [( 'flux', float), ('ivar', float)]) >>> data['flux'][2]= ma.masked >>> wlen_out= np.arange(4100, 4900, 200) >>> out= resample(data, wlen_in, wlen_out, 'flux') >>> np.all(out.mask == ... np.array([(False,), (True,), (True,), (False,)], ... dtype=[('flux', 'bool')])) True

Interpolation is performed using scipy.interpolate.inter1pd. Parameters

data_in [numpy.ndarray or numpy.ma.MaskedArray] Structured numpy array of input spectral data to resample. The input array must be one-dimensional. x_in [string or numpy.ndarray] A field name in data_in containing the independent variable to use for interpolation, or else an array of values with the same shape as the input data. x_out [numpy.ndarray] An array of values for the independent variable where interpolation models should be evaluated to calculate the output values. y [string or iterable of strings.] A field name or a list of field names present in the input data that should be resampled by interpolation and included in the output. data_out [numpy.ndarray or None] Structured numpy array where the output result should be written. If None is specified, then an appropriately sized array will be allocated and returned. Use this method to take control of the memory allocation and, for example, re-use the same array when resampling many spectra. kind [string or integer] Specify the kind of interpolation models to build using any of the forms allowed by scipy.interpolate.inter1pd. If any input dependent values are masked, only the nearest` and ``linear values are allowed. Returns

numpy.ndarray or numpy.ma.MaskedArray Structured numpy array of the resampled result containing all y fields and (if x_in is spec- ified as a string) the output x field. The output will be a numpy.ma.MaskedArray if x_out extends beyond x_in or if data_in is masked.

12.4 speclite.redshift Module

Apply redshift transformations to wavelength, flux, inverse variance, etc.

44 Chapter 12. Operations on Spectroscopic Data speclite Documentation, Release 0.14dev391

12.4.1 Functions

redshift(z_in, z_out[, data_in, data_out, rules]) Transform spectral data from redshift z_in to z_out. redshift speclite.redshift.redshift(z_in, z_out, data_in=None, data_out=None, rules=[]) Transform spectral data from redshift z_in to z_out. Each quantity X is transformed according to a power law:

X_out= X_in*((1+ z_out)/(1+ z_in))**exponent

where exponents are specified with the rules argument. Exponents for some common cases are listed in the table below.

Exponent Quantities 0 flux density in photons/(s*cm^2*Ang) +1 wavelength, wavelength error, flux density in ergs/(s*cm^2*Hz) -1 frequency, frequency error, flux density in ergs/(s*cm^2*Ang) +2 inverse variance of flux density in ergs/(s*cm^2*Ang) -2 inverse variance of flux density in ergs/(s*cm^2*Hz)

For example, to transform separate wavelength and flux arrays using the SDSS standard units of Ang and 1e-17 erg/(s*cm^2*Ang):

>>> wlen= np.arange(4000., 10000.) >>> flux= np.ones(wlen.shape) >>> result= redshift(z_in=0, z_out=1, rules=[ ... dict(name='wlen', exponent=+1, array_in=wlen), ... dict(name='flux', exponent=-1, array_in=flux)]) >>> result.dtype dtype([('wlen', '>> result['flux'][0] 0.5

The same calculation could be performed with the input data stored in a numpy structured array, in which case any additional fields are copied to the output array:

>>> data= np.empty(6000, dtype=[ ... ('wlen', float), ('flux', float), ('maskbits', int)]) >>> data['wlen']= np.arange(4000., 10000.) >>> data['flux']= np.ones_like(data[ 'wlen']) >>> result= redshift(z_in=0, z_out=1, data_in=data, rules=[ ... dict(name='wlen', exponent=+1), ... dict(name='flux', exponent=-1)]) >>> result.dtype dtype([('wlen', '>> result['flux'][0] 0.5

The transformed result is always a numpy structured array, with field (column) names determined by the rules you provide.

12.4. speclite.redshift Module 45 speclite Documentation, Release 0.14dev391

The usual numpy broadcasting rules apply in the transformation expression above so, for example, the same redshift can be applied to multiple spectra, or different redshifts can be applied to the same spectrum with appropriate input shapes. Input arrays can have associated masks and these will be propagated to the output. Input arrays can also have units but these will not be used or propagated to the output since numpy structured arrays do not support per- column units. Parameters

z_in [float or numpy.ndarray] Redshift(s) of the input spectral data, which must all be > -1. z_out [float or numpy.ndarray] Redshift(s) of the output spectral data, which must all be > -1. data_in [numpy.ndarray] Structured numpy array containing input spectrum data to transform. If none is specified, then all quantities must be provided as numpy arrays in the rules. data_out [numpy.ndarray] Structured numpy array where output spectrum data should be written. If none is specified, then an appropriately sized array will be allocated and returned. Use this method to take control of the memory allocation and, for example, re-use the same output array for a sequence of transforms. rules [iterable] An iterable object whose elements are dictionaries. Each dictionary specifies how one quantity will be transformed and must contain ‘name’ and ‘exponent’ values. If an ‘array_in’ value is also specified, it should refer to a numpy array containing the input values to transform. Otherwise, data_in[] is assumed to contain the input values to transform. If no rules are specified and data_in is provided, then data_out is just a copy of data_in. Returns

numpy.ndarray Array of spectrum data with the redshift transform applied. Equal to data_out when set, otherwise a new array is allocated. If data_in is specified, then any fields not listed in rules are copied to data_out, so effectively have an implicit exponent of zero.

46 Chapter 12. Operations on Spectroscopic Data CHAPTER 13

Operations with Filters

13.1 speclite.filters Module

Support for calculations involving filter response curves.

13.1.1 Overview

See Filter Response Curves for information about the standard filters included with this code distribution and instruc- tions for adding your own filters. Filter names have two components, a group name and a band name, which are combined with a hyphen, e.g. “sdss2010-r”. The group names included with this package are:

>>> filter_group_names ['sdss2010', 'decam2014', 'wise2010', 'hsc2017', 'lsst2016', 'bessell', 'BASS', 'MzLS', 'Euclid', ˓→'decamDR1', 'decamDR1noatm', 'gaiadr2']

List the band names associated with any group using, for example:

>>> load_filters('sdss2010-*').names ['sdss2010-u', 'sdss2010-g', 'sdss2010-r', 'sdss2010-i', 'sdss2010-z']

Here is a brief example of calculating SDSS r,i and Bessell V magnitudes for a numpy array of fluxes for 100 spectra covering 4000-10,000 A with 1A pixels:

>>> import astropy.units asu >>> wlen= np.arange(4000, 10000)*u.Angstrom >>> flux= np.ones((100, len(wlen)))*u.erg/ (u.cm**2*u.s*u.Angstrom)

Units are recommended but not required (otherwise, the units shown here are assumed as defaults). Next, load the filter responses:

>>> import speclite.filters >>> filters= speclite.filters.load_filters( ... 'sdss2010-r', 'sdss2010-i', 'bessell-V')

47 speclite Documentation, Release 0.14dev391

Finally, calculate the magnitudes to obtain an astropy Table of results with one row per input spectrum and one column per filter:

>>> mags= filters.get_ab_magnitudes(flux, wlen)

If you prefer to work with a numpy structured array, you can convert the returned table:

>>> mags= filters.get_ab_magnitudes(flux, wlen).as_array()

13.1.2 Padding

Under certain circumstances, you may need to pad an input spectrum to cover the full wavelength range of the filters you are using. See FilterResponse.pad_spectrum() and FilterSequence.pad_spectrum() for details on how this is implemented.

13.1.3 Shifted Filters

It can be useful to work with a filter whose wavelengths have been shifted, e.g. for the applications in http://arxiv.org/ abs/astro-ph/0205243. This is supported with the FilterResponse.create_shifted() method, for example:

>>> wlen= np.arange(4000, 10000)*u.Angstrom >>> flux= np.ones(len(wlen))*u.erg/ (u.cm**2*u.s*u.Angstrom) >>> r0= speclite.filters.load_filter( 'sdss2010-r') >>> rz= r0.create_shifted(band_shift=0.2) >>> print((np.round(r0.get_ab_magnitude(flux, wlen),3))) -21.359 >>> print((np.round(rz.get_ab_magnitude(flux, wlen),3))) -20.963

Note that a shifted filter has a different wavelength coverage, so may require padding of your input spectra.

13.1.4 Convolutions

The filter response convolution operator implemented here is defined as:

∫︁ ∞ 푑푔 퐹 [푅, 푓휆] ≡ (휆)푅(휆)휔(휆)푑휆 0 푑휆 where 푅(휆) is a filter response function, represented by a FilterResponse object, and 푓휆 ≡ 푑푔/푑휆 is an arbitrary differential function of wavelength, which can either be represented as a callable python object or else with arrays of wavelengths and function values. The default weights: 휆 휔(휆) = ℎ푐 are appropriate for photon-counting detectors such as CCDs, and enabled by the default setting photon_weighted = True in the methods below. Otherwise, the convolution is unweighted, 휔(휆) = 1, but arbitrary alternative weights can always be included in the definition of 푓휆. For example, a differential function of frequency 푑푔/푑휈 can be reweighted using: 푑푔 푐 푑푔 푓 (휆) = (휆) = (휈 = 푐/휆) 휆 푑휆 휆2 푑휈

48 Chapter 13. Operations with Filters speclite Documentation, Release 0.14dev391

These definitions make no assumptions about the units of 푓휆, but magnitude calculations are an important special case 3 2 where the units of 푓휆 must have the dimensions 푀/(퐿푇 ), for example, erg/(cm s ).

The magnitude of 푓휆 in the filter band with response 푅 is then:

푚[푅, 푓휆] ≡ −2.5 log10(퐹 [푅, 푓휆]/퐹 [푅, 푓휆,0]) where 푓휆,0(휆) is the reference flux density that defines the photometric system’s zeropoint 퐹 [푅, 푓휆,0]. The zeropoint has dimensions 1/(퐿2푇 ) and gives the rate of incident photons per unit telescope area from a zero magnitude source.

A spectral flux density per unit frequency, 푓휈 = 푑푔/푑휈, should be converted using: 푐 푓 (휆) = 푓 (휈 = 푐/휆) 휆 휆2 휈 for use with the methods implemented here. For the AB system, 푐 푓 퐴퐵(휆) = (3631Jy) , 휆,0 휆2 and the convolutions use photon-counting weights.

13.1.5 Sampling

Filter responses are tabulated on non-uniform grids with sufficient sampling that linear interpolation is sufficient for most applications. When a filter response is convolved with tabulated data, we must also consider the sampling of the tabulated function. In this implementation, we assume that the tabulated function is also sufficiently sampled to allow linear interpolation. The next issue is how to sample the product of a filter response and tabulated function when performing a numerical convolution integral. With the assumptions above, a safe strategy would be to sample the integrand at the union of the two wavelength grids. However, this is relatively expensive since it requires interpolating both the response and the input function. Interpolation is sometimes unavoidable: for example, when the function is linear and represented by its values at only two wavelengths. The approach adopted here is to use the sampling grid of the input function to sample the convolution integrand whenever it samples the filter response sufficiently. This requires that the filter response be interpolated, but this operation only needs to be performed once when many convolutions are performed on the same input wavelength grid. Our criteria for sufficient filter sampling is that at most one filter wavelength point lies between any consecutive pair of input wavelength points. When this condition is not met, the input function will be interpolated at the minimum number of response wavelengths necessary to satisfy the condition. The figure below (generated by this function) illustrates three different sampling regimes that can occur in a convolution with the Bessell V filter (red curve). Filled blue squares show where the input function is sampled and open blue circles show where interpolation of the input function is performed. The left-hand plot shows an extremely undersampled input that is interpolated at every filter point. The middle plot shows a well sampled input that requires no interpolation. The right-hand plot shows an input that is slightly undersampled and requires interpolation at some of the filter points. All three methods give consistent results, with discrepancies of < 0.05%.

13.1. speclite.filters Module 49 speclite Documentation, Release 0.14dev391

The logic described here is encapsulated in the FilterConvolution class. Interpolation is performed automatically, as necessary, by the high-level magnitude calculating methods, but FilterConvolution is available when more control of this process is needed to improve performance.

13.1.6 Performance

If the performance of magnitude calculations is a bottleneck, you can speed up the code significantly by taking ad- vantage of the fact that all of the convolution functions can operate on multidimensional arrays. For example, calling FilterResponse.get_ab_magnitudes() once with an array of 5000 spectra is about 10x faster than calling it 5000 times with the individual spectra. However, in order to take advantage of this speedup, your spectra need to all use the same wavelength grid. Note that the eliminating flux units (which are always optional) from your input spectra will only result in about a 10% speedup, so units are generally recommended.

13.1.7 Attributes

filter_group_names [list] List of filter group names included with this package. default_wavelength_unit [astropy.units.Unit] The default wavelength units assumed when units are not specified. The same units are used to store wavelength values in internal arrays. default_flux_unit [astropy.units.Unit] The default units for spectral flux density per unit wavelength.

13.1.8 Functions

ab_reference_flux(wavelength[, magnitude]) Calculate an AB reference spectrum with the specified magnitude. filter_sampling_explanatory_plot([save]) Generate an explanatory plot for the documentation. load_filter(name[, load_from_cache, verbose]) Load a single filter response by name. load_filters(*names) Load a sequence of filters by name. plot_filters(responses[, wavelength_unit, . . . ]) Plot one or more filter response curves. tabulate_function_of_wavelength(function, . . . ) Evaluate a function of wavelength. validate_wavelength_array(wavelength[, . . . ]) Validate a wavelength array for filter operations.

50 Chapter 13. Operations with Filters speclite Documentation, Release 0.14dev391 ab_reference_flux speclite.filters.ab_reference_flux(wavelength, magnitude=0.0) Calculate an AB reference spectrum with the specified magnitude. For example, to calculate the flux of a 20th magnitude AB reference at 600 nm:

>>> flux= ab_reference_flux(600* astropy.units.nanometer, magnitude=20) >>> print(('{0:.3g}'.format(flux))) 3.02e-17 erg / (Angstrom cm2 s)

This function is used to calculate filter response zeropoints in the AB system. If either of the parameters is an array, the result will be broadcast over the parameters using the usual numpy rules. Parameters

wavelength [astropy.units.Quantity] Wavelength or array of wavelengths where the flux should be eval- uated. Wavelengths must have valid units. magnitude [float or array] Dimensionless magnitude value(s) used to normalize the spectrum. Returns

astropy.units.Quantity Spectral flux densities per unit wavelength tabulated at each input wavelength, in units of default_flux_unit. Raises

ValueError Wavelength parameter does not have valid units.

filter_sampling_explanatory_plot speclite.filters.filter_sampling_explanatory_plot(save=None) Generate an explanatory plot for the documentation. Requires that the matplotlib package is installed. The generated figure appears in the Sampling section. Parameters

save [str or None] Name of the file where this plot should be saved. load_filter speclite.filters.load_filter(name, load_from_cache=True, verbose=False) Load a single filter response by name. See Filter Response Curves for details on the filter response file format and the available standard filters.

13.1. speclite.filters Module 51 speclite Documentation, Release 0.14dev391

A filter response is normally only loaded from disk the first time this function is called, and subsequent calls immediately return the same cached object. Use the verbose option for details on how a filter is loaded:

>>> rband= load_filter( 'sdss2010-r') >>> rband= load_filter( 'sdss2010-r', verbose=True) Returning cached filter response "sdss2010-r"

Use load_filters() to load a sequence of filters from one or more filter groups. Parameters

name [str] Name of the filter response to load, which should normally have the format “-”, and refer to one of the reference filters described here. Otherwise, the name of any file in the ECSV format and containing the required fields can be provided. The existence of the “.ecsv” extension is used to distinguish between these cases and any other extension is considered an error. load_from_cache [bool] Return a previously cached response object if available. Otherwise, always load the file from disk. verbose [bool] Print verbose information about how this filter is loaded. Returns

FilterResponse A FilterResponse object for the requested filter. Raises

ValueError File does not exist or custom file has wrong extension. RuntimeError File is incorrectly formatted. This should never happen for the files included in the source code distribution. load_filters speclite.filters.load_filters(*names) Load a sequence of filters by name. For example, to load all the sdss2010 filters:

>>> sdss= load_filters( 'sdss2010-*') >>> sdss.names ['sdss2010-u', 'sdss2010-g', 'sdss2010-r', 'sdss2010-i', 'sdss2010-z']

Names are intepreted according to the following rules: • A canonical name of the form “-” loads the corresponding single standard filter response. • A group name with a wildcard, “-*”, loads all the standard filters in a group, ordered by increasing effective wavelength.

52 Chapter 13. Operations with Filters speclite Documentation, Release 0.14dev391

• A filename ending with the “.ecsv” extension loads a custom filter response from the specified file. Note that custom filters must be specified individually, even if they all belong to the same group. Parameters

*names Variable length list of names to include. Each name must be in one of the formats described above. Returns

FilterSequence An immutable FilterSequence object containing the requested filters in the order they were specified. plot_filters speclite.filters.plot_filters(responses, wavelength_unit=None, wavelength_limits=None, wave- length_scale=’linear’, legend_loc=’upper right’, cmap=’nipy_spectral’) Plot one or more filter response curves. The matplotlib package must be installed to use this function. The show

responses [FilterSequence] The sequence of filters to plot, normally obtained by calling load_filters(). wavelength_unit [astropy.units.Unit] Convert values along the wavelength axis to the specified unit, or leave them as default_wavelength_unit if this parameter is None. wavelength_limits [tuple or None] Plot limits to use on the wavelength axis, or select limits automatically if this parameter is None. Units are optional. wavelength_scale [str] Scaling to use for the wavelength axis. See matplotlib.pyplot.yscale() for details. legend_loc [str] Location of the legend to plot, or do not display any legend if this value is None. See matplotlib.pyplot.legend() for details. cmap [str or matplotlib.colors.Colormap] Color map to use for plotting each filter band. Col- ors are assigned based on each band’s effective wavelength, so a spectral color map (from blue to red) will give nice results. tabulate_function_of_wavelength speclite.filters.tabulate_function_of_wavelength(function, wavelength, verbose=False) Evaluate a function of wavelength.

13.1. speclite.filters Module 53 speclite Documentation, Release 0.14dev391

Parameters

function [callable] Any function that expects a wavelength or array of wavelengths and re- turns its value. Functions will be called first with wavelength units included and then without units included, in which case they should treat all wavelengths as having default_wavelength_unit. If a function returns a value with units, this will be correctly propagated to the output. wavelength [astropy.units.Quantity] Wavelength or array of wavelengths where the function should be evaluated. Wavelengths must have valid units. verbose [bool] Print details of the sequence of attempts used to call the function. Returns

tuple Tuple (values, units) of function values at each input wavelength. validate_wavelength_array speclite.filters.validate_wavelength_array(wavelength, min_length=0) Validate a wavelength array for filter operations. This function will not perform any copying or allocation if the input is already a numpy array or astropy Quantity. Parameters

wavelength [array] A 1D array of strictly increasing wavelength values with optional units. If units are included, they must be convertible to default_wavelength_unit. Otherwise, the default_wavelength_unit is assumed. min_length [int] The minimum required length of the wavelength array. Returns

numpy.ndarray Array of validated wavelengths without any units, but with values given in default_wavelength_unit. Raises

ValueError Wavelength array is not 1D, or not strictly increasing, or below the minimum length. astropy.units.UnitConversionError The wavelength array has units that are not convertible to default_wavelength_unit

54 Chapter 13. Operations with Filters speclite Documentation, Release 0.14dev391

13.1.9 Classes

FilterConvolution(response, wavelength[, . . . ]) Convolve a filter response with a tabulated function. FilterResponse(wavelength, response, meta[, . . . ]) A filter response curve tabulated in wavelength. FilterSequence(responses) Immutable sequence of filter responses.

FilterConvolution class speclite.filters.FilterConvolution(response, wavelength, photon_weighted=True, interpo- late=False, units=None) Bases: object Convolve a filter response with a tabulated function. See above for details on how the convolution operator implemented by this class is defined, and here for details on how the convolution integrand is sampled. Most of the computation involved depends only on the tabulated function’s wavelength grid, and not on the function values, so this class does the necessary initialization in its constructor, resulting in a function object that can be efficiently re-used with different function values. Use this class to efficiently perform repeated convolutions of different tabulated functions for the same filter on the same wavelength grid. When efficiency is not important or the wavelength grid changes for each convolution, the convencience method FilterResponse.convolve_with_array() can be used instead. Parameters

response [FilterResponse or str] A FilterResponse object or else a fully qualified name of the form “-”, which will be loaded using load_filter(). wavelength [array] A valid array of wavelengths that must cover the full range of the filter response. photon_weighted [bool] Use weights appropriate for a photon-counting detector such as a CCD when this parameter is True. Otherwise, use unit weights. interpolate [bool] Allow interpolation of the tabulated function if necessary. Interpolation is required if two or more of the wavelengths where the filter response is tabulated fall between a consec- utive pair of input wavelengths. Linear interpolation is then performed to estimate the input function at the undersampled filter response wavelengths. Interpolation has a performance impact when evaluating a convolution, so is not enabled by default and can usually be avoided with finer sampling of the input function. units [astropy.units.Quantity or None] When this parameter is not None, then any explicit units attached to the values passed to a convolution must be convertible to these units. When values are passed without units they are assumed to be in these units. Attributes

response [FilterResponse] The filter response used for this convolution.

13.1. speclite.filters Module 55 speclite Documentation, Release 0.14dev391

input_units [astropy.units.Unit] Units expected for values passed to __call__(). output_units [astropy.units.Unit] Units of __call__() result. num_wavelength [int] The number of wavelengths used to tabulate input functions. response_grid [numpy.ndarray] Array of filter response values evaluated at each wavelength. response_slice [slice] Slice of the input wavelength grid used for convolution. interpolate_wavelength [numpy.ndarray or None] Array of wavelengths where the input function will be interpo- lated. interpolate_response [numpy.ndarray or None] Array of filter response values at each interpolate_wavelength. interpolate_sort_order [numpy.ndarray or None] Integer array specifying the sort order required to combine wavelength and interpolate_wavelength. quad_wavelength [numpy.ndarray] Array of wavelengths used for numerical quadrature, combining both wavelength and interpolate_wavelength. quad_weight [astropy.units.Quantity or None] Array of weights corresponding to each quad_wavelength. Will be None if the parameter photon_weighted = False.

Methods Summary

__call__(values[, axis, method, plot]) Evaluate the convolution for arbitrary tabulated func- tion values.

Methods Documentation

__call__(values, axis=-1, method=’trapz’, plot=False) Evaluate the convolution for arbitrary tabulated function values. Parameters

values [array or astropy.units.Quantity] Array of function values to use. Values are assumed to be tabulated on our wavelength grid. Values can be multidimensional, in which case an array of convolution results is returned. If values have units, then these are propagated to the result. axis [int] In case of multidimensional function values, this specifies the index of the axis cor- responding to the wavelength dimension. method [str] Specifies the numerical integration scheme to use and must be either ‘trapz’ or

56 Chapter 13. Operations with Filters speclite Documentation, Release 0.14dev391

‘simps’, to select the corresponding scipy.integration function. The ‘simps’ method may be more accurate than the default ‘trapz’ method, but should be used with care since it is also less robust and more sensitive to the wavelength grids. plot [bool] Displays a plot illustrating how the convolution integrand is constructed. Requires that the matplotlib package is installed and does not support multidimensional input val- ues. This option is primarily intended for debugging and to generate figures for the docu- mentation. Returns

float or numpy.ndarray or astropy.units.Quantity Convolution integral result. If the input values have units then these are propagated to the result, including the units associated with the photon weights (if these are selected). Otherwise, the result will be a plain float or numpy array. If the input is multidimensional, then so is the result but with the specified axis integrated out.

FilterResponse class speclite.filters.FilterResponse(wavelength, response, meta, band_shift=None) Bases: object A filter response curve tabulated in wavelength. Some standard filters are included in this package and can be initialized using load_filter(). For example:

>>> rband= load_filter( 'sdss2010-r')

Objects behave like functions that evaluate their response at aribtrary wavelengths. Wavelength units can be specified, or else default to default_wavelength_unit:

>>> round(rband(6000* astropy.units.Angstrom),4) 0.5323 >>> round(rband(6000),4) 0.5323 >>> round(rband(0.6* astropy.units.micron),4) 0.5323

Filters can be also evaluated for an arbitrary array of wavelengths, returning a numpy array of response values:

>>> resp= rband([5980, 6000, 6020]) >>> np.round(resp[1],4) 0.5323

The effective wavelength of a filter is defined as the photon-weighted mean wavelength:

휆푒푓푓 ≡ 퐹 [푅, 휆]/퐹 [푅, 1] where 퐹 is our convolution operator defined above. Use the effective_wavelength attribute to access this value:

>>> print((np.round(rband.effective_wavelength,1))) 6197.7 Angstrom

The examples below show three different ways to calculate the AB magnitude in the sdss2010-r filter for a source with a constant spectral flux density per unit wavelength of 10−17erg/(cm2 s ). First, we specify the spectrum with a function object:

13.1. speclite.filters Module 57 speclite Documentation, Release 0.14dev391

>>> flux= lambda wlen: 1e-17* default_flux_unit >>> print((rband.get_ab_magnitude(flux).round(3))) 21.141

Next, we tabulate a constant flux using only two wavelength points that span the filter response:

>>> wlen=[5300, 7200]* default_wavelength_unit >>> flux=[1e-17, 1e-17]* default_flux_unit >>> print((rband.get_ab_magnitude(flux, wlen).round(3))) 21.141

Since this spectrum undersamples the filter response, it is automatically interpolated. Finally, we tabulate a constant flux using a dense wavelength grid that oversamples the filter response and does not require any inter- polation:

>>> wlen= np.linspace(5300, 7200, 200)* default_wavelength_unit >>> flux= np.ones_like(wlen.value)* 1e-17* default_flux_unit >>> print((rband.get_ab_magnitude(flux, wlen).round(3))) 21.141

Filters can have an optional wavelength shift applied. See http://arxiv.org/abs/astro-ph/0205243 for applications. Shifted filters can be created from non-shifted filters using create_shifted(). Parameters

wavelength [array] A valid array of wavelengths. response [array] A dimensionless 1D array of filter response values corresponding to each wave- length. Response values must be non-negative and cannot all be zero. The bounding re- sponse values must be zero, and the response is assumed to be zero outside of the specified wavelength range. If this parameter has units, they will be silently ignored. meta [dict] A dictionary of metadata which must include values for the keys group_name and band_name, which must be valid python identifiers. However, you are encouraged to provide the full set of keys listed here, and additional keys are also permitted. band_shift [float or None] A shift to apply to filter wavelengths (but not response values). A shifted filter cannot be saved or further shifted, but can otherwise be used like any other filter. Raises

ValueError Invalid wavelength or response input arrays, or missing required keys in the input metadata. Attributes

name [str] Canonical name of this filter response in the format “-”. effective_wavelength [astropy.units.Quantity] Mean photon-weighted wavelength of this response function, as defined above.

58 Chapter 13. Operations with Filters speclite Documentation, Release 0.14dev391

ab_zeropoint [astropy.units.Quantity] Zeropoint for this filter response in the AB system, as defined above, and including units. meta [dict] Dictionary of metadata associated with this filter. interpolator [scipy.interpolate.interp1d] Linear interpolator of our response function that returns zero for all values outside our wavelength range. Should normally be evaluated through our __call__() convenience method.

Attributes Summary

response Return the response curve array of the filter wavelength Return the wavelength array of the filter

Methods Summary

__call__(wavelength) Evaluate the filter response at arbitrary wavelengths. convolve_with_array(wavelength, values[, . . . ]) Convolve this response with a tabulated function of wavelength. convolve_with_function(function[, . . . ]) Convolve this response with a function of wave- length. create_shifted(band_shift) Create a copy of this filter response with shifted wavelengths. get_ab_maggies(spectrum[, wavelength, axis]) Calculate a spectrum’s relative AB flux convolution. get_ab_magnitude(spectrum[, wavelength, axis]) Calculate a spectrum’s AB magnitude. pad_spectrum(spectrum, wavelength[, axis, . . . ]) Pad a tabulated spectrum to cover this filter’s re- sponse. save([directory_name, overwrite]) Save this filter response to file.

Attributes Documentation

response Return the response curve array of the filter Returns

np.ndarray

An array of response values after trimming any extra leading or trailing zero response values. wavelength Return the wavelength array of the filter Returns

np.ndarray An array of wavelengths with their associated units after trimming any extra leading or trailing zero response values.

13.1. speclite.filters Module 59 speclite Documentation, Release 0.14dev391

Methods Documentation

__call__(wavelength) Evaluate the filter response at arbitrary wavelengths. Parameters

wavelength [array or float] A single wavelength value or an array of wavelengths. If units are included, they will be correctly interpreted. Otherwise default_wavelength_unit is assumed. Returns

numpy.ndarray Numpy array of response values corresponding to each input wavelength. Raises

astropy.units.UnitConversionError Input wavelength(s) have unit that is not convertible to default_wavelength_unit. convolve_with_array(wavelength, values, photon_weighted=True, interpolate=False, axis=-1, units=None, method=’trapz’) Convolve this response with a tabulated function of wavelength. This is a convenience method that creates a temporary FilterConvolution object to perform the convo- lution. See that class’ documentation for details on this method’s parameters and usage. See also the notes above about how the convolution integrand is sampled. Parameters

wavelength [array] A valid array of wavelengths that must cover the full range of this filter’s re- sponse. values [array or astropy.units.Quantity] Array of function values to use. Values are assumed to be tabulated on our wavelength grid. Values can be multidimensional, in which case an array of convolution results is returned. If values have units, then these are propagated to the result. photon_weighted [bool] Use weights appropriate for a photon-counting detector such as a CCD when this parameter is True. Otherwise, use unit weights. interpolate [bool] Allow interpolation of the tabulated function if necessary. See FilterConvolution for details. axis [int] In case of multidimensional function values, this specifies the index of the axis cor- responding to the wavelength dimension. units [astropy.units.Quantity or None] When this parameter is not None, then any explicit values units must be convertible to these units, and these units will be applied to the values if they do not already have units.

60 Chapter 13. Operations with Filters speclite Documentation, Release 0.14dev391

method [str] Specifies the numerical integration scheme to use. See FilterConvolution for de- tails. Returns

float or array or astropy.units.Quantity Convolution integral result(s). If the input values have units then these are propagated to the result(s). If the input is multidimensional, then so is the result but with the specified axis integrated out. convolve_with_function(function, photon_weighted=True, units=None, method=’trapz’) Convolve this response with a function of wavelength. Returns a numerical estimate of the convolution integral 퐹 [푅, 푓] defined above for an arbitrary function of wavelength 푓(휆). For example, to calculate a filter’s effective wavelength:

>>> rband= load_filter( 'sdss2010-r') >>> one= astropy.units.Quantity(1.) >>> numer= rband.convolve_with_function( lambda wlen: wlen) >>> denom= rband.convolve_with_function( lambda wlen: one) >>> print((np.round(numer/ denom,1))) 6197.7 Angstrom

Similarly, a filter’s zeropoint can be calculated using:

>>> zpt= rband.convolve_with_function(ab_reference_flux) >>> print((zpt.round(1))) 551725.0 1 / (cm2 s)

Note that both of these values are pre-calculated in the constructor and are available from the effective_wavelength and ab_zeropoint attributes. Parameters

function [callable] Any function that expects a wavelength or array of wavelengths and re- turns its value. Functions will be called first with wavelength units included and then without units included, in which case they should treat all wavelengths as having default_wavelength_unit. If a function returns a value with units, this will be correctly propagated to the convolution result. photon_weighted [bool] Use weights appropriate for a photon-counting detector such as a CCD when this parameter is True. Otherwise, use unit weights. units [astropy.units.Quantity or None] When this parameter is not None, then any explicit units returned by the function must be convertible to these units, and these units will be applied if the function values do not already have units. method [str] Specifies the numerical integration scheme to use and must be either ‘trapz’ or ‘simps’, to select the corresponding scipy.integration function. The ‘simps’ method may be more accurate than the default ‘trapz’ method, but should be used with care since it is also less robust and more sensitive to the wavelength grid.

13.1. speclite.filters Module 61 speclite Documentation, Release 0.14dev391

Returns

float or astropy.units.Quantity Result of the convolution integral. Units will be included if the function returns a value with units. Otherwise, the implicit units of the result are equal to the implicit function value units multiplied by default_wavelength_unit. Raises

ValueError Function does not behave as expected or invalid method. RuntimeError Function returns inconsistent units. create_shifted(band_shift) Create a copy of this filter response with shifted wavelengths. A filter response 푅(휆) is transformed to blue-shifted response 푅((1 + 푧)휆) by shifting the wavelengths where its response values are tabulated from 휆푖 to 휆푖/(1 + 푧). Note that only the tabulated wavelengths are transformed and not the response values. See http://arxiv.org/abs/astro-ph/0205243 for applications. A shifted filter cannot be saved or further shifted, but can otherwise be used like any other filter. Parameters

band_shift [float or None] Shift to apply to filter wavelengths (but not response values). Returns

FilterResponse A new filter object that is a copy of this filter but with the specified wavelength shift applied. Raises

RuntimeError Cannot apply a second wavelength shift to a filter response. get_ab_maggies(spectrum, wavelength=None, axis=-1) Calculate a spectrum’s relative AB flux convolution.

The result is the dimensionless ratio 퐹 [푅, 푓휆]/퐹 [푅, 푓휆,0] defined above, and provides a linear measure of a source’s flux through this filter relative to an AB standard flux. Use get_ab_magnitude() for the corresponding AB magnitude. Parameters

spectrum [callable or array or astropy.units.Quantity] The spectrum whose flux should be com- pared with the AB standard flux in this filter band. Can either be a callable object (see convolve_with_function() for details) or else an array (See convolve_with_array() for details). A multidimensional array can be used to calculate maggies for many spec- tra at once. The spectrum fluxes must either have explicit units that are convertible to

62 Chapter 13. Operations with Filters speclite Documentation, Release 0.14dev391

default_flux_unit, or else they will be implicitly interpreted as having these default units. wavelength [array or astropy.units.Quantity or None] When this parameter is None, the spectrum must be a callable object. Otherwise, the spectrum must be a valid array of wavelengths that must cover the full range of this filter’s response. A spectrum that does not cover this filter can be padded first using pad_spectrum(). axis [int] The axis along which wavelength increases in a spectrum array. Ignored when the wavelength parameter is None. Returns

float or array

get_ab_magnitude(spectrum, wavelength=None, axis=-1) Calculate a spectrum’s AB magnitude.

Use get_ab_maggies() for the corresponding dimensionless ratio 퐹 [푅, 푓휆]/퐹 [푅, 푓휆,0]. The magnitude is calculated as: Parameters

spectrum [callable or array or astropy.units.Quantity] See get_ab_maggies() for details. wavelength [array or astropy.units.Quantity or None] See get_ab_maggies() for details. axis [int] See get_ab_maggies() for details. Returns

float or array

pad_spectrum(spectrum, wavelength, axis=-1, method=’median’) Pad a tabulated spectrum to cover this filter’s response. This is a convenience method that pads an input spectrum (or spectra) so that it covers this filter’s response and can then be used for convolutions and magnitude calculations:

>>> rband= load_filter( 'decam2014-r') >>> wlen= np.arange(4000, 10000) >>> flux= np.ones((100, len(wlen))) >>> mag= rband.get_ab_magnitude(flux, wlen) Traceback (most recent call last): ... ValueError: Wavelengths do not cover decam2014-r response 3330.0-10990.0 Angstrom. >>> flux, wlen= rband.pad_spectrum(flux, wlen) >>> mag= rband.get_ab_magnitude(flux, wlen)

13.1. speclite.filters Module 63 speclite Documentation, Release 0.14dev391

This method does not attempt to perform a physically motivated extrapolation, so should only be used under special circumstances. An appropriate use would be to extend a spectrum to cover wavelengths where the filter response is almost zero or the spectrum is known to be essentially flat. The three padding methods implemented here are borrowed from numpy.pad(): • median: Pad with the median flux value. • zero: Pad with a zero flux value. • edge: Pad with the edge flux values. If the results from these methods are not in good agreement, you should probably not be padding your spectrum. Parameters

spectrum [array or astropy.units.Quantity] See get_ab_maggies() for details. This method does not check for valid flux density units, if any are specified. wavelength [array or astropy.units.Quantity or None] See get_ab_maggies() for details. axis [int] See get_ab_maggies() for details. method [str] Must be one of ‘median’, ‘zero’, or ‘edge’. Returns

tuple A tuple (padded_spectrum, padded_wavelength) that replaces the inputs with padded equivalents. save(directory_name=’.’, overwrite=True) Save this filter response to file. The response is saved in the ECSV format and can be read back by passing the returned path to load_filter():

file_name= response.save() response2= load_filter(file_name)

The file name in the specified directory will be “-.ecsv”. Any existing file with the same name will be silently overwritten. Saved filter responses cannot have any wavelength shift applied since their file naming convention does not distinguish between different shifts. Therefore, attempting to save a filter with a wavelength shift applied will raise a RuntimeError. Parameters

directory_name [str] An existing directory where the response file should be written. overwrite [bool] Silently overwrite this file when True.

64 Chapter 13. Operations with Filters speclite Documentation, Release 0.14dev391

Returns

str Absolute path of the created file, including the .ecsv extension. Raises

ValueError Directory name does not exist or refers to a file. RuntimeError Filter response has a wavelength shift applied.

FilterSequence class speclite.filters.FilterSequence(responses) Bases: collections.abc.Sequence Immutable sequence of filter responses. Sequences should normally be created by calling load_filters(). Objects implement the immutable sequence API, in addition to the methods listed here. A filter sequence’s get_ab_maggies() and get_ab_magnitudes() methods return their results in a Table and are convenient for calculating convolutions in several bands for multiple spectra. For example, given the following 4 (identical) spectra covering the SDSS filters:

>>> num_spectra, num_pixels=4, 500 >>> wlen= np.linspace(2000, 12000, num_pixels)* default_wavelength_unit >>> flux= np.ones((num_spectra, num_pixels))* 1e-17* default_flux_unit

We can now calculate their magnitudes in all bands with one function:

>>> sdss= load_filters( 'sdss2010-*') >>> mags= sdss.get_ab_magnitudes(flux, wlen)

Refer to the astropy docs for details on working with Tables. For example, to pretty-print the magnitudes with a precision of 0.001:

>>> formats= dict((n, '%.3f') for n in sdss.names) >>> mags.write(None, format='ascii.fixed_width', formats=formats) | sdss2010-u | sdss2010-g | sdss2010-r | sdss2010-i | sdss2010-z | | 22.340 | 21.742 | 21.141 | 20.718 | 20.338 | | 22.340 | 21.742 | 21.141 | 20.718 | 20.338 | | 22.340 | 21.742 | 21.141 | 20.718 | 20.338 | | 22.340 | 21.742 | 21.141 | 20.718 | 20.338 |

Parameters

responses [iterable] Response objects to include in this sequence. Objects are copied to an internal list. Attributes

13.1. speclite.filters Module 65 speclite Documentation, Release 0.14dev391

names [list of str] List of the filter response names in this sequence, with the format “-”. effective_wavelengths [astropy.units.Quantity] List of the effective wavelengths for the filter responses in this se- quence, with the default wavelength units.

Attributes Summary

effective_wavelengths names

Methods Summary

get_ab_maggies(spectrum[, wavelength, axis, . . . ]) Calculate a spectrum’s relative AB flux convolutions. get_ab_magnitudes(spectrum[, wavelength, . . . ]) Calculate a spectrum’s AB magnitude. pad_spectrum(spectrum, wavelength[, axis, . . . ]) Pad a spectrum to cover all filter responses.

Attributes Documentation

effective_wavelengths

names

Methods Documentation

get_ab_maggies(spectrum, wavelength=None, axis=-1, mask_invalid=False) Calculate a spectrum’s relative AB flux convolutions. Calls FilterResponse.get_ab_maggies() for each filter in this sequence and returns the results in a structured array. Use get_ab_magnitudes() for the corresponding AB magnitudes. Parameters

spectrum [callable or array or astropy.units.Quantity] See get_ab_maggies() for details. wavelength [array or astropy.units.Quantity or None] See get_ab_maggies() for details. axis [int] See get_ab_maggies() for details. mask_invalid [bool] When True, if an error occurs while calculating results for one filter (usually because of insufficient wavelength coverage), the corresponding output column will be filled with missing values. Otherwise, any error raises an exception.

66 Chapter 13. Operations with Filters speclite Documentation, Release 0.14dev391

Returns

astropy.table.Table A table of results with column names corresponding to canonical filter names of the form “-”. If the input spectrum data is multidimensional, its first index is mapped to rows of the returned table. get_ab_magnitudes(spectrum, wavelength=None, axis=-1, mask_invalid=False) Calculate a spectrum’s AB magnitude. Calls FilterResponse.get_ab_magnitude() for each filter in this sequence and returns the results in a structured array. Parameters

spectrum [callable or array or astropy.units.Quantity] See get_ab_magnitude() for details. wavelength [array or astropy.units.Quantity or None] See get_ab_magnitude() for details. axis [int] See get_ab_magnitude() for details. mask_invalid [bool] When True, if an error occurs while calculating results for one filter (usually because of insufficient wavelength coverage), the corresponding output column will be filled with missing values. Otherwise, any error raises an exception. Returns

astropy.table.Table A table of results with column names corresponding to canonical filter names of the form “-”. If the input spectrum data is multidimensional, its first index is mapped to rows of the returned table. pad_spectrum(spectrum, wavelength, axis=-1, method=’median’) Pad a spectrum to cover all filter responses. Calls FilterResponse.pad_spectrum() for each filter in this sequence, in order of increasing effective wavelength. Parameters and caveats for this method are the same. Parameters

spectrum [array or astropy.units.Quantity] See FilterResponse.pad_spectrum() for details. wavelength [array or astropy.units.Quantity or None] See FilterResponse.pad_spectrum() for details. axis [int] See FilterResponse.pad_spectrum() for details. method [str] See FilterResponse.pad_spectrum() for details. Returns

13.1. speclite.filters Module 67 speclite Documentation, Release 0.14dev391

tuple A tuple (padded_spectrum, padded_wavelength) that replaces the inputs with padded equivalents.

68 Chapter 13. Operations with Filters Python Module Index

s speclite.accumulate, 39 speclite.downsample, 41 speclite.filters, 47 speclite.redshift, 44 speclite.resample, 43

69 speclite Documentation, Release 0.14dev391

70 Python Module Index Index

Symbols get_ab_magnitudes() (speclite.filters.FilterSequence __call__() (speclite.filters.FilterConvolution method), method), 67 56 L __call__() (speclite.filters.FilterResponse method), 60 load_filter() (in module speclite.filters), 51 A load_filters() (in module speclite.filters), 52 ab_reference_flux() (in module speclite.filters), 51 N accumulate() (in module speclite.accumulate), 39 names (speclite.filters.FilterSequence attribute), 66 C P convolve_with_array() (speclite.filters.FilterResponse pad_spectrum() (speclite.filters.FilterResponse method), 60 method), 63 convolve_with_function() pad_spectrum() (speclite.filters.FilterSequence (speclite.filters.FilterResponse method), method), 67 61 plot_filters() (in module speclite.filters), 53 create_shifted() (speclite.filters.FilterResponse method), 62 R D redshift() (in module speclite.redshift), 45 resample() (in module speclite.resample), 43 downsample() (in module speclite.downsample), 41 response (speclite.filters.FilterResponse attribute), 59 E S effective_wavelengths (speclite.filters.FilterSequence save() (speclite.filters.FilterResponse method), 64 attribute), 66 speclite.accumulate (module), 39 speclite.downsample (module), 41 F speclite.filters (module), 47 filter_sampling_explanatory_plot() (in module speclite.redshift (module), 44 speclite.filters), 51 speclite.resample (module), 43 FilterConvolution (class in speclite.filters), 55 FilterResponse (class in speclite.filters), 57 T FilterSequence (class in speclite.filters), 65 tabulate_function_of_wavelength() (in module speclite.filters), 53 G get_ab_maggies() (speclite.filters.FilterResponse V method), 62 validate_wavelength_array() (in module get_ab_maggies() (speclite.filters.FilterSequence speclite.filters), 54 method), 66 get_ab_magnitude() (speclite.filters.FilterResponse W method), 63 wavelength (speclite.filters.FilterResponse attribute), 59

71