diff --git a/source/MulensModel/coordinates.py b/source/MulensModel/coordinates.py index 8bd6e42a..d22ae69e 100644 --- a/source/MulensModel/coordinates.py +++ b/source/MulensModel/coordinates.py @@ -1,7 +1,8 @@ import numpy as np import warnings -from astropy.coordinates import SkyCoord +from astropy.coordinates import SkyCoord, ICRS, FK4, FK5 +from astropy.coordinates import GeocentricTrueEcliptic from astropy import units as u from MulensModel.utils import Utils @@ -36,10 +37,12 @@ class Coordinates(SkyCoord): """ def __init__(self, *args, **kwargs): - if not isinstance(args[0], (SkyCoord, u.quantity.Quantity)): + if isinstance(args[0], str): if 'unit' not in kwargs and len(args) > 0: self._check_for_ra_in_degrees(args[0]) kwargs['unit'] = (u.hourangle, u.deg) + self._validate_input(args[0], kwargs.get('frame')) + SkyCoord.__init__(self, *args, **kwargs) if self.cartesian.xyz.shape not in [(3,), (3, 1)]: raise ValueError( @@ -73,6 +76,29 @@ def _check_for_ra_in_degrees(self, arg): "a default unit for RA is hours (not degrees). " + str(value)) warnings.warn(warning, UserWarning) + def _validate_input(self, arg, frame): + """ + Validate input for coordinates, checking if format is allowed (ICRS, + FK4 or FK5) or raising ValueError otherwise. If SkyCoord() instance + is provided, the frame should be allowed as well. + """ + allowed_fmts = (str, SkyCoord, ICRS, FK4, FK5) + if not isinstance(arg, allowed_fmts): + raise ValueError(f'Coordinate format {type(arg)} is not allowed.') + + if isinstance(arg, str): + if frame not in [None, 'icrs', 'fk4', 'fk5']: + raise ValueError("Only ICRS, FK4 and FK5 frames are allowed" + + " to Coordinates().") + + elif isinstance(arg, (SkyCoord, u.quantity.Quantity)): + test = '18h00m00s -30d00m00s' + is_icrs = arg.is_equivalent_frame(SkyCoord(test, frame='icrs')) + is_fk4 = arg.is_equivalent_frame(SkyCoord(test, frame='fk4')) + is_fk5 = arg.is_equivalent_frame(SkyCoord(test, frame='fk5')) + if not (is_icrs | is_fk4 | is_fk5): + raise ValueError("Provided SkyCoord is not in allowed frame.") + def _calculate_projected(self): """ Calculate North and East directions projected on the plane of the sky. @@ -96,7 +122,7 @@ def galactic_l(self): Galactic longitude. Note that for connivance, the values l > 180 degrees are represented as 360-l. """ - gal_l = self.galactic.l + gal_l = SkyCoord(self).galactic.l if gal_l > 180. * u.deg: gal_l = gal_l - 360. * u.deg return gal_l @@ -108,7 +134,7 @@ def galactic_b(self): Galactic latitude calculated from (RA, Dec) """ - return self.galactic.b + return SkyCoord(self).galactic.b @property def ecliptic_lon(self): @@ -117,8 +143,7 @@ def ecliptic_lon(self): ecliptic longitude calculated from (RA, Dec) """ - from astropy.coordinates import GeocentricTrueEcliptic - return self.transform_to(GeocentricTrueEcliptic).lon + return SkyCoord(self).transform_to(GeocentricTrueEcliptic).lon @property def ecliptic_lat(self): @@ -127,8 +152,7 @@ def ecliptic_lat(self): ecliptic latitude calculated from (RA, Dec) """ - from astropy.coordinates import GeocentricTrueEcliptic - return self.transform_to(GeocentricTrueEcliptic).lat + return SkyCoord(self).transform_to(GeocentricTrueEcliptic).lat @property def north_projected(self): diff --git a/source/MulensModel/tests/test_Coords.py b/source/MulensModel/tests/test_Coords.py index 23c1dee6..87366c9f 100644 --- a/source/MulensModel/tests/test_Coords.py +++ b/source/MulensModel/tests/test_Coords.py @@ -1,6 +1,8 @@ import os +import unittest import numpy as np -from astropy.coordinates import SkyCoord +import pytest +from astropy.coordinates import SkyCoord, ICRS, FK4, FK5, Galactic import astropy.units as u import MulensModel as mm @@ -49,6 +51,32 @@ def test_event_coords(): assert event_3.model.coords.to_string('hmsdms') == new_coord_str +cval = '18h00m00s -30d00m00s' +tested_cs = [(cval, None), (cval, 'fk4'), + (SkyCoord(cval, frame='fk5'), None), (ICRS(*cval.split()), None), + (FK4(*cval.split()), None), (FK5(*cval.split()), None)] +tested_cs2 = [(cval, 'galactic'), (SkyCoord(cval, frame='galactic'), None), + (Galactic(*cval.split()), None)] + + +@pytest.mark.parametrize("coord_test", tested_cs) +def test_coord_validation(coord_test): + """ + Test Coordinates input to accept frames than icrs, fk4 and fk5. + """ + coord_instance = mm.Coordinates(coord_test[0], frame=coord_test[1]) + assert coord_instance.to_string('hmsdms') == cval + + +@pytest.mark.parametrize("coord_test2", tested_cs2) +def test_coord_validation_error(coord_test2): + """ + Test Coordinates input to reject frames different than icrs, fk4 and fk5. + """ + with unittest.TestCase().assertRaises(ValueError): + mm.Coordinates(coord_test2[0], frame=coord_test2[1]) + + def check_event_coords(event, ra, dec): """ For given Event instance event, check if .ra, .model.ra, diff --git a/source/MulensModel/version.py b/source/MulensModel/version.py index 71fae1bc..2c109d88 100644 --- a/source/MulensModel/version.py +++ b/source/MulensModel/version.py @@ -1 +1 @@ -__version__ = "2.19.3" +__version__ = "2.19.4"