예제 #1
0
def test_no_observer():
    # Tests transformations to and from observer-based frames with no observer defined
    frames_in = [Heliocentric(0*u.km, 0*u.km, 0*u.km, observer=None),
                 Heliocentric(0*u.km, 0*u.km, 0*u.km, observer=None, obstime='2001-01-01'),
                 Helioprojective(0*u.deg, 0*u.deg, observer=None),
                 Helioprojective(0*u.deg, 0*u.deg, observer=None, obstime='2001-01-01')]
    frames_out = frames_in + [
        HeliographicStonyhurst(0*u.deg, 0*u.deg, obstime=None),
        HeliographicStonyhurst(0*u.deg, 0*u.deg, obstime='2001-01-01'),
        Heliocentric(0*u.km, 0*u.km, 0*u.km, observer=None, obstime='2012-12-12'),
        Heliocentric(0*u.km, 0*u.km, 0*u.km, observer="earth", obstime=None),
        Heliocentric(0*u.km, 0*u.km, 0*u.km, observer="earth", obstime='2001-01-01'),
        Helioprojective(0*u.deg, 0*u.deg, observer=None, obstime='2012-12-12'),
        Helioprojective(0*u.deg, 0*u.deg, observer="earth", obstime=None),
        Helioprojective(0*u.deg, 0*u.deg, observer="earth", obstime='2001-01-01')]

    # Self-transformations should succeed
    for f in frames_in:
        f.transform_to(f.replicate_without_data())

    # All other transformations should error
    for i, f1 in enumerate(frames_in):
        for f2 in frames_out[i + 1:]:
            with pytest.raises(ConvertError):
                f1.transform_to(f2)
            with pytest.raises(ConvertError):
                f2.transform_to(f1)
예제 #2
0
def test_hgs_hcc_observer_mismatch():
    # Test whether the transformation gives the same answer regardless of what obstime the observer
    # coordinate is represented in
    observer1 = HeliographicStonyhurst(0*u.deg, 0*u.deg, 1*u.AU, obstime='2001-01-01')
    observer2 = observer1.transform_to(HeliographicStonyhurst(obstime='2001-03-31'))

    hgs = HeliographicStonyhurst(20*u.deg, 40*u.deg, 0.5*u.AU, obstime=observer1.obstime)
    hcc1 = hgs.transform_to(Heliocentric(observer=observer1, obstime=hgs.obstime))
    hcc2 = hgs.transform_to(Heliocentric(observer=observer2, obstime=hgs.obstime))

    assert_quantity_allclose(hcc1.cartesian.xyz, hcc2.cartesian.xyz)
예제 #3
0
def test_hcc_to_hgs():
    '''
    Check that a coordinate pointing to the observer in Heliocentric
    coordinates maps to the lattitude/longitude of the observer in
    HeliographicStonyhurst coordinates.
    '''
    lat = 10 * u.deg
    lon = 20 * u.deg
    observer = HeliographicStonyhurst(lat=lat, lon=lon)
    hcc_in = Heliocentric(x=0*u.km, y=0*u.km, z=1*u.km, observer=observer)
    hgs_out = hcc_in.transform_to(HeliographicStonyhurst)

    assert_quantity_allclose(hgs_out.lat, lat)
    assert_quantity_allclose(hgs_out.lon, lon)
예제 #4
0
def test_hcc_to_hgs():
    '''
    Check that a coordinate pointing to the observer in Heliocentric
    coordinates maps to the lattitude/longitude of the observer in
    HeliographicStonyhurst coordinates.
    '''
    lat = 10 * u.deg
    lon = 20 * u.deg
    observer = HeliographicStonyhurst(lat=lat, lon=lon)
    hcc_in = Heliocentric(x=0*u.km, y=0*u.km, z=1*u.km, observer=observer)
    hgs_out = hcc_in.transform_to(HeliographicStonyhurst)

    assert_quantity_allclose(hgs_out.lat, lat)
    assert_quantity_allclose(hgs_out.lon, lon)
예제 #5
0
def test_hpc_hgs_implicit_hcc():
    # An HPC->HGS transformation should give the same answer whether the transformation step
    #   through HCC is implicit or explicit
    start = SkyCoord(0*u.arcsec, 0*u.arcsec, 0.5*u.AU,
                     frame=Helioprojective(obstime='2019-06-01', observer='earth'))
    frame = HeliographicStonyhurst(obstime='2019-12-01')

    implicit = start.transform_to(frame)
    explicit1 = start.transform_to(Heliocentric(obstime=start.obstime, observer='earth')).\
        transform_to(frame)
    explicit2 = start.transform_to(Heliocentric(obstime=frame.obstime, observer='earth')).\
        transform_to(frame)

    assert_quantity_allclose(implicit.separation_3d(explicit1), 0*u.AU, atol=1e-10*u.AU)
    assert_quantity_allclose(implicit.separation_3d(explicit2), 0*u.AU, atol=1e-10*u.AU)
예제 #6
0
def test_hgs_cartesian_rep_to_hcc():
    # This test checks transformation HGS->HCC when the coordinate is in a Cartesian
    # representation and that it is the same as a transformation from an HGS frame with a
    # spherical representation

    obstime = "2011-01-01"
    hgscoord_cart = SkyCoord(x=1*u.km, y=0.*u.km, z=0.*u.km,
                             frame=HeliographicStonyhurst(obstime=obstime),
                             representation_type='cartesian')
    hgscoord_sph = hgscoord_cart.copy()
    hgscoord_sph.representation_type = 'spherical'
    hcccoord_cart = hgscoord_cart.transform_to(Heliocentric(obstime=obstime))
    hcccoord_sph = hgscoord_sph.transform_to(Heliocentric(obstime=obstime))
    assert_quantity_allclose(hcccoord_cart.x, hcccoord_sph.x)
    assert_quantity_allclose(hcccoord_cart.y, hcccoord_sph.y)
    assert_quantity_allclose(hcccoord_cart.z, hcccoord_sph.z)
예제 #7
0
def semi_circular_loop(length, theta0=0 * u.deg):
    r_1 = const.R_sun

    def r_2_func(x):
        return np.arccos(0.5 * x / r_1.to(u.cm).value) - np.pi + length.to(
            u.cm).value / 2. / x

    r_2 = scipy.optimize.bisect(r_2_func,
                                length.to(u.cm).value / (2 * np.pi),
                                length.to(u.cm).value / np.pi) * u.cm
    alpha = np.arccos(0.5 * (r_2 / r_1).decompose())
    phi = np.linspace(-np.pi * u.rad + alpha, np.pi * u.rad - alpha, 2000)
    # Quadratic formula to find r
    a = 1.
    b = -2 * (r_1.to(u.cm) * np.cos(phi.to(u.radian)))
    c = r_1.to(u.cm)**2 - r_2.to(u.cm)**2
    r = (-b + np.sqrt(b**2 - 4 * a * c)) / 2 / a
    # Choose only points above the surface
    i_r = np.where(r > r_1)
    r = r[i_r]
    phi = phi[i_r]
    hcc_frame = Heliocentric(
        observer=SkyCoord(lon=75 * u.deg,
                          lat=25 * u.deg,
                          radius=r_1,
                          frame='heliographic_stonyhurst'))
    return (SkyCoord(y=r.to(u.cm) * np.sin(phi.to(u.radian)),
                     x=u.Quantity(r.shape[0] * [0 * u.cm]),
                     z=r.to(u.cm) * np.cos(phi.to(u.radian)),
                     frame=hcc_frame).transform_to('heliographic_stonyhurst'))
예제 #8
0
def test_hpc_hcc_different_observer_radius():
    # Tests HPC->HCC with a change in observer at different distances from the Sun
    observer1 = HeliographicStonyhurst(0*u.deg, 0*u.deg, 1*u.AU)
    hpc = Helioprojective(0*u.arcsec, 0*u.arcsec, 0.5*u.AU, observer=observer1)

    observer2 = HeliographicStonyhurst(90*u.deg, 0*u.deg, 0.75*u.AU)
    hcc = hpc.transform_to(Heliocentric(observer=observer2))

    assert_quantity_allclose(hcc.x, -0.5*u.AU)
    assert_quantity_allclose(hcc.y, 0*u.AU, atol=1e-10*u.AU)
    assert_quantity_allclose(hcc.z, 0*u.AU, atol=1e-10*u.AU)
예제 #9
0
def test_hcc_hgs_observer_mismatch():
    # Test whether the transformation gives the same answer regardless of what obstime the observer
    # coordinate is represented in
    observer1 = HeliographicStonyhurst(0 * u.deg,
                                       0 * u.deg,
                                       1 * u.AU,
                                       obstime='2001-01-01')
    observer2 = observer1.transform_to(
        HeliographicStonyhurst(obstime='2001-03-31'))

    hcc1 = Heliocentric(0.2 * u.AU,
                        0.3 * u.AU,
                        0.4 * u.AU,
                        observer=observer1,
                        obstime=observer1.obstime)
    hgs1 = hcc1.transform_to(HeliographicStonyhurst(obstime=hcc1.obstime))

    hcc2 = Heliocentric(0.2 * u.AU,
                        0.3 * u.AU,
                        0.4 * u.AU,
                        observer=observer2,
                        obstime=observer1.obstime)
    hgs2 = hcc2.transform_to(HeliographicStonyhurst(obstime=hcc2.obstime))

    assert_quantity_allclose(hgs1.lon, hgs2.lon)
    assert_quantity_allclose(hgs1.lat, hgs2.lat)
    assert_quantity_allclose(hgs1.radius, hgs2.radius)
예제 #10
0
def test_hpc_to_hcc_same_observer():
    # This test checks transformation HPC->HCC in the case of same observer

    rsun = 1*u.m
    D0 = 1 * u.km
    observer = HeliographicStonyhurst(lat=0 * u.deg, lon=0 * u.deg, radius=D0)
    hcc_frame = Heliocentric(observer=observer)
    hpc_frame = Helioprojective(observer=observer, rsun=rsun)
    hpccoord = SkyCoord(Tx=0 * u.arcsec, Ty=0 * u.arcsec, frame=hpc_frame)
    hcccoord_out = hpccoord.transform_to(hcc_frame)
    hcccoord_expected = hpccoord.transform_to(HeliographicStonyhurst).transform_to(hcc_frame)
    assert_quantity_allclose(hcccoord_out.x, hcccoord_expected.x)
    assert_quantity_allclose(hcccoord_out.y, hcccoord_expected.y)
    assert_quantity_allclose(hcccoord_out.z, hcccoord_expected.z)
예제 #11
0
def test_hcc_to_hpc_same_observer():
    # This test checks transformation HCC->HPC in the case of same observer

    rsun = 1*u.m
    D0 = 1*u.km
    observer = HeliographicStonyhurst(lat=0*u.deg, lon=0*u.deg, radius=D0)
    hcc_frame = Heliocentric(observer=observer)
    hpc_frame = Helioprojective(observer=observer, rsun=rsun)
    hcccoord = SkyCoord(x=rsun, y=rsun, z=rsun, frame=hcc_frame)
    hpccoord_out = hcccoord.transform_to(hpc_frame)
    hpccoord_expected = hcccoord.transform_to(HeliographicStonyhurst).transform_to(hpc_frame)
    assert_quantity_allclose(hpccoord_out.Tx, hpccoord_expected.Tx)
    assert_quantity_allclose(hpccoord_out.Ty, hpccoord_expected.Ty)
    assert_quantity_allclose(hpccoord_out.distance, hpccoord_expected.distance)
예제 #12
0
def test_hpc_to_hcc_different_observer():
    # This test checks transformation HPC->HCC in the case where the HCC and HPC frames are
    # defined by different observers.
    # NOTE: This test is currently expected to fail because the HCC<->HPC transformation does
    # not account for observer location. It will be updated once this is fixed.
    D0 = 1 * u.km
    L0 = 1 * u.deg
    observer_1 = HeliographicStonyhurst(lat=0 * u.deg,
                                        lon=0 * u.deg,
                                        radius=D0)
    observer_2 = HeliographicStonyhurst(lat=0 * u.deg, lon=L0, radius=D0)
    hcc_frame = Heliocentric(observer=observer_1)
    hpc_frame = Helioprojective(observer=observer_2)
    hpccoord = SkyCoord(Tx=0 * u.arcsec, Ty=0 * u.arcsec, frame=hpc_frame)
    with pytest.raises(ConvertError):
        hpccoord.transform_to(hcc_frame)
예제 #13
0
def test_hpc_to_hcc_different_observer():
    # This test checks transformation HPC->HCC in the case where the HCC and HPC frames are
    # defined by different observers.

    rsun = 1*u.m
    D0 = 1*u.km
    L0 = 1*u.deg
    observer_1 = HeliographicStonyhurst(lat=0*u.deg, lon=0*u.deg, radius=D0)
    observer_2 = HeliographicStonyhurst(lat=0*u.deg, lon=L0, radius=D0)
    hcc_frame = Heliocentric(observer=observer_1)
    hpc_frame = Helioprojective(observer=observer_2, rsun=rsun)
    hpccoord = SkyCoord(Tx=0*u.arcsec, Ty=0*u.arcsec, frame=hpc_frame)
    hcccoord_out = hpccoord.transform_to(hcc_frame)
    hcccoord_expected = hpccoord.transform_to(HeliographicStonyhurst).transform_to(hcc_frame)
    assert_quantity_allclose(hcccoord_out.x, hcccoord_expected.x)
    assert_quantity_allclose(hcccoord_out.y, hcccoord_expected.y)
    assert_quantity_allclose(hcccoord_out.z, hcccoord_expected.z)
예제 #14
0
def test_hcc_to_hpc_different_observer():
    # This test checks transformation HCC->HPC in the case where the HCC and HPC frames are
    # defined by different observers.

    rsun = 1*u.m
    D0 = 1*u.km
    L0 = 1*u.deg
    observer_1 = HeliographicStonyhurst(lat=0*u.deg, lon=0*u.deg, radius=D0)
    observer_2 = HeliographicStonyhurst(lat=0*u.deg, lon=L0, radius=D0)
    hcc_frame = Heliocentric(observer=observer_1)
    hpc_frame = Helioprojective(observer=observer_2)
    hcccoord = SkyCoord(x=rsun, y=rsun, z=rsun, frame=hcc_frame)
    hpccoord_out = hcccoord.transform_to(hpc_frame)
    hpccoord_expected = hcccoord.transform_to(HeliographicStonyhurst).transform_to(hpc_frame)
    assert_quantity_allclose(hpccoord_out.Tx, hpccoord_expected.Tx)
    assert_quantity_allclose(hpccoord_out.Ty, hpccoord_expected.Ty)
    assert_quantity_allclose(hpccoord_out.distance, hpccoord_expected.distance)
예제 #15
0
def test_hcc_hcc():
    # Test same observer and changing obstime
    observer = HeliographicStonyhurst(0 * u.deg,
                                      0 * u.deg,
                                      1 * u.AU,
                                      obstime='2001-02-01')
    from_hcc = Heliocentric(0.2 * u.AU,
                            0.3 * u.AU,
                            0.4 * u.AU,
                            observer=observer,
                            obstime='2001-01-01')
    to_hcc = from_hcc.transform_to(
        Heliocentric(observer=observer, obstime='2001-03-31'))

    # Since the observer is the same, the coordinates should be nearly the same but not exactly
    # equal due to motion of the origin (the Sun)
    assert np.all(from_hcc.cartesian.xyz != to_hcc.cartesian.xyz)
    assert_quantity_allclose(from_hcc.cartesian.xyz,
                             to_hcc.cartesian.xyz,
                             rtol=2e-3)

    # Test changing observer and same obstime
    observer1 = HeliographicStonyhurst(0 * u.deg,
                                       0 * u.deg,
                                       1 * u.AU,
                                       obstime='2001-01-01')
    observer2 = HeliographicStonyhurst(0 * u.deg,
                                       0 * u.deg,
                                       1 * u.AU,
                                       obstime='2001-03-31')
    from_hcc = Heliocentric(0.2 * u.AU,
                            0.3 * u.AU,
                            0.4 * u.AU,
                            observer=observer1,
                            obstime='2001-02-01')
    to_hcc = from_hcc.transform_to(
        Heliocentric(observer=observer2, obstime='2001-02-01'))

    # This change in observer is approximately a 90-degree rotation about the Y axis
    assert_quantity_allclose(to_hcc.x, -from_hcc.z, rtol=2e-3)
    assert_quantity_allclose(to_hcc.y, from_hcc.y, rtol=2e-3)
    assert_quantity_allclose(to_hcc.z, from_hcc.x, rtol=2e-3)
예제 #16
0
def test_hgs_hcc_sunspice():
    # Compare our HGS->HCC transformation against SunSPICE
    # "HEQ" is another name for HEEQ, which is equivalent to Heliographic Stonyhurst
    # "HGRTN" is equivalent to our Heliocentric, but with the axes permuted
    # SunSPICE, like us, assumes an Earth observer if not explicitly specified
    #
    # IDL> coord = [7d5, 8d5, 9d5]
    # IDL> convert_sunspice_coord, '2019-06-01', coord, 'HEQ', 'HGRTN'
    # Assuming Earth observation
    # IDL> print, coord
    #        688539.32       800000.00       908797.89

    old = SkyCoord(CartesianRepresentation([7e5, 8e5, 9e5]*u.km),
                   frame=HeliographicStonyhurst(obstime='2019-06-01'))
    new = old.transform_to(Heliocentric(observer='earth'))

    assert_quantity_allclose(new.x, 800000.00*u.km, atol=1e-2*u.km)
    assert_quantity_allclose(new.y, 908797.89*u.km, atol=1e-2*u.km)
    assert_quantity_allclose(new.z, 688539.32*u.km, atol=1e-2*u.km)
예제 #17
0
def _warp_sun_coordinates(xy, smap, new_observer, **diff_rot_kwargs):
    """
    This function takes pixel coordinates in the warped image (`xy`) and
    calculates the pixel locations of those pixels in the map.

    To do this it converts the input pixel coordinates to helioprojective
    coordinates as seen by new_observer, then transforms them to heliographic
    Stonyhurst, adds the differential rotation correction and then transforms
    them back to helioprojective coordinates as seen by the map observer and
    then calculates their corresponding pixel coordinates in the input map.

    This is an inverse function needed by `skimage.transform.warp`.

    Parameters
    ----------
    xy : `numpy.ndarray`
        Pixel coordinates in the warped image.
    smap : `~sunpy.map.GenericMap`
        Original map that we want to transform.

    Returns
    -------
    xy2 : `numpy.ndarray`
        Pixel coordinates in the map corresponding to the input pixels in the
        warped image.
    """
    # Suppress NaN warnings in coordinate transforms
    with warnings.catch_warnings():
        warnings.simplefilter('ignore')

        # The time interval between the new observer time and the map observation time.
        interval = (parse_time(new_observer.obstime) -
                    parse_time(smap.date)).to(u.s)

        # We need to get the input pixel coordinates into the OUTPUT HPC frame.
        # To save us having to construct a WCS etc, we do the transformation
        # using the output map, and then replace the observer in place before
        # transforming to HGS. This is acceptable because the pixel -> world
        # transformation is independent of the observer.
        input_pixels = xy.T * u.pix
        map_coord = smap.pixel_to_world(*input_pixels)
        output_hpc_coords = SkyCoord(map_coord.Tx,
                                     map_coord.Ty,
                                     map_coord.distance,
                                     obstime=new_observer.obstime,
                                     observer=new_observer,
                                     frame=Helioprojective)

        heliographic_coordinate = output_hpc_coords.transform_to(
            HeliographicStonyhurst)
        # Now transform the HGS coordinates to the obstime of the input map (to account for movement of Earth)
        heliographic_coordinate = heliographic_coordinate.transform_to(
            HeliographicStonyhurst(obstime=smap.date))

        # Compute the differential rotation.
        drot = diff_rot(interval, heliographic_coordinate.lat.to(u.degree),
                        **diff_rot_kwargs)

        # The change in longitude is negative because we are mapping from the
        # new coordinates to the old.
        rotated_coord = SkyCoord(heliographic_coordinate.lon - drot,
                                 heliographic_coordinate.lat,
                                 heliographic_coordinate.radius,
                                 obstime=heliographic_coordinate.obstime,
                                 frame=HeliographicStonyhurst)

        # As seen from the map observer, which coordinates are on disk and which are behind the Sun.
        where_off_disk_from_map_observer = rotated_coord.transform_to(
            Heliocentric(observer=smap.observer_coordinate)).z.value < 0

        # Re-project the pixels which are on disk back to location of the original observer
        coordinates_at_map_observer = rotated_coord.transform_to(
            smap.coordinate_frame)

        # Go back to pixel co-ordinates
        x2, y2 = smap.world_to_pixel(coordinates_at_map_observer)

    # Re-stack the data to make it correct output form
    xy2 = np.dstack([x2.T.value.flat, y2.T.value.flat])[0]
    # Set the off disk coordinates to NaN so they are not included in the output image.
    xy2[where_off_disk_from_map_observer.flat] = np.nan

    return xy2