
    HR-eR                        d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZ d dl	Z	d dl
Zd dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d	d
lmZmZmZ d	dlmZ d	dlm Z  d	dl!m"Z"m#Z#m$Z$ g dZ% e j&        dg d          Z'i Z(	 dej)        z  ej*        z  +                    d	ej,        z   ej-                              Z.	 d"dZ/d Z0 G d de          Z1 G d dej2                  Z3dZ4 ee4           G d de"                      Z5 ee4           G d de5                      Z6 ee4           G d de5                      Z7 ee4           G d  d!e5                      Z8dS )#    N)warn)	constants)units)QuantityInfoBase)data)
format_doc)AstropyUserWarning   )AngleLatitude	Longitude)UnknownSiteException)matrix_transpose)BaseRepresentationCartesianDifferentialCartesianRepresentation)EarthLocationBaseGeodeticRepresentationWGS84GeodeticRepresentationWGS72GeodeticRepresentationGRS80GeodeticRepresentationGeodeticLocationlonlatheightg+6?WGS84c                 V    | |} | t           vrt          d|  dt            d          | S )Nz
Ellipsoid z not among known ones ())
ELLIPSOIDS
ValueError)	ellipsoiddefaults     9lib/python3.11/site-packages/astropy/coordinates/earth.py_check_ellipsoidr%   ;   s@    	
""UiUU
UUUVVV    c                 ,   ddl m} 	 t          j                            | t
          j        j                  }t          j	        |
                                                    d                    }n# t          j        j        $ ri}t          |j        t           j                  r  ||                    d                    | ||                    |j                            |d }~wt           j        $ r   ||                    d                    w xY w|rP|                    dg           }|                    dd           d	k    r ||                    d
                    n|}|s ||                    d                    |S )Nr
   )NameResolveError)timeoututf8zconnection timed out)msgresultsstatusOKzunknown failure with Google APIzno results returned)name_resolver(   urllibrequesturlopenr   confremote_timeoutjsonloadsreaddecodeerrorURLError
isinstancereasonsocketr)   formatget)urlerr_str
use_googler(   resp	resp_dataer,   s           r$   _get_json_resultrF   C   s   ......K~%%c493K%LLJtyy{{11&99::		<  H H H ah// 	H""7>>6L>#M#MNNTUU""7>>ah>#?#?@@aG> K K K w~~2H~IIJJJ	K  	--	2..==4((D00""#DEE   1  Jw~~2G~HHIIINs   A)A2 2DA$C**2Dc                   $    e Zd ZdZdZd ZddZdS )EarthLocationInfoz
    Container for meta information like name, description, format.  This is
    required when the object is used as a mixin column within a table, but can
    be used as a general way to store meta information.
    )xyzr"   c                 X    |                     d          } | j        di |}||_        |S )Nr"    )pop_parent_clsr"   )selfmapr"   outs       r$   _construct_from_dictz&EarthLocationInfo._construct_from_dictt   s9     GGK((	d%%%%!
r&   r   Nc                    |                      ||d          }|                    d           |f|                    d          z   }t          j        t	          j        |d         j                  d         j        d          fd| j        D             }| 	                    |          }|
                                D ]\  }	}
t          |j        |	|
           |S )	a  
        Return a new EarthLocation instance which is consistent with the
        input ``cols`` and has ``length`` rows.

        This is intended for creating an empty column object whose elements can
        be set in-place for table operations like join or vstack.

        Parameters
        ----------
        cols : list
            List of input columns
        length : int
            Length of the output column object
        metadata_conflicts : str ('warn'|'error'|'silent')
            How to handle metadata conflicts
        name : str
            Output column name

        Returns
        -------
        col : EarthLocation (or subclass)
            Empty instance of this class consistent with ``cols``
        )metar>   descriptiondtypeshaper   )rX   rW   F)unitcopyc                 V    i | ]%}||d v r|         nt          d         |          &S )xyz)getattr).0keycolsr   s     r$   
<dictcomp>z.EarthLocationInfo.new_like.<locals>.<dictcomp>   sI     
 
 
 se||$s))b31G1G
 
 
r&   )merge_cols_attributesrN   uQuantitynpzerosrW   rY   _represent_as_dict_attrsrS   itemssetattrinfo)rP   ra   lengthmetadata_conflictsnameattrsrX   rQ   rR   attrvaluer   s    `         @r$   new_likezEarthLocationInfo.new_like|   s	   6 **$d,M
 

 			' 	EIIg...zH5Q666T!W\PU
 
 

 
 
 
 
4
 
 
 '',, ;;== 	+ 	+KD%CHdE****
r&   )r   N)__name__
__module____qualname____doc__rh   rS   rr   rM   r&   r$   rH   rH   k   sI           <  2 2 2 2 2 2r&   rH   c                       e Zd ZdZdZ ej        g dej        gdz  d          Z ej        ej        df          Z	dZ
 e            Zd Zed* fd		            Zed+d            Zeddd            Zed,d            Zeddd            Zed-d            Zed             Zej        d             Zed             Zd*dZed             Zed             Zed             Zed             Zd Zd.dZ eed          Z d Z!d Z"d  Z#g d!i fd"Z$ed#             Z%ed$             Z&ed%             Z' fd&Z( fd'Z) fd(Z*g fd)Z+ xZ,S )/r   a  
    Location on the Earth.

    Initialization is first attempted assuming geocentric (x, y, z) coordinates
    are given; if that fails, another attempt is made assuming geodetic
    coordinates (longitude, latitude, height above a reference ellipsoid).
    When using the geodetic forms, Longitudes are measured increasing to the
    east, so west longitudes are negative. Internally, the coordinates are
    stored as geocentric.

    To ensure a specific type of coordinates is used, use the corresponding
    class methods (`from_geocentric` and `from_geodetic`) or initialize the
    arguments with names (``x``, ``y``, ``z`` for geocentric; ``lon``, ``lat``,
    ``height`` for geodetic).  See the class methods for details.


    Notes
    -----
    This class fits into the coordinates transformation framework in that it
    encodes a position on the `~astropy.coordinates.ITRS` frame.  To get a
    proper `~astropy.coordinates.ITRS` object from this object, use the ``itrs``
    property.
    r   rI   rJ   rK      )namesformats)ry   Nc           	         t          |          dk    rHt          |          dk    r5t          |d         t                    r|d                                         S 	  | j        |i |}nZ# t
          j        t          f$ rA}	  | j        |i |}n(# t          $ r}t          d| d| d          d }~ww xY wY d }~nd }~ww xY w|S )Nr
   r   z^Coordinates could not be parsed as either geocentric or geodetic, with respective exceptions "z" and "")
lenr;   r   rZ   from_geocentricrd   
UnitsError	TypeErrorfrom_geodetic	Exception)clsargskwargsrP   exc_geocentricexc_geodetics         r$   __new__zEarthLocation.__new__   s   t99>>c&kkQ..:d1g}3U3U.7<<>>!
	&3&777DDi( 	 	 	(s($9&99   J#1J J:FJ J J   	 s6   A+ +CBB=
B5B00B55B==Cc                 t   |'	 |j         }n2# t          $ r t          d          dw xY wt          j        |          }|j        dk    rt          j        d          	 t          j        ||d          }t          j        ||d          }t          j        ||d          }n'# t          j        $ r t          j        d          w xY wt          j	        |||          \  }}}t          j
        |j        | j                  }|||c|d<   |d	<   |d
<   t                                          | ||d          S )a  
        Location on Earth, initialized from geocentric coordinates.

        Parameters
        ----------
        x, y, z : `~astropy.units.Quantity` or array-like
            Cartesian coordinates.  If not quantities, ``unit`` should be given.
        unit : unit-like or None
            Physical unit of the coordinate values.  If ``x``, ``y``, and/or
            ``z`` are quantities, they will be converted to this unit.

        Raises
        ------
        astropy.units.UnitsError
            If the units on ``x``, ``y``, and ``z`` do not match or an invalid
            unit is given.
        ValueError
            If the shapes of ``x``, ``y``, and ``z`` do not match.
        TypeError
            If ``x`` is not a `~astropy.units.Quantity` and no unit is given.
        NzMGeocentric coordinates should be Quantities unless an explicit unit is given.rl   z4Geocentric coordinates should be in units of length.FrZ   z5Geocentric coordinate units should all be consistent.rI   rJ   rK   )rY   AttributeErrorr   rd   Unitphysical_typer   re   rf   broadcast_arraysemptyrX   _location_dtypesuperr   )r   rI   rJ   rK   rY   struc	__class__s         r$   r   zEarthLocation.from_geocentric   se   . <v!   8   6$<<D)),UVVV	X
1d///A
1d///A
1d///AA| 	X 	X 	X,VWWW	X %aA..1a#"566-.1*c
E#Jc
wwsE4e<<<s    (AB% %$C	        c                 ^   t          || j                  }t          |t          j        d                              dt          j        z            }t          |t          j        d          }t          |t          j                  s!t          j        |t          j	        d          }t          |         |||d          }|                                                    d          |j        z  }|                    | j        |                               |j                  }||_        |S )aY  
        Location on Earth, initialized from geodetic coordinates.

        Parameters
        ----------
        lon : `~astropy.coordinates.Longitude` or float
            Earth East longitude.  Can be anything that initialises an
            `~astropy.coordinates.Angle` object (if float, in degrees).
        lat : `~astropy.coordinates.Latitude` or float
            Earth latitude.  Can be anything that initialises an
            `~astropy.coordinates.Latitude` object (if float, in degrees).
        height : `~astropy.units.Quantity` ['length'] or float, optional
            Height above reference ellipsoid (if float, in meters; default: 0).
        ellipsoid : str, optional
            Name of the reference ellipsoid to use (default: 'WGS84').
            Available ellipsoids are:  'WGS84', 'GRS80', 'WGS72'.

        Raises
        ------
        astropy.units.UnitsError
            If the units on ``lon`` and ``lat`` are inconsistent with angular
            ones, or that on ``height`` with a length.
        ValueError
            If ``lon``, ``lat``, and ``height`` do not have the same shape, or
            if ``ellipsoid`` is not recognized as among the ones implemented.

        Notes
        -----
        For the conversion to geocentric coordinates, the ERFA routine
        ``gd2gc`` is used.  See https://github.com/liberfa/erfa
        r#   Fr      r]   xyz_axis)r%   
_ellipsoidr   rd   degreewrap_atr   r;   re   mr    to_cartesianget_xyzrY   viewr   reshaperX   )r   r   r   r   r"   geodeticr\   rP   s           r$   r   zEarthLocation.from_geodetic  s    B %YGGG	C...66sQX~FFsAH5111&!*-- 	9Z%888Fi(c6FFF##%%--r-::fkIxx+S1199(.II#r&   F)refresh_cachec                   |                      |          }	 ||         }n/# t          $ r"}t          |j        d|j                  |d}~ww xY w| |j        u r|S  | j        |                                 }|j        j        |j        _        |S )a	  
        Return an object of this class for a known observatory/site by name.

        This is intended as a quick convenience function to get basic site
        information, not a fully-featured exhaustive registry of observatories
        and all their properties.

        Additional information about the site is stored in the ``.info.meta``
        dictionary of sites obtained using this method (see the examples below).

        .. note::
            This function is meant to access the site registry from the astropy
            data server, which is saved in the user's local cache.  If you would
            like a site to be added there, issue a pull request to the
            `astropy-data repository <https://github.com/astropy/astropy-data>`_ .
            If the cache already exists the function will use it even if the
            version in the astropy-data repository has been updated unless the
            ``refresh_cache=True`` option is used.  If there is no cache and the
            online version cannot be reached, this function falls back on a
            built-in list, which currently only contains the Greenwich Royal
            Observatory as an example case.

        Parameters
        ----------
        site_name : str
            Name of the observatory (case-insensitive).
        refresh_cache : bool, optional
            If `True`, force replacement of the cached registry with a
            newly downloaded version.  (Default: `False`)

            .. versionadded:: 5.3

        Returns
        -------
        site : `~astropy.coordinates.EarthLocation` (or subclass) instance
            The location of the observatory. The returned class will be the same
            as this class.

        Examples
        --------
        >>> from astropy.coordinates import EarthLocation
        >>> keck = EarthLocation.of_site('Keck Observatory')  # doctest: +REMOTE_DATA
        >>> keck.geodetic  # doctest: +REMOTE_DATA +FLOAT_CMP
        GeodeticLocation(lon=<Longitude -155.47833333 deg>, lat=<Latitude 19.82833333 deg>, height=<Quantity 4160. m>)
        >>> keck.info  # doctest: +REMOTE_DATA
        name = W. M. Keck Observatory
        dtype = (float64, float64, float64)
        unit = m
        class = EarthLocation
        n_bad = 0
        >>> keck.info.meta  # doctest: +REMOTE_DATA
        {'source': 'IRAF Observatory Database', 'timezone': 'US/Hawaii'}

        See Also
        --------
        get_site_names : the list of sites that this function can access
        force_downloadzEarthLocation.get_site_names)close_namesN)	_get_site_registryr   siter   r   r   to_geodeticrk   rn   )r   	site_namer   registryelrE   newels          r$   of_sitezEarthLocation.of_siteB  s    v )))GG	)$BB# 	 	 	&6AM  	
 ",I%C%r~~'7'78E glEJOLs   ! 
AAAc                    |du}|s|rt          d          |r(t          j                            ||d          }d| }n't          j                            |dd          }d| }d| d	}t	          |||
          }|r%|d         d         d         }	|	d         }
|	d         }n2|d         }	t          |	d                   }
t          |	d                   }|rd|
dd|d|d}t          j                            |          }d| }d| d	}t	          |||
          }|d         d         t          j        z  }nd}|                     |t          j	        z  |
t          j	        z  |          S )a  
        Return an object of this class for a given address by querying either
        the OpenStreetMap Nominatim tool [1]_ (default) or the Google geocoding
        API [2]_, which requires a specified API key.

        This is intended as a quick convenience function to get easy access to
        locations. If you need to specify a precise location, you should use the
        initializer directly and pass in a longitude, latitude, and elevation.

        In the background, this just issues a web query to either of
        the APIs noted above. This is not meant to be abused! Both
        OpenStreetMap and Google use IP-based query limiting and will ban your
        IP if you send more than a few thousand queries per hour [2]_.

        .. warning::
            If the query returns more than one location (e.g., searching on
            ``address='springfield'``), this function will use the **first**
            returned location.

        Parameters
        ----------
        address : str
            The address to get the location for. As per the Google maps API,
            this can be a fully specified street address (e.g., 123 Main St.,
            New York, NY) or a city name (e.g., Danbury, CT), or etc.
        get_height : bool, optional
            This only works when using the Google API! See the ``google_api_key``
            block below. Use the retrieved location to perform a second query to
            the Google maps elevation API to retrieve the height of the input
            address [3]_.
        google_api_key : str, optional
            A Google API key with the Geocoding API and (optionally) the
            elevation API enabled. See [4]_ for more information.

        Returns
        -------
        location : `~astropy.coordinates.EarthLocation` (or subclass) instance
            The location of the input address.
            Will be type(this class)

        References
        ----------
        .. [1] https://nominatim.openstreetmap.org/
        .. [2] https://developers.google.com/maps/documentation/geocoding/start
        .. [3] https://developers.google.com/maps/documentation/elevation/start
        .. [4] https://developers.google.com/maps/documentation/geocoding/get-api-key

        NzCurrently, `get_height` only works when using the Google geocoding API, which requires passing a Google API key with `google_api_key`. See: https://developers.google.com/maps/documentation/geocoding/get-api-key for information on obtaining an API key.)addressr`   z2https://maps.googleapis.com/maps/api/geocode/json?r5   )qr>   z+https://nominatim.openstreetmap.org/search?z,Unable to retrieve coordinates for address 'z'; {msg})rA   rB   r   geometrylocationr   lngr   z.8f,)	locationsr`   z4https://maps.googleapis.com/maps/api/elevation/json?z*Unable to retrieve elevation for address '	elevationr   r   )
r!   r0   parse	urlencoderF   floatrd   meterr   deg)r   r   
get_heightgoogle_api_keyrB   parsgeo_urlrA   
geo_resultlocr   r   ele_url
ele_resultr   s                  r$   
of_addresszEarthLocation.of_address  s   d $4/
  	j 	<    	K<))gn*U*UVVDQ4QQGG <))6*J*JKKDJDJJG UTTT%gw:VVV
 	$Q-
+J7Ce*Ce*CC Q-CE
##CE
##C 	$'!7!7!7c!7!7!7OOD<))$//DSTSSGV7VVVG)Z  J  ];/!'9FF F  S15[cAEk& QQQr&   c                8    |                      |          j        S )a\  
        Get list of names of observatories for use with
        `~astropy.coordinates.EarthLocation.of_site`.

        .. note::
            This function is meant to access the site registry from the astropy
            data server, which is saved in the user's local cache.  If you would
            like a site to be added there, issue a pull request to the
            `astropy-data repository <https://github.com/astropy/astropy-data>`_ .
            If the cache already exists the function will use it even if the
            version in the astropy-data repository has been updated unless the
            ``refresh_cache=True`` option is used.  If there is no cache and the
            online version cannot be reached, this function falls back on a
            built-in list, which currently only contains the Greenwich Royal
            Observatory as an example case.

        Parameters
        ----------
        refresh_cache : bool, optional
            If `True`, force replacement of the cached registry with a
            newly downloaded version.  (Default: `False`)

            .. versionadded:: 5.3

        Returns
        -------
        names : list of str
            List of valid observatory names

        See Also
        --------
        of_site : Gets the actual location object for one of the sites names
            this returns.
        r   )r   rz   )r   r   s     r$   get_site_nameszEarthLocation.get_site_names  s    H %%]%CCIIr&   c                 \   ddl m}m} |r|rt          d          |r |            | _        ny|s| j        sp	 t          |t                    r ||          | _        n |            | _        n9# t          $ r, |r d}t          |t                      |            | _        Y nw xY w| j        S )a  
        Gets the site registry.  The first time this either downloads or loads
        from the data file packaged with astropy.  Subsequent calls will use the
        cached version unless explicitly overridden.

        Parameters
        ----------
        force_download : bool or str
            If not False, force replacement of the cached registry with a
            downloaded version. If a str, that will be used as the URL to
            download from (if just True, the default URL will be used).
        force_builtin : bool
            If True, load from the data file bundled with astropy and set the
            cache to that.

        Returns
        -------
        reg : astropy.coordinates.sites.SiteRegistry
        r
   )get_builtin_sitesget_downloaded_sitesz6Cannot have both force_builtin and force_download TruezCould not access the main site list. Falling back on the built-in version, which is rather limited. If you want to retry the download, use the option 'refresh_cache=True'.)
sitesr   r   r!   _site_registryr;   strOSErrorr   r	   )r   r   force_builtinr   r   r+   s         r$   r   z EarthLocation._get_site_registry  s   , 	CBBBBBBB 	W^ 	WUVVV 	=!2!2!4!4C =S%7 ==!.#66 D-A-A.-Q-Q**-A-A-C-C* 	= 	= 	=% S 
 0111):):)<)<C&&&	= !!s   5A. .3B$#B$c                     | j         S )z>The default ellipsoid used to convert to geodetic coordinates.)r   rP   s    r$   r"   zEarthLocation.ellipsoidF  s     r&   c                 .    t          |          | _        d S N)r%   r   )rP   r"   s     r$   r"   zEarthLocation.ellipsoidK  s    *955r&   c                 *    |                                  S )z:Convert to geodetic coordinates for the default ellipsoid.)r   r   s    r$   r   zEarthLocation.geodeticO  s     !!!r&   c                    t          || j                  }|                     | j        t          j                  }t          |dd                              t          |                   }t          t          |j        t          j        dt          j        z  d          |j        t          j        z  |j        | j        z            S )aY  Convert to geodetic coordinates.

        Parameters
        ----------
        ellipsoid : str, optional
            Reference ellipsoid to use.  Default is the one the coordinates
            were initialized with.  Available are: 'WGS84', 'GRS80', 'WGS72'

        Returns
        -------
        lon, lat, height : `~astropy.units.Quantity`
            The tuple is a ``GeodeticLocation`` namedtuple and is comprised of
            instances of `~astropy.coordinates.Longitude`,
            `~astropy.coordinates.Latitude`, and `~astropy.units.Quantity`.

        Raises
        ------
        ValueError
            if ``ellipsoid`` is not recognized as among the ones implemented.

        Notes
        -----
        For the conversion to geodetic coordinates, the ERFA routine
        ``gc2gd`` is used.  See https://github.com/liberfa/erfa
        r   r]   Fr   rZ   r   )
wrap_anglerZ   )r%   r"   r   _array_dtyperd   re   r   represent_asr    r   r   r   r   r   r   rY   )rP   r"   r\   llhs       r$   r   zEarthLocation.to_geodeticT  s    4 %YGGG	ii)1:66%cBUCCCPPy!
 
  cgququ5IIIGquJ$)#
 
 	
r&   c                     | j         d         S )z5Longitude of the location, for the default ellipsoid.r   r   r   s    r$   r   zEarthLocation.lony       }Qr&   c                     | j         d         S )z4Latitude of the location, for the default ellipsoid.r
   r   r   s    r$   r   zEarthLocation.lat~  r   r&   c                     | j         d         S )z2Height of the location, for the default ellipsoid.   r   r   s    r$   r   zEarthLocation.height  r   r&   c                 *    |                                  S z2Convert to a tuple with X, Y, and Z as quantities.)to_geocentricr   s    r$   
geocentriczEarthLocation.geocentric  s     !!###r&   c                 *    | j         | j        | j        fS r   rx   r   s    r$   r   zEarthLocation.to_geocentric  s    ''r&   c                    |r.| j         dk    r#|j        rt          j        | |j        d          } ddlm} | || j        | j        | j        |          S  || j        |j        z
  | j        |j        z
  | j        |j        z
  d||          S )	a[  
        Generates an `~astropy.coordinates.ITRS` object with the location of
        this object at the requested ``obstime``, either geocentric, or
        topocentric relative to a given ``location``.

        Parameters
        ----------
        obstime : `~astropy.time.Time` or None
            The ``obstime`` to apply to the new `~astropy.coordinates.ITRS`, or
            if None, the default ``obstime`` will be used.
        location : `~astropy.coordinates.EarthLocation` or None
            A possible observer's location, for a topocentric ITRS position.
            If not given (default), a geocentric ITRS object will be created.

        Returns
        -------
        itrs : `~astropy.coordinates.ITRS`
            The new object in the ITRS frame, either geocentric or topocentric
            relative to the given ``location``.
        r
   T)subok)ITRSN)rI   rJ   rK   obstimeF)rZ   r   r   )	sizerX   rf   broadcast_tobuiltin_framesr   rI   rJ   rK   )rP   r   r   r   s       r$   get_itrszEarthLocation.get_itrs  s    .  	DtyA~~'-~?4dCCCD 	)(((((4$&DFdfgFFFF4###!   r&   zAn `~astropy.coordinates.ITRS` object
               for the location of this object at the
               default ``obstime``.)docc                     ddl m} |                     |          \  }}t          j        |          |j        d<    |||          S )aX  GCRS position with velocity at ``obstime`` as a GCRS coordinate.

        Parameters
        ----------
        obstime : `~astropy.time.Time`
            The ``obstime`` to calculate the GCRS position/velocity at.

        Returns
        -------
        gcrs : `~astropy.coordinates.GCRS` instance
            With velocity included.
        r
   )GCRSs)r   )r   r   get_gcrs_posvelr   from_cartesiandifferentials)rP   r   r   r   vels        r$   get_gcrszEarthLocation.get_gcrs  sZ     	)(((((''00S!6!Ec!J!J#tC))))r&   c                 $   t          |          }|t          |          z  }t          |d         t          z  dd          }t          | j        | j        | j        d          }|                    |          }|                    |          }	||	fS )a  Calculate GCRS position and velocity given transformation matrices.

        The reference frame z axis must point to the Celestial Intermediate Pole
        (as is the case for CIRS and TETE).

        This private method is used in intermediate_rotation_transforms,
        where some of the matrices are already available for the coordinate
        transformation.

        The method is faster by an order of magnitude than just adding a zero
        velocity to ITRS and transforming to GCRS, because it avoids calculating
        the velocity via finite differencing of the results of the transformation
        at three separate times.
        ).r   r]   Fr   r   )r   r   OMEGA_EARTHrI   rJ   rK   	transformcross)
rP   r   ref_to_itrsgcrs_to_refref_to_gcrsitrs_to_gcrsrot_vec_gcrs	itrs_cartposr   s
             r$   _get_gcrs_posvelzEarthLocation._get_gcrs_posvel  s    * '{33"%5k%B%BB /+-
 
 

 ,DFDFDFOOO	!!,//  %%Cxr&   c                 d    ddl m}m} |                     | ||           ||                    S )a  
        Calculate the GCRS position and velocity of this object at the
        requested ``obstime``.

        Parameters
        ----------
        obstime : `~astropy.time.Time`
            The ``obstime`` to calculate the GCRS position/velocity at.

        Returns
        -------
        obsgeoloc : `~astropy.coordinates.CartesianRepresentation`
            The GCRS position of the object
        obsgeovel : `~astropy.coordinates.CartesianRepresentation`
            The GCRS velocity of the object
        r
   )cirs_to_itrs_matgcrs_to_cirs_mat)/builtin_frames.intermediate_rotation_transformsr  r  r  )rP   r   r  r  s       r$   r   zEarthLocation.get_gcrs_posvel  sc    $	
 	
 	
 	
 	
 	
 	
 	
 $$%%g..0@0@0I0I
 
 	
r&   )sunjupitermoonc                     ddl m t          |          }d|v r|                    d           |                    d           t
          j        t
          j        t
          j        dz  t          j
        z  t
          j        d}|                    |           g }t          j
        t          j        t
          j        t          j
        z            f}|D ]}	 |                    ||                             t          j        dz  t          j        dz  z  |g                     Q# t"          $ r}t#          d| d	          |d
}~wt          j        $ r}	|	xj        dz  c_         d
}	~	ww xY wfd|D             fdd
d         D             }
|
                    t)          | j                                                             d t/          ||
          D             }t1          |d
d
d                   S )a  Return the gravitational redshift at this EarthLocation.

        Calculates the gravitational redshift, of order 3 m/s, due to the
        requested solar system bodies.

        Parameters
        ----------
        obstime : `~astropy.time.Time`
            The ``obstime`` to calculate the redshift at.

        bodies : iterable, optional
            The bodies (other than the Earth) to include in the redshift
            calculation.  List elements should be any body name
            `get_body_barycentric` accepts.  Defaults to Jupiter, the Sun, and
            the Moon.  Earth is always included (because the class represents
            an *Earth* location).

        masses : dict[str, `~astropy.units.Quantity`], optional
            The mass or gravitational parameters (G * mass) to assume for the
            bodies requested in ``bodies``. Can be used to override the
            defaults for the Sun, Jupiter, the Moon, and the Earth, or to
            pass in masses for other bodies.

        Returns
        -------
        redshift : `~astropy.units.Quantity`
            Gravitational redshift in velocity units at given obstime.
        r
   )get_body_barycentricearthgXJ\D)r	  r
  r  r  ry   r   zbody "z" does not have a mass.N)zD"masses" argument values must be masses or gravitational parameters.c                 (    g | ]} |          S rM   rM   )r_   rn   r  r   s     r$   
<listcomp>z8EarthLocation.gravitational_redshift.<locals>.<listcomp>T  s'    LLLT))$88LLLr&   c                 J    g | ]}|d          z
                                    S )r]   )norm)r_   r  	positionss     r$   r  z8EarthLocation.gravitational_redshift.<locals>.<listcomp>V  s.    LLLccIbM)//11LLLr&   r]   c                 :    g | ]\  }}| t           j        z  |z  S rM   )constsc)r_   GMdistances      r$   r  z8EarthLocation.gravitational_redshift.<locals>.<listcomp>Z  s6     
 
 
*82xRC&(NX%
 
 
r&   )solar_systemr  listremoveappendr  GM_sunGM_jupGrd   kgGM_earthupdater   tor   r   KeyErrorr   r   r   r   r  zipsum)rP   r   bodiesmasses_massesGMsM_GM_equivalencybodyerrexc	distances	redshiftsr  r  s    `          @@r$   gravitational_redshiftz$EarthLocation.gravitational_redshift  s&   @ 	766666ffMM'"""g=}H},qt3_	
 
 	vD!&AD"9"9: 	 	D

74=++ACFQS!VO>N=OPPQQQQ P P PEEEEFFCO<       MLLLLVLLL	LLLLYss^LLL	0AAFFHHIII
 
<?Y<O<O
 
 
	
 9TTrT?###s%   AD''
E-1EE-E((E-c                     | d         S )z.The X component of the geocentric coordinates.rI   rM   r   s    r$   rI   zEarthLocation.xa       Cyr&   c                     | d         S )z.The Y component of the geocentric coordinates.rJ   rM   r   s    r$   rJ   zEarthLocation.yf  r3  r&   c                     | d         S )z.The Z component of the geocentric coordinates.rK   rM   r   s    r$   rK   zEarthLocation.zk  r3  r&   c                     t                                          |          }|j        | j        u r|                    | j                  S |                    t
          j                  S r   )r   __getitem__rW   r   r   rd   re   )rP   itemresultr   s      r$   r7  zEarthLocation.__getitem__p  sQ    $$T**<4:%%;;t~...;;qz***r&   c                     t                                          |           t          |d          r|j        | _        d S d S )Nr   )r   __array_finalize__hasattrr   )rP   objr   s     r$   r;  z EarthLocation.__array_finalize__w  sD    ""3'''3%% 	-!nDOOO	- 	-r&   c                 x    | j         dk    rt          d          t                                                      S )NrM   z*0-d EarthLocation arrays cannot be indexed)rX   
IndexErrorr   __len__)rP   r   s    r$   r@  zEarthLocation.__len__|  s3    :IJJJ77??$$$r&   c                    |                      | j        t          j                  }|g k    r| j        }| j                            |||          }|                     | j                                      | j	                  S )z"Helper method for to and to_value.)equivalencies)
r   r   rf   ndarray_equivalenciesrY   r#  rW   r   rX   )rP   rY   rB  
array_view	new_arrays        r$   	_to_valuezEarthLocation._to_value  sl    
 YYt0"*==
B /MILLzLOO	~~dj))11$*===r&   r   )r   N)FN)FF)NN)-rs   rt   ru   rv   r   rf   rW   float64r   r   r   rH   rk   r   classmethodr   r   r   r   r   r   propertyr"   setterr   r   r   r   r   r   r   r   itrsr   r  r   r1  rI   rJ   rK   r7  r;  r@  rG  __classcell__r   s   @r$   r   r      s        0 Jbhbj\TUEUVVWWO28RZ.//LND  " .= .= .= .= .= [.=` , , , [,\ 16 G G G G [GR aR aR aR [aRF -2 #J #J #J #J [#JJ -" -" -" [-"^   X 6 6 6 " " X"#
 #
 #
 #
J     X      X      X 
 $ $ X$( ( (( ( ( (T 8'  D* * *(! ! !F
 
 
: 988I$ I$ I$ I$V   X   X   X+ + + + +- - - - -
% % % % % -/ 	> 	> 	> 	> 	> 	> 	> 	>r&   r   a  {__doc__}

    Parameters
    ----------
    lon, lat : angle-like
        The longitude and latitude of the point(s), in angular units. The
        latitude should be between -90 and 90 degrees, and the longitude will
        be wrapped to an angle between 0 and 360 degrees. These can also be
        instances of `~astropy.coordinates.Angle` and either
        `~astropy.coordinates.Longitude` not `~astropy.coordinates.Latitude`,
        depending on the parameter.
    height : `~astropy.units.Quantity` ['length']
        The height to the point(s).
    copy : bool, optional
        If `True` (default), arrays will be copied. If `False`, arrays will
        be references, though possibly broadcast to ensure matching shapes.

c                   `     e Zd ZdZeeej        dZ fdZ	d	 fd	Z
d Zed             Z xZS )
r   zBase geodetic representation.r   c                 n     t                      j        di | d| j        v r| t          | j        <   d S d S )Nr   rM   )r   __init_subclass____dict__r    r   )r   r   r   s     r$   rQ  z,BaseGeodeticRepresentation.__init_subclass__  sG    !!++F+++3<''),Js~&&& ('r&   NTc                 2   |$t          || j                  sdt          j        z  }t	                                          ||||           | j        j                            t          j                  s!t          j	        | j        j
         d          d S )Nr   r   z& requires height with units of length.)r;   r   rd   r   r   __init__r   rY   is_equivalentUnitTypeErrorrs   )rP   r   r   r   rZ   r   s        r$   rT  z#BaseGeodeticRepresentation.__init__  s    >*S$."A"A>!#XFc6555{--ac22 	/>*RRR  	 	r&   c                     t          j        t          t           | j                  | j        | j        | j                  }t          |dd          S )zs
        Converts WGS84 geodetic coordinates to 3D rectangular (geocentric)
        cartesian coordinates.
        r]   Fr   )erfagd2gcr^   r   r   r   r   r   )rP   r\   s     r$   r   z'BaseGeodeticRepresentation.to_cartesian  sG    
 jD$/**DHdh
 
 'sReDDDDr&   c                     t          j        t          t           | j                  |                    d                    \  }}} | |||d          S )z{
        Converts 3D rectangular cartesian coordinates (assumed geocentric) to
        WGS84 geodetic coordinates.
        r]   r   Fr   )rX  gc2gdr^   r   r   )r   cartr   r   r   s        r$   r   z)BaseGeodeticRepresentation.from_cartesian  sV      :D#.))4<<<+D+D
 
S& s3V%0000r&   )NNT)rs   rt   ru   rv   r   r   rd   re   attr_classesrQ  rT  r   rI  r   rM  rN  s   @r$   r   r     s        ''$XLLL- - - - -
     E E E 1 1 [1 1 1 1 1r&   r   c                       e Zd ZdZdZdS )r   z:Representation of points in WGS84 3D geodetic coordinates.r   Nrs   rt   ru   rv   r   rM   r&   r$   r   r             DDJJJr&   r   c                       e Zd ZdZdZdS )r   z:Representation of points in WGS72 3D geodetic coordinates.WGS72Nr_  rM   r&   r$   r   r     r`  r&   r   c                       e Zd ZdZdZdS )r   z:Representation of points in GRS80 3D geodetic coordinates.GRS80Nr_  rM   r&   r$   r   r     r`  r&   r   )Nr   )9collectionsr5   r=   urllib.errorr0   urllib.parseurllib.requestwarningsr   rX  numpyrf   astropyr   r  r   rd   astropy.units.quantityr   astropy.utilsr   astropy.utils.decoratorsr   astropy.utils.exceptionsr	   anglesr   r   r   errorsr   matrix_utilitiesr   representationr   r   r   __all__
namedtupler   r    cycledayr#  r   dimensionless_anglesr   r%   rF   rH   re   r   geodetic_base_docr   r   r   r   rM   r&   r$   <module>rz     su                                ' ' ' ' ' '       3 3 3 3 3 3       / / / / / / 7 7 7 7 7 7 . . . . . . . . . . ( ( ( ( ( ( . . . . . .            *;)*<>V>V>VWW 
 N (!'1AE9==G#Q#%% 	   % % %PC C C C C( C C CLZ> Z> Z> Z> Z>AJ Z> Z> Z>z ( '1 '1 '1 '1 '1!3 '1 '1 '1T     "<        "<        "<     r&   