import os from hf_only_model import hfonly_66_fixed_fitter, hfonly_fitter, sixsix_movinghf_fitter from spectral_cube import SpectralCube from astropy import units as u import numpy as np import pyspeckit pyspeckit.fitters.default_Registry.add_fitter('hfonly', hfonly_fitter(), 7) pyspeckit.fitters.default_Registry.add_fitter('hfonly66', hfonly_66_fixed_fitter(), 4) pyspeckit.fitters.default_Registry.add_fitter('sixsix_movinghf', sixsix_movinghf_fitter(), 5) cube = SpectralCube.read( '/Volumes/passport/W51-GODDI/W51e2_66_baselined-sc-pb.cube.image.fits') scube = cube[:, 230:307, 205:270] errmap = scube.spectral_slab(-20 * u.km / u.s, 10 * u.km / u.s).std(axis=0) mn = scube.min(axis=0).value guesses = np.empty((7, scube.shape[1], scube.shape[2])) 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
def fit_highj_nh3_absorption(j=6, j2=6, object='w51e2-tot', headerfile='../W51-25GHzcont.map.image.fits', savepath='.', fntemplate='spec-{object}-{j}{j2}-pb.txt', background_tb=4.2e3): """ Fit absorption lines of high-J NH3 """ linename = ammonia_constants.num_to_name[j] * 2 sp, spK, mean_error, mean_error_k = load_spectrum(j=j, object=object, fntemplate=fntemplate) # create our ammonia fitter from the ammonia model that allows Tau as the # variable (instead of kinetic temperature) # the model comes in a few varieties: we've selected the one that assumes # there *is* a background, but we're fitting the continuum-subtracted # spectrum, so this one will accept the background as an input parameter amf = ammonia_hf.nh3_vtau[linename].background_contsub_fitter spK.specfit.Registry.add_fitter('ammonia_bg', amf, 5) sp.plotter() # Fit each component with a gaussian to determine the offsets between components sp.specfit(fittype='gaussian', guesses=[-0.15, 25, 3, -0.15, 32, 3, -0.30, 58, 6, -0.15, 84, 3, -0.15, 90, 3], quiet=True) # Store the fitted velocities and frequencies in convenient variables center = sp.specfit.parinfo[7].value voffs = u.Quantity([(((x-center)*u.km/u.s)) for x in sp.specfit.parinfo.values[1::3]]) foffs = u.Quantity([((((x - center)*u.km/u.s) / constants.c) * sp.xarr.refX).to(u.MHz) for x in sp.specfit.parinfo.values[1::3]]) print("Velocity Offsets: ",voffs) print("Frequency Offsets: ",foffs) models = (pyspeckit.spectrum.models.ammonia_constants.voff_lines_dict[linename][:3] + pyspeckit.spectrum.models.ammonia_constants.voff_lines_dict[linename][-2:]) dfoffs = u.Quantity([(((x-center-m)*u.km/u.s)) for x,m in zip(sp.specfit.parinfo.values[1::3], models[::-1])]) print("Difference between observed and modeled offsets: ",dfoffs) # plot the fits & residuals sp.specfit.plotresiduals(axis=sp.plotter.axis, clear=False, yoffset=sp.data.min()*1.2, label=False) sp.plotter.axis.set_ylim(sp.data.min()*1.2 - 3*mean_error + sp.specfit.residuals.min(), sp.data.max()*1.2 + 3*mean_error) sp.plotter.savefig(os.path.join(savepath, "{object}_nh3_{j}{j2}_eachcomponent.png".format(j=j, j2=j2, object=object))) T = True F = False #parnames=['Tbackground','Tex','tau','center','width'], # input guesses. background_tb is fixed parinfo = amf.make_parinfo(params=[background_tb, 100, 2.5, 58, 0.5], fixed=[T,F,F,F,F],) parinfo.TBACKGROUND0.limited = (False,False) parinfo.TEX0.mpmaxstep=1000 print("DEBUG CHECK: Is parinfo set correctly? (should have background=fixed)\n",parinfo) # do the fits on the brightness temperature spectrum now (with ammonia model) # for the first fit, exclude the main line and fit only the hyperfines spK.plotter() spK.specfit.selectregion(exclude=[40,70], highlight=True) spK.specfit(fittype='ammonia_bg', parinfo=parinfo, #quiet=False, shh=False, verbose=True, veryverbose=False, reset_selection=False) spK.specfit.plot_fit() spK.specfit.plotresiduals(axis=spK.plotter.axis, clear=False, yoffset=spK.data.min()*1.2, label=False) spK.plotter.axis.set_ylim(spK.data.min()*1.2 - 3*mean_error_k + spK.specfit.residuals.min(), spK.data.max()*1.2 + 3*mean_error_k) spK.plotter.savefig("{object}_nh3_{j}{j2}_hyperfineonly.png".format(j=j, j2=j2, object=object)) # second try: fit the main line and the hyperfines simultaneously spK.plotter() spK.specfit(fittype='ammonia_bg', parinfo=parinfo, #quiet=False, shh=False, verbose=True, veryverbose=False, reset_selection=True) spK.specfit.plotresiduals(axis=spK.plotter.axis, clear=False, yoffset=spK.data.min()*1.2, label=False) spK.plotter.axis.set_ylim(spK.data.min()*1.2 - 3*mean_error_k + spK.specfit.residuals.min(), spK.data.max()*1.2 + 3*mean_error_k) spK.plotter.savefig("{object}_nh3_{j}{j2}_fitwhole.png".format(j=j, j2=j2, object=object)) # third try: all lines, but with two components parinfo = amf.make_parinfo(params=[background_tb, 200, 2.5, 58, 1.35, background_tb, 200, 2.5, 59, 0.5,], fixed=[T,F,F,F,F,]*2, npeaks=2) parinfo.TBACKGROUND0.limited = (False,False) parinfo.TBACKGROUND1.limited = (False,False) parinfo.TEX0.mpmaxstep=1000 parinfo.TEX1.mpmaxstep=1000 print("DEBUG CHECK: Is parinfo set correctly? (should have background=fixed and two sets of pars)\n",parinfo) spK.plotter() spK.specfit(fittype='ammonia_bg', parinfo=parinfo, #verbose=True, quiet=False, shh=False, veryverbose=False, reset_selection=True) spK.specfit.plotresiduals(axis=spK.plotter.axis, clear=False, yoffset=spK.data.min()*1.2, label=False) spK.plotter.axis.set_ylim(spK.data.min()*1.2 - 3*mean_error_k + spK.specfit.residuals.min(), spK.data.max()*1.2 + 3*mean_error_k) spK.plotter.axis.set_xlim(-30,200) spK.plotter.savefig("{object}_nh3_{j}{j2}_fitwhole_twocomp.png".format(j=j, j2=j2, object=object)) pl.draw() pl.show() # TODO: refit with NH3 hyperfine model with velocity offsets and linewidths free # ??? optical depth reliable ??? # examine Goddi 2015 on NGC 7538 # -> column density (probably OK using simple LTE) # -> rotational temperature? spK.specfit.Registry.add_fitter('sixsix_movinghf', sixsix_movinghf_fitter(), 5) spK.specfit(fittype='sixsix_movinghf', guesses=[58, 30, 26.9, 31.2, 2]) spK.specfit.plotresiduals(axis=spK.plotter.axis, clear=False, yoffset=spK.data.min()*1.2, label=False) spK.plotter.axis.set_ylim(spK.data.min()*1.2 - 3*mean_error_k + spK.specfit.residuals.min(), spK.data.max()*1.2 + 3*mean_error_k) spK.plotter.axis.set_xlim(-30,200) spK.plotter.savefig("{object}_nh3_{j}{j2}_fitwhole_movinghf.png".format(j=j, j2=j2, object=object)) return sp, spK, (center, voffs, foffs, dfoffs)
mlpi6e2w = sp6e2w.specfit.parinfo mlpi7e2w = sp7e2w.specfit.parinfo mlpi9e2w = sp9e2w.specfit.parinfo mlpi10e2w = sp9e2w.specfit.parinfo mlpi13e2w = sp9e2w.specfit.parinfo print >>outf, "gaussian 6-6 peak={0} +/- {1}, fwhm={2} +/- {3}, integral={4} +/- {5}, center={6} +/- {7}".format(*(tbl_vals_gaussian(sp6e2w.specfit.parinfo))) print >>outf, "gaussian 7-7 peak={0} +/- {1}, fwhm={2} +/- {3}, integral={4} +/- {5}, center={6} +/- {7}".format(*(tbl_vals_gaussian(sp7e2w.specfit.parinfo))) print >>outf, "gaussian 9-9 peak={0} +/- {1}, fwhm={2} +/- {3}, integral={4} +/- {5}, center={6} +/- {7}".format(*(tbl_vals_gaussian(sp9e2w.specfit.parinfo))) print >>outf, "gaussian 10-10 peak={0} +/- {1}, fwhm={2} +/- {3}, integral={4} +/- {5}, center={6} +/- {7}".format(*(tbl_vals_gaussian(sp10e2w.specfit.parinfo))) print >>outf, "gaussian 13-13 peak={0} +/- {1}, fwhm={2} +/- {3}, integral={4} +/- {5}, center={6} +/- {7}".format(*(tbl_vals_gaussian(sp13e2w.specfit.parinfo))) # e2e aka e2east sp6e2e,spK6e2e,_,_ = goddi_nh3_fits.load_spectrum(6, object='w51e2e', headerfile='/Users/adam/work/w51/goddi/W51-25GHzcont.map.image.fits') sp6e2e.specfit.Registry.add_fitter('hfonly',hfonly_fitter(),7) spK6e2e.specfit.Registry.add_fitter('sixsix',sixsix_movinghf_fitter(),7) sp7e2e,spK7e2e,_,_ = goddi_nh3_fits.load_spectrum(7, object='w51e2e', headerfile='/Users/adam/work/w51/goddi/W51-25GHzcont.map.image.fits') sp7e2e.specfit.Registry.add_fitter('hfonly',hfonly_fitter(),7) sp9e2e,spK9e2e,_,_ = goddi_nh3_fits.load_spectrum(9, object='w51e2e', headerfile='/Users/adam/work/w51/goddi/W51-27GHzcont.map.image.fits') sp9e2e.specfit.Registry.add_fitter('hfonly',hfonly_fitter(),7) sp10e2e,spK10e2e,_,_ = goddi_nh3_fits.load_spectrum(10, object='w51e2e', headerfile='/Users/adam/work/w51/goddi/W51-27GHzcont.map.image.fits') sp10e2e.specfit.Registry.add_fitter('hfonly',hfonly_fitter(),7) sp13e2e,spK13e2e,_,_ = goddi_nh3_fits.load_spectrum(13, object='w51e2e', headerfile='/Users/adam/work/w51/goddi/W51-27GHzcont.map.image.fits') sp13e2e.specfit.Registry.add_fitter('hfonly',hfonly_fitter(),7) sp6e2e.plotter() spK6e2e.plotter() sp7e2e.plotter() sp9e2e.plotter() # sp6e2e might be optically thick (in hyperfines, in emission!) sp6e2e.specfit(fittype='hfonly', guesses=[58, 26.9, 0.02, 2.0, 31.4, 0.02, 2.0], fixed=[F,T,F,F,T,F,F], tied=tied)
return spectra,tbl if __name__ == "__main__": spectra,tbl = fit_all() print(tbl) fig = pl.figure(13) fig.clf() T=True F=False sp = spectra['w51e2-core_66'][1] mean_error = sp.data[-20:-2].std() sp.plotter.figure = fig sp.plotter.axis = pl.subplot(2,1,1) sp.plotter() sp.specfit.Registry.add_fitter('sixsix_movinghf', sixsix_movinghf_fitter(), 7) sp.specfit(fittype='sixsix_movinghf', guesses=[58, 83, 26.9, 31.2, 2, 1800, 8200], fixed=[F,F,F,F,F,T,T], annotate=False) sp.plotter.axis.set_xticklabels([]) sp.specfit.plotresiduals(axis=sp.plotter.axis, clear=False, yoffset=sp.data.min()*1.3, label=False) sp.plotter.axis.set_ylim(sp.data.min()*1.3 - 3*mean_error + sp.specfit.residuals.min(), sp.data.max()*1.3 + 3*mean_error) sp.plotter.axis.set_xlim(0, 120) sp1 = spectra['w51e2-core_77'][1] mean_error = sp1.data[-20:-2].std() sp1.plotter.figure = fig sp1.plotter.axis = pl.subplot(2,1,2) sp1.plotter() sp1.specfit.Registry.add_fitter('sevenseven_movinghf', sevenseven_movinghf_fitter(), 7) sp1.specfit(fittype='sevenseven_movinghf', guesses=[58, 83, 27.3, 31.2, 1.32, 1800, 8200], fixed=[F,F,F,F,F,T,T], annotate=False) sp1.specfit.plotresiduals(axis=sp1.plotter.axis, clear=False,
import os from hf_only_model import hfonly_66_fixed_fitter, hfonly_fitter, sixsix_movinghf_fitter from spectral_cube import SpectralCube from astropy import units as u import numpy as np import pyspeckit pyspeckit.fitters.default_Registry.add_fitter('hfonly', hfonly_fitter(), 7) pyspeckit.fitters.default_Registry.add_fitter('hfonly66', hfonly_66_fixed_fitter(), 4) pyspeckit.fitters.default_Registry.add_fitter('sixsix_movinghf', sixsix_movinghf_fitter(), 5) cube = SpectralCube.read('/Volumes/passport/W51-GODDI/W51e2_66_baselined-sc-pb.cube.image.fits') scube = cube[:, 230:307, 205:270] errmap = scube.spectral_slab(-20*u.km/u.s, 10*u.km/u.s).std(axis=0) mn = scube.min(axis=0).value guesses = np.empty((7, scube.shape[1], scube.shape[2])) 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