
    HR-eG                    t   d Z ddlZddlZddlZddlmZmZ ddlZddl	m
Z ddlmZmZ ddlmZmZmZ ddlmZmZ dd	lmZ dd
lmZ ddlmZ ddlmZ g dZ e            Z d Z!d Z"d Z# edd          Z$ G d de$          Z%dZ&dZ' ee&e'd           G d de                      Z( G d de(          Z)dS )zR
Framework and base classes for coordinate frames/"low-level" coordinate
classes.
    N)defaultdict
namedtuple)units)ShapedLikeNDArraycheck_broadcast)
deprecated
format_doclazyproperty)AstropyDeprecationWarningAstropyWarning   )representationAngle)	Attribute)TransformGraph)BaseCoordinateFrameframe_transform_graphGenericFrameRepresentationMappingc                     | t           j        v rt           j        |          } n[t          | t                    rt	          | t           j                  s,t          d| dt          t           j                             | S )zP
    Return a valid representation class from ``value`` or raise exception.
    zRepresentation is zE but must be a BaseRepresentation class or one of the string aliases )rREPRESENTATION_CLASSES
isinstancetype
issubclassBaseRepresentation
ValueErrorlistvalues    =lib/python3.11/site-packages/astropy/coordinates/baseframe.py_get_repr_clsr#   )   s     ((((/t$$ 
Jua>R,S,S 
M M M,01I,J,JM M
 
 	
 L    c                     | t           j        v rt           j        |          } n[t          | t                    rt	          | t           j                  s,t          d| dt          t           j                             | S )z
    Return a valid differential class from ``value`` or raise exception.

    As originally created, this is only used in the SkyCoord initializer, so if
    that is refactored, this function my no longer be necessary.
    zDifferential is zC but must be a BaseDifferential class or one of the string aliases )r   DIFFERENTIAL_CLASSESr   r   r   BaseDifferentialr   r   r    s    r"   _get_diff_clsr(   7   s     &&&&u-t$$ 
Jua>P,Q,Q 
Ku K K,01G,H,HK K
 
 	
 Lr$   c                    t          |           } d| i}|                                D ]\  }}|dk    r3t          j                            |                                 d          }n{|t          j        v rt          j        |         }nZ|Xt          |t                    rt          |t          j	                  s)t          dt          t          j                             |||<   |S )a  Get valid representation and differential classes.

    Parameters
    ----------
    base : str or `~astropy.coordinates.BaseRepresentation` subclass
        class for the representation of the base coordinates.  If a string,
        it is looked up among the known representation classes.
    **differentials : dict of str or `~astropy.coordinates.BaseDifferentials`
        Keys are like for normal differentials, i.e., 's' for a first
        derivative in time, etc.  If an item is set to `None`, it will be
        guessed from the base class.

    Returns
    -------
    repr_classes : dict of subclasses
        The base class is keyed by 'base'; the others by the keys of
        ``diffferentials``.
    baseNzhDifferential is {differential_type!r} but must be a BaseDifferential class or one of the string aliases )r#   itemsr   r&   getget_namer   r   r   r'   r   r   )r*   differentialsrepr_classesnamedifferential_types        r"   _get_repr_classesr2   H   s   & DD>L#0#6#6#8#8 / /&& ! 6 : :4==??D Q Q!"888 ! 67H I*,d33 +/1CDD + V7;A<R7S7SV V   /Tr$   r   )reprname	framenamedefaultunitc                   $     e Zd ZdZd fd	Z xZS )r   a  
    This `~collections.namedtuple` is used with the
    ``frame_specific_representation_info`` attribute to tell frames what
    attribute names (and default units) to use for a particular representation.
    ``reprname`` and ``framename`` should be strings, while ``defaultunit`` can
    be either an astropy unit, the string ``'recommended'`` (which is degrees
    for Angles, nothing otherwise), or None (to indicate that no unit mapping
    should be done).
    recommendedc                 L    t                                          | |||          S N)super__new__)clsr3   r4   r5   	__class__s       r"   r;   zRepresentationMapping.__new__   s    wwsHiEEEr$   )r7   )__name__
__module____qualname____doc__r;   __classcell__r=   s   @r"   r   r   w   sQ         F F F F F F F F F Fr$   a  {__doc__}
    Parameters
    ----------
    data : `~astropy.coordinates.BaseRepresentation` subclass instance
        A representation object or ``None`` to have no data (or use the
        coordinate component arguments, see below).
    {components}
    representation_type : `~astropy.coordinates.BaseRepresentation` subclass, str, optional
        A representation class or string name of a representation class. This
        sets the expected input representation class, thereby changing the
        expected keyword arguments for the data passed in. For example, passing
        ``representation_type='cartesian'`` will make the classes expect
        position data with cartesian names, i.e. ``x, y, z`` in most cases
        unless overridden via ``frame_specific_representation_info``. To see this
        frame's names, check out ``<this frame>().representation_info``.
    differential_type : `~astropy.coordinates.BaseDifferential` subclass, str, dict, optional
        A differential class or dictionary of differential classes (currently
        only a velocity differential with key 's' is supported). This sets the
        expected input differential class, thereby changing the expected keyword
        arguments of the data passed in. For example, passing
        ``differential_type='cartesian'`` will make the classes expect velocity
        data with the argument names ``v_x, v_y, v_z`` unless overridden via
        ``frame_specific_representation_info``. To see this frame's names,
        check out ``<this frame>().representation_info``.
    copy : bool, optional
        If `True` (default), make copies of the input coordinate arrays.
        Can only be passed in as a keyword argument.
    {footer}
z\
    *args, **kwargs
        Coordinate components, with names that depend on the subclass.
 )
componentsfooterc                   l    e Zd ZdZdZdZi Zi Z fdZdddddZ	d Z
d Zed	             ZedBd
            Zed             Zed             Zed             Zed             Zd Zd Zed             Zed             Zed             Z eddd          ed                         ZdCdZdDdZ eeed          Zed             Zej         d             Zed              Z!ed!             Z"dCd"Z#dCd#Z$ ee#          Z% ee$          Z&dEd%Z'dEd&Z(dEd'Z)d( Z*dFd)Z+d* Z,d+ Z-d, Z.e/d-             Z0d. Z1d/ Z2d0 Z3d1 Z4 fd2Z5d3 Z6 fd4Z7d5 Z8 fd6Z9d7 Z:d8 Z;d9 Z<d: Z=ed;             Z>ed<             Z?ed=             Z@ed>             ZAed?             ZBed@             ZCedA             ZD xZES )Gr   a  
    The base class for coordinate frames.

    This class is intended to be subclassed to create instances of specific
    systems.  Subclasses can implement the following attributes:

    * `default_representation`
        A subclass of `~astropy.coordinates.BaseRepresentation` that will be
        treated as the default representation of this frame.  This is the
        representation assumed by default when the frame is created.

    * `default_differential`
        A subclass of `~astropy.coordinates.BaseDifferential` that will be
        treated as the default differential class of this frame.  This is the
        differential class assumed by default when the frame is created.

    * `~astropy.coordinates.Attribute` class attributes
       Frame attributes such as ``FK4.equinox`` or ``FK4.obstime`` are defined
       using a descriptor class.  See the narrative documentation or
       built-in classes code for details.

    * `frame_specific_representation_info`
        A dictionary mapping the name or class of a representation to a list of
        `~astropy.coordinates.RepresentationMapping` objects that tell what
        names and default units should be used on this frame for the components
        of that representation.

    Unless overridden via `frame_specific_representation_info`, velocity name
    defaults are:

      * ``pm_{lon}_cos{lat}``, ``pm_{lat}`` for `~astropy.coordinates.SphericalCosLatDifferential` velocity components
      * ``pm_{lon}``, ``pm_{lat}`` for `~astropy.coordinates.SphericalDifferential` velocity components
      * ``radial_velocity`` for any ``d_distance`` component
      * ``v_{x,y,z}`` for `~astropy.coordinates.CartesianDifferential` velocity components

    where ``{lon}`` and ``{lat}`` are the frame names of the angular components.
    Nc                    t          | dd           }t          | dd           }t          | dd           }|t          |t                    rt          | dd           }|t          |t                    rt          | dd           }|t          |t                    rt          | dd           }|                     |          }|                     d|d           |                     d|d           |                     dt          j        |          d	           i }t          | j                  D ]1}t          |t                    r|                    |j                   2| j                                        D ]\  }}t          |t                    r|||<    || _        t!          | d
          s| j                                        | _        nDt          | j        vr6| j        d | j        D             v r| j                                        | _        i | _         t+                      j        di | |                                  d S )Ndefault_representationdefault_differential"frame_specific_representation_info_default_representation_default_differential#_frame_specific_representation_infoz(Default representation for position dataz=Default representation for differential data (e.g., velocity)z*Mapping for frame-specific component namesr0   c                 0    g | ]}t          |d d          S )r0   Ngetattr).0r*   s     r"   
<listcomp>z9BaseCoordinateFrame.__init_subclass__.<locals>.<listcomp>  s7     G
 G
 G
,0GD&$''G
 G
 G
r$    )rQ   r   property_infer_repr_info_create_readonly_propertycopydeepcopyreversed	__bases__r   r   updateframe_attributes__dict__r+   r   hasattrr>   lowerr0   _frame_class_cacher:   __init_subclass__get_frame_attr_defaults)
r<   kwargsdefault_reprdefault_diff	repr_infoframe_attrsbaseclskvr=   s
            r"   rb   z%BaseCoordinateFrame.__init_subclass__   s   s$<dCCs$:DAAC!EtLL	 :lH#E#E"3(A4HHL:lH#E#E"3(?FFL
9h ? ?%JDQQI((33	 	%%$6	
 	
 	

 	%%"K	
 	
 	

 	%%0M)$$8	
 	
 	
 .. 	= 	=G'#677 =""7#;<<<L&&(( 	# 	#DAq!Y'' #!"A* sF## 	,|))++CHH 55#( G
 G
47MG
 G
 G
 ;
 ;
 |))++CH
 "$!!++F+++ 	##%%%%%r$   T)rX   representation_typer1   c                p   g | _         |                     ||          | _        |                     |||          | _        i }|                                                                 D ]t\  }}||v r=|                    |          }	t          | d|z   |	           t          | |          ||<   Ft          | d|z   |           | j         
                    |           u|r,t          d| j        j         dt          |                     | j        d |                                D             }
|
rt          |
          dk    r]	 t!          |
                                 | _        n%# t&          $ r}t'          d|
           |d }~ww xY w|
D ]}t          | |           n'|
                                d         | _        nd| _        | j        gd| j        j        v r/| j        j        j        | j        j        d         j        j        d	f}n| j        j        j        d	f}| j        | j        d
         |<   d S d S )N_zCoordinate frame z got unexpected keywords: c                 F    i | ]\  }}t          |d d          ||j        S )shaperT   )rQ   rp   )rR   fnmr!   s      r"   
<dictcomp>z0BaseCoordinateFrame.__init__.<locals>.<dictcomp>[  sB       C5'2..U[  r$   r   z0non-scalar attributes with inconsistent shapes: rT   sFr   )_attr_names_with_defaults_infer_representation_representation_infer_data_datarc   r+   popsetattrrQ   append	TypeErrorr=   r>   r   lenr   values_no_data_shaper   popitemr.   cache)selfrX   rl   r1   argsrd   r~   rq   fdefaultr!   shapeserrkeys                r"   __init__zBaseCoordinateFrame.__init__.  s    *,&#99!2 
  
 %%dD&99
 !99;;AACC 	; 	;MC
 f}}

3cCi/// &dC00scCi222.55c:::: 	,DN$; , ,!&\\, ,   : "(,,..  F
  )v;;??#.=v}}.O++% # # #(WvWW "##  & + +c****+ +1..*:*:1*=D'' ')# :! dj... J(1J,S1;D z+4e< 15
DJ'(--- "!s    E& &
F0FFc                 H   ||| j         | j        dS || j         }t          j        |          rt	          |t
          j                  rd|i}nGt          |t                    rt
          j	        |         }d|i}n||| j         k    r
d| j        i}nddi}t          |fi |S )Nr*   rs   rs   r*   )rI   rJ   inspectisclassr   r   r'   r   strr&   r2   )r   rl   r1   diff_clss       r"   ru   z)BaseCoordinateFrame._infer_representation  s    &+<+D 7d>WXXX&"&"=?,-- 	2*q13
 3
 	2
 "%&7 8)3// 
	2 -.?@H!$h&"d&AAA%($*C$D!!%(&M! !4JJ8IJJJr$   c                 b
   d }d }t          |          }|rt          |d         t          j                  s|d         |                    d          }t          |          dk    rt          d          |Y|j        }|                    dd           }|t          |          dk    s|%t          |          dk    rt          d|           n| 
                                }i }| j                                        D ]M\  }	}
t          |          dk    r|                    d          ||
<   1|	|v r|                    |	          ||
<   N|r |                    dd          |d= t          |t          j                  rd|vr|j        }	  |dd|i|}n# t          $ r}	  |j        dd|i|}n# t           $ r t#          |          }|                                 }|                                D ]\  }}|                    ||          }|                    d	| j        j         d
          }|f|_        |w xY wY d }~nd }~ww xY w| 
                    d          }|                     d          }i }|                                D ]M\  }	}
t          |          dk    r|                    d          ||
<   1|	|v r|                    |	          ||
<   N|rt/          |d          rd|vr|j        }n#t          |          dk    rd|v rt          j        }	  |dd|i|}n# t          $ r}t#          |          }|                     d          }|                                D ]\  }}|                    ||          }|                    d	| j        j         d
          }|f|_         d }~ww xY wt          |          dk    r:t          d                    | j        j        t          |                              ||t          d          |r|j        D ]}d| x}|j        v r|j        |         }|j        |         }|t:          j        z  }|                    |          s|                                                                 D ]\  }}||k    r|} n|                     d                                          D ]\  }}||k    r|} nt          | d| d|j          d| d| d|j          d|j          d          |!                    d|i          }|S )Nr   zVCannot create a frame with both a representation object and other positional argumentsrs   r   zMultiple differentials are associated with the representation object passed in to the frame initializer. Only a single velocity differential is supported. Got: distanceTrX   z
__init__()z()_unit_differential
d_distancez0{}.__init__ had {} remaining unhandled argumentszTCannot pass in differential component data without positional (representation) data.d_z has unit "z" with physical type "z", but z has incompatible unit "z" instead of the expected "z".rT   )"r   r   r   r   ry   r}   r|   r.   r,   r   get_representation_clsrepresentation_component_namesr+   r   SphericalRepresentation_unit_representation	Exceptionr   "get_representation_component_namesreplacer=   r>   r   r_   r   RadialDifferentialformatrE   _unitsurs   is_equivalentphysical_typewith_differentials)r   r   rX   rd   representation_datadifferential_datadiffsrepresentation_clsrepr_kwargsnmkwnmrepemsgnames
frame_name	repr_namedifferential_clsdiff_component_namesdiff_kwargscomp	diff_compcurrent_repr_unitcurrent_diff_unitexpected_unitr   valcurrent_repr_namecurrent_diff_names                               r"   rw   zBaseCoordinateFrame._infer_data  s   " Dzz h	ZQ)=>> h	$q'/"&((1++4yy1}}5  
 #.+9$)IIc4$8$8!%-#e**q..%1c%jj1nn$MEJM M   "&!<!<!>!> K#BHHJJ : :et99q==)-!K&&V^^)/D)9)9K&    
 ??:t44<#J/ 113LMMQ"+55);)P& *<*<*V*V$*V+*V*V''       
 .U.@.U / /!%/)4/ /++ %      !!ff $ G G I I5:[[]] E E1J	"%++i"D"DCC!kk,4>;R8V8V8VWW"%  ,++++ *  $::3??#'#J#J3#O#O K399;; : :et99q==)-!K&&V^^)/D)9)9K& ,.BCC<$K77'7'J$$%%**|{/J/J'(';$(8(8(R(Rd(Rk(R(R%%    
 a&&C CCCHHE16 A A-
I!kk)Z@@++lt~7N4R4R4RSSC!VAF t99q==BIIN+SYY    &+<+H<  
  #	
 ,6  !,d,I1B1MMM(;(B4(H%(9(@(K%$5$;M,::=II  "DDFFLLNN& & "d{{47 1 %  + )-(O(O) )%''& &HC  #i//47 1 %  0 )0 L L=N L L/@/NL L 1L L "3L L "3!@	L L
 ,9*GL L L   #6"H"H'(# # #"sD   
F 
I'F76I
7BII

I"
L- -
N<7B N77N<c                 x   |i }t          |                                          D ]>}t          |t                    r't	          |          }|                    |          ||<   ?|                    t          j        t          dd          t          dd          g           d |t          j                 D             }|                    t          j
        t          d dj        di |t          j        t          j        z            t          d dj        di |t          j        t          j        z            t          dd	t          j        t          j        z            g           |                    t          j        t          d
 dj        di |t          j        t          j        z            t          d dj        di |t          j        t          j        z            t          dd	t          j        t          j        z            g           |                    t          j        t          ddt          j        t          j        z            t          ddt          j        t          j        z            t          ddt          j        t          j        z            g           |                    t          j        |t          j                            |                    t          j        |t          j
                            |                    t          j        |t          j                            |S )Nlonlatc                 (    i | ]}|j         |j        S rT   )r3   r4   rR   ms     r"   rr   z8BaseCoordinateFrame._infer_repr_info.<locals>.<dictcomp>h  s+     
 
 
()AJ
 
 
r$   d_lon_coslatzpm_{lon}_cos{lat}d_latzpm_{lat}r   radial_velocityd_lonzpm_{lon}d_xv_xd_yv_yd_zv_zrT   )tuplekeysr   r   r#   ry   
setdefaultr   r   r   SphericalCosLatDifferentialr   r   masyrkmrs   SphericalDifferentialCartesianDifferentialUnitSphericalRepresentationUnitSphericalCosLatDifferentialUnitSphericalDifferential)r<   rg   cls_or_name_clssph_component_maps        r"   rV   z$BaseCoordinateFrame._infer_repr_infoF  s    I !!1!122 	= 	=K+s++ = %[11"+--"<"<	$ 	%"5%002Gu2U2UV	
 	
 	


 
-6q7P-Q
 
 
 	)%".'.CC1BCCEADL 
 &.Z.CC1BCCQUQT\  &l4EqtaczRR
	
 	
 	
 	#%.Z.CC1BCCQUQT\  &.Z.CC1BCCQUQT\  &l4EqtaczRR	
 	
 	
 	#%eUAD13J??%eUAD13J??%eUAD13J??	
 	
 	
 	)9Q5N+O	
 	
 	
 	-y9V/W	
 	
 	
 	'13J)K	
 	
 	
 r$   c                 ~    d|z   fd}t          | |           t          | |t          ||                     d S )Nrn   c                 $    t          |           S r9   rP   )r   private_attrs    r"   getterz=BaseCoordinateFrame._create_readonly_property.<locals>.getter  s    4...r$   )doc)rz   rU   )r<   	attr_namer!   r   r   r   s        @r"   rW   z-BaseCoordinateFrame._create_readonly_property  s^    Y	/ 	/ 	/ 	/ 	/ 	\5)))YS 9 9 9:::::r$   c                 *    t          t                    S )a  Cache for this frame, a dict.

        It stores anything that should be computed from the coordinate data (*not* from
        the frame attributes). This can be used in functions to store anything that
        might be expensive to compute but might be re-used by some other function.
        E.g.::

            if 'user_data' in myframe.cache:
                data = myframe.cache['user_data']
            else:
                myframe.cache['user_data'] = data = expensive_func(myframe.lat)

        If in-place modifications are made to the frame data, the cache should
        be cleared::

            myframe.cache.clear()

        )r   dictr   s    r"   r   zBaseCoordinateFrame.cache  s    ( 4   r$   c                 D    | j         t          d| d          | j         S )z
        The coordinate data for this object.  If this frame has no data, an
        `ValueError` will be raised.  Use `has_data` to
        check if data is present on this frame object.
        NzThe frame object "z" does not have associated data)rx   r   r   s    r"   datazBaseCoordinateFrame.data  s6     :LTLLL   zr$   c                     | j         duS )zA
        True if this frame has `data`, False otherwise.
        N)rx   r   s    r"   has_datazBaseCoordinateFrame.has_data  s    
 z%%r$   c                 6    | j         r| j        j        n| j        S r9   )r   r   rp   r   r   s    r"   rp   zBaseCoordinateFrame.shape  s    "&-HtyT5HHr$   c                 *    t          | j                  S r9   )r}   r   r   s    r"   __len__zBaseCoordinateFrame.__len__  s    49~~r$   c                 &    | j         o
| j        dk    S )Nr   )r   sizer   s    r"   __bool__zBaseCoordinateFrame.__bool__  s    }.Q.r$   c                     | j         j        S r9   )r   r   r   s    r"   r   zBaseCoordinateFrame.size  s    y~r$   c                 (    | j         o| j        j        S r9   )r   r   isscalarr   s    r"   r   zBaseCoordinateFrame.isscalar  s    }3!33r$   c                 *      fd j         D             S )9Return a dict with the defaults for each frame attribute.c                 2    i | ]}|t          |          S rT   rP   )rR   r0   r<   s     r"   rr   z?BaseCoordinateFrame.get_frame_attr_defaults.<locals>.<dictcomp>  s%    JJJTgc4((JJJr$   )r]   r<   s   `r"   rc   z+BaseCoordinateFrame.get_frame_attr_defaults  s#     KJJJS5IJJJJr$   z5.2rc   zThe {func}() {obj_type} is deprecated and may be removed in a future version. Use {alternative}() to obtain a dict of frame attribute names and default values. The fastest way to obtain the names is frame_attributes.keys())alternativemessagec                 *    |                                  S )r   )rc   r   s    r"   get_frame_attr_namesz(BaseCoordinateFrame.get_frame_attr_names  s     **,,,r$   r*   c                 .    || j         |         S | j         S )a.  The class used for part of this frame's data.

        Parameters
        ----------
        which : ('base', 's', `None`)
            The class of which part to return.  'base' means the class used to
            represent the coordinates; 's' the first derivative to time, i.e.,
            the class representing the proper motion and/or radial velocity.
            If `None`, return a dict with both.

        Returns
        -------
        representation : `~astropy.coordinates.BaseRepresentation` or `~astropy.coordinates.BaseDifferential`.
        )rv   )r   whichs     r"   r   z*BaseCoordinateFrame.get_representation_cls  s!     '..''r$   c                 P    || j         d         }t          ||          | _         dS )a  Set representation and/or differential class for this frame's data.

        Parameters
        ----------
        base : str, `~astropy.coordinates.BaseRepresentation` subclass, optional
            The name or subclass to use to represent the coordinate data.
        s : `~astropy.coordinates.BaseDifferential` subclass, optional
            The differential subclass to use to represent any velocities,
            such as proper motion and radial velocity.  If equal to 'base',
            which is the default, it will be inferred from the representation.
            If `None`, the representation will drop any differentials.
        Nr*   r   )rv   r2   )r   r*   rs   s      r"   set_representation_clsz*BaseCoordinateFrame.set_representation_cls  s1     <'/D0da@@@r$   ae  The representation class used for this frame's data.

        This will be a subclass from `~astropy.coordinates.BaseRepresentation`.
        Can also be *set* using the string name of the representation. If you
        wish to set an explicit differential class (rather than have it be
        inferred), use the ``set_representation_cls`` method.
        )fgetfsetr   c                 ,    |                      d          S )a  
        The differential used for this frame's data.

        This will be a subclass from `~astropy.coordinates.BaseDifferential`.
        For simultaneous setting of representation and differentials, see the
        ``set_representation_cls`` method.
        rs   )r   r   s    r"   r1   z%BaseCoordinateFrame.differential_type0  s     **3///r$   c                 2    |                      |           d S )N)rs   )r   r   r!   s     r"   r1   z%BaseCoordinateFrame.differential_type;  s    ##e#,,,,,r$   c                 h   | j                             dd           t          j                    k    ri }t	          t          j                                                  t	          t          j                                                  z   D ]}g g d||<   |j        	                                D ]j\  }}||         d         
                    |           t          |t                    rt          j        nd }||         d         
                    |           k| j        	                                D ]\  }}||         d         }||         d         }d |D             }	t!          |j                                                  D ]J\  }
}||	v rA|	|         }|j        ||
<   t'          |j        t*                    r|j        dk    s
|j        ||
<   Kt-          |          ||         d<   t-          |          ||         d<   || j         d<   t          j                    | j         d<   | j         d         S )Nlast_reprdiff_hash)r   r   r   r   c                     i | ]
}|j         |S rT   )r3   r   s     r"   rr   z@BaseCoordinateFrame._get_representation_info.<locals>.<dictcomp>^  s    ===qQZ===r$   r7   representation_info)ra   r,   r   get_reprdiff_cls_hashr   r   r~   r&   attr_classesr+   r{   r   r   r   degrN   	enumerater   r4   r   r5   r   r   )r<   
repr_attrsrepr_diff_clscc_clsrec_unitmappingsnmsuns	comptomapimapps               r"   _get_representation_infoz,BaseCoordinateFrame._get_representation_info?  sV    "&&';TBB&(() ) J!%a&>&E&E&G&G!H!H4&--//L L " H H 792,F,F
=) - : @ @ B B H HHAu}-g6==a@@@(25%(@(@JquudH}-g6==hGGGGH 8>>@@@ @ 
 !/8 /8==H===	%m&@&E&E&G&GHH 6 6DAqI~~(|!%A
 't'7==6 $ 0M A A%)%5CF 6;3ZZ
=)'25:3ZZ
=)'22<FC"#89;<;R;T;TC"#78%&;<<r$   c                 *    |                                  S )z
        A dictionary with the information of what attribute names for this frame
        apply to particular representations.
        )r  r   s    r"   r  z'BaseCoordinateFrame.representation_infou  s     ,,...r$   c                     i }|                      |          }||S |j                                        }| j        |         d         }t	          ||          D ]
\  }}|||<   |S )Nr   )r   r  r   r  zip)r   r   outrepr_or_diff_cls
data_names
repr_namesr   	data_names           r"   r   z6BaseCoordinateFrame.get_representation_component_names}  s{    66u==#J%27799
-.>?H
$'
J$?$? 	' 	' Iy&C	NN
r$   c                     i }|                      |          }||S | j        |         }|d         }|d         }t          ||          D ]\  }}|r|||<   |S )Nr   r   )r   r  r  )	r   r   r  r  r  r  
repr_unitsr   	repr_units	            r"   "get_representation_component_unitsz6BaseCoordinateFrame.get_representation_component_units  s}    66u==#J-.>?
(
(
$'
J$?$? 	+ 	+ Iy +!*I
r$   Fc                    t          j        |          rt          d          |r||                                }| j        D ]:}|| j        vr/||vr+t          | |          }|r|                                }|||<   ; | j        |fddi|S )a  Base for replicating a frame, with possibly different attributes.

        Produces a new instance of the frame using the attributes of the old
        frame (unless overridden) and with the data given.

        Parameters
        ----------
        data : `~astropy.coordinates.BaseRepresentation` or None
            Data to use in the new frame instance.  If `None`, it will be
            a data-less frame.
        copy : bool, optional
            Whether data and the attributes on the old frame should be copied
            (default), or passed on by reference.
        **kwargs
            Any attributes that should be overridden.
        zClass passed as data instead of a representation instance. If you called frame.representation, this returns the representation class. frame.data returns the instantiated object - you may want to  use this instead.NrX   F)r   r   r|   rX   r]   rt   rQ   r=   )r   r   rX   rd   attrr!   s         r"   
_replicatezBaseCoordinateFrame._replicate  s    ( ?4   	!    	D$99;;D) 	% 	%D4999d&>P>Pd++ )!JJLLE$tt~d999&999r$   c                 ,     | j         | j        fd|i|S )a  
        Return a replica of the frame, optionally with new frame attributes.

        The replica is a new frame object that has the same data as this frame
        object and with frame attributes overridden if they are provided as extra
        keyword arguments to this method. If ``copy`` is set to `True` then a
        copy of the internal arrays will be made.  Otherwise the replica will
        use a reference to the original arrays when possible to save memory. The
        internal arrays are normally not changeable by the user so in most cases
        it should not be necessary to set ``copy`` to `True`.

        Parameters
        ----------
        copy : bool, optional
            If True, the resulting object is a copy of the data.  When False,
            references are used where  possible. This rule also applies to the
            frame attributes.
        **kwargs
            Any additional keywords are treated as frame attributes to be set on the
            new frame object.

        Returns
        -------
        frameobj : `~astropy.coordinates.BaseCoordinateFrame` subclass instance
            Replica of this object, but possibly with new frame attributes.
        rX   )r!  r   r   rX   rd   s      r"   	replicatezBaseCoordinateFrame.replicate  s%    6 tty>>t>v>>>r$   c                       | j         dd|i|S )a6  
        Return a replica without data, optionally with new frame attributes.

        The replica is a new frame object without data but with the same frame
        attributes as this object, except where overridden by extra keyword
        arguments to this method.  The ``copy`` keyword determines if the frame
        attributes are truly copied vs being references (which saves memory for
        cases where frame attributes are large).

        This method is essentially the converse of `realize_frame`.

        Parameters
        ----------
        copy : bool, optional
            If True, the resulting object has copies of the frame attributes.
            When False, references are used where  possible.
        **kwargs
            Any additional keywords are treated as frame attributes to be set on the
            new frame object.

        Returns
        -------
        frameobj : `~astropy.coordinates.BaseCoordinateFrame` subclass instance
            Replica of this object, but without data and possibly with new frame
            attributes.
        NrX   r9   r!  r#  s      r"   replicate_without_dataz*BaseCoordinateFrame.replicate_without_data  s!    6 t99$9&999r$   c                      | j         |fi |S )a  
        Generates a new frame with new data from another frame (which may or
        may not have data). Roughly speaking, the converse of
        `replicate_without_data`.

        Parameters
        ----------
        data : `~astropy.coordinates.BaseRepresentation`
            The representation to use as the data for the new frame.
        **kwargs
            Any additional keywords are treated as frame attributes to be set on the
            new frame object. In particular, `representation_type` can be specified.

        Returns
        -------
        frameobj : `~astropy.coordinates.BaseCoordinateFrame` subclass instance
            A new object in *this* frame, with the same frame attributes as
            this one, but with the ``data`` as the coordinate data.

        r&  )r   r   rd   s      r"   realize_framez!BaseCoordinateFrame.realize_frame  s    * tt..v...r$   c                 H   t          |t                    rt          j        dt                     |}d}t          ||          }|d         }d| j        j        v rE|dk    r6| j        j        d         j        |j	        v r| j        j        d         j        }n#|d         }n||dk    rd}nt          d          |r|j        |j        |f}n	|j        |f}| j        d                             |          }|s|rt          | j        t          j                  rot!          |t          j                  rUt          | j        j        d         t          j        t          j        t          j        f          st+          j        d          | j                            ||          j        d         n| j                            |          | j                            |          }	|	re|rcfd	j        D             }
t5          j        |	d
                   D ]%\  }}|r|
|                             |          |
|<   & j        dddi|
|r0| j        j        d         }| j                            |          }	|	r|rfdj        D             }t5          j        |	d
                   D ]\  }}t          |t          j        t          j        f          r||j        j        vr:t          |t          j                  r||j        j        vrc|r@t;          |          r0	 ||                             |          ||<   # t<          $ r Y w xY w j        dddi|j                             di           | j        d         |<   | j        d         |         S )a  
        Generate and return a new representation of this frame's `data`
        as a Representation object.

        Note: In order to make an in-place change of the representation
        of a Frame or SkyCoord object, set the ``representation``
        attribute of that object to the desired new representation, or
        use the ``set_representation_cls`` method to also set the differential.

        Parameters
        ----------
        base : subclass of BaseRepresentation or string
            The type of representation to generate.  Must be a *class*
            (not an instance), or the string name of the representation
            class.
        s : subclass of `~astropy.coordinates.BaseDifferential`, str, optional
            Class in which any velocities should be represented. Must be
            a *class* (not an instance), or the string name of the
            differential class.  If equal to 'base' (default), inferred from
            the base class.  If `None`, all velocity information is dropped.
        in_frame_units : bool, keyword-only
            Force the representation units to match the specified units
            particular to this frame

        Returns
        -------
        newrep : BaseRepresentation-derived object
            A new representation object of this frame's `data`.

        Raises
        ------
        AttributeError
            If this object had no `data`

        Examples
        --------
        >>> from astropy import units as u
        >>> from astropy.coordinates import SkyCoord, CartesianRepresentation
        >>> coord = SkyCoord(0*u.deg, 0*u.deg)
        >>> coord.represent_as(CartesianRepresentation)  # doctest: +FLOAT_CMP
        <CartesianRepresentation (x, y, z) [dimensionless]
                (1., 0., 0.)>

        >>> coord.representation_type = CartesianRepresentation
        >>> coord  # doctest: +FLOAT_CMP
        <SkyCoord (ICRS): (x, y, z) [dimensionless]
            (1., 0., 0.)>
        znThe argument position for `in_frame_units` in `represent_as` has changed. Use as a keyword argument if needed.r*   r   rs   NzFrame data has no associated differentials (i.e. the frame has no velocity data) - represent_as() only accepts a new representation.r   zneed a distance to retrieve a cartesian representation when both radial velocity and proper motion are present, since otherwise the units cannot match.c                 2    i | ]}|t          |          S rT   rP   )rR   r   r   s     r"   rr   z4BaseCoordinateFrame.represent_as.<locals>.<dictcomp>  s%    TTTDdGD$$7$7TTTr$   r   rX   Fc                 2    i | ]}|t          |          S rT   rP   )rR   r   diffs     r"   rr   z4BaseCoordinateFrame.represent_as.<locals>.<dictcomp>  s%    !X!X!X$d(;(;!X!X!Xr$   rT   )!r   boolwarningswarnr   r2   r   r.   r=   _compatible_differentialsr|   r>   r   r,   r   r   r   CartesianRepresentationr   r   r   r   UnitConversionErrorrepresent_asr  rE   r  tor  r_   r   _differentialsr\   )r   r*   rs   in_frame_unitsr/   r   r   	cache_keycached_repr	new_attrs
datakwargsr   new_attr_unit	data_diff
diffkwargsr   r-  s                  @@r"   r4  z BaseCoordinateFrame.represent_as  sm   j a 	MA  
 NA
 )da888)&1$)))) F{{	',6%?@ @ $(9#:3#?#I  #/#4  Y!v++#V  
  	F"+ )II ,4nEIj!1266yAA a	; B
 ty!*GHH"#5q7PQQ '	/47=0  /B   y--.@BRSS)#.y--.@AA 0445GHHI @^ @TTTTDOTTT
+.t	'@R+S+S N N'D-$ N+5d+;+>+>}+M+M
4(%t~??5?J?? 8< I3C8	 !4889IJJ	 1< 1<!X!X!X!X!X!X!XJ/24?IgDV/W/W "% "%+m ' )$%$?$%$E!" % !%I,?,L L L$ 'y!2FGG% $I,?,L L L$ ) %WT4-@-@ %%3=d3C3F3F}3U3U
4 0 0#, % % % $% *4>CCuC
CCD '..T{;;;6:DJ'(3z*+I66s   &M
MMc                    ddl m} | j        t          d          t	          | j        dd          rQt          | d          rAt          |d          r1t          j        | j	        |j	        k              rt          d          t          j        |          r$t          j        dt                      |            }t          |d	          r|j        }t"                              | j        |j                  }|N|| j        u r|                    | j                  S d
} ||                    | j        |j                             || |          S )a]  
        Transform this object's coordinate data to a new frame.

        Parameters
        ----------
        new_frame : coordinate-like or `~astropy.coordinates.BaseCoordinateFrame` subclass instance
            The frame to transform this coordinate frame into.
            The frame class option is deprecated.

        Returns
        -------
        transframe : coordinate-like
            A new object with the coordinate data represented in the
            ``newframe`` system.

        Raises
        ------
        ValueError
            If there is no possible transformation route.
        r   )ConvertErrorNz%Cannot transform a frame with no datar.   obstimezYou cannot transform a frame that has velocities to another frame at a different obstime. If you think this should (or should not) be possible, please comment at https://github.com/astropy/astropy/issues/6280a  Transforming a frame instance to a frame class (as opposed to another frame instance) will not be supported in the future.  Either explicitly instantiate the target frame, or first convert the source frame instance to a `astropy.coordinates.SkyCoord` and use its `transform_to()` method._sky_coord_framez Cannot transform from {0} to {1})errorsr@  rx   r   rQ   r   r_   npanyrA  NotImplementedErrorr   r   r/  r0  r   rB  r   get_transformr=   r)  r   )r   	new_framer@  transr   s        r"   transform_toz BaseCoordinateFrame.transform_to  s{   * 	)(((((:DEEE DI55	i((	 	9--	 t|y'8899		 &B   ?9%% 
	$M+
 *   "	I9011 	3 "2I%33DNIDWXX=DN** ..ty9994C,szz$.):MNNOOOuT9%%%r$   c                     t          j        |          r|n|j        }t                              | j        |          }||| j        u rdS dS dS )a  
        Determines if this coordinate frame can be transformed to another
        given frame.

        Parameters
        ----------
        new_frame : `~astropy.coordinates.BaseCoordinateFrame` subclass or instance
            The proposed frame to transform into.

        Returns
        -------
        transformable : bool or str
            `True` if this can be transformed to ``new_frame``, `False` if
            not, or the string 'same' if ``new_frame`` is the same system as
            this object but no transformation is defined.

        Notes
        -----
        A return value of 'same' means the transformation will work, but it will
        just give back a copy of this object.  The intended usage is::

            if coord.is_transformable_to(some_unknown_frame):
                coord2 = coord.transform_to(some_unknown_frame)

        This will work even if ``some_unknown_frame``  turns out to be the same
        frame class as ``coord``.  This is intended for cases where the frame
        is the same regardless of the frame attributes (e.g. ICRS), but be
        aware that it *might* also indicate that someone forgot to define the
        transformation between two objects of the same frame class but with
        different attributes.
        NsameFT)r   r   r=   r   rG  )r   rH  new_frame_clsrI  s       r"   is_transformable_toz'BaseCoordinateFrame.is_transformable_to  sX    @ &-_Y%?%?X		YEX%33DNMRR=..vu4r$   c                     || j         v S )a  
        Determine whether or not a frame attribute has its value because it's
        the default value, or because this frame was created with that value
        explicitly requested.

        Parameters
        ----------
        attrnm : str
            The name of the attribute to check.

        Returns
        -------
        isdefault : bool
            True if the attribute ``attrnm`` has its value by default, False if
            it was specified at creation of this frame.
        )rt   )r   attrnms     r"   is_frame_attr_defaultz)BaseCoordinateFrame.is_frame_attr_defaultD  s    " 777r$   c                      u rdS  dS t           t          j                  }t          t          j                  }|r|rt           dd          st          dd          rt	          j        dt                     dS t           j                  r&t          j	         fd j
        D                       S t          j	                                         j                                        j        k              S |s|rdS t           t                    }t          t                    }|r1|r/                               rt          j	         k              S dS |s|rdS t          j	         k              S )a  
        Determine if two frame attributes are equivalent.  Implemented as a
        staticmethod mainly as a convenient location, although conceivable it
        might be desirable for subclasses to override this behavior.

        Primary purpose is to check for equality of representations.  This
        aspect can actually be simplified/removed now that representations have
        equality defined.

        Secondary purpose is to check for equality of coordinate attributes,
        which first checks whether they themselves are in equivalent frames
        before checking for equality in the normal fashion.  This is because
        checking for equality with non-equivalent frames raises an error.
        TNFr.   zTwo representation frame attributes were checked for equivalence when at least one of them has differentials.  This yields False even if the underlying representations are equivalent (although this may change in future versions of Astropy)c                 T    g | ]$}t          |          t          |          k    %S rT   rP   )rR   r   
left_fattrright_fattrs     r"   rS   z8BaseCoordinateFrame._frameattr_equiv.<locals>.<listcomp>  sB         !T22gk46P6PP  r$   )r   r    BaseRepresentationOrDifferentialrQ   r/  r0  r   r=   rD  allrE   to_cartesianxyzr   is_equivalent_frame)rT  rU  left_is_reprright_is_reprleft_is_coordright_is_coords   ``    r"   _frameattr_equivz$BaseCoordinateFrame._frameattr_equivW  s     $$4;#65!*a.PQQ";0RSS 	M 	z?E:: 
g_e? ? 
 F #   u+z';<< v    $.$9     v++--1[5M5M5O5O5SS    	] 	5":/BCC#K1DEE 	^ 	--k:: vjK7888u 	n 	5vjK/000r$   c                     | j         |j         k    rA| j        D ]7}|                     t          | |          t          ||                    s dS 8dS t	          |t
                    st          d          dS )a  
        Checks if this object is the same frame as the ``other`` object.

        To be the same frame, two objects must be the same frame class and have
        the same frame attributes.  Note that it does *not* matter what, if any,
        data either object has.

        Parameters
        ----------
        other : :class:`~astropy.coordinates.BaseCoordinateFrame`
            the other frame to check

        Returns
        -------
        isequiv : bool
            True if the frames are the same, False if not.

        Raises
        ------
        TypeError
            If ``other`` isn't a `~astropy.coordinates.BaseCoordinateFrame` or subclass.
        FTz?Tried to do is_equivalent_frame on something that isn't a frame)r=   r]   r_  rQ   r   r   r|   )r   otherframe_attr_names      r"   rZ  z'BaseCoordinateFrame.is_equivalent_frame  s    . >U_,,#'#8 ! !,,D/22GE?4S4S  ! !55! 4E#677 	Q   5r$   c                     |                                  }|                                 }|rd| d}|rd| j        j         d| d| dS d| j        j         d| dS )Nz ()<z Coordinatez: >z Frame)_frame_attrs_repr
_data_reprr=   r>   )r   
frameattrs	data_reprs      r"   __repr__zBaseCoordinateFrame.__repr__  s    ++--
OO%%	 	,+j+++J 	DUt~.UU:UUUUUUCt~.CCjCCCCr$   c                    | j         sdS | j        rt          | j        d          r,t          | j        | j        j                  r| j        j        }n| j        }d| j        j        v r`|                     d          }| j        j        d         }t          |t          j
        t          j        t          j        f          r|j        }nd}|                     ||d          }t          |          }|                    d          \  }}}|dk    r|                    d          \  }	}}
|	                    d	          }d
 | j                                        D             }t'          |          D ]\  }}|                    ||          ||<   |dz   d	                    |          z   dz   |
z   }n| j        }t          | j                  }|                    d|j        j        z             r%|t1          |j        j                  dz   d         }nd|z   }d| j        j        v rK|                    d          }d|d         v rt          |j        d                                       d          }|d                             d          r<dd                    |d                             d          dd                   z   |d<   |                     d                                          D ]$\  }}|d                             ||          |d<   %|d                             d          r|d         dd         |d<   d                    |          |d<   d                    |          }|S )z7Returns a string representation of the coordinate data.rD   r   rs   NTr7  (rd  , c                     i | ]\  }}||	S rT   rT   )rR   nmprefnmreprs      r"   rr   z2BaseCoordinateFrame._data_repr.<locals>.<dictcomp>  s.       & F  r$   re     zData:

zhas differentialsr    r   rf  )r   rl   r_   r   r   r   r=   r.   r   r   r   r   r   r4  repr	partitionsplitr   r+   r  r,   join
startswithr>   r}   r   r   endswith)r   rep_clsdif_clsdif_datar   rj  part1rn   	remaindercomp_strpart2
comp_namesinvnamesr  r0   data_repr_spldiffreprfrm_nmrep_nms                      r"   rh  zBaseCoordinateFrame._data_repr  s   } 	2# ,	(t/1GHH 3Z	43HN N 3 )-2di---55c::923739,  1 '0G $$Wgd$KKDT

I"+"5"5c":":E1iB%.%8%8%=%="!U%^^D11
 *.*M*S*S*U*U    )44 = =GAt$,LLt$<$<JqMM!CK$))J*?*??#EM	 9DTYIdn&= =>> 	. "3t~'>#?#?!#Cr"IJII!I-I$))))%OOD11M"mB&777 23 788>>tDDA;))#.. M"%!1B1B31G1G1K(L(L"LHQK&*&M&M' '%''F FNFF #+1+"5"5ff"E"EHQKKB<((-- 5#+B<#4HRL$(IIh$7$7b!		-00Ir$   c                     g }| j         D ]`}t          | |          }t          |d          r|                                }nt	          |          }|                    | d|            ad                    |          S )zT
        Returns a string representation of the frame's attributes, if any.
        _astropy_repr_in_frame=ro  )r]   rQ   r_   r  r   r{   rz  )r   	attr_strsattribute_namer   attrstrs        r"   rg  z%BaseCoordinateFrame._frame_attrs_repr  s     	"3 		< 		<N400D t566 $5577d))::::;;;;yy###r$   c           	        	 fd}t                                          | j                  	t          | d          r| j                                        	_        | j                                        	_        | j        D ]}d|z   }|| j        v r t          	|t          | |                     0t          | |          }t          |dd          r ||          }n dk    sdk    rt          j        |          }t          	||           | j
        r || j                  	_        nMd	_        	fd		j        D             }|r*t          |          d
k    r	t          | n|d         	_        nd	_        	S )a}  Create a new instance, applying a method to the underlying data.

        In typical usage, the method is any of the shape-changing methods for
        `~numpy.ndarray` (``reshape``, ``swapaxes``, etc.), as well as those
        picking particular elements (``__getitem__``, ``take``, etc.), which
        are all defined in `~astropy.utils.shapes.ShapedLikeNDArray`. It will be
        applied to the underlying arrays in the representation (e.g., ``x``,
        ``y``, and ``z`` for `~astropy.coordinates.CartesianRepresentation`),
        as well as to any frame attributes that have a shape, with the results
        used to create a new instance.

        Internally, it is also used to apply functions to the above parts
        (in particular, `~numpy.broadcast_to`).

        Parameters
        ----------
        method : str or callable
            If str, it is the name of a method that is applied to the internal
            ``components``. If callable, the function is applied.
        *args : tuple
            Any positional arguments for ``method``.
        **kwargs : dict
            Any keyword arguments for ``method``.
        c                     t          | t                    r | j        gR i S t                    r | gR i S  t	          |           i S r9   )r   r   _applycallablerQ   )r!   r   rd   methods    r"   apply_methodz0BaseCoordinateFrame._apply.<locals>.apply_methodC  s    %!233 C#u|F<T<<<V<<<F## C!6%9$999&999175&114B6BBBr$   rv   rn   rp   rT   rX   flattenNc           	          g | ]E}|j         vt          t          d |z             dd          -t          d |z             j        FS )rn   rp   rT   )rt   rQ   rp   )rR   r   news     r"   rS   z.BaseCoordinateFrame._apply.<locals>.<listcomp>e  sf        ===S4Z 8 8'2FF > S4Z((. >==r$   r   r   )r:   r;   r=   r_   rv   rX   rt   r]   rz   rQ   r   r   rx   r}   r   r   )r   r  r   rd   r  r   _attrr!   r   r  r=   s    ```     @r"   r  zBaseCoordinateFrame._apply)  s   4	C 	C 	C 	C 	C 	C 	C ggoodn--4*++ 	>"&"6";";"="=C(,(F(K(K(M(M%) 	+ 	+D$JEt555UGD%$8$89999e,,5'2.. -(L//EEv%%9)<)< !Ie,,EUE****= 	($TY//CIICI   0  F  (03FaOV,,VAY "" &("
r$   c                    | j         |j         ur)t          d| j         j         d|j         j                   |                     |          st	          d          |j        t	          d          | j        t	          d          | j        dk    rt          d| j         j         d          | j        t	          d	          | j        j         |j        j         ur3t          d| j        j         j         d|j        j         j                   | j        j        r| j        j                                        |j        j                                        k    rt	          d
          | j        j        	                                D ]\\  }}|j         |j        j        |         j         ur9t          d|j         j         d|j        j        |         j         j                   ]|j        | j        |<   | j
                                         d S )Nz(can only set from object of same class:  vs. z0can only set frame item from an equivalent framez+can only set frame with value that has dataz"cannot set frame which has no datarT   zscalar 'z/' frame object does not support item assignmentz!can only set frame if it has dataz*setitem value must have same differentials)r=   r|   r>   rZ  r   rx   rp   r6  r   r+   r   clear)r   itemr!   r   	self_diffs        r"   __setitem__zBaseCoordinateFrame.__setitem__v  sY   >00/4>;R / /O,/ /  
 ''.. 	QOPPP;JKKK:ABBB:34>2 3 3 3  
 :@AAA:u{'<<<X:'0X X7<{7L7UX X  
 :$ 	 z(--//5;3M3R3R3T3TTT !MNNN"&*";"A"A"C"C  Y&ek.H.M.WWW#P$.7P P ;5c:DMP P   X !;
4
 	
r$   c                     t          t          t                                                                t          | j                  z  t          |                     d                    z            S )z
        Override the builtin `dir` behavior to include representation
        names.

        TODO: dynamic representation transforms (i.e. include cylindrical et al.).
        rs   )sortedsetr:   __dir__r   r   )r   r=   s    r"   r  zBaseCoordinateFrame.__dir__  sb     !!""$5667$99#>>??@
 
 	
r$   c                    |                     d          r|                     |          S | j        }||v rB| j        | j         |                     | j        d          }t          |||                   }|S |                     d          }||v rS| j        | j          | j        dddi| 	                    d          }t          |j
        d         ||                   }|S |                     |          S )a$  
        Allow access to attributes on the representation and differential as
        found via ``self.get_representation_component_names``.

        TODO: We should handle dynamic representation transforms here (e.g.,
        `.cylindrical`) instead of defining properties as below.
        rn   NTrm  rs   r7  rT   )r{  __getattribute__r   rx   r   r4  rl   rQ   r   r   r.   )r   r   r  repr   
diff_namess         r"   __getattr__zBaseCoordinateFrame.__getattr__  s!    ??3 	/((...8
:z!		 ##D$<T#RRC#z$/00CJ<<SAA
:z!		
 $$#  #'+'B'B4'H'H C #+C0*T2BCCCJ$$T***r$   c                 L   |                     d          skt          | d          r[t                      }| j                                        D ]}|                    |d                    ||v rt          d|           t                                          ||           d S )Nrn   r  r   zCannot set any frame attribute )	r{  r_   r  r  r~   r\   AttributeErrorr:   __setattr__)r   r   r!   repr_attr_namesrepresentation_attrr=   s        r"   r  zBaseCoordinateFrame.__setattr__  s    s## 	St233 S"%%%+/+C+J+J+L+L I I'#**+>w+GHHHH?**()Q4)Q)QRRRD%(((((r$   c                 `   t          |t                    st          S |                     |          }| j        	|j        |S |s9t          d|                                  d|                                           |j        du | j        du k    rt          d          | j        |j        k    S )zEquality operator for frame.

        This implements strict equality and requires that the frames are
        equivalent and that the representation data are exactly equal.
        Nz5cannot compare: objects must have equivalent frames: r  z9cannot compare: one frame has data and the other does not)r   r   NotImplementedrZ  rx   r|   r'  r   )r   r!   is_equivs      r"   __eq__zBaseCoordinateFrame.__eq__  s     %!455 	"!!++E22:%+"5O 	X..00X X7<7S7S7U7UX X  
 K4TZ4%788K   zU[((r$   c                 2    t          j        | |k              S r9   )rD  logical_notr   s     r"   __ne__zBaseCoordinateFrame.__ne__  s    ~dem,,,r$   c                 2   ddl m} ddlm} |                     t
          j                  }|                    |           }|                    t
          j                  } ||j        |j	        |j        |j	                  } ||t          j                  S )a  
        Computes on-sky separation between this coordinate and another.

        .. note::

            If the ``other`` coordinate object is in a different frame, it is
            first transformed to the frame of this object. This can lead to
            unintuitive behavior if not accounted for. Particularly of note is
            that ``self.separation(other)`` and ``other.separation(self)`` may
            not give the same answer in this case.

        Parameters
        ----------
        other : `~astropy.coordinates.BaseCoordinateFrame`
            The coordinate to get the separation to.

        Returns
        -------
        sep : `~astropy.coordinates.Angle`
            The on-sky separation between this and the ``other`` coordinate.

        Notes
        -----
        The separation is calculated using the Vincenty formula, which
        is stable at all locations, including poles and antipodes [1]_.

        .. [1] https://en.wikipedia.org/wiki/Great-circle_distance

        r   )angular_separationr   )unit)angle_utilitiesr  anglesr   r4  r   r   rJ  r   r   r   degree)r   ra  r  r   self_unit_sphother_transformedother_unit_sphseps           r"   
separationzBaseCoordinateFrame.separation  s    < 	877777!!!!!!))!*GHH!..t44*778UVV ! }0.2DnFX
 
 uSqx((((r$   c                 D   ddl m} t          | j        j        t
          j                  rt          d          |                    |           }t          |j        t
          j                  rt          d          | j        	                                
                    t
          j                  }|j        	                                
                    t
          j                  }||z
                                  }|j        t          j        k    r|S  ||          S )a  
        Computes three dimensional separation between this coordinate
        and another.

        Parameters
        ----------
        other : `~astropy.coordinates.BaseCoordinateFrame`
            The coordinate system to get the distance to.

        Returns
        -------
        sep : `~astropy.coordinates.Distance`
            The real-space distance between these two coordinates.

        Raises
        ------
        ValueError
            If this or the other coordinate do not have distances.
        r   )DistancezCThis object does not have a distance; cannot compute 3d separation.zHThe other object does not have a distance; cannot compute 3d separation.)	distancesr  r   r   r=   r   r   r   rJ  without_differentialsr4  r2  normr  r   one)r   ra  r  other_in_self_systemself_car	other_cardists          r"   separation_3dz!BaseCoordinateFrame.separation_3d9  s   ( 	('''''di)1+HII 	U  
  %11$77*4a6STT 	0   92244AA%
 
 )-CCEERR%
 
	 9$**,,9K8D>>!r$   c                 0    |                      dd          S )ze
        Shorthand for a cartesian representation of the coordinates in this
        object.
        	cartesianTrm  r4  r   s    r"   r  zBaseCoordinateFrame.cartesiank         T BBBr$   c                 0    |                      dd          S )zg
        Shorthand for a cylindrical representation of the coordinates in this
        object.
        cylindricalTrm  r  r   s    r"   r  zBaseCoordinateFrame.cylindricalu  s       t DDDr$   c                 0    |                      dd          S )ze
        Shorthand for a spherical representation of the coordinates in this
        object.
        	sphericalTrm  r  r   s    r"   r  zBaseCoordinateFrame.spherical  r  r$   c                 2    |                      ddd          S )z
        Shorthand for a spherical representation of the positional data and a
        `~astropy.coordinates.SphericalCosLatDifferential` for the velocity
        data in this object.
        r  sphericalcoslatTrm  r  r   s    r"   r  z#BaseCoordinateFrame.sphericalcoslat  s!       .?PT UUUr$   c                 `    d| j         j        vrt          d          | j        j        d         S )z
        Shorthand for retrieving the Cartesian space-motion as a
        `~astropy.coordinates.CartesianDifferential` object.

        This is equivalent to calling ``self.cartesian.differentials['s']``.
        rs   AFrame has no associated velocity (Differential) data information.)r   r.   r   r  r   s    r"   velocityzBaseCoordinateFrame.velocity  s;     di---S   ~+C00r$   c                 8   d| j         j        vrt          d          |                     ddd          }|j        d         j        }|j        d         j        }t          j        |j        |	                    |j
                  j        fd          |j
        z  S )	a  
        Shorthand for the two-dimensional proper motion as a
        `~astropy.units.Quantity` object with angular velocity units. In the
        returned `~astropy.units.Quantity`, ``axis=0`` is the longitude/latitude
        dimension so that ``.proper_motion[0]`` is the longitudinal proper
        motion and ``.proper_motion[1]`` is latitudinal. The longitudinal proper
        motion already includes the cos(latitude) term.
        rs   r  r  r  Trm  r   )axis)r   r.   r   r4  r   r   rD  stackr!   r5  r  )r   sphpm_lonpm_lats       r"   proper_motionz!BaseCoordinateFrame.proper_motion  s     di---S   ->tTT"3'4"3'-HflFIIfk$:$:$@AJJJV[X	
r$   c                     d| j         j        vrt          d          |                     dd          }|j        d         j        S )zs
        Shorthand for the radial or line-of-sight velocity as a
        `~astropy.units.Quantity` object.
        rs   r  r  Trm  )r   r.   r   r4  r   )r   r  s     r"   r   z#BaseCoordinateFrame.radial_velocity  sT     di---S   DAA %00r$   r9   )r*   )Nr*   )F)r*   F)Fr>   r?   r@   rA   rI   rJ   rK   r]   rb   r   ru   rw   classmethodrV   rW   r
   r   rU   r   r   rp   r   r   r   r   rc   r   r   r   r   rl   r1   setterr  r  r   r  r   representation_component_unitsr!  r$  r'  r)  r4  rJ  rN  rQ  staticmethodr_  rZ  rk  rh  rg  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   rB   rC   s   @r"   r   r      s       $ $L " *,&O& O& O& O& O&h  V; V; V; V; V;pK K K8b# b# b#H Z Z [Zx ; ; ; [; ! ! \!* 
 
 X
 & & X& I I XI
  / / /   X 4 4 X4 K K [K Z-N		 	 	 - - [	 	-( ( ( ((A A A A" #(##
 
 
 0 0 X0 - - - 3= 3= [3=j / / \/	 	 	 	    &.X.P%Q%Q"%-X.P%Q%Q"&: &: &: &:P? ? ? ?:: : : ::/ / /.D7 D7 D7 D7L?& ?& ?&B) ) )V8 8 8& @1 @1 \@1D# # #J
D 
D 
DJ J JX$ $ $$K K K K KZ3 3 3j
 
 
 
 
(+ (+ (+T) ) ) ) )) ) )8- - -)) )) ))V0" 0" 0"d C C XC E E XE C C XC V V XV 1 1 X1 
 
 X
* 1 1 X1 1 1 1 1r$   r   c                   6     e Zd ZdZdZ fdZd Z fdZ xZS )r   aS  
    A frame object that can't store data but can hold any arbitrary frame
    attributes. Mostly useful as a utility for the high-level class to store
    intermediate frame attributes.

    Parameters
    ----------
    frame_attrs : dict
        A dictionary of attributes to be used as the frame attributes for this
        frame.
    Nc                     i | _         |                                D ]0\  }}t          |          | j         |<   t          | d|z   |           1t	                                          d            d S )Nrn   )r]   r+   r   rz   r:   r   )r   rh   r0   defaultr=   s       r"   r   zGenericFrame.__init__  sv     "(..00 	/ 	/MD'*3G*<*<D!$'D#*g....r$   c                 d    d|z   | j         v rt          | d|z             S t          d|           )Nrn   zno )r^   rQ   r  )r   r0   s     r"   r  zGenericFrame.__getattr__  s;    :&&4t,,, t...r$   c                     || j         v rt          d| d          t                                          ||           d S )Nzcan't set frame attribute '')r]   r  r:   r  )r   r0   r!   r=   s      r"   r  zGenericFrame.__setattr__  sK    4((( !Ft!F!F!FGGGGGe,,,,,r$   )	r>   r?   r@   rA   r0   r   r  r  rB   rC   s   @r"   r   r     sq        
 
 D    / / /- - - - - - - - -r$   r   )*rA   rX   r   r/  collectionsr   r   numpyrD  astropyr   r   astropy.utilsr   r   astropy.utils.decoratorsr   r	   r
   astropy.utils.exceptionsr   r   rD   r   r   r  r   
attributesr   transformationsr   __all__r   r#   r(   r2   _RepresentationMappingBaser   base_doc_componentsr   r   rT   r$   r"   <module>r     s.       / / / / / / / /           < < < < < < < < J I I I I I I I I I N N N N N N N N ! ! ! ! ! !       ! ! ! ! ! ! + + + + + +   '((     "' ' 'T (ZE  
F F F F F6 F F F < HR888Y1 Y1 Y1 Y1 Y1+ Y1 Y1 98Y1x8!- !- !- !- !-& !- !- !- !- !-r$   