def test_region(): ref_region_name = "test01_img.reg" region_list = ["test01_fk5_sexagecimal.reg", "test01_gal.reg", "test01_ds9_physical.reg", "test01_fk5_degree.reg", "test01_mixed.reg", "test01_ciao.reg", "test01_ciao_physical.reg", ] header = demo_header() ref_region = pyregion.open(join(rootdir,ref_region_name)).as_imagecoord(header) for reg_name in region_list: r = pyregion.open(join(rootdir,reg_name)).as_imagecoord(header) for reg0, reg in zip(ref_region, r): if reg.name == "rotbox": reg.name = "box" assert reg0.name == reg.name if reg0.name in ["ellipse", "box"]: assert np.allclose(reg0.coord_list[:-1], reg.coord_list[:-1], atol=0.01) a0 = reg0.coord_list[-1] a1 = fix_lon(reg.coord_list[-1], 0) assert np.allclose([a0], [a1], atol=0.02) else: assert np.allclose(reg0.coord_list, reg.coord_list, atol=0.01) assert reg0.exclude == reg.exclude
def subcubes_from_ds9(cube, region_file='../nro_maps/SouthShells.reg', pad_factor=1., shape='exact'): """ Extracts subcubes using the ds9 region file. Parameters ---------- cube : SpectralCube, str The cube to be chopped. Must be type spectral_cube.SpectralCube or str filename. region_file : str Path to a ds9 region file. pad_factor : float, optional Expand the subcube around the region by this factor. shape : {'square', 'exact'} The shape of the subcube returned. 'square' returns the smallest square subcube that contains the region. 'exact' returns only the pixels contained within the region. Returns ------- subcubes: list of SpectralCube of SpectralCube """ from spectral_cube import SpectralCube import pyregion try: #If cube is a str filename, read a SpectralCube. cube = SpectralCube.read(cube) except ValueError: pass if shape == 'square': import astropy.units as u subcube_list = [] region_list = pyregion.open(region_file) for region in region_list: half_width = region.coord_list[2] * pad_factor * u.deg ra_center = region.coord_list[0] * u.deg dec_center = region.coord_list[1] * u.deg ra_range = [ra_center - half_width, ra_center + half_width] dec_range = [dec_center - half_width, dec_center + half_width] #print(ra_range, dec_range) subcube_list.append(cube.subcube(ra_range[1], ra_range[0], dec_range[0], dec_range[1])) if shape == 'exact': region_list = pyregion.open(region_file) subcube_list = [] for region in region_list: if pad_factor != 1.: new_string = '{};{}({},{},{}")'.format(region.coord_format, region.name, region.coord_list[0], region.coord_list[1], region.coord_list[2]*3600.*pad_factor) region = pyregion.parse(new_string)[0] subcube_list.append(cube.subcube_from_ds9region(pyregion.ShapeList([region]))) if len(subcube_list) == 1: return subcube_list[0] else: return subcube_list
def __init__(self, x, y, regfile, header=None): """ Parse the ds9 region file here. Also save the number of regions and the x y dimensions of the data""" if(header): self.reg = pyreg.open(regfile).as_imagecoord(header=header) else: self.reg = pyreg.open(regfile) self.filter = self.reg.get_filter() self.x = x self.y = y self.nreg = len(self.reg)
def radioflux(files,fgr,bgr=None,individual=False,action='Flux',fluxerr=0,nsigma=0,verbose=False): """Determine the flux in a region file for a set of files. This is the default action for the code called on the command line, but may be useful to other code as well. Keyword arguments: files -- list of files (mandatory) fdr -- foreground region name (mandatory) bgr -- background region name (optional) individual -- separate region into individual sub-regions action -- what to do once fluxes are measured: allows a user-defined action which must be a drop-in replacement for printflux fluxerr -- flux error in % for spidxmap nsigma -- keep only pixels above these sigma level in ALL maps (bgr must be specified) """ action = {'flux':printflux, 'mean':printmean, 'spidx':printspidx}[action] rms = [] # radio maps for filename in files: rms.append(radiomap(filename,verbose=verbose)) # if using the sigma all the images must have the same size if nsigma > 0: assert all(rms[i].d[0].size == rms[0].d[0].size for i in range(len(rms))) # initial mask mask = (np.zeros_like(rms[0].d) == 0) bgs = [] #1d list: [ radiomap ] for rm in rms: if bgr: bg_ir=pyregion.open(bgr).as_imagecoord(rm.headers[0]) bg=applyregion(rm,bg_ir) bgs.append(bg.rms) # likely brakes with channelled images if nsigma > 0: mask = np.logical_and(mask, np.array(rm.d) > (np.array(bg.rms)*nsigma) ) else: bgs.append(None) fgs = [] # 2d list: [ radiomap x forground_region] for i, rm in enumerate(rms): fg_ir=pyregion.open(fgr).as_imagecoord(rm.headers[0]) if individual: fgs.append([]) for fg_ir_split in fg_ir: fg=pyregion.ShapeList([fg_ir_split]) fgs[-1].append(applyregion(rm,fg,offsource=bgs[i],mask=mask)) else: fgs.append([applyregion(rm,fg_ir,offsource=bgs[i],mask=mask)]) # cycle before on regions and than on rm fgs = np.array(fgs).swapaxes(0,1) action(fgs, fluxerr)
def photometry(dither=1): # read in region file if dither == 2: image,hdr = pyfits.getdata('L1544_J_dither2.fits', header=True) regpix = pyregion.open('L1544_pix_dither2.reg') else: image,hdr = pyfits.getdata('L1544_J_dither1.fits', header=True) regpix = pyregion.open('L1544_pix_dither1.reg') nx1 = hdr['NAXIS1'] nx2 = hdr['NAXIS2'] # calc_maglim(image, nx1, nx2) regsky = pyregion.open('L1544_sky.reg') names = ('star', 'ra', 'dec', 'xc', 'yc', 'flux', 'eflux', 'mag', 'emag') dtypes = ('int', 'S11', 'S11', 'float', 'float', 'float', 'float', 'float', 'float') t = Table(data=None, names=names, dtype=dtypes) # centroid sources cenx = np.zeros(len(regpix), dtype=float) ceny = np.zeros(len(regpix), dtype=float) for i,star in enumerate(regpix): id = star.comment ra = regsky[i].coord_list[0] dec = regsky[i].coord_list[1] # x_init = star.coord_list[0] # y_init = star.coord_list[1] cenx = star.coord_list[0] ceny = star.coord_list[1] # # centroid by fitting a 2D Gaussian # cenx,ceny = gauss_centroid(image, x_init, y_init) t.add_row([id, ra, dec, cenx, ceny, 0.0, 0.0, 0.0, 0.0]) # perform aperture photometry # 30 pixels in radius and sky annuli at 30-50 pixels table = apphot(image, t, 15, [20,30], return_mag=True) formats = {'xc':'%8.3f', 'xc':'%8.3f', 'flux':'%7.2f', \ 'eflux':'%6.2f', 'mag':'%6.3f', 'emag':'%5.3f'} if dither == 2: table.write('flux_dither2.txt', format='ascii.tab', formats=formats) else: table.write('flux_dither1.txt', format='ascii.tab', formats=formats)
def selftest_dor(self, fig=True): """ graphic test of transformations; needs a couple of test files """ import os.path regfile = "30dor.pacs100.test.reg" datfile = "30dor.pacs160.fits" if not os.path.exists(regfile): raise Exception("Need test file " + regfile) if not os.path.exists(datfile): raise Exception("Need test file " + datfile) # need an image f = pyfits.open(datfile) # if hdu 0 has no data, go to hext hdu - if wcs is in hdu0 and data # in hdu1 then we'll be in trouble. i = 0 while len(f[i].data) < 1: i = i + 1 import pyregion pyreg = pyregion.open(regfile) print("a polygon region") self.setpoly(pyreg[1].coord_list) if fig: pl.figure() self.selftest(f[i], fig=fig) print "press enter" x = raw_input() print("a circle region") self.setcircle(pyreg[0].coord_list) if fig: pl.figure() self.selftest(f[i], fig=fig)
def getregionboxcenter(regionfile): """ Extract box center of a DS9 box region. Input is regionfile Return NDPPP compatible string for phasecenter shifting """ r = pyregion.open(regionfile) if len(r[:]) > 1: print 'Only one region can be specified, your file contains', len(r[:]) sys.exit() if r[0].name != 'box': print 'Only box region supported' sys.exit() ra = r[0].coord_list[0] dec = r[0].coord_list[1] boxsizex = r[0].coord_list[2] boxsizey = r[0].coord_list[3] angle = r[0].coord_list[4] if boxsizex != boxsizey: print 'Only a square box region supported, you have these sizes:', boxsizex, boxsizey sys.exit() if np.abs(angle) > 1: print 'Only normally oriented sqaure boxes are supported, your region is oriented under angle:', angle sys.exit() regioncenter = ('{:12.8f}'.format(ra) + 'deg,' + '{:12.8f}'.format(dec) + 'deg').replace(' ', '') return regioncenter
def identifysrcinreg(xSrc, ySrc, regFile): '''Returns source mask array for sources that appear in the regions of regFile (in image coordinates) ''' # Initialize Mask Array msk = np.zeros(xSrc.size, dtype=np.bool) # Read in Regions regs = pyregion.open(regFile) if regs[0].coord_format != 'image': raise ValueError('"image" format only supported region format.') # Identify Sources for reg in regs: if reg.name == 'circle': x, y, r = reg.coord_list inReg = ((xSrc - x)**2 + (ySrc - y)**2 <= r**2) msk[inReg] = True elif reg.name == 'ellipse': x, y, a, b, t = reg.coord_list X = (xSrc - x) * np.cos(np.radians(t)) + (ySrc - y) * np.sin( np.radians(t)) Y = (xSrc - x) * np.sin(np.radians(t)) - (ySrc - y) * np.cos( np.radians(t)) inReg = ((X / a)**2 + (Y / b)**2 <= 1) msk[inReg] = True else: warnings.warn('Region Type "{}" not recognized.'.format(reg.name), RuntimeWarning) # Return return msk
def ds9(regionfile, header, zorder=3, **kwargs): """ Wrapper to return a PatchCollection given a ds9 region file and a fits header. zorder - defaults to 3 so that regions are on top of contours """ # read region file rr = pyregion.open(regionfile) # convert coordinates to image coordinates rrim = rr.as_imagecoord(header) # pyregion and aplpy both correct for the FITS standard origin=1,1 # need to avoid double-correcting for r in rrim: r.coord_list[0] += 1 r.coord_list[1] += 1 if 'text_offset' in kwargs: text_offset = kwargs['text_offset'] del kwargs['text_offset'] else: text_offset = 5.0 # grab the shapes to overplot pp, aa = rrim.get_mpl_patches_texts(text_offset=text_offset) PC = ArtistCollection(pp, **kwargs) # preserves line style (dashed) TC = ArtistCollection(aa, **kwargs) PC.set_zorder(zorder) TC.set_zorder(zorder) return PC, TC
def subtract_fringe(image, template, kwargs): log = get_log_func(default_level='debug', **kwargs) fringe = fits.open(template, memmap=True) hdulist = fits.open(image, memmap=True) layout = get_layout(hdulist) for ext, hdu in layout.enumerate(hdulist): ota = layout.get_ext_ota(ext) log("work on ext {} OTA {}".format(ext, ota)) # get pupilmask regmask_file = os.path.join(os.path.dirname(__file__), 'pupilmask', 'pg_large{}.reg'.format(ota)) if os.path.exists(regmask_file): log("read pupil region mask {}".format(regmask_file)) hdu = fits.ImageHDU(data=hdu.data) pmask = pyregion.open(regmask_file).get_mask(hdu=hdu) pmask = ~pmask # outside is True else: pmask = np.ones_like(hdu.data, dtype=bool) # get fringe mask fmask = mask_fringe(fringe[ext].data, layout, thresh=0.8) fmask[~pmask] = np.nan # inside pupil is nan hdulist[ext].data = de_fringe(hdu.data, fringe[ext].data, fmask, ota, log) return hdulist
def makeClusterCat(regfile, clusterfile): print 'reading', regfile regions = pyregion.open(regfile) centers = np.zeros(len(regions[:]), dtype=([('Name', 'S200'), ('ra', '<f8'), ('dec', '<f8'), ('SumI', '<f8'), ('Cluster', '<i8')])) print 'Number of directions', len(regions[:]) for region_id, regions in enumerate(regions[:]): #print region_id ra = np.pi * regions.coord_list[0] / 180. dec = np.pi * regions.coord_list[1] / 180. centers[region_id][0] = '' centers[region_id][1] = ra centers[region_id][2] = dec centers[region_id][3] = 0. centers[region_id][4] = region_id #print centers[region_id] #sys.exit() print centers np.save(clusterfile, centers) print 'saving', clusterfile
def _cut_stamps_regions(source_file, region_file, source_ext=0, file_prefix='', selected_labels=None, **kwargs): """ Cuts stamps from a FITS image based on a DS9 region file. See docstring for cut_stamps for argument explanations """ # Open region file first, so parse errors will fail before trying to open # a potentially large FITS file regions = pyregion.open(region_file) # Open cutting image hdu_list = fits.open(source_file, mode='readonly', ignore_missing_end=True) # Translate to image coordinates, since we're working in pixel space regions = regions.as_imagecoord(hdu_list[source_ext].header) # If a region has a text label, use that as the default file name # reg.attr[1] is a dictionary of extended region attributes names = [reg.attr[1].get('text', str(num)) for num, reg in enumerate(regions)] if selected_labels is None: selected_labels = set(names) all_stamp_names = [] for name in set(names) & selected_labels: regs_for_name = [reg for reg, nm in zip(regions, names) if nm == name] stamp = _stamp_from_regions(hdu_list, regs_for_name, extension=source_ext, **kwargs) filename = file_prefix + name + '.fits' stamp.writeto(filename, clobber=True) all_stamp_names += [filename] hdu_list.close() return all_stamp_names
def gal2cel(regfile): """ Converts a region file from galactic to celestial coordinates including position angle reference from the center of the box (right now only works on box regions) Requires pyregion with the ShapeList.write() function implemented... not clear if that exists in 1.0 """ reg = pyregion.open(regfile) for R in reg: if R.name == "box": x, y, dx, dy, angle = R.coord_list # posn = coords.Position([x,y],system='galactic') # ra,dec = posn.j2000() posn = coordinates.Galactic(x * u.deg, y * u.deg) ra, dec = posn.fk5.ra.deg, posn.fk5.dec.deg newang = posang.posang(x - dx, y, x + dx, y, system="galactic") coord_list = [ra, dec, dx, dy, angle - newang - 90] R.coord_format = "fk5" R.coord_list = coord_list R.params = coord_list reg.write(regfile[:-4] + "_fk5.reg")
def select_and_bin(): """ """ logger.info('Creating the mapcube for the entire source...') pipeline.xpbin(evt_file_path, algorithm='MCUBE', ebinalg='LIST', ebinning=E_BINNING) logger.info('Opening region file %s...' % reg_file_path) regions = pyregion.open(reg_file_path) logger.info('Found %d regions...' % len(regions)) for i, region in enumerate(regions): ra, dec, rad = region.coord_list rad *= 60. logger.info('Analyzing region at ra = %s, dec = %s' % (ra, dec)) sel_file_path = get_sel_file_path(i) mcube_file_path = get_mcube_file_path(i) pipeline.xpselect(evt_file_path, ra=ra, dec=dec, rad=rad, outfile=sel_file_path) pipeline.xpbin(sel_file_path, algorithm='MCUBE', ebinalg='LIST', ebinning=E_BINNING, outfile=mcube_file_path)
def set_basic_info(self): """compile and rename parameters from several catalogs""" q0 = 0.2 ks = pyfits.open(infodir+'kingfish_sample.fits')[1].data dk = pyfits.open(infodir+'dalephot_kingfish.fits')[1].data fkh = pyfits.open(infodir+'fisher_Hband_kingfish.fits')[1].data sk = pyfits.open(infodir+'skibba_kingfish.fits')[1].data ak = pyfits.open(infodir+'aniano_kingfish_S250_100_SSS_100_vOct2012.fits')[1].data reg = pyregion.open(self.kdir+'photometry/dale_region_files'+self.kname+'.deg.reg') ind = (np.where(ks['NAME'] == self.kname))[0] self.info['ra'] = ks['RA'][ind] self.info['dec'] = ks['DEC'][ind] self.info['dist'] = ak['DIST'][ind] self.arcsec_to_kpc = self.info['dist']*1e3/206265.0 self.info['a'] = ks['SEMIMAJOR'][ind] self.info['b'] = ks['SEMIMINOR'][ind] self.info['pa'] = reg[0].coord_list[2] q = self.info['b']/self.info['a'] self.info['inclination'] = np.arccos(np.sqrt( (q^2- q0^2)/(1 - q0^2)))*(180./np.pi) + 3.0 self.info['R_e'] = {'obs':fkh['R_EFF_BULGE'][ind]} #half-light radius in arcsec self.info['mu_e'] = {'obs':fkh['MU_EFF'][ind]} #in AB mag/arcsec**2 at H band self.info['n_bulge'] = fkh['N_BULGE'][ind] #sersic self.info['H_disk'] = {'obs':fkh['R_DISK'][ind]} #exponential scale length in arcsec self.info['mu0'] = {'obs':fkh['MU_0_DISK'][ind]} #in AB mag/arcsec**2 at H band self.info['R_e']['phys'] = fkh['R_EFF_BULGE'][ind]*self.arcsec_to_kpc #half-light radius in kpc self.info['H_disk']['phys'] = fkh['R_DISK'][ind]*self.arcsec_to_kpc #exponential scale length in arcsec #self.info[['mu0']['phys'] = #self.info[['mu_e']['phys'] = self.info['morph_band'] = 'twomass_H' self.info['type'] = sk['MORPH'][ind]
def get_coord_centroid(filename, region): """ Get centroid coordinates from an image and a region filename: fits file region: ds9 region """ import astropy.io.fits as pyfits import astropy.wcs as pywcs import pyregion from scipy.ndimage.measurements import center_of_mass fits = pyfits.open(filename) header, data = flatten(fits) # extract mask and find center of mass r = pyregion.open(region) mask = r.get_mask(header=header, shape=data.shape) dec_pix, ra_pix = center_of_mass(mask) # convert to ra/dec in angle w = pywcs.WCS(fits[0].header) #w = w.celestial # needs newer astropy ra, dec = w.all_pix2world(ra_pix, dec_pix, 0, 0, 0, ra_dec_order=True) fits.close() return float(ra), float(dec)
def read_mask(maskfile, fitsfile, wolly=False, return_shape=False): '''Parse mask file and return masked region. If 'wolly' is True, return two masks.''' import pyregion if isinstance(fitsfile, str): hdu = fits.open(fitsfile) else: hdu = fitsfile reg = pyregion.open(maskfile) # total mask mask = ~pyregion.get_mask(reg, hdu[0]) if wolly: # return three masks: (top, bottom, total) if len(reg) != 2: raise AttributeError("Wolly masks must have two regions") # make total mask reg = [pyregion.ShapeList([r]) for r in reg] pmask = [~pyregion.get_mask(r, hdu[0]) for r in reg] pmask.append(mask) mask = pmask if return_shape: shapes = [mask_shape(m) for m in mask] mask = tuple(pmask + shapes) #mask is (top,bottom,total,shape_top,shape_bot,shape_total) else: if return_shape: mask = (mask, mask_shape(mask)) return mask
def add_cloud_region(core_dict): import pyregion as pyr data_dir = '/d/bip3/ezbc/multicloud/data/cold_clumps/' region_dir = '/d/bip3/ezbc/multicloud/data/python_output/regions/' #filename = region_dir + 'multicloud_divisions_coldcore_selection.reg' filename = region_dir + 'multicloud_divisions.reg' # region[0] in following format: # [64.26975, 29.342033333333333, 1.6262027777777777, 3.32575, 130.0] # [ra center, dec center, width, height, rotation angle] regions = pyr.open(filename) for region in regions: # Cores defined in following format: 'tag={L1495A}' tag = region.comment region_name = tag[tag.find('{')+1:tag.find('}')].lower() if region_name in ('taurus', 'california', 'perseus'): # Format vertices to be 2 x N array poly_verts = [] for i in xrange(0, len(region.coord_list)/2): poly_verts.append((region.coord_list[2*i], region.coord_list[2*i+1])) for core in core_dict: if core_dict[core]['cloud'] == region_name: core_dict[core]['cloud_region_vertices'] = \ np.array(poly_verts) return core_dict
def read_ds9_region(filename): ''' Converts DS9 region file into format for plotting region. Need the following format: angle : degrees xy : pixels width : pixels height : pixels Region file provides following format: # Region file format: DS9 version 4.1 global color=green dashlist=8 3 width=1 font="helvetica 10 normal roman" select=1 highlite=1 dash=0 fixed=0 edit=1 move=1 delete=1 include=1 source=1 fk5 box(4:17:04.740,+29:20:31.32,5854.33",11972.7",130) # text={test} pyregion module reads DS9 regions: http://leejjoon.github.io/pyregion/users/overview.html ''' # Import external modules import pyregion as pyr # Read region file region = pyr.open(filename) # region[0] in following format: # [64.26975, 29.342033333333333, 1.6262027777777777, 3.32575, 130.0] # [ra center, dec center, width, height, rotation angle] return region[0].coord_list
def regtouptime(regfile,outfile,maxza=15.0): """ Converts a region file to a list of target names + how long they are observable @ arecibo maxza = 15.0 degrees for "broken" Arecibo (2010) or 18-19 for normal Arecibo """ # coordinates @ http://www.naic.edu/~astro/guide/node2.html ra_arecibo = (66+45/60.+11.1/3600.) dec_arecibo = (18+20/60.+36.6/3600.) reg = pyregion.open(regfile) outf = open(outfile,'w') for r in reg: #if r.attr[1]['color'] == filtercolor or not r.attr[1].has_key('text'): # continue text = pos_to_name(r) radec = position_region(r).hmsdms() ra,dec = position_region(r).j2000() za_min = numpy.abs(dec-dec_arecibo) # isoscoles triangle with za_min as perpendicular bisector, maxza as long leg lenth tup = numpy.sqrt(maxza**2-za_min**2)*2.0/15.0 * 60.0 # minutes print >>outf,'%12s %10.2f %10.1f' % (text,za_min,tup) outf.close()
def area_within_reg(reg_name,base_fits=m31): ''' returns deg^s deg^2 to arcsec^2: areas*3600.*3600. deg^2 to arcmin^2: areas*3600. ''' # finds area of concentric reg shapes # use GenUtils.area for the area of a polygon. tot_areas,areas = [],[] proj = wcs.Projection(f_header) r = pyregion.open(reg_name).as_imagecoord(header=f_header) patch_list, artist_list = r.get_mpl_patches_texts() for p in patch_list[::-1]: verts_xy = p.get_xy() pixels = (verts_xy[:,0],verts_xy[:,1]) ra_v,dec_v = proj.toworld(pixels) verts = np.column_stack((ra_v,dec_v)) tot_areas.append(area(verts)) for i in range(len(tot_areas)): if i == len(tot_areas)-1: areas.append(tot_areas[i]) else: areas.append(tot_areas[i]-tot_areas[i+1]) # deg^2 to arcsec^2: areas*3600.*3600. # deg^2 to arcmin^2: areas*3600. return np.array(areas)
def create_patches(): ''' In the current figure, plot patches ''' patches = np.genfromtxt( '/Users/osejo/Desktop/Tesis/massivend/k_catalog/automatize/0215/names_w' + str(fieldw) + '.txt', dtype=str) for patch in patches: region_name = '/Users/osejo/Desktop/Tesis/massivend/k_catalog/automatize/0215/environment/sfandpe/density_plots/masks/w' + str( fieldw) + '/w' + str(fieldw) + '_' + patch + '_gzk_pix.reg' r = pyregion.open(region_name) patch_list, artist_list = r.get_mpl_patches_texts(origin=0) for p in patch_list: #print(p) p.set_facecolor('gray') p.set_edgecolor('gray') #ax.add_patch(p) plt.gca().add_patch(p) for t in artist_list: #ax.add_patch(t) plt.gca().add_patch(t)
def make_reg_masks(regfile,shape): r = pyregion.open(regfile) if len(r) != 2: raise Exception('Exactly two box regions required') paths = [] for reg in r: paths.append(get_region_box(reg.coord_list)) #Always have A be the top half if paths[0].get_extents().ymax > paths[1].get_extents().ymax: pathA = paths[0] pathB = paths[1] else: pathA = paths[1] pathB = paths[2] print 'Building skymasks' maskA = np.array([True if pathA.contains_point([x,y]) else False for x,y in np.ndindex(shape)]) maskA = maskA.reshape(shape).T maskB = np.array([True if pathB.contains_point([x,y]) else False for x,y in np.ndindex(shape)]) maskB = maskB.reshape(shape).T return (~maskA, ~maskB)
def mask_satellite_trail(flc='jcdu36e5q_flc.backup.fits', mask_files=['jcdu36e5q_mask_1.reg', 'jcdu36e5q_mask_2.reg']): """ Use Pyregion to mask satellite trails with a region file. Note: save the region file in "fk5" sky coordinates """ import astropy.io.fits as pyfits import pyregion ### open the FITS image for modifying im = pyfits.open(flc) ### Make the mask for both "DQ" extensions for both ACS/WFC chips for extension in [1,2]: ### Get a mask returning 1 *within* the region and 0 elsewhere im['SCI',extension].header.remove('CPDIS1') im['SCI',extension].header.remove('CPDIS2') reg = pyregion.open(mask_files[extension-1]).as_imagecoord(im['SCI', extension].header) mask = reg.get_mask(im['SCI', extension]) ### Apply the mask to the DQ extension im['DQ', extension].data |= 4096*mask imf = pyfits.open(flc, mode='update') for extension in [1,2]: imf['DQ', extension].data = im['DQ',extension].data ### Write the file imf.flush()
def read_mask(maskfile,fitsfile,wolly=False,return_shape=False): '''Parse mask file and return masked region. If 'wolly' is True, return two masks.''' import pyregion if isinstance(fitsfile,str): hdu = fits.open(fitsfile) else: hdu = fitsfile reg = pyregion.open(maskfile) # total mask mask = ~pyregion.get_mask(reg,hdu[0]) if wolly: # return three masks: (top, bottom, total) if len(reg) != 2: raise AttributeError("Wolly masks must have two regions") # make total mask reg = [pyregion.ShapeList([r]) for r in reg] pmask = [~pyregion.get_mask(r,hdu[0]) for r in reg] pmask.append(mask) mask = pmask if return_shape: shapes = [mask_shape(m) for m in mask] mask = tuple(pmask + shapes) #mask is (top,bottom,total,shape_top,shape_bot,shape_total) else: if return_shape: mask = (mask,mask_shape(mask)) return mask
def gal2cel(regfile): """ Converts a region file from galactic to celestial coordinates including position angle reference from the center of the box (right now only works on box regions) Requires pyregion with the ShapeList.write() function implemented... not clear if that exists in 1.0 """ reg = pyregion.open(regfile) for R in reg: if R.name == 'box': x, y, dx, dy, angle = R.coord_list posn = coords.Position([x, y], system='galactic') ra, dec = posn.j2000() newang = posang.posang(x - dx, y, x + dx, y, system='galactic') coord_list = [ra, dec, dx, dy, angle - newang - 90] R.coord_format = 'fk5' R.coord_list = coord_list R.params = coord_list reg.write(regfile[:-4] + "_fk5.reg")
def size_from_reg(filename, regions, coord): """ find number of pixels necessary to cover the intersection of the regions with a square centered on coord filename : a fits file regions : ds9 regions coord : coordinate of the image center """ import astropy.io.fits as pyfits import astropy.wcs as pywcs import pyregion fits = pyfits.open(filename) header, data = flatten(fits) w = pywcs.WCS(header) # find max dist in pixel on reference image x_c, y_c = w.all_world2pix(coord[0], coord[1], 0, ra_dec_order=True) #print x_c, y_c # ditance would overestimate, get max of x-x_c and y-y_c mask = np.ones(shape=data.shape, dtype=bool) for region in regions: r = pyregion.open(region) mask = (mask & r.get_mask(header=header, shape=data.shape)) y, x = mask.nonzero() if len(x) == 0: return 0 max_size = 2 * np.max( [np.abs(np.array(y) - y_c), np.abs(np.array(x) - x_c)]) return int(max_size)
def __init__(self, filename): self.filename = filename self.reg_list = pyregion.open(filename) min_ra, max_ra, min_dec, max_dec = [], [], [], [] for r in self.reg_list: # TODO: if necessary, box, ellipse and polygon can be added. if r.name == 'circle': c = r.coord_list # c_ra, c_dec, radius # how much RA does the radius correspond to radius_ra = np.rad2deg(2*np.arcsin(np.sin(np.deg2rad(c[2])/2)/np.cos(np.deg2rad(c[1])))) min_ra.append(c[0] - radius_ra) max_ra.append(c[0] + radius_ra) min_dec.append(c[1] - c[2]) max_dec.append(c[1] + c[2]) elif r.name == 'polygon': c = np.array(r.coord_list) # ra_i, dec_i, ra_i+1, dec_i+1 ra_mask = np.zeros(len(c), dtype=bool) ra_mask[::2] = True p_ra = c[ra_mask] p_dec = c[~ra_mask] min_ra.append(np.min(p_ra)) max_ra.append(np.max(p_ra)) min_dec.append(np.min(p_dec)) max_dec.append(np.max(p_dec)) else: logger.error('Region type {} not supported.'.format(r.name)) sys.exit(1) self.min_ra = np.min(min_ra) self.max_ra = np.max(max_ra) self.min_dec = np.min(min_dec) self.max_dec = np.max(max_dec)
def mp_worker(ota, images, layout, kwargs): log = get_log_func(default_level='debug', **kwargs) ext = layout.get_ota_ext(ota) log("work on ext {} OTA {}".format(ext, ota)) hdulists = [fits.open(image, memmap=True) for image in images] # get bkg mask regmask_file = os.path.join(os.path.dirname(__file__), 'pupilmask', 'pg_large{}.reg'.format(ota)) if os.path.exists(regmask_file): log("read pupil region mask {}".format(regmask_file)) hdu = fits.ImageHDU(data=hdulists[0][ext].data) mask = pyregion.open(regmask_file).get_mask(hdu=hdu) mask = ~mask else: mask = None # scale data = [] for hdulist in hdulists: data.append(scale_to_bkg(hdulist[ext].data, mask)) data = np.dstack(data).astype('d') # free some memory for hdulist in hdulists: del hdulist[ext].data combined = np.empty((data.shape[0] * data.shape[1]), dtype=data.dtype) sigma_clip_median(data.reshape(-1, len(hdulists)), combined) return ota, combined.reshape(data.shape[:2])
def size_from_reg(filename, region, coord, pixscale, pad=1.2): """ find the minimum image size to cover a certain region pad: multiplicative factor on the final size """ import astropy.io.fits as pyfits import astropy.wcs as pywcs import pyregion # open fits fits = pyfits.open(filename) header, data = flatten(fits) # extract mask r = pyregion.open(region) mask = r.get_mask(header=header, shape=data.shape) y,x = mask.nonzero() min_ra_pix = np.min(x) min_dec_pix = np.min(y) max_ra_pix = np.max(x) max_dec_pix = np.max(y) # print 'min ra - min dec (pix)', min_ra_pix, min_dec_pix # print 'max ra - max dec (pix)', max_ra_pix, max_dec_pix # to degrees w = pywcs.WCS(fits[0].header) min_ra, min_dec = w.all_pix2world(min_ra_pix, min_dec_pix, 0, 0, 0, ra_dec_order=True) max_ra, max_dec = w.all_pix2world(max_ra_pix, max_dec_pix, 0, 0, 0, ra_dec_order=True) # print 'min ra - min dec (sky)', min_ra, min_dec # print 'max ra - max dec (sky)', max_ra, max_dec max_ra_size = 2*max([abs(coord[0] - min_ra), abs(coord[0] - max_ra)])*3600 # arcsec max_dec_size = 2*max([abs(coord[1] - min_dec), abs(coord[1] - max_dec)])*3600 # arcsec return int(pad*max([max_ra_size, max_dec_size])/pixscale)
def regtoapo(regfile,outfile,filtercolor=None): """ Take an input ds9 .reg file and create an output file formatted to work with APO's TUI filtercolor - if specified, will ignore any regions of this color """ reg = pyregion.open(regfile) outf = open(outfile,'w') for r in reg: if r.attr[1]['color'] == filtercolor or not r.attr[1].has_key('text'): continue if r.name == 'box': x,y,dx,dy,posang = r.coord_list radec = position_region(r).hmsdms() # ds9's position angles are 90 degrees offset from APO's if posang+90 > 360: posang -= 360 print >>outf,'%32s %26s rotangle=%f' % ( '"%s"' % r.attr[1]['text'],radec,posang+90) else: radec = position_region(r).hmsdms() print >>outf,'%32s %26s' % ('"%s"' % r.attr[1]['text'],radec) outf.close()
def blank_image(filename, region, outfile=None, inverse=False, blankval=0.): """ Set to "blankval" all the pixels inside the given region if inverse=True, set to "blankval" pixels outside region. filename: fits file region: ds9 region outfile: output name inverse: reverse region mask blankval: pixel value to set """ import astropy.io.fits as pyfits import pyregion if outfile == None: outfile = filename # open fits fits = pyfits.open(filename) origshape = fits[0].data.shape header, data = flatten(fits) # extract mask r = pyregion.open(region) mask = r.get_mask(header=header, shape=data.shape) if inverse: mask = ~mask data[mask] = blankval # save fits fits[0].data = data.reshape(origshape) fits.writeto(outfile, clobber=True)
def getregionboxcenter(regionfile): """ Extract box center of a DS9 box region. Input is regionfile Return NDPPP compatible string for phasecenter shifting """ r = pyregion.open(regionfile) if len(r[:]) > 1: print('Only one region can be specified, your file contains', len(r[:])) sys.exit() if r[0].name != 'box': print('Only box region supported') sys.exit() ra = r[0].coord_list[0] dec = r[0].coord_list[1] boxsizex = r[0].coord_list[2] boxsizey = r[0].coord_list[3] angle = r[0].coord_list[4] if boxsizex != boxsizey: print('Only a square box region supported, you have these sizes:', boxsizex, boxsizey) sys.exit() if np.abs(angle) > 1: print( 'Only normally oriented sqaure boxes are supported, your region is oriented under angle:', angle) sys.exit() regioncenter = ('{:12.8f}'.format(ra) + 'deg,' + '{:12.8f}'.format(dec) + 'deg').replace(' ', '') return regioncenter
def show_region(fig, region_list): h = demo_header() n = len(region_list) nx = int(math.ceil(n ** .5)) ny = int(math.ceil(1. * n / nx)) nrows_ncols = (ny, nx) grid = [plt.subplot(ny, nx, i + 1) for i in range(n)] for ax, reg_name in zip(grid, region_list): ax.set_aspect(1) r = pyregion.open(reg_name).as_imagecoord(h) patch_list, text_list = r.get_mpl_patches_texts() for p in patch_list: ax.add_patch(p) for t in text_list: ax.add_artist(t) if plt.rcParams["text.usetex"]: reg_name = reg_name.replace("_", r"\_") ax.set_title(reg_name, size=10) for t in ax.get_xticklabels() + ax.get_yticklabels(): t.set_visible(False) return grid
def do_rrlspectra(): hcubes = load_rrlcubes() order = ['H77$\\alpha$', 'H110$\\alpha$'] pl.close(1) pl.close(2) fig = pl.figure(1, figsize=(12,8)) fig2 = pl.figure(2, figsize=(12,8)) colors = ['k','r','g','b','m','#11AAAA'] for regfn in regfiledict: regions = pyregion.open(regfn) for r in regions: spectra = [(c,hcubes[c].get_apspec(r.coord_list, coordsys=r.coord_format, wunit='degree')) for c in order] fig.clf() fig2.clf() for ii,(hline,sp) in enumerate(spectra): sp.xarr.convert_to_unit('km/s') sp.specname = r.attr[1]['text'] sp.unit = 'K' # fit twice: first time, sets the errors sp.specfit(fittype='gaussian', guesses=[1,60,5], multifit=True) sp.specfit(fittype='gaussian', guesses=[1,60,5], multifit=True) pars = sp.specfit.modelpars pars[2] /= 5 sp.plotter(figure=fig, xmin=40, xmax=80, color=colors[ii], clear=False, label=hline) ax1 = sp.plotter.axis sp.plotter(figure=fig2, xmin=00, xmax=120, color=colors[ii], clear=False, label=hline, linewidth=2) ax2 = sp.plotter.axis sp.specfit.plot_fit(composite_fit_color=colors[ii+2], annotate=False) box = ax2.get_position() ax2.set_position([box.x0, box.y0, box.width * 0.9, box.height]) sp.specfit.annotate(bbox_to_anchor=(1.01,0.95) if '110' in hline else (1.01, 0.75), loc='upper left', fontsize=14) sp.plotter.axis.set_ylabel("$T_A^*$ (K)") fig2.savefig(dpath(regfiledict[regfn]+"_wideplot_RRL_aperture_%s.pdf" % sp.specname), bbox_extra_artists=[sp.specfit.fitleg]) fakespec = pyspeckit.Spectrum(xarr=sp.xarr, data=sp.specfit.get_model_frompars(sp.xarr, pars), header=sp.header) fakespec.plotter(axis=ax1, xmin=40, xmax=80, color=colors[ii], clear=False, linestyle='steps--') rrlid = 'H77a' if '77' in hline else '110' sp.write(dpath(regfiledict[regfn]+"_RRL%s_aperture_%s.fits" % (rrlid,sp.specname))) sp.plotter.axis.set_ylabel("$T_A^*$ (K)") sp.plotter.savefig(dpath(regfiledict[regfn]+"_RRL_aperture_%s.pdf" % sp.specname))
def area_within_reg(reg_name, base_fits=m31): ''' returns deg^s deg^2 to arcsec^2: areas*3600.*3600. deg^2 to arcmin^2: areas*3600. ''' # finds area of concentric reg shapes # use GenUtils.area for the area of a polygon. tot_areas, areas = [], [] proj = wcs.Projection(f_header) r = pyregion.open(reg_name).as_imagecoord(header=f_header) patch_list, artist_list = r.get_mpl_patches_texts() for p in patch_list[::-1]: verts_xy = p.get_xy() pixels = (verts_xy[:, 0], verts_xy[:, 1]) ra_v, dec_v = proj.toworld(pixels) verts = np.column_stack((ra_v, dec_v)) tot_areas.append(area(verts)) for i in range(len(tot_areas)): if i == len(tot_areas) - 1: areas.append(tot_areas[i]) else: areas.append(tot_areas[i] - tot_areas[i + 1]) # deg^2 to arcsec^2: areas*3600.*3600. # deg^2 to arcmin^2: areas*3600. return np.array(areas)
def regtocima(regfile, outfile, filtercolor=None): """ Take an input ds9 .reg file and create an output file formatted to work with Arecibo's CIMA [NOT FUNCTIONAL] filtercolor - if specified, will ignore any regions of this color """ #print "Doesn't work yet" #return reg = pyregion.open(regfile) outf = open(outfile, 'w') for r in reg: if r.attr[1]['color'] == filtercolor or not r.attr[1].has_key('text'): continue text = pos_to_name(r) if r.name == 'box': x, y, dx, dy, posang = r.coord_list radec = position_region(r).hmsdms() # ds9's position angles are 90 degrees offset from APO's if posang + 90 > 360: posang -= 360 print >> outf, '%32s %26s rotangle=%f' % ( '"%s"' % r.attr[1]['text'], radec, posang + 90) else: radec = position_region(r).hmsdms() print >> outf, '%32s %26s' % ('"%s"' % r.attr[1]['text'], radec) outf.close()
def regtouptime(regfile, outfile, maxza=15.0): """ Converts a region file to a list of target names + how long they are observable @ arecibo maxza = 15.0 degrees for "broken" Arecibo (2010) or 18-19 for normal Arecibo """ # coordinates @ http://www.naic.edu/~astro/guide/node2.html ra_arecibo = (66 + 45 / 60. + 11.1 / 3600.) dec_arecibo = (18 + 20 / 60. + 36.6 / 3600.) reg = pyregion.open(regfile) outf = open(outfile, 'w') for r in reg: #if r.attr[1]['color'] == filtercolor or not r.attr[1].has_key('text'): # continue text = pos_to_name(r) radec = position_region(r).hmsdms() ra, dec = position_region(r).j2000() za_min = numpy.abs(dec - dec_arecibo) # isoscoles triangle with za_min as perpendicular bisector, maxza as long leg lenth tup = numpy.sqrt(maxza**2 - za_min**2) * 2.0 / 15.0 * 60.0 # minutes print >> outf, '%12s %10.2f %10.1f' % (text, za_min, tup) outf.close()
def make_reg_masks(regfile, shape): r = pyregion.open(regfile) if len(r) != 2: raise Exception('Exactly two box regions required') paths = [] for reg in r: paths.append(get_region_box(reg.coord_list)) #Always have A be the top half if paths[0].get_extents().ymax > paths[1].get_extents().ymax: pathA = paths[0] pathB = paths[1] else: pathA = paths[1] pathB = paths[2] print 'Building skymasks' maskA = np.array([ True if pathA.contains_point([x, y]) else False for x, y in np.ndindex(shape) ]) maskA = maskA.reshape(shape).T maskB = np.array([ True if pathB.contains_point([x, y]) else False for x, y in np.ndindex(shape) ]) maskB = maskB.reshape(shape).T return (~maskA, ~maskB)
def noiseReg(self, datas, heads, region): ''' mask datas within ds9 region estimate noise and background outside of it INPUT: datas: array of data heads: header of file region: ds9 region OUTPUT: background rms number_of_pixels_in_region ''' # set polygonal mask from ds9 region r = pyregion.open(region).as_imagecoord(heads) shape = (heads['NAXIS2'], heads['NAXIS1']) m = r.get_mask(shape=shape) #mean stats background = np.nanmean(datas[m == True]) noise = np.nanstd(datas[m == False]) mm = datas.copy() mm[np.isnan(mm)] = 0. pixels = np.count_nonzero(mm[m == True]) noise = noise / np.sqrt(pixels) return background, noise, pixels
def show_region(fig, region_list): h = demo_header() n = len(region_list) nx = int(math.ceil(n**.5)) ny = int(math.ceil(1. * n / nx)) nrows_ncols = (ny, nx) grid = [plt.subplot(ny, nx, i + 1) for i in range(n)] for ax, reg_name in zip(grid, region_list): ax.set_aspect(1) r = pyregion.open(reg_name).as_imagecoord(h) patch_list, text_list = r.get_mpl_patches_texts() for p in patch_list: ax.add_patch(p) for t in text_list: ax.add_artist(t) if plt.rcParams["text.usetex"]: reg_name = reg_name.replace("_", r"\_") ax.set_title(reg_name, size=10) for t in ax.get_xticklabels() + ax.get_yticklabels(): t.set_visible(False) return grid
def load_ds9_cloud_region(props, filename=None, header=None): import pyregion as pyr # region[0] in following format: # [64.26975, 29.342033333333333, 1.6262027777777777, 3.32575, 130.0] # [ra center, dec center, width, height, rotation angle] regions = pyr.open(filename) props['regions'] = {} for region in regions: # Cores defined in following format: 'tag={L1495A}' tag = region.comment region_name = tag[tag.find('{')+1:tag.find('}')].lower() # Format vertices to be 2 x N array poly_verts = [] for i in xrange(0, len(region.coord_list)/2): poly_verts.append((region.coord_list[2*i], region.coord_list[2*i+1])) poly_verts_pix = [] for i in xrange(0, len(poly_verts)): poly_verts_pix.append(get_pix_coords(ra=poly_verts[i][0], dec=poly_verts[i][1], header=header)[:-1][::-1].tolist()) props['regions'][region_name] = {} props['regions'][region_name]['poly_verts'] = {} props['regions'][region_name]['poly_verts']['wcs'] = poly_verts props['regions'][region_name]['poly_verts']['pixel'] = poly_verts_pix return props
def test_regions(): ''' loads in the regions from the region file and converts these to image coords, then plots them over the image. ''' import pyregion region_name = prefix + 'P173+55cat.srl.reg' r = pyregion.open(region_name) r2 = r.as_imagecoord(header) #this uses image coord #below we use r instead of image coords print r[0].name print 'right ascension, declination, semi-major axis, semi-minor axis, angle' print r[0].coord_format print r[0].coord_list print r[0].comment print r[0].attr #defines a list of matplotlib.patches.Patch and other kinds of artists (usually Text) patch_list, artist_list = r2.get_mpl_patches_texts() fig, ax = plt.subplots() ax.imshow(image_data, cmap = plt.cm.gray, origin = 'lower', vmin = -0.000246005, vmax = 0.000715727) for p in patch_list: ax.add_patch(p) #add the first patch to the plot, then the second, etc #ax.add_artist(artist_list[0]) #similar for the first artist plt.show()
def noiseMultiReg(self, ldata, lhead, region_dir): r = [ f for f in os.listdir(region_dir) if os.path.isfile(os.path.join(region_dir, f)) ] mean_values = np.zeros(len(r)) flux_values = np.zeros(len(r)) pixels = 0. for i in xrange(0, len(r)): region_name = region_dir + r[i] #print region_name re = pyregion.open(region_name).as_imagecoord(lhead) shape = (lhead['NAXIS2'], lhead['NAXIS1']) m_noise = re.get_mask(shape=shape) mask_tmp = np.copy(ldata) #print np.nansum(mask_tmp[m_noise==True]) #mask_tmp[m==True] = np.nan flux_values[i] = np.nansum(mask_tmp[m_noise == True]) mean_values[i] = np.nanmean(mask_tmp[m_noise == True]) pixels += np.count_nonzero(mask_tmp[m_noise == True]) noise = np.nanstd(flux_values) back = np.nanmean(flux_values) pixels = pixels / len(r) return back, noise, pixels
def do_HIspectra(): hcubes = load_HIcubes() order = ['HI'] pl.close(1) fig = pl.figure(1, figsize=(12,8)) colors = ['k','r','g','b','m','#11AAAA'] for regfn in regfiledict: regions = pyregion.open(regfn) for r in regions: spectra = [(c,hcubes[c].get_apspec(r.coord_list, coordsys=r.coord_format, wunit='degree')) for c in order] fig.clf() for ii,(hline,sp) in enumerate(spectra): sp.xarr.convert_to_unit('km/s') sp.specname = r.attr[1]['text'] sp.unit = 'K' sp.plotter(figure=fig, xmin=40, xmax=80, color=colors[ii], clear=False, label=hline) sp.plotter.axis.set_ylabel("$T_A^*$ (K)") sp.plotter.savefig(regfiledict[regfn]+"_HI_aperture_%s.pdf" % sp.specname) sp.write(regfiledict[regfn]+"_HI_aperture_%s.fits" % sp.specname)
def load_regions(self): '''Tell DS9 to load regions based on the provided ``filepath``. The `filepath`` gets parsed to construct the name of the region files based on the observation ID and band. If the region files are not found in the parent path of ``filepath``, the default coordinates will get used for the source (likely from SIMBAD) and for the background. ''' #parse filepath to get obs ID and band dirpath, filename = path.split(self.filepath) base, extn = filename.split('_') obs = base[2:-3] band = base[-2:] #constructs the source and background region file paths regfile = path.join(dirpath, 'detect_%s_%s.reg' % (obs, band)) bkgregfile = path.join(dirpath, 'back_%s_%s.reg' % (obs, band)) #trying to load the background region. If the attempt fails, whatever coordinates are #currently stored in the object bkg_ra and bkg_dec attributes will be displayed. try: bkgregion = pyregion.open(bkgregfile) bkg_ra = bkgregion[0].coord_list[0] bkg_dec = bkgregion[0].coord_list[1] self.bkg_coords = SkyCoord('%s %s' % (bkg_ra, bkg_dec), unit=(u.deg, u.deg)) except IOError: print( 'Background region file missing. Will try default coordinates.' ) self.display_bkg_region() #trying to load the source region. If the attempt fails, whatever coordinates are #currently stored in the object source_ra and source_dec attributes will be displayed. try: region = pyregion.open(regfile) ra = region[0].coord_list[0] dec = region[0].coord_list[1] self.source_coords = SkyCoord('%s %s' % (ra, dec), unit=(u.deg, u.deg)) except IOError: print( 'Region file missing. Only showing default coordinates, if any.' ) self.display_source_region()
def ds9_region(ds, reg, obj=None, field_parameters=None): r""" Create a data container from a ds9 region file. Requires the pyregion package (https://pyregion.readthedocs.io/en/latest/) to be installed. Parameters ---------- ds : FITSDataset The Dataset to create the region from. reg : string The filename of the ds9 region, or a region string to be parsed. obj : data container, optional The data container that will be used to create the new region. Defaults to ds.all_data. field_parameters : dictionary, optional A set of field parameters to apply to the region. Examples -------- >>> ds = yt.load("m33_hi.fits") >>> circle_region = ds9_region(ds, "circle.reg") >>> print(circle_region.quantities.extrema("flux")) """ import pyregion from yt.frontends.fits.api import EventsFITSDataset if os.path.exists(reg): r = pyregion.open(reg) else: r = pyregion.parse(reg) reg_name = reg header = ds.wcs_2d.to_header() # The FITS header only contains WCS-related keywords header["NAXIS1"] = nx = ds.domain_dimensions[ds.lon_axis] header["NAXIS2"] = ny = ds.domain_dimensions[ds.lat_axis] filter = r.get_filter(header=header) mask = filter.mask((ny, nx)).transpose() if isinstance(ds, EventsFITSDataset): prefix = "event_" else: prefix = "" def _reg_field(field, data): i = data[prefix + "xyz"[ds.lon_axis]].d.astype("int") - 1 j = data[prefix + "xyz"[ds.lat_axis]].d.astype("int") - 1 new_mask = mask[i, j] ret = np.zeros(data[prefix + "x"].shape) ret[new_mask] = 1.0 return ret ds.add_field(("gas", reg_name), sampling_type="cell", function=_reg_field) if obj is None: obj = ds.all_data() if field_parameters is not None: for k, v in field_parameters.items(): obj.set_field_parameter(k, v) return obj.cut_region(["obj['%s'] > 0" % (reg_name)])
def find_sources(imgfile, nsig = 1.5, minarea = 10., clean=True, deblend_cont = 0.0001, regfile = None, write = None, bkgsub = True): """ Find sources in the whitelight image using SExtractor. Args: imgfile (str): An image fits file n_sig (float, optional): Detection threshold in units of sky background rms. minarea (float, optional): minimum area in pixels to be considered a valid detection. clean (bool, optional): Perform cleaning? deblend_cont (float, optional): Minimum contrast ratio used for object deblending. Default is 0.005. To entirely disable deblending, set to 1.0. regfile (str, optional): A ds9 region file of areas to be masked out. write (str, optional): write extracted object table to this path. bkgsub (bool, optional): perform background subtraction? Default is set to true. Returns: objects (Table): Summary table of detected objects. segmap (ndarray): Segmentation map. """ # Get whitelight image hdulist = fits.open(imgfile) white = hdulist[0] data = white.data data = data.byteswap().newbyteorder() # sep requires this # Make a mask if available if regfile: reg = pyreg.open(regfile).as_imagecoord(white.header) mask = reg.get_filter().mask(data) else: mask = None # Characterize sky bkg = sep.Background(data, mask = mask) # Subtract background? if bkgsub: bkg.subfrom(data) # Compute background again bkg = sep.Background(data, mask = mask) # Compute source detection threshold thresh = nsig*bkg.globalrms # Extract sources objects, segmap = sep.extract(data, thresh = thresh, mask = mask, deblend_cont = deblend_cont, minarea = minarea, clean = clean, segmentation_map=True) if write: Table(objects).write(write, overwrite = True) return Table(objects), segmap
def ds9(region_file, header, zorder=3, **kwargs): """ Wrapper to return a PatchCollection given a ds9 region file and a fits header. zorder - defaults to 3 so that regions are on top of contours """ try: import pyregion except Exception: raise ImportError("The pyregion package is required to load region files") # read region file if isinstance(region_file, str): rr = pyregion.open(region_file) elif isinstance(region_file, pyregion.ShapeList): rr = region_file else: raise Exception("Invalid type for region_file: %s - should be string or pyregion.ShapeList" % type(region_file)) if isinstance(header, wcs.WCS): header = header.to_header() # convert coordinates to image coordinates rrim = rr.as_imagecoord(header) # pyregion and aplpy both correct for the FITS standard origin=1,1 # need to avoid double-correcting. Also, only some items in `coord_list` # are pixel coordinates, so which ones should be corrected depends on the # shape. for r in rrim: if r.name == 'polygon': correct = range(len(r.coord_list)) elif r.name == 'line': correct = range(4) elif r.name in ['rotbox', 'box', 'ellipse', 'annulus', 'circle', 'panda', 'pie', 'epanda', 'text', 'point', 'vector']: correct = range(2) else: log.warning("Unknown region type '{0}' - please report to the developers") correct = range(2) for i in correct: r.coord_list[i] += 1 if 'text_offset' in kwargs: text_offset = kwargs['text_offset'] del kwargs['text_offset'] else: text_offset = 5.0 # grab the shapes to overplot pp, aa = rrim.get_mpl_patches_texts(text_offset=text_offset) PC = ArtistCollection(pp, **kwargs) # preserves line style (dashed) TC = ArtistCollection(aa, **kwargs) PC.set_zorder(zorder) TC.set_zorder(zorder) return PC, TC
def read_region_file(component_table): """Read region file to get the containment radii""" import pyregion region_list = pyregion.open('fit.reg') r_containment_list = [] for component in region_list: r_containment = np.float(component.coord_list[2]) r_containment_list.append(r_containment) component_table.add_column(Column(data=r_containment_list, name='Containment Radii R80'))
def plot_region(f,regname,color): r=pyregion.open(regname) ra=[] dec=[] for j,c in enumerate(r): sc=SkyCoord(c.coord_list[0],c.coord_list[1],unit=(u.deg,u.deg)) ra.append(sc.ra.value) dec.append(sc.dec.value) f.show_markers(ra,dec,marker='+',facecolor=color,edgecolor=color,linewidth=1,s=100,zorder=100)
def findrms(filename, region): import pyregion from radioflux import radioflux fitsfile = fits.open(filename) rm = radioflux.radiomap(fitsfile) bg_ir = pyregion.open(region).as_imagecoord(rm.prhd) bg = radioflux.applyregion(rm, bg_ir) return bg.rms
def ds9(region_file, header, zorder=3, **kwargs): """ Wrapper to return a PatchCollection given a ds9 region file and a fits header. zorder - defaults to 3 so that regions are on top of contours """ try: import pyregion except: raise ImportError("The pyregion package is required to load region files") # read region file if isinstance(region_file, six.string_types): rr = pyregion.open(region_file) elif isinstance(region_file, pyregion.ShapeList): rr = region_file else: raise Exception("Invalid type for region_file: %s - should be string or pyregion.ShapeList" % type(region_file)) # convert coordinates to image coordinates rrim = rr.as_imagecoord(header) # pyregion and aplpy both correct for the FITS standard origin=1,1 # need to avoid double-correcting. Also, only some items in `coord_list` # are pixel coordinates, so which ones should be corrected depends on the # shape. for r in rrim: if r.name == 'polygon': correct = range(len(r.coord_list)) elif r.name == 'line': correct = range(4) elif r.name in ['rotbox', 'box', 'ellipse', 'annulus', 'circle', 'panda', 'pie', 'epanda', 'text', 'point', 'vector']: correct = range(2) else: log.warning("Unknown region type '{0}' - please report to the developers") correct = range(2) for i in correct: r.coord_list[i] += 1 if 'text_offset' in kwargs: text_offset = kwargs['text_offset'] del kwargs['text_offset'] else: text_offset = 5.0 # grab the shapes to overplot pp, aa = rrim.get_mpl_patches_texts(text_offset=text_offset) PC = ArtistCollection(pp, **kwargs) # preserves line style (dashed) TC = ArtistCollection(aa, **kwargs) PC.set_zorder(zorder) TC.set_zorder(zorder) return PC, TC
def reg2Mask(imgFile, regFile, mskFile=None, hdu=0, show=False, save=True, imgHead=None, reverse=False): """ Mask out the regions in a DS9 region file. Parameters: """ try: import pyregion except Exception: raise Exception("### Please have pyregion installed first") if imgHead is None: if not os.path.isfile(imgFile): raise Exception("### Can not find the Image: %s" % imgFile) else: img = fits.open(imgFile)[0].data head = fits.open(imgFile)[0].header else: img = imgFile head = imgHead if not os.path.isfile(regFile): raise Exception("### Can not find the Region file: %s" % regFile) else: reg = pyregion.open(regFile).as_imagecoord(head) imgX, imgY = img.shape regMask = reg.get_mask(shape=(imgX, imgY)) if not reverse: intMask = regMask.astype(int) else: intMask = np.invert(regMask).astype(int) if save: if mskFile is None: if not reverse: mskFile = regFile.replace('.reg', '_msk.fits') else: mskFile = regFile.replace('.reg', '_invmsk.fits') saveFits(intMask, mskFile, head=head, clobber=True) if show: pngName = mskFile.replace('.fits', '.png') showSEPImage(img, pngName=pngName, mask=intMask, cmap=cmap1, title=mskFile.replace('.fits', '')) return intMask
def add_manual_mask(infile,ds9region,outfile): hdu=fits.open(infile) hduflat = flatten(hdu) map=hdu[0].data r = pyregion.open(ds9region) manualmask = r.get_mask(hdu=hduflat) hdu[0].data=(map.astype(int) | manualmask).astype(np.float32) hdu.writeto(outfile,clobber=True)
def add_manual_mask(infile, ds9region, outfile): hdu = fits.open(infile) hduflat = flatten(hdu) map = hdu[0].data r = pyregion.open(ds9region) manualmask = r.get_mask(hdu=hduflat) hdu[0].data = (map.astype(int) | manualmask).astype(np.float32) hdu.writeto(outfile, clobber=True)
def loadRegions(self): """ Utility method uses the pyregion module (http://pyregion.readthedocs.io/en/latest/) to load and parse a SAO DS9 format region file specifying the positions of the zeroth order dispersion images in the appropriate full, drizzled grism image. """ if self.rawZerothOrderRegions is None: self.rawZerothOrderRegions = pyregion.open( self.zerothOrderRegionFilePath)
def __init__(self, x, y, regfile): """ Parse the ds9 region file here. Also save the number of regions and the x y dimensions of the data""" self.reg = pyreg.open(regfile) self.filter = self.reg.get_filter() self.x = x self.y = y self.nreg = len(self.reg)
def plot_overview(cube='../nro_maps/12CO_20161002_FOREST-BEARS_spheroidal_xyb_grid7.5_0.099kms.fits', region_file='../nro_maps/SouthShells.reg', mode='peak', plotname='12co_peak_shells.png', interactive=False, show_shells=False): """ Show full image with all shells. Parameters ---------- cube : str, optional Description region_file : str, optional Description mode : str, optional Description plotname : str, optional Description interactive : bool, optional Description show_shells : bool, optional Description """ try: cube = SpectralCube.read(cube) except ValueError: pass if mode == "peak": image = cube.max(axis=0) fig = plt.figure() wcs = WCS(image.header) ax = WCSAxes(fig, [0.1,0.1,0.8,0.8], wcs=wcs) fig.add_axes(ax) imgplot = plt.imshow(image.data, cmap=cm.gray, origin='lower', interpolation='none', vmin=0., vmax=100) cb = plt.colorbar() cb.set_label(r'K [T$_{MB}$]') plt.title(r"$^{12}$CO Peak") if show_shells: r = pyregion.open(region_file).as_imagecoord(image.header) patch_list, artist_list = r.get_mpl_patches_texts() for p in patch_list: ax.add_patch(p) for t in artist_list: ax.add_artist(t) pass if interactive: plt.show() else: plt.savefig(plotname)