diff --git a/astroplan/core.py b/astroplan/core.py index 0349ddba..39a8d54c 100644 --- a/astroplan/core.py +++ b/astroplan/core.py @@ -1681,7 +1681,10 @@ def ra(self): """ if isinstance(self, FixedTarget): return self.coord.ra - raise NotImplementedError() + if isinstance(self. NonFixedTarget): + raise ValueError("NonFixedTarget objects require a time and/or " + "other specifications to calculate a position. " + "Did you mean to do NonFixedTarget.at(args).ra?") @property def dec(self): @@ -1690,8 +1693,10 @@ def dec(self): """ if isinstance(self, FixedTarget): return self.coord.dec - raise NotImplementedError() - + if isinstance(self. NonFixedTarget): + raise ValueError("NonFixedTarget objects require a time and/or " + "other specifications to calculate a position. " + "Did you mean to do NonFixedTarget.at(args).dec?") class FixedTarget(Target): """ @@ -1802,8 +1807,59 @@ def _fixed_target_from_name_mock(cls, name): class NonFixedTarget(Target): """ - Placeholder for future function. + An object that is not "fixed" with respect to the celestial sphere. + + A NonFixedTarget object holds a function that computes the coordinates + of the object at various points in time. + + NonFixedTarget objects can at present be initialized only by the + ``NonFixedTarget.from_name`` class method. """ + def __init__(self, coord_function=None, name=None, constant_kwargs=None): + """ + TODO: Docstring. + """ + self.name = name.lower() if name is not None else name + self.coord_function = coord_function + self.constant_kwargs = constant_kwargs + + @classmethod + def from_function(cls, coord_function, name=None): + """ + Initialize a `~astropy.NonFixedTarget` by passing in a function that + computes a `~astropy.coordinates.SkyCoord` for the target object. + + Parameters + ---------- + coord_function : function + This function takes some input parameters and outputs a + `~astropy.coordinates.SkyCoord` for the object at one instance + in time + + name : str (optional) + Name of the object + """ + return cls(coord_function=coord_function, name=name) + + def at(self, *args, **kwargs): + """ + Get a `~astropy.coordinates.SkyCoord` object for the + `~astroplan.NonFixedTarget` at a given time, and/or other parameters. + + Parameters + ---------- + All arguments and keyword arguments passed to already-specified + ``self.coord_function``. + + Returns + ------- + `~astropy.coordinates.SkyCoord` + Specified by passing the arguments to ``self.coord_function``. + """ + if self.constant_kwargs is not None: + for key in self.constant_kwargs: + kwargs[key] = self.constant_kwargs[key] + return self.coord_function(*args, **kwargs) class Constraint(object): """ diff --git a/astroplan/tests/test_core.py b/astroplan/tests/test_core.py index c80f21c9..7379dd70 100644 --- a/astroplan/tests/test_core.py +++ b/astroplan/tests/test_core.py @@ -2,10 +2,10 @@ unicode_literals) from astropy.coordinates import (EarthLocation, Latitude, Longitude, SkyCoord, - AltAz) + AltAz, get_sun) import astropy.units as u from astropy.time import Time -from astropy.tests.helper import remote_data +from astropy.tests.helper import remote_data, assert_quantity_allclose import numpy as np from numpy.testing import assert_allclose import pytz @@ -14,7 +14,8 @@ from ..sites import get_site from ..core import (FixedTarget, Observer, list_FixedTarget_to_SkyCoord, - MAGIC_TIME) + MAGIC_TIME, NonFixedTarget) +from ..moon import get_moon from ..exceptions import TargetAlwaysUpWarning, TargetNeverUpWarning try: @@ -70,6 +71,31 @@ def test_FixedTarget_from_name(): # Make sure separation is small assert polaris_from_name.coord.separation(polaris_from_SIMBAD) < 1*u.arcsec +def test_NonFixedTarget_sun(): + time = Time("1995-08-31 02:03:04") + sun = NonFixedTarget(coord_function=get_sun, name="Sun") + sun_skycoord_nft = sun.at(time) + + sun_skycoord_getsun = get_sun(time) + tolerance = 0.1*u.arcsec + assert_quantity_allclose(sun_skycoord_nft.ra, sun_skycoord_getsun.ra, + atol=tolerance) + assert_quantity_allclose(sun_skycoord_nft.dec, sun_skycoord_getsun.dec, + atol=tolerance) + +def test_NonFixedTarget_moon(): + time = Time("1995-08-31 02:03:04") + location = get_site("Subaru") + pressure = 0*u.bar + moon = NonFixedTarget(coord_function=get_moon, name="Moon") + moon_skycoord_nft = moon.at(time, location, pressure) + + moon_skycoord_getmoon = get_moon(time, location, pressure) + tolerance = 0.1*u.arcsec + assert_quantity_allclose(moon_skycoord_nft.alt, moon_skycoord_getmoon.alt, + atol=tolerance) + assert_quantity_allclose(moon_skycoord_nft.az, moon_skycoord_getmoon.az, + atol=tolerance) def test_Observer_altaz(): """