예제 #1
0
def allowedPos(world_pos, date):
    """
    This routine can be used to check whether WFIRST would be allowed to look at a particular
    position (`world_pos`) on a given `date`.   This is determined by the angle of this position
    relative to the Sun.

    In general, WFIRST can point at angles relative to the Sun in the range 90+/-36 degrees.
    Obviously, pointing too close to the Sun would result in overly high sky backgrounds.  It is
    less obvious why WFIRST cannot look at a spot directly opposite from the Sun (180 degrees on the
    sky).  The reason is that the observatory is aligned such that if the observer is looking at
    some sky position, the solar panels are oriented at 90 degrees from that position.  So it's
    always optimal for the observatory to be pointing at an angle of 90 degrees relative to the
    Sun.  It is also permitted to look within 36 degrees of that optimal position. 

    @param world_pos      A galsim.CelestialCoord indicating the position at which the observer
                          wishes to look.
    @param date           A python datetime object indicating the desired date of observation.
    @returns True or False, indicating whether it is permitted to look at this position on this
             date.
    """
    # Find the Sun's location on the sky on this date.
    from galsim.celestial import _ecliptic_to_equatorial, _sun_position_ecliptic
    sun = _ecliptic_to_equatorial(_sun_position_ecliptic(date), date.year)

    # Find the angle between that and the supplied position
    angle_deg = abs(world_pos.distanceTo(sun) / galsim.degrees)

    # Check if it's within tolerance.
    min_ang = 90. - 36.
    max_ang = 90. + 36.
    return angle_deg >= min_ang and angle_deg <= max_ang
예제 #2
0
def bestPA(world_pos, date):
    """
    This routine determines the best position angle for the observatory for a given observation date
    and position on the sky.

    The best/optimal position angle is determined by the fact that the solar panels are at 90
    degrees to the position being observed, and it is best to have those facing the Sun as directly
    as possible.  Note that if a given `world_pos` is not actually observable on the given `date`,
    then this routine will return None.

    @param world_pos      A galsim.CelestialCoord indicating the position at which the observer
                          wishes to look.
    @param date           A python datetime object indicating the desired date of observation.
    @returns the best position angle for the observatory, as a galsim.Angle, or None if the position
             is not observable.
    """
    # First check for observability.
    if not allowedPos(world_pos, date):
        return None

    # Find the location of the sun on this date.  +X_observatory points out into the sky, towards
    # world_pos, while +Z is in the plane of the sky pointing towards the sun as much as possible.
    from galsim.celestial import _ecliptic_to_equatorial, _sun_position_ecliptic
    sun = _ecliptic_to_equatorial(_sun_position_ecliptic(date), date.year)
    # Now we do a projection onto the sky centered at world_pos to find the (u, v) for the Sun.
    sun_tp = world_pos.project(sun, 'gnomonic')
    # We want to rotate around by 90 degrees to find the +Y obs direction.  Specifically, we want
    # (+X, +Y, +Z)_obs to form a right-handed coordinate system.
    y_obs_tp = galsim.PositionD(-sun_tp.y, sun_tp.x)
    y_obs = world_pos.deproject(y_obs_tp, 'gnomonic')

    # Finally the observatory position angle is defined by the angle between +Y_observatory and the
    # celestial north pole.  It is defined as position angle east of north.
    north = galsim.CelestialCoord(y_obs.ra, 90. * galsim.degrees)
    obs_pa = world_pos.angleBetween(y_obs, north)
    return obs_pa
예제 #3
0
def test_ecliptic():
    """Test the conversion from equatorial to ecliptic coordinates."""
    # Use locations of ecliptic poles from http://en.wikipedia.org/wiki/Ecliptic_pole
    north_pole = galsim.CelestialCoord(galsim.HMS_Angle('18:00:00.00'),
                                       galsim.DMS_Angle('66:33:38.55'))
    el, b = north_pole.ecliptic()
    # North pole should have b=90 degrees, with el being completely arbitrary.
    numpy.testing.assert_almost_equal(b.rad(), pi / 2, decimal=6)

    south_pole = galsim.CelestialCoord(galsim.HMS_Angle('06:00:00.00'),
                                       galsim.DMS_Angle('-66:33:38.55'))
    el, b = south_pole.ecliptic()
    # South pole should have b=-90 degrees, with el being completely arbitrary.
    numpy.testing.assert_almost_equal(b.rad(), -pi / 2, decimal=6)

    # Also confirm that positions that should be the same in equatorial and ecliptic coordinates are
    # actually the same:
    vernal_equinox = galsim.CelestialCoord(0. * galsim.radians,
                                           0. * galsim.radians)
    el, b = vernal_equinox.ecliptic()
    numpy.testing.assert_almost_equal(b.rad(), 0., decimal=6)
    numpy.testing.assert_almost_equal(el.rad(), 0., decimal=6)
    autumnal_equinox = galsim.CelestialCoord(pi * galsim.radians,
                                             0. * galsim.radians)
    el, b = autumnal_equinox.ecliptic()
    numpy.testing.assert_almost_equal(el.rad(), pi, decimal=6)
    numpy.testing.assert_almost_equal(b.rad(), 0., decimal=6)

    # Finally, test the results of using a date to get ecliptic coordinates with respect to the sun,
    # instead of absolute ones. For this, use dates and times of vernal and autumnal equinox
    # in 2014 from
    # http://wwp.greenwichmeantime.com/longest-day/
    # and the conversion to Julian dates from
    # http://www.aavso.org/jd-calculator
    import datetime
    vernal_eq_date = datetime.datetime(2014, 3, 20, 16, 57, 0)
    el, b = vernal_equinox.ecliptic(epoch=2014)
    el_rel, b_rel = vernal_equinox.ecliptic(epoch=2014, date=vernal_eq_date)
    # Vernal equinox: should have (el, b) = (el_rel, b_rel) = 0.0
    numpy.testing.assert_almost_equal(el_rel.rad(), el.rad(), decimal=3)
    numpy.testing.assert_almost_equal(b_rel.rad(), b.rad(), decimal=6)
    # Now do the autumnal equinox: should have (el, b) = (pi, 0) = (el_rel, b_rel) when we look at
    # the time of the vernal equinox.
    el, b = autumnal_equinox.ecliptic(epoch=2014)
    el_rel, b_rel = autumnal_equinox.ecliptic(epoch=2014, date=vernal_eq_date)
    numpy.testing.assert_almost_equal(el_rel.rad(), el.rad(), decimal=3)
    numpy.testing.assert_almost_equal(b_rel.rad(), b.rad(), decimal=6)
    # And check that if it's the date of the autumnal equinox (sun at (180, 0)) but we're looking at
    # the position of the vernal equinox (0, 0), then (el_rel, b_rel) = (-180, 0)
    autumnal_eq_date = datetime.datetime(2014, 9, 23, 2, 29, 0)
    el_rel, b_rel = vernal_equinox.ecliptic(epoch=2014, date=autumnal_eq_date)
    numpy.testing.assert_almost_equal(el_rel.rad(), -pi, decimal=3)
    numpy.testing.assert_almost_equal(b_rel.rad(), 0., decimal=6)
    # And check that if it's the date of the vernal equinox (sun at (0, 0)) but we're looking at
    # the position of the autumnal equinox (180, 0), then (el_rel, b_rel) = (180, 0)
    el_rel, b_rel = autumnal_equinox.ecliptic(epoch=2014, date=vernal_eq_date)
    numpy.testing.assert_almost_equal(el_rel.rad(), pi, decimal=3)
    numpy.testing.assert_almost_equal(b_rel.rad(), 0., decimal=6)

    # Check round-trips: go from CelestialCoord to ecliptic back to equatorial, and make sure
    # results are the same.  This includes use of a function that isn't available to users, but we
    # use it for a few things so we should still make sure it's working properly.
    from galsim.celestial import _ecliptic_to_equatorial
    north_pole_2 = _ecliptic_to_equatorial(north_pole.ecliptic(epoch=2014),
                                           2014)
    numpy.testing.assert_almost_equal(north_pole.ra.rad(),
                                      north_pole_2.ra.rad(),
                                      decimal=6)
    numpy.testing.assert_almost_equal(north_pole.dec.rad(),
                                      north_pole_2.dec.rad(),
                                      decimal=6)
    south_pole_2 = _ecliptic_to_equatorial(south_pole.ecliptic(epoch=2014),
                                           2014)
    numpy.testing.assert_almost_equal(south_pole.ra.rad(),
                                      south_pole_2.ra.rad(),
                                      decimal=6)
    numpy.testing.assert_almost_equal(south_pole.dec.rad(),
                                      south_pole_2.dec.rad(),
                                      decimal=6)
    vernal_equinox_2 = _ecliptic_to_equatorial(
        vernal_equinox.ecliptic(epoch=2014), 2014)
    numpy.testing.assert_almost_equal(vernal_equinox.ra.rad(),
                                      vernal_equinox_2.ra.rad(),
                                      decimal=6)
    numpy.testing.assert_almost_equal(vernal_equinox.dec.rad(),
                                      vernal_equinox_2.dec.rad(),
                                      decimal=6)
    autumnal_equinox_2 = _ecliptic_to_equatorial(
        autumnal_equinox.ecliptic(epoch=2014), 2014)
    numpy.testing.assert_almost_equal(autumnal_equinox.ra.rad(),
                                      autumnal_equinox_2.ra.rad(),
                                      decimal=6)
    numpy.testing.assert_almost_equal(autumnal_equinox.dec.rad(),
                                      autumnal_equinox_2.dec.rad(),
                                      decimal=6)