def moment1_error(cube, scale, axis=0, how='auto', moment0=None, moment1=None): ''' Compute the first moment error. Parameters ---------- cube : SpectralCube Data cube. scale : SpectralCube or `~astropy.units.Quantity` The noise level in the data, either as a single value (with the same units as the cube) or a SpectralCube of noise values. axis : int Axis to compute moment over. how : {'auto', 'cube', 'slice'}, optional The computational method to use. Returns ------- moment1_err : `~spectral_cube.lower_dimensional_structures.Projection` ''' if how == "auto": how = iterator_strategy(cube, 0) if how == "ray": warn("Automatically selected 'ray' which isn't implemented. Using" " 'slice' instead.") how = 'slice' # Compute moments if they aren't given. if moment0 is None: moment0 = cube.moment0(how=how, axis=axis) if moment1 is None: moment1 = cube.moment1(how=how, axis=axis) # Remove velocity offset from centroid to match cube._pix_cen # Requires converting to a Quantity moment1 = u.Quantity(moment1) moment1 -= cube.spectral_axis[0] if how == "cube": moment1_err = _cube1(cube, axis, scale, moment0, moment1) elif how == "slice": moment1_err = _slice1(cube, axis, scale, moment0, moment1) else: raise ValueError("how must be 'cube' or 'slice'.") meta = {'moment_order': 1, 'moment_axis': axis, 'moment_method': how} cube_meta = cube.meta.copy() meta.update(cube_meta) new_wcs = drop_axis(cube._wcs, np2wcs[axis]) return Projection(moment1_err, copy=False, wcs=new_wcs, meta=meta, header=cube._nowcs_header)
def test_single_gray_hole(): one_gray_hole = add_holes((200, 200), hole_level=100, nholes=1) test_gray_hole = Projection(one_gray_hole, wcs=wcs.WCS()) test_bubble = BubbleFinder2D(test_gray_hole, beam=Beam(10), channel=0, sigma=40) test_bubble.multiscale_bubblefind(edge_find=False)
def load_projection(filename): from astropy import wcs from astropy.io import fits from spectral_cube.lower_dimensional_structures import Projection fh = fits.open(filename) return Projection(value=fh[0].data, header=fh[0].header, wcs=wcs.WCS(fh[0].header), unit=u.Unit(fh[0].header['BUNIT']), )
def get_mom0(fn, vrange=[51, 60] * u.km / u.s, exclude_vrange=[40, 75] * u.km / u.s, percentile=30, iterate=True): savename = paths.dpath( os.path.join( os.path.split(fn)[0], 'moments', os.path.split(fn)[1].replace(".fits", "_p30sub.fits"))) if os.path.exists(savename): print("Loading {0} from disk".format(savename)) fh = fits.open(savename) m0 = Projection( value=fh[0].data, header=fh[0].header, wcs=wcs.WCS(fh[0].header), unit=u.Unit(fh[0].header['BUNIT']), ) else: print("Computing {0} from analysis of {1}".format(savename, fn)) cube = SpectralCube.read(fn) #bm = cube.beams[0] #jtok = bm.jtok(cube.wcs.wcs.restfrq*u.Hz) slab = cube.spectral_slab(*vrange) cube.beam_threshold = 1 #contguess = cube.spectral_slab(0*u.km/u.s, 40*u.km/u.s).percentile(50, axis=0) #contguess = cube.spectral_slab(70*u.km/u.s, 100*u.km/u.s).percentile(50, axis=0) mask = (cube.spectral_axis < exclude_vrange[0]) | (cube.spectral_axis > exclude_vrange[1]) masked_cube = cube.with_mask(mask[:, None, None]) try: log.info("Continuum measurement.") contguess = masked_cube.percentile(percentile, axis=0, iterate_rays=iterate, progressbar=iterate) except ValueError as ex: print("skipping {0}".format(fn)) print(ex) raise log.info("Subtract the continuum") slabsub = (slab - contguess) slabsub.beam_threshold = 0.25 log.info("Compute moment 0") m0 = slabsub.moment0() log.info("Save results to {0}".format(savename)) m0.hdu.writeto(savename) return m0
def test_gauss_hole(): one_gauss_hole, params = add_gaussian_holes(np.ones((200, 200)), nholes=1, return_info=True) test_gauss_hole = Projection(one_gauss_hole, wcs=wcs.WCS()) test_bubble = BubbleFinder2D(test_gauss_hole, beam=Beam(10), channel=0, sigma=0.05) test_bubble.multiscale_bubblefind(edge_find=True) test_bubble.visualize_regions(edges=True)
def moment0_error(cube, scale, axis=0, how='auto'): ''' Compute the zeroth moment error. Parameters ---------- cube : SpectralCube Data cube. scale : SpectralCube or `~astropy.units.Quantity` The noise level in the data, either as a single value (with the same units as the cube) or a SpectralCube of noise values. axis : int Axis to compute moment over. how : {'auto', 'cube', 'slice'}, optional The computational method to use. Returns ------- moment0 : `~spectral_cube.lower_dimensional_structures.Projection` ''' if how == "auto": how = iterator_strategy(cube, 0) if how == "ray": warn("Automatically selected 'ray' which isn't implemented. Using" " 'slice' instead.") how = 'slice' if how == "cube": moment0_err = _cube0(cube, axis, scale) elif how == "slice": moment0_err = _slice0(cube, axis, scale) else: raise ValueError("how must be 'cube' or 'slice'.") # Multiply by spectral unit moment0_err *= cube.spectral_axis.unit meta = {'moment_order': 0, 'moment_axis': axis, 'moment_method': how} cube_meta = cube.meta.copy() meta.update(cube_meta) new_wcs = drop_axis(cube._wcs, np2wcs[axis]) return Projection(moment0_err, copy=False, wcs=new_wcs, meta=meta, header=cube._nowcs_header)
def test_multiple_shell(): yy, xx = np.mgrid[-200:200, -200:200] beam = Beam(10) clean_model = shell_model(amp=1.0, ring_small=None, ratio=1.05)(yy, xx) amp = clean_model.max() sigma = 0.25 * amp noisy_model = clean_model + sigma * np.random.random(yy.shape) # smooth_model = convolve_fft(noisy_model, beam.as_kernel(1)) model = Projection(noisy_model, wcs=wcs.WCS()) test_bubble = BubbleFinder2D(model, beam=beam, channel=0, sigma=sigma) test_bubble.multiscale_bubblefind(edge_find=True) ax = test_bubble.visualize_regions(edges=True, show=False) ax.contour(model > 3 * sigma, colors='c') print(test_bubble.region_params)
def test_random_gray_holes(): np.random.seed(375467546) gray_holes = add_holes((500, 500), hole_level=100, nholes=40, max_corr=0.1, rad_max=40) test_gray_holes = Projection(gray_holes, wcs=wcs.WCS()) scales = 3 * np.arange(1, 8, np.sqrt(2)) test_bubble = BubbleFinder2D(test_gray_holes, beam=Beam(10), sigma=10, channel=0, scales=scales) test_bubble.multiscale_bubblefind(edge_find=True, nsig=3, overlap_frac=0.6) test_bubble.visualize_regions(edges=True) # print(test_bubble.region_params) return test_bubble
# argmax = np.argmax(medfilt(arr, smooth_size)) # return cube.spectral_axis[argmax] # return cube.apply_function(peak_velocity, axis=0, projection=True, # unit=cube.spectral_axis.unit) def peak_velocity(inputs): y, x = inputs smooth_size = 31 argmax = np.argmax(medfilt(subcube[:, y, x].value, smooth_size)) return subcube.spectral_axis[argmax], y, x peakvels = Projection(np.zeros(subcube.shape[1:]), wcs=cube.wcs.celestial, unit=cube.spectral_axis.unit) posns = np.where(subcube.mask.include().sum(0) > 0) pool = Pool(6) output = pool.map(peak_velocity, izip(*posns)) pool.close() pool.join() for out in output: peakvels[out[1], out[2]] = out[0] peakvels[peakvels == 0.0 * u.m / u.s] = np.NaN * u.m / u.s
def calc_physics(ra=None, dec=None, r=0.17 * u.pc, dr=0.05 * u.pc, vexp=4 * u.km / u.s, v0=14 * u.km / u.s, cube_12co=None, cube_13co=None, dist=414 * u.pc, snr_cutoff=5., shell_snr_cutoff=3., shell=True, plot=False, linewidth_mode='fwhm', average_Tex=True): """ shell_snr_cutoff is the sigma cutoff for extracting the shell voxels. """ #print(cube_12co.header['CDELT3']) from spectral_cube.lower_dimensional_structures import Projection pix_size = (cube_12co.header['CDELT2'] * u.deg).to(u.arcsec) vstep = (cube_12co.header['CDELT3'] * (u.m / u.s)).to(u.km / u.s) if shell: model_pars = { 'dist': dist, # pc 'pix_size': pix_size, # arcsec 'vstep': vstep, # km/s 'acen': ra.to(u.deg), # deg 'dcen': dec.to(u.deg), # deg 'thickness': 0.0, # pc 'fwhm': 0.0, # km/s 'beta': 0.0, # spectral index 'R': r, # pc 'dr': dr, # pc 'vexp': vexp, # km/s 'depth_offset': 0.0, # pc 'vel_offset': 0.0, # km/s 'v0': v0, # km/s 'ignore_cloud': 1, #Ignore cloud. 'method': 'sample', 'write_fits': False, 'samples_per_voxel': 27 } #Extract 12co shell voxels using model. model_cube = SpectralCube.read(shell_model.ppv_model(**model_pars)) #shell_masked, shell_mask = extract_shell( # cube_file=cube_12co, model_pars=model_pars, return_mask=True) #Extract subcubes with same ra/dec range as shell voxel cube, but #full velocity range. subcube_shell_12co = cube_12co.subcube(model_cube.longitude_extrema[1], model_cube.longitude_extrema[0], model_cube.latitude_extrema[0], model_cube.latitude_extrema[1]) subcube_shell_13co = cube_13co.subcube(model_cube.longitude_extrema[1], model_cube.longitude_extrema[0], model_cube.latitude_extrema[0], model_cube.latitude_extrema[1]) #print(subcube_shell_12co, subcube_shell_13co, model_cube) if plot: plt.figure() plt.subplot(131) plt.imshow(subcube_shell_12co.moment0().data) plt.subplot(132) plt.imshow(subcube_shell_13co.moment0().data) plt.subplot(133) plt.imshow(model_cube.moment0().data) plt.show() else: subcube_shell_12co = cube_12co subcube_shell_13co = cube_13co rms_12co = rms_map(cube=subcube_shell_12co) rms_13co = rms_map(cube=subcube_shell_13co) ### ### Use 13co if 3sigma detected, otherwise use corrected 12co if 3sigma detected. mask_use_13co = (subcube_shell_13co >= shell_snr_cutoff * rms_13co) mask_use_12co = (~mask_use_13co) & (subcube_shell_12co >= shell_snr_cutoff * rms_12co) ### Excitation Temperature Tex = cube_Tex(subcube_shell_12co, average_first=True, plot=False, average=average_Tex) print("Tex is {}".format(Tex)) ### Correct 12co for opacity. subcube_shell_12co_correct = opacity_correct(subcube_shell_12co, cube_thin=subcube_shell_13co, snr_cutoff=snr_cutoff, plot_ratio='ratio.png') #print(subcube_shell_12co_correct) subcube_shell_12co_correct = subcube_shell_12co_correct.with_mask( mask_use_12co) subcube_shell_13co = subcube_shell_13co.with_mask(mask_use_13co) # if plot: # plt.figure() # plt.subplot(121) # plt.imshow(subcube_shell_12co_correct.moment0().data) # plt.subplot(122) # plt.imshow(subcube_shell_13co.moment0().data) # plt.show() if shell: ### Extract shell voxels from opacity-corrected 12co shell_12co_correct = extract_shell(subcube_shell_12co_correct, keep_latlon=True, model_cube=model_cube) shell_13co = extract_shell(subcube_shell_13co, keep_latlon=True, model_cube=model_cube) else: shell_12co_correct = subcube_shell_12co_correct shell_13co = subcube_shell_13co # if plot: # plt.figure() # plt.subplot(121) # plt.imshow(shell_12co_correct.moment0().data) # plt.subplot(122) # plt.imshow(shell_13co.moment0().data) # plt.show() ### ### Use 13co if 3sigma detected, otherwise use corrected 12co if 3sigma detected. # mask_use_13co = (shell_13co >= shell_snr_cutoff * rms_13co) # mask_use_12co = (~mask_use_13co) & (subcube_shell_12co >= shell_snr_cutoff * rms_12co) ### Calculate column density of H2 from 13co where 13co is 3sig, ### otherwise use opacity-corrected 12co. shell_nH2_12co = column_density_H2(shell_12co_correct, Tex=Tex, molecule="12co") shell_nH2_13co = column_density_H2(shell_13co, Tex=Tex, molecule="13co") #print(shell_nH2_12co.shape, shell_nH2_13co.shape) print(np.nansum([shell_nH2_12co, shell_nH2_13co], axis=0), shell_nH2_12co.unit) shell_nH2 = Projection(np.nansum([shell_nH2_12co, shell_nH2_13co], axis=0), header=shell_nH2_12co.header, wcs=shell_nH2_12co.wcs, unit=shell_nH2_12co.unit, dtype=shell_nH2_12co.dtype, meta=shell_nH2_12co.meta, mask=shell_nH2_12co.mask) #print(shell_nH2.shape) # if plot: # plt.figure() # plt.subplot(131) # plt.title("H2 from 12co") # plt.imshow(shell_nH2_12co.data) # plt.subplot(132) # plt.title("H2 from 13co") # plt.imshow(shell_nH2_13co.data) # plt.subplot(133) # plt.title("Total H2") # plt.imshow(shell_nH2) ### Calculate Mass, Momentum, and Energy of Shell! if shell: shell_mass = mass(shell_nH2, distance=414 * u.pc, molecule='H2', mass_unit=u.Msun) shell_momentum = momentum(shell_mass, vexp) shell_energy = energy(shell_mass, vexp) shell_luminosity = (shell_energy / (r / vexp)).to(u.erg / u.s) else: mass_map = mass(shell_nH2, distance=414 * u.pc, molecule='H2', mass_unit=u.Msun, return_map=True) if linewidth_mode == "fwhm": vel_map = subcube_shell_13co.linewidth_fwhm() elif linewidth_mode == "sigma": vel_map = subcube_shell_13co.linewidth_sigma() elif linewidth_mode == "sigma3D": vel_map = 3.**0.5 * subcube_shell_13co.linewidth_sigma() # plt.figure() # plt.imshow(vel_map) # plt.show() #vel_average = np.nanmean(vel_map.value) shell_mass = u.Quantity(np.nansum(mass_map)) shell_momentum = u.Quantity(np.nansum(mass_map * vel_map)) #shell_momentum = vel shell_energy = 0.5 * u.Quantity(np.nansum( mass_map * vel_map * vel_map)) #shell_energy = 0.5 * shell_mass #print(u.Quantity(0.5*shell_mass*u.Quantity(np.nanmean(vel_map))**2.).to(u.erg)) if plot: from aplpy import FITSFigure from astropy.io import fits hdu = shell_nH2.hdu hdu.data = np.log10(shell_nH2.data) fig = FITSFigure(hdu.data) fig.show_colorscale(vmin=21.5, vmax=23.65, interpolation='none') fig.add_colorbar() # plt.imshow(np.log10(shell_nH2.value), interpolation='none', # vmin=21.5, vmax=23.648) # plt.colorbar() # plt.title("log(n(H2) [cm^-2])") #plt.show() plt.savefig("../subregions/berneregion_lognH2.png") hdu = fits.open("../berne_Nh_2.fits")[0] hdu.data = np.log10(hdu.data) fig = FITSFigure(hdu.data) fig.show_colorscale(vmin=21.5, vmax=23.65, interpolation='none') fig.add_colorbar() #plt.show() plt.savefig("../subregions/berne_lognH2.png") # plt.figure() # plt.imshow(vel_map.to(u.km/u.s).value, interpolation='none') # #energy_map = (0.5*mass_map*vel_map*vel_map).to(u.erg).value # vels = vel_map.to(u.km/u.s).value.flatten() # plt.figure() # plt.hist(vels[vels>0], normed=True, log=True, bins=40) # plt.xlabel("Velocity FWHM (km/s)") # plt.ylabel("PDF") # plt.title('Velocity FWHM PDF') # plt.show() # plt.figure() # plt.imshow(vel_map.data) # plt.colorbar() # plt.show() return shell_mass, shell_momentum, shell_energy
def chem_plot_single(linere, yslice=slice(367,467), xslice=slice(114,214), vrange=[51,60]*u.km/u.s, sourcename='e2', filelist=glob.glob(paths.dpath('12m/cutouts/*e2e8*fits')), # 5,8 -> 12.8,8 # 6,8 -> 12.0,8.6 # 5,9 -> 15.0,8.0 # 6,9 -> 15,9.6 #plotgrid=(6,9), figsize=(15.0, 9.6), figsize=(12.0, 8.6), suffix="", vmax_m0=5.0, vmax_max=150, maxbeam=0.5*u.arcsec, contourlevels=None, filetype='pdf', ): text_fontsize = 4.5 if filetype=='png' else 9 for ii in range(1,7): if not all(pl.figure(ii, figsize=figsize).get_size_inches() == figsize): pl.close(ii) fig1 = pl.figure(1, figsize=figsize) fig1.clf() fig2 = pl.figure(2, figsize=figsize) fig2.clf() fig3 = pl.figure(3, figsize=figsize) fig3.clf() fig4 = pl.figure(4, figsize=figsize) fig4.clf() fig5 = pl.figure(5, figsize=figsize) fig5.clf() fig6 = pl.figure(6, figsize=figsize) fig6.clf() figcounter = 0 for ii,fn in enumerate(ProgressBar(filelist)): linename = linere.search(fn).groups()[0] if linename not in labeldict: print() print("Skipping {0} because it's not in the label dict".format(linename)) continue label = labeldict[linename] # cache the results for use in other work, later use, ... m0fitsfn = paths.dpath("chemslices/chemical_m0_slabs_{0}_{1}{2}.fits".format(sourcename, linename, suffix)) m1fitsfn = paths.dpath("chemslices/chemical_m1_slabs_{0}_{1}{2}.fits".format(sourcename, linename, suffix)) m2fitsfn = paths.dpath("chemslices/chemical_m2_slabs_{0}_{1}{2}.fits".format(sourcename, linename, suffix)) maxfitsfn = paths.dpath("chemslices/chemical_max_slabs_{0}_{1}{2}.fits".format(sourcename, linename, suffix)) maxsubfitsfn = paths.dpath("chemslices/chemical_max_sub_slabs_{0}_{1}{2}.fits".format(sourcename, linename, suffix)) madstdfitsfn = paths.dpath("chemslices/chemical_madstd_slabs_{0}_{1}{2}.fits".format(sourcename, linename, suffix)) if not (os.path.exists(m0fitsfn) and os.path.exists(m2fitsfn) and os.path.exists(maxfitsfn) and os.path.exists(madstdfitsfn)): print() print("Extracting max/m0/m1/m2 for {0}".format(fn)) cube = SpectralCube.read(fn)[:,yslice,xslice] goodbeams = np.array([bm.major < maxbeam for bm in cube.beams], dtype='bool') if np.count_nonzero(goodbeams) < 5: print() print("Skipping {0} because it has too few good beams.".format(fn)) continue cube = cube.with_mask(goodbeams[:,None,None]) cube = cube.minimal_subcube() if cube.shape[0] == 0: print() print("Skipping {0} because it was masked out".format(fn)) continue bm = cube.beams[0] restfreq = cube.wcs.wcs.restfrq cube = cube.to(u.K, bm.jtok_equiv(restfreq*u.Hz)) slab = cube.spectral_slab(*vrange) cube.beam_threshold = 1 #contguess = cube.spectral_slab(0*u.km/u.s, 40*u.km/u.s).percentile(50, axis=0) #contguess = cube.spectral_slab(70*u.km/u.s, 100*u.km/u.s).percentile(50, axis=0) mask = (cube.spectral_axis<40*u.km/u.s) | (cube.spectral_axis > 75*u.km/u.s) try: contguess = cube.with_mask(mask[:,None,None]).percentile(30, axis=0) except ValueError as ex: print() print("skipping {0}".format(fn)) print(ex) continue slabsub = (slab-contguess) slab.beam_threshold = 0.25 slabsub.beam_threshold = 0.25 m0 = slabsub.moment0() m1 = slabsub.moment1() m2 = slabsub.moment2() max_sub = slabsub.max(axis=0) max = slab.max(axis=0) madstd = cube.with_mask(mask[:,None,None]).apply_function(mad_std, axis=0, projection=True, progressbar=True, unit=cube.unit,) m0.write(m0fitsfn, overwrite=True) m1.write(m1fitsfn, overwrite=True) m2.write(m2fitsfn, overwrite=True) max.write(maxfitsfn, overwrite=True) max_sub.write(maxsubfitsfn, overwrite=True) madstd.write(madstdfitsfn, overwrite=True) maxfh = max.hdu else: m0fh = fits.open(m0fitsfn) m1fh = fits.open(m1fitsfn) m2fh = fits.open(m2fitsfn) maxfh = fits.open(maxfitsfn)[0] maxsubfh = fits.open(maxsubfitsfn) madstdfh = fits.open(madstdfitsfn) m0 = Projection(value=m0fh[0].data, header=m0fh[0].header, wcs=wcs.WCS(m0fh[0].header), unit=u.Unit(m0fh[0].header['BUNIT']),) m1 = Projection(value=m1fh[0].data, header=m1fh[0].header, wcs=wcs.WCS(m1fh[0].header), unit=u.Unit(m1fh[0].header['BUNIT']),) m2 = Projection(value=m2fh[0].data, header=m2fh[0].header, wcs=wcs.WCS(m2fh[0].header), unit=u.Unit(m2fh[0].header['BUNIT']),) max = Projection(value=maxfh.data, header=maxfh.header, wcs=wcs.WCS(maxfh.header), unit=u.Unit(maxfh.header['BUNIT']),) max_sub = Projection(value=maxsubfh[0].data, header=maxsubfh[0].header, wcs=wcs.WCS(maxsubfh[0].header), unit=u.Unit(maxsubfh[0].header['BUNIT']),) madstd = Projection(value=madstdfh[0].data, header=madstdfh[0].header, wcs=wcs.WCS(madstdfh[0].header), unit=u.Unit(madstdfh[0].header['BUNIT']),) bm = radio_beam.Beam.from_fits_header(m0fh[0].header) restfreq = m0fh[0].header['RESTFRQ'] jtok = bm.jtok(restfreq*u.Hz) fig1 = pl.figure(1, figsize=figsize) fig1.clf() ax1 = fig1.gca() im1 = ax1.imshow(m0.value, vmin=-1.25*jtok.value, vmax=vmax_m0*jtok.value, cmap=pl.cm.bone_r, interpolation='nearest', origin='lower') ax1.text(3, 0.87*m0.shape[0], label, fontsize=text_fontsize) ax1.set_xticklabels([]) ax1.set_yticklabels([]) ax1.set_xticks([]) ax1.set_yticks([]) ax1.set_aspect('equal') cb = pl.colorbar(mappable=im1) cb.set_label("Flux Density (K km s$^{-1}$)", fontsize=12) fig1.savefig(paths.fpath("chemical_slabs/{3}_chemical_m0_slab_{0}{1}.{2}" .format(sourcename, suffix, filetype, linename)), bbox_inches='tight', dpi=300) fig2 = pl.figure(2, figsize=figsize) fig2.clf() ax2 = fig2.gca() im2 = ax2.imshow(m1.value, vmin=vrange[0].value, vmax=vrange[1].value, cmap='seismic', interpolation='nearest', origin='lower') ax2.text(3, 0.87*m0.shape[0], label, fontsize=text_fontsize, color='g') ax2.set_xticklabels([]) ax2.set_yticklabels([]) ax2.set_xticks([]) ax2.set_yticks([]) ax2.set_aspect('equal') cb = pl.colorbar(mappable=im2) cb.set_label("Velocity (km s$^{-1}$)", fontsize=12) fig2.savefig(paths.fpath("chemical_slabs/{3}_chemical_m1_slab_{0}{1}.{2}" .format(sourcename, suffix, filetype, linename)), bbox_inches='tight', dpi=300) fig3 = pl.figure(3, figsize=figsize) fig3.clf() ax3 = fig3.gca() im3 = ax3.imshow(max_sub.value, vmin=-10, vmax=vmax_max, cmap=pl.cm.bone_r, interpolation='nearest', origin='lower') # add a contour to show the regions that are "saturated" above T_max if contourlevels is None: contourlevels = [vmax_max, 300, 400, 500] qcs = ax3.contour(max_sub.value, levels=contourlevels, colors=['r','g','b','y']) #print("levels: {0} = {1}".format(qcs.levels, contourlevels)) ax3.text(3, 0.87*m0.shape[0], label, fontsize=text_fontsize, color='r') ax3.set_xticklabels([]) ax3.set_yticklabels([]) ax3.set_xticks([]) ax3.set_yticks([]) ax3.set_aspect('equal') cb = pl.colorbar(mappable=im3) cb.set_label("Peak Brightness (K)", fontsize=12) fig3.savefig(paths.fpath("chemical_slabs/{3}_chemical_max_contsub_slab_{0}{1}.{2}" .format(sourcename, suffix, filetype, linename)), bbox_inches='tight', dpi=300) fig5 = pl.figure(5, figsize=figsize) fig5.clf() ax5 = fig5.gca() im5 = ax5.imshow(max.value, vmin=-10, vmax=vmax_max, cmap=pl.cm.bone_r, interpolation='nearest', origin='lower') # add a contour to show the regions that are "saturated" above T_max qcs = ax5.contour(max.value, levels=contourlevels, colors=['r','g','b','y']) if False: # debug print("levels: {0} = {1}".format(qcs.levels, contourlevels)) ax5.text(3, 0.87*m0.shape[0], label, fontsize=text_fontsize, color='r') ax5.set_xticklabels([]) ax5.set_yticklabels([]) ax5.set_xticks([]) ax5.set_yticks([]) ax5.set_aspect('equal') cb = pl.colorbar(mappable=im5) cb.set_label("Peak Brightness (K)", fontsize=12) fig5.savefig(paths.fpath("chemical_slabs/{3}_chemical_max_slab_{0}{1}.{2}" .format(sourcename, suffix, filetype, linename)), bbox_inches='tight', dpi=300) fig4 = pl.figure(4, figsize=figsize) fig4.clf() ax4 = fig4.gca() im4 = ax4.imshow(madstd.value, cmap=pl.cm.bone_r, interpolation='nearest', origin='lower') ax4.text(3, 0.87*m0.shape[0], label, fontsize=text_fontsize, color='r') ax4.set_xticklabels([]) ax4.set_yticklabels([]) ax4.set_xticks([]) ax4.set_yticks([]) ax4.set_aspect('equal') cb = pl.colorbar(mappable=im4) cb.set_label("MAD StdDev (K)", fontsize=12) fig4.savefig(paths.fpath("chemical_slabs/{3}_chemical_madstd_slab_{0}{1}.{2}" .format(sourcename, suffix, filetype, linename)), bbox_inches='tight', dpi=300) fig6 = pl.figure(6, figsize=figsize) fig6.clf() ax6 = fig6.gca() im6 = ax6.imshow((m2**0.5).to(u.km/u.s).value * SIGMA2FWHM, vmin=0, vmax=15, cmap='viridis', interpolation='nearest', origin='lower') ax6.text(3, 0.87*m0.shape[0], label, fontsize=text_fontsize, color='k') ax6.set_xticklabels([]) ax6.set_yticklabels([]) ax6.set_xticks([]) ax6.set_yticks([]) ax6.set_aspect('equal') cb = pl.colorbar(mappable=im6) cb.set_label("Velocity Dispersion (km s$^{-1}$)", fontsize=12) fig6.savefig(paths.fpath("chemical_slabs/{3}_chemical_m2_slab_{0}{1}.{2}" .format(sourcename, suffix, filetype, linename)), bbox_inches='tight', dpi=300) figcounter += 1 ax5 = fig5.gca() ax5.cla() cont = get_cont(maxfh.header) im5 = ax5.imshow(cont.value, vmin=-10, vmax=vmax_max, cmap=pl.cm.bone_r, interpolation='nearest', origin='lower') # add a contour to show the regions that are "saturated" above T_max ax5.contour(cont.value, levels=contourlevels, colors=['r','g','b','y']) ax5.text(3, 0.87*m0.shape[0], 'Continuum', fontsize=text_fontsize, color='r') ax5.set_xticklabels([]) ax5.set_yticklabels([]) ax5.set_aspect('equal') fig5.savefig(paths.fpath("cont_max_slab_{0}{1}.{2}" .format(sourcename, suffix, filetype)), bbox_inches='tight', dpi=300)
def chem_plot(linere, yslice=slice(367,467), xslice=slice(114,214), vrange=[51,60]*u.km/u.s, sourcename='e2', filelist=glob.glob(paths.dpath('12m/cutouts/*e2e8*fits')), suffix="", plotgrid=(5,8), figsize=(12.8,8), vmax_m0=5.0, vmax_max=150, maxbeam=0.5*u.arcsec, ): nplots = np.product(plotgrid) for ii in (1,2): if not all(pl.figure(ii, figsize=figsize).get_size_inches() == figsize): pl.close(ii) fig1 = pl.figure(1, figsize=figsize) fig1.clf() gs1 = gridspec.GridSpec(*plotgrid) gs1.update(wspace=0.0, hspace=0.0) fig2 = pl.figure(2, figsize=figsize) fig2.clf() gs2 = gridspec.GridSpec(*plotgrid) gs2.update(wspace=0.0, hspace=0.0) fig3 = pl.figure(3, figsize=figsize) fig3.clf() gs3 = gridspec.GridSpec(*plotgrid) gs3.update(wspace=0.0, hspace=0.0) fig4 = pl.figure(4, figsize=figsize) fig4.clf() gs4 = gridspec.GridSpec(*plotgrid) gs4.update(wspace=0.0, hspace=0.0) figcounter = 0 for ii,fn in enumerate(ProgressBar(filelist)): linename = linere.search(fn).groups()[0] if linename not in labeldict: print("Skipping {0} because it's not in the label dict".format(linename)) continue label = labeldict[linename] # cache the results for use in other work, later use, ... m0fitsfn = paths.dpath("chemslices/chemical_m0_slabs_{0}_{1}{2}.fits".format(sourcename, linename, suffix)) m1fitsfn = paths.dpath("chemslices/chemical_m1_slabs_{0}_{1}{2}.fits".format(sourcename, linename, suffix)) maxfitsfn = paths.dpath("chemslices/chemical_max_slabs_{0}_{1}{2}.fits".format(sourcename, linename, suffix)) madstdfitsfn = paths.dpath("chemslices/chemical_madstd_slabs_{0}_{1}{2}.fits".format(sourcename, linename, suffix)) if not (os.path.exists(m0fitsfn) and os.path.exists(maxfitsfn) and os.path.exists(madstdfitsfn)): print("Extracting max/m0/m1 for {0}".format(fn)) cube = SpectralCube.read(fn)[:,yslice,xslice] goodbeams = np.array([bm.major < maxbeam for bm in cube.beams], dtype='bool') cube = cube.with_mask(goodbeams[:,None,None]) cube = cube.minimal_subcube() if cube.shape[0] == 0: print("Skipping {0} because it was masked out".format(fn)) continue bm = cube.beams[0] restfreq = cube.wcs.wcs.restfrq cube = cube.to(u.K, bm.jtok_equiv(restfreq*u.Hz)) slab = cube.spectral_slab(*vrange) cube.beam_threshold = 1 #contguess = cube.spectral_slab(0*u.km/u.s, 40*u.km/u.s).percentile(50, axis=0) #contguess = cube.spectral_slab(70*u.km/u.s, 100*u.km/u.s).percentile(50, axis=0) mask = (cube.spectral_axis<40*u.km/u.s) | (cube.spectral_axis > 75*u.km/u.s) try: contguess = cube.with_mask(mask[:,None,None]).percentile(30, axis=0) except ValueError as ex: print("skipping {0}".format(fn)) print(ex) continue slabsub = (slab-contguess) slabsub.beam_threshold = 0.25 m0 = slabsub.moment0() m1 = slabsub.moment1() max = slabsub.max(axis=0) madstd = cube.with_mask(mask[:,None,None]).apply_function(mad_std, axis=0, projection=True, progressbar=True, unit=cube.unit,) m0.write(m0fitsfn, overwrite=True) m1.write(m1fitsfn, overwrite=True) max.write(maxfitsfn, overwrite=True) madstd.write(madstdfitsfn, overwrite=True) else: m0fh = fits.open(m0fitsfn) m1fh = fits.open(m1fitsfn) maxfh = fits.open(maxfitsfn) madstdfh = fits.open(madstdfitsfn) m0 = Projection(value=m0fh[0].data, header=m0fh[0].header, wcs=wcs.WCS(m0fh[0].header), unit=u.Unit(m0fh[0].header['BUNIT']),) m1 = Projection(value=m1fh[0].data, header=m1fh[0].header, wcs=wcs.WCS(m1fh[0].header), unit=u.Unit(m1fh[0].header['BUNIT']),) max = Projection(value=maxfh[0].data, header=maxfh[0].header, wcs=wcs.WCS(maxfh[0].header), unit=u.Unit(maxfh[0].header['BUNIT']),) madstd = Projection(value=madstdfh[0].data, header=madstdfh[0].header, wcs=wcs.WCS(madstdfh[0].header), unit=u.Unit(madstdfh[0].header['BUNIT']),) bm = radio_beam.Beam.from_fits_header(m0fh[0].header) restfreq = m0fh[0].header['RESTFRQ'] jtok = bm.jtok(restfreq*u.Hz) if figcounter>=nplots: print("Skipping {0}".format(fn)) break ax1 = fig1.add_subplot(gs1[figcounter]) im1 = ax1.imshow(m0.value, vmin=-1.25*jtok.value, vmax=vmax_m0*jtok.value, cmap=pl.cm.bone_r, interpolation='nearest') ax1.text(3, 0.87*m0.shape[0], label, fontsize=9) ax1.set_xticklabels([]) ax1.set_yticklabels([]) ax1.set_aspect('equal') ax2 = fig2.add_subplot(gs2[figcounter]) im2 = ax2.imshow(m1.value, vmin=vrange[0].value, vmax=vrange[1].value, cmap=pl.cm.viridis, interpolation='nearest') ax2.text(3, 0.87*m0.shape[0], label, fontsize=9, color='w') ax2.set_xticklabels([]) ax2.set_yticklabels([]) ax2.set_aspect('equal') ax3 = fig3.add_subplot(gs2[figcounter]) im3 = ax3.imshow(max.value, vmin=-10, vmax=vmax_max, cmap=pl.cm.bone_r, interpolation='nearest') ax3.text(3, 0.87*m0.shape[0], label, fontsize=9, color='r') ax3.set_xticklabels([]) ax3.set_yticklabels([]) ax3.set_aspect('equal') ax4 = fig4.add_subplot(gs2[figcounter]) im4 = ax4.imshow(madstd.value, cmap=pl.cm.bone_r, interpolation='nearest') ax4.text(3, 0.87*m0.shape[0], label, fontsize=9, color='r') ax4.set_xticklabels([]) ax4.set_yticklabels([]) ax4.set_aspect('equal') figcounter += 1 cbs = {} for ii,fig, im, gs in ((1,fig1,im1,gs1), (2,fig2,im2,gs2), (3,fig3,im3,gs3), (4,fig4,im4,gs4),): bottom,top,left,right = gs.get_grid_positions(fig) cbar_ax = fig.add_axes([np.max(right)+0.01, np.min(bottom), 0.05, np.max(top)-np.min(bottom)]) cbs[ii] = pl.colorbar(mappable=im, cax=cbar_ax) cbs[ii].ax.tick_params(labelsize=12) cbs[1].set_label("Flux Density (K km s$^{-1}$)", fontsize=12) cbs[2].set_label("Velocity (km s$^{-1}$)", fontsize=12) cbs[3].set_label("Peak Brightness (K)", fontsize=12) cbs[4].set_label("MAD StdDev (K)", fontsize=12) pl.draw() pl.show() fig1.savefig(paths.fpath("chemical_m0_slabs_{0}{1}.png".format(sourcename, suffix)), bbox_inches='tight', dpi=150) fig2.savefig(paths.fpath("chemical_m1_slabs_{0}{1}.png".format(sourcename, suffix)), bbox_inches='tight', dpi=150) fig3.savefig(paths.fpath("chemical_max_slabs_{0}{1}.png".format(sourcename, suffix)), bbox_inches='tight', dpi=150) fig4.savefig(paths.fpath("chemical_madstd_slabs_{0}{1}.png".format(sourcename, suffix)), bbox_inches='tight', dpi=150)
return radprof, sdprof, sdprof_sigma if __name__ == "__main__": import matplotlib.pyplot as p from paths import (fourteenB_HI_data_path, arecibo_HI_data_path, c_hi_analysispath, paper1_figures_path, data_path) from constants import moment0_name, lwidth_name from galaxy_params import gal lwidth_hdu = fits.open(fourteenB_HI_data_path(lwidth_name))[0] lwidth = Projection(lwidth_hdu.data, wcs=WCS(lwidth_hdu.header), unit=u.m / u.s) lwidth.meta["beam"] = Beam.from_fits_header(lwidth_hdu.header) # Create a radial profile of the HI vel disp out to 8 kpc. # Beyond 8 kpc, noise is dominant. It may be some reflection of the # warp, but I don't trust it right now. rs, sd, sd_sigma = radial_profile(gal, lwidth, max_rad=8 * u.kpc) sd = sd.to(u.km / u.s) sd_sigma = sd_sigma.to(u.km / u.s) p.errorbar(rs.value, sd.value, yerr=sd_sigma.value, fmt="-", color="b", drawstyle='steps-mid') p.xlabel("R (kpc)") p.ylabel("HI Velocity Dispersion (km/s)")
from spectral_cube.lower_dimensional_structures import Projection from astropy.wcs import WCS from radio_beam import Beam from astropy.io import fits import os from paths import (fourteenB_HI_data_path, arecibo_HI_data_path, c_hi_analysispath, paper1_figures_path, data_path) from constants import hi_freq, moment0_name from galaxy_params import gal mom0_hdu = fits.open(fourteenB_HI_data_path(moment0_name))[0] mom0 = Projection(mom0_hdu.data, wcs=WCS(mom0_hdu.header), unit=u.Jy * u.m / u.s) mom0.meta["beam"] = Beam.from_fits_header(mom0_hdu.header) # Bin size in pc dr = 100 * u.pc # Create a radial profile of HI rs, sd, sd_sigma = surfdens_radial_profile(gal, mom0=mom0, dr=dr, restfreq=hi_freq) rs_n, sd_n, sd_sigma_n = \ surfdens_radial_profile(gal, mom0=mom0, pa_bounds=Angle([0.5 * np.pi * u.rad, -0.5 * np.pi * u.rad]), dr=dr, restfreq=hi_freq) rs_s, sd_s, sd_sigma_s = \ surfdens_radial_profile(gal, mom0=mom0,
# raise ValueError("Fit failed.") return fit, err, model, profile if __name__ == "__main__": from analysis.paths import (fourteenB_HI_data_path, paper1_figures_path, iram_co21_data_path) from analysis.constants import moment0_name from analysis.galaxy_params import gal mom0_fits = fits.open(fourteenB_HI_data_path(moment0_name))[0] beam = Beam.from_fits_header(mom0_fits.header) mom0 = Projection(mom0_fits.data * beam.jtok(hi_freq) / 1000. * u.km / u.s, wcs=WCS(mom0_fits.header)) mom0.meta['beam'] = beam # Create the bubble mask instead of letting FilFinder to do it. bub = BubbleFinder2D(mom0, sigma=80. * beam.jtok(hi_freq) / 1000.) # fils = fil_finder_2D(mom0.value, mom0.header, 10, distance=0.84e6) # fils.mask = ~(bub.mask.copy()) # fils.medskel() # fils.analyze_skeletons() # # So at least on of the radial profiles fails. BUT the second fit is to a # # skeleton that is essentially the entire disk, so plot without interactivity # # and save the plot and the parameters shown in verbose mode. # p.ioff() # fils.find_widths(verbose=True, max_distance=500, auto_cut=False, try_nonparam=False)