Source code for astromodels.core.sky_direction

__author__ = "giacomov"

import collections

from astropy import coordinates

from astromodels.core.parameter import Parameter
from astromodels.core.tree import Node


[docs] class WrongCoordinatePair(ValueError): pass
[docs] class IllegalCoordinateValue(ValueError): pass
[docs] class WrongCoordinateSystem(ValueError): pass
[docs] class SkyDirection(Node): """ This is essentially a wrapper around astropy.coordinates.SkyCoord with a possibility for being serialized and deserialized with YAML. """ def __init__(self, ra=None, dec=None, l=None, b=None, equinox="J2000"): """ :param ra: Right Ascension in degrees :param dec: Declination in degrees :param l: Galactic latitude in degrees :param b: Galactic longitude in degrees :param equinox: string :return: """ self._equinox = equinox # Create the node Node.__init__(self, "position") # Check that we have the right pairs of coordinates if ra is not None and dec is not None: # This goes against duck typing, but it is needed to provide a means of initiating this class # with either Parameter instances or just floats # Try to transform it to float, if it works than we transform it to a parameter ra = self._get_parameter_from_input(ra, 0, 360, "ra", "Right Ascension") dec = self._get_parameter_from_input(dec, -90, 90, "dec", "Declination") self._coord_type = "equatorial" self._add_child(ra) self._add_child(dec) elif l is not None and b is not None: # This goes against duck typing, but it is needed to provide a means of initiating this class # with either Parameter instances or just floats # Try to transform it to float, if it works than we transform it to a parameter l = self._get_parameter_from_input(l, 0, 360, "l", "Galactic longitude") b = self._get_parameter_from_input(b, -90, 90, "b", "Galactic latitude") self._coord_type = "galactic" self._add_child(l) self._add_child(b) else: raise WrongCoordinatePair("You have to specify either (ra, dec) or (l, b).") @staticmethod def _get_parameter_from_input(number_or_parameter, minimum, maximum, what, desc): # Try to transform it to float, if it works than we transform it to a parameter try: number_or_parameter = float(number_or_parameter) except TypeError: assert isinstance(number_or_parameter, Parameter), ( "%s must be either a number or a " "parameter instance" % what ) # So this is a Parameter instance already. Enforce that it has the right maximum and minimum parameter = number_or_parameter assert ( parameter.min_value >= minimum ), "%s must have a minimum greater than or equal to %s" % ( what, minimum, ) assert ( parameter.max_value <= maximum ), "%s must have a maximum less than or equal to %s" % ( what, maximum, ) else: # This was a float. Enforce that it has a legal value assert ( minimum <= number_or_parameter <= maximum ), "%s cannot have a value of %s, " "it must be %s <= %s <= %s" % ( what, number_or_parameter, minimum, what, maximum, ) parameter = Parameter( what, number_or_parameter, desc=desc, min_value=minimum, max_value=maximum, unit="deg", free=False, ) return parameter
[docs] def get_ra(self): """ Get R.A. corresponding to the current position (ICRS, J2000) :return: Right Ascension """ try: return self.ra.value except AttributeError: # Transform from L,B to R.A., Dec return self.sky_coord.transform_to("icrs").ra.value
[docs] def get_dec(self): """ Get Dec. corresponding to the current position (ICRS, J2000) :return: Declination """ try: return self.dec.value except AttributeError: # Transform from L,B to R.A., Dec return self.sky_coord.transform_to("icrs").dec.value
[docs] def get_l(self): """ Get Galactic Longitude (l) corresponding to the current position :return: Galactic Longitude """ try: return self.l.value except AttributeError: # Transform from L,B to R.A., Dec return self.sky_coord.transform_to("galactic").l.value
[docs] def get_b(self): """ Get Galactic latitude (b) corresponding to the current position :return: Latitude """ try: return self.b.value except AttributeError: # Transform from L,B to R.A., Dec return self.sky_coord.transform_to("galactic").b.value
def _get_sky_coord(self): if self._coord_type == "galactic": l = self.l.value b = self.b.value return coordinates.SkyCoord( l=l, b=b, frame="galactic", equinox=self._equinox, unit="deg" ) else: ra = self.ra.value dec = self.dec.value return coordinates.SkyCoord( ra=ra, dec=dec, frame="icrs", equinox=self._equinox, unit="deg" ) @property def sky_coord(self): """ Return an instance of astropy.coordinates.SkyCoord which can be used to make all transformations supported by it :return: astropy.coordinates.SkyCoord """ return self._get_sky_coord() @property def parameters(self): """ Get the dictionary of parameters (either ra,dec or l,b) :return: dictionary of parameters """ if self._coord_type == "galactic": return collections.OrderedDict((("l", self.l), ("b", self.b))) else: return collections.OrderedDict((("ra", self.ra), ("dec", self.dec))) @property def equinox(self): """ Returns the equinox for the coordinates. :return: """ return self._equinox
[docs] def to_dict(self, minimal=False): data = collections.OrderedDict() if self._coord_type == "equatorial": data["ra"] = self.ra.to_dict(minimal) data["dec"] = self.dec.to_dict(minimal) data["equinox"] = self._equinox else: data["l"] = self.l.to_dict(minimal) data["b"] = self.b.to_dict(minimal) data["equinox"] = self._equinox return data
[docs] def fix(self): """ Fix the parameters with the coordinates (either ra,dec or l,b depending on how the class has been instanced) """ if self._coord_type == "equatorial": self.ra.fix = True self.dec.fix = True else: self.l.fix = True self.b.fix = True
[docs] def free(self): """ Free the parameters with the coordinates (either ra,dec or l,b depending on how the class has been instanced) """ if self._coord_type == "equatorial": self.ra.fix = False self.dec.fix = False else: self.l.fix = False self.b.fix = False
[docs] @classmethod def from_dict(cls, data): return cls(**data)
def _repr__base(self, rich_output): if self._coord_type == "equatorial": representation = "Sky direction (R.A., Dec.) = (%.5f, %.5f) (%s)" % ( self.ra.value, self.dec.value, self.equinox, ) else: representation = "Sky direction (l, b) = (%.5f, %.5f) (%s)" % ( self.l.value, self.b.value, self.equinox, ) return representation