Beispiel #1
0
def spec_curve_fit(bin_num, map_name = map_column_dens):
    # following loop has not good style. One should build in some break statements or error messages
    # if files repeatedly appear in loop.
    for one_file in files:
        if 'NH3_11' in one_file:
            file_name_NH3_11 = one_file
        if 'NH3_22' in one_file:
            file_name_NH3_22 = one_file
        if 'NH3_33' in one_file:
            file_name_NH3_33 = one_file
        
    y, x, med = binning(bin_width, bin_num)

    s11, _, offset_velocity11, sp_av11 = averaging_over_dopplervel(file_name_NH3_11, y, x)
    s22, _, offset_velocity22, sp_av22 = averaging_over_dopplervel(file_name_NH3_22, y, x)
    s33, _, offset_velocity33, sp_av33 = averaging_over_dopplervel(file_name_NH3_33, y, x)
    
    xarr11 = SpectroscopicAxis(offset_velocity11*u.km/u.s, velocity_convention='radio',
                           refX=freq_dict['oneone']).as_unit(u.GHz)
    xarr22 = SpectroscopicAxis(offset_velocity22*u.km/u.s, velocity_convention='radio',
                           refX=freq_dict['twotwo']).as_unit(u.GHz)
    xarr33 = SpectroscopicAxis(offset_velocity33*u.km/u.s, velocity_convention='radio',
                           refX=freq_dict['threethree']).as_unit(u.GHz)
        
    sp11 = psk.Spectrum(data=s11, xarr=xarr11, xarrkwargs={'unit':'km/s'},unit='K')
    sp22 = psk.Spectrum(data=s22, xarr=xarr22, xarrkwargs={'unit':'km/s'},unit='K')
    sp33 = psk.Spectrum(data=s33, xarr=xarr33, xarrkwargs={'unit':'km/s'},unit='K')
    
    # This joins all the spectra together into one object.
    allspec = psk.Spectra([sp11,sp22,sp33])
    allspec.xarr.as_unit('Hz',velocity_convention='radio')
    # This add the cold_ammonia model to the list of things we can use for fitting
    allspec.specfit.Registry.add_fitter('cold_ammonia',ammonia.cold_ammonia_model(),6)
    # This does the fit.  The values of the guess are 
    # Kinetic Temperature (usually about 15 to 25 K)
    # Excitation Temperature (between 2.73 K and the excitation temperature)
    # Log Column Density of ammonia
    # Line width (~1 km/s)
    # Offset velocity (you will usually use 0 instead of 8.5)
    # Ortho fraction (leave at 0)
    allspec.specfit(fittype='cold_ammonia',guesses=[23,5,13.1,1,0,0])
    
    # You can make a plot here.
    fig = plt.figure()
    allspec.plotter()
    allspec.specfit.plot_fit(lw=1, components=True)
    plt.xlim((23.692,23.697))
#     plt.xlim((23.72,23.725))
#     plt.xlim((23.8692, 23.8708))
#     plt.savefig("OrionA:pyspeckit_fit_bin_width=%rthis_bin=%r.ps" %(bin_width, this_bin))
    plt.savefig("Map=%r:bin_num=%r_pyspeckit_fit_NH3_11TEST.ps"%(map_name, bin_num))
    plt.show()
    
    # returns the values of the fitted parameters: T_K, T_ex, N, sigma, v, F_0
    return allspec.specfit.parinfo, allspec.specfit.parinfo.errors
Beispiel #2
0
def nh3_spectrum(pars, kms_vals, lines=['oneone', 'twotwo'], snr=5,
                 snr_line='oneone', seed=None):
    # building a spectroscopic axis
    xarr_dict = {}
    for line in lines:
        xarr_dict[line] = pyspeckit.units.SpectroscopicAxis(kms_vals, 'km/s')
        xarr_dict[line].refX = ammonia_constants.freq_dict[line] * u.Hz
        xarr_dict[line].velocity_convention = 'radio'

        # TODO: bug... see if #182 fixes it
        #xarr_dict[line].convert_to_unit('GHz')

        xarr_dict[line] = xarr_dict[line].as_unit('GHz')

    xarr = SpectroscopicAxes([xarr_dict[line] for line in lines])
    xarr.refX = ammonia_constants.freq_dict['oneone'] * u.Hz
    xarr.velocity_convention = 'radio'
    xarr.convert_to_unit('km/s')

    # making synthetic spectra
    sp = pyspeckit.Spectrum(data=np.zeros_like(xarr.value), xarr=xarr)
    sp.Registry.add_fitter('cold_ammonia', ammonia.cold_ammonia_model(), 6)
    sp.specfit.fitter = sp.specfit.Registry.multifitters['cold_ammonia']
    sp.specfit.fittype = 'cold_ammonia'
    signal = sp.specfit.get_full_model(pars=pars)
    sp.data = signal
    line_mask = xarr_dict[snr_line].min(), xarr_dict[snr_line].max()  # GHz
    std_noise = sp.slice(*line_mask).data.max() / snr
    np.random.seed(seed=0)
    try:
        noise = np.random.normal(0, std_noise, sp.xarr.size)
    except ValueError:  # ValueError("scale <= 0")
        noise = 0
    sp.data += noise
    sp.error = np.zeros_like(sp.data) + std_noise

    return sp
Beispiel #3
0
def update_NH3_moment0(region_name='L1688', file_extension='_DR1', threshold=None, 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
    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', 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}_base{1}.fits'.format(region_name,file_extension,line_i)
        file_out='{0}/{0}_NH3_{2}_base{1}_mom0_QA.fits'.format(region_name,file_extension,line_i)
        file_rms='{0}/{0}_NH3_{2}_base{1}_rms_QA.fits'.format(region_name,file_extension,line_i)
        file_rms_mom='{0}/{0}_NH3_{2}_base{1}_mom0_sigma_QA.fits'.format(region_name,file_extension,line_i)
        file_temp='{0}/{0}_NH3_{2}_base{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')
        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.mean(sigma_map[vmap != 0]) + 0.15)*u.km/u.s
        else:
            sigma_v=( np.mean(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)
        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]):
                    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)
        mom_0_rms=rms * dv * np.sqrt(n_chan)
        mom_0_rms.write( file_rms_mom, overwrite=True)
Beispiel #4
0
    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)
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)
Beispiel #6
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)
Beispiel #7
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)
line = 'NH3_11'
OneOneFile = 'nh3_data/{0}_NH3_11_{1}_trim.fits'.format(region, file_extension)
TwoTwoFile = 'nh3_data/{0}_NH3_22_{1}_trim.fits'.format(region, file_extension)
FitFile = 'propertyMaps/{0}_parameter_maps_{1}_flag.fits'.format(
    region, file_extension)

cube11 = pyspeckit.Cube(OneOneFile)
cube11.unit = 'K'
cube22 = pyspeckit.Cube(TwoTwoFile)
cube22.unit = 'K'
cubes = pyspeckit.CubeStack([cube11, cube22])
cubes.unit = 'K'

if not 'cold_ammonia' in cubes.specfit.Registry.multifitters:
    cubes.specfit.Registry.add_fitter('cold_ammonia',
                                      ammonia.cold_ammonia_model(), 6)

#cubes.load_model_fit(FitFile,6,npeaks=1,fittype='cold_ammonia')
#cubes.specfit.parinfo[5]['fixed'] = True

pix_coords = [54, 184]

sp = cubes.get_spectrum(pix_coords[0], pix_coords[1])
F = False
T = True
sp.specfit(fittype='cold_ammonia',
           guesses=[10, 3, 14, 0.3, 3.33, 0],
           fixed=[F, F, F, F, F, T])
#sp.specfit(fittype='cold_ammonia',guesses=[8,3,14,0.24,3.33,0],fixed=[F,F,F,F,F,T])

# Set up plot parameters
Beispiel #9
0
def spec_curve_fit(bin_num, map_name=map_column_dens):
    # following loop has not good style. One should build in some break statements or error messages
    # if files repeatedly appear in loop.
    for one_file in files:
        if 'NH3_11' in one_file:
            file_name_NH3_11 = one_file
        if 'NH3_22' in one_file:
            file_name_NH3_22 = one_file
        if 'NH3_33' in one_file:
            file_name_NH3_33 = one_file

    y, x, med = binning(bin_width, bin_num)

    s11, _, offset_velocity11, sp_av11 = averaging_over_dopplervel(
        file_name_NH3_11, y, x)
    s22, _, offset_velocity22, sp_av22 = averaging_over_dopplervel(
        file_name_NH3_22, y, x)
    s33, _, offset_velocity33, sp_av33 = averaging_over_dopplervel(
        file_name_NH3_33, y, x)

    xarr11 = SpectroscopicAxis(offset_velocity11 * u.km / u.s,
                               velocity_convention='radio',
                               refX=freq_dict['oneone']).as_unit(u.GHz)
    xarr22 = SpectroscopicAxis(offset_velocity22 * u.km / u.s,
                               velocity_convention='radio',
                               refX=freq_dict['twotwo']).as_unit(u.GHz)
    xarr33 = SpectroscopicAxis(offset_velocity33 * u.km / u.s,
                               velocity_convention='radio',
                               refX=freq_dict['threethree']).as_unit(u.GHz)

    sp11 = psk.Spectrum(data=s11,
                        xarr=xarr11,
                        xarrkwargs={'unit': 'km/s'},
                        unit='K')
    sp22 = psk.Spectrum(data=s22,
                        xarr=xarr22,
                        xarrkwargs={'unit': 'km/s'},
                        unit='K')
    sp33 = psk.Spectrum(data=s33,
                        xarr=xarr33,
                        xarrkwargs={'unit': 'km/s'},
                        unit='K')

    # This joins all the spectra together into one object.
    allspec = psk.Spectra([sp11, sp22, sp33])
    allspec.xarr.as_unit('Hz', velocity_convention='radio')
    # This add the cold_ammonia model to the list of things we can use for fitting
    allspec.specfit.Registry.add_fitter('cold_ammonia',
                                        ammonia.cold_ammonia_model(), 6)
    # This does the fit.  The values of the guess are
    # Kinetic Temperature (usually about 15 to 25 K)
    # Excitation Temperature (between 2.73 K and the excitation temperature)
    # Log Column Density of ammonia
    # Line width (~1 km/s)
    # Offset velocity (you will usually use 0 instead of 8.5)
    # Ortho fraction (leave at 0)
    allspec.specfit(fittype='cold_ammonia', guesses=[23, 5, 13.1, 1, 0, 0])

    # You can make a plot here.
    fig = plt.figure()
    allspec.plotter()
    allspec.specfit.plot_fit(lw=1, components=True)
    plt.xlim((23.692, 23.697))
    #     plt.xlim((23.72,23.725))
    #     plt.xlim((23.8692, 23.8708))
    #     plt.savefig("OrionA:pyspeckit_fit_bin_width=%rthis_bin=%r.ps" %(bin_width, this_bin))
    plt.savefig("Map=%r:bin_num=%r_pyspeckit_fit_NH3_11TEST.ps" %
                (map_name, bin_num))
    plt.show()

    # returns the values of the fitted parameters: T_K, T_ex, N, sigma, v, F_0
    return allspec.specfit.parinfo, allspec.specfit.parinfo.errors
Beispiel #10
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):
    """
    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)

    OneOneIntegrated = '{0}/{0}_NH3_11_base{1}_mom0.fits'.format(region,root)
    OneOneFile = '{0}/{0}_NH3_11_base{1}.fits'.format(region,root)
    RMSFile = '{0}/{0}_NH3_11_base{1}_rms.fits'.format(region,root)
    TwoTwoFile = '{0}/{0}_NH3_22_base{1}.fits'.format(region,root)
    ThreeThreeFile = '{0}/{0}_NH3_33_base{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.update('PLANE1','TKIN')
    fitcubefile.header.update('PLANE2','TEX')
    fitcubefile.header.update('PLANE3','COLUMN')
    fitcubefile.header.update('PLANE4','SIGMA')
    fitcubefile.header.update('PLANE5','VELOCITY')
    fitcubefile.header.update('PLANE6','FORTHO')
    fitcubefile.header.update('PLANE7','eTKIN')
    fitcubefile.header.update('PLANE8','eTEX')
    fitcubefile.header.update('PLANE9','eCOLUMN')
    fitcubefile.header.update('PLANE10','eSIGMA')
    fitcubefile.header.update('PLANE11','eVELOCITY')
    fitcubefile.header.update('PLANE12','eFORTHO')
    fitcubefile.header.update('CDELT3',1)
    fitcubefile.header.update('CTYPE3','FITPAR')
    fitcubefile.header.update('CRVAL3',0)
    fitcubefile.header.update('CRPIX3',1)
    fitcubefile.writeto("{0}/{0}_parameter_maps_{1}.fits".format(region,root),clobber=True)