Source code for pyspeckit.wrappers.cube_fit

"""
Cube Fitting
============

Complicated code for fitting of a whole data cube, pixel-by-pixel
"""
from __future__ import print_function
import pyspeckit
from astropy.io import fits
import astropy
import numpy as np
import os

[docs]def cube_fit(cubefilename, outfilename, errfilename=None, scale_keyword=None, vheight=False, verbose=False, signal_cut=3, verbose_level=2, overwrite=True, **kwargs): """ Light-weight wrapper for cube fitting Takes a cube and error map (error will be computed naively if not given) and computes moments then fits for each spectrum in the cube. It then saves the fitted parameters to a reasonably descriptive output file whose header will look like :: PLANE1 = 'amplitude' PLANE2 = 'velocity' PLANE3 = 'sigma' PLANE4 = 'err_amplitude' PLANE5 = 'err_velocity' PLANE6 = 'err_sigma' PLANE7 = 'integral' PLANE8 = 'integral_error' CDELT3 = 1 CTYPE3 = 'FITPAR' CRVAL3 = 0 CRPIX3 = 1 Parameters ---------- errfilename: [ None | string name of .fits file ] A two-dimensional error map to use for computing signal-to-noise cuts scale_keyword: [ None | Char ] Keyword to pass to the data cube loader - multiplies cube by the number indexed by this header kwarg if it exists. e.g., if your cube is in T_A units and you want T_A* vheight: [ bool ] Is there a background to be fit? Used in moment computation verbose: [ bool ] verbose_level: [ int ] How loud will the fitting procedure be? Passed to momenteach and fiteach signal_cut: [ float ] Signal-to-Noise ratio minimum. Spectra with a peak below this S/N ratio will not be fit and will be left blank in the output fit parameter cube overwrite: [ bool ] Overwrite parameter .fits cube if it exists? `kwargs` are passed to :class:`pyspeckit.Spectrum.specfit` """ # Load the spectrum sp = pyspeckit.Cube(cubefilename,scale_keyword=scale_keyword) if os.path.exists(errfilename): errmap = fits.getdata(errfilename) else: # very simple error calculation... biased and bad, needs improvement # try using something from the cubes package errmap = sp.cube.std(axis=0) # Run the fitter sp.mapplot() # Compute the moments at each position to come up with reasonable guesses. # This speeds up the process enormously, but can easily mess up the fits if # there are bad pixels sp.momenteach(vheight=vheight, verbose=verbose) sp.fiteach(errmap=errmap, multifit=None, verbose_level=verbose_level, signal_cut=signal_cut, usemomentcube=True, blank_value=np.nan, verbose=verbose, **kwargs) # steal the header from the error map f = fits.open(cubefilename) # start replacing components of the fits object f[0].data = np.concatenate([sp.parcube,sp.errcube,sp.integralmap]) f[0].header['PLANE1'] = 'amplitude' f[0].header['PLANE2'] = 'velocity' f[0].header['PLANE3'] = 'sigma' f[0].header['PLANE4'] = 'err_amplitude' f[0].header['PLANE5'] = 'err_velocity' f[0].header['PLANE6'] = 'err_sigma' f[0].header['PLANE7'] = 'integral' f[0].header['PLANE8'] = 'integral_error' f[0].header['CDELT3'] = 1 f[0].header['CTYPE3'] = 'FITPAR' f[0].header['CRVAL3'] = 0 f[0].header['CRPIX3'] = 1 # save your work if astropy.version.major >= 2 or (astropy.version.major==1 and astropy.version.minor>=3): f.writeto(outfilename, overwrite=overwrite) else: f.writeto(outfilename, clobber=overwrite) return sp