hi_fig.hide_xaxis_label() hi_fig.hide_yaxis_label() hi_fig.hide_tick_labels() hi_fig.set_title(r"HI") hi_fig.set_nan_color("k") hi_fig.show_regions("pvslices_finalfig.reg") co21_fig = FITSFigure(co21_proj.hdu, subplot=(2, 3, 3), figure=fig) co21_fig.show_grayscale() co21_fig.hide_xaxis_label() co21_fig.hide_yaxis_label() co21_fig.hide_tick_labels() co21_fig.set_title(r"CO(2-1)") for path, pnum in zip(paths[4:7], [4, 5, 6]): pv = extract_pv_slice(hi_cube, path) pv_co21 = extract_pv_slice(co21_cube, path) pv_fig = FITSFigure(pv, subplot=(2, 3, pnum), figure=fig) pv_fig.show_grayscale() pv_fig.show_contour(pv_co21, levels=np.arange(3 * co21_sigma, 20 * co21_sigma, 4 * co21_sigma), colors="g") pv_fig.hide_xaxis_label() pv_fig.hide_xtick_labels() if pnum != 4: pv_fig.hide_yaxis_label() pv_fig.hide_ytick_labels() p.tight_layout()
def pv_wedge(cube, center, length, min_theta, max_theta, ntheta=90, width=1): ''' Create a PV slice from a wedge. ''' y0, x0 = center thetas = np.linspace(min_theta, max_theta, ntheta) pv_slices = [] for i, theta in enumerate(thetas): start_pt = (y0 - (length / 2.) * np.sin(theta), x0 - (length / 2.) * np.cos(theta)) end_pt = (y0 + (length / 2.) * np.sin(theta), x0 + (length / 2.) * np.cos(theta)) path = Path([start_pt, end_pt], width=width) if i == 0: pv_slice = extract_pv_slice(cube, path) pv_path_slice, header = pv_slice.data, pv_slice.header else: pv_path_slice = extract_pv_slice(cube, path).data pv_slices.append(pv_path_slice) # Track the smallest shape if i == 0: path_length = pv_path_slice.shape[1] else: new_path_length = pv_path_slice.shape[1] if new_path_length < path_length: path_length = new_path_length header["NAXIS1"] = path_length # Now loop through and average together avg_pvslice = np.zeros((cube.shape[0], path_length), dtype='float') for pvslice in pv_slices: avg_pvslice += pvslice[:, :path_length] avg_pvslice /= float(ntheta) return PrimaryHDU(avg_pvslice, header=header)
def pvdraw(self): ###--generate PV diagram---### if self.header["naxis"] == 3: da = self.data else : da = self.data[0] if self.vr == None: pv = extract_pv_slice(da, Path(self.slc())) else: vii = int(self.header["crpix3"]+ (self.vr[0] - self.header["crval3"]/1000.) \ /(self.header["cdelt3"]/1000.))-1 vff = int(self.header["crpix3"]+ (self.vr[1] - self.header["crval3"]/1000.) \ /(self.header["cdelt3"]/1000.))-1 pv = extract_pv_slice(da[vii:vff], Path(self.slc())) return pv.data
def drawLV(fitsName,saveFITS=None, RMS=0.5, cutLevel=3.): if saveFITS==None: saveFITS=fitsName[:-5] + "_LV.fits" CO12HDU= fits.open(fitsName)[0] data,head= CO12HDU.data,CO12HDU.header wcs=WCS(head) Nz,Ny,Nx=data.shape beginP=[0, (Ny-1.)/2.] endP= [(Nx) , (Ny-1.)/2.] widthPix=2 from pvextractor import extract_pv_slice,Path endpoints = [beginP,endP] xy = Path(endpoints,width= widthPix ) pv = extract_pv_slice( CO12HDU, xy) os.system("rm " +saveFITS ) pv.writeto(saveFITS) if 1: #modify the first pvData,pvHead=myFITS.readFITS( saveFITS ) pvHead["CDELT1"]=head["CDELT1"] pvHead["CRPIX1"]=head["CRPIX1"] pvHead["NAXIS1"]=head["NAXIS1"] pvHead["CRVAL1"]=head["CRVAL1"] #data[data<cutLevel*RMS ]=0 #by default, we remove those emissions less than 3 sgima # resolution res=30./3600. PVData2D=np.sum(data,axis=1,dtype=float)*res if PVData2D.shape==pvData.shape: #..... #os.system("rm " +saveFITS ) fits.writeto(saveFITS,PVData2D,header=pvHead,overwrite=True) else: print ("The shape of pvdata with manual integration is unequal!" )
def creatPPVHeader(fitsName,saveFITS=None): """ produce the LV header for a fitsName, this function used in dendrogram :param fitsName: :param saveFITS: :return: """ if saveFITS==None: fitsName=os.path.split(fitsName)[1] saveFITS=fitsName[0:-5]+"LVHeader.fits" CO12HDU= fits.open(fitsName)[0] data,head= myFITS.readFITS(fitsName) # wcs=WCS(head) Nz,Ny,Nx=data.shape beginP=[0, (Ny-1.)/2.] endP= [(Nx) , (Ny-1.)/2.] #get pv diagrame widthPix=2 from pvextractor import extract_pv_slice,Path endpoints = [beginP,endP] xy = Path(endpoints,width= widthPix ) pv = extract_pv_slice( CO12HDU, xy) os.system("rm " +saveFITS ) pv.writeto(saveFITS) if 1: #modify the first pvData,pvHead=myFITS.readFITS( saveFITS ) pvHead["CDELT1"]=head["CDELT1"] pvHead["CRPIX1"]=head["CRPIX1"] pvHead["NAXIS1"]=head["NAXIS1"] pvHead["CRVAL1"]=head["CRVAL1"] os.system("rm " +saveFITS ) fits.writeto(saveFITS,pvData,header=pvHead,overwrite=True)
def get_pvs(cubefn, endpoints): fullcubefn = os.path.join(datapath_w51, cubefn) cube = spectral_cube.SpectralCube.read(fullcubefn) velo = cube.spectral_axis cdelt = pvextractor.utils.wcs_utils.get_spectral_scale(cube.wcs) #cube,velo,cdelt = pvextractor.utils.get_cube_info(cubefn) pvPath = pvextractor.geometry.path.Path(endpoints, width=60*u.arcsec) pv = pvextractor.extract_pv_slice(cube, pvPath) #respect_nan=False) npv = len(endpoints) return (pv,npv,velo,cdelt)
def extract_pv_diagram(image, xy=(0., 0.), pa=0., length=100, width=1): ny, nx, nfreq, npol = image.image.shape # Create a data cube that is appropriately shaped. cube = numpy.empty((nfreq, ny, nx)) for i in range(nfreq): cube[i, :, :] = image.image[:, :, i, 0] # Create the Path object. x0, y0 = xy line = [(x0-length/2*numpy.sin(pa),y0-length/2*numpy.cos(pa)), \ (x0+length/2*numpy.sin(pa), y0+length/2*numpy.cos(pa))] path = pvextractor.Path(line, width=width) # Extract the PV diagram along the Path pv = pvextractor.extract_pv_slice(cube, path) # Convert back to my Image class. pvdiagram = numpy.empty((1, pv.data.shape[1], pv.data.shape[0], 1)) for i in range(pv.data.shape[0]): pvdiagram[0, :, i, 0] = pv.data[i, :] # Get the velocity. velocity = c * (image.header["RESTFRQ"] - image.freq) / \ image.header["RESTFRQ"] # Get the x coordinates. x0 = 0. dx = image.header["CDELT2"] * numpy.pi / 180 / arcsec nx0 = int(pv.data.shape[1] / 2) + 1 x = (numpy.arange(pv.data.shape[1]) - (nx0 - 1)) * dx + x0 return Image(pvdiagram, x=x, velocity=velocity, freq=image.freq)
def PV_diagram_plot(filename, label, length=4 * u.arcsec, position_angle=0): cube = spectral_cube.SpectralCube.read(filename) # let's make the "parallel" PV diagram. # The path defines the line, whereupon normal # dimension is collapsed. I.e. the path line defines the offset direction # vector in the pv diagram. image_path = Path([*pv_path(cube.header, length, position_angle)], width=3) hdu = extract_pv_slice(cube.hdu.data, image_path) PV_file_name = 'pv_test_file.fits' save_extracted_pv_slice_hdu(hdu, cube.hdu.header, PV_file_name) image_data, im_hdr = load_fits_im(PV_file_name) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) im = ax.imshow(image_data, aspect='auto', interpolation='nearest', cmap=plt.cm.YlOrBr, origin='lower') ax.set_xlabel('x [pixels]', fontsize=12) ax.set_ylabel(r'y [channels]', fontsize=12) ax.set_title("{0} PV diagram. position_angle={1}".format( label, position_angle)) # Colorbar colorbar_ax = fig.add_axes([0.9, 0.11, 0.05, 0.77]) fig.colorbar(im, cax=colorbar_ax, label=r'Jy Beam$^{-1}$') colorbar_ax.tick_params(labelsize=10) return fig
paths = pvextractor.pvregions.paths_from_regfile('loop_segment_30kms.reg') for mol in ("HCN", "HNC", "HCOp", "HC3N", "H2CS303-202", "H2CS303202"): for pathno, path in enumerate(paths): for fn in (glob.glob("*{0}*image.pbcor.fits".format(mol)) + glob.glob("feathered/Feathered*{0}*.fits".format(mol)) + glob.glob("feathered/Regridded*{0}*fits".format(mol))): if any(x in fn for x in ('mask', 'max', 'sum', 'mom', 'pvext')): continue rcube = (SpectralCube.read(fn).with_spectral_unit( u.km / u.s, velocity_convention='radio').spectral_slab( 0.0 * u.km / u.s, 160 * u.km / u.s)) slice = pvextractor.extract_pv_slice(rcube, path) slice.writeto(fn.replace( ".fits", ".pvextraction_path{0}.fits".format(pathno)), clobber=True) F = aplpy.FITSFigure(slice) F.show_grayscale() F.save( fn.replace(".fits", ".pvextraction_path{0}.png".format(pathno))) print fn.replace(".fits", ".pvextraction_path{0}.png".format(pathno)) F.show_contour( 'SgrB2_a_03_7M.HNC.image.pbcor.pvextraction_path0.fits') F.save( fn.replace(
from pvextractor.geometry import Path jet_endpoints = coordinates.SkyCoord([290.9186, 290.91424]*u.deg, [14.518876, 14.517977]*u.deg, frame='fk5') xy = Path(jet_endpoints, width=2.8*u.arcsec) for ii,(fn,stretch) in enumerate((('w51.neii.square.fits','arcsinh'), ('w51.siv.square.fits','log'), ('W51north_H77_Outflow_cutout.fits','arcsinh'), ('H77a_cutout_1.fits','log'), ('H77a_cutout_2.fits','log'), )): cube = SpectralCube.read(paths.dpath(fn)).with_spectral_unit(u.km/u.s, velocity_convention='radio', rest_value=14128610000.0*u.Hz).spectral_slab(-200*u.km/u.s, 200*u.km/u.s) pv = extract_pv_slice(cube.hdu, xy) pv.data -= np.nanmin(pv.data) - 1e-3 fig = pl.figure(ii) fig.clf() FF = aplpy.FITSFigure(pv, figure=fig) FF.show_grayscale(aspect='auto', invert=True, stretch=stretch) FF.recenter(0.0021, 65e3, width=0.0042, height=300e3) FF._ax1.set_yticklabels([str(float(L.get_text())/1e3) for L in FF._ax1.get_yticklabels()]) FF._ax1.set_ylabel("Velocity (km/s)") FF._ax1.set_xticklabels([str(float(L.get_text())*3600) for L in FF._ax1.get_xticklabels()]) FF._ax1.set_xlabel("Offset (arcsec)") FF.save(paths.fpath('jetpv/{0}.png'.format(fn[:-5]))) FF.save(paths.fpath('jetpv/{0}.pdf'.format(fn[:-5])))
ignore_missing_end=True) mask = BooleanArrayMask(mask=np.isfinite(hdu[0].data), wcs=WCS(hdu[0].header)) sc = SpectralCube(data=hdu[0].data, wcs=WCS(hdu[0].header), mask=mask) # Select the region of interest sc_small = sc[120:300, 156:346, 677:958] # Ends for the PV slice # ends = [(107, 74), (151, 76), (220, 54)] ends = [(105, 70), (145, 80), (227, 28), (238, 1)] xy = Path(ends, width=10) pv = extract_pv_slice(sc_small, xy) p.subplot(121) p.imshow(sc_small.moment0().value, cmap="binary", origin="lower") p.plot([i for i, j in ends], [j for i, j in ends], 'b-') p.subplot(122) p.imshow(pv.data, cmap="binary", origin="lower") p.colorbar() p.show() hdu.close() # Now examine a subsection of the region that overlaps with the edge of # NGC-1333. I'm not sure the instrument that took the data, but it maps
e2siored = e2mslab.spectral_slab(74*u.km/u.s, 118*u.km/u.s).moment0() e2siored.write('/Users/adam/work/w51/alma/FITS/longbaseline/{line}_74to118kms_e2.fits'.format(line=line), overwrite=True) import pvextractor from pvextractor.pvregions import paths_from_regions import pyregion import paths reg = pyregion.open(paths.rpath('../regions/e2eoutflow_reference_vector.reg')) outflowcoords = paths_from_regions(reg) outflowpath = outflowcoords[0] outflowpath.width = 0.15*u.arcsec extracted = pvextractor.extract_pv_slice(e2slab, outflowpath) import aplpy FF = aplpy.FITSFigure(extracted) FF.show_grayscale(aspect='auto') FF.save(paths.fpath('outflows/{line}_PV_e2e.png'.format(line=line))) e8cube = SpectralCube.read('/Volumes/passport/alma/w51/longbaseline/W51e8cax.SPW0_ALL_medsub_cutout.fits') e8vcube = e8cube.with_spectral_unit(u.km/u.s, rest_value=freq, velocity_convention='radio') e8slab = e8vcube.spectral_slab(-100*u.km/u.s, 210*u.km/u.s) e8slab.allow_huge_operations = True e8med = e8slab.median(axis=0)
if pf[0].data.ndim != mywcs.wcs.naxis: naxes = ['NAXIS%i' % ii for ii in range(1,mywcs.wcs.naxis+1)] # WCS is 1-indexed axes_to_keep = [ii+1 for ii,nax in enumerate(naxes) if header[nax] > 1] mywcs = mywcs.sub(axes_to_keep) pf[0].header = mywcs.to_header() rstringlist = dd.get('regions -system wcs').split("\n") regions = load_regions_stringlist(rstringlist) if len(regions) == 0: sys.exit("No regions found") paths = paths_from_regions(regions) hdu = pvextractor.extract_pv_slice(pf[0], paths[regionid], order=0) with tempfile.NamedTemporaryFile(suffix='fits', delete=False) as tf: hdu.writeto(tf.name) # it may be possible to do this by # ds9_pvextract.py $xpa_method | $image # or any of the commented methods below... dd.set('frame new') #print tf.name dd.set('fits '+tf.name) #dd.set_pyfits(fits.HDUList(hdu)) #dd.set_np2arr(slc)
linexy=cube.wcs.wcs_pix2world(linex, liney, 0, 0) linex=[i for i in linexy[0]] liney=[i for i in linexy[1]] if width!=0: polyxy=path.sample_polygons(spacing=step, wcs=cube.wcs) polyx, polyy=[], [] for i in range(len(polyxy)): polyx+=polyxy[i].x polyy+=polyxy[i].y polyxy=cube.wcs.wcs_pix2world(polyx, polyy, 0, 0) polyx=[i for i in polyxy[0]] polyy=[i for i in polyxy[1]] """ slice export """ slice=extract_pv_slice(cube, path, spacing=step) slice.data=slice.data.transpose() keys=['CTYPE', 'CRVAL', 'CDELT', 'CRPIX', 'CUNIT'] for i in range(len(keys)): slice.header[keys[i]+'1'], slice.header[keys[i]+'2']=slice.header[keys[i]+'2'], slice.header[keys[i]+'1'] slice.header.comments[keys[i]+'1'], slice.header.comments[keys[i]+'2']=slice.header.comments[keys[i]+'2'], slice.header.comments[keys[i]+'1'] slice.header['CDELT1']=slice.header['CDELT1']/1e3 slice.header.comments['CDELT1']='[km/s] Coordinate increment at reference point' slice.header['CUNIT1']='km/s' slice.header['CRVAL1']=slice.header['CRVAL1']/1e3 slice.header.comments['CRVAL1']='[km/s] Coordinate value at reference point' if spec!=[]: slice.header['CRPIX1']=float(1.0) slice.header['CRVAL1']=linexy[2][0]/1e3
#rp = pyregion.RegionParser() # have to check for ds9 dropping degenerate axes if pf[0].data.ndim != mywcs.wcs.naxis: naxes = ['NAXIS%i' % ii for ii in range(1, mywcs.wcs.naxis + 1)] # WCS is 1-indexed axes_to_keep = [ii + 1 for ii, nax in enumerate(naxes) if header[nax] > 1] mywcs = mywcs.sub(axes_to_keep) pf[0].header = mywcs.to_header() rstringlist = dd.get('regions -system wcs').split("\n") regions = load_regions_stringlist(rstringlist) if len(regions) == 0: sys.exit("No regions found") paths = paths_from_regions(regions) hdu = pvextractor.extract_pv_slice(pf[0], paths[regionid], order=0) with tempfile.NamedTemporaryFile(suffix='fits', delete=False) as tf: hdu.writeto(tf) # it may be possible to do this by # ds9_pvextract.py $xpa_method | $image # or any of the commented methods below... dd.set('frame new') #print tf.name dd.set('fits ' + tf.name) #dd.set_pyfits(fits.HDUList(hdu)) #dd.set_np2arr(slc)
maxpars=[70, 5, 1500, 1e18, 10000], minpars=[40, 0.1, 50, 1e13, min_background], signal_cut=0, maskmap=absorption_mask, errmap=err.value, multicore=4) pcube_cont.write_fit('e2e_CH3CN_Absorption_fits.fits', clobber=True) from kinematic_analysis_pv_LB import diskycoords, outflowpath import pvextractor import pylab as pl pl.figure(5).clf() for width in (None, 0.05 * u.arcsec, 0.1 * u.arcsec, 0.15 * u.arcsec): diskypath = pvextractor.Path(diskycoords, width) extracted_disky = pvextractor.extract_pv_slice( pcube_cont.parcube[0:1, :, :], diskypath, wcs=pcube_cont.wcs) pl.plot(extracted_disky.data.squeeze(), label=str(width)) pl.xlabel("Offset (pixels)") pl.ylabel("Velocity (km/s)") pl.ylim(55, 60) pl.xlim(855, 890) pl.legend(loc='best') pl.savefig(paths.fpath("longbaseline/kinematics/velocity_vs_offset.png")) pl.figure(6).clf() diskypath = pvextractor.Path(diskycoords, width=None) extracted_disky = pvextractor.extract_pv_slice(pcube_cont.parcube[0:1, :, :], diskypath,
cmap.set_bad((1.0,)*3) else: cmap.set_bad((0.9,0.9,0.9,0.5)) pvfilename = ('orbits/KDL2014_orbit_on_{0}.fits'.format(molecule)) if os.path.exists(pvfilename): pv = fits.open(pvfilename)[0] else: # respect_nan = False so that the background is zeros where there is data # and nan where there is not data # But not respecting nan results in data getting averaged with nan, so we # need to respect it and then manually flag (in a rather unreliable # fashion!) #pv = pvextractor.extract_pv_slice(cube, P, respect_nan=False) pv = pvextractor.extract_pv_slice(cube, P, respect_nan=True) if not os.path.isdir(os.path.dirname(pvfilename)): os.mkdir(os.path.dirname(pvfilename)) pv.writeto(pvfilename) bad_cols = np.isnan(np.nanmax(pv.data, axis=0)) nandata = np.isnan(pv.data) pv.data[nandata & ~bad_cols] = 0 ok = ~nandata & ~bad_cols fig1 = pl.figure(1, figsize=figsize) fig1.clf() ax = fig1.gca() mywcs = WCS(pv.header) xext, = mywcs.sub([1]).wcs_pix2world((0,pv.shape[1]), 0)
def _slice_from_path(x, y, data, attribute, slc): """ Extract a PV-like slice from a cube :param x: An array of x values to extract (pixel units) :param y: An array of y values to extract (pixel units) :param data: :class:`~glue.core.data.Data` :param attribute: :claass:`~glue.core.data.Component` :param slc: orientation of the image widget that `pts` are defined on :returns: (slice, x, y) slice is a 2D Numpy array, corresponding to a "PV ribbon" cutout from the cube x and y are the resampled points along which the ribbon is extracted :note: For >3D cubes, the "V-axis" of the PV slice is the longest cube axis ignoring the x/y axes of `slc` """ from pvextractor import Path, extract_pv_slice p = Path(list(zip(x, y))) cube = data[attribute] dims = list(range(data.ndim)) s = list(slc) ind = _slice_index(data, slc) from astropy.wcs import WCS if isinstance(data.coords, WCS): cube_wcs = data.coords else: cube_wcs = None # transpose cube to (z, y, x, <whatever>) def _swap(x, s, i, j): x[i], x[j] = x[j], x[i] s[i], s[j] = s[j], s[i] _swap(dims, s, ind, 0) _swap(dims, s, s.index('y'), 1) _swap(dims, s, s.index('x'), 2) cube = cube.transpose(dims) if cube_wcs is not None: cube_wcs = cube_wcs.sub([data.ndim - nx for nx in dims[::-1]]) # slice down from >3D to 3D if needed s = tuple([slice(None)] * 3 + [slc[d] for d in dims[3:]]) cube = cube[s] # sample cube spacing = 1 # pixel x, y = [np.round(_x).astype(int) for _x in p.sample_points(spacing)] try: result = extract_pv_slice(cube, path=p, wcs=cube_wcs, order=0) wcs = WCS(result.header) except Exception: # sometimes pvextractor complains due to wcs. Try to recover result = extract_pv_slice(cube, path=p, wcs=None, order=0) wcs = None data = result.data return data, x, y, wcs
for line, restfreq, velocity_res, spw in line_to_image_list: basename = line frq = float(restfreq.strip('GHz')) * u.GHz vcube = cube.with_spectral_unit(u.km/u.s, velocity_convention='radio', rest_value=frq) svcube = vcube.spectral_slab((vrange[0]-1)*u.km/u.s, (vrange[1]+1)*u.km/u.s) if svcube.shape[0] <= 1: continue print("Extracting {0}: {1}".format(line, restfreq)) extracted = pvextractor.extract_pv_slice(svcube, P) #extracted.writeto(outfn, clobber=True) ww = wcs.WCS(extracted.header) ww.wcs.cdelt[1] /= 1000.0 ww.wcs.crval[1] /= 1000.0 ww.wcs.cunit[1] = u.km/u.s ww.wcs.cdelt[0] *= 3600 ww.wcs.cunit[0] = u.arcsec fig = pl.figure(1) fig.clf() ax = fig.add_axes([0.15, 0.1, 0.8, 0.8],projection=ww) ax.imshow(extracted.data, cmap='viridis') ax.set_xlabel("Offset [\"]") ax.set_ylabel("$V_{LSR}$ [km/s]")
limitedmin=[T,T,T,T,T], maxpars=[70,5,1500,1e18,10000], minpars=[40,0.1,50,1e13,min_background], signal_cut=0, maskmap=absorption_mask, errmap=err.value, multicore=4) pcube_cont.write_fit('e2e_CH3CN_Absorption_fits.fits', clobber=True) from kinematic_analysis_pv_LB import diskycoords, outflowpath import pvextractor import pylab as pl pl.figure(5).clf() for width in (None, 0.05*u.arcsec, 0.1*u.arcsec, 0.15*u.arcsec): diskypath = pvextractor.Path(diskycoords, width) extracted_disky = pvextractor.extract_pv_slice(pcube_cont.parcube[0:1,:,:], diskypath, wcs=pcube_cont.wcs) pl.plot(extracted_disky.data.squeeze(), label=str(width)) pl.xlabel("Offset (pixels)") pl.ylabel("Velocity (km/s)") pl.ylim(55,60) pl.xlim(855,890) pl.legend(loc='best') pl.savefig(paths.fpath("longbaseline/kinematics/velocity_vs_offset.png")) pl.figure(6).clf() diskypath = pvextractor.Path(diskycoords, width=None) extracted_disky = pvextractor.extract_pv_slice(pcube_cont.parcube[0:1,:,:], diskypath, wcs=pcube_cont.wcs)
'NGC4448': (-999.,900.), 'NGC4559': (-999.,1000.), 'NGC4631': (-999.,850.), 'NGC5055': (200.,800.), 'NGC5229': (-999.,470.), 'UGC2082': (550.,850.), 'UGC4278': (400.,700.), 'UGC7774': (350.,680.)} for galaxy in galaxies: pv_path = PathFromCenter(center=gvals[galaxy]['CENTER'], length=gvals[galaxy]['DIAMETER']*u.arcsec, angle=gvals[galaxy]['PA']*u.deg, width=1.*u.arcsec) pv_slice = extract_pv_slice(galaxy+'-LR-cube.fits', pv_path) hdr = pv_slice.header vaxis = (np.arange(hdr['NAXIS2'])+1.-hdr['CRPIX2'])*hdr['CDELT2']+hdr['CRVAL2'] vaxis /= 1000. if galaxy in velrange.keys(): print 'REDUCING VELOCITY RANGE' vmin, vmax = velrange[galaxy] if vmin < -998.: vmin = np.min(vaxis) gvp = np.where(np.logical_and(vaxis<=vmax,vaxis>=vmin)) print np.min(gvp), np.max(gvp), len(vaxis) data = pv_slice.data newdata = data[gvp,:] pv_slice.data = newdata voffset = np.min(gvp)
for molecule,fn in zip(molecules[-4:],filenames[-4:]): log.info(molecule) cube = spectral_cube.SpectralCube.read(fn) if weight: wcube = (spectral_cube.SpectralCube.read(hpath('APEX_H2CO_303_202_smooth_bl.fits')) if 'smooth' in fn else spectral_cube.SpectralCube.read(hpath('APEX_H2CO_303_202_bl.fits'))) if cube.shape != wcube.shape: log.info("Not weighting {0}".format(fn)) continue weighted = copy.copy(cube) weighted._data = wcube._data * cube._data pv1 = pvextractor.extract_pv_slice(weighted, P, respect_nan=True) pv2 = pvextractor.extract_pv_slice(wcube.with_mask(cube.mask), P, respect_nan=True) pv = copy.copy(pv1) pv.data = pv1.data/pv2.data else: # respect_nan = False so that the background is zeros where there is data # and nan where there is not data # But not respecting nan results in data getting averaged with nan, so we # need to respect it and then manually flag (in a rather unreliable # fashion!) #pv = pvextractor.extract_pv_slice(cube, P, respect_nan=False) pv = pvextractor.extract_pv_slice(cube, P, respect_nan=True) bad_cols = np.isnan(np.nanmax(pv.data, axis=0)) nandata = np.isnan(pv.data) pv.data[nandata & ~bad_cols] = 0
from astropy import units as u from astropy.coordinates import FK5 import numpy as np ra = [278.3947241,278.3928173,278.3896708,278.3882779,278.387925,278.3874497,278.3881945,278.3888875] dec= [-8.644493589,-8.645027916,-8.646443333,-8.648562055,-8.649796945,-8.651193056,-8.65423175,-8.655833333] for i in range(len(ra)-1): dra = ra[i+1] - ra[i] ddec = dec[i+1] - dec[i] sepa = np.sqrt((dra*np.cos(dec[i]/180.*np.pi))**2 + (ddec)**2) angle = np.arctan(ddec / (dra*np.cos(dec[i]/180.*np.pi))) / np.pi * 180. sepa *= 3600. sepa_pix = sepa/0.8 sepa_pc = sepa/3600./180.*np.pi*4600. print "Separation between points: %.2f arcsec or %.2f pixels" % (sepa, sepa_pix) print "Separation between points: %.2f pc" % (sepa_pc) print "Position angles of segments: %.2f deg" % (90 - angle) g = FK5(ra * u.deg, dec * u.deg) path0 = Path(g, width=5 * u.arcsec) slice0 = extract_pv_slice('18308_11_line.fits', path0) slice0.writeto('I18308_11_slice.fits',overwrite=True) slice1 = extract_pv_slice('18308_22_line.fits', path0) slice1.writeto('I18308_22_slice.fits',overwrite=True)
def plot_pv_diagram(image_path, outpath, coords=None, ext='.png', save=False): """ F**k Miriad and CASA, let's just use a package. Args: image_path (str): path to fits image, including extension. coords (tuple of tuples): if you have x and y values for the disk axis, enter them. """ # Not all the machines have this package installed, # so don't run it unless necessary. from pvextractor import extract_pv_slice from pvextractor import Path as PVPath # Can use this to test for points: if coords is None: keep_trying = True # For HCN xs, ys = [38, 57], [55, 45] while keep_trying: plt.close() print("Find coordinates for a line across the disk axis:") # Import and crop the data, 70 pixels in each direction. image_data_3d = fits.getdata(image_path).squeeze()[:, 80:176, 80:176] # Make a quick moment map image_data = np.sum(image_data_3d, axis=0) # Plot plt.contourf(image_data, 50, cmap='BrBG') plt.colorbar(extend='both') plt.contour(image_data, colors='k', linewidths=0.2) plt.plot(xs, ys, '-k') plt.show(block=False) response = input('\nWant to try again?\n[y/n]: ').lower() keep_trying = True if response == 'y' or response == 'yes' else False if keep_trying: xs_raw = input( 'Enter the x coordinates (previous attempt: {}):\n[x1, x2]: ' .format(xs)) xs = tuple(int(x.strip()) for x in xs_raw.split(',')) ys_raw = input( 'Enter the x coordinates (previous attempt: {}):\n[y1, y2]: ' .format(ys)) ys = tuple(int(x.strip()) for x in ys_raw.split(',')) else: xs, ys = coords path = PVPath([(xs[0], ys[0]), (xs[1], ys[1])]) pv_data = extract_pv_slice(image_data_3d, path).data.T # Make the plot. plt.close() plt.clf() fig, (ax_image, ax_pv) = plt.subplots(1, 2, figsize=(10, 5), gridspec_kw={'width_ratios': [2, 2]}) ax_image.contourf(image_data, 50, cmap='BrBG') # ax_image.colorbar(extend='both') ax_image.contour(image_data, colors='k', linewidths=0.2) ax_image.plot(xs, ys, '-k') ax_pv.contourf(pv_data, 30, cmap='inferno') # ax_pv.colorbar(extend='both') ax_pv.contour(pv_data, 30, colors='k', linewidths=0.1) # Image aesthetics pixel_to_AU = 0.045 * 389 # arcsec/pixel * distance -> AU pixel_to_as = 0.045 pv_ts = np.array(ax_pv.get_xticks().tolist()) * pixel_to_AU # pv_ticks = np.linspace(min(pv_ts), max(pv_ts), 5) - np.mean(pv_ts) start, end = ax_pv.get_xlim() pv_tick_labels = (np.linspace(start, end, 5) - np.mean([start, end])) * pixel_to_AU pv_tick_labels = [int(tick) for tick in pv_tick_labels] vmin, vmax = ax_pv.get_ylim() vel_tick_labels = np.linspace(vmin, vmax, 5) - np.mean([vmin, vmax]) vel_tick_labels = [int(tick) for tick in vel_tick_labels] ax_pv.set_xticklabels(pv_tick_labels) ax_pv.set_yticklabels(vel_tick_labels) ax_pv.set_ylabel("Velocity (km/s)", weight='bold', rotation=270) ax_pv.set_xlabel("Position Offset (AU)", weight='bold') ax_pv.yaxis.tick_right() ax_pv.yaxis.set_label_position("right") start, end = ax_image.get_xlim() image_xtick_labels = (np.linspace(start, end, 5) - np.mean([start, end])) * pixel_to_AU image_xtick_labels = [int(tick) for tick in image_xtick_labels] start, end = ax_image.get_ylim() image_ytick_labels = (np.linspace(start, end, 5) - np.mean([start, end])) * pixel_to_AU image_ytick_labels = [int(tick) for tick in image_ytick_labels] x_ts = np.array(ax_image.get_xticks().tolist()) * pixel_to_AU # image_xticks = np.linspace(min(x_ts), max(x_ts), 5) - np.mean(x_ts) # image_xtick_labels = [int(tick) for tick in image_xticks] # y_ts = np.array(ax_image.get_yticks().tolist()) * pixel_to_AU # image_yticks = np.linspace(min(y_ts), max(y_ts), 5) - np.mean(y_ts) # image_ytick_labels = [int(tick) for tick in image_yticks] # ax_image.set_xticklabels(x_ts) # ax_image.set_yticklabels(y_ts) ax_image.set_xticklabels(image_xtick_labels) ax_image.set_yticklabels(image_ytick_labels) ax_image.set_xlabel("Position Offset (AU)", weight='bold') ax_image.set_ylabel("Position Offset (AU)", weight='bold') mol = get_line(image_path).upper() plt.suptitle('Moment Map and PV Diagram for {}'.format(mol), weight='bold') # plt.tight_layout() if save: plt.savefig(outpath + ext) print("Saved PV diagram to {}{}".format(outpath, ext)) else: print("Showing:") plt.show(block=False)
cube = SpectralCube.read('FITS/Orion_NWSE_12CO2-1_merge_7m_12m.image.fits') mask = (cube.spectral_axis < 3*u.km/u.s) | (cube.spectral_axis > 14.5*u.km/u.s) cube = cube.with_mask(mask[:,None,None]) mx = cube.max(axis=0) med = cube.median(axis=0) mx = mx - med pl.close(1) for ii,(path,theta) in enumerate(zip(paths, angles)): outfilename = "pvdiagrams/NWSE_rotation_{0:0.4g}.fits".format(theta) if os.path.exists(outfilename): hdu = fits.open(outfilename)[0] else: hdu = pvextractor.extract_pv_slice(cube=cube, path=path) hdu.writeto(outfilename) print(theta,outfilename) pl.figure(1, figsize=(12,12)).clf() F = aplpy.FITSFigure(hdu, figure=pl.figure(1), subplot=[0.1, 0.6, 0.8, 0.35]) F.show_grayscale() F.set_title("Rotation {0:0.4g} degrees".format(theta)) F2 = aplpy.FITSFigure(mx.hdu, figure=pl.figure(1), subplot=[0.25,0.05, 0.5, 0.45]) F2.show_grayscale() F2.show_lines([np.array([path.ra.deg, path.dec.deg])], color='r') F2.recenter(center.ra, center.dec, radius=(1.1*u.arcmin).to(u.deg).value) F.save('pvdiagrams/NWSE_rotation_{0:04d}.png'.format(ii), dpi=300)
paths = pvextractor.pvregions.paths_from_regfile('loop_segment_30kms.reg') for mol in ("HCN","HNC","HCOp","HC3N","H2CS303-202","H2CS303202"): for pathno,path in enumerate(paths): for fn in (glob.glob("*{0}*image.pbcor.fits".format(mol)) + glob.glob("feathered/Feathered*{0}*.fits".format(mol)) + glob.glob("feathered/Regridded*{0}*fits".format(mol))): if any(x in fn for x in ('mask','max','sum','mom','pvext')): continue rcube = (SpectralCube.read(fn) .with_spectral_unit(u.km/u.s, velocity_convention='radio') .spectral_slab(0.0*u.km/u.s, 160*u.km/u.s)) slice = pvextractor.extract_pv_slice(rcube, path) slice.writeto(fn.replace(".fits",".pvextraction_path{0}.fits".format(pathno)), clobber=True) F = aplpy.FITSFigure(slice) F.show_grayscale() F.save(fn.replace(".fits",".pvextraction_path{0}.png".format(pathno))) print fn.replace(".fits",".pvextraction_path{0}.png".format(pathno)) F.show_contour('SgrB2_a_03_7M.HNC.image.pbcor.pvextraction_path0.fits') F.save(fn.replace(".fits",".pvextraction_path{0}_contourHNCACA.png".format(pathno))) F.remove_layer('contour_set_1') F.show_contour('feathered/Feathered_HNC.pvextraction_path0.fits') F.save(fn.replace(".fits",".pvextraction_path{0}_contourHNCFeath.png".format(pathno))) for ii in pl.get_fignums(): pl.close(ii)
fc='none', #transform=ax.transData, clip_on=True, #clip_box=ax.bbox, wcs=cube.data.coords.wcs) for patch in patches: patch.set_linewidth(0.5) patch.set_alpha(0.5) patch.zorder = 50 patchcoll = matplotlib.collections.PatchCollection(patches, match_original=True) patchcoll.zorder = 10 ax.add_collection(patchcoll) ax.axis([x.min(), x.max(), y.min(), y.max()]) pv = pvextractor.extract_pv_slice(cube.data['PRIMARY'], P, wcs=cube.data.coords.wcs) pvwidget = PVSliceWidget(image=pv.data, wcs=wcs.WCS(pv.header), image_client=cube_viewer, x=x, y=y, interpolation='nearest') pv_viewer = app.add_widget(pvwidget, label="Orbit PV Slice") ax2 = pvwidget.axes dl = (table['l'][1:] - table['l'][:-1]) db = (table['b'][1:] - table['b'][:-1]) dist = (dl**2 + db**2)**0.5 cdist = np.zeros(dist.size + 1) * u.deg cdist[1:] = dist.cumsum() * u.deg
assert 'cutout' in fn basename = ".".join([os.path.basename(namesplit[0]), namesplit[1], name+"_diskpv", "fits"]) outfn = paths.dpath(os.path.join("12m/pv/", basename)) cube = SpectralCube.read(fn) cube.allow_huge_operations=True cube.beam_threshold = 5 med = cube.median(axis=0) medsub = cube - med P = pvextractor.Path(diskycoords, 0.2*u.arcsec) extracted = pvextractor.extract_pv_slice(medsub, P) #extracted.writeto(outfn, clobber=True) ww = wcs.WCS(extracted.header) ww.wcs.cdelt[1] /= 1000.0 ww.wcs.crval[1] /= 1000.0 ww.wcs.cunit[1] = u.km/u.s ww.wcs.cdelt[0] *= 3600 ww.wcs.cunit[0] = u.arcsec fig = pl.figure(1) fig.clf() ax = fig.add_axes([0.15, 0.1, 0.8, 0.8],projection=ww) ax.imshow(extracted.data, cmap='viridis') ax.set_xlabel("Offset [\"]") ax.set_ylabel("$V_{LSR}$ [km/s]")
frame='fk5') xy = Path(jet_endpoints, width=2.8 * u.arcsec) for ii, (fn, stretch) in enumerate(( ('w51.neii.square.fits', 'arcsinh'), ('w51.siv.square.fits', 'log'), ('W51north_H77_Outflow_cutout.fits', 'arcsinh'), ('H77a_cutout_1.fits', 'log'), ('H77a_cutout_2.fits', 'log'), )): cube = SpectralCube.read(paths.dpath(fn)).with_spectral_unit( u.km / u.s, velocity_convention='radio', rest_value=14128610000.0 * u.Hz).spectral_slab(-200 * u.km / u.s, 200 * u.km / u.s) pv = extract_pv_slice(cube.hdu, xy) pv.data -= np.nanmin(pv.data) - 1e-3 fig = pl.figure(ii) fig.clf() FF = aplpy.FITSFigure(pv, figure=fig) FF.show_grayscale(aspect='auto', invert=True, stretch=stretch) FF.recenter(0.0021, 65e3, width=0.0042, height=300e3) FF._ax1.set_yticklabels( [str(float(L.get_text()) / 1e3) for L in FF._ax1.get_yticklabels()]) FF._ax1.set_ylabel("Velocity (km/s)") FF._ax1.set_xticklabels( [str(float(L.get_text()) * 3600) for L in FF._ax1.get_xticklabels()]) FF._ax1.set_xlabel("Offset (arcsec)") FF.save(paths.fpath('jetpv/{0}.png'.format(fn[:-5]))) FF.save(paths.fpath('jetpv/{0}.pdf'.format(fn[:-5])))
#('w51_12CO_21_contsub_hires.image.pbcor.fits', 'arcsinh', -0.01, 0.2, # 'e8'), )): pars = parameters[source] cube = SpectralCube.read(paths.dpath(fn)) cube = cube.with_spectral_unit(u.km / u.s, velocity_convention='radio') cube = cube.spectral_slab(-200 * u.km / u.s, 200 * u.km / u.s) outname = os.path.split('{0}_{1}.{{extension}}'.format(fn[:-5], source))[-1] outpath_pv = paths.dpath('pv/' + outname.format(extension='fits')) if not os.path.exists(outpath_pv): pv = extract_pv_slice(cube.hdu, pars['path']) #pv.data -= np.nanmin(pv.data) - 1e-3 pv.writeto(outpath_pv, clobber=True) else: pv = fits.open(outpath_pv)[0] origin = offset_to_point(pars['origin'].ra.deg, pars['origin'].dec.deg, pars['path']) fig = pl.figure(ii) fig.clf() FF = aplpy.FITSFigure(pv, figure=fig) FF.show_grayscale(aspect='auto', invert=True, stretch=stretch, vmin=vmin,
#ax.plot(table['l'], table['b'], 'r-', linewidth=2, alpha=0.5) #ax.plot(x, y, 'r-', linewidth=2, alpha=0.5) patches = P.to_patches(1, ec='red', fc='none', #transform=ax.transData, clip_on=True, #clip_box=ax.bbox, wcs=cube.data.coords.wcs) for patch in patches: patch.set_linewidth(0.5) patch.set_alpha(0.5) patch.zorder = 50 patchcoll = matplotlib.collections.PatchCollection(patches, match_original=True) patchcoll.zorder=10 ax.add_collection(patchcoll) ax.axis([x.min(),x.max(),y.min(),y.max()]) pv = pvextractor.extract_pv_slice(cube.data['PRIMARY'], P, wcs=cube.data.coords.wcs) pvwidget = PVSliceWidget(image=pv.data, wcs=wcs.WCS(pv.header), image_client=cube_viewer, x=x, y=y, interpolation='nearest') pv_viewer = app.add_widget(pvwidget, label="Orbit PV Slice") ax2 = pvwidget.axes dl = (table['l'][1:]-table['l'][:-1]) db = (table['b'][1:]-table['b'][:-1]) dist = (dl**2+db**2)**0.5 cdist = np.zeros(dist.size+1) * u.deg cdist[1:] = dist.cumsum() * u.deg #pixscale = ((x[1]-x[0])**2+(y[1]-y[0])**2)**0.5 pixscale = wcs.utils.celestial_pixel_scale(cube.data.coords.wcs) spwcs = cube.data.coords.wcs.sub([wcs.WCSSUB_SPECTRAL])
basename = ".".join([os.path.basename(namesplit[0]), namesplit[1], name+"_diskpv", "fits"]) outfn = paths.dpath(os.path.join("12m/pv/", basename)) print("Extracting {0} {2}: {1}".format(fn, direction, name)) cube = SpectralCube.read(fn) cube.allow_huge_operations=True cube.beam_threshold = 5 med = cube.median(axis=0) medsub = cube - med extraction_path = pvextractor.Path(diskycoords, 0.2*u.arcsec) extracted = pvextractor.extract_pv_slice(medsub, extraction_path) #extracted.writeto(outfn, clobber=True) ww = wcs.WCS(extracted.header) ww.wcs.cdelt[1] /= 1000.0 ww.wcs.crval[1] /= 1000.0 ww.wcs.cunit[1] = u.km/u.s ww.wcs.cdelt[0] *= 3600 ww.wcs.cunit[0] = u.arcsec fig = pl.figure(1) fig.clf() ax = fig.add_axes([0.15, 0.1, 0.8, 0.8],projection=ww) ax.imshow(extracted.data, cmap='viridis') ax.set_xlabel("Offset [\"]") ax.set_ylabel("$V_{LSR}$ [km/s]")
mask = BooleanArrayMask(mask=np.isfinite(hdu[0].data), wcs=WCS(hdu[0].header)) sc = SpectralCube(data=hdu[0].data, wcs=WCS(hdu[0].header), mask=mask) # Select the region of interest sc_small = sc[120:300, 156:346, 677:958] # Ends for the PV slice # ends = [(107, 74), (151, 76), (220, 54)] ends = [(105, 70), (145, 80), (227, 28), (238, 1)] xy = Path(ends, width=10) pv = extract_pv_slice(sc_small, xy) p.subplot(121) p.imshow(sc_small.moment0().value, cmap="binary", origin="lower") p.plot([i for i, j in ends], [j for i, j in ends], 'b-') p.subplot(122) p.imshow(pv.data, cmap="binary", origin="lower") p.colorbar() p.show() hdu.close() # Now examine a subsection of the region that overlaps with the edge of # NGC-1333. I'm not sure the instrument that took the data, but it maps
basename = line frq = float(restfreq.strip('GHz')) * u.GHz vcube = cube.with_spectral_unit(u.km/u.s, velocity_convention='radio', rest_value=frq) svcube = vcube.spectral_slab((vrange[0]-1)*u.km/u.s, (vrange[1]+1)*u.km/u.s) if svcube.shape[0] <= 5: print("SKIPPING {3} {0} {2}: {1}".format(line, restfreq, direction, name)) continue print("Extracting {3} {0} {2}: {1}".format(line, restfreq, direction, name)) extracted = pvextractor.extract_pv_slice(svcube, extraction_path) #extracted.writeto(outfn, clobber=True) ww = wcs.WCS(extracted.header) ww.wcs.cdelt[1] /= 1000.0 ww.wcs.crval[1] /= 1000.0 ww.wcs.cunit[1] = u.km/u.s ww.wcs.cdelt[0] *= 3600 ww.wcs.cunit[0] = u.arcsec fig = pl.figure(1) fig.clf() ax = fig.add_axes([0.15, 0.1, 0.8, 0.8],projection=ww) ax.imshow(extracted.data, cmap='viridis', vmin=-0.005) ax.set_xlabel("Offset [\"]") ax.set_ylabel("$V_{LSR}$ [km/s]")
log.info(molecule) cube = spectral_cube.SpectralCube.read(fn) if weight: wcube = (spectral_cube.SpectralCube.read( hpath('APEX_H2CO_303_202_smooth_bl.fits')) if 'smooth' in fn else spectral_cube.SpectralCube.read( hpath('APEX_H2CO_303_202_bl.fits'))) if cube.shape != wcube.shape: log.info("Not weighting {0}".format(fn)) continue weighted = copy.copy(cube) weighted._data = wcube._data * cube._data pv1 = pvextractor.extract_pv_slice(weighted, P, respect_nan=True) pv2 = pvextractor.extract_pv_slice(wcube.with_mask(cube.mask), P, respect_nan=True) pv = copy.copy(pv1) pv.data = pv1.data / pv2.data else: # respect_nan = False so that the background is zeros where there is data # and nan where there is not data # But not respecting nan results in data getting averaged with nan, so we # need to respect it and then manually flag (in a rather unreliable # fashion!) #pv = pvextractor.extract_pv_slice(cube, P, respect_nan=False) pv = pvextractor.extract_pv_slice(cube, P, respect_nan=True) bad_cols = np.isnan(np.nanmax(pv.data, axis=0)) nandata = np.isnan(pv.data)
header[kw+"2"] = header[kw+"3"] del header[kw+"3"] header['CTYPE1'] = 'OFFSET' header = pvextractor.utils.wcs_slicing.slice_wcs(WCS(header), spatial_scale=7.2*u.arcsec).to_header() pv = fits.PrimaryHDU(data=pv1/pv2, header=header) pv2hdu = fits.PrimaryHDU(data=pv2, header=header) else: # respect_nan = False so that the background is zeros where there is data # and nan where there is not data # But not respecting nan results in data getting averaged with nan, so we # need to respect it and then manually flag (in a rather unreliable # fashion!) #pv = pvextractor.extract_pv_slice(cube, P, respect_nan=False) pv = pvextractor.extract_pv_slice(cube, P, respect_nan=True) if not os.path.isdir(os.path.dirname(pvfilename)): os.mkdir(os.path.dirname(pvfilename)) pv.writeto(pvfilename) bad_cols = np.isnan(np.nanmax(pv.data, axis=0)) nandata = np.isnan(pv.data) pv.data[nandata & ~bad_cols] = 0 ok = ~nandata & ~bad_cols if 'TemperatureFromRatio' in molecule: pv.data[ok] = pwtem(pv.data[ok]) fig1 = pl.figure(1, figsize=figsize) fig1.clf()
LSB = SpectralCube.read(LSB_file) USB = SpectralCube.read(USB_file) ################################################################################################### # generate pV in pvextractor ################################################################################################### from pvextractor import PathFromCenter from pvextractor import extract_pv_slice full = PathFromCenter(center=kin_center, length=60*u.arcsec, angle=disk_PA, width=30*u.arcsec) maj = PathFromCenter(center=kin_center, length=60*u.arcsec, angle=disk_PA, width=1*u.arcsec) LSB_pV_full = extract_pv_slice(LSB, full) LSB_pV_maj = extract_pv_slice(LSB, maj) USB_pV_full = extract_pv_slice(USB, full) USB_pV_maj = extract_pv_slice(USB, maj) # offset is in degrees, frequency in Hz # convert to reasonable units # shift offset axis so that 0 corresponds to the kinematic center for h in [LSB_pV_full.header, LSB_pV_maj.header, USB_pV_full.header, USB_pV_maj.header]: h['crval1'] *= 60*60 h['cdelt1'] *= 60*60 h['cunit1'] = 'arcsec' h['crval2'] /= 1e9 h['cdelt2'] /= 1e9 h['cunit2'] = 'GHz' h['crval1'] = 0.
83.77088618, 83.79621755, 83.82001665, 83.84612392, 83.8783804, 83.91332917, 83.95142695, 83.98952916, 84.0308125, 84.07400417, 84.11910176, 84.1642031 ] * u.deg, [ -4.876200218, -4.879461026, -4.897820323, -4.915411506, -4.93299871, -4.965857804, -4.99067018, -5.033833723, -5.076613716, -5.123974925, -5.173573767, -5.222459592, -5.271344718, -5.318700697, -5.36452826, -5.412955261, -5.461988054, -5.510106789, -5.555931851, -5.605577113, -5.6519109, -5.701555547, -5.752730272, -5.801156183, -5.84927762, -5.897401317, -5.940943148, -5.986011267, -6.029551074, -6.068507208, -6.103567778, -6.135131552, -6.166692778, -6.195094167, -6.219704167, -6.240522195, -6.261336664 ] * u.deg) path4 = Path(fk, width=6 * u.arcmin) slice3 = extract_pv_slice( '/Users/shuokong/GoogleDrive/13co/products/regrid_12co_specsmooth_0p25_mask_imfit_13co_pix_2_Tmb.fits', path4) slice3.writeto('my_slice.fits') import aplpy import matplotlib.pyplot as plt fig = plt.figure() gc = aplpy.FITSFigure('my_slice.fits', dimensions=[0, 1], figure=fig, hdu=0) gc.show_colorscale(aspect='auto') gc.ticks.set_xspacing(21.) gc.ticks.set_minor_frequency(7) gc.axis_labels.set_ytext('Velocity (km/s)') gc.ticks.show() gc.ticks.set_color('black') gc.ticks.set_length(10)
os.path.join( 'pv', os.path.split( fn.replace( ".image.pbcor.fits", "_medsub_diskpv_{0}.fits".format(width)))[-1])) if not os.path.exists(outfn): # width = 0.05 arcsec encompasses the disk; however, most # of the actual line emission comes from just above/below... #extraction_path = pvextractor.Path(diskycoords, width=0.05*u.arcsec) extraction_path = pvextractor.Path(diskycoords, width=width * u.arcsec) log.info( "Beginning extraction of path with width {0} for {1}". format(extraction_path.width, outfn)) extracted = pvextractor.extract_pv_slice( medsub, extraction_path) log.info("Writing to {0}".format(outfn)) extracted.writeto(outfn, overwrite=True) for linename, linefreq in disk_lines.items(): print(linename, width, fnt, spw, time.time() - t0) pl.close('all') band = 'B' + bandre.search(fnt).groups()[0] if 'robust' in fn: robustnum = robustnumre.search(fn).groups()[0] basename = ( "{0}_{1}_{4}_robust{2}_diskpv_{3}.fits".format( name, linename, robustnum, width, band))
rotation_axis_len = 50 pv_path_1 = (source_position_px[0], source_position_px[1] - rotation_axis_len / 2.0 ) # (x, y) pixel values pv_path_2 = (source_position_px[0], source_position_px[1] + rotation_axis_len / 2.0 ) # (x, y) pixel values # The path defines the line, whereupon normal # dimension is collapsed. I.e. the path line defines the offset direction # vector in the pv diagram. image_path = Path([pv_path_1, pv_path_2]) data_cube, hdr = load_fits_cube(cube_file) hdu = extract_pv_slice(data_cube, image_path) save_extracted_pv_slice_hdu(hdu, hdr, PV_file_name) n_x = int(hdr['NAXIS1']) n_chan = int(hdr['NAXIS2']) font_size = 12 fig = plt.figure() ax = fig.add_subplot(1, 1, 1) image_data, im_hdr = load_fits_im(PV_file_name) im = ax.imshow(image_data, aspect='auto', interpolation='nearest', cmap=plt.cm.YlOrBr,