def __init__(self, DynSpecMS): self.DynSpecMS=DynSpecMS self.DIRNAME="DynSpecs_%s"%self.DynSpecMS.OutName #image = self.DynSpecMS.Image #self.ImageData=np.squeeze(fits.getdata(image, ext=0)) self.ImageI=self.DynSpecMS.ImageI if self.ImageI and os.path.isfile(self.DynSpecMS.ImageI): self.im=self.imI=image(self.DynSpecMS.ImageI) self.ImageIData=self.imI.getdata()[0,0] self.ImageV=self.DynSpecMS.ImageV if self.ImageV and os.path.isfile(self.ImageV): self.imV=image(self.DynSpecMS.ImageV) self.ImageVData=self.imV.getdata()[0,1] else: self.ImageVData=self.ImageIData.copy() self.imV=self.imI self.ImageVData=np.random.randn(*self.ImageVData.shape) self.ImageV=self.ImageI self.CatFlux=np.zeros((self.DynSpecMS.NDir,),dtype=[('Name','S200'),("ra",np.float64),("dec",np.float64),('Type','S200'),("IDFacet",np.int32), ("FluxI",np.float32),("FluxV",np.float32),("sigFluxI",np.float32),("sigFluxV",np.float32)]) self.CatFlux=self.CatFlux.view(np.recarray) os.system("rm -rf %s"%self.DIRNAME) os.system("mkdir -p %s/TARGET"%self.DIRNAME) os.system("mkdir -p %s/OFF"%self.DIRNAME)
def main(image_pre, image_post, res_val, max_factor=0.5): """ Verify subtraction by checking quantities in residual images Parameters ---------- image_pre : str Filename of image before selfcal image_post : str Filename of image after selfcal res_val : float Maximum allowed value of peak residual (Jy/beam) max_factor : float Factor by which old peak residual must exceed new peak residual """ imgpre = pim.image(image_pre) maxvalpre = numpy.max(numpy.abs(imgpre.getdata())) imgpost = pim.image(image_post) maxvalpost = numpy.max(numpy.abs(imgpost.getdata())) if (maxvalpost > res_val) or (maxvalpost*max_factor > maxvalpre): return {'break': False, 'maxvalpost': maxvalpost, 'maxvalpre': maxvalpre} else: return {'break': True, 'maxvalpost': maxvalpost, 'maxvalpre': maxvalpre}
def main(args): image = args.image pb = pim.image(image) pbdata = pb.getdata() (nx,ny) = pbdata.shape[2:] pbrad = args.radius*nx cy = ny/2 cx = nx/2 pbcounter = 0 for j in range(nx,cx,-1): k = ny while np.sqrt((j-cx)**2+(k-cy)**2)>pbrad and k>cy: pbcounter += 1 pbdata[:,:,k-1,j-1]=0. pbdata[:,:,k-1,nx-j]=0. pbdata[:,:,ny-k,j-1]=0. pbdata[:,:,ny-k,nx-j]=0. k -= 1 if k == ny: print j,nx break print pbcounter,'x 4 =',pbcounter*4,'zeros replaced' if args.output == '': while image[-1]=='/': image=image[:-1] outim = image+'z' else: outim = args.output print 'Writing',outim pout = pim.image(outim,values=pbdata,coordsys=pb.coordinates())
def validate_image_equality(image_1_path, image_2_path, max_delta): import pyrap.images as pim # get the difference between the two images print("comparing images from paths:") print(image_1_path) print(image_2_path) im = pim.image('"{0}" - "{1}"'.format(image_1_path, image_2_path)) im.saveas("difference.IM2") # get the stats of the image stats_dict = im.statistics() return_value = compare_image_statistics(stats_dict, max_delta) if not return_value: print("\n\n\n") print("*"*30) print("Statistics of the produced image:") im = pim.image("{0}".format(image_1_path)) stats_dict_single_image = im.statistics() print(stats_dict_single_image) print("\n\n\n") print("Statistics of the compare image:") im = pim.image("{0}".format(image_2_path)) stats_dict_single_image = im.statistics() print(stats_dict_single_image) print("\n\n\n") print("difference between produced image and the baseline image:") print("maximum delta: {0}".format(max_delta)) print(stats_dict) print("*"*30) return return_value
def validate_image_equality(image_1_path, image_2_path, max_delta): import pyrap.images as pim # get the difference between the two images print "comparing images from paths:" print image_1_path print image_2_path im = pim.image('"{0}" - "{1}"'.format(image_1_path, image_2_path)) im.saveas("difference.IM2") # get the stats of the image stats_dict = im.statistics() return_value = compare_image_statistics(stats_dict, max_delta) if not return_value: print "\n\n\n" print "*"*30 print "Statistics of the produced image:" im = pim.image("{0}".format(image_1_path)) stats_dict_single_image = im.statistics() print stats_dict_single_image print "\n\n\n" print "Statistics of the compare image:" im = pim.image("{0}".format(image_2_path)) stats_dict_single_image = im.statistics() print stats_dict_single_image print "\n\n\n" print "difference between produced image and the baseline image:" print "maximum delta: {0}".format(max_delta) print stats_dict print "*"*30 return return_value
def validate_image_equality(image_1_path, image_2_path, max_delta): import pyrap.images as pim # get the difference between the two images im = pim.image("{0} - {1}".format(image_1_path, image_2_path)) im.saveas("difference.IM2") # get the stats of the image stats_dict = im.statistics() return_value = compare_image_statistics(stats_dict, max_delta) if not return_value: print "\n\n\n" print "*" * 30 print "Statistics of the produced image:" im = pim.image("{0}".format(image_1_path)) stats_dict_single_image = im.statistics() print stats_dict_single_image print "\n\n\n" print "Statistics of the compare image:" im = pim.image("{0}".format(image_2_path)) stats_dict_single_image = im.statistics() print stats_dict_single_image print "\n\n\n" print "difference between produced image and the baseline image:" print "maximum delta: {0}".format(max_delta) print stats_dict print "*" * 30 return return_value
def main(image_pre, image_post, res_val, max_factor=0.5): """ Verify subtraction by checking quantities in residual images Parameters ---------- image_pre : str Filename of image before selfcal image_post : str Filename of image after selfcal res_val : float Maximum allowed value of peak residual (Jy/beam) max_factor : float Factor by which old peak residual must exceed new peak residual """ imgpre = pim.image(image_pre) maxvalpre = numpy.max(numpy.abs(imgpre.getdata())) imgpost = pim.image(image_post) maxvalpost = numpy.max(numpy.abs(imgpost.getdata())) if (maxvalpost > res_val) or (maxvalpost * max_factor > maxvalpre): return { 'break': False, 'maxvalpost': maxvalpost, 'maxvalpre': maxvalpre } else: return { 'break': True, 'maxvalpost': maxvalpost, 'maxvalpre': maxvalpre }
def main(args): image = args.image pb = pim.image(image) pbdata = pb.getdata() (nx, ny) = pbdata.shape[2:] pbrad = args.radius * nx cy = ny / 2 cx = nx / 2 pbcounter = 0 for j in range(nx, cx, -1): k = ny while np.sqrt((j - cx)**2 + (k - cy)**2) > pbrad and k > cy: pbcounter += 1 pbdata[:, :, k - 1, j - 1] = 0. pbdata[:, :, k - 1, nx - j] = 0. pbdata[:, :, ny - k, j - 1] = 0. pbdata[:, :, ny - k, nx - j] = 0. k -= 1 if k == ny: print j, nx break print pbcounter, 'x 4 =', pbcounter * 4, 'zeros replaced' if args.output == '': while image[-1] == '/': image = image[:-1] outim = image + 'z' else: outim = args.output print 'Writing', outim pout = pim.image(outim, values=pbdata, coordsys=pb.coordinates())
def mask_vertices(mask_im, vertices_file): """ Modify the input image to exclude regions outside of the polygon Parameters ---------- mask_im : pyrap.images image() object Mask image to modify vertices_file: str Filename of pickle file that contains direction dictionary with vertices Returns ------- new_im: pyrap.images image() object Modified mask image bool_mask : pyrap.images image() object Modified mask image """ import pyrap.images as pim ma = mask_im.coordinates() new_im = pim.image('',shape=mask_im.shape(), coordsys=ma) bool_mask = pim.image('',shape=mask_im.shape(), coordsys=ma) img_type = mask_im.imagetype() data = mask_im.getdata() bool_data = np.ones(data.shape) vertices = read_vertices(vertices_file) RAverts = vertices[0] Decverts = vertices[1] xvert = [] yvert = [] for RAvert, Decvert in zip(RAverts, Decverts): pixels = mask_im.topixel([1, 1, Decvert*np.pi/180.0, RAvert*np.pi/180.0]) xvert.append(pixels[2]) # x -> Dec yvert.append(pixels[3]) # y -> RA poly = Polygon(xvert, yvert) # Find distance to nearest poly edge and unmask those that # are outside the facet (dist < 0) masked_ind = np.indices(data[0, 0].shape) dist = poly.is_inside(masked_ind[0], masked_ind[1]) outside_ind = np.where(dist < 0.0) if len(outside_ind[0]) > 0: data[0, 0, masked_ind[0][outside_ind], [masked_ind[1][outside_ind]]] = 0 bool_data[0, 0, masked_ind[0][outside_ind], [masked_ind[1][outside_ind]]] = 0 new_im.putdata(data) bool_mask.putdata(bool_data) return new_im, bool_mask
def find_imagenoise(imagename): """ Finds noise, dynamic range, and min/max for an image Parameters ---------- imagename : str Filename of image Returns ------- rms : float Noise (Jy/beam) of image dynamic_range : float Dynamic range (max/min) of image minmax : float Ratio of min/max """ im = pim.image(imagename) image = numpy.copy(im.getdata()) mean, rms = meanclip(image) minmax = abs(numpy.min(image) / numpy.max(image)) return rms, numpy.abs(numpy.max(image) / rms), minmax
def find_imagenoise(imagename): """ Finds noise, dynamic range, and min/max for an image Parameters ---------- imagename : str Filename of image Returns ------- rms : float Noise (Jy/beam) of image dynamic_range : float Dynamic range (max/min) of image minmax : float Ratio of min/max """ im = pim.image(imagename) image = numpy.copy(im.getdata()) mean, rms = meanclip(image) minmax = abs(numpy.min(image) / numpy.max(image)) return rms, numpy.abs(numpy.max(image)/rms), minmax
def init2(): from pyrap.images import image im = image("/home/tasse/Desktop/FITS/image_049_073.img.restored.fits") PMaj = (im.imageinfo()["restoringbeam"]["major"]["value"]) PMin = (im.imageinfo()["restoringbeam"]["minor"]["value"]) PPA = (im.imageinfo()["restoringbeam"]["positionangle"]["value"]) print( ModColor.Str(" - Using psf (maj,min,pa)=(%6.2f, %6.2f, %6.2f)" % (PMaj, PMin, PPA), col='green', Bold=False)) ToSig = (1. / 3600.) * (np.pi / 180.) / (2. * np.sqrt(2. * np.log(2))) PMaj *= ToSig PMin *= ToSig PPA *= np.pi / 180 b = im.getdata()[0, 0, :, :] b = b[3000:4000, 3000:4000] #[100:250,200:350] c = im.coordinates() incr = np.abs(c.dict()["direction0"]["cdelt"][0]) print( ModColor.Str(" - Psf Size Sigma_(Maj,Min) = (%5.1f,%5.1f) pixels" % (PMaj / incr, PMin / incr), col="green", Bold=False)) Islands = ClassIslands.ClassIslands(b, 10., Boost=1, DoPlot=1) #Islands.Noise=30e-3 Islands.FindAllIslands() sourceList = [] ImOut = np.zeros_like(b) pylab.ion() for i in range(len(Islands.ListX)): #comment='Isl %i/%i' % (i+1,len(Islands.ListX)) #pBAR.render(int(100* float(i+1) / len(Islands.ListX)), comment) xin, yin, zin = np.array(Islands.ListX[i]), np.array( Islands.ListY[i]), np.array(Islands.ListS[i]) xm = int(np.sum(xin * zin) / np.sum(zin)) ym = int(np.sum(yin * zin) / np.sum(zin)) #Fit=ClassPointFit(xin,yin,zin,psf=(PMaj/incr,PMin/incr,PPA),noise=Islands.Noise) Fit = ClassPointFit(xin, yin, zin, psf=(PMaj / incr, PMin / incr, PPA), noise=Islands.Noise[xm, ym]) sourceList += Fit.DoAllFit() Fit.PutFittedArray(ImOut) xlist = [] ylist = [] slist = [] for ijs in sourceList: i, j, s = ijs xlist.append(i) ylist.append(j) slist.append(s) Islands.FittedComps = (xlist, ylist, slist) Islands.FitIm = ImOut Islands.plot()
def main(fitsimage, outfilename, force_stokes_i=False): """ Convert a fits image to a CASA image Parameters ---------- fitsimage : str Name of FITS image outfilename : str Name of output CASA image force_stokes_i : bool, optional If True, force Stokes axis to be 'I' """ casaimage = pim.image(fitsimage) casaimage.saveas(outfilename, overwrite=True) if type(force_stokes_i) is str: if force_stokes_i.lower() == 'true': force_stokes_i = True else: force_stokes_i = False if force_stokes_i: coords = casaimage.coordinates().dict() coords['stokes1']['stokes'] = ['I'] freq = coords['spectral2']['wcs']['crval'] coords['spectral2']['restfreqs'] = np.array([freq]) outtable = pt.table(outfilename, readonly=False, ack=False) outtable.putkeywords({'coords': coords}) outtable.done()
def convertStamps(self, BoxPix=200, SubPlots=(2, 2), rms=0.0007): im = image(self.FitsName) data = im.getdata()[0, 0] D = data Np = 1000 nx, ny = D.shape indx = np.int64(np.random.rand(Np) * nx) indy = np.int64(np.random.rand(Np) * ny) #rms=np.std(D[indx,indy]) NX, NY = GiveNXNYPanels(len(self.DicoStamps.keys()), ratio=800 / 500) pol, freq, rac, decc = im.toworld((0, 0, 0, 0)) pylab.clf() for iStamp in self.DicoStamps.keys(): ax = pylab.subplot(NX, NY, iStamp + 1) outname = self.FitsName + ".%2.2i" % iStamp rac = self.DicoStamps[iStamp]["radeg"] * np.pi / 180 decc = self.DicoStamps[iStamp]["decdeg"] * np.pi / 180 _, _, xc, yc = im.topixel((pol, freq, decc, rac)) D = data[int(xc) - BoxPix:int(xc) + BoxPix, int(yc) - BoxPix:int(yc) + BoxPix] vmax = 30. * rms #np.max([D.max(),10.*rms]) pylab.imshow(D, vmin=-5. * rms, vmax=vmax, cmap="gray") ax.set_xticklabels([]) ax.get_xaxis().set_visible(False) ax.set_yticklabels([]) ax.get_yaxis().set_visible(False) pylab.tight_layout() pylab.draw() pylab.show(False) pylab.pause(0.1)
def CleanMaskedComponants(self, MaskName): print >> log, "Cleaning model dictionary from masked components using %s" % ( MaskName) im = image(MaskName) MaskArray = im.getdata()[0, 0].T[::-1] for (x, y) in self.DicoSMStacked["Comp"].keys(): if MaskArray[x, y] == 0: del (self.DicoSMStacked["Comp"][(x, y)])
def main(image, output=None, radius=0.5): """ Zero corners of avgpb images Parameters ---------- image : str avgpb image output : str, optional Output image name. If None, add a 'z' to the end of the input filename radius : float, optional Radius beyond which to zero avgpb values (expressed as fraction of image width) """ if type(radius) is str: radius = float(radius) pb = pim.image(image) pbdata = pb.getdata() (nx, ny) = pbdata.shape[2:] pbrad = radius * nx cy = ny / 2 cx = nx / 2 pbcounter = 0 for j in range(nx, cx, -1): k = ny while np.sqrt((j-cx)**2+(k-cy)**2) > pbrad and k > cy: pbcounter += 1 pbdata[:, :, k-1, j-1] = 0. pbdata[:, :, k-1, nx-j] = 0. pbdata[:, :, ny-k, j-1] = 0. pbdata[:, :, ny-k, nx-j] = 0. k -= 1 if k == ny: break print pbcounter,'x 4 =',pbcounter*4,'zeros replaced' if output is None: while image[-1] == '/': image = image[: -1] outim = image + 'z' else: outim = output pout = pim.image(outim, values=pbdata, coordsys=pb.coordinates())
def Print(ImageName="testImage.fits"): im=image(ImageName) d=im.getdata() _,_,lx,ly=np.where(d!=0) for x,y in zip(lx,ly): _,_,dec,ra=im.toworld([0,0,x,y]) print rad2hmsdms.rad2hmsdms(ra,Type="ra").replace(" ",":"),", ",rad2hmsdms.rad2hmsdms(dec,Type="dec").replace(" ",".")
def find_imagenoise(imagename): """ Finds the noise level of an image """ im = pim.image(imagename) image = numpy.copy(im.getdata()) mean, rms = meanclip(image) #im.close() return rms, numpy.abs(numpy.max(image) / numpy.min(image))
def find_imagenoise(imagename): """ Finds the noise level of an image """ im = pim.image(imagename) image = numpy.copy(im.getdata()) mean, rms = meanclip(image) #im.close() return rms, numpy.abs(numpy.max(image)/numpy.min(image))
def __init__(self, imagename, *args, **kwargs): """ Constructor Keyword arguments: imagename -- Str to casa image of primary beam """ super(MSPrimaryBeamModel, self).__init__(*args, **kwargs) self.imagename = imagename try: from taskinit import ia ia.open(imagename) self.cs = ia.coordsys() self.nx = ia.shape()[0] self.ny = ia.shape()[1] self.refpix_x = self.cs.referencepixel()['numeric'][0] self.refpix_y = self.cs.referencepixel()['numeric'][1] self.increment_x = self.cs.increment()['numeric'][0] self.increment_y = self.cs.increment()['numeric'][1] try: self.frequencyaxis = self.cs.findaxisbyname('frequency') self.nu0 = self.cs.referencevalue()['numeric'][ self.frequencyaxis] except Exception: self.nu0 = None print('Some stuff!') self.data = ia.getregion()[:, :, 0, 0] ia.done() except ImportError: from pyrap.images import image im = image(imagename) self.nx = im.shape()[-1] self.nx = im.shape()[-2] self.cs = im.coordinates() self.cs_dir = self.cs.get_coordinate('direction') self.refpix_x = self.cs_dir.get_referencepixel()[1] self.refpix_y = self.cs_dir.get_referencepixel()[0] self.increment_x = self.cs_dir.get_increment()[1] self.increment_y = self.cs_dir.get_increment()[0] try: self.nu0 = self.cs.get_coordinate( 'spectral').get_referencevalue() except Exception: self.nu0 = None print( 'Warning! No frequency information in primary beam model.') self.data = im.getdata()[0, 0]
def CleanMaskedComponants(self,MaskName,InvertMask=False): print("Cleaning model dictionary from masked components using %s [%i componants]"%(MaskName,len(self.DicoSMStacked["Comp"])), file=log) im=image(MaskName) MaskArray=im.getdata()[0,0].T[::-1] if InvertMask: print(" Inverting the mask", file=log) MaskArray=1-MaskArray for (x,y) in self.DicoSMStacked["Comp"].keys(): if MaskArray[x,y]==0: del(self.DicoSMStacked["Comp"][(x,y)]) print(" There are %i componants left"%len(self.DicoSMStacked["Comp"]), file=log)
def readExternalMaskFromFits(self): CleanMaskImage = self.GD["Mask"]["External"] if not CleanMaskImage: return print(" Reading mask image: %s" % CleanMaskImage, file=log) MaskImage = image(CleanMaskImage).getdata() nch, npol, _, _ = MaskImage.shape MaskArray = np.zeros(MaskImage.shape, np.bool8) for ch in range(nch): for pol in range(npol): MaskArray[ch, pol, :, :] = np.bool8( MaskImage[ch, pol].T[::-1].copy())[:, :] self.ExternalMask = MaskArray
def __init__( self, Gain=0.3, MaxMinorIter=100, NCPU=6, CycleFactor=2.5, FluxThreshold=None, RMSFactor=3, PeakFactor=0, GD=None, SearchMaxAbs=1, CleanMaskImage=None, ImagePolDescriptor=["I"], ModelMachine=None, **kw # absorb any unknown keywords arguments into this ): self.SearchMaxAbs = SearchMaxAbs self.ModelImage = None self.MaxMinorIter = MaxMinorIter self.NCPU = NCPU self.MaskArray = None self.GD = GD self.MultiFreqMode = (self.GD["Freq"]["NBand"] > 1) self.NFreqBand = self.GD["Freq"]["NBand"] self.FluxThreshold = FluxThreshold self.CycleFactor = CycleFactor self.RMSFactor = RMSFactor self.PeakFactor = PeakFactor self.GainMachine = ClassGainMachine.ClassGainMachine(GainMin=Gain) if ModelMachine is None: import ClassModelMachineHogbom as ClassModelMachine self.ModelMachine = ClassModelMachine.ClassModelMachine( self.GD, GainMachine=self.GainMachine) else: self.ModelMachine = ModelMachine self.GainMachine = self.ModelMachine.GainMachine self.GiveEdges = GiveEdges.GiveEdges self._niter = 0 if CleanMaskImage is not None: print >> log, "Reading mask image: %s" % CleanMaskImage MaskArray = image(CleanMaskImage).getdata() nch, npol, _, _ = MaskArray.shape self._MaskArray = np.zeros(MaskArray.shape, np.bool8) for ch in range(nch): for pol in range(npol): self._MaskArray[ch, pol, :, :] = np.bool8( 1 - MaskArray[ch, pol].T[::-1].copy())[:, :] self.MaskArray = self._MaskArray[0] self._peakMode = "normal" self.CurrentNegMask = None self._NoiseMap = None self._PNRStop = None # in _peakMode "sigma", provides addiitonal stopping criterion
def get_rms_noise(imageName): image = pim.image(imageName) nfo = image.info() d = image.getdata() nstokes = d.shape[1] nra = d.shape[2] ndec = d.shape[3] # bmaj = nfo['imageinfo']['restoringbeam']['major']['value'] # bmin = nfo['imageinfo']['restoringbeam']['minor']['value'] # barea = 2.*np.pi*bmaj*bmin/(2.3548**2) noises = [] Id = d[0, 0, (nra // 2 - nra // f):(nra // 2 + nra // f)].flatten() if nstokes == 4: Qd = d[0, 1, (nra // 2 - nra // f):(nra // 2 + nra // f)].flatten() Ud = d[0, 2, (nra // 2 - nra // f):(nra // 2 + nra // f)].flatten() Vd = d[0, 3, (nra // 2 - nra // f):(nra // 2 + nra // f)].flatten() hrange = (-1, 1) Ih = np.histogram(Id, bins=100, range=hrange) # 0 = values, 1 = bin edges Ix = Ih[1][:-1] + 0.5 * (Ih[1][1] - Ih[1][0]) Iv = Ih[0] / float(max(Ih[0])) # stupid fitting method Inoise = myfit(Ix, Iv, imageName + '_histI.png') noises.append(('I', Inoise)) if nstokes == 4: hrange = (-0.1, 0.1) Qh = np.histogram(Qd, bins=100, range=hrange) # 0 = values, 1 = left bin edges Qx = Qh[1][:-1] + 0.5 * (Qh[1][1] - Qh[1][0]) Qv = Qh[0] / float(max(Qh[0])) Uh = np.histogram(Ud, bins=100, range=hrange) # 0 = values, 1 = left bin edges Ux = Uh[1][:-1] + 0.5 * (Uh[1][1] - Uh[1][0]) Uv = Uh[0] / float(max(Uh[0])) Vh = np.histogram(Vd, bins=100, range=hrange) # 0 = values, 1 = left bin edges Vx = Vh[1][:-1] + 0.5 * (Vh[1][1] - Vh[1][0]) Vv = Vh[0] / float(max(Vh[0])) Qnoise = myfit(Qx, Qv, imageName + '_histQ.png') Unoise = myfit(Ux, Uv, imageName + '_histU.png') Vnoise = myfit(Vx, Vv, imageName + '_histV.png') noises.append(('Q', Qnoise)) noises.append(('U', Unoise)) noises.append(('V', Vnoise)) return noises
def ComputeNoiseMap(self): print >> log, "Compute noise map..." Boost = self.Boost Acopy = self.Restored[0, 0, 0::Boost, 0::Boost].copy() SBox = (self.box[0] / Boost, self.box[1] / Boost) # MeanAbs=scipy.ndimage.filters.mean_filter(np.abs(Acopy),SBox) # Acopy[Acopy>0]=MeanAbs[Acopy>0] # Noise=np.sqrt(scipy.ndimage.filters.median_filter(np.abs(Acopy)**2,SBox)) x = np.linspace(-10, 10, 1000) f = 0.5 * (1. + scipy.special.erf(x / np.sqrt(2.))) n = SBox[0] * SBox[1] F = 1. - (1. - f)**n ratio = np.abs(np.interp(0.5, F, x)) Noise = -scipy.ndimage.filters.minimum_filter(Acopy, SBox) / ratio #Noise[Noise<0]=0 # indxy=(Acopy>5.*Noise) # Acopy[indxy]=5*Noise[indxy] # Noise=np.sqrt(scipy.ndimage.filters.median_filter(np.abs(Acopy)**2,SBox)) # indxy=(Acopy>5.*Noise) # Acopy[indxy]=5*Noise[indxy] # Noise=np.sqrt(scipy.ndimage.filters.median_filter(np.abs(Acopy)**2,SBox)) NoiseMed = np.median(Noise) Noise[Noise < NoiseMed] = NoiseMed self.Noise = np.zeros_like(self.Restored[0, 0]) for i in range(Boost): for j in range(Boost): s00, s01 = Noise.shape s10, s11 = self.Noise[i::Boost, j::Boost].shape s0, s1 = min(s00, s10), min(s10, s11) self.Noise[i::Boost, j::Boost][0:s0, 0:s1] = Noise[:, :][0:s0, 0:s1] ind = np.where(self.Noise == 0.) self.Noise[ind] = 1e-10 if self.OutNameNoiseMap != "": print >> log, "Save noise map as %s" % self.OutNameNoiseMap self.CasaIm.saveas(self.OutNameNoiseMap) CasaNoise = image(self.OutNameNoiseMap) CasaNoise.putdata(self.Noise) CasaNoise.tofits(self.OutNameNoiseMap + ".fits") del (CasaNoise) os.system("rm %s" % self.OutNameNoiseMap)
def get_rms_noise (imageName): image = pim.image(imageName) nfo = image.info() d = image.getdata() nstokes = d.shape[1] nra = d.shape[2] ndec = d.shape[3] # bmaj = nfo['imageinfo']['restoringbeam']['major']['value'] # bmin = nfo['imageinfo']['restoringbeam']['minor']['value'] # barea = 2.*np.pi*bmaj*bmin/(2.3548**2) noises = [] Id = d[0,0, (nra/2 - nra/f):(nra/2 + nra/f)].flatten() if nstokes==4: Qd = d[0,1, (nra/2 - nra/f):(nra/2 + nra/f)].flatten() Ud = d[0,2, (nra/2 - nra/f):(nra/2 + nra/f)].flatten() Vd = d[0,3, (nra/2 - nra/f):(nra/2 + nra/f)].flatten() hrange = (-1,1) Ih = np.histogram(Id, bins=100, range=hrange) # 0 = values, 1 = bin edges Ix = Ih[1][:-1] + 0.5*(Ih[1][1] - Ih[1][0]) Iv = Ih[0]/float(max(Ih[0])) # stupid fitting method Inoise = myfit(Ix, Iv, imageName+'_histI.png') noises.append (('I', Inoise)) if nstokes==4: hrange = (-0.1, 0.1) Qh = np.histogram(Qd, bins=100,range=hrange) # 0 = values, 1 = left bin edges Qx = Qh[1][:-1] + 0.5*(Qh[1][1] - Qh[1][0]) Qv = Qh[0]/float(max(Qh[0])) Uh = np.histogram(Ud, bins=100, range=hrange) # 0 = values, 1 = left bin edges Ux = Uh[1][:-1] + 0.5*(Uh[1][1] - Uh[1][0]) Uv = Uh[0]/float(max(Uh[0])) Vh = np.histogram(Vd, bins=100, range=hrange) # 0 = values, 1 = left bin edges Vx = Vh[1][:-1] + 0.5*(Vh[1][1] - Vh[1][0]) Vv = Vh[0]/float(max(Vh[0])) Qnoise = myfit(Qx, Qv, imageName+'_histQ.png') Unoise = myfit(Ux, Uv, imageName+'_histU.png') Vnoise = myfit(Vx, Vv, imageName+'_histV.png') noises.append (('Q', Qnoise)) noises.append (('U', Unoise)) noises.append (('V', Vnoise)) return noises
def getPatchNamesFromMask(mask, RARad, DecRad, root='mask'): """ Returns an array of patch names for each (RA, Dec) pair in radians """ import math import pyrap.images as pim import scipy.ndimage as nd import numpy as np maskdata = pim.image(mask) maskval = maskdata.getdata()[0][0] act_pixels = maskval rank = len(act_pixels.shape) connectivity = nd.generate_binary_structure(rank, rank) mask_labels, count = nd.label(act_pixels, connectivity) patchNums = [] patchNames = [] for raRad, decRad in zip(RARad, DecRad): (a, b, _, _) = maskdata.toworld([0, 0, 0, 0]) (_, _, pixY, pixX) = maskdata.topixel([a, b, decRad, raRad]) try: # != is a XOR for booleans patchNums.append(mask_labels[int(pixY), int(pixX)]) except: patchNums.append(0) # Check if there is a patch with id = 0. If so, this means there were # some Gaussians that fell outside of the regions in the patch # mask file. n = 0 for p in patchNums: if p != 0: in_patch = np.where(patchNums == p) if pad_index: patchNames.append( '{0}_patch_'.format(root) + str(p).zfill(int(np.ceil(np.log10(len(patchNums)))))) else: patchNames.append('{0}_patch_'.format(root) + str(p)) else: patchNames.append('patch_' + str(n)) n += 1 return np.array(patchNames)
def PutDataInNewImage(ImageNameIn, ImageNameOut, data, CorrT=False): im = image(ImageNameIn) F = pyfits.open(ImageNameIn) F0 = F[0] nx = F0.header["NAXIS1"] ny = F0.header["NAXIS2"] npol = F0.header["NAXIS3"] nch = F0.header["NAXIS4"] shape = (nch, npol, ny, nx) Dico = im.coordinates().dict() cell = abs(Dico["direction0"]["cdelt"][0]) * 180 / np.pi * 3600 ra, dec = Dico["direction0"]["crval"] CasaImage = ClassCasaimage(ImageNameOut, shape, cell, (ra, dec)) CasaImage.setdata(data, CorrT=CorrT) CasaImage.ToFits() CasaImage.close()
def getPatchNamesFromMask(mask, RARad, DecRad, root='mask', pad_index=False): """ Returns an array of patch names for each (RA, Dec) pair in radians """ import pyrap.images as pim import scipy.ndimage as nd import numpy as np maskdata = pim.image(mask) maskval = maskdata.getdata()[0][0] act_pixels = maskval rank = len(act_pixels.shape) connectivity = nd.generate_binary_structure(rank, rank) mask_labels, count = nd.label(act_pixels, connectivity) patchNums = [] patchNames = [] for raRad, decRad in zip(RARad, DecRad): (a, b, _, _) = maskdata.toworld([0, 0, 0, 0]) (_, _, pixY, pixX) = maskdata.topixel([a, b, decRad, raRad]) try: # != is a XOR for booleans patchNums.append(mask_labels[int(pixY), int(pixX)]) except: patchNums.append(0) # Check if there is a patch with id = 0. If so, this means there were # some Gaussians that fell outside of the regions in the patch # mask file. n = 0 for p in patchNums: if p != 0: if pad_index: patchNames.append('{0}_patch_'.format(root) + str(p).zfill(int(np.ceil(np.log10(len(set(patchNums))+1))))) else: patchNames.append('{0}_patch_'.format(root)+str(p)) else: patchNames.append('patch_'+str(n)) n += 1 return np.array(patchNames)
def setModelImage(self): print "set model image" self.im=image(self.Fits) im=self.im c=im.coordinates() dx,_=c.__dict__["_csys"]["direction0"]["cdelt"] self.CellSizeRad=np.abs(dx) self.PSFGaussPars=self.ResInPix*self.CellSizeRad,self.ResInPix*self.CellSizeRad,0. Fits=self.Fits self.Model=self.im.getdata()[0,0] if self.XcYcDx!=None: xc,yc,dx=self.XcYcDx x0,x1=xc-dx,xc+dx y0,y1=yc-dx,yc+dx self.Model=self.Model[x0:x1,y0:y1] #self.Plot(self.Model) print " done set model image"
def find_imagenoise(imagename): """ Finds noise and dynamic range for an image Parameters ---------- imagename : str Filename of image Returns ------- rms : float Noise (Jy/beam) of image dynamic_range : float Dynamic range (max/min) of image """ im = pim.image(imagename) image = numpy.copy(im.getdata()) mean, rms = meanclip(image) return rms, numpy.abs(numpy.max(image)/rms)
def getMaskValues(mask, RARad, DecRad): """ Returns an array of mask values for each (RA, Dec) pair in radians. """ import math import pyrap.images as pim import numpy as np maskdata = pim.image(mask) maskval = maskdata.getdata()[0][0] vals = [] for raRad, decRad in zip(RARad, DecRad): (a, b, _, _) = maskdata.toworld([0, 0, 0, 0]) (_, _, pixY, pixX) = maskdata.topixel([a, b, decRad, raRad]) try: if maskval[int(pixY), int(pixX)]: vals.append(True) else: vals.append(False) except: vals.append(False) return np.array(vals)
def getrms(image,facetmask=None): """ Return the rms of source-free regions in the image. image should be a FITS file of the form xxx-image.fits. xxxnm-fitsmask should exist. """ mask=image.replace('-image.fits','nm.fitsmask') if facetmask is None: # guess facet mask name root=image[16:].replace('-image.fits','') facetmask='templatemask_'+root+'.masktmp' imhdu=pyfits.open(image) mkhdu=pyfits.open(mask) maskim=pi.image(facetmask) imdata=imhdu[0].data[0,0] maskdata=mkhdu[0].data[0,0] fmaskdata=maskim.getdata()[0,0] assert(imdata.shape==maskdata.shape) assert(imdata.shape==fmaskdata.shape) filter=(maskdata==0) & (fmaskdata==1) mdata=imdata[filter] return np.std(mdata)
def getrms(image, facetmask=None): """ Return the rms of source-free regions in the image. image should be a FITS file of the form xxx-image.fits. xxxnm-fitsmask should exist. """ mask = image.replace('-image.fits', 'nm.fitsmask') if facetmask is None: # guess facet mask name root = image[16:].replace('-image.fits', '') facetmask = 'templatemask_' + root + '.masktmp' imhdu = pyfits.open(image) mkhdu = pyfits.open(mask) maskim = pi.image(facetmask) imdata = imhdu[0].data[0, 0] maskdata = mkhdu[0].data[0, 0] fmaskdata = maskim.getdata()[0, 0] assert (imdata.shape == maskdata.shape) assert (imdata.shape == fmaskdata.shape) filter = (maskdata == 0) & (fmaskdata == 1) mdata = imdata[filter] return np.std(mdata)
def getMaskValues(mask, RARad, DecRad): """ Returns an array of mask values for each (RA, Dec) pair in radians. """ import math import pyrap.images as pim import numpy as np maskdata = pim.image(mask) maskval = maskdata.getdata()[0][0] vals = [] for raRad, decRad in zip(RARad, DecRad): (a, b, _, _) = maskdata.toworld([0, 0, 0, 0]) (_, _, pixY, pixX) = maskdata.topixel([a, b, decRad, raRad]) try: if maskval[pixY, pixX]: vals.append(True) else: vals.append(False) except: vals.append(False) return np.array(vals)
def __init__ (self, path, mode): try: from pyrap.images import image except ImportError: raise UnsupportedError ('cannot open CASAcore images in Pyrap mode without ' 'the Python module "pyrap.images"') super (PyrapImage, self).__init__ (path, mode) # no mode specifiable self._handle = image (path) allinfo = self._handle.info () self.units = maybelower (allinfo.get ('unit')) self.shape = np.asarray (self._handle.shape (), dtype=np.int) self.axdescs = [] if 'coordinates' in allinfo: pc = allinfo['coordinates'].get ('pointingcenter') # initial=True signifies that the pointing center information # hasn't actually been initialized. if pc is not None and not pc['initial']: # This bit of info doesn't have any metadata about units or # whatever; appears to be fixed as RA/Dec in radians. self.pclat = pc['value'][1] self.pclon = pc['value'][0] ii = self._handle.imageinfo () if 'restoringbeam' in ii: self.bmaj = _pyrap_convert (ii['restoringbeam']['major'], 'rad') self.bmin = _pyrap_convert (ii['restoringbeam']['minor'], 'rad') self.bpa = _pyrap_convert (ii['restoringbeam']['positionangle'], 'rad') # Make sure that angular units are always measured in radians, # because anything else is ridiculous. from pyrap.quanta import quantity self._wcscale = wcscale = np.ones (self.shape.size) c = self._handle.coordinates () radian = quantity (1., 'rad') for item in c.get_axes (): if isinstance (item, six.string_types): self.axdescs.append (item.replace (' ', '_')) else: for subitem in item: self.axdescs.append (subitem.replace (' ', '_')) def getconversion (text): q = quantity (1., text) if q.conforms (radian): return q.get_value ('rad') return 1 i = 0 for item in c.get_unit (): if isinstance (item, six.string_types): wcscale[i] = getconversion (item) i += 1 elif len (item) == 0: wcscale[i] = 1 # null unit i += 1 else: for subitem in item: wcscale[i] = getconversion (subitem) i += 1 # Figure out which axes are lat/long/spec. We have some # paranoia code the give up in case there are multiple axes # that appear to be of the same type. This stuff could # be cleaned up. lat = lon = spec = -1 try: logspecidx = c.get_names ().index ('spectral') except ValueError: specaxname = None else: specaxname = c.get_axes ()[logspecidx] for i, name in enumerate (self.axdescs): # These symbolic direction names obtained from # casacore/coordinates/Coordinates/DirectionCoordinate.cc # Would be nice to have a better system for determining # this a la what wcslib provides. if name == specaxname: spec = i elif name in ('Right_Ascension', 'Hour_Angle', 'Longitude'): if lon == -1: lon = i else: lon = -2 elif name in ('Declination', 'Latitude'): if lat == -1: lat = i else: lat = -2 if lat >= 0: self._latax = lat if lon >= 0: self._lonax = lon if spec >= 0: self._specax = spec # Phew, that was gross. if self._specax is not None: sd = c.get_coordinate ('spectral').dict () wi = sd.get ('wcs') if wi is not None: try: from mirtask._miriad_c import mirwcs_compute_freq except ImportError: pass else: spectype = wi['ctype'].replace ('\x00', '')[:4] restfreq = sd.get ('restfreq', 0.) specval = self.toworld (0.5 * (self.shape - 1))[self._specax] self.charfreq = mirwcs_compute_freq (spectype, specval, restfreq) * 1e-9 # TODO: any unit weirdness or whatever here? self.mjd = c.get_obsdate ()['m0']['value']
#!/usr/bin/python # Write CASA image to fits import sys import pyrap.images as pi import os.path args=len(sys.argv) if (args==1): print "usage: tofits.py [CASA images]"; sys.exit(1) for fn in sys.argv[1:]: print 'Doing',fn outname=fn+'.fits' if os.path.isfile(outname): print '... skip, FITS file already exists' continue im=pi.image(fn) im.tofits(outname) print '... writing FITS file'
# Quick & dirty inverse-variance weighted image averaging. # John Swinbank, 2010-07-10 import sys from numpy import average from pyrap.images import image image_data = [ image(file).getdata() for file in sys.argv[2:] ] result = average( image_data, axis=0, weights=[1/data.var() for data in image_data] ) output = image( sys.argv[1] + ".img", values=result, coordsys=image(sys.argv[2]).coordinates() ) output.tofits(sys.argv[1] + ".fits")
# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # #usage: extractbeam.py imagename import pyrap.images as pim from pyrap import quanta import sys for img in sys.argv[1:]: this_pim = pim.image(img) info_dict = this_pim.info()['imageinfo']['restoringbeam'] # get beam info bpar_ma = quanta.quantity(info_dict['major']).get_value('arcsec') bpar_mi = quanta.quantity(info_dict['minor']).get_value('arcsec') bpar_pa = quanta.quantity(info_dict['positionangle']).get_value('deg') print('\n{0} - Beam: maj {1:0.3f} (arcsec), min {2:2.3f} (arcsec), pa {3:0.2f} (deg)'.format(img, bpar_ma, bpar_mi,bpar_pa))
X,Y = np.shape(rawdata) rawdata = rawdata[Y/3:2*Y/3,X/3:2*X/3] orig_raw = rawdata med, std, mask = Median_clip(rawdata, full_output=True, ftol=0.0, max_iter=10, sigma=4) rawdata[mask==False] = med v[i]=std fln.close() for i in range(0,x): w[i]=1/v[i] print "Calculated weights:\n{0}".format(w) #Gather images image_data = [ image(file).getdata() for file in y ] #Write result result = np.average( image_data, axis=0, weights=w ) output = image( img_name, values=result, coordsys=image(y[-1]).coordinates() ) output.tofits(fits_name)
def _allocate_buffers( imagenames, new_stampsize, nstackpos): import numpy as np try: from taskinit import ia dataread = 'casa' except ImportError: from pyrap.images import image dataread = 'pyrap' global skymap global data global oldimagenames global stampsize global imagesizes if dataread == 'casa': ia.open(imagenames[0]) cs = ia.coordsys() outnchans = ia.boundingbox()['trc'][2]+1 outnstokes = ia.boundingbox()['trc'][3]+1 ia.done() elif dataread == 'pyrap': im = image(imagenames[0]) cs = im.coordinates() outnchans = im.shape()[cs.get_axes().index(cs.get_coordinate('spectral').get_axes())] outnstokes = im.shape()[cs.get_axes().index(cs.get_coordinate('stokes').get_axes())] # To improve performance this module will keep buffers between run. # This following code resets these buffers if they have grown obsolete. if oldimagenames == []: oldimagenames = imagenames if oldimagenames != imagenames: oldimagenames = imagenames skymap = [] data = [] if stampsize == 0: stampsize = new_stampsize elif stampsize != new_stampsize: stampsize = new_stampsize data = [] skymap = [] if not(data == []) and nstackpos != data.shape[0]: data = [] # If there is no data buffer create one. # The data buffer is used to save the right stacking positions before stacking them. # During stacking this is where the full stack will actually be saved. if data == []: data = np.zeros((nstackpos, new_stampsize, new_stampsize, outnstokes, outnchans)) else: data = 0.*data # If there is no skymap buffer create one. # This is the data that is most important to buffer. # Reading a skymap from disk is a time consuming task and we don't want to do this too much. if skymap == []: for imagename in imagenames: if dataread == 'casa': ia.open(imagename) skymap.append(ia.getregion()) ia.done() elif dataread == 'pyrap': buff = im.getdata() dir_axis = cs.get_axes().index(cs.get_coordinate('direction').get_axes()) x_axis = dir_axis+cs.get_coordinate('direction').get_axes().index('Right Ascension') y_axis = dir_axis+cs.get_coordinate('direction').get_axes().index('Declination') specax = cs.get_axes().index(cs.get_coordinate('spectral').get_axes()) stokesax = cs.get_axes().index(cs.get_coordinate('stokes').get_axes()) axis_order = [x_axis, y_axis, stokesax, specax] for i in range(len(axis_order)-1): if axis_order[i] != i: target = axis_order.index(i) origin = i buff = buff.swapaxes(axis_order[origin], axis_order[target]) axis_order[origin], axis_order[target] =\ axis_order[target], axis_order[origin] skymap.append(buff) imagesizes = [] for imagename in imagenames: if dataread == 'casa': ia.open(imagename) imagesizes.append((ia.shape()[0], ia.shape()[1])) ia.done() elif dataread == 'pyrap': dir_axis = cs.get_axes().index(cs.get_coordinate('direction').get_axes()) x_axis_index = dir_axis+cs.get_coordinate('direction').get_axes().index('Right Ascension') y_axis_index = dir_axis+cs.get_coordinate('direction').get_axes().index('Declination') imagesizes.append((im.shape()[x_axis_index], im.shape()[y_axis_index]))
def main(image_name, mask_name, atrous_do=False, threshisl=0.0, threshpix=0.0, rmsbox=None, rmsbox_bright=(35, 7), iterate_threshold=False, adaptive_rmsbox=False, img_format='fits', threshold_format='float', trim_by=0.0, vertices_file=None, atrous_jmax=6, pad_to_size=None, skip_source_detection=False, region_file=None, nsig=5.0, reference_ra_deg=None, reference_dec_deg=None): """ Make a clean mask and return clean threshold Parameters ---------- image_name : str Filename of input image from which mask will be made. If the image does not exist, a template image with center at (reference_ra_deg, reference_dec_deg) will be made internally mask_name : str Filename of output mask image atrous_do : bool, optional Use wavelet module of PyBDSM? threshisl : float, optional Value of thresh_isl PyBDSM parameter threshpix : float, optional Value of thresh_pix PyBDSM parameter rmsbox : tuple of floats, optional Value of rms_box PyBDSM parameter rmsbox_bright : tuple of floats, optional Value of rms_box_bright PyBDSM parameter iterate_threshold : bool, optional If True, threshold will be lower in 20% steps until at least one island is found adaptive_rmsbox : tuple of floats, optional Value of adaptive_rms_box PyBDSM parameter img_format : str, optional Format of output mask image (one of 'fits' or 'casa') threshold_format : str, optional Format of output threshold (one of 'float' or 'str_with_units') trim_by : float, optional Fraction by which the perimeter of the output mask will be trimmed (zeroed) vertices_file : str, optional Filename of file with vertices (must be a pickle file containing a dictionary with the vertices in the 'vertices' entry) atrous_jmax : int, optional Value of atrous_jmax PyBDSM parameter pad_to_size : int, optional Pad output mask image to a size of pad_to_size x pad_to_size skip_source_detection : bool, optional If True, source detection is not run on the input image region_file : str, optional Filename of region file in CASA format. If given, no mask image is made (the region file is used as the clean mask) nsig : float, optional Number of sigma of returned threshold value reference_ra_deg : float, optional RA for center of output mask image reference_dec_deg : float, optional Dec for center of output mask image Returns ------- result : dict Dict with nsig-sigma rms threshold """ if image_name is not None: if image_name.lower() == 'none': image_name = None if rmsbox is not None and type(rmsbox) is str: rmsbox = eval(rmsbox) if type(rmsbox_bright) is str: rmsbox_bright = eval(rmsbox_bright) if pad_to_size is not None and type(pad_to_size) is str: pad_to_size = int(pad_to_size) if type(atrous_do) is str: if atrous_do.lower() == 'true': atrous_do = True threshisl = 4.0 # override user setting to ensure proper source fitting else: atrous_do = False if type(iterate_threshold) is str: if iterate_threshold.lower() == 'true': iterate_threshold = True else: iterate_threshold = False if type(adaptive_rmsbox) is str: if adaptive_rmsbox.lower() == 'true': adaptive_rmsbox = True else: adaptive_rmsbox = False if type(skip_source_detection) is str: if skip_source_detection.lower() == 'true': skip_source_detection = True else: skip_source_detection = False if reference_ra_deg is not None and reference_dec_deg is not None: reference_ra_deg = float(reference_ra_deg) reference_dec_deg = float(reference_dec_deg) if not os.path.exists(image_name): print('Input image not found. Making empty image...') if not skip_source_detection: print('ERROR: Source detection cannot be done on an empty image') sys.exit(1) if reference_ra_deg is not None and reference_dec_deg is not None: image_name = mask_name + '.tmp' make_template_image(image_name, reference_ra_deg, reference_dec_deg) else: print('ERROR: if image not found, a refernce position must be given') sys.exit(1) trim_by = float(trim_by) atrous_jmax = int(atrous_jmax) threshpix = float(threshpix) threshisl = float(threshisl) nsig = float(nsig) if not skip_source_detection: if vertices_file is not None: # Modify the input image to blank the regions outside of the polygon temp_img = pim.image(image_name) image_name += '.blanked' temp_img.saveas(image_name, overwrite=True) input_img = pim.image(image_name) data = input_img.getdata() vertices = read_vertices(vertices_file) RAverts = vertices[0] Decverts = vertices[1] xvert = [] yvert = [] for RAvert, Decvert in zip(RAverts, Decverts): pixels = input_img.topixel([1, 1, Decvert*np.pi/180.0, RAvert*np.pi/180.0]) xvert.append(pixels[2]) # x -> Dec yvert.append(pixels[3]) # y -> RA poly = Polygon(xvert, yvert) # Find masked regions masked_ind = np.where(data[0, 0]) # Find distance to nearest poly edge and set to NaN those that # are outside the facet (dist < 0) dist = poly.is_inside(masked_ind[0], masked_ind[1]) outside_ind = np.where(dist < 0.0) if len(outside_ind[0]) > 0: data[0, 0, masked_ind[0][outside_ind], masked_ind[1][outside_ind]] = np.nan # Save changes input_img.putdata(data) if iterate_threshold: # Start with given threshold and lower it until we get at least one island nisl = 0 while nisl == 0: img = bdsm.process_image(image_name, mean_map='zero', rms_box=rmsbox, thresh_pix=threshpix, thresh_isl=threshisl, atrous_do=atrous_do, ini_method='curvature', thresh='hard', adaptive_rms_box=adaptive_rmsbox, adaptive_thresh=150, rms_box_bright=rmsbox_bright, rms_map=True, quiet=True, atrous_jmax=atrous_jmax) nisl = img.nisl threshpix /= 1.2 threshisl /= 1.2 if threshpix < 5.0: break else: img = bdsm.process_image(image_name, mean_map='zero', rms_box=rmsbox, thresh_pix=threshpix, thresh_isl=threshisl, atrous_do=atrous_do, ini_method='curvature', thresh='hard', adaptive_rms_box=adaptive_rmsbox, adaptive_thresh=150, rms_box_bright=rmsbox_bright, rms_map=True, quiet=True, atrous_jmax=atrous_jmax) if img.nisl == 0: print('No islands found. Clean mask cannot be made.') sys.exit(1) # Check if there are large islands preset (indicating that multi-scale # clean is needed) has_large_isl = False for isl in img.islands: if isl.size_active > 100: # Assuming normal sampling, a size of 100 pixels would imply # a source of ~ 10 beams has_large_isl = True if (region_file is not None) and (region_file != '[]'): # Copy the CASA region file (stripped of brackets, etc.) and return os.system('cp {0} {1}'.format(region_file.strip('[]"'), mask_name)) if not skip_source_detection: if threshold_format == 'float': return {'threshold_5sig': nsig * img.clipped_rms, 'multiscale': has_large_isl} elif threshold_format == 'str_with_units': # This is done to get around the need for quotes around strings in casapy scripts # 'casastr/' is removed by the generic pipeline return {'threshold_5sig': 'casastr/{0}Jy'.format(nsig * img.clipped_rms), 'multiscale': has_large_isl} else: return {'threshold_5sig': '0.0'} elif not skip_source_detection: img.export_image(img_type='island_mask', mask_dilation=0, outfile=mask_name, img_format=img_format, clobber=True) if vertices_file is not None or trim_by > 0 or pad_to_size is not None or skip_source_detection: # Alter the mask in various ways if skip_source_detection: # Read the image mask_im = pim.image(image_name) else: # Read the PyBDSM mask mask_im = pim.image(mask_name) data = mask_im.getdata() coordsys = mask_im.coordinates() if reference_ra_deg is not None and reference_dec_deg is not None: values = coordsys.get_referencevalue() values[2][0] = reference_dec_deg/180.0*np.pi values[2][1] = reference_ra_deg/180.0*np.pi coordsys.set_referencevalue(values) imshape = mask_im.shape() del(mask_im) if pad_to_size is not None: imsize = pad_to_size coordsys['direction'].set_referencepixel([imsize/2, imsize/2]) pixmin = (imsize - imshape[2]) / 2 if pixmin < 0: print("The padded size must be larger than the original size.") sys.exit(1) pixmax = pixmin + imshape[2] data_pad = np.zeros((1, 1, imsize, imsize), dtype=np.float32) data_pad[0, 0, pixmin:pixmax, pixmin:pixmax] = data[0, 0] new_mask = pim.image('', shape=(1, 1, imsize, imsize), coordsys=coordsys) new_mask.putdata(data_pad) else: new_mask = pim.image('', shape=imshape, coordsys=coordsys) new_mask.putdata(data) data = new_mask.getdata() if skip_source_detection: # Mask all pixels data[:] = 1 if vertices_file is not None: # Modify the clean mask to exclude regions outside of the polygon vertices = read_vertices(vertices_file) RAverts = vertices[0] Decverts = vertices[1] xvert = [] yvert = [] for RAvert, Decvert in zip(RAverts, Decverts): try: pixels = new_mask.topixel([0, 1, Decvert*np.pi/180.0, RAvert*np.pi/180.0]) except: pixels = new_mask.topixel([1, 1, Decvert*np.pi/180.0, RAvert*np.pi/180.0]) xvert.append(pixels[2]) # x -> Dec yvert.append(pixels[3]) # y -> RA poly = Polygon(xvert, yvert) # Find masked regions masked_ind = np.where(data[0, 0]) # Find distance to nearest poly edge and unmask those that # are outside the facet (dist < 0) dist = poly.is_inside(masked_ind[0], masked_ind[1]) outside_ind = np.where(dist < 0.0) if len(outside_ind[0]) > 0: data[0, 0, masked_ind[0][outside_ind], masked_ind[1][outside_ind]] = 0 if trim_by > 0.0: sh = np.shape(data) margin = int(sh[2] * trim_by / 2.0 ) data[0, 0, 0:sh[2], 0:margin] = 0 data[0, 0, 0:margin, 0:sh[3]] = 0 data[0, 0, 0:sh[2], sh[3]-margin:sh[3]] = 0 data[0, 0, sh[2]-margin:sh[2], 0:sh[3]] = 0 # Save changes new_mask.putdata(data) if img_format == 'fits': new_mask.tofits(mask_name, overwrite=True) elif img_format == 'casa': new_mask.saveas(mask_name, overwrite=True) else: print('Output image format "{}" not understood.'.format(img_format)) sys.exit(1) if not skip_source_detection: if threshold_format == 'float': return {'threshold_5sig': nsig * img.clipped_rms, 'multiscale': has_large_isl} elif threshold_format == 'str_with_units': # This is done to get around the need for quotes around strings in casapy scripts # 'casastr/' is removed by the generic pipeline return {'threshold_5sig': 'casastr/{0}Jy'.format(nsig * img.clipped_rms), 'multiscale': has_large_isl} else: return {'threshold_5sig': '0.0'}
def main(args): # Generate lists of input images and check that they exist images=[] avgpbs=[] psf_fwhm = [] # resolution frequency = [] # frequency of images (should be equal?) imagesbase=args.images.split(',') for base in imagesbase: images.append(base+'.'+args.extension) if not os.path.exists(images[-1]): print("Error: Image",images[-1],"does not exist") return 1 avgpbs.append(base+'.'+args.avgpbext) if not os.path.exists(avgpbs[-1]): print("Error: PB image",avgpbs[-1],"does not exist") return 1 # Collect weights and invert if requested if args.weights == '': weights = np.ones(len(images)) else: weights = np.array(args.weights.split(',')).astype('float') if args.invertwt: weights = 1./weights if len(weights) != len(images): print("Error: List of weights is not the same length as list of images.") return 1 print("Combining images") formstr = '{0:45s} {1:45s} {2:s} {3:s} {4:s} {5:s}' print(formstr.format("-----","--------","------------","-------","-------","------")) print(formstr.format("Image", "PB image","Norm. weight", "Maj(ac)", "Min(ac)","PA(deg)")) print(formstr.format("-----","--------","------------","-------","-------","------")) for i in range(len(images)): this_pim = pim.image(images[i]) info_dict = this_pim.info()['imageinfo']['restoringbeam'] # get beam info bpar_ma = quanta.quantity(info_dict['major']).get_value('deg') bpar_mi = quanta.quantity(info_dict['minor']).get_value('deg') bpar_pa = quanta.quantity(info_dict['positionangle']).get_value('deg') psf_fwhm.append([bpar_ma, bpar_mi, bpar_pa]) frequency.append(this_pim.info()['coordinates']['spectral2']['restfreq']) print('{0:45.45s} {1:45.45s} {2:0.2f} {3:0.2f} {4:0.2f} {5:0.2f}'.format(images[i], avgpbs[i], weights[i]/sum(weights), bpar_ma*60, bpar_mi*60,bpar_pa)) psf_fwhm = np.array(psf_fwhm) frequency = np.array(frequency) mean_psf_fwhm = np.mean(psf_fwhm, axis=0) mean_frequency = np.mean(frequency) print('\nmean Beam: {0:0.3f} maj (arcmin), {1:2.3f} min (arcmin), {2:0.2f} pa (deg)'.format(mean_psf_fwhm[0]*60, mean_psf_fwhm[1]*60, mean_psf_fwhm[2])) print('(Frequency (MHz):', mean_frequency*1e-6) if np.max(mean_frequency-frequency)/mean_frequency > 1e-6: print('\n\nWARNING.\nAre you using images from different bands?') print('Frequencies (Hz):', frequency) # Initialize some vectors declims = [] # store the limits of the declination axes ralims = [] # store the limits of the r.a. axes rainc = [] # store the r.a. increments in case they differ decinc = [] # store the dec increments in case they differ pims = [] # stores the pyrap images of the data ppbs = [] # stores the pyrap images of the pb images # Get image frames for input images for im, pb in zip(images, avgpbs): image = pim.image(im) sptcoords = image.coordinates().get_coordinate('spectral') nc = sptcoords.get_axis_size() assert(sptcoords.get_image_axis() == 0) # Get Stokes axis. Ensure we are working with the Stokes parameter requested. stkcoords = image.coordinates().get_coordinate('stokes') assert(stkcoords.get_image_axis() == 1) if stkcoords.get_axis_size() == 1: assert(stkcoords.get_stokes()[0] == args.stokes) else: stks = stkcoords.get_stokes().index(args.stokes) image = image.subimage(blc=(0, stks), trc=(nc-1, stks), dropdegenerate=False) ns = 1 dircoords = image.coordinates().get_coordinate('direction') nx = dircoords.get_axis_size(axis=1) ny = dircoords.get_axis_size(axis=0) inc = dircoords.get_increment() ref = dircoords.get_referencepixel() val = dircoords.get_referencevalue() ra_axis = (list(range(nx))-ref[1])*inc[1]+val[1] dec_axis = (list(range(ny))-ref[0])*inc[0]+val[0] rainc.append(inc[1]) decinc.append(inc[0]) declims.append(min(dec_axis)) declims.append(max(dec_axis)) mean_ra = np.mean(ra_axis) ralims.append((min(ra_axis)-mean_ra)*np.cos(val[0])+mean_ra) ralims.append((max(ra_axis)-mean_ra)*np.cos(val[0])+mean_ra) pims.append(image) ppbs.append(pim.image(pb)) # Generate the mosaic coordinate frame master_dec = np.arange(min(declims),max(declims),min(decinc)) if max(ralims)-min(ralims) > 5.*np.pi/3.: # crossed RA=0 print("Warning: I think the mosaic crosses RA=0, treating the coordinates as such.") #ralims[ralims>np.pi] -= 2.*np.pi for i in range(len(ralims)): if ralims[i]>np.pi: ralims[i] = ralims[i]-2.*np.pi master_ra = np.arange(max(ralims),min(ralims),max(rainc)) if args.verbose: print("Found ra,dec pixel increments (arcsec):") print(np.array(rainc)*206265.) print(np.array(decinc)*206265.) ma = pims[-1].coordinates() ma['direction'].set_referencepixel([len(master_dec)/2,len(master_ra)/2]) ma['direction'].set_increment([min(decinc),max(rainc)]) ma['direction'].set_referencevalue([master_dec[len(master_dec)/2],master_ra[len(master_ra)/2]]) if args.NCP: print('Setting NCP projection is not yet working ....') #ma['direction'].set_projection('ZEA') # Initialize the arrays for the output image, sensitivity, and weights master_im = np.zeros((len(master_dec),len(master_ra))) master_weight = np.zeros((len(master_dec),len(master_ra))) master_sens = np.zeros((len(master_dec),len(master_ra))) # Reproject the images onto the master grid, weight and normalize for i in range(len(pims)): im = pims[i].regrid([2,3],ma,outshape=(nc,ns,len(master_dec),len(master_ra))) pb = ppbs[i].regrid([2,3],ma,outshape=(nc,ns,len(master_dec),len(master_ra))) imdata = np.squeeze(im.getdata()) pbdata = np.squeeze(pb.getdata()) newim = imdata newpb = pbdata newwt = (weights[i]*newpb)**2 master_im += newim*newwt master_sens += newpb*newwt master_weight += newwt inds = master_weight != 0. master_im[inds] /= master_weight[inds] master_sens[inds] /= master_weight[inds] # Show image if requested if args.plotimg: plt.imshow(master_im,vmin=0.,vmax=0.5) plt.show() # Write fits files arrax = np.zeros( (1,1, len(master_im[:,0]), len(master_im[0,:])) ) arrax[0,0,:,:] = master_im # Open new casa image for mosaic new_pim = pim.image('',shape=(1,1, len(master_dec),len(master_ra)), coordsys=ma) new_pim.putdata(arrax) # Write fits new_pim.tofits(args.outfits, overwrite=True) # Same for sensitivity new_pim_sens = pim.image('',shape=(1,1,len(master_dec),len(master_ra)),coordsys=ma) arrax[0,0,:,:] = master_sens new_pim_sens.putdata(arrax) # new_pim_sens.tofits(args.sensfits, overwrite=True) # need to add new beam info (not sure if this is possible with pyrap) hdu = pyfits.open(args.outfits,mode='update') header = hdu[0].header header.update('BMAJ',mean_psf_fwhm[0]) header.update('BMIN',mean_psf_fwhm[1]) header.update('BPA',mean_psf_fwhm[2]) header.update('BUNIT',pims[-1].info()['unit']) header.update('RESTFRQ',mean_frequency) header.update('RESTFREQ',mean_frequency) newhdu = pyfits.PrimaryHDU(data=hdu[0].data, header=header) newhdu.writeto(args.outfits,clobber=True) return
# # Copyright (C) 2013 - Francesco de Gasperin # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # usage: extractbeam.py imagename import pyrap.images as pim from pyrap import quanta import sys this_pim = pim.image(sys.argv[1]) info_dict = this_pim.info()["imageinfo"]["restoringbeam"] # get beam info bpar_ma = quanta.quantity(info_dict["major"]).get_value("arcsec") bpar_mi = quanta.quantity(info_dict["minor"]).get_value("arcsec") bpar_pa = quanta.quantity(info_dict["positionangle"]).get_value("deg") print "\nmean Beam: {0:0.3f} maj (arcsec), {1:2.3f} min (arcsec), {2:0.2f} pa (deg)".format(bpar_ma, bpar_mi, bpar_pa)
def run(self, awimager_output, ms_per_image, sourcelist, target, output_image, minbaseline, maxbaseline, processed_ms_dir, fillrootimagegroup_exec, environment, sourcedb, concat_ms, correlated_output_location, msselect_executable): self.environment.update(environment) """ :param awimager_output: Path to the casa image produced by awimager :param ms_per_image: The X (90) measurements set scheduled to create the image :param sourcelist: list of sources found in the image :param target: <unused> :param minbaseline: Minimum baseline used for the image :param maxbaseline: largest/maximum baseline used for the image :param processed_ms_dir: The X (90) measurements set actually used to create the image :param fillrootimagegroup_exec: Executable used to add image data to the hdf5 image :rtype: self.outputs['hdf5'] set to "succes" to signal node succes :rtype: self.outputs['image'] path to the produced hdf5 image """ with log_time(self.logger): ms_per_image_map = DataMap.load(ms_per_image) # ***************************************************************** # 1. add image info # Get all the files in the processed measurement dir file_list = os.listdir(processed_ms_dir) processed_ms_paths = [] ms_per_image_map.iterator = DataMap.SkipIterator for item in ms_per_image_map: ms_path = item.file processed_ms_paths.append(ms_path) #add the information the image try: self.logger.debug("Start addImage Info") addimg.addImagingInfo(awimager_output, processed_ms_paths, sourcedb, minbaseline, maxbaseline) except Exception, error: self.logger.warn("addImagingInfo Threw Exception:") self.logger.warn(error) # Catch raising of already done error: allows for rerunning # of the recipe if "addImagingInfo already done" in str(error): self.logger.warn("addImagingInfo already done, continue") pass else: raise Exception(error) #The majority of the tables is updated correctly # *************************************************************** # 2. convert to hdf5 image format output_directory = None pim_image = pim.image(awimager_output) try: self.logger.info("Saving image in HDF5 Format to: {0}" .format( output_image)) # Create the output directory output_directory = os.path.dirname(output_image) create_directory(output_directory) # save the image pim_image.saveas(output_image, hdf5=True) except Exception, error: self.logger.error( "Exception raised inside pyrap.images: {0}".format( str(error))) raise error
def main(args): # Generate lists of input images and check that they exist images=[] avgpbs=[] psf_fwhm = [] # resolution frequency = [] # frequency of images (should be equal?) #imagesbase=args.images.split(',') #for base in imagesbase: # images.append(base+'.'+args.extension) # if not os.path.exists(images[-1]): # print "Error: Image",images[-1],"does not exist" # return 1 # avgpbs.append(base+'0.'+args.avgpbext) # if not os.path.exists(avgpbs[-1]): # print "Error: PB image",avgpbs[-1],"does not exist" # return 1 # images = ['imfield0_clusterRX42_patch_s163.image.tt0','imfield0_clusterRX42_patch_s188.image.tt0',\ # 'imfield0_clusterRX42_patch_s92.image.tt0','imfield0_clusterRX42_patch_s204.image.tt0', \ # 'imfield0_clusterRX42_patch_s101.image.tt0','imfield0_clusterRX42_patch_s323.image.tt0',\ # 'imfield0_clusterRX42_patch_s184.image.tt0','imfield0_clusterRX42_patch_s301.image.tt0',\ # 'imfield0_clusterRX42_patch_s351.image.tt0','imfield0_clusterRX42_patch_s35.image.tt0',\ # 'imfield0_clusterRX42_patch_s86.image.tt0','imfield0_clusterRX42_patch_s25.image.tt0',\ # 'imfield0_clusterRX42_patch_s182.image.tt0','imfield0_clusterRX42_patch_s71.image.tt0',\ # 'imfield0_clustersRX42_patch_s0.image.tt0','imfield0_clusterRX42_patch_s180.image.tt0',\ # 'imfield0_clusterRX42_patch_s259.image.tt0','imfield0_clusterRX42_patch_s338.image.tt0',\ # 'imfield0_clusterRX42_patch_s377.image.tt0','imfield0_clusterRX42_patch_s337.image.tt0',\ # 'imfield0_clusterRX42_patch_s223.image.tt0'] images = sorted(glob.glob('templatemask_*.masktmp')) # avgpbs = ['templatemask_RX42_SB180-189.RX42_patch_s163.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s188.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s92.masktmp', \ # 'templatemask_RX42_SB180-189.RX42_patch_s204.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s101.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s323.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s184.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s301.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s351.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s35.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s86.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s25.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s182.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s71.masktmp',\ # 'templatemask_RX42_SB180-189.sRX42_patch_s0.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s180.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s259.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s338.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s377.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s337.masktmp',\ # 'templatemask_RX42_SB180-189.RX42_patch_s223.masktmp'] avgpbs = [] srcints = [] for im in images: tmp = im.split('_') #print tmp tmp = tmp[1] #tmp = tmp.split('cluster') #print tmp #tmp = tmp[1] tmp = tmp.split('.') #print tmp src = tmp[0] srcint = int(src.replace('s','')) srcints.append(srcint) #print tmp #maskn = 'templatemask_' + src + '.masktmp' maskn = im #maskn2 = 'templatemask_' + src + '.masktmp3' #print maskn #if os.path.isdir('../' + maskn2): #maskn = maskn2 avgpbs.append( maskn) #print maskn #avgpbs.app = sorted(glob.glob('templatemask_*.masktmp')) #print avgpbs # Collect weights and invert if requested if args.weights == '': weights = np.ones(len(images)) else: weights = np.array(args.weights.split(',')).astype('float') if args.invertwt: weights = 1./weights if len(weights) != len(images): print "Error: List of weights is not the same length as list of images." return 1 print "Combining images" formstr = '{0:45s} {1:45s}' print formstr.format("-----","--------") print formstr.format("Image", "PB image") print formstr.format("-----","--------") for i in range(len(images)): this_pim = pim.image(images[i]) #info_dict = this_pim.info()['imageinfo']['restoringbeam'] # get beam info #bpar_ma = quanta.quantity(info_dict['major']).get_value('deg') #bpar_mi = quanta.quantity(info_dict['minor']).get_value('deg') #bpar_pa = quanta.quantity(info_dict['positionangle']).get_value('deg') #psf_fwhm.append([bpar_ma, bpar_mi, bpar_pa]) frequency.append(this_pim.info()['coordinates']['spectral2']['restfreq']) #print '{0:45.45s} {1:45.45s} {2:0.2f} {3:0.2f} {4:0.2f} {5:0.2f}'.format(images[i], avgpbs[i], weights[i]/sum(weights), bpar_ma*60, bpar_mi*60,bpar_pa) print '{0:45.45s} {1:45.45s}'.format(images[i], avgpbs[i]) #psf_fwhm = np.array(psf_fwhm) frequency = np.array(frequency) #mean_psf_fwhm = np.mean(psf_fwhm, axis=0) mean_frequency = np.mean(frequency) #print '\nmean Beam: {0:0.3f} maj (arcmin), {1:2.3f} min (arcmin), {2:0.2f} pa (deg)'.format(mean_psf_fwhm[0]*60, mean_psf_fwhm[1]*60, mean_psf_fwhm[2]) print '(Frequency (MHz):', mean_frequency*1e-6 if np.max(mean_frequency-frequency)/mean_frequency > 1e-6: print '\n\nWARNING.\nAre you using images from different bands?' print 'Frequencies (Hz):', frequency time.sleep(2) # give user time to see this ... # Initialize some vectors declims = [] # store the limits of the declination axes ralims = [] # store the limits of the r.a. axes rainc = [] # store the r.a. increments in case they differ decinc = [] # store the dec increments in case they differ pims = [] # stores the pyrap images of the data ppbs = [] # stores the pyrap images of the pb images # Get image frames for input images for im, pb in zip(images, avgpbs): image = pim.image(im) sptcoords = image.coordinates().get_coordinate('spectral') nc = sptcoords.get_axis_size() assert(sptcoords.get_image_axis() == 0) # Get Stokes axis. Ensure we are working with the Stokes parameter requested. #stkcoords = image.coordinates().get_coordinate('stokes') #assert(stkcoords.get_image_axis() == 1) #if stkcoords.get_axis_size() == 1: #assert(stkcoords.get_stokes()[0] == args.stokes) #else: #stks = stkcoords.get_stokes().index(args.stokes) #image = image.subimage(blc=(0, stks), trc=(nc-1, stks), dropdegenerate=False) ns = 1 dircoords = image.coordinates().get_coordinate('direction') nx = dircoords.get_axis_size(axis=1) ny = dircoords.get_axis_size(axis=0) inc = dircoords.get_increment() ref = dircoords.get_referencepixel() val = dircoords.get_referencevalue() ra_axis = (range(nx)-ref[1])*inc[1]+val[1] dec_axis = (range(ny)-ref[0])*inc[0]+val[0] rainc.append(inc[1]) decinc.append(inc[0]) declims.append(min(dec_axis)) declims.append(max(dec_axis)) mean_ra = np.mean(ra_axis) ralims.append((min(ra_axis)-mean_ra)*np.cos(val[0])+mean_ra) ralims.append((max(ra_axis)-mean_ra)*np.cos(val[0])+mean_ra) pims.append(image) ppbs.append(pim.image(pb)) # Generate the mosaic coordinate frame master_dec = np.arange(min(declims),max(declims),min(decinc)) if max(ralims)-min(ralims) > 5.*np.pi/3.: # crossed RA=0 print "Warning: I think the mosaic crosses RA=0, treating the coordinates as such." #ralims[ralims>np.pi] -= 2.*np.pi for i in range(len(ralims)): if ralims[i]>np.pi: ralims[i] = ralims[i]-2.*np.pi master_ra = np.arange(max(ralims),min(ralims),max(rainc)) if args.verbose: print "Found ra,dec pixel increments (arcsec):" print np.array(rainc)*206265.,np.array(decinc)*206265. ma = pims[-1].coordinates() ma['direction'].set_referencepixel([len(master_dec)/2,len(master_ra)/2]) ma['direction'].set_increment([min(decinc),max(rainc)]) ma['direction'].set_referencevalue([master_dec[len(master_dec)/2],master_ra[len(master_ra)/2]]) #if args.NCP: #print 'Setting NCP projection is not yet working ....' #ma['direction'].set_projection('ZEA') # Initialize the arrays for the output image, sensitivity, and weights master_im = np.zeros((len(master_dec),len(master_ra))) master_weight = np.zeros((len(master_dec),len(master_ra))) master_sens = np.zeros((len(master_dec),len(master_ra))) # Reproject the images onto the master grid, weight and normalize for i in range(len(pims)): im = pims[i].regrid([2,3],ma,outshape=(nc,ns,len(master_dec),len(master_ra))) pb = ppbs[i].regrid([2,3],ma,outshape=(nc,ns,len(master_dec),len(master_ra))) imdata = np.squeeze(im.getdata()) pbdata = np.squeeze(pb.getdata()) newim = imdata * srcints[i] # scale by src number newpb = pbdata newwt = (weights[i]*newpb)**2 master_im += newim*newwt master_sens += newpb*newwt master_weight += newwt inds = master_weight != 0. inds_2 = np.where(master_weight == 0.0) #inds_2 = master_weight == 0. master_im[inds] /= master_weight[inds] master_sens[inds] /= master_weight[inds] print 'HH', inds_2 master_im[inds_2] = np.nan # Show image if requested if args.plotimg: plt.imshow(master_im,vmin=0.,vmax=0.5) plt.show() # Write fits files arrax = np.zeros( (1,1, len(master_im[:,0]), len(master_im[0,:])) ) arrax[0,0,:,:] = master_im print 'max', np.max(arrax) # Open new casa image for mosaic new_pim = pim.image('',shape=(1,1, len(master_dec),len(master_ra)), coordsys=ma) new_pim.putdata(arrax) # Write fits new_pim.tofits(args.outfits, overwrite=True) # Same for sensitivity new_pim_sens = pim.image('',shape=(1,1,len(master_dec),len(master_ra)),coordsys=ma) arrax[0,0,:,:] = master_sens new_pim_sens.putdata(arrax) # new_pim_sens.tofits(args.sensfits, overwrite=True) # need to add new beam info (not sure if this is possible with pyrap) hdu = pyfits.open(args.outfits,mode='update') header = hdu[0].header #header.update('BMAJ',mean_psf_fwhm[0]) #header.update('BMIN',mean_psf_fwhm[1]) #header.update('BPA',mean_psf_fwhm[2]) #header.update('BUNIT',pims[-1].info()['unit']) header.update('RESTFRQ',mean_frequency) header.update('RESTFREQ',mean_frequency) newhdu = pyfits.PrimaryHDU(data=hdu[0].data, header=header) newhdu.writeto(args.outfits,clobber=True) return
def main(args): if args.plotimg: import pylab as plt # Generate lists of input images and check that they exist images = [] avgpbs = [] psf_fwhm = [] # resolution frequency = [] # frequency of images (should be equal?) # We determine if list of images is passed as a file or as an actual list if args.images.find(",") == -1: imagesbase = np.loadtxt(args.images, dtype=str) else: imagesbase = args.images.split(",") for base in imagesbase: images.append(base + "." + args.extension) if not os.path.exists(images[-1]): print "Error: Image", images[-1], "does not exist" return 1 avgpbs.append(base + "0." + args.avgpbext) if not os.path.exists(avgpbs[-1]): print "Error: PB image", avgpbs[-1], "does not exist" return 1 # Collect weights and invert if requested if args.weights == "": weights = np.ones(len(images)) else: weights = np.array(args.weights.split(",")).astype("float") if args.invertwt: weights = 1.0 / weights if len(weights) != len(images): print "Error: List of weights is not the same length as list of images." return 1 print "Combining images" formstr = "{0:45s} {1:45s} {2:s} {3:s} {4:s} {5:s}" print formstr.format("-----", "--------", "------------", "-------", "-------", "------") print formstr.format("Image", "PB image", "Norm. weight", "Maj(ac)", "Min(ac)", "PA(deg)") print formstr.format("-----", "--------", "------------", "-------", "-------", "------") for i in range(len(images)): this_pim = pim.image(images[i]) info_dict = this_pim.info()["imageinfo"]["restoringbeam"] # get beam info bpar_ma = quanta.quantity(info_dict["major"]).get_value("deg") bpar_mi = quanta.quantity(info_dict["minor"]).get_value("deg") bpar_pa = quanta.quantity(info_dict["positionangle"]).get_value("deg") psf_fwhm.append([bpar_ma, bpar_mi, bpar_pa]) frequency.append(this_pim.info()["coordinates"]["spectral2"]["restfreq"]) print "{0:45.45s} {1:45.45s} {2:0.2f} {3:0.2f} {4:0.2f} {5:0.2f}".format( images[i], avgpbs[i], weights[i] / sum(weights), bpar_ma * 60, bpar_mi * 60, bpar_pa ) psf_fwhm = np.array(psf_fwhm) frequency = np.array(frequency) mean_psf_fwhm = np.mean(psf_fwhm, axis=0) mean_frequency = np.mean(frequency) print "\nmean Beam: {0:0.3f} maj (arcmin), {1:2.3f} min (arcmin), {2:0.2f} pa (deg)".format( mean_psf_fwhm[0] * 60, mean_psf_fwhm[1] * 60, mean_psf_fwhm[2] ) print "(Frequency (MHz):", mean_frequency * 1e-6 if np.max(mean_frequency - frequency) / mean_frequency > 1e-6: print "\n\nWARNING.\nAre you using images from different bands?" print "Frequencies (Hz):", frequency time.sleep(2) # give user time to see this ... # Initialize some vectors declims = [] # store the limits of the declination axes # ralims = [] # store the limits of the r.a. axes raleft = [] raright = [] rainc = [] # store the r.a. increments in case they differ decinc = [] # store the dec increments in case they differ pims = [] # stores the pyrap images of the data ppbs = [] # stores the pyrap images of the pb images # Get image frames for input images for im, pb in zip(images, avgpbs): image = pim.image(im) sptcoords = image.coordinates().get_coordinate("spectral") nc = sptcoords.get_axis_size() assert sptcoords.get_image_axis() == 0 # Get Stokes axis. Ensure we are working with the Stokes parameter requested. stkcoords = image.coordinates().get_coordinate("stokes") assert stkcoords.get_image_axis() == 1 if stkcoords.get_axis_size() == 1: assert stkcoords.get_stokes()[0] == args.stokes else: stks = stkcoords.get_stokes().index(args.stokes) image = image.subimage(blc=(0, stks), trc=(nc - 1, stks), dropdegenerate=False) ns = 1 dircoords = image.coordinates().get_coordinate("direction") nx = dircoords.get_axis_size(axis=1) ny = dircoords.get_axis_size(axis=0) inc = dircoords.get_increment() ref = dircoords.get_referencepixel() val = dircoords.get_referencevalue() ra_axis = (range(nx) - ref[1]) * inc[1] + val[1] dec_axis = (range(ny) - ref[0]) * inc[0] + val[0] rainc.append(inc[1]) decinc.append(inc[0]) declims.append(min(dec_axis)) declims.append(max(dec_axis)) mean_ra = np.mean(ra_axis) # ralims.append((min(ra_axis)-mean_ra)*np.cos(val[0])+mean_ra) # ralims.append((max(ra_axis)-mean_ra)*np.cos(val[0])+mean_ra) raleft.append((ra_axis[0] - mean_ra) * np.cos(val[0]) + mean_ra) raright.append((ra_axis[-1] - mean_ra) * np.cos(val[0]) + mean_ra) pims.append(image) ppbs.append(pim.image(pb)) # Generate the mosaic coordinate frame if not args.NCP: print ("Using the regular mosaic mode.") master_dec = np.arange(min(declims), max(declims), min(decinc)) if max(raleft) - min(raright) > 5.0 * np.pi / 3.0: # crossed RA=0 print "Warning: I think the mosaic crosses RA=0, treating the coordinates as such." ##ralims[ralims>np.pi] -= 2.*np.pi # for i in range(len(ralims)): # if ralims[i]>np.pi: ralims[i] = ralims[i]-2.*np.pi for i in range(len(raright)): raright[i] = raright[i] - 2.0 * np.pi master_ra = np.arange(max(raleft), min(raright), max(rainc)) lmra = len(master_ra) if args.maxwidth != 0: if lmra > args.maxwidth: xboundary = (lmra - args.maxwidth) / 2 master_ra = master_ra[xboundary:-xboundary] if args.verbose: print "Found ra,dec pixel increments (arcsec):" print np.array(rainc) * 206265.0, np.array(decinc) * 206265.0 ma = pims[-1].coordinates() ma["direction"].set_referencepixel([len(master_dec) / 2, len(master_ra) / 2]) ma["direction"].set_increment([decinc[np.argmin(np.abs(decinc))], rainc[np.argmin(np.abs(rainc))]]) ma["direction"].set_referencevalue([master_dec[len(master_dec) / 2], master_ra[len(master_ra) / 2]]) else: print ("Using the special NCP mosaic mode.") ra_width = 20.0 / 180 * np.pi dec_width = 20.0 / 180 * np.pi rainc = rainc[np.argmin(np.abs(rainc))] decinc = decinc[np.argmin(np.abs(decinc))] ra_imsize = int(ra_width / np.abs(rainc)) dec_imsize = int(dec_width / np.abs(decinc)) master_ra = np.arange(ra_imsize, dtype=float) / ra_imsize * rainc - ra_width / 2 master_dec = np.arange(dec_imsize, dtype=float) / dec_imsize * decinc - dec_width / 2 ma = pims[-1].coordinates() ma["direction"].set_referencevalue([np.pi / 2, 0.0]) ma["direction"].set_increment([decinc, rainc]) ma["direction"].set_referencepixel([dec_imsize / 2.0, ra_imsize / 2.0]) # Initialize the arrays for the output image, sensitivity, and weights master_im = np.zeros((len(master_dec), len(master_ra))) master_weight = np.zeros((len(master_dec), len(master_ra))) master_sens = np.zeros((len(master_dec), len(master_ra))) # Reproject the images onto the master grid, weight and normalize for i in range(len(pims)): im = pims[i].regrid([2, 3], ma, outshape=(nc, ns, len(master_dec), len(master_ra))) pb = ppbs[i].regrid([2, 3], ma, outshape=(nc, ns, len(master_dec), len(master_ra))) imdata = np.squeeze(im.getdata()) pbdata = np.squeeze(pb.getdata()) newim = imdata newpb = pbdata newwt = (weights[i] * newpb) ** 2 master_im += newim * newwt master_sens += newpb * newwt master_weight += newwt inds = master_weight != 0.0 master_im[inds] /= master_weight[inds] master_sens[inds] /= master_weight[inds] # Show image if requested if args.plotimg: plt.imshow(master_im, vmin=0.0, vmax=0.5) plt.show() # Write fits files arrax = np.zeros((1, 1, len(master_im[:, 0]), len(master_im[0, :]))) arrax[0, 0, :, :] = master_im # Open new casa image for mosaic new_pim = pim.image("", shape=(1, 1, len(master_dec), len(master_ra)), coordsys=ma) new_pim.putdata(arrax) # Write fits new_pim.tofits(args.outfits, overwrite=True) # Same for sensitivity new_pim_sens = pim.image("", shape=(1, 1, len(master_dec), len(master_ra)), coordsys=ma) arrax[0, 0, :, :] = master_sens new_pim_sens.putdata(arrax) # new_pim_sens.tofits(args.sensfits, overwrite=True) # need to add new beam info (not sure if this is possible with pyrap) hdu = pyfits.open(args.outfits, mode="update") header = hdu[0].header header.update("BMAJ", mean_psf_fwhm[0]) header.update("BMIN", mean_psf_fwhm[1]) header.update("BPA", mean_psf_fwhm[2]) header.update("BUNIT", pims[-1].info()["unit"]) header.update("RESTFRQ", mean_frequency) header.update("RESTFREQ", mean_frequency) newhdu = pyfits.PrimaryHDU(data=hdu[0].data, header=header) newhdu.writeto(args.outfits, clobber=True) return
def _msss_mask(self, mask_file_path, sourcedb_path, mask_patch_size = 1.0): """ Fill casa image with a mask based on skymodel(sourcedb) Bugs: [email protected] pipeline implementation [email protected] version 0.32 Edited by JDS, 2012-03-16: - Properly convert maj/minor axes to half length - Handle empty fields in sky model by setting them to 0 - Fix off-by-one error at mask boundary FIXED BUG - if a source is outside the mask, the script ignores it - if a source is on the border, the script draws only the inner part - can handle skymodels with different headers KNOWN BUG - not works with single line skymodels, workaround: add a fake source outside the field - mask patched display large amounts of aliasing. A possible sollution would be normalizing to pixel centre. ( int(normalize_x * npix) / npix + (0.5 /npix)) ideally the patch would increment in pixel radiuses Version 0.3 (Wouter Klijn, [email protected]) - Usage of sourcedb instead of txt document as 'source' of sources This allows input from different source sources Version 0.31 (Wouter Klijn, [email protected]) - Adaptable patch size (patch size needs specification) - Patch size and geometry is broken: needs some astronomer magic to fix it, problem with afine transformation prol. Version 0.32 (Wouter Klijn, [email protected]) - Renaming of variable names to python convention """ # increment in maj/minor axes [arcsec] pad = 500. # open mask mask = pim.image(mask_file_path, overwrite = True) mask_data = mask.getdata() xlen, ylen = mask.shape()[2:] freq, stokes, null, null = mask.toworld([0, 0, 0, 0]) # Open the sourcedb: table = pt.table(sourcedb_path + "::SOURCES") pdb = lofar.parmdb.parmdb(sourcedb_path) # Get the data of interest source_list = table.getcol("SOURCENAME") source_type_list = table.getcol("SOURCETYPE") # All date in the format valuetype:sourcename all_values_dict = pdb.getDefValues() # Loop the sources for source, source_type in zip(source_list, source_type_list): if source_type == 1: type_string = "Gaussian" else: type_string = "Point" self.logger.info("processing: {0} ({1})".format(source, type_string)) # Get de right_ascension and declination (already in radians) right_ascension = all_values_dict["Ra:" + source][0, 0] declination = all_values_dict["Dec:" + source][0, 0] if source_type == 1: # Get the raw values from the db maj_raw = all_values_dict["MajorAxis:" + source][0, 0] min_raw = all_values_dict["MinorAxis:" + source][0, 0] pa_raw = all_values_dict["Orientation:" + source][0, 0] # convert to radians (conversion is copy paste JDS) # major radius (+pad) in rad maj = (((maj_raw + pad)) / 3600.) * np.pi / 180. # minor radius (+pad) in rad minor = (((min_raw + pad)) / 3600.) * np.pi / 180. pix_asc = pa_raw * np.pi / 180. # wenss writes always 'GAUSSIAN' even for point sources # -> set to wenss beam+pad if maj == 0 or minor == 0: maj = ((54. + pad) / 3600.) * np.pi / 180. minor = ((54. + pad) / 3600.) * np.pi / 180. # set to wenss beam+pad elif source_type == 0: maj = (((54. + pad) / 2.) / 3600.) * np.pi / 180. minor = (((54. + pad) / 2.) / 3600.) * np.pi / 180. pix_asc = 0. else: self.logger.info( "WARNING: unknown source source_type ({0})," "ignoring: ".format(source_type)) continue # define a small square around the source to look for it null, null, border_y1, border_x1 = mask.topixel( [freq, stokes, declination - maj, right_ascension - maj / np.cos(declination - maj)]) null, null, border_y2, border_x2 = mask.topixel( [freq, stokes, declination + maj, right_ascension + maj / np.cos(declination + maj)]) xmin = np.int(np.floor(np.min([border_x1, border_x2]))) xmax = np.int(np.ceil(np.max([border_x1, border_x2]))) ymin = np.int(np.floor(np.min([border_y1, border_y2]))) ymax = np.int(np.ceil(np.max([border_y1, border_y2]))) if xmin > xlen or ymin > ylen or xmax < 0 or ymax < 0: self.logger.info( "WARNING: source {0} falls outside the mask," " ignoring: ".format(source)) continue if xmax > xlen or ymax > ylen or xmin < 0 or ymin < 0: self.logger.info( "WARNING: source {0} falls across map edge".format(source)) for pixel_x in xrange(xmin, xmax): for pixel_y in xrange(ymin, ymax): # skip pixels outside the mask field if pixel_x >= xlen or pixel_y >= ylen or\ pixel_x < 0 or pixel_y < 0: continue # get pixel right_ascension and declination in rad null, null, pix_dec, pix_ra = mask.toworld( [0, 0, pixel_y, pixel_x]) # Translate and rotate coords. translated_pixel_x = (pix_ra - right_ascension) * np.sin( pix_asc) + (pix_dec - declination) * np.cos(pix_asc) # to align with ellipse translate_pixel_y = -(pix_ra - right_ascension) * np.cos( pix_asc) + (pix_dec - declination) * np.sin(pix_asc) if (((translated_pixel_x ** 2) / (maj ** 2)) + ((translate_pixel_y ** 2) / (minor ** 2))) < \ mask_patch_size: mask_data[0, 0, pixel_y, pixel_x] = 1 null = null mask.putdata(mask_data) table.close()
def __init__(self,BaseImageName,BeamPix=5,ResidualImName="",DoAlpha=1, MaskName="",CleanNegComp=False, NBands=1, SmoothMode=0,MakeCorrected=1,options=None): self.DoAlpha=DoAlpha self.BaseImageName=BaseImageName self.BeamPix=BeamPix self.NBands=NBands self.OutName=options.OutName self.options=options self.SmoothMode=SmoothMode self.MakeCorrected=MakeCorrected self.header_dict={} FileDicoModel="%s.DicoModel"%BaseImageName # ClassModelMachine,DicoModel=GiveModelMachine(FileDicoModel) # self.ModelMachine=ClassModelMachine(Gain=0.1) # self.ModelMachine.FromDico(DicoModel) print("Building model machine", file=log) ModConstructor = ClassModModelMachine() self.ModelMachine=ModConstructor.GiveInitialisedMMFromFile(FileDicoModel) if MaskName!="": self.ModelMachine.CleanMaskedComponants(MaskName) if CleanNegComp: self.ModelMachine.CleanNegComponants(box=10,sig=2) if ResidualImName=="": #if "App" in self.ModeNorm: # FitsFile="%s.app.residual.fits"%BaseImageName #else: # FitsFile="%s.int.residual.fits"%BaseImageName ResidualImName=FitsFile="%s.app.residual.fits"%BaseImageName else: ResidualImName=FitsFile=ResidualImName if self.MakeCorrected: if self.SmoothMode: NormImageName="%s.MeanSmoothNorm.fits"%BaseImageName else: NormImageName="%s.Norm.fits"%BaseImageName print("Reading residual image", file=log) self.FitsFile=FitsFile im=image(FitsFile) c=im.coordinates() self.radec=c.dict()["direction0"]["crval"] CellSizeRad,_=c.dict()["direction0"]["cdelt"] self.CellSizeRad=np.abs(CellSizeRad) self.Cell=(self.CellSizeRad*180/np.pi)*3600 self.CellArcSec=self.Cell self.ResidualData=im.getdata() nchan,npol,_,_=self.ResidualData.shape testImage=np.zeros_like(self.ResidualData) print("Transposing residual...", file=log) if ResidualImName!="": for ch in range(nchan): for pol in range(npol): testImage[ch,pol,:,:]=self.ResidualData[ch,pol,:,:].T[::-1,:]#*1.0003900000000001 if self.MakeCorrected: print("Reading beam...", file=log) SqrtNormImage=np.zeros_like(self.ResidualData) imNorm=image(NormImageName).getdata() print("Transposing beam...", file=log) for ch in range(nchan): for pol in range(npol): SqrtNormImage[ch,pol,:,:]=np.sqrt(imNorm[ch,pol,:,:].T[::-1,:]) else: SqrtNormImage=np.ones_like(self.ResidualData) _,_,nx,_=testImage.shape Nr=10000 indx,indy=np.int64(np.random.rand(Nr)*nx),np.int64(np.random.rand(Nr)*nx) self.StdResidual=np.std(testImage[0,0,indx,indy]) self.Residual=testImage self.SqrtNormImage=SqrtNormImage
#!/usr/bin/env python # Convert input CASA image to fits using pyrap. # # Written by Joris van Zwieten, [email protected], September 2010, Version 1.0 # import pyrap.images as im import os.path import sys if len(sys.argv) < 2 or len(sys.argv) > 3: print "usage: img2fits.py <casa image> [output]" sys.exit(1) inf = sys.argv[1] if len(sys.argv) == 3: outf = sys.argv[2] else: outf = os.path.splitext(sys.argv[1])[0] + '.fits' print "converting %s -> %s" % (inf, outf) image = im.image(inf) image.tofits(outf)
img = bdsm.process_image('%s.restored'%workingimage,advanced_opts='True',detection_image='%s.restored'%workingimage,thresh_isl=3,thresh_pix=5,blank_limit=1E-4,adaptive_rms_box='True',adaptive_thresh=200)#,adaptive_rms_box='True',atrous_do='True') img.export_image(outfile="mask_%s"%workingimage,img_type='island_mask',img_format='casa') img.export_image(outfile="rms_%s"%workingimage,img_type='rms',img_format='casa') os.system('image2fits in=%s.restored out=%s.restored.fits'%(workingimage,workingimage)) f = pyfits.open('%s.restored.fits'%workingimage) noisearray = f[0].data.flatten() maxpixel = np.max(noisearray) noisearray = np.random.permutation(noisearray)[:10000] noisepix = np.array(filter(lambda x: abs(x) > 10E-8,noisearray)) noisepix = np.array(filter(lambda x: abs(x)<infodict['Est Noise']*50.0/1000.0,noisepix)) rms = fit_gaussian_histogram(noisepix,'n') print 'rms %s, maxpixel %s'%(rms,maxpixel) f.close() minthreshold = rms image = pim.image("rms_%s"%workingimage) imshape = image.shape() dataarray = image.getdata(blc=[0,0,0,0], trc=[imshape[0]-1,imshape[1]-1,imshape[2]-1,imshape[3]-1]) dataarray[np.where(np.isnan(dataarray))] = 0 dataarray = dataarray.flatten() threshold1 = str(np.min([np.max(dataarray)*1E3,prevthreshold]))+'mJy' dataarray = np.random.permutation(dataarray)[:10000] dataarray = np.array(filter(lambda x: abs(x) > minthreshold,dataarray)) dataarray = np.random.permutation(dataarray)[:10000] dataarray.sort() threshold2 = dataarray[int(len(dataarray)*0.99)] threshold3 = dataarray[int(len(dataarray)*0.85)] threshold4 = dataarray[int(len(dataarray)*0.60)] thresholds = [str(threshold2*1E3)+'mJy',str(threshold3*1E3)+'mJy',str(threshold4*1E3)+'mJy'] threshold2 = thresholds[0]
def main(args): input_images = glob.glob(args.indir + '/' + args.inpat) assert (len(input_images) <= 8 and len(input_images) > 0) beam_params = {} # to store beam params for each image for later use image_data = {} # store all image data image_increments = {} # pixel size of each image decval = {} # declination of each image (should be the same) max_bmaj = 0. for inim in input_images: print bcolors.OKGREEN + 'Opening %s' % (inim) + bcolors.ENDC im = pim.image(inim) beam_params[inim] = im.imageinfo()['restoringbeam'] if im.imageinfo()['restoringbeam']['major']['value'] > max_bmaj: max_bmaj = im.imageinfo()['restoringbeam']['major']['value'] # The next line presumes single-frequency, single-Stokes! image_data[inim] = im.getdata()[0, 0, :, :] coords = im.coordinates() d = coords.get_coordinate('direction') decval[inim] = d.get_referencevalue()[0] image_increments[inim] = coords.get_increment()[2][0] * 206265. print bcolors.OKGREEN + 'Maximum beam size is %f arcsec' % ( max_bmaj) + bcolors.ENDC big_beam_value = numpy.ceil(max_bmaj) + 1. print bcolors.OKGREEN + 'Target beam size will be %f arcsec' % ( big_beam_value) + bcolors.ENDC # In future, possibly try to reject images with particularly large beam values. # Here, convolve data arrays to big common beam big_beam = Beam.Beam(big_beam_value, big_beam_value, 0.) for inim in input_images: print bcolors.OKGREEN + 'Convolving image data from %s' % ( inim) + bcolors.ENDC bmaj = beam_params[inim]['major']['value'] bmin = beam_params[inim]['minor']['value'] bpa = beam_params[inim]['positionangle']['value'] req = big_beam.Deconvolve(Beam.Beam(bmin, bmaj, bpa)) print 'Starting beam arcsec (maj,min,pa): %.2f, %.2f, %.2f' % ( bmaj, bmin, bpa) print 'Convolving beam arcsec (maj,min,pa): %.2f, %.2f, %.2f' % ( req.amaj, req.amin, req.theta) pix = image_increments[inim] req_maj_pix = req.amaj / pix req_min_pix = req.amin / pix b_pix = Beam.Beam(req_min_pix, req_maj_pix, req.theta) scale_factor_factor = 1. print 'Convolving beam pixels (maj,min,pa): %.2f, %.2f, %.2f' % ( b_pix.amaj, b_pix.amin, b_pix.theta) xr = numpy.ceil( req.amaj / pix) * 5. # convolving beam defined out to +/- 5 sigma x, y = numpy.mgrid[-xr:xr + 1, -xr:xr + 1] r = numpy.array([x, y]).T g_a = b_pix.norm / scale_factor_factor * numpy.exp( -0.5 * (r * (b_pix.icov * r[..., None, :]).sum(-1)).sum(-1).T) image_data[inim] = scipy.signal.fftconvolve(image_data[inim], g_a, mode='same') # Here, obtain noise (proxy) for inverse-variance weighting print bcolors.OKGREEN + 'Computing noise proxy for each convolved image' + bcolors.ENDC image_weights = {} sumweight = 0. for inim in input_images: #image_weights[inim]=1. noise_proxy = numpy.median( numpy.absolute(image_data[inim] - numpy.median(image_data[inim]))) print 'Noise proxy for %s is %f' % (inim, noise_proxy) image_weights[inim] = 1. / noise_proxy**2 sumweight += image_weights[inim] # Now stack stack_data = numpy.zeros(image_data[input_images[0]].shape) for inim in input_images: stack_data += image_weights[inim] * image_data[inim] / sumweight # Write out to disk print bcolors.OKGREEN + 'Writing image to %s' % (args.outim) + bcolors.ENDC im.saveas(args.outim) im = pim.image(args.outim) stack_data_out = numpy.expand_dims(numpy.expand_dims(stack_data, axis=0), axis=0) im.putdata(stack_data_out) im = 0 # Update beam size in image info struct print bcolors.OKGREEN + 'Updating image info (beam size)' + bcolors.ENDC t = pt.table(args.outim, readonly=False, ack=False) iminfo = t.getkeyword('imageinfo') iminfo['restoringbeam']['major']['value'] = big_beam_value iminfo['restoringbeam']['minor']['value'] = big_beam_value iminfo['restoringbeam']['positionangle']['value'] = 0. t.putkeyword('imageinfo', iminfo) t.close()
def main(images, vertices, outfits, maxwidth=0): """ Creates mosaic Parameters ---------- images : str or list of str List of filenames of facet images. May be given as a list or as a string (e.g., '[image1, image2]' vertices : str or list of str List of filenames of facet vertices files. May be given as a list or as a string (e.g., '[vert1, vert2]' outfits : str Filename of output FITS mosaic maxwidth : int, optional Maximum number of pixels to consider for the width of the mosaic [default 0 = unlimited] This can be helpful at high declination. """ if type(images) is str: images = images.strip('[]').split(',') images = [im.strip() for im in images] if type(vertices) is str: vertices = vertices.strip('[]').split(',') vertices = [v.strip() for v in vertices] formstr = '{0:45s} {1:45s} {2:s} {3:s} {4:s} {5:s}' print formstr.format("-----","--------","------------","-------","-------","------") print formstr.format("Image", "FC reg","Norm. weight", "Maj(ac)", "Min(ac)","PA(deg)") print formstr.format("-----","--------","------------","-------","-------","------") psf_fwhm = [] # resolution frequency = [] # frequency of images (should be equal?) for i in range(len(images)): this_pim = pim.image(images[i]) info_dict = this_pim.info()['imageinfo']['restoringbeam'] bpar_ma = quanta.quantity(info_dict['major']).get_value('deg') bpar_mi = quanta.quantity(info_dict['minor']).get_value('deg') bpar_pa = quanta.quantity(info_dict['positionangle']).get_value('deg') psf_fwhm.append([bpar_ma, bpar_mi, bpar_pa]) frequency.append(this_pim.info()['coordinates']['spectral2']['restfreq']) print '{0:45.45s} {1:45.45s} {2:0.2f} {3:0.2f} {4:0.2f} {5:0.2f}'.format(images[i], vertices[i], 0, bpar_ma*60, bpar_mi*60,bpar_pa) psf_fwhm = np.array(psf_fwhm) frequency = np.array(frequency) mean_psf_fwhm = np.mean(psf_fwhm, axis=0) mean_frequency = np.mean(frequency) # Initialize some vectors declims = [] # store the limits of the declination axes raleft = [] raright = [] rainc = [] # store the r.a. increments in case they differ decinc = [] # store the dec increments in case they differ pims = [] # stores the pyrap images of the data # Get image frames for input images for im in images: image = pim.image(im) sptcoords = image.coordinates().get_coordinate('spectral') nc = sptcoords.get_axis_size() # Get Stokes axis. Ensure we are working with the Stokes parameter requested. stkcoords = image.coordinates().get_coordinate('stokes') if stkcoords.get_axis_size() == 1: assert(stkcoords.get_stokes()[0] == 'I') else: stks = stkcoords.get_stokes().index('I') image = image.subimage(blc=(0, stks), trc=(nc-1, stks), dropdegenerate=False) ns = 1 dircoords = image.coordinates().get_coordinate('direction') nx = dircoords.get_axis_size(axis=1) ny = dircoords.get_axis_size(axis=0) inc = dircoords.get_increment() ref = dircoords.get_referencepixel() val = dircoords.get_referencevalue() # wsclean image header is weird if val[1]<0: val[1]+=2*np.pi ra_axis = (range(nx)-ref[1])*inc[1]+val[1] dec_axis = (range(ny)-ref[0])*inc[0]+val[0] rainc.append(inc[1]) decinc.append(inc[0]) declims.append(min(dec_axis)) declims.append(max(dec_axis)) mean_ra = np.mean(ra_axis) raleft.append((ra_axis[0]-mean_ra)*np.cos(val[0])+mean_ra) raright.append((ra_axis[-1]-mean_ra)*np.cos(val[0])+mean_ra) pims.append(image) # Generate the mosaic coordinate frame master_dec = np.arange(min(declims),max(declims),min(decinc)) if max(raleft)-min(raright) > 5.*np.pi/3.: # crossed RA=0 for i in range(len(raright)): raright[i] = raright[i]-2.*np.pi master_ra = np.arange(max(raleft),min(raright),max(rainc)) lmra = len(master_ra) if maxwidth != 0: if lmra > maxwidth: xboundary = (lmra-maxwidth)/2 master_ra = master_ra[xboundary:-xboundary] print "Found ra,dec pixel increments (arcsec):" print np.array(rainc)*206265.,np.array(decinc)*206265. ma = pims[-1].coordinates() ma['direction'].set_referencepixel([len(master_dec)/2,len(master_ra)/2]) ma['direction'].set_increment([decinc[np.argmin(np.abs(decinc))],rainc[np.argmin(np.abs(rainc))]]) ma['direction'].set_referencevalue([master_dec[len(master_dec)/2],master_ra[len(master_ra)/2]]) # Initialize the arrays for the output image, sensitivity, and weights master_im = np.zeros((len(master_dec),len(master_ra))) master_mask = np.zeros((len(master_dec),len(master_ra))) # Reproject the images onto the master grid, weight and normalize for i, im in enumerate(pims): print 'doing image',i im, mask = mask_vertices(im, vertices[i]) im = im.regrid([2,3],ma,outshape=(int(nc),int(ns),len(master_dec),len(master_ra))) mask = mask.regrid([2,3],ma,outshape=(int(nc),int(ns),len(master_dec),len(master_ra))) master_im += np.squeeze(im.getdata()) master_mask += np.squeeze(mask.getdata()) blank=np.ones_like(im)*np.nan master_im=np.where(master_mask,master_im,blank) # Write fits files arrax = np.zeros( (1,1, len(master_im[:,0]), len(master_im[0,:])) ) arrax[0,0,:,:] = master_im # Open new casa image for mosaic new_pim = pim.image('',shape=(1,1, len(master_dec),len(master_ra)), coordsys=ma) new_pim.putdata(arrax) # Write fits new_pim.tofits(outfits, overwrite=True) # need to add new beam info (not sure if this is possible with pyrap) hdu = pyfits.open(outfits,mode='update') header = hdu[0].header header.update('BMAJ',mean_psf_fwhm[0]) header.update('BMIN',mean_psf_fwhm[1]) header.update('BPA',mean_psf_fwhm[2]) header.update('BUNIT',pims[-1].info()['unit']) header.update('RESTFRQ',mean_frequency) header.update('RESTFREQ',mean_frequency) newhdu = pyfits.PrimaryHDU(data=hdu[0].data, header=header) newhdu.writeto(outfits,clobber=True)
def _getPixelCoords1Im(coords, imagename): from interval import interval import math try: from taskinit import ia ia.open(imagename) cs = ia.coordsys() Nx = ia.shape()[0] Ny = ia.shape()[1] ia.done() x0 = cs.referencevalue()['numeric'][0] y0 = cs.referencevalue()['numeric'][1] x_pix_ref = cs.referencepixel()['numeric'][0] y_pix_ref = cs.referencepixel()['numeric'][1] x_pix_inc = cs.increment()['numeric'][0] y_pix_inc = cs.increment()['numeric'][1] # If we fail to load ia, we will use pyrap instead. # This probably means stacker was loaded from outside casapy. except ImportError: from pyrap.images import image im = image(imagename) cs = im.coordinates().get_coordinate('direction') dir_axis_index = im.coordinates().get_axes().index(cs.get_axes()) imshape = im.shape() try: x_axis_index = cs.get_axes().index('Right Ascension') except ValueError: raise ValueError('Could not find direction coordinate: '\ 'RightAscension') try: y_axis_index = cs.get_axes().index('Declination') except ValueError: raise ValueError('Could not find direction coordinate: '\ 'Declination') Nx = im.shape()[dir_axis_index + x_axis_index] Ny = im.shape()[dir_axis_index + y_axis_index] x0 = cs.get_referencevalue()[x_axis_index] y0 = cs.get_referencevalue()[y_axis_index] x_pix_ref = cs.get_referencepixel()[x_axis_index] y_pix_ref = cs.get_referencepixel()[y_axis_index] x_pix_inc = cs.get_increment()[x_axis_index] y_pix_inc = cs.get_increment()[y_axis_index] pixcoords = [] for coord in coords: dx = (coord.x - x0) * math.cos(coord.y) dy = math.asin(math.sin(coord.y) / math.cos(dx)) - y0 x = dx / x_pix_inc + x_pix_ref y = dy / y_pix_inc + y_pix_ref if x in interval[0, Nx - 1] and y in interval[0., Ny - 1]: # pixcoords.append(Coord(x,y, coord.weight)) c = Coord(x, y, coord.weight) try: c.index = coord.index except AttributeError: pass pixcoords.append(c) return pixcoords
def on_press(event): """ Handle key presses """ global fig, all_directions, at, selected_direction if event.key == 'u': # Update plot info = 'Updating display...' c = at.get_child() c.set_text(info) fig.canvas.draw() update_plot() if selected_direction is None: # Print "done" only if there is no selection, as otherwise it will # overwrite the direction state info text info += '\n...done' c = at.get_child() c.set_text(info) fig.canvas.draw() return elif event.key == 'c': # Open selfcal images (if any) selfcal_images = find_selfcal_images(selected_direction) if len(selfcal_images) > 0: info = 'Opening selfcal images for {}...'.format(selected_direction.name) if hasaplpy: # Update the text box as the call below takes a few seconds c = at.get_child() c.set_text(info) fig.canvas.draw() make_selfcal_images.main(selfcal_images, interactive=True, facet_name=selected_direction.name) else: if os.path.exists('/tmp/tempimage'): shutil.rmtree('/tmp/tempimage') im = pim.image(selfcal_images) im.view() else: info = 'No selfcal images exist for {}'.format(selected_direction.name) elif event.key == 'i': # Open full facet image (if any) facet_image = find_facet_image(selected_direction) if len(facet_image) > 0: info = 'Opening facet image for {}...'.format(selected_direction.name) im2 = pim.image(facet_image[0]) im2.view() else: info = 'No image of facet exists for {}'.format(selected_direction.name) elif event.key == 't': # Open fast TEC selfcal plots (if any) selfcal_plots = find_selfcal_tec_plots(selected_direction) if len(selfcal_plots) > 0: info = 'Opening selfcal TEC solution plots for {}...'.format(selected_direction.name) os.system('display -geometry 800x600 {} &'.format(' '.join(selfcal_plots))) else: info = 'Final selfcal solutions do not exist for {}'.format(selected_direction.name) elif event.key == 'g': # Open slow Gain selfcal plots (if any) selfcal_plots = find_selfcal_gain_plots(selected_direction) if len(selfcal_plots) > 0: info = 'Opening selfcal Gain solution plots for {}...'.format(selected_direction.name) os.system('display -geometry 800x600 {} &'.format(' '.join(selfcal_plots))) else: info = 'Final selfcal solutions do not exist for {}'.format(selected_direction.name) elif event.key == 'h': info='Reprinting instructions' show_instructions() else: return # Update info box c = at.get_child() c.set_text(info) fig.canvas.draw()