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.")
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)