示例#1
0
def update_rest_moment0(region_name='L1688', file_extension='DR1_rebase3', v_mean=2.5, sigma_v=0.3):
    """
    Update moment calculation for non-NH3 lines. Don't base on NH3 fit; these lines may be
    offset in velocity. Right now including velocity ranges by hand. 
    """
    for line in ['HC5N','HC7N_21_20','HC7N_22_21','C2S','NH3_33']:
        file_in ='{0}/{0}_{2}_{1}.fits'.format(region_name,file_extension,line)
        file_out='{0}/{0}_{2}_{1}_mom0_QA.fits'.format(region_name,file_extension,line)
        file_rms='{0}/{0}_{2}_{1}_rms_QA.fits'.format(region_name,file_extension,line)
        # Load pyspeckit cube
        pycube = pyspeckit.Cube(file_in)
        # Use spectral cube to calculate integrated intensity maps
        cube_raw = SpectralCube.read(file_in)
        # in km/s not Hz
        cube = cube_raw.with_spectral_unit(u.km / u.s,velocity_convention='radio')
        vaxis=cube.spectral_axis
        dv=np.abs(vaxis[1]-vaxis[0])
        vmean = v_mean*u.km/u.s
        sigmav = sigma_v*u.km/u.s
        total_spc=np.sqrt( (vaxis-vmean)**2)/sigmav < 3
        mask3d = np.ones(cube.shape,dtype=bool)
        for ii in np.arange(cube.shape[2]):
            for jj in np.arange(cube.shape[1]):
                mask3d[:,jj,ii] = total_spc
        # create masked cube
        cube2 = cube.with_mask(mask3d)
        cube3 = cube.with_mask(~mask3d)
        # calculate moment map
        moment_0 = cube2.moment(axis=0)
        moment_0.write( file_out, overwrite=True)
        rms=cube3.std(axis=0)
        rms.write( file_rms, overwrite=True)
示例#2
0
    def __init__(self, *args):
        """
        A collection of Specfit objects mapped to SubCubes
        by the mapper method. Includes* methods to fit multiple
        guess grids for different models, and the means to
        decide between the results of those fits.

        *In a distant[citation needed] future.

        Input parameters: see ~pyspeckit.Cube
        """

        # parent cube, used for attribute propagation
        self.supercube = pyspeckit.Cube(*args)

        # making a bunch of references to make our life easier
        self.cube = self.SuperCube.cube
        self.xarr = self.SuperCube.xarr
        self.header = self.SuperCube.header

        # FIXME: rewrite mapplot to include the mapper/judge methods!
        #        doesn't work in its current implementation, will need
        #        to rewire different params and errors, for variable
        #        number of parameters across different models
        self.multiplot = self.SuperCube.mapplot

        # MultiCube's own instances:
        self.multigrid = {}
        self.tesseract = {}
def test_load_cube_from_spectralcube():
    sc = make_fake_cube()
    pcube = pyspeckit.Cube(cube=sc)

    assert pcube.unit == 'K'
    assert pcube.xarr.unit == 'km/s'

    return pcube
示例#4
0
def make_cube(files=(file_nh311_dr1, file_nh322_dr1),
              rms_files=(file_rms_nh311_dr1, file_rms_nh322_dr1)):
    """
    Opens the cube and calculates all the pre-fitting attributes of interest.
    """
    # make sure we're working on arrays (why?)
    files = np.atleast_1d([f for f in files])
    rms_files = np.atleast_1d([f for f in rms_files])

    if files.size > 1:
        spc_dict = {f: pyspeckit.Cube(f) for f in files}
        rmsmaps = {f: fits.getdata(ef) for f, ef in zip(files, rms_files)}
        for f in files:
            spc_dict[f].errorcube = np.repeat([rmsmaps[f]],
                                              spc_dict[f].xarr.size,
                                              axis=0)
        # now the errorcubes should merge automatically
        spc = pyspeckit.CubeStack([spc_dict[f] for f in files])
        spc.xarr.refX = spc.cubelist[0].xarr.refX
        spc.xarr.refX_unit = spc.cubelist[0].xarr.refX_unit
    else:
        spc = pyspeckit.Cube(files[0])
        rms = fits.getdata(rms_files[0])
        # easier to handle everything get_spectrum-related
        spc.errorcube = np.repeat([rms], spc.xarr.size, axis=0)

    # I don't see a reason why errorcube should be a masked array
    if type(spc.errorcube) == np.ma.MaskedArray:
        spc.errorcube = np.array(spc.errorcube)

    spc.xarr.velocity_convention = 'radio'
    spc.xarr.convert_to_unit('km/s')

    snr = (spc.cube / spc.errorcube).max(axis=0)

    # TODO: fix multinest-pipeline.py and run_multicube.py
    #spc.errmap = rms
    spc.snrmap = snr

    return spc
def velocity(cube, wavelength, velocity_range, multicore, outfile):
    '''
    
    cube: str
        The cube path and filename, e.g. path_to_cube/cube_filename.fits

    wavelength: str
        The line one wishes to compute the velocity map for, e.g. Ha, SII6717, or stacked for the stacked version. Default is stacked. 
        Available lines are SII6717, SII6731, Ha, NII6548, NII6584, Hb, OIII5007, SIII9068, OI6300.

    velocity_range: array
        The velocity range, e.g. [-200,200]. Default is [-300,300].

    multicore: int
        The number of cores for the parallelization. Default is 3.

    outfile: str
        The name of the output file. Default is wavelength+'_velocity.fits'.

    '''

    cube = spectral_cube.SpectralCube.read(str(cube), hdu=1)
    hd = cube.header
    ## NEED TO IMPLEMENT CONTINUUM SUBTRACTION BASED ON SPECIFIED WAVELENGTH ##
    slabs = [
        cube.with_spectral_unit(u.km / u.s, 'optical', wl).spectral_slab(
            velocity_range[0] * u.km / u.s, velocity_range[1] * u.km / u.s)
        for wl in wavelength
    ]
    newcube_shape = (sum(s.shape[0] for s in slabs), ) + slabs[0].shape[1:]
    newcube_spaxis = np.concatenate([s.spectral_axis
                                     for s in slabs]).value * u.km / u.s
    sortvect = newcube_spaxis.argsort()
    sortspaxis = newcube_spaxis[sortvect]
    newcube = np.empty(newcube_shape)
    ind = 0
    for ii, slab in enumerate(slabs):
        data = slab.filled_data[:] / slab.sum(axis=0)
        newcube[ind:ind + data.shape[0], :, :] = data
        ind += data.shape[0]

    supercube = newcube[sortvect, :, :]
    pxarr = pyspeckit.units.SpectroscopicAxis(sortspaxis.value, unit='km/s')
    print pxarr
    pcube = pyspeckit.Cube(cube=supercube, xarr=pxarr, header=hd)
    pcube.fiteach(fittype='gaussian',
                  guesses=[1 / np.sqrt(np.pi), 5, 20.0],
                  errmap=np.ones(supercube.shape[1:]) / 100.,
                  multicore=3)
    ff = fits.PrimaryHDU(data=pcube.parcube[1], header=hd)
    ff.writeto(outfile, clobber=True)
示例#6
0
def load_model_fit(cube, filename, ncomp):
    # currently only loads ammonia multi-component model
    pcube = pyspeckit.Cube(cube=cube)

    # reigster fitter
    linename = 'oneone'
    import ammonia_multiv as ammv

    fitter = ammv.nh3_multi_v_model_generator(n_comp=ncomp,
                                              linenames=[linename])
    pcube.specfit.Registry.add_fitter('nh3_multi_v', fitter, fitter.npars)

    pcube.load_model_fit(filename, npars=fitter.npars, fittype='nh3_multi_v')
    gc.collect()
    return pcube
def get_subregion_pcube(cube303m, cube303, cube321, region):
    #scube = cube_merge_high.subcube_from_ds9region(pyregion.ShapeList([region]))
    scube303m = cube303m.subcube_from_ds9region(pyregion.ShapeList([region]))
    scube303 = cube303.subcube_from_ds9region(pyregion.ShapeList([region]))
    scube321 = cube321.subcube_from_ds9region(pyregion.ShapeList([region]))
    # TODO: get error map
    #pcube = pyspeckit.Cube(cube=scube)
    pcube303 = pyspeckit.Cube(cube=scube303)
    pcube303.xarr.refX = cube303.wcs.wcs.restfrq
    pcube303.xarr.refX_unit = 'Hz'
    pcube321 = pyspeckit.Cube(cube=scube321)
    pcube321.xarr.refX = cube321.wcs.wcs.restfrq
    pcube321.xarr.refX_unit = 'Hz'
    pcube = pyspeckit.CubeStack([
        pcube303,
        pcube321,
    ])
    pcube.specfit.Registry.add_fitter('h2co_simple',
                                      simple_fitter3,
                                      4,
                                      multisingle='multi')
    pcube.xarr.refX = cube303m.wcs.wcs.restfrq
    pcube.xarr.refX_unit = 'Hz'
    return pcube, scube303m
示例#8
0
def multiscale_fit_clouddn(center=(643 - 1, 164 - 1)):
    clouddn_slice = np.s_[:, center[1] - 16:center[1] + 16,
                          center[0] - 16:center[0] + 16]

    clouddn_cube = cube_merge_high[clouddn_slice]
    clouddn_pcube = pyspeckit.Cube(cube=clouddn_cube)
    clouddn_pcube.xarr.refX = clouddn_cube.wcs.wcs.restfrq

    return multiscale_fit(clouddn_pcube,
                          16,
                          16,
                          savedir='clouddn',
                          savepre='clouddn',
                          guesses=[0.1, 19, 8, 0.3, 0.9, 0.2],
                          offset_scale=0.4)
示例#9
0
def multiscale_fit_g1pt2_cool(center=(236, 95)):  # G1.23-0.08box
    g1pt2_cool_slice = np.s_[:, center[1] - 16:center[1] + 16,
                             center[0] - 16:center[0] + 16]

    g1pt2_cool_cube = cube_merge_high[g1pt2_cool_slice]
    g1pt2_cool_pcube = pyspeckit.Cube(cube=g1pt2_cool_cube)
    g1pt2_cool_pcube.xarr.refX = g1pt2_cool_cube.wcs.wcs.restfrq

    return multiscale_fit(g1pt2_cool_pcube,
                          16,
                          16,
                          savedir='g1.2',
                          savepre='g1.2_coolspot',
                          guesses=[0.1, 91, 13.6, 0.3, 0.9, 0.2],
                          offset_scale=0.4)
示例#10
0
def multiscale_fit_g08south_hot(center=(434, 63)):
    g08south_slice = np.s_[:, center[1] - 16:center[1] + 16,
                           center[0] - 16:center[0] + 16]

    g08south_cube = cube_merge_high[g08south_slice]
    g08south_pcube = pyspeckit.Cube(cube=g08south_cube)
    g08south_pcube.xarr.refX = g08south_cube.wcs.wcs.restfrq

    multiscale_fit(g08south_pcube,
                   16,
                   16,
                   savedir='g0.8_south',
                   savepre='g0.8_south_hotspot',
                   guesses=[0.5, 40.3, 7.9, 0.57, 0.5, 0.3],
                   offset_scale=0.4)
示例#11
0
def multiscale_fit_g08south_cool(center=(426, 36)):
    g08south_cool_slice = np.s_[:, center[1] - 16:center[1] + 16,
                                center[0] - 16:center[0] + 16]

    g08south_cool_cube = cube_merge_high[g08south_cool_slice]
    g08south_cool_pcube = pyspeckit.Cube(cube=g08south_cool_cube)
    g08south_cool_pcube.xarr.refX = g08south_cool_cube.wcs.wcs.restfrq

    multiscale_fit(g08south_cool_pcube,
                   16,
                   16,
                   savedir='g0.8_south',
                   savepre='g0.8_south_coolspot',
                   guesses=[0.5, 50.3, 10.6, 0.3, 0.9, 0.2] +
                   [0.3, 96.3, 3.6, 0.3, 0.9, 0.2],
                   offset_scale=0.4)
示例#12
0
def multiscale_fit_g1pt6(center=(53, 143)):
    g1pt6_slice = np.s_[:, center[1] - 16:center[1] + 16,
                        center[0] - 16:center[0] + 16]

    g1pt6_cube = cube_merge_high[g1pt6_slice]
    g1pt6_pcube = pyspeckit.Cube(cube=g1pt6_cube)
    g1pt6_pcube.xarr.refX = g1pt6_cube.wcs.wcs.restfrq

    return multiscale_fit(g1pt6_pcube,
                          16,
                          16,
                          savedir='g1.6',
                          savepre='g1.6_spot',
                          guesses=[0.1, 157, 8, 0.3, 0.9, 0.2] +
                          [0.1, 60, 9, 0.3, 0.9, 0.2],
                          offset_scale=0.4)
示例#13
0
def pyspeckit_fit_cube(cube, max_map, centroid_map, width_map, noisemap, lines,
                       vz):
    """
    This is experimental and doesn't really work: the idea here is to fit all
    lines in the cube simultaneously.
    """
    import pyspeckit

    vz = u.Quantity(vz, u.km / u.s)

    fcube = cube.with_spectral_unit(u.GHz)

    def inrange(x):
        return (x < fcube.spectral_extrema[1]
                and x > fcube.spectral_extrema[0])

    lines_in_cube = {
        linename: linedata
        for linename, linedata in lines.items()
        if inrange(linedata['frequency'] * (1 - vz / constants.c))
    }

    frequencies = sorted(linedata['frequency']
                         for linedata in lines_in_cube.values())

    line_guesses = [[
        max_map.value,
        ((1 - centroid_map / constants.c) * frq).to(u.GHz).value,
        ((width_map / constants.c) * frq).to(u.GHz).value
    ] for frq in frequencies]
    line_guesses = np.array([x for y in line_guesses for x in y])

    guesses = np.array([max_map.value, centroid_map.value, width_map.value])
    #vcube = cube.with_spectral_unit(u.km/u.s, velocity_convention='optical')
    pcube = pyspeckit.Cube(cube=fcube)
    pcube.mapplot.plane = max_map.value
    pcube.fiteach(guesses=guesses,
                  start_from_point=(150, 150),
                  errmap=noisemap.value)
示例#14
0
# it's barely worth it; cuts off 10% of pixels
f1 = all_lines['H2CO_303_202']*u.GHz
f2 = all_lines['H2CO_321_220']*u.GHz
h2co_cube_merge_high = cube_merge_high.spectral_slab(f1*(1-(150*u.km/u.s/constants.c)),
                                                     f2*(1+(100*u.km/u.s/constants.c)))
h2co_noise_cube = noise_spcube.spectral_slab(f1*(1-(150*u.km/u.s/constants.c)),
                                           f2*(1+(100*u.km/u.s/constants.c)))

h2co_cube_merge_high_sm = cube_merge_high_sm.spectral_slab(f1*(1-(150*u.km/u.s/constants.c)),
                                                           f2*(1+(100*u.km/u.s/constants.c)))
h2co_noise_cube_sm = noise_spcube_sm.spectral_slab(f1*(1-(150*u.km/u.s/constants.c)),
                                                 f2*(1+(100*u.km/u.s/constants.c)))


# Pyspeckit cube made from spectralcube
pcube_merge_high = pyspeckit.Cube(cube=h2co_cube_merge_high._data,
                                  errorcube=h2co_noise_cube._data,
                                  header=h2co_cube_merge_high.header,
                                  xarr=h2co_cube_merge_high.spectral_axis,
                                 )
pcube_merge_high.xarr.refX = 218.22219
pcube_merge_high.xarr.refX_unit = 'GHz'

pcube_merge_high_sm = pyspeckit.Cube(cube=h2co_cube_merge_high_sm._data,
                                  errorcube=h2co_noise_cube_sm._data,
                                  header=h2co_cube_merge_high_sm.header,
                                  xarr=h2co_cube_merge_high_sm.spectral_axis,
                                 )
pcube_merge_high_sm.xarr.refX = 218.22219
pcube_merge_high_sm.xarr.refX_unit = 'GHz'
示例#15
0
import os
import astropy.units as u

if not os.path.exists('n2hp_cube.fit'):
    import astropy.utils.data as aud
    from astropy.io import fits
    f = aud.download_file(
        'ftp://cdsarc.u-strasbg.fr/pub/cats/J/A%2BA/472/519/fits/opha_n2h.fit')
    with fits.open(f) as ff:
        ff[0].header['CUNIT3'] = 'm/s'
        for kw in ['CTYPE4', 'CRVAL4', 'CDELT4', 'CRPIX4']:
            del ff[0].header[kw]
        ff.writeto('n2hp_cube.fit')

# Load the spectral cube
spc = pyspeckit.Cube('n2hp_cube.fit')

# Register the fitter
# The N2H+ fitter is 'built-in' but is not registered by default; this example
# shows how to register a fitting procedure
# 'multi' indicates that it is possible to fit multiple components and a
# background will not automatically be fit 4 is the number of parameters in the
# model (excitation temperature, optical depth, line center, and line width)
spc.Registry.add_fitter('n2hp_vtau', pyspeckit.models.n2hp.n2hp_vtau_fitter, 4)

# Get a measurement of the error per pixel
errmap = spc.slice(20, 28, unit='km/s').cube.std(axis=0)

# A good way to write a cube fitter is to have it load from disk if the cube
# fit was completed successfully in the past
if os.path.exists('n2hp_fitted_parameters.fits'):
fit_dir = 'fit/'
# primary beam corrected file and in Kelvin units
file_in_K = data_dir + 'pNH2D.fits'

snr_min = 5
file_thick = fit_dir + 'pNH2D_fit_thick_par_snr{0}.fits'.format(snr_min)
file_thin = fit_dir + 'pNH2D_fit_thin_par_snr{0}.fits'.format(snr_min)
rms_file = data_dir + 'pNH2D_rms.fits'
SNR_file = data_dir + 'pNH2D_SNR.fits'
Tpeak_file = data_dir + 'pNH2D_Tpeak.fits'
mask_file = data_dir + 'pNH2D_mask.fits'

# rest-freq used in Harju et al. (2020) for ortho-NH2D
freq_line = 110.153599 * u.GHz

cube = pyspeckit.Cube(file_in_K)
cube.xarr.refX = freq_line
cube.xarr.velocity_convention = 'radio'
cube.xarr.convert_to_unit('km/s')

#
# source dependent parameters
#
# pixel to start fit and to make sample plot of the line fit
xmax = 269
ymax = 240
# velocity range with signal (of the main hf-component) to
# calculate moment maps
vmin = 3.4
vmax = 5.0
# default velocity used as guess in fit
示例#17
0
                               simple_fitter2)
from full_cubes import cube_merge_high
from masked_cubes import (cube303, cube303sm, cube303m, cube321m, cube303msm,
                          cube321msm, cube321, cube321sm)
from noise import (noise, noise_cube, sm_noise, cube303nm, cube303nmsm,
                   cube321nm, cube321nmsm)
import pyspeckit
from astrodendro import Dendrogram
from astropy.utils.console import ProgressBar
import paths
import pylab as pl

brick_slice = np.s_[:, 131:154, 710:740]

brick_cube = cube_merge_high[brick_slice]
brick_pcube = pyspeckit.Cube(cube=brick_cube)
brick_pcube.xarr.refX = brick_cube.wcs.wcs.restfrq

brick_pcube.specfit.Registry.add_fitter('h2co_simple',
                                        simple_fitter2,
                                        6,
                                        multisingle='multi')

b303m = cube303m[brick_slice]
m1 = b303m.moment1(axis=0).to(u.km / u.s)

# For radial multiscale fitting, see multiscale_fit.py


def do_pyspeck_fits_1comp():
    #guesses_simple = [1,25,5,0.5,0.7,1]
def hmm1_cubefit(vmin=3.4,
                 vmax=5.0,
                 tk_ave=10.,
                 do_plot=False,
                 snr_min=5.0,
                 multicore=1,
                 do_thin=False):
    """
    Fit NH3(1,1) and (2,2) cubes for H-MM1.
    It fits all pixels with SNR larger than requested. 
    Initial guess is based on moment maps and neighboring pixels. 
    The fitting can be done in parallel mode using several cores, 
    however, this is dangerous for large regions, where using a 
    good initial guess is important. 
    It stores the result in a FITS cube. 

    TODO:
    -convert FITS cube into several FITS files
    -Improve initial guess
    
    Parameters
    ----------
    vmin : numpy.float
        Minimum centroid velocity to plot, in km/s.
    vmax : numpy.float
        Maximum centroid velocity to plot, in km/s.
    tk_ave : numpy.float
        Mean kinetic temperature of the region, in K.
    do_plot : bool
        If True, then a map of the region to map is shown.
    snr_min : numpy.float
        Minimum signal to noise ratio of the spectrum to be fitted.
    multicore : int
        Numbers of cores to use for parallel processing. 
    """

    cube11sc = SpectralCube.read(OneOneFile)
    cube22sc = SpectralCube.read(TwoTwoFile)
    cube11_v = cube11sc.with_spectral_unit(u.km / u.s,
                                           velocity_convention='radio',
                                           rest_value=freq11)
    cube22_v = cube22sc.with_spectral_unit(u.km / u.s,
                                           velocity_convention='radio',
                                           rest_value=freq22)
    from pyspeckit.spectrum.units import SpectroscopicAxis
    spec11 = SpectroscopicAxis(cube11_v.spectral_axis,
                               refX=freq11,
                               velocity_convention='radio')
    spec22 = SpectroscopicAxis(cube22_v.spectral_axis,
                               refX=freq22,
                               velocity_convention='radio')

    errmap11 = fits.getdata(RMSFile_11)
    errmap22 = fits.getdata(RMSFile_22)
    errmap_K = errmap11  #[errmap11, errmap22]
    Tpeak11 = fits.getdata(OneOnePeak)

    moment1 = fits.getdata(OneOneMom1)
    moment2 = (fits.getdata(OneOneMom2))**0.5

    snr = cube11sc.filled_data[:].value / errmap11
    peaksnr = Tpeak11 / errmap11

    planemask = (peaksnr > snr_min)  # *(errmap11 < 0.15)
    planemask = remove_small_objects(planemask, min_size=40)
    planemask = opening(planemask, disk(1))
    #planemask = (peaksnr>20) * (errmap11 < 0.2)

    mask = (snr > 3) * planemask

    maskcube = cube11sc.with_mask(mask.astype(bool))
    maskcube = maskcube.with_spectral_unit(u.km / u.s,
                                           velocity_convention='radio')
    slab = maskcube.spectral_slab(vmax * u.km / u.s, vmin * u.km / u.s)
    w11 = slab.moment(order=0, axis=0).value
    peakloc = np.nanargmax(w11)
    ymax, xmax = np.unravel_index(peakloc, w11.shape)

    moment2[np.isnan(moment2)] = 0.2
    moment2[moment2 < 0.2] = 0.2

    ## Load FITS files
    cube11 = pyspeckit.Cube(OneOneFile, maskmap=planemask)
    cube22 = pyspeckit.Cube(TwoTwoFile, maskmap=planemask)
    # Stack files
    cubes = pyspeckit.CubeStack([cube11, cube22], maskmap=planemask)
    cubes.unit = "K"
    # Define initial guess
    guesses = np.zeros((6, ) + cubes.cube.shape[1:])
    moment1[moment1 < vmin] = vmin + 0.2
    moment1[moment1 > vmax] = vmax - 0.2
    guesses[0, :, :] = tk_ave  # Kinetic temperature
    guesses[1, :, :] = 7  # Excitation  Temp
    guesses[2, :, :] = 14.5  # log(column)
    guesses[
        3, :, :] = moment2  # Line width / 5 (the NH3 moment overestimates linewidth)
    guesses[4, :, :] = moment1  # Line centroid
    guesses[5, :, :] = 0.5  # F(ortho) - ortho NH3 fraction (fixed)
    if do_plot:
        import matplotlib.pyplot as plt
        plt.imshow(w11 * planemask, origin='lower')
        plt.show()
    print('start fit')
    cubes.specfit.Registry.add_fitter('cold_ammonia',
                                      ammonia.cold_ammonia_model(), 6)
    if do_thin:
        file_out = "{0}H-MM1_cold_parameter_maps_snr{1}_thin_v1.fits".format(
            fit_dir, snr_min)
    else:
        file_out = "{0}H-MM1_cold_parameter_maps_snr{1}_thick_v1.fits".format(
            fit_dir, snr_min)
    cubes.fiteach(fittype='cold_ammonia',
                  guesses=guesses,
                  integral=False,
                  verbose_level=3,
                  fixed=[do_thin, False, False, False, False, True],
                  signal_cut=2,
                  limitedmax=[True, False, False, False, True, True],
                  maxpars=[20, 15, 20, 0.4, vmax, 1],
                  limitedmin=[True, True, True, True, True, True],
                  minpars=[5, 2.8, 12.0, 0.05, vmin, 0],
                  start_from_point=(xmax, ymax),
                  use_neighbor_as_guess=True,
                  position_order=1 / peaksnr,
                  errmap=errmap_K,
                  multicore=multicore)
    # Store fits into FITS cube
    fitcubefile = fits.PrimaryHDU(data=np.concatenate(
        [cubes.parcube, cubes.errcube]),
                                  header=cubes.header)
    fitcubefile.header.set('PLANE1', 'TKIN')
    fitcubefile.header.set('PLANE2', 'TEX')
    fitcubefile.header.set('PLANE3', 'COLUMN')
    fitcubefile.header.set('PLANE4', 'SIGMA')
    fitcubefile.header.set('PLANE5', 'VELOCITY')
    fitcubefile.header.set('PLANE6', 'FORTHO')
    fitcubefile.header.set('PLANE7', 'eTKIN')
    fitcubefile.header.set('PLANE8', 'eTEX')
    fitcubefile.header.set('PLANE9', 'eCOLUMN')
    fitcubefile.header.set('PLANE10', 'eSIGMA')
    fitcubefile.header.set('PLANE11', 'eVELOCITY')
    fitcubefile.header.set('PLANE12', 'eFORTHO')
    fitcubefile.header.set('CDELT3', 1)
    fitcubefile.header.set('CTYPE3', 'FITPAR')
    fitcubefile.header.set('CRVAL3', 0)
    fitcubefile.header.set('CRPIX3', 1)
    fitcubefile.writeto(file_out, overwrite=True)
示例#19
0
def cube_fit(cubefilename,
             outfilename,
             errfilename=None,
             scale_keyword=None,
             vheight=False,
             verbose=False,
             signal_cut=3,
             verbose_level=2,
             clobber=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
    clobber: [ 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 = pyfits.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 = pyfits.open(cubefilename)
    # start replacing components of the pyfits 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
    f.writeto(outfilename, clobber=clobber)

    return sp
示例#20
0
import astropy
import pyspeckit
try:
    from astropy.io import fits as pyfits
except ImportError:
    import pyfits
import numpy as np

# Load the spectrum
sp = pyspeckit.Cube('region5_hcn_crop.fits')
errmap = pyfits.getdata('region5.hcn.errmap.fits')

# Register the fitter
# The N2H+ fitter is 'built-in' but is not registered by default; this example
# shows how to register a fitting procedure
# 'multi' indicates that it is possible to fit multiple components and a background will not automatically be fit
# 4 is the number of parameters in the model (excitation temperature, optical depth, line center, and line width)
sp.Registry.add_fitter('hcn_amp', pyspeckit.models.hcn.hcn_amp, 3)

# Run the fitter
sp.mapplot()

# use an individual spectrum selected semi-arbitrarily from the map to get an estimate of the error
# this method has been rendered obsolete - use the error map instead
#s = sp.get_spectrum(20,20)
#s.plotter()
#s.Registry = sp.Registry
#s.specfit.Registry = sp.Registry
#s.specfit(fittype='hcn_amp',guesses=[2.5,-5.6,1.5],show_components=True,debug=True,quiet=False)
#s.specfit(fittype='hcn_amp',guesses=[2.5,-5.6,1.5],show_components=True,debug=True,quiet=False)
#sp.error = s.specfit.errspec
示例#21
0
# set up CASA-like shortcuts
F=False; T=True

# Some optional parameters for the script
# (if False, it will try to load an already-stored version 
# of the file)
fitcube = True

# Mask out low S/N pixels (to speed things up)
mask = pyfits.getdata('hotclump_11_mask.fits')
mask = np.isfinite(mask) * (mask > 0)

# Load the data using a mask
# Then calibrate the data (the data we're loading in this case are in Janskys,
# but we want surface brightness in Kelvin for the fitting process)
cube11 = pyspeckit.Cube('hotclump_11.cube_r0.5.image.fits', maskmap=mask)
cube11.cube *= (13.6 * (300.0 /
    (pyspeckit.spectrum.models.ammonia.freq_dict['oneone']/1e9))**2 *
    1./cube11.header.get('BMAJ')/3600. * 1./cube11.header.get('BMIN')/3600. )
cube11.unit = "K"
cube22 = pyspeckit.Cube('hotclump_22.cube_r0.5_contsub.image.fits', maskmap=mask)
cube22.cube *= (13.6 * (300.0 /
        (pyspeckit.spectrum.models.ammonia.freq_dict['twotwo']/1e9))**2 *
        1./cube22.header.get('BMAJ')/3600. * 1./cube22.header.get('BMIN')/3600. )
cube22.unit = "K"
cube44 = pyspeckit.Cube('hotclump_44.cube_r0.5_contsub.image.fits', maskmap=mask)
cube44.cube *= (13.6 * (300.0 /
        (pyspeckit.spectrum.models.ammonia.freq_dict['fourfour']/1e9))**2 *
        1./cube44.header.get('BMAJ')/3600. * 1./cube44.header.get('BMIN')/3600. )
cube44.unit = "K"
示例#22
0
def cubefit_gen(cube,
                ncomp=2,
                paraname=None,
                modname=None,
                chisqname=None,
                guesses=None,
                errmap11name=None,
                multicore=None,
                mask_function=None,
                snr_min=3.0,
                linename="oneone",
                momedgetrim=True,
                saveguess=False,
                **kwargs):
    '''
    Perform n velocity component fit on the GAS ammonia 1-1 data.
    (This should be the function to call for all future codes if it has been proven to be reliable)
    # note: the method can probably be renamed to cubefit()

    Parameters
    ----------
    cube : str
        The file name of the ammonia 1-1 cube or a SpectralCube object
    ncomp : int
        The number of components one wish to fit. Default is 2
    paraname: str
        The output file name of the
    Returns
    -------
    pcube : 'pyspeckit.cubes.SpectralCube.Cube'
        Pyspeckit cube object containing both the fit and the original data cube
    '''

    if hasattr(cube, 'spectral_axis'):
        pcube = pyspeckit.Cube(cube=cube)

    else:
        cubename = cube
        cube = SpectralCube.read(cubename)
        pcube = pyspeckit.Cube(filename=cubename)

    pcube.unit = "K"

    # the following check on rest-frequency may not be necessarily for GAS, but better be safe than sorry
    # note: this assume the data cube has the right units
    if cube._wcs.wcs.restfrq == np.nan:
        # Specify the rest frequency not present
        cube = cube.with_spectral_unit(u.Hz,
                                       rest_value=freq_dict[linename] * u.Hz)
    cube = cube.with_spectral_unit(u.km / u.s, velocity_convention='radio')

    if pcube.wcs.wcs.restfrq == np.nan:
        # Specify the rest frequency not present
        pcube.xarr.refX = freq_dict[linename] * u.Hz
    pcube.xarr.velocity_convention = 'radio'

    # always register the fitter just in case different lines are used
    fitter = ammv.nh3_multi_v_model_generator(n_comp=ncomp,
                                              linenames=[linename])
    pcube.specfit.Registry.add_fitter('nh3_multi_v', fitter, fitter.npars)
    print "number of parameters is {0}".format(fitter.npars)
    print "the line to fit is {0}".format(linename)

    # Specify a width for the expected velocity range in the data
    #v_peak_hwidth = 3.0 # km/s (should be sufficient for GAS Orion, but may not be enough for KEYSTONE)
    v_peak_hwidth = 4.0  # km/s (should be sufficient for GAS Orion, but may not be enough for KEYSTONE)

    if errmap11name is not None:
        errmap11 = fits.getdata(errmap11name)
    else:
        # a quick way to estimate RMS as long as the noise dominates the spectrum by channels
        mask_finite = np.isfinite(cube._data)
        errmap11 = mad_std(cube._data[mask_finite], axis=0)
        print "median rms: {0}".format(np.nanmedian(errmap11))

    snr = cube.filled_data[:].value / errmap11
    peaksnr = np.nanmax(snr, axis=0)

    #the snr map will inetiabley be noisy, so a little smoothing
    kernel = Gaussian2DKernel(1)
    peaksnr = convolve(peaksnr, kernel)

    # trim the edges by 3 pixels to guess the location of the peak emission
    footprint_mask = np.any(np.isfinite(cube._data), axis=0)

    if np.logical_and(footprint_mask.size > 1000, momedgetrim):
        print "triming the edges to make moment maps"
        footprint_mask = binary_erosion(footprint_mask, disk(3))

    # the following function is copied directly from GAS
    def default_masking(snr, snr_min=5.0):
        planemask = (snr > snr_min)
        if planemask.size > 100:
            planemask = remove_small_objects(planemask, min_size=40)
            planemask = opening(planemask, disk(1))
        return (planemask)

    if 'maskmap' in kwargs:
        planemask = kwargs['maskmap']
    elif mask_function is None:
        planemask = default_masking(peaksnr, snr_min=snr_min)
    else:
        planemask = mask_function(peaksnr, snr_min=snr_min)

    print "planemask size: {0}, shape: {1}".format(planemask[planemask].size,
                                                   planemask.shape)

    # masking
    mask = np.isfinite(cube._data) * planemask * footprint_mask

    print "mask size: {0}, shape: {1}".format(mask[mask].size, mask.shape)

    maskcube = cube.with_mask(mask.astype(bool))
    maskcube = maskcube.with_spectral_unit(u.km / u.s,
                                           velocity_convention='radio')

    if guesses is not None:
        v_guess = guesses[::4]
        v_guess[v_guess == 0] = np.nan
    else:
        v_guess = np.nan

    if np.isfinite(v_guess).sum() > 0:
        v_guess = v_guess[np.isfinite(v_guess)]
        v_median = np.median(v_guess)
        print "The median of the user provided velocities is: {0}".format(
            v_median)
        m0, m1, m2 = main_hf_moments(maskcube,
                                     window_hwidth=v_peak_hwidth,
                                     v_atpeak=v_median)
    else:
        m0, m1, m2 = main_hf_moments(maskcube, window_hwidth=v_peak_hwidth)
        v_median = np.median(m1[np.isfinite(m1)])
        print "median velocity: {0}".format(v_median)

        if False:
            # save the moment maps for diagnostic purposes
            hdr_new = copy.deepcopy(pcube.header)
            hdr_new['CDELT3'] = 1
            hdr_new['CTYPE3'] = 'FITPAR'
            hdr_new['CRVAL3'] = 0
            hdr_new['CRPIX3'] = 1

            savename = "{0}_moments.fits".format(
                os.path.splitext(paraname)[0], "parameter_maps")
            fitcubefile = fits.PrimaryHDU(data=np.array([m0, m1, m2]),
                                          header=hdr_new)
            fitcubefile.writeto(savename, overwrite=True)

    # remove the nana values to allow np.nanargmax(m0) to operate smoothly
    m0[np.isnan(
        m0
    )] = 0.0  # I'm not sure if this is a good way to get around the sum vs nansum issue

    # define acceptable v range based on the provided or determined median velocity
    vmax = v_median + v_peak_hwidth
    vmin = v_median - v_peak_hwidth

    # find the location of the peak signal (to determine the first pixel to fit if nearest neighbour method is used)
    peakloc = np.nanargmax(m0)
    ymax, xmax = np.unravel_index(peakloc, m0.shape)

    # set the fit parameter limits (consistent with GAS DR1)
    Texmin = 3.0  # K; a more reasonable lower limit (5 K T_kin, 1e3 cm^-3 density, 1e13 cm^-2 column, 3km/s sigma)
    Texmax = 40  # K; DR1 T_k for Orion A is < 35 K. T_k = 40 at 1e5 cm^-3, 1e15 cm^-2, and 0.1 km/s yields Tex = 37K
    sigmin = 0.07  # km/s
    sigmax = 2.5  # km/s; for Larson's law, a 10pc cloud has sigma = 2.6 km/s
    taumax = 100.0  # a reasonable upper limit for GAS data. At 10K and 1e5 cm^-3 & 3e15 cm^-2 -> 70
    taumin = 0.2  # note: at 1e3 cm^-3, 1e13 cm^-2, 1 km/s linewidth, 40 K -> 0.15
    eps = 0.001  # a small perturbation that can be used in guesses

    # get the guesses based on moment maps
    # tex and tau guesses are chosen to reflect low density, diffusive gas that are likley to have low SNR
    gg = moment_guesses(m1, m2, ncomp, sigmin=sigmin, moment0=m0)

    if guesses is None:
        guesses = gg

    else:
        # fill in the blanks with moment guesses
        guesses[guesses == 0] = np.nan
        gmask = np.isfinite(guesses)
        guesses[~gmask] = gg[~gmask]

        # fill in the failed sigma guesses with moment guesses
        gmask = guesses[1::4] < sigmin
        guesses[1::4][gmask] = gg[1::4][gmask]

        print "user provided guesses accepted"

    # The guesses should be fine in the first case, but just in case, make sure the guesses are confined within the
    # appropriate limits
    guesses[::4][guesses[::4] > vmax] = vmax
    guesses[::4][guesses[::4] < vmin] = vmin
    guesses[1::4][guesses[1::4] > sigmax] = sigmax
    guesses[1::4][guesses[1::4] < sigmin] = sigmin + eps
    guesses[2::4][guesses[2::4] > Texmax] = Texmax
    guesses[2::4][guesses[2::4] < Texmin] = Texmin
    guesses[3::4][guesses[3::4] > taumax] = taumax
    guesses[3::4][guesses[3::4] < taumin] = taumin

    if saveguess:
        # save the guesses for diagnostic purposes
        hdr_new = copy.deepcopy(pcube.header)
        hdr_new['CDELT3'] = 1
        hdr_new['CTYPE3'] = 'FITPAR'
        hdr_new['CRVAL3'] = 0
        hdr_new['CRPIX3'] = 1

        savedir = "{0}/{1}".format(path.dirname(paraname), "guesses")

        try:
            os.makedirs(savedir)
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise

        savename = "{0}_guesses.fits".format(
            path.splitext(paraname)[0], "parameter_maps")
        savename = "{0}/{1}".format(savedir, path.basename(savename))

        fitcubefile = fits.PrimaryHDU(data=guesses, header=hdr_new)
        fitcubefile.writeto(savename, overwrite=True)

    # set some of the fiteach() inputs to that used in GAS DR1 reduction
    if not 'integral' in kwargs:
        kwargs['integral'] = False

    if not 'verbose_level' in kwargs:
        kwargs['verbose_level'] = 3

    if not 'signal_cut' in kwargs:
        kwargs['signal_cut'] = 2

    # Now fit the cube. (Note: the function inputs are consistent with GAS DR1 whenever possible)
    print('start fit')

    # use SNR masking if not provided
    if not 'maskmap' in kwargs:
        print "mask mask!"
        kwargs['maskmap'] = planemask * footprint_mask

    if np.sum(kwargs['maskmap']) < 1:
        print("[WARNING]: maskmap has no pixel, no fitting will be performed")
        return pcube
    elif np.sum(np.isfinite(guesses)) < 1:
        print("[WARNING]: guesses has no pixel, no fitting will be performed")
        return pcube

    pcube.fiteach(fittype='nh3_multi_v',
                  guesses=guesses,
                  start_from_point=(xmax, ymax),
                  use_neighbor_as_guess=False,
                  limitedmax=[True, True, True, True] * ncomp,
                  maxpars=[vmax, sigmax, Texmax, taumax] * ncomp,
                  limitedmin=[True, True, True, True] * ncomp,
                  minpars=[vmin, sigmin, Texmin, taumin] * ncomp,
                  multicore=multicore,
                  **kwargs)

    if paraname != None:
        save_pcube(pcube, paraname, ncomp=ncomp)

    if modname != None:
        model = SpectralCube(pcube.get_modelcube(),
                             pcube.wcs,
                             header=cube.header)
        model.write(modname, overwrite=True)

    if chisqname != None:
        chisq = get_chisq(cube, pcube.get_modelcube(), expand=20)
        chisqfile = fits.PrimaryHDU(data=chisq,
                                    header=cube.wcs.celestial.to_header())
        chisqfile.writeto(chisqname, overwrite=True)

    return pcube
示例#23
0
def get_multiV_models(paraname,
                      refcubename,
                      n_comp=2,
                      savename=None,
                      snrname=None,
                      rms=0.15,
                      rmspath=None,
                      linename="oneone"):
    '''
    Creates a fits file containing the model cubes of individual components stacked into a hypercube
    :param paraname:
    :param refcubename:
    :param n_comp:
    :param savename:
    :param snrname:
    :param rms:
    :param rmspath:
    :return:
    '''

    para, hdr = fits.getdata(paraname, header=True)

    pcube = pyspeckit.Cube(refcubename)
    xarr = pcube.xarr

    cubes = [pcube.cube.copy() for i in np.arange(n_comp)]
    cubes = np.array(cubes)
    cubes[:] = np.nan

    # remove the error components
    n_para = n_comp * 4
    para = para[:n_para]
    assert para.shape[0] == n_para

    yy, xx = np.indices(para.shape[1:])
    nanvals = np.any(~np.isfinite(para), axis=0)
    isvalid = np.any(para, axis=0) & ~nanvals
    valid_pixels = zip(xx[isvalid], yy[isvalid])

    def model_a_pixel(xy):
        x, y = int(xy[0]), int(xy[1])
        models = [
            ammonia._ammonia_spectrum(xarr.as_unit('GHz'),
                                      tex=tex,
                                      tau_dict={linename: tau},
                                      width=width,
                                      xoff_v=vel,
                                      fortho=0.0,
                                      line_names=[linename])
            for vel, width, tex, tau in zip(para[::4, y, x], para[1::4, y, x],
                                            para[2::4, y, x], para[3::4, y, x])
        ]
        cubes[:, :, y, x] = models

    for xy in ProgressBar(list(valid_pixels)):
        print int(xy[0]), int(xy[1])
        model_a_pixel(xy)

    if savename != None:
        f_name, f_extension = path.splitext(savename)
        for i, data in enumerate(cubes):
            fname = "{0}_v{1}_{2}".format(f_name, i, f_extension)
            model = SpectralCube(data, pcube.wcs, header=pcube.header)
            model.write(fname, overwrite=True)

    if snrname != None:
        # calculate the peak temperature
        Tpeak = np.array([np.nanmax(cube, axis=0) for cube in cubes])

        if rmspath is not None:
            rmsdata = fits.getdata(rmspath)
            if rmsdata.shape == Tpeak[0].shape:
                rms = rmsdata
            else:
                print "[WARNING]: The shape of the rms map ({0}) does not match the shape of the emission map {1}." \
                      " An uniform rms value of: {2} has been adopted instead".format(rmsdata.shape, Tpeak[0].shape, rms)

        snr = Tpeak / rms
        snrfile = fits.PrimaryHDU(data=snr, header=pcube.header)

        for i in np.arange(n_comp * 8) + 1:
            key = 'PLANE{0}'.format(i)
            if key in hdr:
                hdr.remove(key)

        snrfile.header.set('CDELT3', 1)
        snrfile.header.set('CTYPE3', 'FITPAR')
        snrfile.header.set('PLANE1', 'SNR_0')
        snrfile.header.set('PLANE2', 'SNR_1')
        snrfile.header.set('NAXIS3', n_comp * 8)
        snrfile.writeto(snrname, overwrite=True)

    return cubes
示例#24
0
import pyspeckit
from spectral_cube import SpectralCube
from astropy import units as u
import pylab as pl

cube11 = SpectralCube.read(filename='unpb_mosaic_11_trim.fits', allow_huge_operations=True)
cube11.allow_huge_operations=True
cube11 = cube11.to(u.K)
cube11 = cube11.with_spectral_unit(u.km/u.s, velocity_convention='radio')

n11cube = pyspeckit.Cube(cube = cube11)

cube22 = SpectralCube.read('unpb_mosaic_22_trim.fits', allow_huge_operations=True)
cube22.allow_huge_operations=True
cube22 = cube22.to(u.K)
cube22 = cube22.with_spectral_unit(u.km/u.s, velocity_convention='radio')

n22cube = pyspeckit.Cube(cube = cube22)

cube44 = SpectralCube.read('unpb_mosaic_44_trim.fits', allow_huge_operations=True)
cube44.allow_huge_operations=True
cube44 = cube44.to(u.K)
cube44 = cube44.with_spectral_unit(u.km/u.s, velocity_convention='radio')

n44cube = pyspeckit.Cube(cube = cube44)

cube55 = SpectralCube.read('unpb_mosaic_55_trim.fits', allow_huge_operations=True)
cube55.allow_huge_operations=True
cube55 = cube55.to(u.K)
cube55 = cube55.with_spectral_unit(u.km/u.s, velocity_convention='radio')
示例#25
0
def update_rest_moment0_2(region_name='L1688', file_extension='base_all_rebase3', threshold=0.0125, save_masked=False):
    """
    Function to update moment calculation based on centroid velocity from line fit.
    For a given line cube, we check which channels have flux in the model cube, 
    and then use those channels as the appropiate channels for integration.

    Based on code provided by Vlas Sokolov

    Parameters
    ----------
    region : str
        Name of region to re-calculate moment map
    file_extension : str
        filename extension
    threshold : float
        minimum threshold in model cube used to identify channels with emission
        Default is down to the machine precision, a better result could be 
        obtained with 0.0125
    save_masked : Boolean
        Keyword to store the masked cube used in the integrated intensity calculation.
        This is useful to 

    Usage: 
    import GAS
    GAS.PropertyMaps.update_rest_moment0_2(region_name='NGC1333', file_extension='DR1_rebase3', threshold=0.0125, save_masked=True)

    """
    # Add NH3 (3,3) to this list once change Gaussian fits to fit this line as well
    for line in ['HC5N','HC7N_21_20','HC7N_22_21','C2S']:
        fit_file='{0}/{0}_{1}_{2}_param_cube.fits'.format(region_name,line,file_extension)
        fit_model_file='{0}/{0}_{1}_{2}_gauss_cube.fits'.format(region_name,line,file_extension)
        file_in ='{0}/{0}_{1}_{2}.fits'.format(region_name,line,file_extension)
        file_out='{0}/{0}_{1}_{2}_mom0_QA.fits'.format(region_name,line,file_extension)
        file_rms='{0}/{0}_{1}_{2}_rms_QA.fits'.format(region_name,line,file_extension)
        file_rms_mom='{0}/{0}_{1}_{2}_mom0_sigma_QA.fits'.format(region_name,line,file_extension)
        file_temp='{0}/{0}_{1}_{2}_masked_temp.fits'.format(region_name,line,file_extension)
        # Load pyspeckit cube
        # Might be able to just load the Gaussian cube here.. 
        pycube = pyspeckit.Cube(file_in)
        pycube.load_model_fit( fit_file, npars=3, npeaks=1, fittype='gaussian')
        # If threshold is not defined, then use the machine accuracy
        if threshold == None:
            threshold=np.finfo(pycube.data.dtype).eps
        # Get model cube from pyspeckit. Is completely zero for Gaussian fits. Why? 
        #modelcube = pycube.get_modelcube()
        # Using output model file from the Gaussian fitter instead
        model = pyspeckit.Cube(fit_model_file)
        modelcube = model.cube
        # Use spectral cube to calculate integrated intensity maps
        cube_raw = SpectralCube.read(file_in)
        # in km/s not Hz
        cube = cube_raw.with_spectral_unit(u.km / u.s,velocity_convention='radio')
        vaxis=cube.spectral_axis
        dv=np.abs(vaxis[1]-vaxis[0])
        # define mask 
        mask3d = modelcube > threshold
        # What to do with pixels without signal
        # Calculate mean velocity and velocity dispersion
        vmap=pycube.parcube[1,:,:]
        sigma_map=pycube.parcube[2,:,:]
        vmean=np.nanmean(vmap[vmap != 0])*u.km/u.s
        sigma_v=( np.nanmedian(sigma_map[vmap != 0]))*u.km/u.s
        total_spc=np.sqrt( (vaxis-vmean)**2)/sigma_v < 3.0
        # 
        im_mask=np.sum(mask3d, axis=0)
        # Here checking for bad fits. Places where parameter uncertainties are zero or unreasonably low
        # Probably a more elegant way to do this! 
        # For Gaussian fits: parameters are [amp, vlsr, sigma]
        for ii in np.arange( im_mask.shape[1]):
            for jj in np.arange( im_mask.shape[0]):
                if ((im_mask[jj,ii] == 0) or (pycube.parcube[2,jj,ii] < 3*pycube.errcube[2,jj,ii]) or
                    (pycube.errcube[1,jj,ii] == 0) or (pycube.errcube[1,jj,ii] > 0.2)):
                    mask3d[:,jj,ii] = total_spc
        n_chan=np.sum(mask3d, axis=0)
        # create masked cube
        cube2 = cube.with_mask(mask3d)
        cube3 = cube.with_mask(~mask3d)
        #
        if save_masked:
            cube2.write( file_temp, overwrite=True)
        # calculate moment map
        moment_0 = cube2.moment(axis=0)
        moment_0.write( file_out, overwrite=True)
        rms=cube3.std(axis=0)
        rms.write( file_rms, overwrite=True)
示例#26
0
F = False
T = True

# Some optional parameters for the script
# (if False, it will try to load an already-stored version
# of the file)
fitcube = True

# Mask out low S/N pixels (to speed things up)
mask = pyfits.getdata('badpix_mask.fits')
mask = np.isfinite(mask) * (mask > 0)

# Load the data using a mask
# Then calibrate the data (the data we're loading in this case are in Janskys,
# but we want surface brightness in Kelvin for the fitting process)
cube11 = pyspeckit.Cube('unpb_mosaic_11.fits', maskmap=mask)
cube11.cube *= (
    13.6 * (300.0 /
            (pyspeckit.spectrum.models.ammonia.freq_dict['oneone'] / 1e9))**2 *
    1. / cube11.header.get('BMAJ') / 3600. * 1. / cube11.header.get('BMIN') /
    3600.)
cube11.unit = "K"
cube22 = pyspeckit.Cube('unpb_mosaic_22.fits', maskmap=mask)
cube22.cube *= (
    13.6 * (300.0 /
            (pyspeckit.spectrum.models.ammonia.freq_dict['twotwo'] / 1e9))**2 *
    1. / cube22.header.get('BMAJ') / 3600. * 1. / cube22.header.get('BMIN') /
    3600.)
cube22.unit = "K"
cube44 = pyspeckit.Cube('unpb_mosaic_44.fits', maskmap=mask)
cube44.cube *= (
示例#27
0
def update_NH3_moment0(region_name='L1688', file_extension='DR1_rebase3', threshold=0.0125, trim_edge=True, save_masked=False):
    """
    Function to update moment calculation based on centroid velocity from line fit.
    For a given NH3(1,1) cube, we check which channels have flux in the model cube, 
    and then use those channels as the appropiate channels for integration.

    Based on code provided by Vlas Sokolov

    Parameters
    ----------
    region : str
        Name of region to re-calculate moment map
    file_extension : str
        filename extension
    threshold : float
        minimum threshold in model cube used to identify channels with emission
        Default is down to the machine precision, a better result could be 
        obtained with 0.0125
    trim_edge : Boolean
        Keyword to trim noisy edges of output maps using disk erode 
    save_masked : Boolean
        Keyword to store the masked cube used in the integrated intensity calculation.
        This is useful to 

    Usage: 
    import GAS
    GAS.PropertyMaps.update_NH3_moment0(region_name='NGC1333', file_extension='DR1_rebase3', threshold=0.0125, save_masked=True)

    """
    fit_file='{0}/{0}_parameter_maps_{1}.fits'.format(region_name,file_extension)
    for line_i in ['11','22']:
        file_in ='{0}/{0}_NH3_{2}_{1}.fits'.format(region_name,file_extension,line_i)
        file_out='{0}/{0}_NH3_{2}_{1}_mom0_QA.fits'.format(region_name,file_extension,line_i)
        file_rms='{0}/{0}_NH3_{2}_{1}_rms_QA.fits'.format(region_name,file_extension,line_i)
        file_rms_mom='{0}/{0}_NH3_{2}_{1}_mom0_sigma_QA.fits'.format(region_name,file_extension,line_i)
        file_temp='{0}/{0}_NH3_{2}_{1}_masked_temp.fits'.format(region_name,file_extension,line_i)
        # Load pyspeckit cube
        pycube = pyspeckit.Cube(file_in)
        if 'FITTYPE' in fits.getheader(fit_file):
            # 'FITTYPE' is not present in old versions of the parameter files
            pycube.load_model_fit( fit_file, npars=6, npeaks=1)
        else:
    	    if not 'cold_ammonia' in pycube.specfit.Registry.multifitters:
                pycube.specfit.Registry.add_fitter('cold_ammonia',ammonia.cold_ammonia_model(),6)
            pycube.load_model_fit( fit_file, npars=6, npeaks=1, fittype='cold_ammonia')
        # If threshold is not defined, then use the machine accuracy
        if threshold == None:
            threshold=np.finfo(pycube.data.dtype).eps
        # Get model cube from pyspeckit, this take some time
        modelcube = pycube.get_modelcube()
        # Use spectral cube to calculate integrated intensity maps
        cube_raw = SpectralCube.read(file_in)
        # in km/s not Hz
        cube = cube_raw.with_spectral_unit(u.km / u.s,velocity_convention='radio')
        if trim_edge:
            cube = trim_edge_spectral_cube(cube)
        vaxis=cube.spectral_axis
        dv=np.abs(vaxis[1]-vaxis[0])
        # define mask 
        mask3d = modelcube > threshold
        # What to do with pixels without signal
        # Calculate mean velocity and velocity dispersion
        vmap=pycube.parcube[4,:,:]
        sigma_map=pycube.parcube[3,:,:]
        vmean=np.mean(vmap[vmap != 0])*u.km/u.s
        if line_i == '11':
            sigma_v=( np.median(sigma_map[vmap != 0]) + 0.15)*u.km/u.s
        else:
            sigma_v=( np.median(sigma_map[vmap != 0]))*u.km/u.s
        total_spc=np.sqrt( (vaxis-vmean)**2)/sigma_v < 3.0
        # 
        im_mask=np.sum(mask3d, axis=0)
        # Here checking for bad fits. Places where parameter uncertainties are zero or unreasonably low
        # Probably a more elegant way to do this! 
        for ii in np.arange( im_mask.shape[1]):
            for jj in np.arange( im_mask.shape[0]):
                if ((im_mask[jj,ii] == 0) or (pycube.parcube[3,jj,ii] < 3*pycube.errcube[3,jj,ii]) or
                    (pycube.errcube[4,jj,ii] == 0) or (pycube.errcube[1,jj,ii] < 0.01) or 
		    (pycube.parcube[0,jj,ii] == 5)):
                    mask3d[:,jj,ii] = total_spc
        n_chan=np.sum(mask3d, axis=0)
        # create masked cube
        cube2 = cube.with_mask(mask3d)
        cube3 = cube.with_mask(~mask3d)
        #
        if save_masked:
            cube2.write( file_temp, overwrite=True)
        # calculate moment map
        moment_0 = cube2.moment(axis=0)
        moment_0.write( file_out, overwrite=True)
        rms=cube3.std(axis=0)
        rms.write( file_rms, overwrite=True)
示例#28
0
import os
import astropy.units as u

if not os.path.exists('n2hp_cube.fit'):
    import astropy.utils.data as aud
    from astropy.io import fits
    f = aud.download_file(
        'ftp://cdsarc.u-strasbg.fr/pub/cats/J/A%2BA/472/519/fits/opha_n2h.fit')
    with fits.open(f) as ff:
        ff[0].header['CUNIT3'] = 'm/s'
        for kw in ['CTYPE4', 'CRVAL4', 'CDELT4', 'CRPIX4']:
            del ff[0].header[kw]
        ff.writeto('n2hp_cube.fit')

# Load the spectral cube cropped in the middle for efficiency
spc = pyspeckit.Cube('n2hp_cube.fit')[:, 25:28, 12:15]
# Set the velocity convention: in the future, this may be read directly from
# the file, but for now it cannot be.
spc.xarr.refX = 93176265000.0 * u.Hz
spc.xarr.velocity_convention = 'radio'
spc.xarr.convert_to_unit('km/s')

# Register the fitter
# The N2H+ fitter is 'built-in' but is not registered by default; this example
# shows how to register a fitting procedure
# 'multi' indicates that it is possible to fit multiple components and a
# background will not automatically be fit 4 is the number of parameters in the
# model (excitation temperature, optical depth, line center, and line width)
spc.Registry.add_fitter('n2hp_vtau', pyspeckit.models.n2hp.n2hp_vtau_fitter, 4)

# Get a measurement of the error per pixel
示例#29
0
guesses[0, :, :] = 58
guesses[1, :, :] = 26.9
guesses[2, :, :] = 0.010
guesses[3, :, :] = 1.5
guesses[4, :, :] = 31.4
guesses[5, :, :] = 0.010
guesses[6, :, :] = 1.5

negmask = mn < -0.005
guesses[2, negmask] = -0.1
guesses[5, negmask] = -0.1

#peak = scube.max(axis=0)
#mask = peak>0.005*peak.unit

pcube = pyspeckit.Cube(cube=scube)
parfilename = 'fitted_nh366_hf_emission.fits'
if os.path.exists(parfilename):
    pcube.load_model_fit(parfilename, 7, 1, 'hfonly')
else:
    pcube.fiteach(
        fittype='hfonly',
        guesses=guesses,
        limits=[(50, 70), (24, 29), (-10, 5), (0, 4), (29, 34), (-10, 5),
                (0, 4)],
        limitedmin=[True] * 7,
        limitedmax=[True] * 7,
        integral=False,
        errmap=errmap.value,
        signal_cut=0,
        #maskmap=mask,
示例#30
0
def cubefit(region='NGC1333', blorder=1, vmin=5, vmax=15, do_plot=False, 
            snr_min=5.0, multicore=1, file_extension=None, mask_function = None, gauss_fit=False):
    """
    Fit NH3(1,1) and (2,2) cubes for the requested region. 
    It fits all pixels with SNR larger than requested. 
    Initial guess is based on moment maps and neighboring pixels. 
    The fitting can be done in parallel mode using several cores, 
    however, this is dangerous for large regions, where using a 
    good initial guess is important. 
    It stores the result in a FITS cube. 

    TODO:
    -Improve initial guess
    
    Parameters
    ----------
    region : str
        Name of region to reduce
    blorder : int
        order of baseline removed
    vmin : numpy.float
        Minimum centroid velocity to plot, in km/s.
    vmax : numpy.float
        Maximum centroid velocity to plot, in km/s.
    do_plot : bool
        If True, then a map of the region to map is shown.
    snr_min : numpy.float
        Minimum signal to noise ratio of the spectrum to be fitted.
    multicore : int
        Numbers of cores to use for parallel processing.
    file_extension : str
        File extension of the input maps. Default is 'base#' where # is the 
        blorder parameter above.
    mask_function : fun
        function to create a custom made mask for analysis. Defaults to using 
        `default_masking`
    """
    if file_extension:
        root = file_extension
    else:
        # root = 'base{0}'.format(blorder)
        root = 'all'

    OneOneIntegrated = '{0}/{0}_NH3_11_{1}_mom0.fits'.format(region,root)
    OneOneFile = '{0}/{0}_NH3_11_{1}.fits'.format(region,root)
    RMSFile = '{0}/{0}_NH3_11_{1}_rms.fits'.format(region,root)
    TwoTwoFile = '{0}/{0}_NH3_22_{1}.fits'.format(region,root)
    ThreeThreeFile = '{0}/{0}_NH3_33_{1}.fits'.format(region,root)
        
    cube11sc = SpectralCube.read(OneOneFile)
    cube22sc = SpectralCube.read(TwoTwoFile)
    errmap11 = fits.getdata(RMSFile)
    rms = np.nanmedian(errmap11)

    snr = cube11sc.filled_data[:].value/errmap11
    peaksnr = np.max(snr,axis=0)
    if mask_function is None:
        planemask = default_masking(peaksnr,snr_min = snr_min)
    else:
        planemask = mask_function(peaksnr,snr_min = snr_min)
    
    #planemask = (peaksnr>20) * (errmap11 < 0.2)

    mask = (snr>3)*planemask
    maskcube = cube11sc.with_mask(mask.astype(bool))
    maskcube = maskcube.with_spectral_unit(u.km/u.s,velocity_convention='radio')
    slab = maskcube.spectral_slab( vmax*u.km/u.s, vmin*u.km/u.s)
    w11=slab.moment( order=0, axis=0).value
    peakloc = np.nanargmax(w11)
    ymax,xmax = np.unravel_index(peakloc,w11.shape)
    moment1 = slab.moment( order=1, axis=0).value
    moment2 = (slab.moment( order=2, axis=0).value)**0.5
    moment2[np.isnan(moment2)]=0.2
    moment2[moment2<0.2]=0.2
    cube11 = pyspeckit.Cube(OneOneFile,maskmap=planemask)
    cube11.unit="K"
    cube22 = pyspeckit.Cube(TwoTwoFile,maskmap=planemask)
    cube22.unit="K"
    #cube33 = pyspeckit.Cube(ThreeThreeFile,maskmap=planemask)
    #cube33.unit="K" # removed as long as we're not modeling OPR
    cubes = pyspeckit.CubeStack([cube11,cube22],maskmap=planemask)
    cubes.unit="K"
    guesses = np.zeros((6,)+cubes.cube.shape[1:])
    moment1[moment1<vmin] = vmin+0.2
    moment1[moment1>vmax] = vmax-0.2
    guesses[0,:,:] = 12                    # Kinetic temperature 
    guesses[1,:,:] = 3                     # Excitation  Temp
    guesses[2,:,:] = 14.5                  # log(column)
    guesses[3,:,:] = moment2  # Line width / 5 (the NH3 moment overestimates linewidth)               
    guesses[4,:,:] = moment1  # Line centroid              
    guesses[5,:,:] = 0.0                   # F(ortho) - ortho NH3 fraction (fixed)
    if do_plot:
        import matplotlib.pyplot as plt
        plt.imshow( w11, origin='lower',interpolation='nearest')
        plt.show()
    F=False
    T=True
    
    if not 'cold_ammonia' in cubes.specfit.Registry.multifitters:
        cubes.specfit.Registry.add_fitter('cold_ammonia',ammonia.cold_ammonia_model(),6)
        
    print('start fit')
    cubes.fiteach(fittype='cold_ammonia',  guesses=guesses,
                  integral=False, verbose_level=3, 
                  fixed=[F,F,F,F,F,T], signal_cut=2,
                  limitedmax=[F,F,T,F,T,T],
                  maxpars=[0,0,17.0,0,vmax,1],
                  limitedmin=[T,T,T,T,T,T],
                  minpars=[5,2.8,12.0,0.04,vmin,0],
                  start_from_point=(xmax,ymax),
                  use_neighbor_as_guess=True, 
                  position_order = 1/peaksnr,
                  errmap=errmap11, multicore=multicore)

    fitcubefile = fits.PrimaryHDU(data=np.concatenate([cubes.parcube,cubes.errcube]), header=cubes.header)
    fitcubefile.header.set('PLANE1','TKIN')
    fitcubefile.header.set('PLANE2','TEX')
    fitcubefile.header.set('PLANE3','COLUMN')
    fitcubefile.header.set('PLANE4','SIGMA')
    fitcubefile.header.set('PLANE5','VELOCITY')
    fitcubefile.header.set('PLANE6','FORTHO')
    fitcubefile.header.set('PLANE7','eTKIN')
    fitcubefile.header.set('PLANE8','eTEX')
    fitcubefile.header.set('PLANE9','eCOLUMN')
    fitcubefile.header.set('PLANE10','eSIGMA')
    fitcubefile.header.set('PLANE11','eVELOCITY')
    fitcubefile.header.set('PLANE12','eFORTHO')
    fitcubefile.header.set('CDELT3',1)
    fitcubefile.header.set('CTYPE3','FITPAR')
    fitcubefile.header.set('CRVAL3',0)
    fitcubefile.header.set('CRPIX3',1)
    fitcubefile.writeto("{0}/{0}_parameter_maps_{1}.fits".format(region,root),clobber=True)

    if gauss_fit==True:
	molecules = ['C2S', 'HC7N_22_21', 'HC7N_21_20', 'HC5N']
	for i in molecules:
        	gauss_fitter(region=region, mol=i, vmin=vmin, vmax=vmax, snr_min=snr_min, multicore=multicore, file_extension=file_extension)