def _check_coord_repr_diff_types(c):
    if isinstance(c.data, r.UnitSphericalRepresentation):
        raise ConvertError("Transforming to/from a Galactocentric frame "
                           "requires a 3D coordinate, e.g. (angle, angle, "
                           "distance) or (x, y, z).")

    if ('s' in c.data.differentials and isinstance(
            c.data.differentials['s'],
        (r.UnitSphericalDifferential, r.UnitSphericalCosLatDifferential,
         r.RadialDifferential))):
        raise ConvertError("Transforming to/from a Galactocentric frame "
                           "requires a 3D velocity, e.g., proper motion "
                           "components and radial velocity.")
Example #2
0
    def transform_to(self, frame, merge_attributes=True):
        # a modified version of the corresponding astropy function.
        from astropy.coordinates.errors import ConvertError

        frame_kwargs = {}

        # Frame name (string) or frame class?  Coerce into an instance.
        try:
            frame = _get_frame_class(frame)()
        except Exception:
            pass

        if isinstance(frame, SkyCoord):
            frame = frame.frame  # Change to underlying coord frame instance

        if isinstance(frame, BaseCoordinateFrame):
            new_frame_cls = frame.__class__
            # Get frame attributes, allowing defaults to be overridden by
            # explicitly set attributes of the source if ``merge_attributes``.
            for attr in frame_transform_graph.frame_attributes:
                self_val = getattr(self, attr, None)
                frame_val = getattr(frame, attr, None)
                if (frame_val is not None
                    and not (merge_attributes
                             and frame.is_frame_attr_default(attr))):
                    frame_kwargs[attr] = frame_val
                elif (self_val is not None
                      and not self.is_frame_attr_default(attr)):
                    frame_kwargs[attr] = self_val
                elif frame_val is not None:
                    frame_kwargs[attr] = frame_val
        else:
            raise ValueError('Transform `frame` must be a frame name, class, or instance')

        # Hacky solution here -- Frames other than LunarTopo cannot accept a MoonLocation object
        # and can get confused by it. Do not pass along `location` unless certain it will work.
        moonloc_incompatible = not isinstance(frame, LunarTopo)
        graph_attrs = frame_transform_graph.frame_attributes
        if hasattr(self, 'location'):
            loc = getattr(self, 'location')
            if isinstance(loc, MoonLocation):
                if moonloc_incompatible:
                    frame_kwargs.pop('location')
            elif 'location' in graph_attrs.keys() \
                    and isinstance(graph_attrs['location'], MoonLocationAttribute):
                frame_transform_graph.frame_attributes['location'] = \
                    EarthLocationAttribute(default=None)

        # Get the composite transform to the new frame
        trans = frame_transform_graph.get_transform(self.frame.__class__, new_frame_cls)
        if trans is None:
            raise ConvertError('Cannot transform from {} to {}'
                               .format(self.frame.__class__, new_frame_cls))

        # Make a generic frame which will accept all the frame kwargs that
        # are provided and allow for transforming through intermediate frames
        # which may require one or more of those kwargs.
        generic_frame = GenericFrame(frame_kwargs)

        # Do the transformation, returning a coordinate frame of the desired
        # final type (not generic).
        new_coord = trans(self.frame, generic_frame)

        # Finally make the new SkyCoord object from the `new_coord` and
        # remaining frame_kwargs that are not frame_attributes in `new_coord`.
        for attr in (set(new_coord.get_frame_attr_names())
                     & set(frame_kwargs.keys())):
            frame_kwargs.pop(attr)

        return self.__class__(new_coord, **frame_kwargs)
    def transform_to(self, frame):
        """
        Transform this coordinate to a new frame.

        Parameters
        ----------
        frame : str or `BaseCoordinateFrame` class / instance or `SkyCoord` instance
            The frame to transform this coordinate into.

        Returns
        -------
        coord : `SkyCoord`
            A new object with this coordinate represented in the `frame` frame.

        Raises
        ------
        ValueError
            If there is no possible transformation route.
        """
        from astropy.coordinates.errors import ConvertError

        if frame is None or isinstance(self.frame, NoFrame):
            raise ValueError('Cannot transform to/from this SkyCoord because '
                             'the frame was not specified at creation.')

        frame_kwargs = {}

        # Frame name (string) or frame class?  Coerce into an instance.
        try:
            frame = _get_frame_class(frame)()
        except:
            pass

        if isinstance(frame, SkyCoord):
            frame = frame.frame  # Change to underlying coord frame instance

        if isinstance(frame, BaseCoordinateFrame):
            new_frame_cls = frame.__class__

            # Set the keyword args for making a new frame instance for the
            # transform.  If the supplied frame instance has a non-default
            # value set then use that, otherwise use the self attribute value
            # if it is not None.
            for attr in FRAME_ATTR_NAMES_SET():
                self_val = getattr(self, attr, None)
                frame_val = getattr(frame, attr, None)
                if (frame_val is not None and
                        attr not in frame._attr_names_with_defaults):
                    frame_kwargs[attr] = frame_val
                elif self_val is not None:
                    frame_kwargs[attr] = self_val
        else:
            raise ValueError('Transform `frame` must be a frame name, class, or instance')

        # Get the composite transform to the new frame
        trans = frame_transform_graph.get_transform(self.frame.__class__, new_frame_cls)
        if trans is None:
            raise ConvertError('Cannot transform from {0} to {1}'
                               .format(self.frame.__class__, new_frame_cls))

        # Make a generic frame which will accept all the frame kwargs that
        # are provided and allow for transforming through intermediate frames
        # which may require one or more of those kwargs.
        generic_frame = GenericFrame(frame_kwargs)

        # Do the transformation, returning a coordinate frame of the desired
        # final type (not generic).
        new_coord = trans(self.frame, generic_frame)

        # Finally make the new SkyCoord object from the `new_coord` and
        # remaining frame_kwargs that are not frame_attributes in `new_coord`.
        # We could remove overlaps here, but the init code is set up to accept
        # overlaps as long as the values are identical (which they must be).
        return self.__class__(new_coord, **frame_kwargs)