示例#1
0
def test_get_body_heliographic_stonyhurst():
    # Validate against published values from the Astronomical Almanac (2013)
    e1 = get_body_heliographic_stonyhurst('earth', '2013-Jan-01')
    assert_quantity_allclose(e1.lon, 0 * u.deg, atol=1e-12 * u.deg)
    assert_quantity_allclose(e1.lat, -3.03 * u.deg, atol=5e-3 * u.deg)
    assert_quantity_allclose(e1.radius, 0.9832947 * u.AU, atol=5e-7 * u.AU)

    e2 = get_body_heliographic_stonyhurst('earth', '2013-Sep-01')
    assert_quantity_allclose(e2.lon, 0 * u.deg, atol=1e-12 * u.deg)
    assert_quantity_allclose(e2.lat, 7.19 * u.deg, atol=5e-3 * u.deg)
    assert_quantity_allclose(e2.radius, 1.0092561 * u.AU, atol=5e-7 * u.AU)
示例#2
0
def prepare_test_data(file_format):
    pytest.importorskip('sunpy', minversion='2.1.0')
    from sunpy.map import Map
    from sunpy.coordinates.ephemeris import get_body_heliographic_stonyhurst

    if file_format == 'fits':
        map_aia = Map(os.path.join(DATA, 'aia_171_level1.fits'))
        data = map_aia.data
        wcs = map_aia.wcs
        date = map_aia.date
        target_wcs = wcs.deepcopy()
    elif file_format == 'asdf':
        pytest.importorskip('astropy', minversion='4.0')
        pytest.importorskip('gwcs', minversion='0.12')
        asdf = pytest.importorskip('asdf')
        aia = asdf.open(os.path.join(DATA, 'aia_171_level1.asdf'))
        data = aia['data'][...]
        wcs = aia['wcs']
        date = wcs.output_frame.reference_frame.obstime
        target_wcs = Map(os.path.join(DATA, 'aia_171_level1.fits')).wcs.deepcopy()
    else:
        raise ValueError('file_format should be fits or asdf')

    # Reproject to an observer on Venus

    target_wcs.wcs.cdelt = ([24, 24]*u.arcsec).to(u.deg)
    target_wcs.wcs.crpix = [64, 64]
    venus = get_body_heliographic_stonyhurst('venus', date)
    target_wcs.wcs.aux.hgln_obs = venus.lon.to_value(u.deg)
    target_wcs.wcs.aux.hglt_obs = venus.lat.to_value(u.deg)
    target_wcs.wcs.aux.dsun_obs = venus.radius.to_value(u.m)

    return data, wcs, target_wcs
示例#3
0
def get_position_heliographic_stonyhurst(body_name, time, observer):
    """
    Get the position of one of the supported bodies as seen from the
    observer.  If

    Parameters
    ----------
    body_name :


    time :


    observer :

    Returns
    -------
    `~astropy.coordinate.SkyCoord`
    """
    _body_name = body_name.lower()

    # Check if the body is one of the supported spacecraft.  Note that the
    if _body_name in spacecraft:
        coordinate = get_horizons_coord(_body_name, time).transform_to(
            frames.HeliographicStonyhurst)
    # Check if the body is one of the supported solar system objects
    elif _body_name in solar_system_objects:
        coordinate = get_body_heliographic_stonyhurst(_body_name,
                                                      time=time,
                                                      observer=observer)
    else:
        raise ValueError('The body name is not recognized.')
    return coordinate
示例#4
0
def test_get_body_heliographic_stonyhurst_light_travel_time():
    # Tests whether the apparent position of the Sun accounts for light travel time
    t = Time('2012-06-05 22:34:48.350')  # An arbitrary test time

    # Use the implemented correction for light travel time
    implementation = get_body_heliographic_stonyhurst('sun',
                                                      t,
                                                      observer=get_earth(t))
    implementation_icrs = SkyCoord(implementation).icrs.cartesian

    # Use a manual correction for light travel time
    light_travel_time = get_earth(t).radius / speed_of_light
    manual = get_body_heliographic_stonyhurst('sun', t - light_travel_time)
    manual_icrs = SkyCoord(manual).icrs.cartesian

    difference = (implementation_icrs - manual_icrs).norm()
    assert_quantity_allclose(difference, 0 * u.m, atol=1 * u.m)
示例#5
0
def get_position(body_name, time, observer=None):
    """
    Get the position of one of the supported bodies.  If an observer is given then light travel time from the body
    to the observer is taken in to account.

    Parameters
    ----------
    body_name : `str`
        The body whose position will be calculated

    time : `~astropy.time.Time`
        The time at which the body position is calculated.  If the observer is not None, then the time is the
        time at the observer.

    observer : None, `~astropy.coordinate.SkyCoord`
        If None, the position of the body is returned.  If not none, the position of the body as seen from the
        observer takes into account the light travel time from the body to the observer.

    Returns
    -------
    `~astropy.coordinate.SkyCoord`
        The position of the body.  If the observer is not none, the position of the body as seen from the
        observer takes into account the light travel time from the body to the observer.
    """
    _body_name = body_name.lower()

    if observer is None:
        if _body_name in spice_spacecraft:
            spice_target = get_spice_target(_body_name)
            if _body_name == 'soho':
                # Use the SPICE kernels if available, otherwise estimate the position of SOHO.
                try:
                    coordinate = spice_target.coordinate(time)
                except:  # SpiceyError:
                    earth = get_body('earth', time).transform_to(frames.HeliographicStonyhurst)
                    coordinate = SkyCoord(lat=earth.lat, lon=earth.lon, radius=0.99 * earth.radius, obstime=time, frame=frames.HeliographicStonyhurst)
            else:
                coordinate = spice_target.coordinate(time)
        elif _body_name in solar_system_objects:
            coordinate = get_body(_body_name, time)
        else:
            raise ValueError('The body name is not recognized.')
    else:
        if _body_name in spice_spacecraft:
            #log.warning('Light travel time corrected locations of spacecraft are not yet supported ({:s} seen from observer).'.format(body_name))
            spice_target = get_spice_target(_body_name)
            coordinate = spice_target.coordinate(time)
        elif _body_name in solar_system_objects:
            body_frame = get_body_heliographic_stonyhurst(_body_name, observer=observer, time=time)
            # Explicitly convert the returned body frame in to a SkyCoord.
            coordinate = SkyCoord(lat=body_frame.lat, lon=body_frame.lon, radius=body_frame.radius, obstime=time, frame=frames.HeliographicStonyhurst)
        else:
            raise ValueError('The body name is not recognized.')
    return coordinate.transform_to(frames.HeliographicStonyhurst)
示例#6
0
def test_get_body_heliographic_stonyhurst_light_travel_time_array():
    # Tests whether requesting an array of locations returns the same answers as individually
    t1 = Time('2001-02-03 04:05:06')
    t2 = Time('2011-12-13 14:15:16')

    venus1 = get_body_heliographic_stonyhurst('venus',
                                              t1,
                                              observer=get_earth(t1))
    venus2 = get_body_heliographic_stonyhurst('venus',
                                              t2,
                                              observer=get_earth(t2))
    both = get_body_heliographic_stonyhurst('venus', [t1, t2],
                                            observer=get_earth([t1, t2]))

    assert_quantity_allclose(venus1.lon, both[0].lon)
    assert_quantity_allclose(venus1.lat, both[0].lat)
    assert_quantity_allclose(venus1.radius, both[0].radius)
    assert_quantity_allclose(venus2.lon, both[1].lon)
    assert_quantity_allclose(venus2.lat, both[1].lat)
    assert_quantity_allclose(venus2.radius, both[1].radius)
示例#7
0
def test_reproject_roundtrip(file_format):

    # Test the reprojection with solar data, which ensures that the masking of
    # pixels based on round-tripping works correctly. Using asdf is not just
    # about testing a different format but making sure that GWCS works.

    # The observer handling changed in 2.1.
    pytest.importorskip('sunpy', minversion='2.1.0')
    from sunpy.map import Map
    from sunpy.coordinates.ephemeris import get_body_heliographic_stonyhurst

    if file_format == 'fits':
        map_aia = Map(get_pkg_data_filename('data/aia_171_level1.fits', package='reproject.tests'))
        data = map_aia.data
        wcs = map_aia.wcs
        date = map_aia.date
        target_wcs = wcs.deepcopy()
    elif file_format == 'asdf':
        pytest.importorskip('astropy', minversion='4.0')
        pytest.importorskip('gwcs', minversion='0.12')
        asdf = pytest.importorskip('asdf')
        aia = asdf.open(
            get_pkg_data_filename('data/aia_171_level1.asdf', package='reproject.tests'))
        data = aia['data'][...]
        wcs = aia['wcs']
        date = wcs.output_frame.reference_frame.obstime
        target_wcs = Map(
            get_pkg_data_filename('data/aia_171_level1.fits',
                                  package='reproject.tests')).wcs.deepcopy()
    else:
        raise ValueError('file_format should be fits or asdf')

    # Reproject to an observer on Venus

    target_wcs.wcs.cdelt = ([24, 24]*u.arcsec).to(u.deg)
    target_wcs.wcs.crpix = [64, 64]
    venus = get_body_heliographic_stonyhurst('venus', date)
    target_wcs.wcs.aux.hgln_obs = venus.lon.to_value(u.deg)
    target_wcs.wcs.aux.hglt_obs = venus.lat.to_value(u.deg)
    target_wcs.wcs.aux.dsun_obs = venus.radius.to_value(u.m)

    output, footprint = reproject_interp((data, wcs), target_wcs, (128, 128))

    header_out = target_wcs.to_header()

    # ASTROPY_LT_40: astropy v4.0 introduced new default header keywords,
    # once we support only astropy 4.0 and later we can update the reference
    # data files and remove this section.
    for key in ('CRLN_OBS', 'CRLT_OBS', 'DSUN_OBS', 'HGLN_OBS', 'HGLT_OBS',
                'MJDREFF', 'MJDREFI', 'MJDREF', 'MJD-OBS', 'RSUN_REF'):
        header_out.pop(key, None)
    header_out['DATE-OBS'] = header_out['DATE-OBS'].replace('T', ' ')

    return array_footprint_to_hdulist(output, footprint, header_out)
示例#8
0
def test_consistency_with_horizons(use_DE440s, obstime):
    # Check that the high-accuracy Astropy ephemeris has been set
    assert solar_system_ephemeris.get() == 'de440s'

    # Check whether the location of Earth is the same between Astropy and JPL HORIZONS
    e1 = get_earth(obstime)
    e2 = get_horizons_coord('Geocenter', obstime)
    assert_quantity_allclose(e2.separation_3d(e1), 0 * u.km, atol=50 * u.m)

    # Check whether the location of Mars is the same between Astropy and JPL HORIZONS
    e1 = get_body_heliographic_stonyhurst('mars', obstime)
    e2 = get_horizons_coord('Mars barycenter', obstime)
    assert_quantity_allclose(e2.separation_3d(e1), 0 * u.km, atol=500 * u.m)
示例#9
0
def test_consistency_with_horizons(astropy_ephemeris_de432s, obstime):
    # get_horizons_coord() depends on astroquery
    pytest.importorskip("astroquery")

    # Check whether the location of Earth is the same between Astropy and JPL HORIZONS
    e1 = get_earth(obstime)
    e2 = get_horizons_coord('Geocenter', obstime)
    assert_quantity_allclose(e2.separation_3d(e1), 0 * u.km, atol=50 * u.m)

    # Check whether the location of Mars is the same between Astropy and JPL HORIZONS
    e1 = get_body_heliographic_stonyhurst('mars', obstime)
    e2 = get_horizons_coord('Mars barycenter', obstime)
    assert_quantity_allclose(e2.separation_3d(e1), 0 * u.km, atol=500 * u.m)
示例#10
0
def test_velocity_hgs_hci():
    # HGS and HCI share the same origin and Z axis, so the induced velocity is entirely angular
    obstime = Time(['2021-01-01', '2021-04-01', '2021-07-01', '2021-10-01'])
    venus_hgs = get_body_heliographic_stonyhurst('venus', obstime, include_velocity=True)
    venus_hci = venus_hgs.transform_to(HeliocentricInertial(obstime=obstime))

    # The induced velocity is the longitude component of Earth's velocity, ~360 deg/yr
    induced_dlon = get_earth(obstime, include_velocity=True).heliocentricinertial.d_lon
    assert_quantity_allclose(induced_dlon, 360*u.deg/u.yr, rtol=0.05)

    # The HCI velocity should be the same as the HGS velocity except for the induced velocity
    assert_quantity_allclose(venus_hci.d_distance, venus_hgs.d_radius, rtol=1e-5)
    assert_quantity_allclose(venus_hci.d_lon, venus_hgs.d_lon + induced_dlon, rtol=1e-6)
    assert_quantity_allclose(venus_hci.d_lat, venus_hgs.d_lat)
示例#11
0
def test_reproject_roundtrip(file_format):

    # Test the reprojection with solar data, which ensures that the masking of
    # pixels based on round-tripping works correctly. Using asdf is not just
    # about testing a different format but making sure that GWCS works.

    pytest.importorskip('sunpy', minversion='1.0.4')
    from sunpy.map import Map
    from sunpy.coordinates.ephemeris import get_body_heliographic_stonyhurst

    if file_format == 'fits':
        map_aia = Map(os.path.join(DATA, 'aia_171_level1.fits'))
        data = map_aia.data
        wcs = map_aia.wcs
        date = map_aia.date
        target_wcs = wcs.deepcopy()
    elif file_format == 'asdf':
        pytest.importorskip('astropy', minversion='4.0')
        pytest.importorskip('gwcs', minversion='0.12')
        asdf = pytest.importorskip('asdf')
        aia = asdf.open(os.path.join(DATA, 'aia_171_level1.asdf'))
        data = aia['data'][...]
        wcs = aia['wcs']
        date = wcs.output_frame.reference_frame.obstime
        target_wcs = Map(os.path.join(DATA,
                                      'aia_171_level1.fits')).wcs.deepcopy()
    else:
        raise ValueError('file_format should be fits or asdf')

    # Reproject to an observer on Venus

    target_wcs.wcs.cdelt = ([24, 24] * u.arcsec).to(u.deg)
    target_wcs.wcs.crpix = [64, 64]
    venus = get_body_heliographic_stonyhurst('venus', date)
    target_wcs.heliographic_observer = venus

    output, footprint = reproject_interp((data, wcs), target_wcs, (128, 128))

    return array_footprint_to_hdulist(output, footprint,
                                      target_wcs.to_header())
                    observatory='SOHO',
                    instrument='LASCO',
                    detector='C3')
lasco = sunpy.map.Map(f)

###############################################################################
# A user warning let's you know that there is missing metadata for the observer
# location. sunpy goes ahead and assumes that the observer is at Earth.

print(lasco.observer_coordinate)

###############################################################################
# To check that this worked let's get the location of Mercury in this exposure
# and show that it is in the correct location.

mercury_wrong = get_body_heliographic_stonyhurst(
    'mercury', lasco.date, observer=lasco.observer_coordinate)
mercury_hpc_wrong = mercury_wrong.transform_to(lasco.coordinate_frame)
print(mercury_hpc_wrong)

##############################################################################
# Let's plot how this looks with the incorrect observer information.

fig = plt.figure()
ax = fig.add_subplot(projection=lasco)

# Let's tweak the axis to show in degrees instead of arcsec
lon, lat = ax.coords
lon.set_major_formatter('d.dd')
lat.set_major_formatter('d.dd')
ax.plot_coord(mercury_hpc_wrong,
              's',