Ejemplo n.º 1
0
def test_wcs_dropping():
    wcs = WCS(naxis=4)
    wcs.wcs.pc = np.zeros([4, 4])
    np.fill_diagonal(wcs.wcs.pc, np.arange(1, 5))
    pc = wcs.wcs.pc  # for later use below

    dropped = wcs.dropaxis(0)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([2, 3, 4]))
    dropped = wcs.dropaxis(1)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 3, 4]))
    dropped = wcs.dropaxis(2)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 2, 4]))
    dropped = wcs.dropaxis(3)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 2, 3]))

    wcs = WCS(naxis=4)
    wcs.wcs.cd = pc

    dropped = wcs.dropaxis(0)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([2, 3, 4]))
    dropped = wcs.dropaxis(1)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 3, 4]))
    dropped = wcs.dropaxis(2)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 2, 4]))
    dropped = wcs.dropaxis(3)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 2, 3]))
Ejemplo n.º 2
0
def test_distortion_correlations():

    filename = get_pkg_data_filename('../../tests/data/sip.fits')
    w = WCS(filename)
    assert_equal(w.axis_correlation_matrix, True)

    # Changing PC to an identity matrix doesn't change anything since
    # distortions are still present.
    w.wcs.pc = [[1, 0], [0, 1]]
    assert_equal(w.axis_correlation_matrix, True)

    # Nor does changing the name of the axes to make them non-celestial
    w.wcs.ctype = ['X', 'Y']
    assert_equal(w.axis_correlation_matrix, True)

    # However once we turn off the distortions the matrix changes
    w.sip = None
    assert_equal(w.axis_correlation_matrix, [[True, False], [False, True]])

    # If we go back to celestial coordinates then the matrix is all True again
    w.wcs.ctype = ['RA---TAN', 'DEC--TAN']
    assert_equal(w.axis_correlation_matrix, True)

    # Or if we change to X/Y but have a non-identity PC
    w.wcs.pc = [[0.9, -0.1], [0.1, 0.9]]
    w.wcs.ctype = ['X', 'Y']
    assert_equal(w.axis_correlation_matrix, True)
Ejemplo n.º 3
0
def test_skycoord_to_pixel_swapped():

    # Regression test for a bug that caused skycoord_to_pixel and
    # pixel_to_skycoord to not work correctly if the axes were swapped in the
    # WCS.

    # Import astropy.coordinates here to avoid circular imports
    from astropy.coordinates import SkyCoord

    header = get_pkg_data_contents('maps/1904-66_TAN.hdr', encoding='binary')
    wcs = WCS(header)

    wcs_swapped = wcs.sub([WCSSUB_LATITUDE, WCSSUB_LONGITUDE])

    ref = SkyCoord(0.1 * u.deg, -89. * u.deg, frame='icrs')

    xp1, yp1 = skycoord_to_pixel(ref, wcs)
    xp2, yp2 = skycoord_to_pixel(ref, wcs_swapped)

    assert_allclose(xp1, xp2)
    assert_allclose(yp1, yp2)

    # WCS is in FK5 so we need to transform back to ICRS
    new1 = pixel_to_skycoord(xp1, yp1, wcs).transform_to('icrs')
    new2 = pixel_to_skycoord(xp1, yp1, wcs_swapped).transform_to('icrs')

    assert_allclose(new1.ra.degree, new2.ra.degree)
    assert_allclose(new1.dec.degree, new2.dec.degree)
Ejemplo n.º 4
0
def test_slice():
    mywcs = WCS(naxis=2)
    mywcs.wcs.crval = [1, 1]
    mywcs.wcs.cdelt = [0.1, 0.1]
    mywcs.wcs.crpix = [1, 1]
    mywcs._naxis = [1000, 500]
    pscale = 0.1 # from cdelt

    slice_wcs = mywcs.slice([slice(1, None), slice(0, None)])
    assert np.all(slice_wcs.wcs.crpix == np.array([1, 0]))
    assert slice_wcs._naxis == [1000, 499]

    # test that CRPIX maps to CRVAL:
    assert_allclose(
        slice_wcs.wcs_pix2world(*slice_wcs.wcs.crpix, 1),
        slice_wcs.wcs.crval, rtol=0.0, atol=1e-6 * pscale
    )

    slice_wcs = mywcs.slice([slice(1, None, 2), slice(0, None, 4)])
    assert np.all(slice_wcs.wcs.crpix == np.array([0.625, 0.25]))
    assert np.all(slice_wcs.wcs.cdelt == np.array([0.4, 0.2]))
    assert slice_wcs._naxis == [250, 250]

    slice_wcs = mywcs.slice([slice(None, None, 2), slice(0, None, 2)])
    assert np.all(slice_wcs.wcs.cdelt == np.array([0.2, 0.2]))
    assert slice_wcs._naxis == [500, 250]

    # Non-integral values do not alter the naxis attribute
    slice_wcs = mywcs.slice([slice(50.), slice(20.)])
    assert slice_wcs._naxis == [1000, 500]
    slice_wcs = mywcs.slice([slice(50.), slice(20)])
    assert slice_wcs._naxis == [20, 500]
    slice_wcs = mywcs.slice([slice(50), slice(20.5)])
    assert slice_wcs._naxis == [1000, 50]
Ejemplo n.º 5
0
def test_slice_fitsorder():
    mywcs = WCS(naxis=2)
    mywcs.wcs.crval = [1, 1]
    mywcs.wcs.cdelt = [0.1, 0.1]
    mywcs.wcs.crpix = [1, 1]

    slice_wcs = mywcs.slice([slice(1, None), slice(0, None)], numpy_order=False)
    assert np.all(slice_wcs.wcs.crpix == np.array([0, 1]))

    slice_wcs = mywcs.slice([slice(1, None, 2), slice(0, None, 4)], numpy_order=False)
    assert np.all(slice_wcs.wcs.crpix == np.array([0.25, 0.625]))
    assert np.all(slice_wcs.wcs.cdelt == np.array([0.2, 0.4]))

    slice_wcs = mywcs.slice([slice(1, None, 2)], numpy_order=False)
    assert np.all(slice_wcs.wcs.crpix == np.array([0.25, 1]))
    assert np.all(slice_wcs.wcs.cdelt == np.array([0.2, 0.1]))
Ejemplo n.º 6
0
def pix2world(wcsHeader, width, height, startX=0, startY=0, corner=True, ascartesian=False):
    """
    Calculate RA, Dec coordinates of a given pixel coordinate rectangle.
           
    ra, dec = pix2world(..)
    ra and dec are indexed as [y,x]
    
    Each array element contains the RA,Dec coords of the top left corner of the
    given pixel if corner==True, otherwise the coords of the pixel center. 
    If corner==True, an additional row and column exists at the bottom and right so that
    it is possible to get the bottom and right corner values for those pixels.
    
    :param dictionary wcsHeader: WCS header
    :param width: width of rectangle
    :param height: height of rectangle
    :param startX: x coordinate of rectangle, can be negative
    :param startY: y coordinate of rectangle, can be negative
    
    If ascartesian=False:
    
    :rtype: tuple(ra, dec) with arrays of shape (height+1,width+1) if corner==True, else (height,width)
    
    If ascartesian=True:
    
    :rtype: array of shape (height[+1],width[+1],3) with x,y,z order 
    """
    if corner:
        startX -= 0.5 # top left corner instead of pixel center
        startY -= 0.5
    x, y = np.meshgrid(np.arange(startX,startX+width+corner), np.arange(startY,startY+height+corner))
    
    # check if TAN projection and use our fast version, otherwise fall-back to astropy
    if wcsHeader['CTYPE1'] == 'RA---TAN' and wcsHeader['CTYPE2'] == 'DEC--TAN' and \
       wcsHeader['LATPOLE'] == 0.0:
        res = tan_pix2world(wcsHeader, x, y, 0, ascartesian=ascartesian)
        
    else:
        wcs = WCS(wcsHeader)
        ra, dec = wcs.all_pix2world(x, y, 0, ra_dec_order=True)
        if ascartesian:
            np.deg2rad(ra, ra)
            np.deg2rad(dec, dec)
            res = spherical_to_cartesian(None, dec, ra, astuple=False)
        else:
            res = ra, dec
    
    return res
Ejemplo n.º 7
0
def wcsTest():
    wcsPath = getResourcePath('ISS030-E-102170_dc.wcs')
    header = readHeader(wcsPath)
    
    # the pixel coordinates of which we want the world coordinates
    x, y = np.meshgrid(np.arange(0,4000), np.arange(0,2000))
    x = x.ravel()
    y = y.ravel()
    
    # first, calculate using astropy as reference
    wcs = WCS(header)
    t0 = time.time()
    ra_astropy, dec_astropy = wcs.wcs_pix2world(x, y, 0)
    print('astropy wcs:', time.time()-t0, 's')
    
    # now, check against our own implementation
    #tan_pix2world(header, x, y, 0) # warmup
    t0 = time.time()
    ra, dec = tan_pix2world(header, x, y, 0)
    print('own wcs:', time.time()-t0, 's')
    
    assert_almost_equal([ra, dec], [ra_astropy, dec_astropy])
Ejemplo n.º 8
0
def test_slice_with_sip():
    mywcs = WCS(naxis=2)
    mywcs.wcs.crval = [1, 1]
    mywcs.wcs.cdelt = [0.1, 0.1]
    mywcs.wcs.crpix = [1, 1]
    mywcs._naxis = [1000, 500]
    mywcs.wcs.ctype = ['RA---TAN-SIP', 'DEC--TAN-SIP']
    a = np.array(
        [[0, 0, 5.33092692e-08, 3.73753773e-11, -2.02111473e-13],
         [0, 2.44084308e-05, 2.81394789e-11, 5.17856895e-13, 0.0],
         [-2.41334657e-07, 1.29289255e-10, 2.35753629e-14, 0.0, 0.0],
         [-2.37162007e-10, 5.43714947e-13, 0.0, 0.0, 0.0],
         [ -2.81029767e-13, 0.0, 0.0, 0.0, 0.0]]
    )
    b = np.array(
        [[0, 0, 2.99270374e-05, -2.38136074e-10, 7.23205168e-13],
         [0, -1.71073858e-07, 6.31243431e-11, -5.16744347e-14, 0.0],
         [6.95458963e-06, -3.08278961e-10, -1.75800917e-13, 0.0, 0.0],
         [3.51974159e-11, 5.60993016e-14, 0.0, 0.0, 0.0],
         [-5.92438525e-13, 0.0, 0.0, 0.0, 0.0]]
    )
    mywcs.sip = Sip(a, b, None, None, mywcs.wcs.crpix)
    mywcs.wcs.set()
    pscale = 0.1 # from cdelt

    slice_wcs = mywcs.slice([slice(1, None), slice(0, None)])
    # test that CRPIX maps to CRVAL:
    assert_allclose(
        slice_wcs.all_pix2world(*slice_wcs.wcs.crpix, 1),
        slice_wcs.wcs.crval, rtol=0.0, atol=1e-6 * pscale
    )

    slice_wcs = mywcs.slice([slice(1, None, 2), slice(0, None, 4)])
    # test that CRPIX maps to CRVAL:
    assert_allclose(
        slice_wcs.all_pix2world(*slice_wcs.wcs.crpix, 1),
        slice_wcs.wcs.crval, rtol=0.0, atol=1e-6 * pscale
    )
Ejemplo n.º 9
0
Archivo: fits.py Proyecto: esa/auromat
def recomputeXylsPixelPositions(originalXylsPath, originalWcsPath, newWcsPathOrHeader):
    """
    Return pixel coordinates valid for `newWcsPathOrHeader` for
    the reference stars found in `originalXylsPath` (belonging to `originalWcsPath`).
    
    :rtype: tuple (x,y) with x and y being ndarrays
    """
    # Step 1: compute RA,Dec of reference stars (as this is not stored in .xyls)
    originalWCS = WCS(readHeader(originalWcsPath))
    x, y = readXy(originalXylsPath)
    ra, dec = originalWCS.all_pix2world(x, y, 0)
    
    # Step 2: compute pixel positions of reference stars in new WCS solution
    if isinstance(newWcsPathOrHeader, string_types):
        newWCS = WCS(readHeader(newWcsPathOrHeader))
    else:
        newWCS = WCS(newWcsPathOrHeader)

    # all_world2pix raised a NoConvergenc error
    # As we don't use SIP, we don't need to use all_world2pix.
    # wcs_world2pix doesn't support any distortion correction. 
    xNew, yNew = newWCS.wcs_world2pix(ra, dec, 0)
    
    return xNew,yNew
Ejemplo n.º 10
0
def test_wcs_swapping():
    wcs = WCS(naxis=4)
    wcs.wcs.pc = np.zeros([4, 4])
    np.fill_diagonal(wcs.wcs.pc, np.arange(1, 5))
    pc = wcs.wcs.pc  # for later use below

    swapped = wcs.swapaxes(0, 1)
    assert np.all(swapped.wcs.get_pc().diagonal() == np.array([2, 1, 3, 4]))
    swapped = wcs.swapaxes(0, 3)
    assert np.all(swapped.wcs.get_pc().diagonal() == np.array([4, 2, 3, 1]))
    swapped = wcs.swapaxes(2, 3)
    assert np.all(swapped.wcs.get_pc().diagonal() == np.array([1, 2, 4, 3]))

    wcs = WCS(naxis=4)
    wcs.wcs.cd = pc

    swapped = wcs.swapaxes(0, 1)
    assert np.all(swapped.wcs.get_pc().diagonal() == np.array([2, 1, 3, 4]))
    swapped = wcs.swapaxes(0, 3)
    assert np.all(swapped.wcs.get_pc().diagonal() == np.array([4, 2, 3, 1]))
    swapped = wcs.swapaxes(2, 3)
    assert np.all(swapped.wcs.get_pc().diagonal() == np.array([1, 2, 4, 3]))
Ejemplo n.º 11
0
def test_wcs_to_celestial_frame_extend():

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['XOFFSET', 'YOFFSET']
    mywcs.wcs.set()
    with pytest.raises(ValueError):
        wcs_to_celestial_frame(mywcs)

    class OffsetFrame:
        pass

    def identify_offset(wcs):
        if wcs.wcs.ctype[0].endswith('OFFSET') and wcs.wcs.ctype[1].endswith('OFFSET'):
            return OffsetFrame()

    with custom_wcs_to_frame_mappings(identify_offset):
        frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, OffsetFrame)

    # Check that things are back to normal after the context manager
    with pytest.raises(ValueError):
        wcs_to_celestial_frame(mywcs)
Ejemplo n.º 12
0
def test_custom_ctype_to_ucd_mappings():

    wcs = WCS(naxis=1)
    wcs.wcs.ctype = ['SPAM']

    assert wcs.world_axis_physical_types == [None]

    # Check simple behavior

    with custom_ctype_to_ucd_mapping({'APPLE': 'food.fruit'}):
        assert wcs.world_axis_physical_types == [None]

    with custom_ctype_to_ucd_mapping({
            'APPLE': 'food.fruit',
            'SPAM': 'food.spam'
    }):
        assert wcs.world_axis_physical_types == ['food.spam']

    # Check nesting

    with custom_ctype_to_ucd_mapping({'SPAM': 'food.spam'}):
        with custom_ctype_to_ucd_mapping({'APPLE': 'food.fruit'}):
            assert wcs.world_axis_physical_types == ['food.spam']

    with custom_ctype_to_ucd_mapping({'APPLE': 'food.fruit'}):
        with custom_ctype_to_ucd_mapping({'SPAM': 'food.spam'}):
            assert wcs.world_axis_physical_types == ['food.spam']

    # Check priority in nesting

    with custom_ctype_to_ucd_mapping({'SPAM': 'notfood'}):
        with custom_ctype_to_ucd_mapping({'SPAM': 'food.spam'}):
            assert wcs.world_axis_physical_types == ['food.spam']

    with custom_ctype_to_ucd_mapping({'SPAM': 'food.spam'}):
        with custom_ctype_to_ucd_mapping({'SPAM': 'notfood'}):
            assert wcs.world_axis_physical_types == ['notfood']
Ejemplo n.º 13
0
def dendro_import_hdf5(filename):
    """Import 'filename' and construct a dendrogram from it"""
    import h5py
    from astropy.wcs.wcs import WCS

    log.debug('Loading HDF5 file from disk...')
    with h5py.File(filename, 'r') as h5f:
        newick = h5f['newick'][()]
        data = h5f['data'][()]
        index_map = h5f['index_map'][()]

        params = {}
        if 'min_value' in h5f.attrs:
            params['min_value'] = h5f.attrs['min_value']
            params['min_delta'] = h5f.attrs['min_delta']
            params['min_npix'] = h5f.attrs['min_npix']

        try:
            wcs = WCS(h5f['wcs_header'][()])
        except KeyError:
            wcs = None

    log.debug('Parsing dendrogram...')
    return parse_dendrogram(newick, data, index_map, params, wcs)
Ejemplo n.º 14
0
def test_time_1d_roundtrip(header_time_1d, scale):

    # Check that coordinates round-trip

    pixel_in = np.arange(3, 10)

    header_time_1d['CTYPE1'] = scale.upper()
    wcs = WCS(header_time_1d)

    # Simple test
    time = wcs.pixel_to_world(pixel_in)
    pixel_out = wcs.world_to_pixel(time)
    assert_allclose(pixel_in, pixel_out)

    # Test with an intermediate change to a different scale/format
    time = wcs.pixel_to_world(pixel_in).tdb
    time.format = 'isot'
    pixel_out = wcs.world_to_pixel(time)
    assert_allclose(pixel_in, pixel_out)
Ejemplo n.º 15
0
def test_slice_with_sip():
    mywcs = WCS(naxis=2)
    mywcs.wcs.crval = [1, 1]
    mywcs.wcs.cdelt = [0.1, 0.1]
    mywcs.wcs.crpix = [1, 1]
    mywcs._naxis = [1000, 500]
    mywcs.wcs.ctype = ['RA---TAN-SIP', 'DEC--TAN-SIP']
    a = np.array(
        [[0, 0, 5.33092692e-08, 3.73753773e-11, -2.02111473e-13],
         [0, 2.44084308e-05, 2.81394789e-11, 5.17856895e-13, 0.0],
         [-2.41334657e-07, 1.29289255e-10, 2.35753629e-14, 0.0, 0.0],
         [-2.37162007e-10, 5.43714947e-13, 0.0, 0.0, 0.0],
         [-2.81029767e-13, 0.0, 0.0, 0.0, 0.0]]
    )
    b = np.array(
        [[0, 0, 2.99270374e-05, -2.38136074e-10, 7.23205168e-13],
         [0, -1.71073858e-07, 6.31243431e-11, -5.16744347e-14, 0.0],
         [6.95458963e-06, -3.08278961e-10, -1.75800917e-13, 0.0, 0.0],
         [3.51974159e-11, 5.60993016e-14, 0.0, 0.0, 0.0],
         [-5.92438525e-13, 0.0, 0.0, 0.0, 0.0]]
    )
    mywcs.sip = Sip(a, b, None, None, mywcs.wcs.crpix)
    mywcs.wcs.set()
    pscale = 0.1  # from cdelt

    slice_wcs = mywcs.slice([slice(1, None), slice(0, None)])
    # test that CRPIX maps to CRVAL:
    assert_allclose(
        slice_wcs.all_pix2world(*slice_wcs.wcs.crpix, 1),
        slice_wcs.wcs.crval, rtol=0.0, atol=1e-6 * pscale
    )

    slice_wcs = mywcs.slice([slice(1, None, 2), slice(0, None, 4)])
    # test that CRPIX maps to CRVAL:
    assert_allclose(
        slice_wcs.all_pix2world(*slice_wcs.wcs.crpix, 1),
        slice_wcs.wcs.crval, rtol=0.0, atol=1e-6 * pscale
    )
Ejemplo n.º 16
0
CRVAL2  = 20
CRVAL3  = 25
CRPIX1  = 30
CRPIX2  = 40
CRPIX3  = 45
CDELT1  = -0.1
CDELT2  =  0.5
CDELT3  =  0.1
CUNIT1  = deg
CUNIT2  = Hz
CUNIT3  = deg
"""

with warnings.catch_warnings():
    warnings.simplefilter('ignore', VerifyWarning)
    WCS_SPECTRAL_CUBE = WCS(Header.fromstring(HEADER_SPECTRAL_CUBE, sep='\n'))
WCS_SPECTRAL_CUBE.pixel_bounds = [(-1, 11), (-2, 18), (5, 15)]


def test_invalid_slices():
    with pytest.raises(IndexError):
        SlicedLowLevelWCS(WCS_SPECTRAL_CUBE,
                          [None, None, [False, False, False]])

    with pytest.raises(IndexError):
        SlicedLowLevelWCS(WCS_SPECTRAL_CUBE,
                          [None, None, slice(None, None, 2)])

    with pytest.raises(IndexError):
        SlicedLowLevelWCS(WCS_SPECTRAL_CUBE, [None, None, 1000.100])
Ejemplo n.º 17
0
Archivo: fits.py Proyecto: esa/auromat
def getCatalogStars(header, limit=500, limitFactor=2.5, maxVmag=None, retVmag=False, retry=1):
    """
    Queries the Vizier catalog and retrieves stars for the sky area
    as defined by the given WCS header.
    
    :param header: FITS WCS header, must include IMAGEW and IMAGEH
    :param limit: maximum number of stars to return (optional)
    :param limitFactor: how much more stars to query for;
                        The search region is a circle. To reach the desired
                        limit of returned stars after filtering stars outside
                        the image bounds more stars have to be queried for initially.
    :param maxVmag: maximum magnitude of stars (optional)
    :param retVmag: if true, include Vmag in the result tuple
    :param retry: how many times to retry in case of errors (e.g. network problems)
    :rtype: tuple (x, y) or (x, y, vmag) sorted by decreasing brightness, origin (0,0)
            Note that vmag is a masked array and can contain masked values.
    """
    column_filters = {}
    if maxVmag:
        column_filters['VTmag'] = '<' + str(maxVmag)
        
    w, h = header['IMAGEW'], header['IMAGEH']
                
    # Step 1: query stars in tycho-2 online catalog, ordered by Vmag
    # We add a small border here. This is useful for
    # circling stars in an image, such that half circles
    # are drawn at the image corners instead of suddenly disappearing
    # circles.
    catalog = 'I/259/tyc2'
    centerRa, centerDec = getCenterRADec(header)
    border = 0.01 * w
    radiusBorder = getPixelScale(header)*border
    
    radius = getRadius(header) + radiusBorder
    if limit:
        # we have to query more stars as our search region is a circle
        # and we are filtering stars out afterwards
        row_limit = int(limitFactor*limit)
    else:
        row_limit = -1
    print('Querying Vizier...')
    v = Vizier(columns=['_RAJ2000', '_DEJ2000', '+VTmag'],
               column_filters=column_filters, 
               row_limit=row_limit)
    try:
        result = v.query_region(coord.SkyCoord(ra=centerRa, dec=centerDec,
                                               unit=(u.deg, u.deg),
                                               frame='icrs'), 
                                radius=radius*u.deg, catalog=catalog)[0]
    except Exception as e:
        if retry > 0:
            print(repr(e))
            print('retrying...')
            time.sleep(2)
            # astroquery may have stored a corrupt response in its cache,
            # so we try again without using the cache
            # see https://github.com/astropy/astroquery/issues/465
            with suspend_cache(Vizier):
                return getCatalogStars(header, limit, limitFactor, maxVmag, retVmag, retry-1)
        print('Vizier query_region: ra={}, dec={}, radius={}, column_filters={}, row_limit={}, catalog={}'.
              format(centerRa, centerDec, radius, column_filters, row_limit, catalog),
              file=sys.stderr)
        raise
        
    vmag = result['VTmag']
    ra = result['_RAJ2000']
    dec = result['_DEJ2000']
    
    print(len(vmag), 'stars received')
    
    # Step 2: compute pixel coordinates for stars
    wcs = WCS(header)
    x, y = wcs.wcs_world2pix(ra, dec, 0)
    
    # Step 3: remove stars outside the image bounds
    # As above, we leave a small border here.
    inside = (-border <= y) & (y < h+border) & (-border <= x) & (x < w+border)
    x = x[inside]
    y = y[inside]
    vmag = vmag[inside]
    print(len(vmag), 'stars left after filtering')
    
    if limit and len(vmag) < limit:
        print('NOTE: limit of {} not reached, debug info follows'.format(limit), file=sys.stderr)
        print('Vizier query_region: ra={}, dec={}, radius={}, column_filters={}, row_limit={}, catalog={}'.
              format(centerRa, centerDec, radius, column_filters, row_limit, catalog),
              file=sys.stderr)
        print('filter: border={}, width={}, height={}'.format(border,w,h))
    
    # Step 4: apply limit by removing the faintest stars
    if limit:
        x = x[:limit]
        y = y[:limit]
        vmag = vmag[:limit]
        
    if retVmag:
        return x, y, vmag
    else:
        return x, y
Ejemplo n.º 18
0
def test_has_celestial(ctype, cel):
    mywcs = WCS(naxis=len(ctype))
    mywcs.wcs.ctype = ctype

    assert mywcs.has_celestial == cel
Ejemplo n.º 19
0
def test_pixscale_cd():
    mywcs = WCS(naxis=2)
    mywcs.wcs.cd = [[-0.1, 0], [0, 0.2]]
    mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']
    assert_almost_equal(proj_plane_pixel_scales(mywcs), (0.1, 0.2))
Ejemplo n.º 20
0
 def identify_offset(frame, projection=None):
     if isinstance(frame, OffsetFrame):
         wcs = WCS(naxis=2)
         wcs.wcs.ctype = ['XOFFSET', 'YOFFSET']
         return wcs
Ejemplo n.º 21
0
def test_wcs_to_celestial_frame():

    # Import astropy.coordinates here to avoid circular imports
    from astropy.coordinates.builtin_frames import ICRS, ITRS, FK5, FK4, Galactic

    mywcs = WCS(naxis=2)
    mywcs.wcs.set()
    with pytest.raises(ValueError) as exc:
        assert wcs_to_celestial_frame(mywcs) is None
    assert exc.value.args[0] == "Could not determine celestial frame corresponding to the specified WCS object"

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['XOFFSET', 'YOFFSET']
    mywcs.wcs.set()
    with pytest.raises(ValueError):
        assert wcs_to_celestial_frame(mywcs) is None

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, ICRS)

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']
    mywcs.wcs.equinox = 1987.
    mywcs.wcs.set()
    print(mywcs.to_header())
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, FK5)
    assert frame.equinox == Time(1987., format='jyear')

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']
    mywcs.wcs.equinox = 1982
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, FK4)
    assert frame.equinox == Time(1982., format='byear')

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['GLON-SIN', 'GLAT-SIN']
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, Galactic)

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['TLON-CAR', 'TLAT-CAR']
    mywcs.wcs.dateobs = '2017-08-17T12:41:04.430'
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, ITRS)
    assert frame.obstime == Time('2017-08-17T12:41:04.430')

    for equinox in [np.nan, 1987, 1982]:
        mywcs = WCS(naxis=2)
        mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']
        mywcs.wcs.radesys = 'ICRS'
        mywcs.wcs.equinox = equinox
        mywcs.wcs.set()
        frame = wcs_to_celestial_frame(mywcs)
        assert isinstance(frame, ICRS)

    # Flipped order
    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['DEC--TAN', 'RA---TAN']
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, ICRS)

    # More than two dimensions
    mywcs = WCS(naxis=3)
    mywcs.wcs.ctype = ['DEC--TAN', 'VELOCITY', 'RA---TAN']
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, ICRS)

    mywcs = WCS(naxis=3)
    mywcs.wcs.ctype = ['GLAT-CAR', 'VELOCITY', 'GLON-CAR']
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, Galactic)
Ejemplo n.º 22
0
def test_unrecognized_unit():
    # TODO: Determine whether the following behavior is desirable
    wcs = WCS(naxis=1)
    with pytest.warns(UnitsWarning):
        wcs.wcs.cunit = ['bananas // sekonds']
        assert wcs.world_axis_units == ['bananas // sekonds']
Ejemplo n.º 23
0
def test_celestial():
    mywcs = WCS(naxis=4)
    mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN', 'VOPT', 'STOKES']
    cel = mywcs.celestial
    assert tuple(cel.wcs.ctype) == ('RA---TAN', 'DEC--TAN')
    assert cel.axis_type_names == ['RA', 'DEC']
Ejemplo n.º 24
0
def test_fit_wcs_from_points():
    header_str_linear = """
XTENSION= 'IMAGE   '           / Image extension
BITPIX  =                  -32 / array data type
NAXIS   =                    2 / number of array dimensions
NAXIS1  =                   50
NAXIS2  =                   50
PCOUNT  =                    0 / number of parameters
GCOUNT  =                    1 / number of groups
RADESYS = 'ICRS    '
EQUINOX =               2000.0
WCSAXES =                    2
CTYPE1  = 'RA---TAN'
CTYPE2  = 'DEC--TAN'
CRVAL1  =    250.3497414839765
CRVAL2  =    2.280925599609063
CRPIX1  =               1045.0
CRPIX2  =               1001.0
CD1_1   =   -0.005564478186178
CD1_2   =   -0.001042099258152
CD2_1   =     0.00118144146585
CD2_2   =   -0.005590816683583
"""

    header_str_sip = """
XTENSION= 'IMAGE   '           / Image extension
BITPIX  =                  -32 / array data type
NAXIS   =                    2 / number of array dimensions
NAXIS1  =                   50
NAXIS2  =                   50
PCOUNT  =                    0 / number of parameters
GCOUNT  =                    1 / number of groups
RADESYS = 'ICRS    '
EQUINOX =               2000.0
WCSAXES =                    2
CTYPE1  = 'RA---TAN-SIP'
CTYPE2  = 'DEC--TAN-SIP'
CRVAL1  =    250.3497414839765
CRVAL2  =    2.280925599609063
CRPIX1  =               1045.0
CRPIX2  =               1001.0
CD1_1   =   -0.005564478186178
CD1_2   =   -0.001042099258152
CD2_1   =     0.00118144146585
CD2_2   =   -0.005590816683583
A_ORDER =                    2
B_ORDER =                    2
A_2_0   =    2.02451189234E-05
A_0_2   =   3.317603337918E-06
A_1_1   = 1.73456334971071E-05
B_2_0   =   3.331330003472E-06
B_0_2   = 2.04247482482589E-05
B_1_1   = 1.71476710804143E-05
AP_ORDER=                    2
BP_ORDER=                    2
AP_1_0  = 0.000904700296389636
AP_0_1  = 0.000627660715584716
AP_2_0  =  -2.023482905861E-05
AP_0_2  =  -3.332285841011E-06
AP_1_1  =  -1.731636633824E-05
BP_1_0  = 0.000627960882053211
BP_0_1  = 0.000911222886084808
BP_2_0  =  -3.343918167224E-06
BP_0_2  =  -2.041598249021E-05
BP_1_1  =  -1.711876336719E-05
A_DMAX  =    44.72893589844534
B_DMAX  =    44.62692873032506
"""
    header_linear = fits.Header.fromstring(header_str_linear, sep='\n')
    header_sip = fits.Header.fromstring(header_str_sip, sep='\n')

    true_wcs_linear = WCS(header_linear, relax=True)
    true_wcs_sip = WCS(header_sip, relax=True)

    # Getting the pixel coordinates
    x, y = np.meshgrid(list(range(10)), list(range(10)))
    x = x.flatten()
    y = y.flatten()

    # Calculating the true sky positions
    world_pix_linear = true_wcs_linear.pixel_to_world(x, y)
    world_pix_sip = true_wcs_sip.pixel_to_world(x, y)

    # Fitting the wcs, no distortion.
    fit_wcs_linear = fit_wcs_from_points((x, y),
                                         world_pix_linear,
                                         proj_point='center',
                                         sip_degree=None)

    # Fitting the wcs, with distortion.
    fit_wcs_sip = fit_wcs_from_points((x, y),
                                      world_pix_sip,
                                      proj_point='center',
                                      sip_degree=2)

    # Validate that the true sky coordinates calculated with `true_wcs_linear`
    # match sky coordinates calculated from the wcs fit with only linear terms

    world_pix_linear_new = fit_wcs_linear.pixel_to_world(x, y)

    dists = world_pix_linear.separation(world_pix_linear_new)

    assert dists.max() < 7e-5 * u.deg
    assert np.std(dists) < 2.5e-5 * u.deg

    # Validate that the true sky coordinates calculated with `true_wcs_sip`
    # match the sky coordinates calculated from the wcs fit with SIP of same
    # degree (2)

    world_pix_sip_new = fit_wcs_sip.pixel_to_world(x, y)
    dists = world_pix_sip.separation(world_pix_sip_new)

    assert dists.max() < 7e-6 * u.deg
    assert np.std(dists) < 2.5e-6 * u.deg

    # Test 360->0 degree crossover
    header_linear["CRVAL1"] = 352.3497414839765
    header_sip["CRVAL1"] = 352.3497414839765

    true_wcs_linear = WCS(header_linear, relax=True)
    true_wcs_sip = WCS(header_sip, relax=True)

    # Calculating the true sky positions
    world_pix_linear = true_wcs_linear.pixel_to_world(x, y)
    world_pix_sip = true_wcs_sip.pixel_to_world(x, y)

    # Fitting the wcs, no distortion.
    fit_wcs_linear = fit_wcs_from_points((x, y),
                                         world_pix_linear,
                                         proj_point='center',
                                         sip_degree=None)

    # Fitting the wcs, with distortion.
    fit_wcs_sip = fit_wcs_from_points((x, y),
                                      world_pix_sip,
                                      proj_point='center',
                                      sip_degree=2)

    # Validate that the true sky coordinates calculated with `true_wcs_linear`
    # match sky coordinates calculated from the wcs fit with only linear terms

    world_pix_linear_new = fit_wcs_linear.pixel_to_world(x, y)

    dists = world_pix_linear.separation(world_pix_linear_new)

    assert dists.max() < 7e-5 * u.deg
    assert np.std(dists) < 2.5e-5 * u.deg
Ejemplo n.º 25
0
def test_phys_type_polarization(header_polarized):
    w = WCS(header_polarized)
    assert w.world_axis_physical_types[2] == 'phys.polarization.stokes'
Ejemplo n.º 26
0
def test_fit_wcs_from_points():
    header_str_linear = """
XTENSION= 'IMAGE   '           / Image extension
BITPIX  =                  -32 / array data type
NAXIS   =                    2 / number of array dimensions
NAXIS1  =                   50
NAXIS2  =                   50
PCOUNT  =                    0 / number of parameters
GCOUNT  =                    1 / number of groups
RADESYS = 'ICRS    '
EQUINOX =               2000.0
WCSAXES =                    2
CTYPE1  = 'RA---TAN'
CTYPE2  = 'DEC--TAN'
CRVAL1  =    250.3497414839765
CRVAL2  =    2.280925599609063
CRPIX1  =               1045.0
CRPIX2  =               1001.0
CD1_1   =   -0.005564478186178
CD1_2   =   -0.001042099258152
CD2_1   =     0.00118144146585
CD2_2   =   -0.005590816683583
"""

    header_str_sip = """
XTENSION= 'IMAGE   '           / Image extension
BITPIX  =                  -32 / array data type
NAXIS   =                    2 / number of array dimensions
NAXIS1  =                   50
NAXIS2  =                   50
PCOUNT  =                    0 / number of parameters
GCOUNT  =                    1 / number of groups
RADESYS = 'ICRS    '
EQUINOX =               2000.0
WCSAXES =                    2
CTYPE1  = 'RA---TAN-SIP'
CTYPE2  = 'DEC--TAN-SIP'
CRVAL1  =    250.3497414839765
CRVAL2  =    2.280925599609063
CRPIX1  =               1045.0
CRPIX2  =               1001.0
CD1_1   =   -0.005564478186178
CD1_2   =   -0.001042099258152
CD2_1   =     0.00118144146585
CD2_2   =   -0.005590816683583
A_ORDER =                    2
B_ORDER =                    2
A_2_0   =    2.02451189234E-05
A_0_2   =   3.317603337918E-06
A_1_1   = 1.73456334971071E-05
B_2_0   =   3.331330003472E-06
B_0_2   = 2.04247482482589E-05
B_1_1   = 1.71476710804143E-05
AP_ORDER=                    2
BP_ORDER=                    2
AP_1_0  = 0.000904700296389636
AP_0_1  = 0.000627660715584716
AP_2_0  =  -2.023482905861E-05
AP_0_2  =  -3.332285841011E-06
AP_1_1  =  -1.731636633824E-05
BP_1_0  = 0.000627960882053211
BP_0_1  = 0.000911222886084808
BP_2_0  =  -3.343918167224E-06
BP_0_2  =  -2.041598249021E-05
BP_1_1  =  -1.711876336719E-05
A_DMAX  =    44.72893589844534
B_DMAX  =    44.62692873032506
"""
    # A known header that failed before
    header_str_prob = """
NAXIS   =                    2 / number of array dimensions
WCSAXES =                    2 / Number of coordinate axes
CRPIX1  =               1024.5 / Pixel coordinate of reference point
CRPIX2  =               1024.5 / Pixel coordinate of reference point
CD1_1   = -1.7445934400771E-05 / Coordinate transformation matrix element
CD1_2   = -4.9826985362578E-08 / Coordinate transformation matrix element
CD2_1   = -5.0068838822312E-08 / Coordinate transformation matrix element
CD2_2   =  1.7530614610951E-05 / Coordinate transformation matrix element
CTYPE1  = 'RA---TAN'           / Right ascension, gnomonic projection
CTYPE2  = 'DEC--TAN'           / Declination, gnomonic projection
CRVAL1  =      5.8689341666667 / [deg] Coordinate value at reference point
CRVAL2  =     -71.995508583333 / [deg] Coordinate value at reference point
"""

    header_linear = fits.Header.fromstring(header_str_linear, sep='\n')
    header_sip = fits.Header.fromstring(header_str_sip, sep='\n')
    header_prob = fits.Header.fromstring(header_str_prob, sep='\n')

    true_wcs_linear = WCS(header_linear, relax=True)
    true_wcs_sip = WCS(header_sip, relax=True)
    true_wcs_prob = WCS(header_prob, relax=True)

    # Getting the pixel coordinates
    x, y = np.meshgrid(list(range(10)), list(range(10)))
    x = x.flatten()
    y = y.flatten()

    # Calculating the true sky positions
    world_pix_linear = true_wcs_linear.pixel_to_world(x, y)
    world_pix_sip = true_wcs_sip.pixel_to_world(x, y)
    world_pix_prob = true_wcs_prob.pixel_to_world(x, y)

    # Fitting the wcs, no distortion.
    fit_wcs_linear = fit_wcs_from_points((x, y),
                                         world_pix_linear,
                                         proj_point='center',
                                         sip_degree=None)

    # Fitting the wcs, with distortion.
    fit_wcs_sip = fit_wcs_from_points((x, y),
                                      world_pix_sip,
                                      proj_point='center',
                                      sip_degree=2)

    # Fitting the problematic WCS
    fit_wcs_prob = fit_wcs_from_points((x, y),
                                       world_pix_prob,
                                       proj_point='center',
                                       sip_degree=None)

    # Validate that the true sky coordinates calculated with `true_wcs_linear`
    # match sky coordinates calculated from the wcs fit with only linear terms

    world_pix_linear_new = fit_wcs_linear.pixel_to_world(x, y)

    dists = world_pix_linear.separation(world_pix_linear_new)

    assert dists.max() < 7e-5 * u.deg
    assert np.std(dists) < 2.5e-5 * u.deg

    # Validate that the true sky coordinates calculated with `true_wcs_sip`
    # match the sky coordinates calculated from the wcs fit with SIP of same
    # degree (2)

    world_pix_sip_new = fit_wcs_sip.pixel_to_world(x, y)
    dists = world_pix_sip.separation(world_pix_sip_new)

    assert dists.max() < 7e-6 * u.deg
    assert np.std(dists) < 2.5e-6 * u.deg

    # Validate that the true sky coordinates calculated from the problematic
    # WCS match

    world_pix_prob_new = fit_wcs_prob.pixel_to_world(x, y)
    dists = world_pix_prob.separation(world_pix_prob_new)

    assert dists.max() < 7e-6 * u.deg
    assert np.std(dists) < 2.5e-6 * u.deg

    # Test 360->0 degree crossover
    header_linear["CRVAL1"] = 352.3497414839765
    header_sip["CRVAL1"] = 352.3497414839765
    header_prob["CRVAL1"] = 352.3497414839765

    true_wcs_linear = WCS(header_linear, relax=True)
    true_wcs_sip = WCS(header_sip, relax=True)
    true_wcs_prob = WCS(header_prob)

    # Calculating the true sky positions
    world_pix_linear = true_wcs_linear.pixel_to_world(x, y)
    world_pix_sip = true_wcs_sip.pixel_to_world(x, y)
    world_pix_prob = true_wcs_prob.pixel_to_world(x, y)

    # Fitting the wcs, no distortion.
    fit_wcs_linear = fit_wcs_from_points((x, y),
                                         world_pix_linear,
                                         proj_point='center',
                                         sip_degree=None)

    # Fitting the wcs, with distortion.
    fit_wcs_sip = fit_wcs_from_points((x, y),
                                      world_pix_sip,
                                      proj_point='center',
                                      sip_degree=2)

    # Fitting the problem WCS
    fit_wcs_prob = fit_wcs_from_points((x, y),
                                       world_pix_prob,
                                       proj_point='center',
                                       sip_degree=None)

    # Validate that the true sky coordinates calculated with `true_wcs_linear`
    # match sky coordinates calculated from the wcs fit with only linear terms

    world_pix_linear_new = fit_wcs_linear.pixel_to_world(x, y)

    dists = world_pix_linear.separation(world_pix_linear_new)

    assert dists.max() < 7e-5 * u.deg
    assert np.std(dists) < 2.5e-5 * u.deg

    # Validate fit with SIP
    world_pix_sip_new = fit_wcs_sip.pixel_to_world(x, y)
    dists = world_pix_sip.separation(world_pix_sip_new)

    assert dists.max() < 7e-6 * u.deg
    assert np.std(dists) < 2.5e-6 * u.deg

    # Validate the problematic WCS
    world_pix_prob_new = fit_wcs_prob.pixel_to_world(x, y)
    dists = world_pix_prob.separation(world_pix_prob_new)

    assert dists.max() < 7e-6 * u.deg
    assert np.std(dists) < 2.5e-6 * u.deg

    # Test CRPIX bounds requirement
    wcs_str = """
WCSAXES =                    2 / Number of coordinate axes
CRPIX1  =               1045.0 / Pixel coordinate of reference point
CRPIX2  =               1001.0 / Pixel coordinate of reference point
PC1_1   =  0.00056205870415378 / Coordinate transformation matrix element
PC1_2   =    -0.00569181083243 / Coordinate transformation matrix element
PC2_1   =   0.0056776810932466 / Coordinate transformation matrix element
PC2_2   =   0.0004208048403273 / Coordinate transformation matrix element
CDELT1  =                  1.0 / [deg] Coordinate increment at reference point
CDELT2  =                  1.0 / [deg] Coordinate increment at reference point
CUNIT1  = 'deg'                / Units of coordinate increment and value
CUNIT2  = 'deg'                / Units of coordinate increment and value
CTYPE1  = 'RA---TAN'           / Right ascension, gnomonic projection
CTYPE2  = 'DEC--TAN'           / Declination, gnomonic projection
CRVAL1  =      104.57797893504 / [deg] Coordinate value at reference point
CRVAL2  =     -74.195502593322 / [deg] Coordinate value at reference point
LONPOLE =                180.0 / [deg] Native longitude of celestial pole
LATPOLE =     -74.195502593322 / [deg] Native latitude of celestial pole
TIMESYS = 'TDB'                / Time scale
TIMEUNIT= 'd'                  / Time units
DATEREF = '1858-11-17'         / ISO-8601 fiducial time
MJDREFI =                  0.0 / [d] MJD of fiducial time, integer part
MJDREFF =                  0.0 / [d] MJD of fiducial time, fractional part
DATE-OBS= '2019-03-27T03:30:13.832Z' / ISO-8601 time of observation
MJD-OBS =      58569.145993426 / [d] MJD of observation
MJD-OBS =      58569.145993426 / [d] MJD at start of observation
TSTART  =      1569.6467941661 / [d] Time elapsed since fiducial time at start
DATE-END= '2019-03-27T04:00:13.831Z' / ISO-8601 time at end of observation
MJD-END =      58569.166826748 / [d] MJD at end of observation
TSTOP   =      1569.6676274905 / [d] Time elapsed since fiducial time at end
TELAPSE =        0.02083332443 / [d] Elapsed time (start to stop)
TIMEDEL =    0.020833333333333 / [d] Time resolution
TIMEPIXR=                  0.5 / Reference position of timestamp in binned data
RADESYS = 'ICRS'               / Equatorial coordinate system
"""
    wcs_header = fits.Header.fromstring(wcs_str, sep='\n')
    ffi_wcs = WCS(wcs_header)

    yi, xi = (1000, 1000)
    y, x = (10, 200)

    center_coord = SkyCoord(ffi_wcs.all_pix2world([[xi + x // 2, yi + y // 2]],
                                                  0),
                            unit='deg')[0]
    ypix, xpix = [arr.flatten() for arr in np.mgrid[xi:xi + x, yi:yi + y]]
    world_pix = SkyCoord(*ffi_wcs.all_pix2world(xpix, ypix, 0), unit='deg')

    fit_wcs = fit_wcs_from_points((ypix, xpix), world_pix, proj_point='center')

    assert (fit_wcs.wcs.crpix.astype(int) == [1100, 1005]).all()
    assert fit_wcs.pixel_shape == (200, 10)
Ejemplo n.º 27
0
def time_1d_wcs(header_time_1d):
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', FITSFixedWarning)
        return WCS(header_time_1d)
Ejemplo n.º 28
0
def test_wcs_to_celestial_frame():

    # Import astropy.coordinates here to avoid circular imports
    from astropy.coordinates.builtin_frames import ICRS, ITRS, FK5, FK4, Galactic

    mywcs = WCS(naxis=2)
    mywcs.wcs.set()
    with pytest.raises(ValueError,
                       match="Could not determine celestial frame "
                       "corresponding to the specified WCS object"):
        assert wcs_to_celestial_frame(mywcs) is None

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['XOFFSET', 'YOFFSET']
    mywcs.wcs.set()
    with pytest.raises(ValueError):
        assert wcs_to_celestial_frame(mywcs) is None

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, ICRS)

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']
    mywcs.wcs.equinox = 1987.
    mywcs.wcs.set()
    print(mywcs.to_header())
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, FK5)
    assert frame.equinox == Time(1987., format='jyear')

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']
    mywcs.wcs.equinox = 1982
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, FK4)
    assert frame.equinox == Time(1982., format='byear')

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['GLON-SIN', 'GLAT-SIN']
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, Galactic)

    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['TLON-CAR', 'TLAT-CAR']
    mywcs.wcs.dateobs = '2017-08-17T12:41:04.430'
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, ITRS)
    assert frame.obstime == Time('2017-08-17T12:41:04.430')

    for equinox in [np.nan, 1987, 1982]:
        mywcs = WCS(naxis=2)
        mywcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']
        mywcs.wcs.radesys = 'ICRS'
        mywcs.wcs.equinox = equinox
        mywcs.wcs.set()
        frame = wcs_to_celestial_frame(mywcs)
        assert isinstance(frame, ICRS)

    # Flipped order
    mywcs = WCS(naxis=2)
    mywcs.wcs.ctype = ['DEC--TAN', 'RA---TAN']
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, ICRS)

    # More than two dimensions
    mywcs = WCS(naxis=3)
    mywcs.wcs.ctype = ['DEC--TAN', 'VELOCITY', 'RA---TAN']
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, ICRS)

    mywcs = WCS(naxis=3)
    mywcs.wcs.ctype = ['GLAT-CAR', 'VELOCITY', 'GLON-CAR']
    mywcs.wcs.set()
    frame = wcs_to_celestial_frame(mywcs)
    assert isinstance(frame, Galactic)
Ejemplo n.º 29
0
from astropy.tests.helper import assert_quantity_allclose
from astropy.units import Quantity
from astropy.coordinates import ICRS, FK5, Galactic, SkyCoord
from astropy.io.fits import Header
from astropy.io.fits.verify import VerifyWarning
from astropy.units.core import UnitsWarning
from astropy.utils.data import get_pkg_data_filename
from astropy.wcs.wcs import WCS, FITSFixedWarning
from astropy.wcs.wcsapi.fitswcs import custom_ctype_to_ucd_mapping
from astropy.wcs._wcs import __version__ as wcsver

###############################################################################
# The following example is the simplest WCS with default values
###############################################################################

WCS_EMPTY = WCS(naxis=1)
WCS_EMPTY.wcs.crpix = [1]


def test_empty():

    wcs = WCS_EMPTY

    # Low-level API

    assert wcs.pixel_n_dim == 1
    assert wcs.world_n_dim == 1
    assert wcs.array_shape is None
    assert wcs.pixel_shape is None
    assert wcs.world_axis_physical_types == [None]
    assert wcs.world_axis_units == ['']
Ejemplo n.º 30
0
def test_wcs_dropping():
    wcs = WCS(naxis=4)
    wcs.wcs.pc = np.zeros([4, 4])
    np.fill_diagonal(wcs.wcs.pc, np.arange(1, 5))
    pc = wcs.wcs.pc  # for later use below

    dropped = wcs.dropaxis(0)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([2, 3, 4]))
    dropped = wcs.dropaxis(1)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 3, 4]))
    dropped = wcs.dropaxis(2)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 2, 4]))
    dropped = wcs.dropaxis(3)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 2, 3]))

    wcs = WCS(naxis=4)
    wcs.wcs.cd = pc

    dropped = wcs.dropaxis(0)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([2, 3, 4]))
    dropped = wcs.dropaxis(1)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 3, 4]))
    dropped = wcs.dropaxis(2)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 2, 4]))
    dropped = wcs.dropaxis(3)
    assert np.all(dropped.wcs.get_pc().diagonal() == np.array([1, 2, 3]))
Ejemplo n.º 31
0
def getCatalogStars(header,
                    limit=500,
                    limitFactor=2.5,
                    maxVmag=None,
                    retVmag=False,
                    retry=1):
    """
    Queries the Vizier catalog and retrieves stars for the sky area
    as defined by the given WCS header.
    
    :param header: FITS WCS header, must include IMAGEW and IMAGEH
    :param limit: maximum number of stars to return (optional)
    :param limitFactor: how much more stars to query for;
                        The search region is a circle. To reach the desired
                        limit of returned stars after filtering stars outside
                        the image bounds more stars have to be queried for initially.
    :param maxVmag: maximum magnitude of stars (optional)
    :param retVmag: if true, include Vmag in the result tuple
    :param retry: how many times to retry in case of errors (e.g. network problems)
    :rtype: tuple (x, y) or (x, y, vmag) sorted by decreasing brightness, origin (0,0)
            Note that vmag is a masked array and can contain masked values.
    """
    column_filters = {}
    if maxVmag:
        column_filters['VTmag'] = '<' + str(maxVmag)

    w, h = header['IMAGEW'], header['IMAGEH']

    # Step 1: query stars in tycho-2 online catalog, ordered by Vmag
    # We add a small border here. This is useful for
    # circling stars in an image, such that half circles
    # are drawn at the image corners instead of suddenly disappearing
    # circles.
    catalog = 'I/259/tyc2'
    centerRa, centerDec = getCenterRADec(header)
    border = 0.01 * w
    radiusBorder = getPixelScale(header) * border

    radius = getRadius(header) + radiusBorder
    if limit:
        # we have to query more stars as our search region is a circle
        # and we are filtering stars out afterwards
        row_limit = int(limitFactor * limit)
    else:
        row_limit = -1
    print('Querying Vizier...')
    v = Vizier(columns=['_RAJ2000', '_DEJ2000', '+VTmag'],
               column_filters=column_filters,
               row_limit=row_limit)
    try:
        result = v.query_region(coord.SkyCoord(ra=centerRa,
                                               dec=centerDec,
                                               unit=(u.deg, u.deg),
                                               frame='icrs'),
                                radius=radius * u.deg,
                                catalog=catalog)[0]
    except Exception as e:
        if retry > 0:
            print(repr(e))
            print('retrying...')
            time.sleep(2)
            # astroquery may have stored a corrupt response in its cache,
            # so we try again without using the cache
            # see https://github.com/astropy/astroquery/issues/465
            with suspend_cache(Vizier):
                return getCatalogStars(header, limit, limitFactor, maxVmag,
                                       retVmag, retry - 1)
        print(
            'Vizier query_region: ra={}, dec={}, radius={}, column_filters={}, row_limit={}, catalog={}'
            .format(centerRa, centerDec, radius, column_filters, row_limit,
                    catalog),
            file=sys.stderr)
        raise

    vmag = result['VTmag']
    ra = result['_RAJ2000']
    dec = result['_DEJ2000']

    print(len(vmag), 'stars received')

    # Step 2: compute pixel coordinates for stars
    wcs = WCS(header)
    x, y = wcs.wcs_world2pix(ra, dec, 0)

    # Step 3: remove stars outside the image bounds
    # As above, we leave a small border here.
    inside = (-border <= y) & (y < h + border) & (-border <= x) & (x <
                                                                   w + border)
    x = x[inside]
    y = y[inside]
    vmag = vmag[inside]
    print(len(vmag), 'stars left after filtering')

    if limit and len(vmag) < limit:
        print(
            'NOTE: limit of {} not reached, debug info follows'.format(limit),
            file=sys.stderr)
        print(
            'Vizier query_region: ra={}, dec={}, radius={}, column_filters={}, row_limit={}, catalog={}'
            .format(centerRa, centerDec, radius, column_filters, row_limit,
                    catalog),
            file=sys.stderr)
        print('filter: border={}, width={}, height={}'.format(border, w, h))

    # Step 4: apply limit by removing the faintest stars
    if limit:
        x = x[:limit]
        y = y[:limit]
        vmag = vmag[:limit]

    if retVmag:
        return x, y, vmag
    else:
        return x, y
Ejemplo n.º 32
0
def test_spectral_1d(header_spectral_1d, ctype1, observer):

    # This is a regression test for issues that happened with 1-d WCS
    # where the target is not defined but observer is.

    header = header_spectral_1d.copy()
    header['CTYPE1'] = ctype1
    header['CRVAL1'] = 0.1
    header['CDELT1'] = 0.001

    if ctype1[0] == 'V':
        header['CUNIT1'] = 'm s-1'
    else:
        header['CUNIT1'] = ''

    header['RESTWAV'] = 1.420405752E+09
    header['MJD-OBS'] = 55197

    if observer:
        header['OBSGEO-L'] = 144.2
        header['OBSGEO-B'] = -20.2
        header['OBSGEO-H'] = 0.
        header['SPECSYS'] = 'BARYCENT'

    with warnings.catch_warnings():
        warnings.simplefilter('ignore', FITSFixedWarning)
        wcs = WCS(header)

    # First ensure that transformations round-trip

    spectralcoord = wcs.pixel_to_world(31)

    assert isinstance(spectralcoord, SpectralCoord)
    assert spectralcoord.target is None
    assert (spectralcoord.observer is not None) is observer

    if observer:
        expected_message = 'No target defined on SpectralCoord'
    else:
        expected_message = 'No observer defined on WCS'

    with pytest.warns(AstropyUserWarning, match=expected_message):
        pix = wcs.world_to_pixel(spectralcoord)

    assert_allclose(pix, [31], rtol=1e-6)

    # Also make sure that we can convert a SpectralCoord on which the observer
    # is not defined but the target is.

    with pytest.warns(AstropyUserWarning,
                      match='No velocity defined on frame'):
        spectralcoord_no_obs = SpectralCoord(
            spectralcoord.quantity,
            doppler_rest=spectralcoord.doppler_rest,
            doppler_convention=spectralcoord.doppler_convention,
            target=ICRS(10 * u.deg, 20 * u.deg, distance=1 * u.kpc))

    if observer:
        expected_message = 'No observer defined on SpectralCoord'
    else:
        expected_message = 'No observer defined on WCS'

    with pytest.warns(AstropyUserWarning, match=expected_message):
        pix2 = wcs.world_to_pixel(spectralcoord_no_obs)
    assert_allclose(pix2, [31], rtol=1e-6)

    # And finally check case when both observer and target are defined on the
    # SpectralCoord

    with pytest.warns(AstropyUserWarning,
                      match='No velocity defined on frame'):
        spectralcoord_no_obs = SpectralCoord(
            spectralcoord.quantity,
            doppler_rest=spectralcoord.doppler_rest,
            doppler_convention=spectralcoord.doppler_convention,
            observer=ICRS(10 * u.deg, 20 * u.deg, distance=0 * u.kpc),
            target=ICRS(10 * u.deg, 20 * u.deg, distance=1 * u.kpc))

    if observer:
        pix3 = wcs.world_to_pixel(spectralcoord_no_obs)
    else:
        with pytest.warns(AstropyUserWarning,
                          match='No observer defined on WCS'):
            pix3 = wcs.world_to_pixel(spectralcoord_no_obs)

    assert_allclose(pix3, [31], rtol=1e-6)