Esempio n. 1
0
def angdist(ra, dec, ps, ds=None):
    """
    Calculate angular distance of point sources to point in the sky

    Parameters
    ----------
    ra:		float, R.A. of ROI (in degree)
    dec:	float, DEC. of ROI (in degree)
    ps:		list, list of point sources as generated with pointlike

    kwargs
    ------
    ds:		list, list of point sources as generated with pointlike, if None, don't use it and 
    		don't return it

    Returns
    -------
    list that contains the angular distance in degrees to point sources
    """

    skydir = SkyDir(ra, dec, SkyDir.EQUATORIAL)
    diffPs = empty(len(ps))

    for i, p in enumerate(ps):
        diffPs[i] = skydir.difference(
            p.skydir) * 180. / pi  # angular separation in degree
    if not ds == None:
        diffDs = empty(len(ds))
        for i, d in enumerate(ds):
            diffDs[i] = skydir.difference(
                d.skydir) * 180. / pi  # angular separation in degree
        return diffPs, diffDs
    else:
        return diffPs
Esempio n. 2
0
    def update_positions(self, tsmin=10, qualmax=8):
        """ use the localization information associated with each source to update position
            require ts>tsmin, qual<qualmax
            
        """
        print '---Updating positions---'
        sources = [
            s for s in self.sources
            if s.skydir is not None and np.any(s.spectral_model.free)
        ]
        #print 'sources:', [s.name for s in sources]
        print '%-15s%6s%8s %8s' % ('name', 'TS', 'qual', 'delta_ts')
        for source in sources:
            has_ts = hasattr(source, 'ts')
            print '%-15s %6.0f' % (source.name, source.ts if has_ts else -1.0),
            if not hasattr(source, 'ellipse') or source.ellipse is None:
                print ' no localization info'
                continue
            if not has_ts:
                print '    no TS'
                continue

            if source.ts < tsmin:
                print '    TS<%.0f' % (tsmin)
                continue
            newdir = SkyDir(*source.ellipse[:2])
            qual, delta_ts = source.ellipse[-2:]
            print '%6.1f%6.1f' % (qual, delta_ts),
            if qual > qualmax:
                print ' qual>%.1f' % qualmax
                continue
            print ' %s -> %s, moved %.2f' % (
                source.skydir, newdir,
                np.degrees(newdir.difference(source.skydir)))
            source.skydir = newdir
Esempio n. 3
0
def moment_analysis(tsmap, wcs, fudge=1.44):
    """ perform localization by a moment analysis of a TS map
        tsmap : array of float: TS values on a grid, must be square
        wcs : Projector object
            implements pix2sph function of two ints to return ra,dec
        fudge : float
            Additional factor to multiply the ellipse radii
            (Determined empirically)
    returns: 
        ra, dec, ax, bx, ang
    """
    vals = np.exp(-0.5* tsmap**2).flatten(); 
    peak_fraction = vals.max()/sum(vals)
    

    n = len(vals)
    nx = ny =int(np.sqrt(n))
    #centers of pixels have index +0.5
    ix = np.array([ i % nx for i in range(n)]) +0.5
    iy = np.array([ i //nx for i in range(n)]) +0.5
    norm = 1./sum(vals)
    t = [sum(u*vals)*norm for u in  ix,iy, ix**2, ix*iy, iy**2]
    center = (t[0],t[1])
    C = np.matrix(center)
    variance = (np.matrix(((t[2], t[3]),(t[3], t[4]))) - C.T * C)
    ra,dec = wcs.pix2sph(center[0]+0.5,center[1]+0.5)
    peak = SkyDir(ra,dec)
    # get coords of center, measure degrees/pixel
    nc = (nx+1)/2
    rac, decc = wcs.pix2sph(nc, nc)
    scale = wcs.pix2sph(nc, nc+1)[1] - decc
    size = nx*scale
    # adjust variance
    variance = scale**2 * variance
    offset = np.degrees(peak.difference(SkyDir(rac,decc)))

    # add effects of binsize
    var  = variance #NO+ np.matrix(np.diag([1,1]))*(scale/3)**2
    #Eigenvalue analysis to get ellipse coords
    u,v =np.linalg.eigh(var)
    ang =np.degrees(np.arctan2(v[1,1], -v[1,0]))
    if min(u)< 0.5* max(u): 
        print 'Too elliptical : %s, setting circular' % u
        u[0]=u[1] = max(u)
    tt = np.sqrt(u) * fudge
    if u[1]>u[0]:
        ax,bx = tt[1], tt[0]
        ang = 90-ang
    else:
        ax,bx = tt
    return ra, dec, ax,bx, ang
Esempio n. 4
0
def rotate_equator(skydir,target,anti=False):
    """ Rotate skydir such that target would be rotated 
        to the celestial equator. 
        
        A few simple tests:

            >>> a = SkyDir(0,0)
            >>> b = SkyDir(30,30)
            >>> rotate_equator(a, b)
            SkyDir(330.000,-30.000)
            >>> anti_rotate_equator(a, b)
            SkyDir(30.000,30.000)

        There was previously a bug when the 'target' was the equator.
        I think it is fixed now:

            >>> rotate_equator(b, a)
            SkyDir(30.000,30.000)
            >>> anti_rotate_equator(b, a)
            SkyDir(30.000,30.000)


        Another test: 

            >>> sd = SkyDir(-.2,-.2)
            >>> target = SkyDir(5,5)
            >>> l=rotate_equator(sd, target)
            >>> print '%.2f, %.2f' % (l.ra(), l.dec())
            354.80, -5.20
            >>> l=anti_rotate_equator(sd, target)
            >>> print '%.2f, %.2f' % (l.ra(), l.dec())
            4.80, 4.80
    """
    if np.allclose([target.ra(), target.dec()], [0,0]):
        return skydir


    equator=SkyDir(0,0)

    axis=target.cross(equator)

    theta=equator.difference(target)
    if anti: theta*=-1

    newdir=SkyDir(skydir.ra(),skydir.dec())
    newdir().rotate(axis(),theta)
    return newdir
Esempio n. 5
0
class PeakFinder(object):
    """Log of analysis stream
    <pre>%(logstream)s</pre>
    """
    def __init__(self, filename):
        t = os.path.split(os.path.splitext(filename)[0])[-1].split('_')
        self.sourcename = ' '.join(t[:-1]).replace('p', '+')

        self.df = df = SkyImage(filename)
        wcs = df.projector()
        self.tsmap = np.array(df.image())
        nx, ny = df.naxis1(), df.naxis2()
        assert nx == ny, 'Array not square?'

        vals = np.exp(-0.5 * self.tsmap**2)  # convert to likelihood from TS
        norm = 1. / sum(vals)
        self.peak_fract = norm * vals.max()
        center, variance = self.moments_analysis(vals)
        ra, dec = wcs.pix2sph(center[1], center[0])
        self.peak = SkyDir(ra, dec)
        self.scale = wcs.pix2sph(center[0], center[1] + 1)[1] - dec
        self.size = nx * self.scale
        self.variance = self.scale**2 * variance
        rac, decc = wcs.pix2sph(nx / 2, ny / 2)
        self.offset = np.degrees(self.peak.difference(SkyDir(rac, decc)))

    def moments_analysis(self, vals):
        n = len(vals)
        nx = int(np.sqrt(n))
        ix = np.array([i % nx for i in range(n)])
        iy = np.array([i // nx for i in range(n)])
        norm = 1. / sum(vals)
        t = [sum(u * vals) * norm for u in ix, iy, ix**2, ix * iy, iy**2]
        center = (t[0], t[1])
        C = np.matrix(center)
        variance = (np.matrix(((t[2], t[3]), (t[3], t[4]))) - C.T * C)
        return center, variance

    def ellipse(self):
        # add effects of binsize
        var = self.variance + np.matrix(np.diag([1, 1])) * (self.scale / 3)**2
        t, v = np.linalg.eigh(var)
        ang = np.degrees(np.arcsin(np.array(
            v)[0][0]))  #guess. Needs adjustment depending on which is largest
        return t[0], t[1], ang
Esempio n. 6
0
def moment_analysis(tsmap, wcs):
    """ perform localization by a moment analysis of a TS map
        tsmap : array of float
            should be square
        wcs : Projector object
            implements pix2sph function of two ints to return ra,dec
    returns: 
        ra, dec, ax, bx, phi
    """
    vals = np.exp(-0.5 * tsmap**2).flatten()

    n = len(vals)
    nx = ny = int(np.sqrt(n))
    ix = np.array([i % nx for i in range(n)])
    iy = np.array([i // nx for i in range(n)])
    norm = 1. / sum(vals)
    t = [sum(u * vals) * norm for u in ix, iy, ix**2, ix * iy, iy**2]
    center = (t[0], t[1])
    C = np.matrix(center)
    variance = (np.matrix(((t[2], t[3]), (t[3], t[4]))) - C.T * C)
    ra, dec = wcs.pix2sph(center[1], center[0])
    peak = SkyDir(ra, dec)
    rac, decc = wcs.pix2sph(nx / 2, ny / 2)
    scale = wcs.pix2sph(nx / 2, ny / 2 + 1)[1] - decc
    size = nx * scale
    variance = scale**2 * variance
    offset = np.degrees(peak.difference(SkyDir(rac, decc)))

    # add effects of binsize
    var = variance + np.matrix(np.diag([1, 1])) * (scale / 3)**2
    t, v = np.linalg.eigh(var)
    ang = np.degrees(np.arctan2(v[1, 1], -v[1, 0]))

    tt = np.sqrt(t)
    if t[1] > t[0]:
        ax, bx = tt[1], tt[0]
        ang = 90 - ang
    else:
        ax, bx = tt
    return ra, dec, ax, bx, ang
Esempio n. 7
0
    def __call__(self, skydir):
        """ This funciton is analogous to the BandCALDBPsf.__call__ function
            except that it always returns the density (probability per unit
            area). Also, it is different in that it takes in a skydir or WSDL 
            instead of a radial distance. """
        if isinstance(skydir, BaseWeightedSkyDirList):
            difference = np.empty(len(skydir), dtype=float)
            PythonUtilities.arclength(
                difference, skydir, self.extended_source.spatial_model.center)
            return self.val(difference)
        elif type(skydir) == np.ndarray:
            return self.val(skydir)
        elif type(skydir) == list and len(skydir) == 3:
            skydir = SkyDir(Hep3Vector(skydir[0], skydir[1], skydir[2]))

        elif type(skydir) == SkyDir:
            return float(
                self.val(
                    skydir.difference(
                        self.extended_source.spatial_model.center)))
        else:
            raise Exception("Unknown input to AnalyticConvolution.__call__()")