Beispiel #1
0
def shapelet_getroot(xfn, yfn, xco, xcen, ycen):
    """ This finds the root for finding the shapelet centre. If there are multiple roots, takes
    that which closest to the 'centre', taken as the intensity barycentre. This is the python
    version of getroot.f of anaamika."""
    import functions as func

    root = None
    npoint = len(xfn)
    error = 0
    if npoint == 0:
        error = 1
    elif yfn.max() * yfn.min() >= 0.:
        error = 1

    minint = 0
    minintold = 0
    for i in range(1, npoint):
        if yfn[i - 1] * yfn[i] < 0.:
            if minintold == 0:  # so take nearest to centre
                if abs(yfn[i - 1]) < abs(yfn[i]):
                    minint = i - 1
                else:
                    minint = i
            else:
                dnew = func.dist_2pt([xco, xfn[i]], [xcen, ycen])
                dold = func.dist_2pt([xco, xfn[minintold]], [xcen, ycen])
                if dnew <= dold:
                    minint = i
                else:
                    minint = minintold
            minintold = minint

    if minint < 1 or minint > npoint: error = 1
    if error != 1:
        low = minint - min(2, minint)  #-1)
        up = minint + min(2,
                          npoint - 1 - minint)  # python array indexing rubbish
        nfit = up - low + 1
        xfit = xfn[low:low + nfit]
        yfit = yfn[low:low + nfit]
        sig = N.ones(nfit)
        smask = N.zeros(nfit, dtype=bool)
        xx = [i for i in range(low, low + nfit)]

        [c, m], errors = func.fit_mask_1d(xfit,
                                          yfit,
                                          sig,
                                          smask,
                                          func.poly,
                                          do_err=False,
                                          order=1)
        root = -c / m
        if root < xfn[low] or root > xfn[up]: error = 1

    return root, error
Beispiel #2
0
def shapelet_getroot(xfn, yfn, xco, xcen, ycen):
    """ This finds the root for finding the shapelet centre. If there are multiple roots, takes
    that which closest to the 'centre', taken as the intensity barycentre. This is the python
    version of getroot.f of anaamika."""
    import functions as func

    root = None
    npoint = len(xfn)
    error = 0
    if npoint == 0:
        error = 1
    elif yfn.max() * yfn.min() >= 0.0:
        error = 1

    minint = 0
    minintold = 0
    for i in range(1, npoint):
        if yfn[i - 1] * yfn[i] < 0.0:
            if minintold == 0:  # so take nearest to centre
                if abs(yfn[i - 1]) < abs(yfn[i]):
                    minint = i - 1
                else:
                    minint = i
            else:
                dnew = func.dist_2pt([xco, xfn[i]], [xcen, ycen])
                dold = func.dist_2pt([xco, xfn[minintold]], [xcen, ycen])
                if dnew <= dold:
                    minint = i
                else:
                    minint = minintold
            minintold = minint

    if minint < 1 or minint > npoint:
        error = 1
    if error != 1:
        low = minint - min(2, minint)  # -1)
        up = minint + min(2, npoint - 1 - minint)  # python array indexing rubbish
        nfit = up - low + 1
        xfit = xfn[low : low + nfit]
        yfit = yfn[low : low + nfit]
        sig = N.ones(nfit)
        smask = N.zeros(nfit, dtype=bool)
        xx = [i for i in range(low, low + nfit)]

        [c, m], errors = func.fit_mask_1d(xfit, yfit, sig, smask, func.poly, do_err=False, order=1)
        root = -c / m
        if root < xfn[low] or root > xfn[up]:
            error = 1

    return root, error
Beispiel #3
0
    def edit_vorogenlist(self, vorogenP, frac):
        """ Edit primary voronoi generator list. Each tile has a tile centre and can
        have more than one generator to be averaged. tile_list is a list of arrays, indexed
        by the tile number and each array is an array of numbers in the ngen list which are
        the generators in that tile. xtile, ytile and snrtile are arrays of length number_of_tiles
        and have x,y,snr of each tile. Group together generators
        if closer than a fraction of dist to third closest."""

        xgen, ygen, snrgen = vorogenP
        flag = N.zeros(len(xgen))
        coord=N.array([xgen,ygen]).transpose()
        tile_list = []
        tile_coord = []; tile_snr = []
        for i in range(len(xgen)):
            dist = N.array(map(lambda t: func.dist_2pt(coord[i], t), coord))
            indi = N.argsort(dist)
            sortdist = dist[indi]
            if sortdist[1] < frac * sortdist[2]:    # first is the element itself
              if flag[indi[1]] + flag[i] == 0:   #  not already deleted from other pair
                tile_list.append([i, indi[1]])
                tile_coord.append((coord[i]*snrgen[i]+coord[indi[1]]*snrgen[indi[1]])/(snrgen[i]+snrgen[indi[1]]))
                tile_snr.append(snrgen[i]+snrgen[indi[1]])
                flag[i] = 1
                flag[indi[1]] = 1
            else:
              if len(dist) > 3:
                if sortdist[1]+sortdist[2] < 2.0*frac*sortdist[3]: # for 3 close-by sources
                  in1=indi[1]
                  in2=indi[2]
                  if flag[in1]+flag[in2]+flag[i] == 0: # not already deleted from others
                    tile_list.append([i, in1, in2])
                    tile_coord.append((coord[i]*snrgen[i]+coord[in1]*snrgen[in1]+coord[in2]*snrgen[in2]) \
                               /(snrgen[i]+snrgen[in1]+snrgen[in2]))
                    tile_snr.append(snrgen[i]+snrgen[in1]+snrgen[in2])
                    flag[i] = 1
                    flag[in1] = 1
                    flag[in2] = 1
              else:
                tile_list.append([i])
                tile_coord.append(coord[i])
                tile_snr.append(snrgen[i])

        # Assign any leftover generators
        for i in range(len(xgen)):
            if flag[i] == 0:
                tile_list.append([i])
                tile_coord.append(coord[i])
                tile_snr.append(snrgen[i])

        return tile_list, tile_coord, tile_snr
Beispiel #4
0
    def edit_vorogenlist(self, vorogenP, frac):
        """ Edit primary voronoi generator list. Each tile has a tile centre and can
        have more than one generator to be averaged. tile_list is a list of arrays, indexed
        by the tile number and each array is an array of numbers in the ngen list which are
        the generators in that tile. xtile, ytile and snrtile are arrays of length number_of_tiles
        and have x,y,snr of each tile. Group together generators
        if closer than a fraction of dist to third closest."""

        xgen, ygen, snrgen = vorogenP
        flag = N.zeros(len(xgen))
        coord=N.array([xgen,ygen]).transpose()
        tile_list = []
        tile_coord = []; tile_snr = []
        for i in range(len(xgen)):
            dist = N.array(map(lambda t: func.dist_2pt(coord[i], t), coord))
            indi = N.argsort(dist)
            sortdist = dist[indi]
            if sortdist[1] < frac * sortdist[2]:    # first is the element itself
              if flag[indi[1]] + flag[i] == 0:   #  not already deleted from other pair
                tile_list.append([i, indi[1]])
                tile_coord.append((coord[i]*snrgen[i]+coord[indi[1]]*snrgen[indi[1]])/(snrgen[i]+snrgen[indi[1]]))
                tile_snr.append(snrgen[i]+snrgen[indi[1]])
                flag[i] = 1
                flag[indi[1]] = 1
            else:
              if len(dist) > 3:
                if sortdist[1]+sortdist[2] < 2.0*frac*sortdist[3]: # for 3 close-by sources
                  in1=indi[1]
                  in2=indi[2]
                  if flag[in1]+flag[in2]+flag[i] == 0: # not already deleted from others
                    tile_list.append([i, in1, in2])
                    tile_coord.append((coord[i]*snrgen[i]+coord[in1]*snrgen[in1]+coord[in2]*snrgen[in2]) \
                               /(snrgen[i]+snrgen[in1]+snrgen[in2]))
                    tile_snr.append(snrgen[i]+snrgen[in1]+snrgen[in2])
                    flag[i] = 1
                    flag[in1] = 1
                    flag[in2] = 1
              else:
                tile_list.append([i])
                tile_coord.append(coord[i])
                tile_snr.append(snrgen[i])

        # Assign any leftover generators
        for i in range(len(xgen)):
            if flag[i] == 0:
                tile_list.append([i])
                tile_coord.append(coord[i])
                tile_snr.append(snrgen[i])

        return tile_list, tile_coord, tile_snr
Beispiel #5
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