Exemple #1
0
    def get_solar_params_from_string(arg):
        """Return Galactocentric solar parameters given string names for the
        parameter sets.
        """
        # Resolve the meaning of 'latest': The latest parameter set is from v4.0
        # - update this as newer parameter choices are added
        if arg == 'latest':
            arg = 'v4.0'

        params = dict()
        references = dict()

        # Currently, all versions use the same sky position for Sgr A*:
        params['galcen_coord'] = ICRS(ra=266.4051*u.degree,
                                      dec=-28.936175*u.degree)
        references['galcen_coord'] = \
            'http://adsabs.harvard.edu/abs/2004ApJ...616..872R'

        # The roll angle is the same for both frames:
        params['roll'] = 0 * u.deg

        if arg == 'pre-v4.0':
            params['galcen_distance'] = 8.3 * u.kpc
            references['galcen_distance'] = \
                'https://ui.adsabs.harvard.edu/#abs/2009ApJ...692.1075G'

            params['galcen_v_sun'] = r.CartesianDifferential([11.1,
                                                              220+12.24,
                                                              7.25]*u.km/u.s)
            references['galcen_v_sun'] = \
                ['https://ui.adsabs.harvard.edu/#abs/2010MNRAS.403.1829S',
                 'https://ui.adsabs.harvard.edu/#abs/2015ApJS..216...29B']

            params['z_sun'] = 27.0 * u.pc
            references['z_sun'] = \
                'https://ui.adsabs.harvard.edu/#abs/2001ApJ...553..184C'

        elif arg == 'v4.0':
            params['galcen_distance'] = 8.122 * u.kpc
            references['galcen_distance'] = \
                'https://ui.adsabs.harvard.edu/abs/2018A%26A...615L..15G'

            params['galcen_v_sun'] = r.CartesianDifferential([12.9,
                                                              245.6,
                                                              7.78]*u.km/u.s)
            references['galcen_v_sun'] = \
                ['https://ui.adsabs.harvard.edu/abs/2018RNAAS...2..210D',
                 'https://ui.adsabs.harvard.edu/abs/2018A%26A...615L..15G',
                 'https://ui.adsabs.harvard.edu/abs/2004ApJ...616..872R']

            params['z_sun'] = 20.8 * u.pc
            references['z_sun'] = \
                'https://ui.adsabs.harvard.edu/abs/2019MNRAS.482.1417B'

        else:
            raise ValueError('Invalid string input to retrieve solar '
                             'parameters for Galactocentric frame: "{}"'
                             .format(arg))

        return params, references
Exemple #2
0
def test_representation_with_multiple_differentials():
    from astropy.coordinates.builtin_frames import ICRS

    dif1 = r.CartesianDifferential([1, 2, 3]*u.km/u.s)
    dif2 = r.CartesianDifferential([1, 2, 3]*u.km/u.s**2)
    rep = r.CartesianRepresentation([1, 2, 3]*u.pc,
                                    differentials={'s': dif1, 's2': dif2})

    # check warning is raised for a scalar
    with pytest.raises(ValueError):
        ICRS(rep)
Exemple #3
0
def test_vel_transformation_obstime_err():
    # TODO: replace after a final decision on PR #6280
    from astropy.coordinates.sites import get_builtin_sites

    diff = r.CartesianDifferential([.1, .2, .3]*u.km/u.s)
    rep = r.CartesianRepresentation([1, 2, 3]*u.au, differentials=diff)

    loc = get_builtin_sites()['example_site']

    aaf = AltAz(obstime='J2010', location=loc)
    aaf2 = AltAz(obstime=aaf.obstime + 3*u.day, location=loc)
    aaf3 = AltAz(obstime=aaf.obstime + np.arange(3)*u.day, location=loc)
    aaf4 = AltAz(obstime=aaf.obstime, location=loc)

    aa = aaf.realize_frame(rep)

    with pytest.raises(NotImplementedError) as exc:
        aa.transform_to(aaf2)
    assert 'cannot transform' in exc.value.args[0]

    with pytest.raises(NotImplementedError) as exc:
        aa.transform_to(aaf3)
    assert 'cannot transform' in exc.value.args[0]

    aa.transform_to(aaf4)

    aa.transform_to(ICRS())
Exemple #4
0
def test_differentialattribute():
    from astropy.coordinates import BaseCoordinateFrame
    from astropy.coordinates.attributes import DifferentialAttribute

    # Test logic of passing input through to allowed class
    vel = [1, 2, 3] * u.km / u.s
    dif = r.CartesianDifferential(vel)

    class TestFrame(BaseCoordinateFrame):
        attrtest = DifferentialAttribute(
            default=dif, allowed_classes=[r.CartesianDifferential])

    frame1 = TestFrame()
    frame2 = TestFrame(attrtest=dif)
    frame3 = TestFrame(attrtest=vel)

    assert np.all(frame1.attrtest.d_xyz == frame2.attrtest.d_xyz)
    assert np.all(frame1.attrtest.d_xyz == frame3.attrtest.d_xyz)

    # This shouldn't work if there is more than one allowed class:
    class TestFrame2(BaseCoordinateFrame):
        attrtest = DifferentialAttribute(default=dif,
                                         allowed_classes=[
                                             r.CartesianDifferential,
                                             r.CylindricalDifferential
                                         ])

    frame1 = TestFrame2()
    frame2 = TestFrame2(attrtest=dif)
    with pytest.raises(TypeError):
        TestFrame2(attrtest=vel)
Exemple #5
0
class transfunc:
    rep = r.CartesianRepresentation(np.arange(3)*u.pc)
    dif = r.CartesianDifferential(*np.arange(3, 6)*u.pc/u.Myr)
    rep0 = r.CartesianRepresentation(np.zeros(3)*u.pc)

    @classmethod
    def both(cls, coo, fr):
        # exchange x <-> z and offset
        M = np.array([[0., 0., 1.],
                      [0., 1., 0.],
                      [1., 0., 0.]])
        return M, cls.rep.with_differentials(cls.dif)

    @classmethod
    def just_matrix(cls, coo, fr):
        # exchange x <-> z and offset
        M = np.array([[0., 0., 1.],
                      [0., 1., 0.],
                      [1., 0., 0.]])
        return M, None

    @classmethod
    def no_matrix(cls, coo, fr):
        return None, cls.rep.with_differentials(cls.dif)

    @classmethod
    def no_pos(cls, coo, fr):
        return None, cls.rep0.with_differentials(cls.dif)

    @classmethod
    def no_vel(cls, coo, fr):
        return None, cls.rep
Exemple #6
0
def test_too_many_differentials():
    dif1 = r.CartesianDifferential(*np.arange(3, 6)*u.pc/u.Myr)
    dif2 = r.CartesianDifferential(*np.arange(3, 6)*u.pc/u.Myr**2)
    rep = r.CartesianRepresentation(np.arange(3)*u.pc,
                                    differentials={'s': dif1, 's2': dif2})

    with pytest.raises(ValueError):
        c = TCoo1(rep)

    # register and do the transformation and check against expected
    trans = t.AffineTransform(transfunc.both, TCoo1, TCoo2)
    trans.register(frame_transform_graph)

    # Check that if frame somehow gets through to transformation, multiple
    # differentials are caught
    c = TCoo1(rep.without_differentials())
    c._data = c._data.with_differentials({'s': dif1, 's2': dif2})
    with pytest.raises(ValueError):
        c.transform_to(TCoo2())

    trans.unregister(frame_transform_graph)
 def __init__(self, *args, **kwargs):
     # based on Luri et al 2020 including "main" line in table 5
     default_params = {
         'gal_coord': ICRS(ra=81.28 * u.degree, dec=-69.78 * u.degree),
         "gal_distance": 49.5 * u.kpc,
         "galvel_heliocentric": r.CartesianDifferential([439.0, 91.7, 262.2] * (u.km / u.s)),
         "inclination": 34.08 * u.degree,
         "PA": 309.9 * u.degree,
     }
     kwds = dict()
     kwds.update(default_params)
     kwds.update(kwargs)
     super().__init__(*args, **kwds)
 def __init__(self, *args, **kwargs):
     # these values for comparison with vdm12 transformation - not necessarily current
     default_params = {
         'gal_coord': ICRS(ra=10.68470833 * u.degree, dec=41.26875 * u.degree),
         "gal_distance": 770.0 * u.kpc,
         "galvel_heliocentric": r.CartesianDifferential([178.9, -138.8, -301.] * (u.km / u.s)),
         "inclination": (-77.) * u.degree,
         "PA": 37. * u.degree,
     }
     kwds = dict()
     kwds.update(default_params)
     kwds.update(kwargs)
     super().__init__(*args, **kwds)
Exemple #9
0
def test_affine_transform_fail(transfunc):
    diff = r.CartesianDifferential(8, 9, 10, unit=u.pc/u.Myr)
    rep = r.CartesianRepresentation(5, 6, 7, unit=u.pc, differentials=diff)
    c = TCoo1(rep)

    # register and do the transformation and check against expected
    trans = t.AffineTransform(transfunc, TCoo1, TCoo2)
    trans.register(frame_transform_graph)

    with pytest.raises(ValueError):
        c.transform_to(TCoo2())

    trans.unregister(frame_transform_graph)
 def __init__(self, *args, **kwargs):
     # these values for comparison with vdm12 transformation - not necessarily current
     default_params = {
         'gal_coord': ICRS(ra=23.4621 * u.degree, dec=30.65994167 * u.degree),
         "gal_distance": 794.0 * u.kpc,
         # "gal_distance": 810.0 * u.kpc,
         "galvel_heliocentric": r.CartesianDifferential([87.3, 28.2, -180.] * (u.km / u.s)),
         "inclination": (-55.) * u.degree,
         "PA": 23. * u.degree,
     }
     kwds = dict()
     kwds.update(default_params)
     kwds.update(kwargs)
     super().__init__(*args, **kwds)
def test_shorthand_representations():
    from astropy.coordinates.builtin_frames import ICRS

    rep = r.CartesianRepresentation([1, 2, 3] * u.pc)
    dif = r.CartesianDifferential([1, 2, 3] * u.km / u.s)
    rep = rep.with_differentials(dif)

    icrs = ICRS(rep)

    sph = icrs.spherical
    assert isinstance(sph, r.SphericalRepresentation)
    assert isinstance(sph.differentials['s'], r.SphericalDifferential)

    sph = icrs.sphericalcoslat
    assert isinstance(sph, r.SphericalRepresentation)
    assert isinstance(sph.differentials['s'], r.SphericalCosLatDifferential)
 def __init__(self, *args, skyalign=False, **kwargs):
     # left some example code for subclasses in here
     default_params = {
         'gal_coord': ICRS(ra=10.68470833 * u.degree, dec=41.26875 * u.degree),
         "gal_distance": 780.0 * u.kpc,
         "galvel_heliocentric": r.CartesianDifferential([125.2, -73.8, -300.] * (u.km / u.s)),
         "inclination": (-77.) * u.degree,
         "PA": 37. * u.degree,
     }
     kwds = dict()
     kwds.update(default_params)
     if skyalign:
         kwds['inclination'] = 0. * u.deg
         kwds['PA'] = 0. * u.deg
     kwds.update(kwargs)
     super().__init__(*args, **kwds)
def get_galvel(pmra, pmdec, radial_velocity, distance):
    """Utility routine to retrieve a CartesianDifferential from proper motion, velocity, and distance.

    This is useful to initialize an ExternalGalaxyFrame, by passing the keyword galvel_heliocentric=get_galvel(
         1.0*u.mas/u.yr, 2.0*u.mas/u.yr, radial_velocity=250.*u.km/u.s, distance=400.*u.kpc)
    Parameters:
        pmra, pmdec: Quantity dimension of angle/time
            Proper motion in RA, dec directions. Here pmra means metric and not coordinate velocity
            (i.e., cos factor should be included)
        radial_velocity: Quantity, dimension of velocity
            Heliocentric radial velocity
        distance: Quantity, dimension of length
            Heliocentric distance
    """
    v_x = (pmra * distance / u.rad).to(u.km / u.s)
    v_y = (pmdec * distance / u.rad).to(u.km / u.s)
    v_z = radial_velocity.to(u.km / u.s)
    return r.CartesianDifferential(v_x, v_y, v_z)
Exemple #14
0
from astropy.coordinates import representation as r
from astropy.coordinates.baseframe import (BaseCoordinateFrame,
                                           RepresentationMapping,
                                           frame_transform_graph, base_doc)
from astropy.coordinates.transformations import AffineTransform
from astropy.coordinates.attributes import DifferentialAttribute

from .baseradec import BaseRADecFrame, doc_components as doc_components_radec
from .icrs import ICRS
from .galactic import Galactic
from .fk4 import FK4

# For speed
J2000 = Time('J2000')

v_bary_Schoenrich2010 = r.CartesianDifferential([11.1, 12.24, 7.25]*u.km/u.s)

__all__ = ['LSR', 'GalacticLSR', 'LSRK', 'LSRD']


doc_footer_lsr = """
    Other parameters
    ----------------
    v_bary : `~astropy.coordinates.representation.CartesianDifferential`
        The velocity of the solar system barycenter with respect to the LSR, in
        Galactic cartesian velocity components.
"""


@format_doc(base_doc, components=doc_components_radec, footer=doc_footer_lsr)
class LSR(BaseRADecFrame):
Exemple #15
0
class galactocentric_frame_defaults(ScienceState):
    """This class controls the global setting of default values for the frame
    attributes in the `~astropy.coordinates.Galactocentric` frame, which may be
    updated in future versions of ``astropy``. Note that when using
    `~astropy.coordinates.Galactocentric`, changing values here will not affect
    any attributes that are set explicitly by passing values in to the
    `~astropy.coordinates.Galactocentric` initializer. Modifying these defaults
    will only affect the frame attribute values when using the frame as, e.g.,
    ``Galactocentric`` or ``Galactocentric()`` with no explicit arguments.

    This class controls the parameter settings by specifying a string name,
    with the following pre-specified options:

    - 'pre-v4.0': The current default value, which sets the default frame
      attribute values to their original (pre-astropy-v4.0) values.
    - 'v4.0': The attribute values as updated in Astropy version 4.0.
    - 'latest': An alias of the most recent parameter set (currently: 'v4.0')

    Alternatively, user-defined parameter settings may be registered, with
    :meth:`~astropy.coordinates.galactocentric_frame_defaults.register`,
    and used identically as pre-specified parameter sets. At minimum,
    registrations must have unique names and a dictionary of parameters
    with keys "galcen_coord", "galcen_distance", "galcen_v_sun", "z_sun",
    "roll". See examples below.

    This class also tracks the references for all parameter values in the
    attribute ``references``, as well as any further information the registry.
    The pre-specified options can be extended to include similar
    state information as user-defined parameter settings -- for example, to add
    parameter uncertainties.

    The preferred method for getting a parameter set and metadata, by name, is
    :meth:`~galactocentric_frame_defaults.get_from_registry` since
    it ensures the immutability of the registry.

    See :ref:`astropy:astropy-coordinates-galactocentric-defaults` for more
    information.

    Examples
    --------
    The default `~astropy.coordinates.Galactocentric` frame parameters can be
    modified globally::

        >>> from astropy.coordinates import galactocentric_frame_defaults
        >>> _ = galactocentric_frame_defaults.set('v4.0') # doctest: +SKIP
        >>> Galactocentric() # doctest: +SKIP
        <Galactocentric Frame (galcen_coord=<ICRS Coordinate: (ra, dec) in deg
            (266.4051, -28.936175)>, galcen_distance=8.122 kpc, galcen_v_sun=(12.9, 245.6, 7.78) km / s, z_sun=20.8 pc, roll=0.0 deg)>
        >>> _ = galactocentric_frame_defaults.set('pre-v4.0') # doctest: +SKIP
        >>> Galactocentric() # doctest: +SKIP
        <Galactocentric Frame (galcen_coord=<ICRS Coordinate: (ra, dec) in deg
            (266.4051, -28.936175)>, galcen_distance=8.3 kpc, galcen_v_sun=(11.1, 232.24, 7.25) km / s, z_sun=27.0 pc, roll=0.0 deg)>

    The default parameters can also be updated by using this class as a context
    manager::

        >>> with galactocentric_frame_defaults.set('pre-v4.0'):
        ...     print(Galactocentric()) # doctest: +FLOAT_CMP
        <Galactocentric Frame (galcen_coord=<ICRS Coordinate: (ra, dec) in deg
            (266.4051, -28.936175)>, galcen_distance=8.3 kpc, galcen_v_sun=(11.1, 232.24, 7.25) km / s, z_sun=27.0 pc, roll=0.0 deg)>

    Again, changing the default parameter values will not affect frame
    attributes that are explicitly specified::

        >>> import astropy.units as u
        >>> with galactocentric_frame_defaults.set('pre-v4.0'):
        ...     print(Galactocentric(galcen_distance=8.0*u.kpc)) # doctest: +FLOAT_CMP
        <Galactocentric Frame (galcen_coord=<ICRS Coordinate: (ra, dec) in deg
            (266.4051, -28.936175)>, galcen_distance=8.0 kpc, galcen_v_sun=(11.1, 232.24, 7.25) km / s, z_sun=27.0 pc, roll=0.0 deg)>

    Additional parameter sets may be registered, for instance to use the
    Dehnen & Binney (1998) measurements of the solar motion. We can also
    add metadata, such as the 1-sigma errors. In this example we will modify
    the required key "parameters", change the recommended key "references" to
    match "parameters", and add the extra key "error" (any key can be added)::

        >>> state = galactocentric_frame_defaults.get_from_registry("v4.0")
        >>> state["parameters"]["galcen_v_sun"] = (10.00, 225.25, 7.17) * (u.km / u.s)
        >>> state["references"]["galcen_v_sun"] = "https://ui.adsabs.harvard.edu/full/1998MNRAS.298..387D"
        >>> state["error"] = {"galcen_v_sun": (0.36, 0.62, 0.38) * (u.km / u.s)}
        >>> galactocentric_frame_defaults.register(name="DB1998", **state)

    Just as in the previous examples, the new parameter set can be retrieved with::

        >>> state = galactocentric_frame_defaults.get_from_registry("DB1998")
        >>> print(state["error"]["galcen_v_sun"])  # doctest: +FLOAT_CMP
        [0.36 0.62 0.38] km / s

    """

    _latest_value = 'v4.0'
    _value = None
    _references = None
    _state = dict()  # all other data

    # Note: _StateProxy() produces read-only view of enclosed mapping.
    _registry = {
        "v4.0": {
            "parameters": _StateProxy(
                {
                    "galcen_coord": ICRS(
                        ra=266.4051 * u.degree, dec=-28.936175 * u.degree
                    ),
                    "galcen_distance": 8.122 * u.kpc,
                    "galcen_v_sun": r.CartesianDifferential(
                        [12.9, 245.6, 7.78] * (u.km / u.s)
                    ),
                    "z_sun": 20.8 * u.pc,
                    "roll": 0 * u.deg,
                }
            ),
            "references": _StateProxy(
                {
                    "galcen_coord": "https://ui.adsabs.harvard.edu/abs/2004ApJ...616..872R",
                    "galcen_distance": "https://ui.adsabs.harvard.edu/abs/2018A%26A...615L..15G",
                    "galcen_v_sun": [
                        "https://ui.adsabs.harvard.edu/abs/2018RNAAS...2..210D",
                        "https://ui.adsabs.harvard.edu/abs/2018A%26A...615L..15G",
                        "https://ui.adsabs.harvard.edu/abs/2004ApJ...616..872R",
                    ],
                    "z_sun": "https://ui.adsabs.harvard.edu/abs/2019MNRAS.482.1417B",
                    "roll": None,
                }
            ),
        },
        "pre-v4.0": {
            "parameters": _StateProxy(
                {
                    "galcen_coord": ICRS(
                        ra=266.4051 * u.degree, dec=-28.936175 * u.degree
                    ),
                    "galcen_distance": 8.3 * u.kpc,
                    "galcen_v_sun": r.CartesianDifferential(
                        [11.1, 220 + 12.24, 7.25] * (u.km / u.s)
                    ),
                    "z_sun": 27.0 * u.pc,
                    "roll": 0 * u.deg,
                }
            ),
            "references": _StateProxy(
                {
                    "galcen_coord": "https://ui.adsabs.harvard.edu/abs/2004ApJ...616..872R",
                    "galcen_distance": "https://ui.adsabs.harvard.edu/#abs/2009ApJ...692.1075G",
                    "galcen_v_sun": [
                        "https://ui.adsabs.harvard.edu/#abs/2010MNRAS.403.1829S",
                        "https://ui.adsabs.harvard.edu/#abs/2015ApJS..216...29B",
                    ],
                    "z_sun": "https://ui.adsabs.harvard.edu/#abs/2001ApJ...553..184C",
                    "roll": None,
                }
            ),
        },
    }

    @classproperty  # read-only
    def parameters(cls):
        return cls._value

    @classproperty  # read-only
    def references(cls):
        return cls._references

    @classmethod
    def get_from_registry(cls, name: str):
        """
        Return Galactocentric solar parameters and metadata given string names
        for the parameter sets. This method ensures the returned state is a
        mutable copy, so any changes made do not affect the registry state.

        Returns
        -------
        state : dict
            Copy of the registry for the string name.
            Should contain, at minimum:

            - "parameters": dict
                Galactocentric solar parameters
            - "references" : Dict[str, Union[str, Sequence[str]]]
                References for "parameters".
                Fields are str or sequence of str.

        Raises
        ------
        KeyError
            If invalid string input to registry
            to retrieve solar parameters for Galactocentric frame.

        """
        # Resolve the meaning of 'latest': latest parameter set is from v4.0
        # - update this as newer parameter choices are added
        if name == 'latest':
            name = cls._latest_value

        # Get the state from the registry.
        # Copy to ensure registry is immutable to modifications of "_value".
        # Raises KeyError if `name` is invalid string input to registry
        # to retrieve solar parameters for Galactocentric frame.
        state = copy.deepcopy(cls._registry[name])  # ensure mutable

        return state

    @deprecated("v4.2", alternative="`get_from_registry`")
    @classmethod
    def get_solar_params_from_string(cls, arg):
        """
        Return Galactocentric solar parameters given string names
        for the parameter sets.

        Returns
        -------
        parameters : dict
            Copy of Galactocentric solar parameters from registry

        Raises
        ------
        KeyError
            If invalid string input to registry
            to retrieve solar parameters for Galactocentric frame.

        """
        return cls.get_from_registry(arg)["parameters"]

    @classmethod
    def validate(cls, value):
        if value is None:
            value = cls._latest_value

        if isinstance(value, str):
            state = cls.get_from_registry(value)
            cls._references = state["references"]
            cls._state = state
            parameters = state["parameters"]

        elif isinstance(value, dict):
            parameters = value

        elif isinstance(value, Galactocentric):
            # turn the frame instance into a dict of frame attributes
            parameters = dict()
            for k in value.frame_attributes:
                parameters[k] = getattr(value, k)
            cls._references = value.frame_attribute_references.copy()
            cls._state = dict(parameters=parameters,
                              references=cls._references)

        else:
            raise ValueError("Invalid input to retrieve solar parameters for "
                             "Galactocentric frame: input must be a string, "
                             "dict, or Galactocentric instance")

        return parameters

    @classmethod
    def register(cls, name: str, parameters: dict, references=None,
                 **meta: dict):
        """Register a set of parameters.

        Parameters
        ----------
        name : str
            The registration name for the parameter and metadata set.
        parameters : dict
            The solar parameters for Galactocentric frame.
        references : dict or None, optional
            References for contents of `parameters`.
            None becomes empty dict.
        **meta : dict, optional
            Any other properties to register.

        """
        # check on contents of `parameters`
        must_have = {"galcen_coord", "galcen_distance", "galcen_v_sun",
                     "z_sun", "roll"}
        missing = must_have.difference(parameters)
        if missing:
            raise ValueError(f"Missing parameters: {missing}")

        references = references or {}  # None -> {}

        state = dict(parameters=parameters, references=references)
        state.update(meta)  # meta never has keys "parameters" or "references"

        cls._registry[name] = state
class Galactocentric(BaseCoordinateFrame):
    r"""
    A coordinate or frame in the Galactocentric system. This frame
    requires specifying the Sun-Galactic center distance, and optionally
    the height of the Sun above the Galactic midplane.

    The position of the Sun is assumed to be on the x axis of the final,
    right-handed system. That is, the x axis points from the position of
    the Sun projected to the Galactic midplane to the Galactic center --
    roughly towards :math:`(l,b) = (0^\circ,0^\circ)`. For the default
    transformation (:math:`{\rm roll}=0^\circ`), the y axis points roughly
    towards Galactic longitude :math:`l=90^\circ`, and the z axis points
    roughly towards the North Galactic Pole (:math:`b=90^\circ`).

    The default position of the Galactic Center in ICRS coordinates is
    taken from Reid et al. 2004,
    http://adsabs.harvard.edu/abs/2004ApJ...616..872R.

    .. math::

        {\rm RA} = 17:45:37.224~{\rm hr}\\
        {\rm Dec} = -28:56:10.23~{\rm deg}

    The default distance to the Galactic Center is 8.3 kpc, e.g.,
    Gillessen et al. (2009),
    https://ui.adsabs.harvard.edu/#abs/2009ApJ...692.1075G/abstract

    The default height of the Sun above the Galactic midplane is taken to
    be 27 pc, as measured by Chen et al. (2001),
    https://ui.adsabs.harvard.edu/#abs/2001ApJ...553..184C/abstract

    The default solar motion relative to the Galactic center is taken from a
    combination of Schönrich et al. (2010) [for the peculiar velocity] and
    Bovy (2015) [for the circular velocity at the solar radius],
    https://ui.adsabs.harvard.edu/#abs/2010MNRAS.403.1829S/abstract
    https://ui.adsabs.harvard.edu/#abs/2015ApJS..216...29B/abstract

    For a more detailed look at the math behind this transformation, see
    the document :ref:`coordinates-galactocentric`.

    The frame attributes are listed under **Other Parameters**.
    """

    default_representation = r.CartesianRepresentation
    default_differential = r.CartesianDifferential

    # frame attributes
    galcen_coord = CoordinateAttribute(default=ICRS(ra=266.4051 * u.degree,
                                                    dec=-28.936175 * u.degree),
                                       frame=ICRS)
    galcen_distance = QuantityAttribute(default=8.3 * u.kpc)

    galcen_v_sun = DifferentialAttribute(
        default=r.CartesianDifferential([11.1, 220 + 12.24, 7.25] * u.km /
                                        u.s),
        allowed_classes=[r.CartesianDifferential])

    z_sun = QuantityAttribute(default=27. * u.pc)
    roll = QuantityAttribute(default=0. * u.deg)

    def __init__(self, *args, **kwargs):

        # backwards-compatibility
        if ('galcen_ra' in kwargs or 'galcen_dec' in kwargs):
            warnings.warn(
                "The arguments 'galcen_ra', and 'galcen_dec' are "
                "deprecated in favor of specifying the sky coordinate"
                " as a CoordinateAttribute using the 'galcen_coord' "
                "argument", AstropyDeprecationWarning)

            galcen_kw = dict()
            galcen_kw['ra'] = kwargs.pop('galcen_ra', self.galcen_coord.ra)
            galcen_kw['dec'] = kwargs.pop('galcen_dec', self.galcen_coord.dec)
            kwargs['galcen_coord'] = ICRS(**galcen_kw)

        super().__init__(*args, **kwargs)

    @property
    def galcen_ra(self):
        warnings.warn(
            "The attribute 'galcen_ra' is deprecated. Use "
            "'.galcen_coord.ra' instead.", AstropyDeprecationWarning)
        return self.galcen_coord.ra

    @property
    def galcen_dec(self):
        warnings.warn(
            "The attribute 'galcen_dec' is deprecated. Use "
            "'.galcen_coord.dec' instead.", AstropyDeprecationWarning)
        return self.galcen_coord.dec

    @classmethod
    def get_roll0(cls):
        """
        The additional roll angle (about the final x axis) necessary to align
        the final z axis to match the Galactic yz-plane.  Setting the ``roll``
        frame attribute to  -this method's return value removes this rotation,
        allowing the use of the `Galactocentric` frame in more general contexts.
        """
        # note that the actual value is defined at the module level.  We make at
        # a property here because this module isn't actually part of the public
        # API, so it's better for it to be accessable from Galactocentric
        return _ROLL0
Exemple #17
0
def test_concatenate_representations():
    from astropy.coordinates.funcs import concatenate_representations
    from astropy.coordinates import representation as r

    reps = [r.CartesianRepresentation([1, 2, 3.]*u.kpc),
            r.SphericalRepresentation(lon=1*u.deg, lat=2.*u.deg,
                                      distance=10*u.pc),
            r.UnitSphericalRepresentation(lon=1*u.deg, lat=2.*u.deg),
            r.CartesianRepresentation(np.ones((3, 100)) * u.kpc),
            r.CartesianRepresentation(np.ones((3, 16, 8)) * u.kpc)]

    reps.append(reps[0].with_differentials(
        r.CartesianDifferential([1, 2, 3.] * u.km/u.s)))
    reps.append(reps[1].with_differentials(
        r.SphericalCosLatDifferential(1*u.mas/u.yr, 2*u.mas/u.yr, 3*u.km/u.s)))
    reps.append(reps[2].with_differentials(
        r.SphericalCosLatDifferential(1*u.mas/u.yr, 2*u.mas/u.yr, 3*u.km/u.s)))
    reps.append(reps[2].with_differentials(
        r.UnitSphericalCosLatDifferential(1*u.mas/u.yr, 2*u.mas/u.yr)))
    reps.append(reps[2].with_differentials(
        {'s': r.RadialDifferential(1*u.km/u.s)}))
    reps.append(reps[3].with_differentials(
        r.CartesianDifferential(*np.ones((3, 100)) * u.km/u.s)))
    reps.append(reps[4].with_differentials(
        r.CartesianDifferential(*np.ones((3, 16, 8)) * u.km/u.s)))

    # Test that combining all of the above with itself succeeds
    for rep in reps:
        if not rep.shape:
            expected_shape = (2, )
        else:
            expected_shape = (2 * rep.shape[0], ) + rep.shape[1:]

        tmp = concatenate_representations((rep, rep))
        assert tmp.shape == expected_shape

        if 's' in rep.differentials:
            assert tmp.differentials['s'].shape == expected_shape

    # Try combining 4, just for something different
    for rep in reps:
        if not rep.shape:
            expected_shape = (4, )
        else:
            expected_shape = (4 * rep.shape[0], ) + rep.shape[1:]

        tmp = concatenate_representations((rep, rep, rep, rep))
        assert tmp.shape == expected_shape

        if 's' in rep.differentials:
            assert tmp.differentials['s'].shape == expected_shape

    # Test that combining pairs fails
    with pytest.raises(TypeError):
        concatenate_representations((reps[0], reps[1]))

    with pytest.raises(ValueError):
        concatenate_representations((reps[0], reps[5]))

    # Check that passing in a single object fails
    with pytest.raises(TypeError):
        concatenate_representations(reps[0])
Exemple #18
0
from astropy.time import Time
from astropy.coordinates import representation as r
from astropy.coordinates.baseframe import (BaseCoordinateFrame,
                                           RepresentationMapping,
                                           frame_transform_graph, base_doc)
from astropy.coordinates.transformations import AffineTransform
from astropy.coordinates.attributes import DifferentialAttribute

from .baseradec import BaseRADecFrame, doc_components as doc_components_radec
from .icrs import ICRS
from .galactic import Galactic

# For speed
J2000 = Time('J2000')

v_bary_Schoenrich2010 = r.CartesianDifferential([11.1, 12.24, 7.25] * u.km /
                                                u.s)

__all__ = ['LSR', 'GalacticLSR']

doc_footer_lsr = """
    Other parameters
    ----------------
    v_bary : `~astropy.coordinates.representation.CartesianDifferential`
        The velocity of the solar system barycenter with respect to the LSR, in
        Galactic cartesian velocity components.
"""


@format_doc(base_doc, components=doc_components_radec, footer=doc_footer_lsr)
class LSR(BaseRADecFrame):
    r"""A coordinate or frame in the Local Standard of Rest (LSR).
Exemple #19
0
    @classmethod
    def no_pos(cls, coo, fr):
        return None, cls.rep0.with_differentials(cls.dif)

    @classmethod
    def no_vel(cls, coo, fr):
        return None, cls.rep


@pytest.mark.parametrize('transfunc', [transfunc.both, transfunc.no_matrix,
                                       transfunc.no_pos, transfunc.no_vel,
                                       transfunc.just_matrix])
@pytest.mark.parametrize('rep', [
    r.CartesianRepresentation(5, 6, 7, unit=u.pc),
    r.CartesianRepresentation(5, 6, 7, unit=u.pc,
                              differentials=r.CartesianDifferential(8, 9, 10,
                                                                    unit=u.pc/u.Myr)),
    r.CartesianRepresentation(5, 6, 7, unit=u.pc,
                              differentials=r.CartesianDifferential(8, 9, 10,
                                                                    unit=u.pc/u.Myr))
     .represent_as(r.CylindricalRepresentation, r.CylindricalDifferential)
])
def test_affine_transform_succeed(transfunc, rep):
    c = TCoo1(rep)

    # compute expected output
    M, offset = transfunc(c, TCoo2)

    _rep = rep.to_cartesian()
    diffs = {k: diff.represent_as(r.CartesianDifferential, rep)
             for k, diff in rep.differentials.items()}
    expected_rep = _rep.with_differentials(diffs)