Example #1
0
    def inigaus_fbdsm(self, isl, thr, beam, img):
        """ initial guess for gaussians like in fbdsm """
        from math import sqrt
        from const import fwsig
        import functions as func

        im = isl.image - isl.islmean
        if img.opts.ini_method == 'curvature':
            im_pos = -1.0 * func.make_curvature_map(isl.image - isl.islmean)
            thr_pos = 0.0
        else:
            im_pos = im
            thr_pos = thr
        mask = isl.mask_active
        av = img.clipped_mean
        inipeak, iniposn, im1 = func.get_maxima(im,
                                                mask,
                                                thr_pos,
                                                isl.shape,
                                                beam,
                                                im_pos=im_pos)
        if len(inipeak) == 0:
            av, stdnew, maxv, maxp, minv, minp = func.arrstatmask(im, mask)
            inipeak = [maxv]
            iniposn = [maxp]
        nmulsrc1 = len(iniposn)

        domore = True
        while domore:
            domore = False
            av, stdnew, maxv, maxp, minv, minp = func.arrstatmask(im1, mask)
            if stdnew > isl.rms and maxv >= thr and maxv >= isl.mean + 2.0 * isl.rms:
                domore = True
                x1, y1 = N.array(iniposn).transpose()
                dumr = N.sqrt((maxp[0] - x1) * (maxp[0] - x1) +
                              (maxp[1] - y1) * (maxp[1] - y1))
                distbm = dumr / sqrt(beam[0] * beam[1] * fwsig * fwsig)
                if N.any((distbm < 0.5) + (dumr < 2.2)):
                    domore = False
                if domore:
                    iniposn.append(N.array(maxp))
                    inipeak.append(maxv)
                    im1 = func.mclean(im1, maxp, beam)

        inipeak = N.array(inipeak)
        iniposn = N.array(iniposn)
        ind = list(N.argsort(inipeak))
        ind.reverse()
        inipeak = inipeak[ind]
        iniposn = iniposn[ind]
        gaul = []
        for i in range(len(inipeak)):
            g = (float(inipeak[i]), int(iniposn[i][0]), int(
                iniposn[i][1])) + beam
            gaul.append(g)

        return gaul, nmulsrc1, len(inipeak)
Example #2
0
    def inigaus_fbdsm(self, isl, thr, beam, img):
        """ initial guess for gaussians like in fbdsm """
        from math import sqrt
        from const import fwsig
        import functions as func

        im = isl.image-isl.islmean
        if img.opts.ini_method == 'curvature':
            im_pos = -1.0 * func.make_curvature_map(isl.image-isl.islmean)
            thr_pos = 0.0
        else:
            im_pos = im
            thr_pos = thr
        mask = isl.mask_active
        av = img.clipped_mean
        inipeak, iniposn, im1 = func.get_maxima(im, mask, thr_pos, isl.shape, beam, im_pos=im_pos)
        if len(inipeak) == 0:
          av, stdnew, maxv, maxp, minv, minp = func.arrstatmask(im, mask)
          inipeak = [maxv]; iniposn = [maxp]
        nmulsrc1 = len(iniposn)

        domore = True
        while domore:
          domore = False
          av, stdnew, maxv, maxp, minv, minp = func.arrstatmask(im1, mask)
          if stdnew > isl.rms and maxv >= thr and maxv >= isl.mean+2.0*isl.rms:
            domore = True
            x1, y1 = N.array(iniposn).transpose()
            dumr = N.sqrt((maxp[0]-x1)*(maxp[0]-x1)+(maxp[1]-y1)*(maxp[1]-y1))
            distbm = dumr/sqrt(beam[0]*beam[1]*fwsig*fwsig)
            if N.any((distbm < 0.5) + (dumr < 2.2)):
              domore = False
            if domore:
              iniposn.append(N.array(maxp)); inipeak.append(maxv)
              im1 = func.mclean(im1, maxp, beam)

        inipeak = N.array(inipeak); iniposn = N.array(iniposn)
        ind = list(N.argsort(inipeak)); ind.reverse()
        inipeak = inipeak[ind]
        iniposn = iniposn[ind]
        gaul = []
        for i in range(len(inipeak)):
          g = (float(inipeak[i]), int(iniposn[i][0]), int(iniposn[i][1])) + beam
          gaul.append(g)

        return gaul, nmulsrc1, len(inipeak)
Example #3
0
    def inigaus_nobeam(self, isl, thr, beam, img):
        """ To get initial guesses when the source sizes are very different
        from the beam, and can also be elongated. Mainly in the context of
        a-trous transform images. Need to arrive at a good guess of the sizes
        and hence need to partition the image around the maxima first. Tried the
        IFT watershed algo but with markers, it segments the island only around
        the minima and not the whole island. Cant find a good weighting scheme
        for tesselation either. Hence will try this :

        Calculate number of maxima. If one, then take moment as initial
        guess. If more than one, then moment of whole island is one of the
        guesses if mom1 is within n pixels of one of the maxima. Else dont take
        whole island moment. Instead, find minima on lines connecting all maxima
        and use geometric mean of all minima of a peak as the size of that peak.
        """
        from math import sqrt
        from const import fwsig
        import scipy.ndimage as nd
        import functions as func

        im = isl.image-isl.islmean
        if img.opts.ini_method == 'curvature':
            im_pos = -1.0 * func.make_curvature_map(isl.image-isl.islmean)
            thr_pos = 0.0
        else:
            im_pos = im
            thr_pos = -1e9
        mask = isl.mask_active
        av = img.clipped_mean
        inipeak, iniposn, im1 = func.get_maxima(im, mask, thr_pos, isl.shape, beam, im_pos=im_pos)
        npeak = len(iniposn)
        gaul = []

        av, stdnew, maxv, maxp, minv, minp = func.arrstatmask(im, mask)
        mom = func.momanalmask_gaus(isl.image-isl.islmean, isl.mask_active, 0, 1.0, True)
        if npeak <= 1:
          g = (float(maxv), int(round(mom[1])), int(round(mom[2])), mom[3]/fwsig, \
                                  mom[4]/fwsig, mom[5])
          gaul.append(g)

        if npeak > 1:                   # markers start from 1=background, watershed starts from 1=background
          watershed, markers = func.watershed(im, mask=isl.mask_active)
          nshed = N.max(markers)-1      # excluding background
          xm, ym = N.transpose([N.where(markers==i) for i in range(1,nshed+2)])[0]
          coords = [c for c in N.transpose([xm,ym])[1:]]
          alldists = [func.dist_2pt(c1, c2) for c1 in coords for c2 in coords if N.any(c1!=c2)]  # has double
          meandist = N.mean(alldists)    # mean dist between all pairs of markers
          compact = []; invmask = []
          for ished in range(nshed):
            shedmask = N.where(watershed==ished+2, False, True) + isl.mask_active # good unmasked pixels = 0
            imm = nd.binary_dilation(~shedmask, N.ones((3,3), int))
            xbad, ybad = N.where((imm==1)*(im>im[xm[ished+1], ym[ished+1]]))
            imm[xbad, ybad] = 0
            invmask.append(imm); x, y = N.where(imm); xcen, ycen = N.mean(x), N.mean(y) # good pixels are now = 1
            dist = func.dist_2pt([xcen, ycen], [xm[ished+1], ym[ished+1]])
            if dist < max(3.0, meandist/4.0):
              compact.append(True)  # if not compact, break source + diffuse
            else:
              compact.append(False)
          if not N.all(compact):
           avsize = []
           ind = N.where(compact)[0]
           for i in ind: avsize.append(N.sum(invmask[i]))
           avsize = sqrt(N.mean(N.array(avsize)))
           for i in range(len(compact)):
             if not compact[i]:                         # make them all compact
               newmask = N.zeros(imm.shape, bool)
               newmask[max(0,xm[i+1]-avsize/2):min(im.shape[0],xm[i+1]+avsize/2), \
                       max(0,ym[i+1]-avsize/2):min(im.shape[1],ym[i+1]+avsize/2)] = True
               invmask[i] = invmask[i]*newmask
          resid = N.zeros(im.shape, dtype=N.float32)                    # approx fit all compact ones
          for i in range(nshed):
            mask1 = ~invmask[i]
            size = sqrt(N.sum(invmask))/fwsig
            xf, yf = coords[i][0], coords[i][1]
            p_ini = [im[xf, yf], xf, yf, size, size, 0.0]
            x, y = N.indices(im.shape)
            p, success = func.fit_gaus2d(im*invmask[i], p_ini, x, y)
            resid = resid + func.gaus_2d(p, x, y)
            gaul.append(p)
          resid = im - resid
          if not N.all(compact):                        # just add one gaussian to fit whole unmasked island
            maxv = N.max(resid)                         # assuming resid has only diffuse emission. can be false
            x, y = N.where(~isl.mask_active); xcen = N.mean(x); ycen = N.mean(y)
            invm = ~isl.mask_active
            #bound = invm - nd.grey_erosion(invm, footprint = N.ones((3,3), int)) # better to use bound for ellipse fitting
            mom = func.momanalmask_gaus(invm, N.zeros(invm.shape, dtype=N.int16), 0, 1.0, True)
            g = (maxv, xcen, ycen, mom[3]/fwsig, mom[4]/fwsig, mom[5]-90.)
            gaul.append(g)
            coords.append([xcen, ycen])

        return gaul
Example #4
0
    def in_same_island(self, pair, img, g_list, isl, subim, subn, subm, delc):
        """ Whether two gaussians belong to the same source or not. """
        import functions as func

        def same_island_min(pair, g_list, subim, delc, tol=0.5):
            """ If the minimum of the reconstructed fluxes along the line joining the peak positions
                is greater than thresh_isl times the rms_clip, they belong to different islands. """

            g1 = g_list[pair[0]]
            g2 = g_list[pair[1]]
            pix1 = N.array(g1.centre_pix)
            pix2 = N.array(g2.centre_pix)

            x1, y1 = N.floor(pix1) - delc
            x2, y2 = N.floor(pix2) - delc
            pix1 = N.array(
                N.unravel_index(N.argmax(subim[x1:x1 + 2, y1:y1 + 2]),
                                (2, 2))) + [x1, y1]
            pix2 = N.array(
                N.unravel_index(N.argmax(subim[x2:x2 + 2, y2:y2 + 2]),
                                (2, 2))) + [x2, y2]
            if pix1[1] >= subn: pix1[1] = pix1[1] - 1
            if pix2[1] >= subm: pix2[1] = pix2[1] - 1

            maxline = int(round(N.max(N.abs(pix1 - pix2) + 1)))
            flux1 = g1.peak_flux
            flux2 = g2.peak_flux
            # get pix values of the line
            pixdif = pix2 - pix1
            same_island_min = False
            same_island_cont = False
            if maxline == 1:
                same_island_min = True
                same_island_cont = True
            else:
                if abs(pixdif[0]) > abs(pixdif[1]):
                    xline = N.round(min(pix1[0], pix2[0]) + N.arange(maxline))
                    yline = N.round((pix1[1]-pix2[1])/(pix1[0]-pix2[0])* \
                           (min(pix1[0],pix2[0])+N.arange(maxline)-pix1[0])+pix1[1])
                else:
                    yline = N.round(min(pix1[1], pix2[1]) + N.arange(maxline))
                    xline = N.round((pix1[0]-pix2[0])/(pix1[1]-pix2[1])* \
                           (min(pix1[1],pix2[1])+N.arange(maxline)-pix1[1])+pix1[0])
                rpixval = N.zeros(maxline, dtype=N.float32)
                xbig = N.where(xline >= N.size(subim, 0))
                xline[xbig] = N.size(subim, 0) - 1
                ybig = N.where(yline >= N.size(subim, 1))
                yline[ybig] = N.size(subim, 1) - 1
                for i in range(maxline):
                    pixval = subim[xline[i], yline[i]]
                    rpixval[i] = pixval
                min_pixval = N.min(rpixval)
                minind_p = N.argmin(rpixval)
                maxind_p = N.argmax(rpixval)

                if minind_p in (0, maxline - 1) and maxind_p in (0,
                                                                 maxline - 1):
                    same_island_cont = True
                if min_pixval >= min(flux1, flux2):
                    same_island_min = True
                elif abs(min_pixval - min(flux1, flux2)
                         ) <= tol * isl.rms * img.opts.thresh_isl:
                    same_island_min = True

            return same_island_min, same_island_cont

        def same_island_dist(pair, g_list, tol=0.5):
            """ If the centres are seperated by a distance less than half the sum of their
                fwhms along the PA of the line joining them, they belong to the same island. """
            from math import sqrt

            g1 = g_list[pair[0]]
            g2 = g_list[pair[1]]
            pix1 = N.array(g1.centre_pix)
            pix2 = N.array(g2.centre_pix)
            gsize1 = g1.size_pix
            gsize2 = g2.size_pix

            fwhm1 = func.gdist_pa(pix1, pix2, gsize1)
            fwhm2 = func.gdist_pa(pix1, pix2, gsize2)
            dx = pix2[0] - pix1[0]
            dy = pix2[1] - pix1[1]
            dist = sqrt(dy * dy + dx * dx)

            if dist <= tol * (fwhm1 + fwhm2):
                same_island = True
            else:
                same_island = False

            return same_island

        if img.opts.group_by_isl:
            same_isl1_min = True
            same_isl1_cont = True
            same_isl2 = True
        else:
            if img.opts.group_method == 'curvature':
                subim = -1.0 * func.make_curvature_map(subim)
            tol = img.opts.group_tol
            same_isl1_min, same_isl1_cont = same_island_min(
                pair, g_list, subim, delc, tol)
            same_isl2 = same_island_dist(pair, g_list, tol / 2.0)

        g1 = g_list[pair[0]]

        same_island = (same_isl1_min and same_isl2) or same_isl1_cont

        return same_island
Example #5
0
    def in_same_island(self, pair, img, g_list, isl, subim, subn, subm, delc):
        """ Whether two gaussians belong to the same source or not. """
        import functions as func

        def same_island_min(pair, g_list, subim, delc, tol=0.5):
            """ If the minimum of the reconstructed fluxes along the line joining the peak positions
                is greater than thresh_isl times the rms_clip, they belong to different islands. """

            g1 = g_list[pair[0]]
            g2 = g_list[pair[1]]
            pix1 = N.array(g1.centre_pix)
            pix2 = N.array(g2.centre_pix)

            x1, y1 = N.floor(pix1)-delc; x2, y2 = N.floor(pix2)-delc
            pix1 = N.array(N.unravel_index(N.argmax(subim[x1:x1+2,y1:y1+2]), (2,2)))+[x1,y1]
            pix2 = N.array(N.unravel_index(N.argmax(subim[x2:x2+2,y2:y2+2]), (2,2)))+[x2,y2]
            if pix1[1] >= subn: pix1[1] = pix1[1]-1
            if pix2[1] >= subm: pix2[1] = pix2[1]-1

            maxline = int(round(N.max(N.abs(pix1-pix2)+1)))
            flux1 = g1.peak_flux
            flux2 = g2.peak_flux
                                                # get pix values of the line
            pixdif = pix2 - pix1
            same_island_min = False
            same_island_cont = False
            if maxline == 1:
              same_island_min = True
              same_island_cont = True
            else:
              if abs(pixdif[0]) > abs(pixdif[1]):
                xline = N.round(min(pix1[0],pix2[0])+N.arange(maxline))
                yline = N.round((pix1[1]-pix2[1])/(pix1[0]-pix2[0])* \
                       (min(pix1[0],pix2[0])+N.arange(maxline)-pix1[0])+pix1[1])
              else:
                yline = N.round(min(pix1[1],pix2[1])+N.arange(maxline))
                xline = N.round((pix1[0]-pix2[0])/(pix1[1]-pix2[1])* \
                       (min(pix1[1],pix2[1])+N.arange(maxline)-pix1[1])+pix1[0])
              rpixval = N.zeros(maxline, dtype=N.float32)
              xbig = N.where(xline >= N.size(subim,0))
              xline[xbig] = N.size(subim,0) - 1
              ybig = N.where(yline >= N.size(subim,1))
              yline[ybig] = N.size(subim,1) - 1
              for i in range(maxline):
                pixval = subim[xline[i],yline[i]]
                rpixval[i] = pixval
              min_pixval = N.min(rpixval)
              minind_p = N.argmin(rpixval)
              maxind_p = N.argmax(rpixval)

              if minind_p in (0, maxline-1) and maxind_p in (0, maxline-1):
                same_island_cont = True
              if min_pixval >= min(flux1, flux2):
                same_island_min = True
              elif abs(min_pixval-min(flux1,flux2)) <= tol*isl.rms*img.opts.thresh_isl:
                same_island_min = True

            return same_island_min, same_island_cont

        def same_island_dist(pair, g_list, tol=0.5):
            """ If the centres are seperated by a distance less than half the sum of their
                fwhms along the PA of the line joining them, they belong to the same island. """
            from math import sqrt

            g1 = g_list[pair[0]]
            g2 = g_list[pair[1]]
            pix1 = N.array(g1.centre_pix)
            pix2 = N.array(g2.centre_pix)
            gsize1 = g1.size_pix
            gsize2 = g2.size_pix

            fwhm1 = func.gdist_pa(pix1, pix2, gsize1)
            fwhm2 = func.gdist_pa(pix1, pix2, gsize2)
            dx = pix2[0]-pix1[0]; dy = pix2[1]-pix1[1]
            dist = sqrt(dy*dy + dx*dx)

            if dist <= tol*(fwhm1+fwhm2):
              same_island = True
            else:
              same_island = False

            return same_island

        if img.opts.group_by_isl:
            same_isl1_min = True
            same_isl1_cont = True
            same_isl2 = True
        else:
            if img.opts.group_method == 'curvature':
                subim = -1.0 * func.make_curvature_map(subim)
            tol = img.opts.group_tol
            same_isl1_min, same_isl1_cont = same_island_min(pair, g_list, subim, delc, tol)
            same_isl2 = same_island_dist(pair, g_list, tol/2.0)

        g1 = g_list[pair[0]]

        same_island = (same_isl1_min and same_isl2) or same_isl1_cont

        return same_island