Example #1
0
def main(args):
    with fitsio.FITS(args.catalogue) as infile:
        hdu = infile[1]
        ra1 = hdu['RA_1'][:]
        dec1 = hdu['DEC_1'][:]

        ra2 = hdu['ra_2'][:]
        dec2 = hdu['dec_2'][:]


    coords1 = ICRS(ra=ra1, dec=dec1, unit=(u.radian, u.radian))
    coords2 = ICRS(ra=ra2, dec=dec2, unit=(u.degree, u.degree))

    separations = coords1.separation(coords2).degree * 3600.

    fig, axes = plt.subplots(figsize=(11, 8))

    axes.hist(separations, 30, histtype='step')
    axes.set_xlabel(r'Separation / arcseconds')
    axes.grid(True)

    fig.tight_layout()

    if args.output is not None:
        fig.savefig(args.output, bbox_inches='tight')
    else:
        plt.show()
Example #2
0
def test_coord_get():

    # Test default (instance=None)
    obs = Helioprojective.observer
    assert obs is "earth"

    # Test get
    obstime = "2013-04-01"
    obs = Helioprojective(observer="earth", obstime=obstime).observer
    earth = get_earth(obstime)
    assert isinstance(obs, HeliographicStonyhurst)
    assert_quantity_allclose(obs.lon, earth.lon)
    assert_quantity_allclose(obs.lat, earth.lat)
    assert_quantity_allclose(obs.radius, earth.radius)

    # Test get
    obstime = "2013-04-01"
    obs = Helioprojective(obstime=obstime).observer
    earth = get_earth(obstime)
    assert isinstance(obs, HeliographicStonyhurst)
    assert_quantity_allclose(obs.lon, earth.lon)
    assert_quantity_allclose(obs.lat, earth.lat)
    assert_quantity_allclose(obs.radius, earth.radius)

    # Test get mars
    obstime = Time(parse_time("2013-04-01"))
    obs = Helioprojective(observer="mars", obstime=obstime).observer
    out_icrs = ICRS(get_body_barycentric("mars", obstime))
    mars = out_icrs.transform_to(HeliographicStonyhurst(obstime=obstime))

    assert isinstance(obs, HeliographicStonyhurst)
    assert_quantity_allclose(obs.lon, mars.lon)
    assert_quantity_allclose(obs.lat, mars.lat)
    assert_quantity_allclose(obs.radius, mars.radius)
def main(args):
    with fitsio.FITS(args.catalogue) as infile:
        hdu = infile[1]
        ra1 = hdu['RA_1'][:]
        dec1 = hdu['DEC_1'][:]

        ra2 = hdu['ra_2'][:]
        dec2 = hdu['dec_2'][:]

        x = hdu['X_coordinate'][:]
        y = hdu['Y_coordinate'][:]


    coords1 = ICRS(ra=ra1, dec=dec1, unit=(u.radian, u.radian))
    coords2 = ICRS(ra=ra2, dec=dec2, unit=(u.degree, u.degree))

    separations = coords1.separation(coords2).degree * 3600.

    fig, axes = plt.subplots(2, 2, sharex=True, figsize=(11, 8))
    [(x_axis, y_axis), (x_zoomed, y_zoomed)] = axes

    nsigma = 5
    nbins = 2048 / 128
    print('Using {} bins'.format(nbins))
    x_axis.plot(x, separations, 'k.', color='0.4')
    x_axis.set_ylabel(r'X')

    ledges, x_binned = compute_binned(x, separations, nbins)
    _, x_binned_error = compute_binned_errors(x, separations, ledges)
    bin_centres = compute_bin_centres(ledges)

    for ax in [x_axis, x_zoomed]:
        ax.errorbar(bin_centres[:-1], x_binned[:-1], x_binned_error[:-1],
                color='r', ls='None')
        ax.plot(ledges, x_binned, color='r', drawstyle='steps-post')

    y_axis.plot(y, separations, 'k.', color='0.4')
    y_axis.set_ylabel(r'y')

    ledges, y_binned = compute_binned(y, separations, nbins)
    _, y_binned_error = compute_binned_errors(y, separations, ledges)

    for ax in [y_axis, y_zoomed]:
        ax.errorbar(bin_centres[:-1], y_binned[:-1], x_binned_error[:-1],
                color='r', ls='None')
        ax.plot(ledges, y_binned, color='r', drawstyle='steps-post')

    link_y_limits(x_zoomed, y_zoomed)

    for ax in axes.flatten():
        ax.grid(True)

    fig.tight_layout()

    if args.output is not None:
        fig.savefig(args.output, bbox_inches='tight')
    else:
        plt.show()
Example #4
0
def test_radec_to_munu():
    from astropy import units as u
    from astropy.coordinates import ICRS
    from .. import SDSSMuNu
    radec = ICRS(ra=0.0*u.deg,dec=0.0*u.deg)
    munu = radec.transform_to(SDSSMuNu(stripe=10))
    assert munu.mu.value == 0.0
    assert munu.nu.value == 0.0
    assert munu.incl.value == 0.0
Example #5
0
 def eq2gal(self,ra,dec):
     try:
         ra = Angle(ra)
         dec = Angle(dec)
         c = ICRS(ra=ra, dec=dec)
         return c.transform_to(Galactic)
     except Exception as e:
         print(e)
         return 0
Example #6
0
def v_hist():
	""""""
	t = Table.read("../data/deimos.fits")
	print(t.keys())
	
	N = len(t)
	ra = np.zeros(N)*u.deg
	dec = np.zeros(N)*u.deg
	
	for j in range(N):
		ra[j] = Angle(t['RA'][j] + ' hours')
		dec[j] = Angle(t['DEC'][j] + 'degrees')
	
	# 
	fname = '../data/TriS-1.out'
	ra_s, dec_s, i, priority, inmask = np.loadtxt(fname, usecols=(1,2,4,6,8), unpack=True, dtype='|S11, |S11, <f4, <f4, <i4', skiprows=4)
	
	Nm = np.size(ra_s)
	ra_m = np.zeros(Nm)*u.deg
	dec_m = np.zeros(Nm)*u.deg
	
	for j in range(Nm):
		ra_m[j] = Angle(ra_s[j] + ' hours')
		dec_m[j] = Angle(dec_s[j] + 'degrees')
	
	# match catalogs
	ref = ICRS(ra_m, dec_m, unit=(u.degree, u.degree))
	cat = ICRS(ra, dec, unit=(u.degree, u.degree))
	id1, d21, d31 = cat.match_to_catalog_sky(ref)
	
	matches = d21<0.5*u.arcsec
	
	t_priority = priority[id1]
	i_m = i[id1]
	indices = (t['ZQUALITY']>-1)
	
	t['Z'] *= 300000
	
	add_npcolumn(t, name="priority", vec=t_priority)
	#print(t_priority, np.size(t_priority))
	
	plt.close()
	plt.figure()
	
	plt.subplot(221)
	plt.hist(t['Z'], bins=np.arange(-400,200,10), histtype='step', color='k')
	plt.hist(t['Z'][indices], bins=np.arange(-400,200,10), histtype='step', color='b')
	plt.hist(t['Z'][t_priority>=500], bins=np.arange(-400,200,10), histtype='step', color='r')
	
	plt.minorticks_on()
	
	plt.subplot(222)
	plt.plot(i_m[indices], t['Z'][indices], 'ko')
	print(t['Z'][t_priority>=500], i_m[t_priority>=500])
	print(np.max(i_m[indices]))
def test_icrs_altaz_moonish(testframe):
    """
    Check that something expressed in *ICRS* as being moon-like goes to the
    right AltAz distance
    """
    # we use epv00 instead of get_sun because get_sun includes aberration
    earth_pv_helio, earth_pv_bary = epv00(*get_jd12(testframe.obstime, 'tdb'))
    earth_icrs_xyz = earth_pv_bary[0]*u.au
    moonoffset = [0, 0, MOONDIST.value]*MOONDIST.unit
    moonish_icrs = ICRS(CartesianRepresentation(earth_icrs_xyz + moonoffset))
    moonaa = moonish_icrs.transform_to(testframe)

    # now check that the distance change is similar to earth radius
    assert 1000*u.km < np.abs(moonaa.distance - MOONDIST).to(u.au) < 7000*u.km
Example #8
0
def test_array_separation():
    c1 = ICRS([0, 0]*u.deg, [0, 0]*u.deg)
    c2 = ICRS([1, 2]*u.deg, [0, 0]*u.deg)

    npt.assert_array_almost_equal(c1.separation(c2).degree, [1, 2])

    c3 = ICRS([0, 3.]*u.deg, [0., 0]*u.deg, distance=[1, 1.] * u.kpc)
    c4 = ICRS([1, 1.]*u.deg, [0., 0]*u.deg, distance=[1, 1.] * u.kpc)

    # the 3-1 separation should be twice the 0-1 separation, but not *exactly* the same
    sep = c3.separation_3d(c4)
    sepdiff = sep[1] - (2 * sep[0])

    assert abs(sepdiff.value) < 1e-5
    assert sepdiff != 0
def test_icrs_gcrscirs_sunish(testframe):
    """
    check that the ICRS barycenter goes to about the right distance from various
    ~geocentric frames (other than testframe)
    """
    # slight offset to avoid divide-by-zero errors
    icrs = ICRS(0*u.deg, 0*u.deg, distance=10*u.km)

    gcrs = icrs.transform_to(GCRS(obstime=testframe.obstime))
    assert (EARTHECC - 1)*u.au < gcrs.distance.to(u.au) < (EARTHECC + 1)*u.au

    cirs = icrs.transform_to(CIRS(obstime=testframe.obstime))
    assert (EARTHECC - 1)*u.au < cirs.distance.to(u.au) < (EARTHECC + 1)*u.au

    itrs = icrs.transform_to(ITRS(obstime=testframe.obstime))
    assert (EARTHECC - 1)*u.au < itrs.spherical.distance.to(u.au) < (EARTHECC + 1)*u.au
Example #10
0
def test_array_coordinates_transformations(arrshape, distance):
    """
    Test transformation on coordinates with array content (first length-2 1D, then a 3D array)
    """
    # M31 coordinates from test_transformations
    raarr = np.ones(arrshape) * 10.6847929
    decarr = np.ones(arrshape) * 41.2690650
    if distance is not None:
        distance = np.ones(arrshape) * distance

    print(raarr, decarr, distance)
    c = ICRS(ra=raarr*u.deg, dec=decarr*u.deg, distance=distance)
    g = c.transform_to(Galactic)

    assert g.l.shape == arrshape

    npt.assert_array_almost_equal(g.l.degree, 121.17440967)
    npt.assert_array_almost_equal(g.b.degree, -21.57299631)

    if distance is not None:
        assert g.distance.unit == c.distance.unit

    # now make sure round-tripping works through FK5
    c2 = c.transform_to(FK5).transform_to(ICRS)
    npt.assert_array_almost_equal(c.ra.radian, c2.ra.radian)
    npt.assert_array_almost_equal(c.dec.radian, c2.dec.radian)

    assert c2.ra.shape == arrshape

    if distance is not None:
        assert c2.distance.unit == c.distance.unit

    # also make sure it's possible to get to FK4, which uses a direct transform function.
    fk4 = c.transform_to(FK4)

    npt.assert_array_almost_equal(fk4.ra.degree, 10.0004, decimal=4)
    npt.assert_array_almost_equal(fk4.dec.degree, 40.9953, decimal=4)

    assert fk4.ra.shape == arrshape
    if distance is not None:
        assert fk4.distance.unit == c.distance.unit

    # now check the reverse transforms run
    cfk4 = fk4.transform_to(ICRS)
    assert cfk4.ra.shape == arrshape
def ra_dec_distance(ra1, dec1, ra2, dec2, use_icrs=False, arcsec=False):
    # conversion between degree and radians
    pi  = 3.1415926536
    d2r = pi/180.00

    if use_icrs:
        coord1 = ICRS(ra=ra1, dec=dec1, unit=(u.degree,u.degree))
        coord2 = ICRS(ra=ra2, dec=dec2, unit=(u.degree,u.degree))
    else:
        coord1 = FK5(ra=ra1, dec=dec1, unit=(u.degree,u.degree))
        coord2 = FK5(ra=ra2, dec=dec2, unit=(u.degree,u.degree))
    # The separation is in unit of arcsecond or degree
    if arcsec:
        sep = coord1.separation(coord2).arcsecond
    else:
        sep = (coord1.separation(coord2).radian / d2r )

    return sep
def test_icrs_cirs():
    """
    Check a few cases of ICRS<->CIRS for consistency.

    Also includes the CIRS<->CIRS transforms at different times, as those go
    through ICRS
    """
    ra, dec, dist = randomly_sample_sphere(200)
    inod = ICRS(ra=ra, dec=dec)
    iwd = ICRS(ra=ra, dec=dec, distance=dist*u.pc)

    cframe1 = CIRS()
    cirsnod = inod.transform_to(cframe1)  # uses the default time
    # first do a round-tripping test
    inod2 = cirsnod.transform_to(ICRS)
    assert_allclose(inod.ra, inod2.ra)
    assert_allclose(inod.dec, inod2.dec)

    # now check that a different time yields different answers
    cframe2 = CIRS(obstime=Time('J2005', scale='utc'))
    cirsnod2 = inod.transform_to(cframe2)
    assert not allclose(cirsnod.ra, cirsnod2.ra, rtol=1e-8)
    assert not allclose(cirsnod.dec, cirsnod2.dec, rtol=1e-8)

    # parallax effects should be included, so with and w/o distance should be different
    cirswd = iwd.transform_to(cframe1)
    assert not allclose(cirswd.ra, cirsnod.ra, rtol=1e-8)
    assert not allclose(cirswd.dec, cirsnod.dec, rtol=1e-8)
    # and the distance should transform at least somehow
    assert not allclose(cirswd.distance, iwd.distance, rtol=1e-8)

    # now check that the cirs self-transform works as expected
    cirsnod3 = cirsnod.transform_to(cframe1)  # should be a no-op
    assert_allclose(cirsnod.ra, cirsnod3.ra)
    assert_allclose(cirsnod.dec, cirsnod3.dec)

    cirsnod4 = cirsnod.transform_to(cframe2)  # should be different
    assert not allclose(cirsnod4.ra, cirsnod.ra, rtol=1e-8)
    assert not allclose(cirsnod4.dec, cirsnod.dec, rtol=1e-8)

    cirsnod5 = cirsnod4.transform_to(cframe1)  # should be back to the same
    assert_allclose(cirsnod.ra, cirsnod5.ra)
    assert_allclose(cirsnod.dec, cirsnod5.dec)
def test_table_can_be_read_and_coords_good():
    objs = Table.read(TABLE_NAME, format='ascii', delimiter=',')
    columns = ['object', 'ra', 'dec']
    for col in columns:
        assert col in objs.colnames
    for row in objs:
        try:
            simbad_pos = ICRS.from_name(row['object'])
        except name_resolve.NameResolveError:
            continue
        table_pos = ICRS(row['ra'], row['dec'], unit=(u.hour, u.degree))
        # CHANGE ASSERT TO IF/THEN, print name then assert 0
        sep = table_pos.separation(simbad_pos).arcsec
        warn = ''
        if sep > MAX_SEP:
            warn = ('Bad RA/Dec for object {}, '
                    'separation is {} arcsec'.format(row['object'], sep))
            print (warn)
        assert len(warn) == 0
Example #14
0
def test_regression_3920():
    """
    Issue: https://github.com/astropy/astropy/issues/3920
    """
    loc = EarthLocation.from_geodetic(0*u.deg, 0*u.deg, 0)
    time = Time('2010-1-1')

    aa = AltAz(location=loc, obstime=time)
    sc = SkyCoord(10*u.deg, 3*u.deg)
    assert sc.transform_to(aa).shape == tuple()
    # That part makes sense: the input is a scalar so the output is too

    sc2 = SkyCoord(10*u.deg, 3*u.deg, 1*u.AU)
    assert sc2.transform_to(aa).shape == tuple()
    # in 3920 that assert fails, because the shape is (1,)

    # check that the same behavior occurs even if transform is from low-level classes
    icoo = ICRS(sc.data)
    icoo2 = ICRS(sc2.data)
    assert icoo.transform_to(aa).shape == tuple()
    assert icoo2.transform_to(aa).shape == tuple()
Example #15
0
   def get_radec(self):
      """
      Extracts the RA and Dec information from the data container.  This
      is not necessary, and some of the data containers may not even have
      WCS info, but extracting the coordinates if it does simplifies some
      later tasks.
      """

      """ Extract the information into the new containers """
      self.ra = None
      self.dec = None
      if self.rafield is not None:
         try:
            self.ra  = self.data[self.rafield].copy()
         except:
            try:
               self.ra = self.data['x_world'].copy()
            except:
               self.ra = None
      if self.decfield is not None:
         try:
            self.dec = self.data[self.decfield].copy()
         except:
            try:
               self.dec = self.data['y_world'].copy()
            except:
               self.dec = None

      """ 
      Put data into a SkyCoords container for easy coordinate-based calculations
      """
      if (self.ra is not None) and (self.dec is not None):
         """ 
         Determine whether the RA coordinate is in hours or in degrees
         For now this test is made simple: if the format of the RA data is
          a string, then the data is expected to be in hms format, otherwise
          expect decimal degrees.
         """
         if type(self.ra[0]) is str or type(self.ra[0]) is np.string_:
            raunit = u.hourangle
         else:
            raunit = u.deg
         self.radec = SkyCoord(self.ra,self.dec,unit=(raunit,u.deg))

      """ 
      If radec has not been set, report this information
      (consider raising an exception in future versions of the code)
      """
      if self.radec is None:
         print ''
         print 'WARNING: get_radec was called but RA and Dec information was'
         print '         not found.  Please check the format of your catalog.'
         print ''
Example #16
0
class SkyCircle(object):
    """A circle on the sky.
    
    Parameters
    ----------
    center : `~astropy.coordinates.coordsystems.SphericalCoordinatesBase`
        Circle center coordinate
    radius : `~astropy.coordinates.angles.Angle`
        Circle radius
    """
    
    def __init__(self, center, radius):
        from astropy.coordinates import ICRS, Angle
        self.center = ICRS(center)
        self.radius = Angle(radius)

    def contains(self, coordinate):
        """Checks if the coordinate lies inside the circle.

        Parameters
        ----------
        coordinate : `~astropy.coordinates.coordsystems.SphericalCoordinatesBase`
            Coordinate to check for containment.

        Returns
        -------
        contains : bool
            Does this region contain the coordinate?
        """
        return self.center.separation(coordinate) <= self.radius

    def intersects(self, other):
        """Checks if two sky circles overlap.

        Parameters
        ----------
        other : `~SkyCircle`
            Other region.
        """
        return self.center.separation(other.center) <= self.radius + other.radius
def main(args):
    with fitsio.FITS(args.catalogue) as infile:
        hdu = infile[1]
        ra1 = hdu['RA_1'][:]
        dec1 = hdu['DEC_1'][:]

        ra2 = hdu['ra_2'][:]
        dec2 = hdu['dec_2'][:]

        jmag = hdu['jmag'][:]


    coords1 = ICRS(ra=ra1, dec=dec1, unit=(u.radian, u.radian))
    coords2 = ICRS(ra=ra2, dec=dec2, unit=(u.degree, u.degree))

    separations = coords1.separation(coords2).degree * 3600.

    nbins = 30
    height, xedges, yedges = np.histogram2d(jmag, separations, nbins)

    fig, axis = plt.subplots(figsize=(11, 8))

    mappable = axis.pcolormesh(xedges[:-1], yedges[:-1], np.log10(height.T + 1), 
            cmap=plt.cm.binary)
    axis.plot(jmag, separations, 'k.', alpha=0.2)

    stat, ledges, _ = stats.binned_statistic(jmag, separations, statistic='median',
            bins=nbins)
    axis.plot(ledges[:-1], stat, drawstyle='steps-post', color='r')

    axis.set_xlabel(r'2MASS J Magnitude')
    axis.set_ylabel(r'Separation / arcseconds')
    axis.grid(True)

    fig.tight_layout()

    if args.output is not None:
        fig.savefig(args.output, bbox_inches='tight')
    else:
        plt.show()
Example #18
0
def sdss_IAU_id_to_ra_dec(sdssids, matchtocatalog=None):
    """
    Converts IAU SDSS identifiers (e.g.,"J151503.37+421253.9") to their RA/Decs

    Returns an ICRS object if `matchtocatalog` is None, otherwise
    `catalogidx, skysep`

    """
    import re
    from astropy.coordinates import ICRS, Latitude, Longitude

    rex = re.compile(r'J(\d{2})(\d{2})(\d{2}(?:\.\d{1,2})?)'
                     r'([+-])(\d{2})(\d{2})(\d{2}(?:\.\d)?)')

    if isinstance(sdssids, six.string_types):
        sdssids = [sdssids]

    ras = []
    decs = []
    for idi in sdssids:
        res = rex.match(idi)
        if res is None:
            raise ValueError('Could not match ' + idi)
        res = res.groups()
        rah, ram, rasc = res[:3]
        desgn, ded, dem, des = res[-4:]

        ras.append(':'.join((rah, ram, rasc)))
        decs.append(desgn + ':'.join((ded, dem, des)))

    coords = ICRS(ra=Longitude(ras, u.hourangle), dec=Latitude(decs, u.degree))
    if matchtocatalog:
        if not hasattr(matchtocatalog, 'match_to_catalog_sky'):
            matchtocatalog = ICRS(ra=np.array(matchtocatalog['ra'])*u.deg,
                                  dec=np.array(matchtocatalog['dec'])*u.deg)
        idx, sep, sep3d = coords.match_to_catalog_sky(matchtocatalog)
        return idx, sep.to(u.arcsec)
    else:
        return coords
Example #19
0
def get_body_heliographic_stonyhurst(body, time='now'):
    """
    Return a `~sunpy.coordinates.frames.HeliographicStonyhurst` frame for the location of a
    solar-system body at a specified time.

    Parameters
    ----------
    body : `str`
        The solar-system body for which to calculate positions
    time : various
        Time to use as `~astropy.time.Time` or in a parse_time-compatible format

    Returns
    -------
    out : `~sunpy.coordinates.frames.HeliographicStonyhurst`
        Location of the solar-system body in the `~sunpy.coordinates.HeliographicStonyhurst` frame
    """
    obstime = parse_time(time)

    body_icrs = ICRS(get_body_barycentric(body, obstime))
    body_hgs = body_icrs.transform_to(HGS(obstime=obstime))

    return body_hgs
Example #20
0
def azel2radec(az_deg, el_deg, lat_deg, lon_deg, t):
    """convert astronomical target horizontal azimuth, elevation to ecliptic right ascension, declination (degrees)"""

    if PY2 or Time is None:  # non-AstroPy method, less accurate
        return vazel2radec(az_deg, el_deg, lat_deg, lon_deg, t)

    t = str2dt(t)

    obs = EarthLocation(lat=lat_deg * u.deg, lon=lon_deg * u.deg)

    direc = AltAz(location=obs,
                  obstime=Time(t),
                  az=az_deg * u.deg,
                  alt=el_deg * u.deg)

    sky = SkyCoord(direc.transform_to(ICRS()))

    return sky.ra.deg, sky.dec.deg
Example #21
0
def test_skycoord_transforms():
    # An EarthLocation object should still get copied over
    # under transformations.

    eloc = EarthLocation.from_geodetic(0.0, 10.0)
    coords = ltest.get_catalog()

    altaz = coords.transform_to(AltAz(location=eloc, obstime=Time.now()))

    assert altaz.location == eloc

    gcrs = altaz.transform_to(GCRS())

    assert gcrs.location == eloc

    icrs = altaz.transform_to(ICRS())

    assert icrs.location == eloc
Example #22
0
 def plot_hpix(self,
               hpix,
               nside,
               order='nested',
               color='blue',
               edgecolor='black',
               zorder=1,
               alpha=1):
     bounds = HEALPix(nside=nside, order=order, frame=ICRS())
     corners = bounds.boundaries_skycoord(np.unique(hpix), step=1)
     poly = MultiPolygon(Polygon(np.array([-(corners[idx].ra.deg - 360 * (corners[idx].ra.deg > 180)), corners[idx].dec.deg]).T) \
             for idx in range(len(corners.ra)) if not any(abs(corners[idx].ra.deg - 360 * (corners[idx].ra.deg > 180) - 180) == 0))
     self.ax.add_geometries([poly],
                            crs=ccrs.PlateCarree(),
                            facecolor=color,
                            alpha=alpha,
                            edgecolor=edgecolor,
                            zorder=zorder)
Example #23
0
File: rad.py Project: ezanatta/MLE
 def get_r(RA, DEC):
     R = np.zeros(len(RA))
     ys = np.zeros(len(RA))
     for i in range(0, len(RA)):
         aux = SkyCoord(RA[i], DEC[i])
         aux = aux.icrs
         ra = str(int(aux.ra.hms.h)) + 'h' + str(int(
             aux.ra.hms.m)) + 'm' + str(int(aux.ra.hms.s)) + 's'
         dec = str(int(aux.dec.dms.d)) + 'd' + str(abs(int(
             aux.dec.dms.m))) + 'm' + str(abs(int(aux.dec.dms.s))) + 's'
         coordinates = ra + ' ' + dec
         coord = ICRS(coordinates)
         ygc, r = correct_rgc(coord, galcenter, Angle(str(inps[3])),
                              Angle(str(inps[2])),
                              Distance(inps[4], unit=u.kpc))
         R[i] = r.value
         ys[i] = ygc
     return R, ys
Example #24
0
def build_ephem_interpolant(body, period, t_span, rtol=1e-5):
    """Interpolates ephemerides data

    Parameters
    ----------
    body : Body
        Source body.
    period : ~astropy.units.Quantity
        Orbital period.
    t_span : list(~astropy.units.Quantity)
        Initial and final epochs.
    rtol : float, optional
        Relative tolerance. Controls the number of sampled data points,
        defaults to 1e-5.

    Returns
    -------
    intrp : ~scipy.interpolate.interpolate.interp1d
        Interpolated function.

    """
    h = (period * rtol).to(u.day).value
    t_span = (t_span[0].to(u.day).value, t_span[1].to(u.day).value + 0.01)
    t_values = np.linspace(*t_span, int(
        (t_span[1] - t_span[0]) / h))  # type: ignore
    r_values = np.zeros((t_values.shape[0], 3))

    for i, t in enumerate(t_values):
        epoch = Time(t, format="jd", scale="tdb")

        r = get_body_barycentric(body.name, epoch)
        r = (ICRS(
            x=r.x, y=r.y, z=r.z,
            representation_type=CartesianRepresentation).transform_to(
                GCRS(obstime=epoch)).represent_as(CartesianRepresentation))

        r_values[i] = r.xyz.to(u.km)

    t_values = ((t_values - t_span[0]) * u.day).to(u.s).value
    return interp1d(t_values,
                    r_values,
                    kind="cubic",
                    axis=0,
                    assume_sorted=True)
Example #25
0
def hdu_to_imagemodel(in_hdu):
    """
    Workaround for initializing a `jwst.datamodels.ImageModel` from a
    normal FITS ImageHDU that could contain HST header keywords and
    unexpected WCS definition.

    TBD

    Parameters
    ----------
    in_hdu : `astropy.io.fits.ImageHDU`


    Returns
    -------
    img : `jwst.datamodels.ImageModel`


    """
    from astropy.io.fits import ImageHDU, HDUList
    from astropy.coordinates import ICRS

    from jwst.datamodels import util
    import gwcs

    hdu = ImageHDU(data=in_hdu.data, header=in_hdu.header)

    new_header = strip_telescope_header(hdu.header)

    hdu.header = new_header

    # Initialize data model
    img = util.open(HDUList([hdu]))

    # Initialize GWCS
    tform = gwcs.wcs.utils.make_fitswcs_transform(new_header)
    hwcs = gwcs.WCS(forward_transform=tform, output_frame=ICRS())  # gwcs.CelestialFrame())
    sh = hdu.data.shape
    hwcs.bounding_box = ((-0.5, sh[0]-0.5), (-0.5, sh[1]-0.5))

    # Put gWCS in meta, where blot/drizzle expect to find it
    img.meta.wcs = hwcs

    return img
Example #26
0
def get_body_heliographic_stonyhurst(body, time='now', observer=None):
    """
    Return a `~sunpy.coordinates.frames.HeliographicStonyhurst` frame for the location of a
    solar-system body at a specified time.

    Parameters
    ----------
    body : `str`
        The solar-system body for which to calculate positions
    time : various
        Time to use as `~astropy.time.Time` or in a parse_time-compatible format
    observer : `~astropy.coordinates.SkyCoord`
        If not None, the returned coordinate is the apparent location (i.e., accounts for light
        travel time)

    Returns
    -------
    out : `~sunpy.coordinates.frames.HeliographicStonyhurst`
        Location of the solar-system body in the `~sunpy.coordinates.HeliographicStonyhurst` frame
    """
    obstime = parse_time(time)

    if observer is None:
        body_icrs = get_body_barycentric(body, obstime)
    else:
        observer_icrs = SkyCoord(observer).icrs.cartesian

        # This implementation is modeled after Astropy's `_get_apparent_body_position`
        light_travel_time = 0.*u.s
        emitted_time = obstime
        delta_light_travel_time = 1.*u.s  # placeholder value
        while np.any(np.fabs(delta_light_travel_time) > 1.0e-8*u.s):
            body_icrs = get_body_barycentric(body, emitted_time)
            distance = (body_icrs - observer_icrs).norm()
            delta_light_travel_time = light_travel_time - distance / speed_of_light
            light_travel_time = distance / speed_of_light
            emitted_time = obstime - light_travel_time

        log.info(f"Apparent body location accounts for {light_travel_time.to('s').value:.2f}"
                  " seconds of light travel time")

    body_hgs = ICRS(body_icrs).transform_to(HGS(obstime=obstime))

    return body_hgs
Example #27
0
def compute_healpix_vertices(depth, ipix, wcs):
    path_vertices = np.array([])
    codes = np.array([])

    depth = int(depth)

    step = 1
    if depth < 3:
        step = 2

    ipix_lon, ipix_lat = cdshealpix.vertices(ipix, depth)

    ipix_lon = ipix_lon[:, [2, 3, 0, 1]]
    ipix_lat = ipix_lat[:, [2, 3, 0, 1]]
    ipix_boundaries = SkyCoord(ipix_lon, ipix_lat, frame=ICRS())
    # Projection on the given WCS
    xp, yp = skycoord_to_pixel(ipix_boundaries, wcs=wcs)

    c1 = np.vstack((xp[:, 0], yp[:, 0])).T
    c2 = np.vstack((xp[:, 1], yp[:, 1])).T
    c3 = np.vstack((xp[:, 2], yp[:, 2])).T
    c4 = np.vstack((xp[:, 3], yp[:, 3])).T

    # if depth < 3:
    #     c5 = np.vstack((xp[:, 4], yp[:, 4])).T
    #     c6 = np.vstack((xp[:, 5], yp[:, 5])).T
    #     c7 = np.vstack((xp[:, 6], yp[:, 6])).T
    #     c8 = np.vstack((xp[:, 7], yp[:, 7])).T

    #     cells = np.hstack((c1, c2, c3, c4, c5, c6, c7, c8, np.zeros((c1.shape[0], 2))))

    #     path_vertices = cells.reshape((9*c1.shape[0], 2))
    #     single_code = np.array([Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY])
    # else:
    cells = np.hstack((c1, c2, c3, c4, np.zeros((c1.shape[0], 2))))

    path_vertices = cells.reshape((5 * c1.shape[0], 2))
    single_code = np.array(
        [Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY])

    codes = np.tile(single_code, c1.shape[0])

    return path_vertices, codes
Example #28
0
def merge_cat(tmass, ukidss, vista):
    moc_vista = MOC()
    read_moc_fits(moc_vista, '../data/vista/moc_vista.fits')
    moc_ukidss = MOC()
    read_moc_fits(moc_ukidss, '../data/ukidss/moc_ukidss.fits')

    moc_order = moc_vista.order
    hp = HEALPix(nside=2**moc_order, order='nested', frame=ICRS())
    moc_allsky = MOC(0, tuple(range(12)))
    moc_tmass = moc_allsky - moc_ukidss - moc_vista
    moc_vista = moc_vista - moc_ukidss

    vista_final = utils.sources_inmoc(vista,
                                      hp,
                                      moc_vista,
                                      moc_order=moc_order,
                                      ra='posRA',
                                      dec='posDec')
    vista_final.rename_column('NVTobjID', 'NIRobjID')
    vista_final.add_column(
        Table.Column(['VISTA'] * len(vista_final), name='NIR_SURVEY'))

    tmass_final = utils.sources_inmoc(tmass,
                                      hp,
                                      moc_tmass,
                                      moc_order=moc_order,
                                      ra='posRA',
                                      dec='posDec')
    tmass_final.rename_column('NTMobjID', 'NIRobjID')
    tmass_final.add_column(
        Table.Column(['2MASS'] * len(tmass_final), name='NIR_SURVEY'))

    ukidss.rename_column('NUKobjID', 'NIRobjID')
    ukidss.add_column(Table.Column(['UKIDSS'] * len(ukidss),
                                   name='NIR_SURVEY'))

    xmatchcat_final = vstack([tmass_final, vista_final, ukidss])

    msk = np.logical_or(xmatchcat_final['NIR_SURVEY'] == 'UKIDSS',
                        xmatchcat_final['NIR_SURVEY'] == '2MASS')
    msk = np.logical_and(xmatchcat_final['NIRobjID'].mask, msk)

    return xmatchcat_final
Example #29
0
    def _fullsky_projection(self, wcs: WCS, shape: tuple, display_visible_sky: bool):
        """ """
        values = copy.deepcopy(self.value)
        if display_visible_sky:
            values[~self.visible_sky] = np.nan
        
        if isinstance(values, da.Array):
            with ProgressBar() if log.getEffectiveLevel() <= logging.INFO else DummyCtMgr():
                values = values.compute()

        with np.errstate(invalid='ignore'):
            # Ignore the invalid value in bilinear_interpolation (astropy-healpix)
            array, _ = reproject_from_healpix(
                (values, ICRS()),
                wcs,
                nested=False,
                shape_out=shape
            )
        return array
Example #30
0
def test_ephemerides():
    """
    We test that using different ephemerides gives very similar results
    for transformations
    """
    t = Time("2014-12-25T07:00")
    moon = SkyCoord(
        GCRS(318.10579159 * u.deg,
             -11.65281165 * u.deg,
             365042.64880308 * u.km,
             obstime=t))

    icrs_frame = ICRS()
    hcrs_frame = HCRS(obstime=t)
    ecl_frame = HeliocentricMeanEcliptic(equinox=t)
    cirs_frame = CIRS(obstime=t)

    moon_icrs_builtin = moon.transform_to(icrs_frame)
    moon_hcrs_builtin = moon.transform_to(hcrs_frame)
    moon_helioecl_builtin = moon.transform_to(ecl_frame)
    moon_cirs_builtin = moon.transform_to(cirs_frame)

    with solar_system_ephemeris.set('jpl'):
        moon_icrs_jpl = moon.transform_to(icrs_frame)
        moon_hcrs_jpl = moon.transform_to(hcrs_frame)
        moon_helioecl_jpl = moon.transform_to(ecl_frame)
        moon_cirs_jpl = moon.transform_to(cirs_frame)

    # most transformations should differ by an amount which is
    # non-zero but of order milliarcsecs
    sep_icrs = moon_icrs_builtin.separation(moon_icrs_jpl)
    sep_hcrs = moon_hcrs_builtin.separation(moon_hcrs_jpl)
    sep_helioecl = moon_helioecl_builtin.separation(moon_helioecl_jpl)
    sep_cirs = moon_cirs_builtin.separation(moon_cirs_jpl)

    assert_allclose([sep_icrs, sep_hcrs, sep_helioecl],
                    0.0 * u.deg,
                    atol=10 * u.mas)
    assert all(sep > 10 * u.microarcsecond
               for sep in (sep_icrs, sep_hcrs, sep_helioecl))

    # CIRS should be the same
    assert_allclose(sep_cirs, 0.0 * u.deg, atol=1 * u.microarcsecond)
Example #31
0
def test_array_coordinates_transformations(arrshape, distance):
    """
    Test transformation on coordinates with array content (first length-2 1D, then a 3D array)
    """
    # M31 coordinates from test_transformations
    raarr = np.ones(arrshape) * 10.6847929
    decarr = np.ones(arrshape) * 41.2690650
    if distance is not None:
        distance = np.ones(arrshape) * distance

    print(raarr, decarr, distance)
    c = ICRS(ra=raarr * u.deg, dec=decarr * u.deg, distance=distance)
    g = c.transform_to(Galactic())

    assert g.l.shape == arrshape

    npt.assert_array_almost_equal(g.l.degree, 121.17440967)
    npt.assert_array_almost_equal(g.b.degree, -21.57299631)

    if distance is not None:
        assert g.distance.unit == c.distance.unit

    # now make sure round-tripping works through FK5
    c2 = c.transform_to(FK5()).transform_to(ICRS())
    npt.assert_array_almost_equal(c.ra.radian, c2.ra.radian)
    npt.assert_array_almost_equal(c.dec.radian, c2.dec.radian)

    assert c2.ra.shape == arrshape

    if distance is not None:
        assert c2.distance.unit == c.distance.unit

    # also make sure it's possible to get to FK4, which uses a direct transform function.
    fk4 = c.transform_to(FK4())

    npt.assert_array_almost_equal(fk4.ra.degree, 10.0004, decimal=4)
    npt.assert_array_almost_equal(fk4.dec.degree, 40.9953, decimal=4)

    assert fk4.ra.shape == arrshape
    if distance is not None:
        assert fk4.distance.unit == c.distance.unit

    # now check the reverse transforms run
    cfk4 = fk4.transform_to(ICRS())
    assert cfk4.ra.shape == arrshape
Example #32
0
def test_spectralcoord_with_obstarget(tmpdir):

    sc = SpectralCoord(10 * u.GHz,
                       observer=ICRS(1 * u.km,
                                     2 * u.km,
                                     3 * u.km,
                                     representation_type='cartesian'),
                       target=Galactic(10 * u.deg,
                                       20 * u.deg,
                                       distance=30 * u.pc))
    tree = dict(spectralcoord=sc)

    def check(asdffile):
        assert isinstance(asdffile['spectralcoord'], SpectralCoord)
        assert_quantity_allclose(asdffile['spectralcoord'].quantity,
                                 10 * u.GHz)
        assert isinstance(asdffile['spectralcoord'].observer, ICRS)
        assert isinstance(asdffile['spectralcoord'].target, Galactic)

    assert_roundtrip_tree(tree, tmpdir, asdf_check_func=check)
Example #33
0
    def apply_mask(self, mask):
        """
        Remove particles from source arrays according to a mask.

        Parameters
        ----------
        mask : array-like, containing boolean-like
            Remove particles with indices corresponding to False values from
            the source arrays.
        """

        self.T_g = self.T_g[mask]
        self.mHI_g = self.mHI_g[mask]
        self.coordinates_g = self.coordinates_g[mask]
        self.sky_coordinates = ICRS(self.coordinates_g)
        self.hsm_g = self.hsm_g[mask]
        self.npart = np.sum(mask)
        if self.npart == 0:
            raise RuntimeError('No source particles in target region.')
        return
    def test_calculate_parallactic_angle(self) -> None:
        # TODO: Implement test (DM-21336)
        radec_icrs = ICRS(Angle(0.0, unit=u.hourangle), Angle(-80.0,
                                                              unit=u.deg))

        location = EarthLocation.from_geodetic(lon=-70.747698 * u.deg,
                                               lat=-30.244728 * u.deg,
                                               height=2663.0 * u.m)

        current_time = astropy_time_from_tai_unix(current_tai())

        current_time.location = location

        par_angle = calculate_parallactic_angle(
            location,
            current_time.sidereal_time("mean"),
            radec_icrs,
        )

        assert par_angle is not None
Example #35
0
File: egs.py Project: suchanek/PMA
def get_radial_vals(star_list):
    """create a list containing non-zero Radial Velocities.

    The input star_list is a list object returned by job.results()

    Parameters
    ----------
    star_list : list returned by job.results()

    Returns
    -------
    v_gsr : list of coordinates containing non-zero radial_velicities
    """
    i = 0
    count = len(star_list)
    x = []

    # make a fancy progressbar to monitor progress since this this iterates over
    # typically long star lists
    widgets = [
        ' [',
        progressbar.Timer(),
        '] ',
        progressbar.Bar(),
        ' (',
        progressbar.ETA(),
        ') ',
    ]

    with progressbar.ProgressBar(max_value=count, widgets=widgets) as bar2:
        for star in star_list:
            ra = star['ra'] * u.deg
            dec = star['dec'] * u.deg
            radial = star['radial_velocity'] * u.km / u.s
            star_icrs = ICRS(ra=ra, dec=dec, radial_velocity=radial)
            # convert to GSR from barycentric
            x.append(rv_to_gsr(star_icrs).value)
            count = count + 1
            i = i + 1
            bar2.update(i)
    return x
Example #36
0
    def _create_coord_from_offset(observer, radial_velocity):
        """
        Generates a default target or observer from a provided observer or
        target with an offset defined such as to create the provided radial
        velocity.

        Parameters
        ----------
        observer : `~astropy.coordinates.BaseCoordinateFrame` or `~astropy.coordinates.SkyCoord`
            Observer frame off which to base the target frame.
        radial_velocity : `~astropy.units.Quantity`
            Radial velocity used to calculate appropriate offsets between
            provided observer and generated target.

        Returns
        -------
        target : `~astropy.coordinates.BaseCoordinateFrame` or `~astropy.coordinates.SkyCoord`
            Generated target frame.
        """

        # The generated observer or target will be set up along the same y and z
        # coordinates as the target or observer, but offset along the x direction

        observer_icrs = observer.transform_to(ICRS())

        d = observer_icrs.cartesian.norm()
        drep = CartesianRepresentation(
            [DEFAULT_DISTANCE.to(d.unit), 0 * d.unit, 0 * d.unit])

        obs_vel = observer_icrs.cartesian.differentials['s']

        target = (observer_icrs.cartesian.without_differentials() +
                  drep).with_differentials(
                      CartesianDifferential([
                          _relativistic_velocity_addition(
                              obs_vel.d_x, radial_velocity),
                          obs_vel.d_y.to(radial_velocity.unit),
                          obs_vel.d_z.to(radial_velocity.unit)
                      ]))

        return observer_icrs.realize_frame(target)
Example #37
0
    def from_body(cls, body, epochs, *, attractor=None, plane=Planes.EARTH_EQUATOR):
        """Return `Ephem` for a `SolarSystemPlanet` at certain epochs.

        Parameters
        ----------
        body: ~poliastro.bodies.SolarSystemPlanet
            Body.
        epochs: ~astropy.time.Time
            Epochs to sample the body positions.
        attractor : ~poliastro.bodies.SolarSystemPlanet, optional
            Body to use as central location,
            if not given the Solar System Barycenter will be used.
        plane : ~poliastro.frames.Planes, optional
            Fundamental plane of the frame, default to Earth Equator.

        """
        if epochs.isscalar:
            epochs = epochs.reshape(1)

        if epochs.scale != "tdb":
            epochs = epochs.tdb
            warn(
                "Input time was converted to scale='tdb' with value "
                f"{epochs.tdb.value}. Use Time(..., scale='tdb') instead.",
                TimeScaleWarning,
                stacklevel=2,
            )

        r, v = get_body_barycentric_posvel(body.name, epochs)
        coordinates = r.with_differentials(v.represent_as(CartesianDifferential))

        destination_frame = _get_destination_frame(attractor, plane, epochs)

        if destination_frame is not None:
            coordinates = (
                ICRS(coordinates)
                .transform_to(destination_frame)
                .represent_as(CartesianRepresentation, CartesianDifferential)
            )

        return cls(coordinates, epochs, plane)
def test_icrs_cirs():
    """
    Check a few cases of ICRS<->CIRS for consistency.

    Also includes the CIRS<->CIRS transforms at different times, as those go
    through ICRS
    """
    ra, dec, dist = randomly_sample_sphere(200)
    inod = ICRS(ra=ra, dec=dec)
    iwd = ICRS(ra=ra, dec=dec, distance=dist * u.pc)

    cframe1 = CIRS()
    cirsnod = inod.transform_to(cframe1)  # uses the default time
    # first do a round-tripping test
    inod2 = cirsnod.transform_to(ICRS)
    assert_allclose(inod.ra, inod2.ra)
    assert_allclose(inod.dec, inod2.dec)

    # now check that a different time yields different answers
    cframe2 = CIRS(obstime=Time('J2005', scale='utc'))
    cirsnod2 = inod.transform_to(cframe2)
    assert not allclose(cirsnod.ra, cirsnod2.ra, rtol=1e-8)
    assert not allclose(cirsnod.dec, cirsnod2.dec, rtol=1e-8)

    # parallax effects should be included, so with and w/o distance should be different
    cirswd = iwd.transform_to(cframe1)
    assert not allclose(cirswd.ra, cirsnod.ra, rtol=1e-8)
    assert not allclose(cirswd.dec, cirsnod.dec, rtol=1e-8)
    # and the distance should transform at least somehow
    assert not allclose(cirswd.distance, iwd.distance, rtol=1e-8)

    # now check that the cirs self-transform works as expected
    cirsnod3 = cirsnod.transform_to(cframe1)  # should be a no-op
    assert_allclose(cirsnod.ra, cirsnod3.ra)
    assert_allclose(cirsnod.dec, cirsnod3.dec)

    cirsnod4 = cirsnod.transform_to(cframe2)  # should be different
    assert not allclose(cirsnod4.ra, cirsnod.ra, rtol=1e-8)
    assert not allclose(cirsnod4.dec, cirsnod.dec, rtol=1e-8)

    cirsnod5 = cirsnod4.transform_to(cframe1)  # should be back to the same
    assert_allclose(cirsnod.ra, cirsnod5.ra)
    assert_allclose(cirsnod.dec, cirsnod5.dec)
def EarthPosition(t, ephem='builtin'):
    '''
    The position of Earth at time, t, w.r.t. the Sun 
    using astropy.coordinates.solar_system_ephemeris.
    '''
#    logger = logging.getLogger()
#    logger.critical('As of 1.3, astropy has changed the behavior of some functions, giving diverging answers from previous versions')
    
    T = Time(t, format='jd', scale='utc')

    # pos_bary, vel_bary = get_body_barycentric_posvel('earth', time=T)
    with solar_system_ephemeris.set(ephem):
        pos_bary = get_body_barycentric('earth', time=T)
    pos_ICRS = ICRS(pos_bary)

    hcrs_frame = HCRS(obstime=T)
    Pos_HCRS = np.vstack((SkyCoord(pos_ICRS).transform_to(hcrs_frame).
                            cartesian.xyz.to(u.meter).value))
    Pos_HCI = HCRS2HCI(Pos_HCRS)
    
    return Pos_HCI
Example #40
0
def geomotion_velocity(time, skycoord, frame="heliocentric"):
    """ Perform a barycentric/heliocentric velocity correction.

    For the correciton, this routine uses the ephemeris:  astropy.coordinates.solar_system_ephemeris.set
    For more information see `~astropy.coordinates.solar_system_ephemeris`.

    Parameters
    ----------
    time : astropy.time.Time
        The time of observation, including the location.
    skycoord: astropy.coordinates.SkyCoord
        The RA and DEC of the pointing, as a SkyCoord quantity.
    frame : str
        The reference frame that should be used for the calculation.

    Returns
    -------
    vcorr : float
        The velocity correction that should be added to the original velocity.
    """

    # Check that the RA/DEC of the object is ICRS compatible
    if not skycoord.is_transformable_to(ICRS()):
        msgs.error("Cannot transform RA/DEC of object to the ICRS")

    # Calculate ICRS position and velocity of Earth's geocenter
    ep, ev = solar_system.get_body_barycentric_posvel('earth', time)
    # Calculate GCRS position and velocity of observatory
    op, ov = time.location.get_gcrs_posvel(time)
    # ICRS and GCRS are axes-aligned. Can add the velocities
    velocity = ev + ov
    if frame == "heliocentric":
        # ICRS position and velocity of the Sun
        sp, sv = solar_system.get_body_barycentric_posvel('sun', time)
        velocity += sv

    # Get unit ICRS vector in direction of SkyCoord
    sc_cartesian = skycoord.icrs.represent_as(
        UnitSphericalRepresentation).represent_as(CartesianRepresentation)
    return sc_cartesian.dot(velocity).to(units.km / units.s).value
Example #41
0
File: utils.py Project: pkgw/pywwt
def sanitize_image(image, output_file, overwrite=False):
    """
    Transform a FITS image so that it is in equatorial coordinates with a TAN
    projection and floating-point values, all of which are required to work
    correctly in WWT at the moment.

    Image can be a filename, an HDU, or a tuple of (array, WCS).
    """

    # The reproject package understands the different inputs to this function
    # so we can just transparently pass it through.

    wcs, shape_out = find_optimal_celestial_wcs([image],
                                                frame=ICRS(),
                                                projection='TAN')

    array, footprint = reproject_interp(image, wcs, shape_out=shape_out)

    fits.writeto(output_file,
                 array.astype(np.float32),
                 wcs.to_header(),
                 overwrite=overwrite)
Example #42
0
    def __new__(cls, *args, **kwargs):
        # We don't want to call this method if we've already set up
        # an skyoffset frame for this class.
        if not (issubclass(cls, ReferencePlaneFrame)
                and cls is not ReferencePlaneFrame):
            # We get the origin argument, and handle it here. Default is ICRS:
            # the user might want to use arbitrary reference plane coordinates
            # without every transforming them
            origin_frame = kwargs.get('origin', ICRS())

            if hasattr(origin_frame, 'frame'):
                origin_frame = origin_frame.frame
            newcls = _make_cls(origin_frame.__class__)
            return newcls.__new__(newcls, *args, **kwargs)

        # http://stackoverflow.com/questions/19277399/why-does-object-new-work-differently-in-these-three-cases
        # See above for why this is necessary. Basically, because some child
        # may override __new__, we must override it here to never pass
        # arguments to the object.__new__ method.
        if super().__new__ is object.__new__:
            return super().__new__(cls)
        return super().__new__(cls, *args, **kwargs)
def test_observer_init_rv_behavior():
    """
    Test basic initialization behavior or observer/target and redshift/rv
    """

    # Start off by specifying the radial velocity only
    sc_init = SpectralCoord([4000, 5000] * u.AA,
                            radial_velocity=100 * u.km / u.s)
    assert sc_init.observer is None
    assert sc_init.target is None
    assert_quantity_allclose(sc_init.radial_velocity, 100 * u.km / u.s)

    # Next, set the observer, and check that the radial velocity hasn't changed
    with pytest.warns(AstropyUserWarning,
                      match='No velocity defined on frame'):
        sc_init.observer = ICRS(
            CartesianRepresentation([0 * u.km, 0 * u.km, 0 * u.km]))
    assert sc_init.observer is not None
    assert_quantity_allclose(sc_init.radial_velocity, 100 * u.km / u.s)

    # Setting the target should now cause the original radial velocity to be
    # dropped in favor of the automatically computed one
    sc_init.target = SkyCoord(CartesianRepresentation(
        [1 * u.km, 0 * u.km, 0 * u.km]),
                              frame='icrs',
                              radial_velocity=30 * u.km / u.s)
    assert sc_init.target is not None
    assert_quantity_allclose(sc_init.radial_velocity, 30 * u.km / u.s)

    # The observer can only be set if originally None - now that it isn't
    # setting it again should fail
    with pytest.raises(ValueError, match='observer has already been set'):
        sc_init.observer = GCRS(
            CartesianRepresentation([0 * u.km, 1 * u.km, 0 * u.km]))

    # And similarly, changing the target should not be possible
    with pytest.raises(ValueError, match='target has already been set'):
        sc_init.target = GCRS(
            CartesianRepresentation([0 * u.km, 1 * u.km, 0 * u.km]))
Example #44
0
def radec(ra, dec):
    """ Equatorial coordinates
        
        :param ra:
            Right ascension in degrees
        :type ra: float
        :param dec:
            Declination in degrees
        :type dec: float

        :returns: :class:`astropy.coordinates.ICRS` object
        :rtype: :class:`astropy.coordinates.ICRS`

        :Example:
        
        >>> from nenupysim.astro import eq_coord
        >>> radec = eq_coord(
                ra=51,
                dec=39,
            )
    """
    return ICRS(ra=ra * u.deg, dec=dec * u.deg)
Example #45
0
def azel2radec(
    az_deg: float, el_deg: float, lat_deg: float, lon_deg: float, time: datetime, usevallado: bool = False
) -> Tuple[float, float]:
    """
    viewing angle (az, el) to sky coordinates (ra, dec)

    Parameters
    ----------
    az_deg : float
         azimuth [degrees clockwize from North]
    el_deg : float
             elevation [degrees above horizon (neglecting aberration)]
    lat_deg : float
              observer latitude [-90, 90]
    lon_deg : float
              observer longitude [-180, 180] (degrees)
    time : datetime.datetime or str
           time of observation
    usevallado : bool, optional
                 default use astropy. If true, use Vallado algorithm

    Returns
    -------
    ra_deg : float
         ecliptic right ascension (degress)
    dec_deg : float
         ecliptic declination (degrees)
    """

    if usevallado or Time is None:  # non-AstroPy method, less accurate
        return vazel2radec(az_deg, el_deg, lat_deg, lon_deg, time)

    obs = EarthLocation(lat=lat_deg * u.deg, lon=lon_deg * u.deg)

    direc = AltAz(location=obs, obstime=Time(str2dt(time)), az=az_deg * u.deg, alt=el_deg * u.deg)

    sky = SkyCoord(direc.transform_to(ICRS()))

    return sky.ra.deg, sky.dec.deg
Example #46
0
    def __init__(self, nside, coordsystem, order='nested', array=None):
        """
        grid: HEALPix map object
        nside: HEALPix nside parameter (int, power of 2)
        order: pixel ordering scheme of the HEALPix map
        coordsystem: Coordsystem object that describes the coordinate system  
        Note: 
        The HEALPix map used for the grid is initialized with a dummy ICRS 
        coordinate frame, that is not used in practise as healpy nor astropy 
        don't support ECEF/Geographic coordinate systems. 
        Instead the grid coordinates are defined through a coordinate system
        obtained from the LAL library.
        """

        if array is not None:
            assert len(array) == healpy.nside2npix(nside), "Data array has incorrect size"
        
        self.grid = HEALPix(nside=nside, order=order, frame=ICRS()) 
        self.nside = nside
        self.order = order
        self.coordsystem = coordsystem
        self.data = numpy.empty(healpy.nside2npix(nside)) if array is None else array
Example #47
0
    def to_icrs(self):
        """Creates a new Orbit object with its coordinates transformed to ICRS.

        Notice that, strictly speaking, the center of ICRS is the Solar System Barycenter
        and not the Sun, and therefore these orbits cannot be propagated in the context
        of the two body problem. Therefore, this function exists merely for practical
        purposes.

        .. versionadded:: 0.11.0

        """
        coords = self.frame.realize_frame(self.represent_as(CartesianRepresentation))
        coords.representation_type = CartesianRepresentation

        icrs_cart = coords.transform_to(ICRS).represent_as(CartesianRepresentation)

        # TODO: The attractor is in fact the Solar System Barycenter
        ss = self.from_vectors(
            Sun, r=icrs_cart.xyz, v=icrs_cart.differentials["s"].d_xyz, epoch=self.epoch
        )
        ss._frame = ICRS()  # Hack!
        return ss
Example #48
0
def build_ephem_interpolant(body, period, t_span, rtol=1e-5):
    h = (period * rtol).to(u.day).value
    t_span = (t_span[0].to(u.day).value, t_span[1].to(u.day).value + 0.01)
    t_values = np.linspace(*t_span, int((t_span[1] - t_span[0]) / h))
    r_values = np.zeros((t_values.shape[0], 3))

    for i, t in enumerate(t_values):
        epoch = Time(t, format="jd", scale="tdb")

        r = get_body_barycentric(body.name, epoch)
        r = (ICRS(
            x=r.x, y=r.y, z=r.z,
            representation_type=CartesianRepresentation).transform_to(
                GCRS(obstime=epoch)).represent_as(CartesianRepresentation))

        r_values[i] = r.xyz.to(u.km)

    t_values = ((t_values - t_span[0]) * u.day).to(u.s).value
    return interp1d(t_values,
                    r_values,
                    kind="cubic",
                    axis=0,
                    assume_sorted=True)
Example #49
0
def test_gcrs_altaz():
    """
    Check GCRS<->AltAz transforms for round-tripping.  Has multiple paths
    """
    from astropy.coordinates import EarthLocation

    ra, dec, _ = randomly_sample_sphere(1)
    gcrs = GCRS(ra=ra[0], dec=dec[0], obstime='J2000')

    # check array times sure N-d arrays work
    times = Time(np.linspace(2456293.25, 2456657.25, 51) * u.day, format='jd')

    loc = EarthLocation(lon=10 * u.deg, lat=80. * u.deg)
    aaframe = AltAz(obstime=times, location=loc)

    aa1 = gcrs.transform_to(aaframe)
    aa2 = gcrs.transform_to(ICRS()).transform_to(CIRS()).transform_to(aaframe)
    aa3 = gcrs.transform_to(ITRS()).transform_to(CIRS()).transform_to(aaframe)

    # make sure they're all consistent
    assert_allclose(aa1.alt, aa2.alt)
    assert_allclose(aa1.az, aa2.az)
    assert_allclose(aa1.alt, aa3.alt)
    assert_allclose(aa1.az, aa3.az)
Example #50
0
def visibility_main():
    """Plot a single target."""
    parser = argparse.ArgumentParser(description="A visibility plotter for a single target.")
    parser.add_argument("target", type=six.text_type, help="Object name as resolved by SIMBAD")
    parser.add_argument("-d","--date", help="Date before night, as parsed by Astropy.", default=Time.now())
    parser.add_argument("-o","--output", type=six.text_type, help="Output filename.")
    parser.add_argument("-O", "--observatory", type=six.text_type, help="Observatory Name", default="Mauna Kea")
    parser.add_argument("--tz", type=six.text_type, help="Local Timezone.")
    parser.add_argument("--show", action="store_true", help="Show, don't save.")
    options = parser.parse_args()
    
    # Setup Target
    t = Target(name=options.target, position=ICRS.from_name(options.target))
    date = Time(options.date, scale='utc')
    
    if not options.output:
        options.output = "visibility_{0}_{1:%Y%m%d}.pdf".format(t.name.replace(" ", "_"), date.datetime)
    
    o = Observatory.from_name(options.observatory)
    print(o)
    t.compute(o)
    print(t)
    
    # Setup Figure
    fig = plt.figure()
    bbox = (0.1, 0.1, 0.65, 0.8) # l, b, w, h
    v_ax = fig.add_axes(bbox)
    v = VisibilityPlot(o, date)
    v.add(t)
    v(v_ax, moon_distance_maximum=(60 * u.degree))
    
    if options.show:
        plt.show()
    else:
        plt.savefig(options.output)
        subprocess.call(["open", options.output])
def match_objects(folder_labels):

        print("----------------------------------------")
        print("Running Module 2: Match Objects")

        # stores all "_" filter txt files (eventually will group by similar exposure times in event there are more than one J,Ks files
        j_files = np.hstack(np.array(glob.glob('Data/{}/*-J.txt'.format(folder))) for folder in folder_labels)
        k_files = np.hstack(np.array(glob.glob('Data/{}/*-Ks.txt'.format(folder))) for folder in folder_labels)

        print j_files
        print k_files
        j_filter_data = np.empty([0,5])
        ra1 = np.empty([0,1])
        ra2 = np.empty([0,1])

        k_filter_data = np.empty([0,5])
        dec1 = np.empty([0,1])
        dec2 = np.empty([0,1])

        print '\nPlease wait while all data is loaded from files...'
        
        # appends data from all J filter files in folder if multiple 
        for j in j_files:
                # generate numpy array from txt files
                new_data1 = np.genfromtxt(j, unpack = False)
                j_filter_data = np.vstack([j_filter_data, new_data1])
                print 'Data from J filter file', j, 'loaded...'
                print j_filter_data.shape
                
        ra1 = j_filter_data[:,3]
        dec1 = j_filter_data[:,4]
        print 'J Filter shape:', ra1.shape, dec1.shape

        # appends data from all Ks filter files in folder if multiple
        for k in k_files:
                new_data2 = np.genfromtxt(k, unpack = False)              
                k_filter_data = np.vstack([k_filter_data, new_data2])
                print 'Data from Ks filter file', k, 'loaded...'
                print k_filter_data.shape

        ra2 = k_filter_data[:,3]
        dec2 = k_filter_data[:,4]
        print 'Ks Filter shape:', ra2.shape, dec2.shape

        print 'Data from all files loaded.'
        print '\nPlease wait while objects are matched across the J and Ks Filter...'
        # j filter ra/dec info to be compared
        # in units of degrees
        obj_1 = ICRS(ra1, dec1, unit=(u.degree, u.degree))

        # k filter ra/dec info to be compared
        # in units of degrees
        obj_2 = ICRS(ra2, dec2, unit=(u.degree, u.degree))

        # This function will match all objects from obj_1 (j-filter) with an object in obj_2 (ks-filter)
        # By its nature, match_to_catalog_sky compares object data against catalog of sky, which would yield a closest match for every object
        # In our application, we compare two different sets of object data to each other, which should not guarantee a match
        # This means that we will get as many matches as there are objects in the smaller object data set (in this case, the j-filter will always have less objects)
        # This could be problematic since a "closest" match will be made relative to the available objects in obj_2 (ks-filter)
        # So a match does not necessarily constitute a match for us
        # To remedy this, I have run the matched objects through another test to compare the sum of differences against a set tolerance
        # This will ensure that all matches are within a controlled and tolerable closeness
        idx, d2d, d3d = obj_1.match_to_catalog_sky(obj_2) # match j band to k band since there are more objects in k

        # gets data matches from k-filter data based on matched indexes returned by match_to_catalog_sky
        matches = k_filter_data[idx,:]

        # appends all data columns for matched objects in a [:,10] array
        # j-filter
        #   0 -> Classification
        #   1 -> Aper_flux_3
        #   2 -> Aper_flux_3_err
        #   3 -> RA
        #   4 -> DEC
        # k-filter
        #   5 -> Classification
        #   6 -> Aper_flux_3
        #   7 -> Aper_flux_3_err
        #   8 -> RA
        #   9 -> DEC
        filter_matches = np.column_stack([j_filter_data, matches])

        # CHANGE THE TOLERANCE TO SEE WHAT WORKS BEST
        tolerance = 0.0001

        # compares sum of differences between RA/DEC values to set tolerance to ensure quality matches
        # see long comment above to see reasoning
        within_tol_index = ((abs(filter_matches[:,3]-filter_matches[:,8]) < tolerance) & (abs(filter_matches[:,4]-filter_matches[:,9]) < tolerance)).nonzero()
        
        stellar_obj_matches = (np.squeeze((filter_matches[within_tol_index,:]), axis=0))

        print '\nNumber of matches found', stellar_obj_matches.shape
        np.savetxt('Resources/J_Ks-matches.txt', stellar_obj_matches, fmt=['%.1f', '%.10f', '%.10f', '%.10f', '%.10f','%.1f', '%.10f', '%.10f', '%.10f', '%.10f'], delimiter=' ')
Example #52
0
 def __init__(self, center, radius):
     from astropy.coordinates import ICRS, Angle
     self.center = ICRS(center)
     self.radius = Angle(radius)
Example #53
0
 def test_radec_to_munu(self):
     radec = ICRS(ra=0.0*u.deg, dec=0.0*u.deg)
     munu = radec.transform_to(SDSSMuNu(stripe=10))
     assert munu.mu.value == 0.0
     assert munu.nu.value == 0.0
     assert munu.incl.value == 0.0
Example #54
0
def proc_m67(file_path=None,outdir=None, bias_fil=None):

    from astropy.coordinates import ICRS 
    from astropy.io import ascii
    from astropy import units as u
    from astropy.io.fits import getdata
    import xastropy.PH136.experiments.hrdiagram as hrd

    # Defaults
    if file_path == None: 
        file_path = 'Raw/'
    if outdir == None: 
        outdir = 'Science/'

    # Bias frame
    if bias_fil == None:
        bias_fil = 'Bias.fits'
    bias_img,bias_head = getdata(bias_fil,0,header=True)
    

    # Read Log
    data = ascii.read('simple.log',delimiter='|')
    nfil = len(data)
    all_coord = ICRS(ra=data['RA'], dec=data['DEC'], unit=(u.hour,u.degree))

    # M67 coords
    m67_rac = '08:54:24'
    m67_decc = '+11:49:00'
    m67_c = ICRS(m67_rac, m67_decc, unit=(u.hour,u.degree))

    # Find all M67
    sep = (m67_c.separation(all_coord)).degree
    im67, = np.where( sep < 1. ) # 1 degree
    m67 = data[im67]

    # 5 positions
    m67_ra = ['08:52:02.2', '08:52:15.3', '08:51:49.9', '08:51:50.0', '08:52:16.2']
    m67_dec = ['+11:52:41.0', '+11:55:51.0', '+11:55:53.0', '+11:49:38.0', '+11:49:40.0']
    m67_pointings = ICRS(ra=m67_ra, dec=m67_dec, unit=(u.hour, u.degree))

    # Filters
    all_filt=np.array(m67['Filter'])
    filters,ifilt = np.unique(all_filt,return_index=True)

    # Loop on Filterse
    all_fil = []
    for ff in filters:

        # Load Sky frame
        skyfil = 'Sky_'+ff+'.fits'
        sky_img,head = getdata(skyfil,0,header=True)

        # Images
        idx = np.where(m67['Filter'] == ff) 

        # Loop on images
        for kk in np.concatenate(idx,axis=0):
            # Read
            img,head = getdata(m67[kk]['File'],0,header=True)

            # Bias subtract
            img = img - bias_img

            # Trim
            timg = hrd.trimflip_img(img)

            # Flat field
            timg = timg / sky_img

            # Normalize by exposure
            timg = timg / m67[kk]['Exp']

            # Filename
            coord = ICRS(head['RA'], head['DEC'], unit=(u.hour,u.degree))
            sep = (coord.separation(m67_pointings)).degree
            ipos = np.argmin(sep)
            outfil = outdir+'M67_C'+str(ipos)+'_t'+str(int(m67[kk]['Exp']))+'_'+ff+'.fits'

            # Check for duplicate
            flg_skip = 0
            mt = [i for i in range(len(all_fil)) if all_fil[i] == outfil] 
            if len(mt) > 0:
                print 'Duplicate image', outfil
                print 'Skipping...'
                continue
            all_fil.append(outfil)
            

            # Write
            print 'Writing ', outfil
            fits.writeto(outfil, timg, clobber=True)
            
    return
Example #55
0
def proc_sa104(file_path=None,outdir=None, bias_fil=None):

    from astropy.coordinates import ICRS 
    from astropy.io import ascii
    from astropy import units as u
    from astropy.io.fits import getdata
    import xastropy.PH136.experiments.hrdiagram as hrd

    # Defaults
    if file_path == None: 
        file_path = 'Raw/'
    if outdir == None: 
        outdir = 'Std/'

    # Bias frame
    if bias_fil == None:
        bias_fil = 'Bias.fits'
    bias_img,bias_head = getdata(bias_fil,0,header=True)
    

    # Read Log
    data = ascii.read('simple.log',delimiter='|')
    nfil = len(data)
    all_coord = ICRS(ra=data['RA'], dec=data['DEC'], unit=(u.hour,u.degree))

    # M67 coords
    sa104_rac = '12:43:44.3'
    sa104_decc = '-00:29:40.0'
    sa104_c = ICRS(sa104_rac, sa104_decc, unit=(u.hour,u.degree))

    # Find all SA 104
    sep = (sa104_c.separation(all_coord)).degree
    isa104, = np.where( sep < 1. ) # 1 degree
    sa104 = data[isa104]

    # Filters
    all_filt=np.array(sa104['Filter'])
    filters,ifilt = np.unique(all_filt,return_index=True)

    # Loop on Filterse
    all_fil = []
    for ff in filters:

        # Load Sky frame
        skyfil = 'Sky_'+ff+'.fits'
        sky_img,head = getdata(skyfil,0,header=True)

        # Images
        idx = np.where(sa104['Filter'] == ff) 

        # Loop on images
        for kk in np.concatenate(idx,axis=0):
            # Read
            img,head = getdata(sa104[kk]['File'],0,header=True)

            # Bias subtract
            img = img - bias_img

            # Trim
            timg = hrd.trimflip_img(img)

            # Flat field
            timg = timg / sky_img

            # Normalize by exposure
            timg = timg / sa104[kk]['Exp']

            # Filename
            outfil = outdir+'SA104_t'+str(int(sa104[kk]['Exp']))+'_'+ff+'.fits'

            # Check for duplicate
            flg_skip = 0
            mt = [i for i in range(len(all_fil)) if all_fil[i] == outfil] 
            if len(mt) > 0:
                print 'Duplicate image', outfil
                print 'Skipping...'
                continue
            all_fil.append(outfil)
            

            # Write
            print 'Writing ', outfil
            fits.writeto(outfil, timg, head, clobber=True)
            
    return
Example #56
0
 def set_targets(self, v_plotter):
     """Setup the single target."""
     t = Target(name=self.opts.target, position=ICRS.from_name(self.opts.target))
     self.log.log(_ll(2), t)
     v_plotter.add(t)
Example #57
0
class Secat:

   """

   The __init__ method has been changed to return something like a record
   array, which has the same number of rows as the old 2D float array, but
   which stores each row as a single tuple.  It is thus a 1D array, sort of
   like a structure array in C.  The columns can be accessed by field name,
   which for now is just 'f0', 'f1', etc., unless the input catalog is in
   SExtractor's FITS LDAC format, in which case the field names actually
   correspond to the SExtractor variable names.

   The code used to expect the old 2D float array format.  It should have
   all been updated, but there may still be some issues.

   """

   def __init__(self, incat, catformat='ldac', verbose=True, namecol=None,
                racol=None, deccol=None, rafield=None, decfield=None,
                usecols=False):
      """
      This method gets called when the user types something like
         secat = Secat(infile)

      Inputs:
         incat     - input table data.  This can be in one of two forms:
                       1. a file containing the catalog (most common)
                       2. a Table instance containing the catalog data
         catformat - format of the input file, if incat is a filename.  
                     The options are:
                      ascii    - 
                      asciitab -
                      ldac     - 
                      sdssfits - 
                      secat    -
                     NOTE: this parameter is not used if incat is a Table
                      rather than the name of an input file
      """

      """ Set a flag showing whether the file has been modified """
      self.modified = False

      """ Set other default values """
      self.radec = None
      self.rafield = None
      self.decfield = None
      self.centpos = None
      self.galmask = None
      self.starmask = None

      """
      Start by loading the catalog information
      """
      incattype = (str(type(incat))).split('.')[-1]
      if incattype[0:3] == 'Tab' or incattype[0:4] == 'FITS':
         self.data = incat.copy()
         if rafield:
            self.rafield = rafield
         if decfield:
            self.decfield = decfield
         self.nrows = len(incat)
         self.ncols = len(incat.columns)
         self.catformat = 'Table'

      elif isinstance(incat, str):
         self.load_from_file(incat, catformat=catformat, verbose=verbose,
                             namecol=namecol, racol=racol, deccol=deccol,
                             rafield=rafield, decfield=decfield,
                             usecols=usecols)
      else:
         print('')
         print('ERROR: input catalog must either be a filename or a Table')
         print(' Input catalog type is' + str(type(incat)))
         print('')
         return None

   #-----------------------------------------------------------------------

   def load_from_file(self, incat, catformat='ldac', verbose=True, namecol=None,
                      racol=None, deccol=None, rafield=None, decfield=None,
                      usecols=False):

      if verbose:
         print ""
         print "Loading data from catalog file %s" % incat
         print "-----------------------------------------------"
         print "Expected catalog format: %s" % catformat
         print ""

      """
      Define a flag for successful reading of input catalog
      """
      read_success = True

      """ Read in catalog in a manner appropriate to the catformat """
      if catformat == 'secat':
         try:
            self.data = ascii.read(incat)
            ncols = len(self.data.colnames)
            nrows = len(self.data)
            """ Set the field names """
            self.rafield  = 'ALPHA_J2000'
            self.decfield = 'DELTA_J2000'
         except:
            print "  ERROR. Problem in loading file %s" % incat
            print "  Check to make sure filename matches an existing file."
            print ""
            print "  This also may have failed if the input file is in the"
            print "   SExtractor FITS LDAC format.  Checking that..."
            print ""
            read_success = False

      elif catformat == 'asciitab':
         f = open(incat)
         foo = f.readline()
         f.close()
         if foo[0] == '#':
            try:
               self.data = ascii.read(incat, guess=False,
                                      format='commented_header')
            except:
               print('')
               print('ERROR: Could not read data from %s' % incat)
               print(' Tried using "commented_header" format but failed') 
               print(' Please check input file.')
               print('')
               raise IOError
         else:
            try:
               self.data = ascii.read(incat)
            except:
               print ''
               print 'ERROR: Could not properly read data from %s' % incat
               print 'Tried using the automatic formatting but failed'
               print ' Please check input file.'
               print ''
               raise IOError
         ncols = len(self.data.colnames)
         nrows = len(self.data)
         """ Set the field names """
         if rafield:
            self.rafield = rafield
         if decfield:
            self.decfield = decfield

      elif catformat=='ascii':
         """ ASCII format """
         try:
            """ Set up the data format in the catalog """
            foo = np.loadtxt(incat,dtype='S30')
            ncols = foo.shape[1]
            del foo
            coltypes = np.ones(ncols,dtype='S3')
            coltypes[:] = 'f8'
            if namecol is not None:
               print "Object name column: %d" % namecol
               coltypes[namecol] = 'S30'
            colstr = ''
            for i in range(ncols):
               colstr = '%s,%s' % (colstr,coltypes[i])
            colstr = colstr[1:]
            dt = np.dtype(colstr)

            """ Actually read in the data """
            self.informat = 'ascii'
            self.data = np.loadtxt(incat,dtype=dt)
            nrows = self.data.shape[0]

            """ Set the field names """
            if racol is not None:
               self.rafield = 'f%d' % racol
            else:
               self.rafield = None
            if deccol is not None:
               self.decfield = 'f%d' % deccol
            else:
               self.decfield = None
            if namecol is not None:
               self.namefield = 'f%d' % namecol
            else:
               self.namefield = None

         except:
            print "  ERROR. Problem in loading file %s" % incat
            print "  Check to make sure filename matches an existing file."
            print "  "
            print "  This may have failed if there is a string column in"
            print "   the input catalog (e.g., for an object name).  "
            print "  If this is the case, use the namecol to indicate which "
            print "   column contains the string values (column numbers are "
            print "   zero-indexed)"
            print ""
            print "  This also may have failed if the input file is in the"
            print "   SExtractor FITS LDAC format.  Checking that..."
            print ""
            read_success = False

      elif catformat.lower()=='ldac' or read_success==False:
         try:
            self.data = Table.read(incat, format='fits', hdu=2)
         except:
            print "  ERROR. Problem in loading file %s" % incat
            print "  Check to make sure filename matches an existing file."
            print "  "
            return
         self.informat = 'ldac'
         nrows = len(self.data)
         ncols = len(self.data.columns)

         """ Set the field names """
         self.rafield = 'ALPHA_J2000'
         self.decfield = 'DELTA_J2000'

      elif catformat.lower()=='sdssfits' or read_success==False:
         try:
            self.data = Table.read(incat, format='fits', hdu=1)
         except:
            print "  ERROR. Problem in loading file %s" % incat
            print "  Check to make sure filename matches an existing file."
            print "  "
            return
         self.informat = 'sdss'
         nrows = len(self.data)
         ncols = len(self.data.columns)

         """ Set the field names """
         self.rafield = 'ra'
         self.decfield = 'dec'

         """
         Split the stars from the galaxies, according to the SDSS 
         classification.
         In the SDSS scheme, type=3 is a galaxy and type=6 is a star
         """
         if 'type' in self.data.colnames:
            oclass = self.data['type']
         elif 'type_r' in self.data.colnames:
            oclass = self.data['type_r']
         else:
            oclass = None
   
         if oclass is not None:
            self.galmask = oclass == 3
            self.starmask = oclass == 6
         else:
            self.galmask = np.ones(dtype=bool)
            self.starmask = None
         print('Read SDSS catalog from %s' % incat)
         print('Number of galaxies: %5d' % self.galmask.sum())
         if self.starmask is not None:
            print('Number of stars:    %5d' % self.starmask.sum())

      else:
         print ''
         print 'Unrecognized format.  Must be one of:'
         print '  ascii, secat, ldac, sdssfits'
         sys.exit()

      if verbose:
         print "Number of rows:    %d" % nrows
         print "Number of columns: %d" % ncols
         if self.rafield is not None:
            print 'RA field name:  %s' % self.rafield
         if self.decfield is not None:
            print 'Dec field name: %s' % self.decfield

      self.infile = incat
      self.catformat = catformat
      self.nrows = nrows
      self.ncols = ncols
      
   #-----------------------------------------------------------------------

   def close_ldac(self):
      """
      Closes the catalog.  If the catalog is in fits format and it has
      been modified (as shown by the modified parameter in this Secat class)
      then use flush rather than close.
      """

      """ Close the file if it is in the expected format """
      if self.informat == 'ldac':
         if self.modified:
            self.hdu.flush()
            print 'Updating input fits LDAC file: %s' % self.infile
         else:
            self.hdu.close()
      else:
         print ''
         print 'WARNING. Calling close_ldac but file is not in ldac format'
         print ''

   #----------------------------------------------------------------------

   def make_magmask(self, magname, mfaint=None, mbright=None):
      """
      Makes a mask that is True for magnitudes brighter than mfaint and
       fainter than mbright.
      Note that one of these two could have the value None, in which case
       it would be ignored.  For example, if mbright is None, then the mask
       will be True for all galaxies brighter than mfaint

      Inputs:
       magname - the name in the catalog for the column that represents the
                  object magnitudes.  This could be something like, e.g., 'r' 
                  or 'MAG_AUTO'
      """

      mag = self.data[magname]
      if mfaint is None and mbright is None:
         self.magmask = np.ones(self.nrows,dtype=bool)
      elif mfaint is None:
         self.magmask = mag >= mbright
      elif mbright is None:
         self.magmask = mag <= mfaint
      else:
         self.magmask = (mag >= mbright) & (mag <= mfaint)

   #-----------------------------------------------------------------------

   def get_radec(self):
      """
      Extracts the RA and Dec information from the data container.  This
      is not necessary, and some of the data containers may not even have
      WCS info, but extracting the coordinates if it does simplifies some
      later tasks.
      """

      """ Extract the information into the new containers """
      self.ra = None
      self.dec = None
      if self.rafield is not None:
         try:
            self.ra  = self.data[self.rafield].copy()
         except:
            try:
               self.ra = self.data['x_world'].copy()
            except:
               self.ra = None
      if self.decfield is not None:
         try:
            self.dec = self.data[self.decfield].copy()
         except:
            try:
               self.dec = self.data['y_world'].copy()
            except:
               self.dec = None

      """ 
      Put data into a SkyCoords container for easy coordinate-based calculations
      """
      if (self.ra is not None) and (self.dec is not None):
         """ 
         Determine whether the RA coordinate is in hours or in degrees
         For now this test is made simple: if the format of the RA data is
          a string, then the data is expected to be in hms format, otherwise
          expect decimal degrees.
         """
         if type(self.ra[0]) is str or type(self.ra[0]) is np.string_:
            raunit = u.hourangle
         else:
            raunit = u.deg
         self.radec = SkyCoord(self.ra,self.dec,unit=(raunit,u.deg))

      """ 
      If radec has not been set, report this information
      (consider raising an exception in future versions of the code)
      """
      if self.radec is None:
         print ''
         print 'WARNING: get_radec was called but RA and Dec information was'
         print '         not found.  Please check the format of your catalog.'
         print ''

   #----------------------------------------------------------------------

   def read_centpos(self, posfile, verbose=False):
      """
      Reads a position in from a file and converts it to an astropy SkyCoord
      format.

      NOTE: right now this is hard-wired to just read in a file in the 
      standard Keck starlist format:

          label rahr ramin rasec decdeg decamin decasec equinox

      which matches the *.pos in CDF's Lenses/Data/* directories

      Inputs:
       posfile - file containing the RA and dec
      """

      """ Read the data from the file """
      posinfo = ascii.read(posfile, 
                           names=['object', 'rahr', 'ramin', 'rasec',
                                  'decdeg', 'decamin', 'decasec', 'equinox'])

      """ Convert to SkyCoord format """
      i = posinfo[0]
      ra  = '%d:%d:%f' % (i['rahr'], i['ramin'], i['rasec'])
      dec = '%d:%d:%f' % (i['decdeg'], i['decamin'], i['decasec'])
      radec = SkyCoord(ra, dec, unit=(u.hourangle, u.deg))

      """ Print out information if requested """
      if verbose:
         print('')
         print('Object: %s' % i['object'])
         print('Coordinates: %s %s' % \
                  (radec.ra.to_string(unit=u.hourangle, decimal=False,
                                      sep=':', precision=3, pad=True),
                   radec.dec.to_string(decimal=False, sep=':', precision=3,
                                       alwayssign=True, pad=True)))

      """ Save the output within the class """
      self.centpos = radec

   #----------------------------------------------------------------------

   def sort_by_pos(self, centpos):
      """
      Sorts the catalog in terms of distance from some central position, which
      is passed as a SkyCoord variable (from astropy.coordinates)
      """

      """ First check to see that we actual have WCS information  """
      if self.radec is None:
         print ''
         print 'ERROR: sort_by_pos.  No WCS information in catalog'
         print ''
         return

      """ Otherwise, use the SkyCoords functionality to easily sort """
      sep   = self.radec.separation(centpos)
      try:
         offsets = self.radec.spherical_offsets_to(centpos)
      except:
         offsets = None
      ind   = np.argsort(sep.arcsec)
      if self.catformat == 'ascii':
         self.data = self.data[ind,:]
      else:
         print self.catformat
         self.data = self.data[ind]

      """ Also sort things that are outside the data table """
      self.radec   = self.radec[ind]
      self.ra      = self.ra[ind]
      self.dec     = self.ra[ind]
      self.sep     = sep[ind]
      if offsets is None:
         self.dx = None
         self.dy = None
      else:
         self.dx = (offsets[0].arcsecond)[ind]
         self.dy = (offsets[1].arcsecond)[ind]
      self.sortind = ind


   #-----------------------------------------------------------------------

   def make_reg_file(self, outfile, rcirc, color='green', fluxcol=None, 
                     fluxerrcol=None, labcol=None, labdx=0.0012, labdy=0.0012,
                     plot_high_snr=False, mask=None, snrgood=10.):
      """
      Uses the RA and Dec info in the catalog to make a region file that
      can be used with ds9.
      """

      """ 
      Start by putting the RA and Dec info into a somewhat more convenient
      format
      """

      self.get_radec()
      if self.radec is None:
         print ""
         print "ERROR: Could not read RA and Dec information from input file"
         return

      """ 
      If the flux information is given, then report on high SNR detections
      """

      ngood = 0
      snrmask = None
      if fluxcol is not None and fluxerrcol is not None:
         if self.informat == 'ldac':
            if type(fluxcol) is int:
               flux = self.data.field(fluxcol)
               fluxerr = self.data.field(fluxerrcol)
            else:
               flux = self.data[fluxcol]
               fluxerr = self.data[fluxerrcol]
         else:
            flux = self.data['f%d' %fluxcol]
            fluxerr = self.data['f%d' % fluxerrcol]
         snr = flux / fluxerr
         snrmask = snr>snrgood

      """ Mask the input data if requested """
      print('Total objects in catalog:        %d' % len(self.radec))
      if mask is not None:
         radec  = self.radec[mask]
         selmask = mask
         print('Objects selected by mask:        %d' % len(radec))
      else:
         radec = self.radec
         selmask = np.ones(len(radec), dtype=bool)
      ntot   = len(radec)
      radeg  = radec.ra.degree
      decdeg = radec.dec.degree

      """ Select the high SNR objects, if requested """
      if snrmask is not None:
         selsnrmask = (selmask) & (snrmask)
         radecgood = self.radec[selsnrmask]
         ngood = len(radecgood)
         print 'Of those, objects with SNR>%.1f: %d' % (snrgood,ngood)
         gradeg  = radecgood.ra.degree
         gdecdeg = radecgood.dec.degree
         
      """ Write the output region file """
      f = open(outfile,'w')
      f.write('global color=%s\n' % color)
      for i in range(ntot):
         f.write('fk5;circle(%10.6f,%+10.6f,%.1f")\n' % 
                 (radeg[i],decdeg[i],rcirc))
      if plot_high_snr and ngood>0:
         f.write('global color=red\n')
         for i in range(ngood):
            f.write('fk5;circle(%10.6f,%+10.6f,0.0011)\n' \
                       %(gradeg[i],gdecdeg[i]))

      """ Add labels if requested """
      if labcol is not None:
         lab = self.data[labcol][selmask]
         cosdec = np.cos(pi * self.dec[selmask] / 180.)
         xx = self.ra[selmask] + labdx * cosdec
         yy = self.dec[selmask] + labdy
         f.write('global color=%s\n' % color)
         for i in range(ntot):
            f.write('fk5;text(%10.6f,%+10.6f) # text={%s}\n'% \
                       (xx[i],yy[i],str(lab[i])))

      """ Wrap up """
      print "Wrote region file %s" % outfile
      f.close()


   #-----------------------------------------------------------------------

   #def plot_radec(self, symb='bo'):
   #-----------------------------------------------------------------------

   def plot_fwhm(self, fwhmcol='FWHM_IMAGE', magcol='MAG_AUTO', 
                 xlim=(0,15), ylim=(28,16)):
      """
      Plots FWHM vs. magnitude.  This can be used to find the stellar locus
      and, thus, determine the seeing.

      Inputs:
         fwhmcol - column name for the FWHM data.  Default = 'fwhm_image'
         magcol  - column name for the magnitude data.  Default = 'mag_auto'
         xlim    - initial limits for FWHM axis on plot.  Default = (0,15)
         ylim    - initial limits for mag axis on plot.  Default = (28,16)
      """

      try:
         fwhm = self.data[fwhmcol]
      except KeyError:
         print ''
         print 'Catalog does not contain a %d column' % fwhmcol
         print ''
         return
      try:
         mag = self.data[magcol]
      except KeyError:
         print ''
         print 'Catalog does not contain a %d column' % magcol
         print ''
         return
      plt.plot(fwhm,mag,'bo')
      plt.xlim(xlim)
      plt.ylim(ylim)
      plt.xlabel('FWHM (pixels)')
      plt.ylabel('Magnitude')
      plt.show()

   #-----------------------------------------------------------------------

   def plot_nhist(self, magcol='MAG_AUTO', usestarmask=False,
                  magmin=15, magmax=28, color='b', alpha=1.):
      """
      Plots a histogram of galaxy magnitudes (similar to a log N-log S plot)
      that can be used to determine the magnitude to which the catalog is 
      complete.  A minimum FWHM can be set in order to select objects that
      are likely to be galaxies, but this is not required.

      Inputs:
         magcol      - column containing the magnitudes. Default = 'mag_auto'
         usestarmask - when this parameter is set to True, then use the
                       starmask mask to select the galaxies.
                       NOTE: this means that the set_starmask method has to
                       have been run for each of the input catalogs, or
                       else all objects will be plotted
                       Default=False
         magmin      - minimum magnitude to use for the plot. Default=15
         magmax      - maximum magnitude to use for the plot. Default=28
      """

      """ Get the magnitudes to be plotted """
      if usestarmask:
         if self.starmask is None:
            print('')
            print('WARNING: you have set usestarmask=True but there are')
            print(' no stars selected by the starmask')
            print('Please make sure that set_starmask has been run BEFORE'
                  'runing plot_nhist')
            print(' if you want to use this mask')
            print('')
            return
         else:
            mag = (self.data[self.starmask==False][magcol]).copy()
      else:
         mag = self.data[magcol].copy()

      mag = mag[np.isfinite(mag)]

      """ Plot the histogram """
      nbins = int(2 * (magmax - magmin))
      plt.hist(mag,range=(magmin, magmax), bins=nbins, color=color, 
               alpha=alpha)

      del(mag)

   #-----------------------------------------------------------------------

   def match_radec(self, ra2, dec2, rmatch, dra2=0., ddec2=0., doplot=True):
      """

      *** UNDER CONSTRUCTION!  DO NOT USE YET. ***

      Given a list of ra,dec coordinates (ra2, dec2), possibly from a second
      catalog, and a match tolerance, find the matches to the catalog
      contained in self.data

      Inputs:
        ra2      - RA (decimal degrees) for catalog 
        dec2     - Dec (decimal degrees) for second catalog
        rmatch   - max distance for a valid match (arcsec)
        dra2     - optional offset in ARCSEC to apply to ra2, if there is a known
                   offset between the catalogs (default=0.0)
        ddec2    - optional offset in ARCSEC to apply to dec2, if there is a
                   known offset between the catalogs (default=0.0)
      """

      print ""
      print "Matching catalogs: basic info"
      print "--------------------------------------------"
      print " Catalog 1: %d coordinates" % self.ra.size
      print " Catalog 2: %d coordinates" % ra2.size

      """ Initialize containers for output information """
      ramatch  = np.zeros(self.ra.size)
      decmatch = np.zeros(self.ra.size)
      self.nmatch   = np.zeros(self.ra.size,dtype=int)
      self.matchdx  = np.zeros(self.ra.size)
      self.matchdy  = np.zeros(self.ra.size)
      self.indmatch = np.ones(self.ra.size,dtype=int) * -1

      """ Correct for known shifts """
      ra2 = ra2.copy() + dra2/(3600.*np.cos(dec2))
      dec2 = dec2.copy() + ddec2/3600.

      """ Loop over catalog """
      print ""
      print "Searching for matches..."
      print "------------------------------"
      for i in range(self.ra.size):
         dx,dy = coords.sky_to_darcsec(self.ra[i],self.dec[i],ra2,dec2)
         dpos = np.sqrt(dx**2 + dy**2)
         isort = np.argsort(dpos)
         if dpos[isort[0]]<=rmatch:
            ramatch[i]  = self.ra[i]
            decmatch[i] = self.dec[i]
            self.matchdx[i]  = dx[isort[0]]
            self.matchdy[i]  = dy[isort[0]]
            self.nmatch[i]   = dpos[dpos<=rmatch].size
            self.indmatch[i] = isort[0]
         del dx,dy,dpos
      print " Number of matches between the catalogs:  %d" % \
          (self.nmatch>0).sum()
      mra  = ramatch[self.nmatch>0]
      mdec = decmatch[self.nmatch>0]
      mdx  = self.matchdx[self.nmatch>0]
      mdy  = self.matchdy[self.nmatch>0]
      mdx0 = np.median(mdx)
      mdy0 = np.median(mdy)
      print " Median offset for matches (RA):  %+6.2f arcsec" % mdx0
      print " Median offset for matches (Dec): %+6.2f arcsec" % mdy0

      """ Plot up some offsets, if desired """
      if doplot:
         plt.figure(1)
         plt.scatter(mdx,mdy)
         plt.axis('scaled')
         plt.xlabel(r'$\Delta \alpha$ (arcsec)')
         plt.ylabel(r'$\Delta \delta$ (arcsec)')
         plt.title('Offsets between matched sources (rmatch = %5.2f)' % rmatch)
         plt.axvline(0.0,color='r')
         plt.axhline(0.0,color='r')
         plt.plot(np.array([mdx0]),np.array([mdy0]),'r*',ms=20)
         plt.xlim(-1.1*rmatch,1.1*rmatch)
         plt.ylim(-1.1*rmatch,1.1*rmatch)

         plt.figure(2)
         #
         ax1 = plt.subplot(221)
         plt.scatter(mra,mdy)
         plt.setp(ax1.get_xticklabels(), visible=False)
         plt.ylabel(r'$\Delta \delta$ (arcsec)')
         plt.axhline(0.0,color='r')
         #
         ax2 = plt.subplot(223, sharex=ax1)
         plt.scatter(mra,mdx)
         plt.xlabel(r'$\alpha$')
         plt.ylabel(r'$\Delta \alpha$ (arcsec)')
         plt.axhline(0.0,color='r')
         #
         ax3 = plt.subplot(222, sharey=ax1)
         plt.scatter(mdec,mdy)
         plt.axhline(0.0,color='r')
         plt.setp(ax3.get_xticklabels(), visible=False)
         plt.setp(ax3.get_yticklabels(), visible=False)
         #
         ax4 = plt.subplot(224)
         plt.scatter(mdec,mdx)
         plt.xlabel(r'$\delta$')
         plt.axhline(0.0,color='r')
         plt.setp(ax4.get_yticklabels(), visible=False)

         plt.show()

      """ Clean up """
      del ramatch,decmatch
      del mdx,mdy,mra,mdec

   #-----------------------------------------------------------------------

   def print_ccmap(self, outfile, verbose=True):
      """
      Prints out a file that can be used as the input for the pyraf ccmap
      task.  This file has 4 columns:  x  y  RA  Dec

      Inputs:
         outfile   -  output file to be used as input for ccmap
         verbose   -  print task info
      """
      if verbose:
         print ""
         print "Printing to file for use in ccmap:  %s" % outfile
         print ""
      f = open(outfile,'w')
      f.write('# (x,y) catalog: %s\n' % self.infile)
      f.write('# Astrometric catalog: %s\n' % self.matchcat)
      f.write('# Columns are x y RA Dec\n')
      for i in range(self.nmatch):
         f.write('%8.2f %8.2f  %11.7f %+11.7f\n' % \
                    (self.matchx[i],self.matchy[i],self.matchra[i],
                     self.matchdec[i]))
      f.close()

   #-----------------------------------------------------------------------

   def find_closest_xy(self, xast, yast, xcol, ycol):

      """
      Finds the closest match, in (x,y) space to each member of the astrometric
      catalog (represented by xast,yast).
      """

      self.matchind = np.zeros(xast.size, dtype=int)

      xfield = 'f%d' % xcol
      yfield = 'f%d' % ycol

      for i in range(xast.size):
         dx = xast[i] - self.data[xfield]
         dy = yast[i] - self.data[yfield]
         dpos = dx**2 + dy**2
         sindex = np.argsort(dpos)
         self.matchind[i] = sindex[0]

      self.matchdx = xast - self.data[xfield][self.matchind]
      self.matchdy = yast - self.data[yfield][self.matchind]

   #-----------------------------------------------------------------------

   def match_xy(self, xa, ya, max_offset=None, xcol=8, ycol=9, verbose=True):

      """
      Find the closest match to each astrometric catalog object and calculate the
      offsets.
      Do two loops, to deal with possible confusion of sources on first pass
      through
      """
      dxmed = 0
      dymed = 0
      for i in range(2):
         if verbose:
            print ''
            print 'Pass %d' % (i+1)
            print '------------------------'
         xa0 = xa - dxmed
         ya0 = ya - dymed
         self.find_closest_xy(xa0,ya0,xcol,ycol)
         dxmed = np.median(self.matchdx)
         dymed = np.median(self.matchdy)
         if max_offset is not None:
            dpos = np.sqrt(self.matchdx**2 + self.matchdy**2)
            goodmask = dpos<max_offset
            if verbose:
               print "Applying a maximum offset cut of %7.1f pixels" % max_offset
               print "Median shifts before clipping: %7.2f %7.2f" % (dxmed,dymed)
         else:
            goodmask = np.ones(xa.size,dtype=bool)
         dxm  = self.matchdx[goodmask]
         dym  = self.matchdy[goodmask]
         dxmed = np.median(dxm)
         dymed = np.median(dym)
         if verbose:
            print "Median shifts after pass:   %7.2f %7.2f" % (dxmed,dymed)

      """
      Transfer information into object and clean up
      """
      if verbose:
         print ''
         print 'Found %d astrometric objects within FOV of image' % xa.size
         print 'Matched %d objects to astrometric catalog.' % dxm.size
      self.nmatch = dxm.size
      self.goodmask = goodmask.copy()
      self.matchind = self.matchind[goodmask]
      del xa0,ya0,goodmask

   #-----------------------------------------------------------------------

   def match_fits_to_ast(self, fitsfile, astcat, outfile=None, max_offset=None, 
                         racol=1, deccol=2, xcol=8, ycol=9, 
                         doplot=True, edgedist=50., imhdu=0, verbose=True):

      """
      Given the fits file from which this object (self) was defined 
      and an astrometric catalog, find the closest matches of the 
      astrometric objects to those contained in this object, using the WCS 
      information in the fits header.
      """

      if(verbose):
         print "Running match_fits_to_ast with:"
         print "   fitsfile = %s" % fitsfile
         print "   astcat   = %s" % astcat
      self.infits = fitsfile
      self.matchcat = astcat

      """
      Start by opening the fits file and reading the appropriate columns from
      the catalogs
      """
      hdulist = imf.open_fits(fitsfile)
      hdr = hdulist[imhdu].header
      if verbose:
         print ""
         hdulist.info()

      """
      Select the astrometric catalog objects that fall within the fits file FOV
      (at least with its current WCS)
      """
      raa,deca,xa,ya,astmask = select_good_ast(astcat,hdr,racol,deccol,edgedist)
      if verbose:
         print 'Found %d astrometric objects within FOV of image' % raa.size
         
      """
      Find the closest match to each astrometric catalog object
      """
      self.match_xy(xa,ya,max_offset,xcol,ycol,verbose)

      """ Transfer info about matches into the object """
      xfield = 'f%d' % xcol
      yfield = 'f%d' % ycol
      self.astmask  = astmask.copy()
      self.matchx   = self.data[xfield][self.matchind].copy()
      self.matchy   = self.data[yfield][self.matchind].copy()
      self.matchra  = raa[self.goodmask].copy()
      self.matchdec = deca[self.goodmask].copy()
      self.matchdx  = self.matchdx[self.goodmask]
      self.matchdy  = self.matchdy[self.goodmask]

      """ Plot the offsets if desired """
      if doplot:
         dxmed = np.median(self.matchdx)
         dymed = np.median(self.matchdx)
         plt.figure()
         plt.scatter(self.matchdx,self.matchdy)
         plt.xlabel('x offset (pix)')
         plt.ylabel('y offset (pix)')
         plt.axhline(color='k')
         plt.axvline(color='k')
         plt.axvline(dxmed,color='r')
         plt.axhline(dymed,color='r')
         print ""
         print "Black lines represent x=0 and y=0 axes"
         print "Red lines show median offsets of dx_med=%7.2f and dy_med=%7.2f" \
             % (dxmed,dymed)
         #plt.show()

      """ Write the output file, in a format appropriate for input to ccmap """
      if outfile is not None:
         self.print_ccmap(outfile,verbose)

      """ Clean up """
      hdulist.close()
      del hdr,raa,deca,xa,ya,astmask

   # -----------------------------------------------------------------------

   def set_starmask(self, mask):
      """
      Takes the input mask and assigns it to an internal mask associated
      with this instance of the Secat class.
      The internal mask is called starmask and has values of True for objects
      that have been identified as stars by the provided external mask.

      The external mask will be based on some characteristics in the catalog.
      Examples could be objects with a SExtractor CLASS_STAR value greater
       than 0.7, or a FWHM_IMAGE less than a certain value, or ...
      """

      self.starmask = mask
def match_Stars(fits_file, save_location='./', nobsfile='obsout', standard_stars_file='standard_stars.dat', out_nobsfile='final_obsout', header_line=5, SN_coord=None, dist_treshold = 0.0004, sel_3D=True ):
    '''- fits_file is the full path of the reference fits file.
    - save_location is the directory in which the output will be saved.
    - nobsfile is the full path of the nobsfile.
    - standard_stars_file is the full path of the standard stars file.
    - phot_band is the photometric reference band.
    - index_band is the indec of the band in the standard_stars_file.
    - offset is an integer which changes the nobsfile line that is used to name the star. e.g, if g is the reference but the band order in 
    nobsfile is u then g the offset should be'1'
    - header_line is the line number of the header of the standard_stars_file
    - dist_treshold the match is discarded if the stars are farther apart than this value (degrees)
    
    The output is four images showing the matched stars plus 'final_obsout', which is the nobsfile with the star names
    in place.'''

    import pyfits
    hdulist = pyfits.open(fits_file)
    prihdr = hdulist[0].header
    phot_band = prihdr['filter1']
    index_band = phot_band.lower()
    print phot_band

    if SN_coord==None:
        SN_c = ICRS(prihdr['RA']+prihdr['DEC'], unit = (u.hourangle, u.degree))
        SN_coord = [SN_c.ra.degree, SN_c.dec.degree]

    obsout_file = nobsfile
    gri_file = standard_stars_file

    if os.path.isfile(fits_file) == True: 
        w = WCS(fits_file)
        ##
        obsout = genfromtxt(obsout_file,dtype=None, missing_values='INDEF')
        gri = genfromtxt(gri_file,dtype=None, missing_values='INDEF', skip_header=header_line-1,names=True)

        ##
        def marker_size_(in_mag):
            return 20*(nanmax(in_mag)-in_mag)/(nanmax(in_mag)-nanmin(in_mag))
        def select_phot_(in_v,phot_out,phot_list):
            out_v = copy(in_v)
            for i in range(size(out_v)): 
                if phot_list[i]!=phot_out:
                    out_v[i]=nan
            return out_v
        ##
        figure(figsize=(8,8))
        # all_pix2world is from http://docs.astropy.org/en/stable/wcs/
        lon, lat =w.all_pix2world(obsout['f4'], obsout['f5'], 0)
        
        lon = select_phot_( lon , phot_out=phot_band, phot_list=obsout['f1'])
        lat = select_phot_( lat , phot_out=phot_band, phot_list=obsout['f1'])
        scatter(lon,lat,marker='o',s=marker_size_(obsout['f6'])  )
        scatter(gri['RA'],gri['dec'],color='r',marker='o',s=marker_size_(gri[index_band])    )
        plot(SN_coord[0],SN_coord[1],'+g')
        gca().invert_yaxis()
        savefig(save_location+'out1.pdf')
        #
        # match_to_catalog_sky is from https://www.sites.google.com/site/mrpaulhancock/blog/theage-oldproblemofcross-matchingastronomicalsources
        
        indx1 = [i for i in range(size(lon)) if not isnan(lon*lat)[i]]
        
        cat1_ra = lon[indx1]
        cat1_dec = lat[indx1]
        cat2_ra =  gri['RA']
        cat2_dec = gri['dec']

        cat3_ra = [SN_coord[0]]
        cat3_dec = [SN_coord[1]]
        
        cat1 = ICRS(cat1_ra,cat1_dec,unit = (u.degree,u.degree))
        cat2 = ICRS(cat2_ra,cat2_dec,unit = (u.degree,u.degree))
        cat3 = ICRS(cat3_ra,cat3_dec,unit = (u.degree,u.degree))
        index_list,dist2d,dist3d = cat2.match_to_catalog_sky(cat1)

        index_list_SN,dist2d_3,dist3d_3 = cat3.match_to_catalog_sky(cat1)
        
        indexes_gri = []
        indexes_obsout = []
        distances=[]
        for i in range(size(gri)):
            j = indx1[index_list[i]]
            cos_dec = cos(lat[j]*pi/(180.))
            dist_ = ( sqrt(sum(array([(lon[j] - gri['RA'][i])*cos_dec  ,   lat[j] - gri['dec'][i]])**2)) )
            if dist_ < dist_treshold:
                indexes_gri.append(i)
                indexes_obsout.append(j)
            distances.append(dist_)

        if sel_3D:

            valuesA_=[]
            valuesB_=[]
            for i in indexes_gri:
                j = indx1[index_list[i]]
                valuesA_.append(obsout['f6'][j])
                valuesB_.append(gri[index_band][i])
            valuesA_=array(valuesA_);valuesB_=array(valuesB_) 
            sigma_res =  median(abs(valuesA_- valuesB_ - median(valuesA_ - valuesB_)))
            res_ =  abs(valuesA_- valuesB_ - median(valuesA_ - valuesB_))
    
            indexes_gri_new = []
            indexes_obsout = []
            distances=[]
            ii=0
            for i in indexes_gri:
                j = indx1[index_list[i]]
                cos_dec = cos(lat[j]*pi/(180.))
                dist_ = ( sqrt(sum(array([(lon[j] - gri['RA'][i])*cos_dec  ,   lat[j] - gri['dec'][i]])**2)) )
                if dist_ < dist_treshold:
                    if not sel_3D or res_[ii] < 4.*sigma_res:
                        indexes_gri_new.append(i)
                        indexes_obsout.append(j)
                distances.append(dist_)
                ii+=1
            indexes_gri = indexes_gri_new

            indexes_gri_new = []
            indexes_obsout = []
            distances=[]
            ii=0
            for i in indexes_gri:
                j = indx1[index_list[i]]
                cos_dec = cos(lat[j]*pi/(180.))
                dist_ = ( sqrt(sum(array([(lon[j] - gri['RA'][i])*cos_dec  ,   lat[j] - gri['dec'][i]])**2)) )
                if dist_ < dist_treshold:
                    if not sel_3D or res_[ii] < 3.*sigma_res:
                        indexes_gri_new.append(i)
                        indexes_obsout.append(j)
                distances.append(dist_)
                ii+=1
            indexes_gri = indexes_gri_new

        indexes_obsout_SN = nan
        j = indx1[index_list_SN[0]]
        cos_dec = cos(lat[j]*pi/(180.))
        dist_ = ( sqrt(sum(array([(lon[j] - SN_coord[0])*cos_dec  ,   lat[j] - SN_coord[1]])**2)) )
        if dist_ < dist_treshold:
            #indexes_gri.append(i)
            indexes_obsout_SN = j

        figure()
        hist(distances,1000,label='catalog stars')
        plot([dist_ ,dist_],[0,1],'g', linewidth=10, label='SN')
        plot([dist_treshold,dist_treshold],[0,3],':k', label='dist_treshold')
        xlim((0,0.002))
        xlabel('distance (degree)')
        ylabel('N stars')
        legend()
        savefig(save_location+'out2.pdf')
        #
        figure(figsize=(8,8))
        offset = list(obsout['f1']).index(phot_band)
        for i in indexes_gri:
            j = indx1[index_list[i]]
            obsout[j-offset][0]=gri[i][0]
            scatter(lon[j],lat[j],marker='o',s=marker_size_(obsout['f6'])[j]  )
            scatter(gri['RA'][i],gri['dec'][i],color='r',marker='o',s=marker_size_(gri[index_band])[i]    )
            plot(SN_coord[0],SN_coord[1],'+g')
            plot([lon[j],gri['RA'][i]],[lat[j],gri['dec'][i]])
        if not isnan(indexes_obsout_SN):
            j=indexes_obsout_SN
            obsout[j-offset][0] = 'SN'
            scatter(lon[j],lat[j],marker='o',color='g',s=marker_size_(obsout['f6'])[j]  )
        gca().invert_yaxis()
        savefig(save_location+'out3.pdf')
        #
        figure()
        for i in indexes_gri:
            j = indx1[index_list[i]]
            plot( obsout['f6'][j],gri[index_band][i],'bo')
        savefig(save_location+'out4.pdf')
        
        ## Save final_obsout            

        f=open(save_location+out_nobsfile,'w+')
        for j in range(len(obsout)):
            for k in range(len(obsout[j])):
                if k <len(obsout[j])-1:
                    f.write(str(obsout[j][k]).replace('nan','INDEF').replace('False','INDEF'))
                    for h in range(13-len(str(obsout[j][k]).replace('nan','INDEF').replace('False','INDEF'))):
                        f.write(' ')
                else:
                    f.write(str(obsout[j][k]).replace('nan','INDEF').replace('False','INDEF')+'\n')
        f.close()    

    else:
        print fits_file + 'not found'
    return