Ejemplo n.º 1
0
        shape = None
    source = SkyModel.Source(name, pos, flux, shape=shape)
    # Adding source peak flux (error) as extra flux attributes for sources,
    # and to avoid null values for point sources I_peak = src["Total_flux"]
    if shape:
        source.setAttribute("I_peak", float(src["peak_flux"]))
        source.setAttribute("I_peak_err", float(src["err_peak_flux"]))
    else:
        source.setAttribute("I_peak", float(src["int_flux"]))
        source.setAttribute("I_peak_err", float(src["err_int_flux"]))

    return source


data = Table.read('{0}_comp.{1}'.format(
    outfile.split('.')[0],
    outfile.split('.')[-1]),
                  format=outfile.split('.')[-1])

for i, src in enumerate(data):

    model.sources.append(tigger_src(src, i))

wcs = WCS(image)
centre = wcs.getCentreWCSCoords()
model.ra0, model.dec0 = map(numpy.deg2rad, centre)

model.save(tname_lsm)
# Rename using CORPAT
utils.xrun("tigger-convert", [tname_lsm, "--rename -f"])
Ejemplo n.º 2
0
class load(object):


    def __init__(self, imagename, psfname=None, sourcefinder_name='pybdsm',
	             saveformat="gaul", makeplots=True, do_psf_corr=True, 
				 do_local_var=True, psf_corr_region=5, local_var_region=10,
				 rel_excl_src=None, pos_smooth=2, neg_smooth=2, loglevel=0, 
				 thresh_pix=5, thresh_isl=3, neg_thresh_isl=3,
				 neg_thresh_pix=5, reset_rel=None, prefix=None, 
				 do_nearsources=False, savefits=False, 
				 increase_beam_cluster=False, savemask_pos=False,
				 savemask_neg=False, no_smooth=True, **kw):

        """ Takes in image and extracts sources and makes 
            reliability estimations..
           
		
        imagename: Fits image
        psfname: PSF fits image, optional. 

        sourcefinder_name: str, optional. Default 'pybdsm'.
            Uses source finder specified.

        makeplots: bool, optional. Default is True.
            Make reliability plots.

        do_psf_corr : bool, optional. Default True.
            If True, PSF correlation will be added
            as an extra parameter for density estimations.
            NB: the PSF fits image must be provided.

        do_local_var : bool, optional. Default is True.
            If True, adds local variance as an extra parameter,
            for density estimations. 
        
        do_nearsources: boolean. Default is False.
            If true it adds number of nearest neighnours as an extra
            parameter. It looks for sources around 5 beam sizes.

        psf_corr_region : int, optional. Default value is 5. 
            Data size to correlate around a source, in beam sizes.
 
        local_var_region: int, optional. Default 10.
            Data size to compute the local variance in beam sizes.

        rel_excl_src : floats, optional. Default is None. 
            Excludes sources in a specified region
            e.g ra, dec, radius in degrees. For
            2 regions: ra1, dec1, radius1: ra2, dec2, radius2, etc.

        pos_smooth : float, optional. Default 2.
            Masking threshold for the positive image.
            For default value 2, data peaks < 2 * image noise
            are masked.

        neg_smooth : float, optional. Default 2.
            Similar to pos_smooth but applied to the negative image.

        thresh_isl :  float, optional. Default is 3.
            Threshold for forming islands in the positive image

        thresh_pix : float, optional. Default is 5.
            Threshold for model fitting, in positive image.

        neg_thresh_isl : float, optional. Default is 3. 
            Simialr to thresh_isl but for negative image.

        neg_thresh_pix : float, optional. Default is 5. 
            Similar to thresh_pix but for negative image.

        savefits: boolean. Default is False.
            If True a negative image is saved.

        reset_rel: boolean. Default is False. If true then
            sources with correlation < 0.002 and rel >0.60
            have their reliabilities set to 0.

        increase_beam_cluster: boolean, optional. If True, sources
            groupings will be increase by 20% the beam size. If False,
            the actual beam size will be used. Default is False.

        savemask_pos: boolean, optional. If true the mask applied on 
            the positive side of an image after smoothing is saved.
            
        savemask_neg: Similar to savemask_pos but for the negative
            side of an image.
        
        loglevel : int, optional. Default is 0.
            Provides Pythonlogging options, 0, 1, 2 and 3 are for info, debug,
            error and critial respectively.
   
         kw : kward for source extractions. Should be a mapping e.g
            kw['thresh_isl'] = 2.0 or kw['do_polarization'] = True 
        """


        #
        self.smoothing = not no_smooth
       
        self.prefix = prefix

        # log level  
        self.loglevel = loglevel
        self.log = utils.logger(self.loglevel, prefix=self.prefix)

        
        # image, psf image
        self.imagename = imagename
        self.psfname = psfname 

        with pyfits.open(imagename) as hdu:
            self.header = hdu[0].header
            self.wcs = WCS(self.header, mode="pyfits")
            self.pixelsize = abs(self.header["cdelt1"])
      
        self.bmaj = numpy.deg2rad(self.header["BMAJ"])

        # boolean optionals    
        self.makeplots = makeplots
        self.do_local_var = do_local_var
        self.nearsources = do_nearsources
        self.do_psf_corr = do_psf_corr
        self.savemaskpos = savemask_pos
        self.savemaskneg = savemask_neg
        self.savefits = savefits
        self.derel = reset_rel
        self.log.info("Catalogues will be saved as %s, where srl is source "
					  " and gaul is Gaussians. "%saveformat)
        self.catalogue_format = "." + saveformat
        if not self.psfname:
            self.log.info(" No psf provided, do_psf_corr is set to False.")
            self.do_psf_corr = False

 
        # computing negative noise
        self.noise, self.mean = utils.negative_noise(self.imagename, self.prefix)
        
        self.log.info(" The negative noise is %e Jy/beam"%self.noise)
        if self.noise == 0: 
            self.log.debug(" The negative noise is 0, check image")

        # source finder initialization
        self.sourcefinder_name  = sourcefinder_name
        self.log.info(" Using %s source finder to extract the sources."%
                      self.sourcefinder_name)

        self.negimage = self.prefix + "_negative.fits"
        utils.invert_image(self.imagename, self.negimage)  
       
        # smoothing factors
        self.pos_smooth = pos_smooth
        self.neg_smooth = neg_smooth
        
        # region to evaluate
        self.corrstep = psf_corr_region
        self.localstep = local_var_region
        self.radiusrm = rel_excl_src
        self.do_beam = increase_beam_cluster
         
        beam_pix = int(round(numpy.rad2deg(self.bmaj)/self.pixelsize))
        self.locstep = self.localstep * beam_pix
        self.cfstep = self.corrstep * beam_pix
        self.bmin, self.bpa =  self.header["BMIN"], self.header["BPA"]

        self.opts_pos = {}
        if self.do_beam:
            bmaj = self.header["BMAJ"]
            self.opts_pos["beam"] = (1.2*bmaj, 1.2*self.bmin, self.bpa)

        # Pybdsm or source finder fitting thresholds
        self.thresh_isl = thresh_isl
        self.thresh_pix = thresh_pix
        self.opts_pos = dict(thresh_pix=self.thresh_pix,
                             thresh_isl=self.thresh_isl)
        
        self.opts_pos.update(kw)
        self.opts_neg = {}
        self.opts_neg.update(kw)
        self.neg_thresh_isl = neg_thresh_isl
        self.neg_thresh_pix = neg_thresh_pix
        self.opts_neg["thresh_isl"] = self.neg_thresh_isl
        self.opts_neg["thresh_pix"] = self.neg_thresh_pix
 
     
    def source_finder(self, image=None, thresh=None, prefix=None,
                      noise=None, output=None, savemask=None, **kw):
        
        #kw.update(kwards)
        tpos = None
        naxis = self.header["NAXIS1"] 
        boundary = numpy.array([self.locstep, self.cfstep])
        #trim_box = (boundary.max(), naxis - boundary.max(),
        #          boundary.max(), naxis - boundary.max())
        trim_box = None
        # data smoothing
        if self.smoothing:

            ext = utils.fits_ext(image)
            tpos = tempfile.NamedTemporaryFile(suffix="."+ext, dir=".")
            tpos.flush()

            mask, noise = utils.thresh_mask(image, tpos.name,
                          thresh=thresh, noise=self.noise, 
                          sigma=True, smooth=True, prefix=prefix, 
                          savemask=savemask)

            # using the masked image for forming islands
            kw["detection_image"] = tpos.name
            kw["blank_limit"] = self.noise/1.0e5

        # source extraction
        utils.sources_extraction(
             image=image, output=output, 
             sourcefinder_name=self.sourcefinder_name,
             trim_box=trim_box,
             prefix=self.prefix, **kw)

        if tpos:
            tpos.close()


    def remove_sources_within(self, model):
        
        sources = model.sources
        rel_remove = self.radiusrm[0].split(":")
        for i in range(len(rel_remove)):
                ra, dec, tolerance = rel_remove[i].split(",")
                ra_r =  numpy.deg2rad(float(ra))
                dec_r =  numpy.deg2rad(float(dec))
                tolerance_r = numpy.deg2rad(float(tolerance))
                within = model.getSourcesNear(ra_r, dec_r, tolerance_r)   
                for src in sorted(sources):
                    if src in within:
                         model.sources.remove(src)
        return model
    

    def params(self, modelfits):
     
        # reads in source finder output             
        with pyfits.open(modelfits) as hdu:
            data = hdu[1].data

        tfile = tempfile.NamedTemporaryFile(suffix=".txt")
        tfile.flush() 

        # writes a catalogue in a temporaty txt file
        with open(tfile.name, "w") as std:
            std.write("#format:name ra_rad dec_rad i emaj_r emin_r pa_r\n")

        model = Tigger.load(tfile.name) # open a tmp. file
    
        peak, total, area, loc, corr = [], [], [], [], []
        for i in range(len(data)):
            flux = data["Total_flux"][i] 
            dc_emaj, dc_emin = data["DC_Maj"][i], data["DC_Min"][i]
            ra, dec = data["RA"][i], data["DEC"][i]
            pa = data["DC_PA"][i]
            name = "SRC%d"%i
            peak_flux = data["Peak_flux"][i]

            posrd =  ModelClasses.Position(numpy.deg2rad(ra), numpy.deg2rad(dec))
            flux_I = ModelClasses.Polarization(flux, 0, 0, 0)
            if dc_emaj == 0 and dc_emin == 0: 
                shape = None
            else:
                shape = ModelClasses.Gaussian(numpy.deg2rad(dc_emaj), numpy.deg2rad(dc_emin),
                                         numpy.deg2rad(pa))
            
            srs = SkyModel.Source(name, posrd, flux_I, shape=shape)
            
            # using convolved maj and min for reliability estimate
            emaj, emin = data["Maj"][i], data["Min"][i]

            # area: find ex and ey if are 0 assign beam size
            if emaj or emin == 0:
                srcarea = math.pi * (numpy.rad2deg(self.bmaj)) * pow(3600.0, 2) *\
                       (numpy.rad2deg(self.bmin)) 
            if  emaj and emin > 0: 
                srcarea = emaj * emin * math.pi * pow(3600.0, 2) # arcsecond
            
            # only accepts sources with flux > 0 and not nan RA and DEC
            # and local variance
            pos = [self.wcs.wcs2pix(*(ra, dec))][0] #positions from deg to pixel

            with pyfits.open(self.negimage) as hdu:
                negdata = utils.image_data( hdu[0].data )

            if flux > 0 and peak_flux > 0 and not math.isnan(float(ra))\
                and not math.isnan(float(dec)):

                  local = utils.compute_local_variance(negdata,
                            pos, self.locstep)

                  srs.setAttribute("local_variance", local)

                  
                  if not math.isnan(float(local)) or local  > 0:
                      if self.psfname:
                          pdata, psf = utils.compute_psf_correlation(self.imagename,
                                         self.psfname, pos, self.cfstep)

                          if len(pdata) == len(psf):
                              c_region = numpy.corrcoef((pdata, psf))
                              cf =  (numpy.diag((numpy.rot90(c_region))**2)
                                           .sum())**0.5/2**0.5

                              srs.setAttribute("correlation_factor", cf)
                              corr.append(cf)
                              model.sources.append(srs) 
                              peak.append(peak_flux)
                              total.append(flux)
                              area.append(srcarea)
                              loc.append(local)
                      else:
                          model.sources.append(srs) 
                          peak.append(peak_flux)
                          total.append(flux)
                          area.append(srcarea)
                          loc.append(local)
    
        labels = dict(size=(0, "Log$_{10}$(Source area)"), 
                      peak=(1, "Log$_{10}$( Peak flux [Jy] )"), 
                      tot=(2, "Log$_{10}$( Total flux [Jy] )"))

        if self.do_psf_corr:
            labels.update( {"coeff":(len(labels),
                            "Log$_{10}$ (CF)")})
        if self.do_local_var:
            labels.update( {"local": (len(labels),
                            "Log$_{10}$(Local Variance)")})
        if self.nearsources:
            labels.update( {"near": (len(labels),
                            "Log$_{10}$(Near Sources)")})

        nsrc = len(model.sources)
        out = numpy.zeros([nsrc, len(labels)])         
         
        # returning parameters
        for i, src in enumerate(model.sources):

            ra, dec = src.pos.ra, src.pos.dec
            near = model.getSourcesNear(ra, dec, 5 * self.bmaj)
            nonear = len(near) 
            if self.nearsources:
                src.setAttribute("neibours", nonear)

            if self.do_psf_corr and self.do_local_var and self.nearsources:
                 out[i,...] =  area[i], peak[i], total[i], corr[i], loc[i], nonear

            elif self.do_psf_corr and self.do_local_var and not self.nearsources:
                 out[i,...] =   area[i], peak[i], total[i] , corr[i], loc[i]
        
            elif self.do_psf_corr and self.nearsources and not self.do_local_var:
                out[i,...] =   area[i], peak[i], total[i] , corr[i], nonear
            
            elif not self.do_psf_corr and self.do_local_var and self.nearsources:
                out[i,...] =   area[i], peak[i], total[i] , loc[i], nonear
            
            elif self.do_psf_corr and not self.do_local_var and not self.nearsources:
                out[i,...] =   area[i], peak[i], total[i] , corr[i]
            
            elif not self.do_psf_corr and self.do_local_var and not self.nearsources:
                out[i,...] =   area[i], peak[i], total[i] , loc[i]
            
            elif not self.do_psf_corr and not self.do_local_var and self.nearsources:
                out[i,...] =   area[i], peak[i], total[i] , nonear

            else:
                out[i,...] =   area[i], peak[i], total[i]


        # removes the rows with 0s
        removezeros = (out == 0).sum(1)
        output = out[removezeros <= 0, :]
                  
        return model, numpy.log10(output), labels 


    def get_reliability(self):


        # finding sources 
        self.log.info(" Extracting the sources on both sides ")

        pfile = self.prefix + self.catalogue_format + ".fits"
        nfile = self.prefix + "_negative" + self.catalogue_format + ".fits"
        # i need to catch mmap.mmap error here

        # running a source finder
        self.source_finder(image=self.negimage,
                           output=nfile, thresh=self.neg_smooth,
                           savemask=self.savemaskneg,
                           prefix=self.prefix, **self.opts_neg)

        self.source_finder(image=self.imagename,
                           output=pfile, thresh=self.pos_smooth, 
                           savemask=self.savemaskpos,
                           prefix=self.prefix, **self.opts_pos)

        self.log.info(" Source Finder completed successfully ")


         
        pmodel, positive, labels = self.params(pfile)
        nmodel, negative, labels = self.params(nfile)
     
        # setting up a kernel, Gaussian kernel
        bandwidth = []

        for plane in negative.T:
            bandwidth.append(plane.std())

        nplanes = len(labels)
        cov = numpy.zeros([nplanes, nplanes])
        nnsrc = len(negative)
        npsrc = len(positive)
        
        self.log.info(" There are %d positive and %d negtive detections "%(npsrc, nnsrc))
 
        if nnsrc == 0 or npsrc ==0:
            self.log.error("The resulting array has length of 0 thus cannot compute"
                    " the reliability. Aborting.")

        self.log.info(" Computing the reliabilities ")
        for i in range(nplanes):
            for j in range(nplanes):
                if i == j:
                    cov[i, j] = bandwidth[i]*((4.0/((nplanes+2)*
                                  nnsrc))**(1.0/(nplanes+4.0)))
        self.log.info("The resulting covariance matrix is %r"%cov)

        pcov = utils.gaussian_kde_set_covariance(positive.T, cov)
        ncov = utils.gaussian_kde_set_covariance(negative.T, cov)
    
        # get number densities
        nps = pcov(positive.T) * npsrc
        nns = ncov(positive.T) * nnsrc

        # define reliability of positive catalog
        rel = (nps-nns)/nps
        for src, rf in zip(pmodel.sources, rel):
            src.setAttribute("rel", rf)
        self.log.info(" Saved the reliabilities values.")

        # remove sources with poor correlation and high reliability,
        # the values are currently arbitrary
        if self.do_psf_corr and self.derel:
            for s in pmodel.sources:
                cf, r = s.correlation_factor, s.rel
                if cf < 0.006 and r > 0.60:
                    s.rel = 0.0    

        if self.makeplots:
            savefig = self.prefix + "_planes.png"
            utils.plot(positive, negative, rel=rel, labels=labels,
                        savefig=savefig, prefix=self.prefix)

        # removes sources in a given radius from the phase center
        if self.radiusrm:
            self.log.info(" Remove sources ra, dec, radius of  %r" 
                          " from the phase center" %self.radiusrm)
            pmodel = self.remove_sources_within(pmodel)


        if not self.savefits:
            self.log.info(" Deleting the negative image.")
            os.system("rm -r %s"%self.negimage)

        # Set field Center
        pmodel.ra0, pmodel.dec0 = map(numpy.deg2rad, self.wcs.getCentreWCSCoords())

        return  pmodel, nmodel, self.locstep
Ejemplo n.º 3
0
class load(object):
    def __init__(self,
                 imagename,
                 psfname=None,
                 sourcefinder_name='pybdsm',
                 saveformat="gaul",
                 makeplots=True,
                 do_psf_corr=True,
                 do_local_var=True,
                 psf_corr_region=5,
                 local_var_region=10,
                 rel_excl_src=None,
                 pos_smooth=2,
                 neg_smooth=2,
                 loglevel=0,
                 thresh_pix=5,
                 thresh_isl=3,
                 neg_thresh_isl=3,
                 neg_thresh_pix=5,
                 reset_rel=None,
                 prefix=None,
                 do_nearsources=False,
                 savefits=False,
                 increase_beam_cluster=False,
                 savemask_pos=False,
                 savemask_neg=False,
                 no_smooth=True,
                 **kw):
        """ Takes in image and extracts sources and makes 
            reliability estimations..
           
		
        imagename: Fits image
        psfname: PSF fits image, optional. 

        sourcefinder_name: str, optional. Default 'pybdsm'.
            Uses source finder specified.

        makeplots: bool, optional. Default is True.
            Make reliability plots.

        do_psf_corr : bool, optional. Default True.
            If True, PSF correlation will be added
            as an extra parameter for density estimations.
            NB: the PSF fits image must be provided.

        do_local_var : bool, optional. Default is True.
            If True, adds local variance as an extra parameter,
            for density estimations. 
        
        do_nearsources: boolean. Default is False.
            If true it adds number of nearest neighnours as an extra
            parameter. It looks for sources around 5 beam sizes.

        psf_corr_region : int, optional. Default value is 5. 
            Data size to correlate around a source, in beam sizes.
 
        local_var_region: int, optional. Default 10.
            Data size to compute the local variance in beam sizes.

        rel_excl_src : floats, optional. Default is None. 
            Excludes sources in a specified region
            e.g ra, dec, radius in degrees. For
            2 regions: ra1, dec1, radius1: ra2, dec2, radius2, etc.

        pos_smooth : float, optional. Default 2.
            Masking threshold for the positive image.
            For default value 2, data peaks < 2 * image noise
            are masked.

        neg_smooth : float, optional. Default 2.
            Similar to pos_smooth but applied to the negative image.

        thresh_isl :  float, optional. Default is 3.
            Threshold for forming islands in the positive image

        thresh_pix : float, optional. Default is 5.
            Threshold for model fitting, in positive image.

        neg_thresh_isl : float, optional. Default is 3. 
            Simialr to thresh_isl but for negative image.

        neg_thresh_pix : float, optional. Default is 5. 
            Similar to thresh_pix but for negative image.

        savefits: boolean. Default is False.
            If True a negative image is saved.

        reset_rel: boolean. Default is False. If true then
            sources with correlation < 0.002 and rel >0.60
            have their reliabilities set to 0.

        increase_beam_cluster: boolean, optional. If True, sources
            groupings will be increase by 20% the beam size. If False,
            the actual beam size will be used. Default is False.

        savemask_pos: boolean, optional. If true the mask applied on 
            the positive side of an image after smoothing is saved.
            
        savemask_neg: Similar to savemask_pos but for the negative
            side of an image.
        
        loglevel : int, optional. Default is 0.
            Provides Pythonlogging options, 0, 1, 2 and 3 are for info, debug,
            error and critial respectively.
   
         kw : kward for source extractions. Should be a mapping e.g
            kw['thresh_isl'] = 2.0 or kw['do_polarization'] = True 
        """

        #
        self.smoothing = not no_smooth

        self.prefix = prefix

        # log level
        self.loglevel = loglevel
        self.log = utils.logger(self.loglevel, prefix=self.prefix)

        # image, psf image
        self.imagename = imagename
        self.psfname = psfname

        with pyfits.open(imagename) as hdu:
            self.header = hdu[0].header
            self.wcs = WCS(self.header, mode="pyfits")
            self.pixelsize = abs(self.header["cdelt1"])

        self.bmaj = numpy.deg2rad(self.header["BMAJ"])

        # boolean optionals
        self.makeplots = makeplots
        self.do_local_var = do_local_var
        self.nearsources = do_nearsources
        self.do_psf_corr = do_psf_corr
        self.savemaskpos = savemask_pos
        self.savemaskneg = savemask_neg
        self.savefits = savefits
        self.derel = reset_rel
        self.log.info("Catalogues will be saved as %s, where srl is source "
                      " and gaul is Gaussians. " % saveformat)
        self.catalogue_format = "." + saveformat
        if not self.psfname:
            self.log.info(" No psf provided, do_psf_corr is set to False.")
            self.do_psf_corr = False

        # computing negative noise
        self.noise, self.mean = utils.negative_noise(self.imagename,
                                                     self.prefix)

        self.log.info(" The negative noise is %e Jy/beam" % self.noise)
        if self.noise == 0:
            self.log.debug(" The negative noise is 0, check image")

        # source finder initialization
        self.sourcefinder_name = sourcefinder_name
        self.log.info(" Using %s source finder to extract the sources." %
                      self.sourcefinder_name)

        self.negimage = self.prefix + "_negative.fits"
        utils.invert_image(self.imagename, self.negimage)

        # smoothing factors
        self.pos_smooth = pos_smooth
        self.neg_smooth = neg_smooth

        # region to evaluate
        self.corrstep = psf_corr_region
        self.localstep = local_var_region
        self.radiusrm = rel_excl_src
        self.do_beam = increase_beam_cluster

        beam_pix = int(round(numpy.rad2deg(self.bmaj) / self.pixelsize))
        self.locstep = self.localstep * beam_pix
        self.cfstep = self.corrstep * beam_pix
        self.bmin, self.bpa = self.header["BMIN"], self.header["BPA"]

        self.opts_pos = {}
        if self.do_beam:
            bmaj = self.header["BMAJ"]
            self.opts_pos["beam"] = (1.2 * bmaj, 1.2 * self.bmin, self.bpa)

        # Pybdsm or source finder fitting thresholds
        self.thresh_isl = thresh_isl
        self.thresh_pix = thresh_pix
        self.opts_pos = dict(thresh_pix=self.thresh_pix,
                             thresh_isl=self.thresh_isl)

        self.opts_pos.update(kw)
        self.opts_neg = {}
        self.opts_neg.update(kw)
        self.neg_thresh_isl = neg_thresh_isl
        self.neg_thresh_pix = neg_thresh_pix
        self.opts_neg["thresh_isl"] = self.neg_thresh_isl
        self.opts_neg["thresh_pix"] = self.neg_thresh_pix

    def source_finder(self,
                      image=None,
                      thresh=None,
                      prefix=None,
                      noise=None,
                      output=None,
                      savemask=None,
                      **kw):

        #kw.update(kwards)
        tpos = None
        naxis = self.header["NAXIS1"]
        boundary = numpy.array([self.locstep, self.cfstep])
        #trim_box = (boundary.max(), naxis - boundary.max(),
        #          boundary.max(), naxis - boundary.max())
        trim_box = None
        # data smoothing
        if self.smoothing:

            ext = utils.fits_ext(image)
            tpos = tempfile.NamedTemporaryFile(suffix="." + ext, dir=".")
            tpos.flush()

            mask, noise = utils.thresh_mask(image,
                                            tpos.name,
                                            thresh=thresh,
                                            noise=self.noise,
                                            sigma=True,
                                            smooth=True,
                                            prefix=prefix,
                                            savemask=savemask)

            # using the masked image for forming islands
            kw["detection_image"] = tpos.name
            kw["blank_limit"] = self.noise / 1.0e5

        # source extraction
        utils.sources_extraction(image=image,
                                 output=output,
                                 sourcefinder_name=self.sourcefinder_name,
                                 trim_box=trim_box,
                                 prefix=self.prefix,
                                 **kw)

        if tpos:
            tpos.close()

    def remove_sources_within(self, model):

        sources = model.sources
        rel_remove = self.radiusrm[0].split(":")
        for i in range(len(rel_remove)):
            ra, dec, tolerance = rel_remove[i].split(",")
            ra_r = numpy.deg2rad(float(ra))
            dec_r = numpy.deg2rad(float(dec))
            tolerance_r = numpy.deg2rad(float(tolerance))
            within = model.getSourcesNear(ra_r, dec_r, tolerance_r)
            for src in sorted(sources):
                if src in within:
                    model.sources.remove(src)
        return model

    def params(self, modelfits):

        # reads in source finder output
        with pyfits.open(modelfits) as hdu:
            data = hdu[1].data

        tfile = tempfile.NamedTemporaryFile(suffix=".txt")
        tfile.flush()

        # writes a catalogue in a temporaty txt file
        with open(tfile.name, "w") as std:
            std.write("#format:name ra_rad dec_rad i emaj_r emin_r pa_r\n")

        model = Tigger.load(tfile.name)  # open a tmp. file

        peak, total, area, loc, corr = [], [], [], [], []
        for i in range(len(data)):
            flux = data["Total_flux"][i]
            dc_emaj, dc_emin = data["DC_Maj"][i], data["DC_Min"][i]
            ra, dec = data["RA"][i], data["DEC"][i]
            pa = data["DC_PA"][i]
            name = "SRC%d" % i
            peak_flux = data["Peak_flux"][i]

            posrd = ModelClasses.Position(numpy.deg2rad(ra),
                                          numpy.deg2rad(dec))
            flux_I = ModelClasses.Polarization(flux, 0, 0, 0)
            if dc_emaj == 0 and dc_emin == 0:
                shape = None
            else:
                shape = ModelClasses.Gaussian(numpy.deg2rad(dc_emaj),
                                              numpy.deg2rad(dc_emin),
                                              numpy.deg2rad(pa))

            srs = SkyModel.Source(name, posrd, flux_I, shape=shape)

            # using convolved maj and min for reliability estimate
            emaj, emin = data["Maj"][i], data["Min"][i]

            # area: find ex and ey if are 0 assign beam size
            if emaj or emin == 0:
                srcarea = math.pi * (numpy.rad2deg(self.bmaj)) * pow(3600.0, 2) *\
                       (numpy.rad2deg(self.bmin))
            if emaj and emin > 0:
                srcarea = emaj * emin * math.pi * pow(3600.0, 2)  # arcsecond

            # only accepts sources with flux > 0 and not nan RA and DEC
            # and local variance
            pos = [self.wcs.wcs2pix(*(ra, dec))
                   ][0]  #positions from deg to pixel

            with pyfits.open(self.negimage) as hdu:
                negdata = utils.image_data(hdu[0].data)

            if flux > 0 and peak_flux > 0 and not math.isnan(float(ra))\
                and not math.isnan(float(dec)):

                local = utils.compute_local_variance(negdata, pos,
                                                     self.locstep)

                srs.setAttribute("local_variance", local)

                if not math.isnan(float(local)) or local > 0:
                    if self.psfname:
                        pdata, psf = utils.compute_psf_correlation(
                            self.imagename, self.psfname, pos, self.cfstep)

                        if len(pdata) == len(psf):
                            c_region = numpy.corrcoef((pdata, psf))
                            cf = (numpy.diag((numpy.rot90(c_region))**
                                             2).sum())**0.5 / 2**0.5

                            srs.setAttribute("correlation_factor", cf)
                            corr.append(cf)
                            model.sources.append(srs)
                            peak.append(peak_flux)
                            total.append(flux)
                            area.append(srcarea)
                            loc.append(local)
                    else:
                        model.sources.append(srs)
                        peak.append(peak_flux)
                        total.append(flux)
                        area.append(srcarea)
                        loc.append(local)

        labels = dict(size=(0, "Log$_{10}$(Source area)"),
                      peak=(1, "Log$_{10}$( Peak flux [Jy] )"),
                      tot=(2, "Log$_{10}$( Total flux [Jy] )"))

        if self.do_psf_corr:
            labels.update({"coeff": (len(labels), "Log$_{10}$ (CF)")})
        if self.do_local_var:
            labels.update(
                {"local": (len(labels), "Log$_{10}$(Local Variance)")})
        if self.nearsources:
            labels.update({"near": (len(labels), "Log$_{10}$(Near Sources)")})

        nsrc = len(model.sources)
        out = numpy.zeros([nsrc, len(labels)])

        # returning parameters
        for i, src in enumerate(model.sources):

            ra, dec = src.pos.ra, src.pos.dec
            near = model.getSourcesNear(ra, dec, 5 * self.bmaj)
            nonear = len(near)
            if self.nearsources:
                src.setAttribute("neibours", nonear)

            if self.do_psf_corr and self.do_local_var and self.nearsources:
                out[i,
                    ...] = area[i], peak[i], total[i], corr[i], loc[i], nonear

            elif self.do_psf_corr and self.do_local_var and not self.nearsources:
                out[i, ...] = area[i], peak[i], total[i], corr[i], loc[i]

            elif self.do_psf_corr and self.nearsources and not self.do_local_var:
                out[i, ...] = area[i], peak[i], total[i], corr[i], nonear

            elif not self.do_psf_corr and self.do_local_var and self.nearsources:
                out[i, ...] = area[i], peak[i], total[i], loc[i], nonear

            elif self.do_psf_corr and not self.do_local_var and not self.nearsources:
                out[i, ...] = area[i], peak[i], total[i], corr[i]

            elif not self.do_psf_corr and self.do_local_var and not self.nearsources:
                out[i, ...] = area[i], peak[i], total[i], loc[i]

            elif not self.do_psf_corr and not self.do_local_var and self.nearsources:
                out[i, ...] = area[i], peak[i], total[i], nonear

            else:
                out[i, ...] = area[i], peak[i], total[i]

        # removes the rows with 0s
        removezeros = (out == 0).sum(1)
        output = out[removezeros <= 0, :]

        return model, numpy.log10(output), labels

    def get_reliability(self):

        # finding sources
        self.log.info(" Extracting the sources on both sides ")

        pfile = self.prefix + self.catalogue_format + ".fits"
        nfile = self.prefix + "_negative" + self.catalogue_format + ".fits"
        # i need to catch mmap.mmap error here

        # running a source finder
        self.source_finder(image=self.negimage,
                           output=nfile,
                           thresh=self.neg_smooth,
                           savemask=self.savemaskneg,
                           prefix=self.prefix,
                           **self.opts_neg)

        self.source_finder(image=self.imagename,
                           output=pfile,
                           thresh=self.pos_smooth,
                           savemask=self.savemaskpos,
                           prefix=self.prefix,
                           **self.opts_pos)

        self.log.info(" Source Finder completed successfully ")

        pmodel, positive, labels = self.params(pfile)
        nmodel, negative, labels = self.params(nfile)

        # setting up a kernel, Gaussian kernel
        bandwidth = []

        for plane in negative.T:
            bandwidth.append(plane.std())

        nplanes = len(labels)
        cov = numpy.zeros([nplanes, nplanes])
        nnsrc = len(negative)
        npsrc = len(positive)

        self.log.info(" There are %d positive and %d negtive detections " %
                      (npsrc, nnsrc))

        if nnsrc == 0 or npsrc == 0:
            self.log.error(
                "The resulting array has length of 0 thus cannot compute"
                " the reliability. Aborting.")

        self.log.info(" Computing the reliabilities ")
        for i in range(nplanes):
            for j in range(nplanes):
                if i == j:
                    cov[i, j] = bandwidth[i] * ((4.0 / (
                        (nplanes + 2) * nnsrc))**(1.0 / (nplanes + 4.0)))
        self.log.info("The resulting covariance matrix is %r" % cov)

        pcov = utils.gaussian_kde_set_covariance(positive.T, cov)
        ncov = utils.gaussian_kde_set_covariance(negative.T, cov)

        # get number densities
        nps = pcov(positive.T) * npsrc
        nns = ncov(positive.T) * nnsrc

        # define reliability of positive catalog
        rel = (nps - nns) / nps
        for src, rf in zip(pmodel.sources, rel):
            src.setAttribute("rel", rf)
        self.log.info(" Saved the reliabilities values.")

        # remove sources with poor correlation and high reliability,
        # the values are currently arbitrary
        if self.do_psf_corr and self.derel:
            for s in pmodel.sources:
                cf, r = s.correlation_factor, s.rel
                if cf < 0.006 and r > 0.60:
                    s.rel = 0.0

        if self.makeplots:
            savefig = self.prefix + "_planes.png"
            utils.plot(positive,
                       negative,
                       rel=rel,
                       labels=labels,
                       savefig=savefig,
                       prefix=self.prefix)

        # removes sources in a given radius from the phase center
        if self.radiusrm:
            self.log.info(" Remove sources ra, dec, radius of  %r"
                          " from the phase center" % self.radiusrm)
            pmodel = self.remove_sources_within(pmodel)

        if not self.savefits:
            self.log.info(" Deleting the negative image.")
            os.system("rm -r %s" % self.negimage)

        # Set field Center
        pmodel.ra0, pmodel.dec0 = map(numpy.deg2rad,
                                      self.wcs.getCentreWCSCoords())

        return pmodel, nmodel, self.locstep
Ejemplo n.º 4
0
  class FITSWCSpix (_Projector):
    """FITS WCS projection, as determined by a FITS header. lm is in pixels (0-based)."""
    def __init__ (self,header):
      """Constructor. Create from filename (treated as FITS file), or a FITS header object""";
      # attach to FITS file or header
      if isinstance(header,str):
        header = pyfits.open(header)[0].header;
      else:
        self.wcs = WCS(header,mode="pyfits");
      try:
        ra0,dec0 = self.wcs.getCentreWCSCoords();
        self.xpix0,self.ypix0 = self.wcs.wcs2pix(*self.wcs.getCentreWCSCoords());
        self.xscale = self.wcs.getXPixelSizeDeg()*DEG;
        self.yscale = self.wcs.getYPixelSizeDeg()*DEG;
        has_projection = True;
      except:
        print "No WCS in FITS file, falling back to pixel coordinates.";
        ra0 = dec0 = self.xpix0 = self.ypix0 = 0;
        self.xscale = self.yscale = DEG/3600;
        has_projection = False;
      _Projector.__init__(self,ra0*DEG,dec0*DEG,has_projection=has_projection);

    def lm (self,ra,dec):
      if not self.has_projection():
        return numpy.sin(ra)/self.xscale,numpy.sin(dec)/self.yscale;
      if numpy.isscalar(ra) and numpy.isscalar(dec):
        if ra - self.ra0 > math.pi:
          ra -= 2*math.pi;
        if ra - self.ra0 < -math.pi:
          ra += 2*math.pi;
        return self.wcs.wcs2pix(ra/DEG,dec/DEG);
      else:
        if numpy.isscalar(ra):
          ra = numpy.array(ra);
        ra[ra - self.ra0 > math.pi] -= 2*math.pi;
        ra[ra - self.ra0 < -math.pi] += 2*math.pi;
        ## when fed in arrays of ra/dec, wcs.wcs2pix will return a nested list of
        ## [[l1,m1],[l2,m2],,...]. Convert this to an array and extract columns.
        lm = numpy.array(self.wcs.wcs2pix(ra/DEG,dec/DEG));
        return lm[...,0],lm[...,1];

    def radec (self,l,m):
      if not self.has_projection():
        return numpy.arcsin(l*self.xscale),numpy.arcsin(m*self.yscale);
      if numpy.isscalar(l) and numpy.isscalar(m):
        ra,dec = self.wcs.pix2wcs(l,m);
      else:
## this is slow as molasses because of the way astLib.WCS implements the loop. ~120 seconds for 4M pixels
        ## when fed in arrays of ra/dec, wcs.wcs2pix will return a nested list of
        ## [[l1,m1],[l2,m2],,...]. Convert this to an array and extract columns.
#        radec = numpy.array(self.wcs.pix2wcs(l,m));
#        ra = radec[...,0];
#        dec = radec[...,1];
### try a faster implementation -- oh well, only a bit faster, ~95 seconds for the same
### can also replace list comprehension with map(), but that doesn't improve things.
### Note also that the final array constructor takes ~10 secs!
        radec = numpy.array([ PyWCSTools.wcs.pix2wcs(self.wcs.WCSStructure,x,y) for x,y in zip(l+1,m+1) ]);
        ra = radec[...,0];
        dec = radec[...,1];
      return ra*DEG,dec*DEG;


    def offset (self,dra,ddec):
      return self.xpix0 - dra/self.xscale,self.ypix0 + ddec/self.xscale;

    def __eq__ (self,other):
      """By default, two projections are the same if their classes match, and their ra0/dec0 match."""
      return type(self) is type(other) and (self.ra0,self.dec0,self.xpix0,self.ypix0,self.xscale,self.yscale)  == (other.ra0,other.dec0,other.xpix0,other.ypix0,other.xscale,other.yscale);
Ejemplo n.º 5
0
  class FITSWCSpix (_Projector):
    """FITS WCS projection, as determined by a FITS header. lm is in pixels (0-based)."""
    def __init__ (self,header):
      """Constructor. Create from filename (treated as FITS file), or a FITS header object""";
      # attach to FITS file or header
      if isinstance(header,str):
        header = pyfits.open(header)[0].header;
      else:
        self.wcs = WCS(header,mode="pyfits");
      try:
        ra0,dec0 = self.wcs.getCentreWCSCoords();
        self.xpix0,self.ypix0 = self.wcs.wcs2pix(*self.wcs.getCentreWCSCoords());
        self.xscale = self.wcs.getXPixelSizeDeg()*DEG;
        self.yscale = self.wcs.getYPixelSizeDeg()*DEG;
        has_projection = True;
      except:
        print "No WCS in FITS file, falling back to pixel coordinates.";
        ra0 = dec0 = self.xpix0 = self.ypix0 = 0;
        self.xscale = self.yscale = DEG/3600;
        has_projection = False;
      _Projector.__init__(self,ra0*DEG,dec0*DEG,has_projection=has_projection);

    def lm (self,ra,dec):
      if not self.has_projection():
        return numpy.sin(ra)/self.xscale,numpy.sin(dec)/self.yscale;
      if numpy.isscalar(ra) and numpy.isscalar(dec):
        if ra - self.ra0 > math.pi:
          ra -= 2*math.pi;
        if ra - self.ra0 < -math.pi:
          ra += 2*math.pi;
        return self.wcs.wcs2pix(ra/DEG,dec/DEG);
      else:
        if numpy.isscalar(ra):
          ra = numpy.array(ra);
        ra[ra - self.ra0 > math.pi] -= 2*math.pi;
        ra[ra - self.ra0 < -math.pi] += 2*math.pi;
        ## when fed in arrays of ra/dec, wcs.wcs2pix will return a nested list of
        ## [[l1,m1],[l2,m2],,...]. Convert this to an array and extract columns.
        lm = numpy.array(self.wcs.wcs2pix(ra/DEG,dec/DEG));
        return lm[...,0],lm[...,1];

    def radec (self,l,m):
      if not self.has_projection():
        return numpy.arcsin(l*self.xscale),numpy.arcsin(m*self.yscale);
      if numpy.isscalar(l) and numpy.isscalar(m):
        ra,dec = self.wcs.pix2wcs(l,m);
      else:
## this is slow as molasses because of the way astLib.WCS implements the loop. ~120 seconds for 4M pixels
        ## when fed in arrays of ra/dec, wcs.wcs2pix will return a nested list of
        ## [[l1,m1],[l2,m2],,...]. Convert this to an array and extract columns.
#        radec = numpy.array(self.wcs.pix2wcs(l,m));
#        ra = radec[...,0];
#        dec = radec[...,1];
### try a faster implementation -- oh well, only a bit faster, ~95 seconds for the same
### can also replace list comprehension with map(), but that doesn't improve things.
### Note also that the final array constructor takes ~10 secs!
        radec = numpy.array([ PyWCSTools.wcs.pix2wcs(self.wcs.WCSStructure,x,y) for x,y in zip(l+1,m+1) ]);
        ra = radec[...,0];
        dec = radec[...,1];
      return ra*DEG,dec*DEG;


    def offset (self,dra,ddec):
      return self.xpix0 - dra/self.xscale,self.ypix0 + ddec/self.xscale;

    def __eq__ (self,other):
      """By default, two projections are the same if their classes match, and their ra0/dec0 match."""
      return type(self) is type(other) and (self.ra0,self.dec0,self.xpix0,self.ypix0,self.xscale,self.yscale)  == (other.ra0,other.dec0,other.xpix0,other.ypix0,other.xscale,other.yscale);