a
    ߙfb                     @   s  d dl mZ 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	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mZm Z  d	dl!m"Z" d	dl#m$Z$ g dZ%e&dg dZ'i Z(dej) ej* +d	ej, e- Z.d$ddZ/dd Z0G dd deZ1G dd dej2Z3dZ4ee4G dd deZ5ee4G dd de5Z6ee4G d d! d!e5Z7ee4G d"d# d#e5Z8dS )%    )warnN)units)	constants)QuantityInfoBase)data)
format_doc)AstropyUserWarning   )Angle	LongitudeLatitude)BaseRepresentationCartesianRepresentationCartesianDifferential)matrix_transpose)UnknownSiteException)EarthLocationBaseGeodeticRepresentationWGS84GeodeticRepresentationWGS72GeodeticRepresentationGRS80GeodeticRepresentationGeodeticLocationlonlatheightg+6?WGS84c                 C   s.   | d u r|} | t vr*td|  dt  d| S )Nz
Ellipsoid z not among known ones ())
ELLIPSOIDS
ValueError)	ellipsoiddefault r"   8lib/python3.9/site-packages/astropy/coordinates/earth.py_check_ellipsoid4   s
    r$   c              
   C   s
  ddl m} z,tjj| tjjd}t	|
 d}W n tjjy } zBt|jtjrn||jdd|n||j|jd|W Y d }~n,d }~0  tjy   ||jddY n0 |r|dg }|dd d	kr||jd
dn|}|s||jdd|S )Nr	   )NameResolveError)timeoututf8zconnection timed out)msgresultsZstatusZOKzunknown failure with Google APIzno results returned)Zname_resolver%   urllibZrequestZurlopenr   ZconfZremote_timeoutjsonloadsreaddecodeerrorZURLError
isinstancereasonsocketr&   formatget)Zurlerr_str
use_googler%   ZrespZ	resp_dataer)   r"   r"   r#   _get_json_result<   s$    (r8   c                   @   s&   e Zd ZdZdZdd Zd	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                 C   s$   | d}| jf i |}||_|S )Nr    )popZ_parent_clsr    )selfmapr    outr"   r"   r#   _construct_from_dictk   s    
z&EarthLocationInfo._construct_from_dictr   Nc                    s   |   ||d}|d |f|d }tjtj| d jd d jdd fdd	| jD }| 	|}|
 D ]\}	}
t|j|	|
 qx|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``
        )metar3   Zdescriptiondtypeshaper   )rD   rC   F)unitcopyc                    s,   i | ]$}||d v r| nt  d |qS )xyz)getattr).0keycolsr   r"   r#   
<dictcomp>   s   z.EarthLocationInfo.new_like.<locals>.<dictcomp>)Zmerge_cols_attributesr=   uQuantitynpZzerosrC   rE   _represent_as_dict_attrsrA   itemssetattrinfo)r>   rM   lengthZmetadata_conflictsnameattrsrD   r?   r@   attrvaluer"   rL   r#   new_likes   s    



zEarthLocationInfo.new_like)r   N)__name__
__module____qualname____doc__rR   rA   r[   r"   r"   r"   r#   r9   c   s   r9   c                       s  e Zd ZdZdZeg dejgd dZeejdfZ	e
 Zdd ZedD fd
d	ZedEddZedd ZedFddZedd ZedGddZedd Zejdd Zedd ZdHddZedd  Zed!d" Zed#d$ Zed%d& Zd'd( ZdId)d*Zeed+d,Zd-d. Z d/d0 Z!d1d2 Z"g d3i fd4d5Z#ed6d7 Z$ed8d9 Z%ed:d; Z& fd<d=Z' fd>d?Z( fd@dAZ)g fdBdCZ*  Z+S )Jr   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   r:   r;   r<      )namesZformats)ra   c                 O   s   t |dkr2t |dkr2t|d tr2|d  S z| j|i |}W nt tjtfy } zVz| j|i |}W n4 t	y } ztd
||W Y d }~n
d }~0 0 W Y d }~n
d }~0 0 |S )Nr	   r   zjCoordinates could not be parsed as either geocentric or geodetic, with respective exceptions "{}" and "{}")lenr0   r   rF   from_geocentricrO   
UnitsError	TypeErrorfrom_geodetic	Exceptionr3   )clsargskwargsr>   Zexc_geocentricZexc_geodeticr"   r"   r#   __new__   s    2zEarthLocation.__new__Nc                    s   |du r2z
|j }W q< ty.   tddY q<0 n
t|}|jdkrPtdz4tj||dd}tj||dd}tj||dd}W n tjy   tdY n0 t	|||\}}}t
|j| j}|||  |d< |d	< |d
< t j| ||d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.rV   z4Geocentric coordinates should be in units of length.FrF   z5Geocentric coordinate units should all be consistent.r:   r;   r<   )rE   AttributeErrorrf   rO   UnitZphysical_typere   rP   rQ   Zbroadcast_arraysemptyrD   _location_dtypesuperrl   )ri   r:   r;   r<   rE   Zstruc	__class__r"   r#   rd      s(    




zEarthLocation.from_geocentric        c                 C   s   t || jd}t|tjdddtj }t|tjdd}t|tjsXtj|tj	dd}t
| |||dd}| jdd|j> }|| 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!   Frm      rH   xyz_axis)r$   
_ellipsoidr
   rO   ZdegreeZwrap_atr   r0   rP   mr   to_cartesianget_xyzrE   viewrq   reshaperD   )ri   r   r   r   r    geodeticrG   r>   r"   r"   r#   rg     s    !zEarthLocation.from_geodeticc              
   C   s~   |   }z|| }W n8 tyL } z t|jd|jd|W Y d}~n
d}~0 0 | |ju r\|S | j|  }|jj|j_|S d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::
            When this function is called, it will attempt to download site
            information from the astropy data server. If you would like a site
            to be added, issue a pull request to the
            `astropy-data repository <https://github.com/astropy/astropy-data>`_ .
            If a site cannot be found in the registry (i.e., an internet
            connection is not available), it will fall back on a built-in list,
            In the future, this bundled list might include a version-controlled
            list of canonical observatories extracted from the online version,
            but it currently only contains the Greenwich Royal Observatory as an
            example case.

        Parameters
        ----------
        site_name : str
            Name of the observatory (case-insensitive).

        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 = void192
        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
        EarthLocation.get_site_names)close_namesN)	_get_site_registryr   Zsiter   rt   rg   to_geodeticrU   rW   )ri   Z	site_nameregistryZelr7   Znewelr"   r"   r#   of_site5  s    6
zEarthLocation.of_siteFc                 C   s8  |du}|s|rt d|r:tj||d}d| }ntj|dd}d| }d| d	}t|||d
}|r|d d d }	|	d }
|	d }n |d }	t|	d }
t|	d }|r|
dd|d|d}tj|}d| }d| d	}t|||d
}|d d tj }nd}| j|tj	 |
tj	 |d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.)addressrK   z2https://maps.googleapis.com/maps/api/geocode/json?r+   )qr3   z+https://nominatim.openstreetmap.org/search?z,Unable to retrieve coordinates for address 'z'; {msg})r5   r6   r   Zgeometrylocationr   Zlngr   z.8f,)Z	locationsrK   z4https://maps.googleapis.com/maps/api/elevation/json?z*Unable to retrieve elevation for address 'Z	elevationru   r   )
r   r*   parseZ	urlencoder8   floatrO   Zmeterrg   deg)ri   r   Z
get_heightZgoogle_api_keyr6   ZparsZgeo_urlr5   Z
geo_resultlocr   r   Zele_urlZ
ele_resultr   r"   r"   r#   
of_addressy  sL    3


zEarthLocation.of_addressc                 C   s
   |   jS )ai  
        Get list of names of observatories for use with
        `~astropy.coordinates.EarthLocation.of_site`.

        .. note::
            When this function is called, it will first attempt to
            download site information from the astropy data server.  If it
            cannot (i.e., an internet connection is not available), it will fall
            back on the list included with astropy (which is a limited and dated
            set of sites).  If you think a site should be added, issue a pull
            request to the
            `astropy-data repository <https://github.com/astropy/astropy-data>`_ .

        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   rb   )ri   r"   r"   r#   get_site_names  s    r   c                 C   s   ddl m}m} |r |r td|r2|  }| _npt| dd}|sF|szt|tr\||}n| }W n6 ty   |rx d}t	t
|| j | }Y n0 || _|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 True_site_registryNzCould not access the online site list. Falling back on the built-in version, which is rather limited. If you want to retry the download, do {0}._get_site_registry(force_download=True))Zsitesr   r   r   r   rI   r0   strOSErrorr   r   r3   r\   )ri   Zforce_downloadZforce_builtinr   r   Zregr(   r"   r"   r#   r     s&    


z EarthLocation._get_site_registryc                 C   s   | j S )z>The default ellipsoid used to convert to geodetic coordinates.)rz   r>   r"   r"   r#   r    -  s    zEarthLocation.ellipsoidc                 C   s   t || _d S N)r$   rz   )r>   r    r"   r"   r#   r    2  s    c                 C   s   |   S )z:Convert to geodetic coordinates for the default ellipsoid.)r   r   r"   r"   r#   r   6  s    zEarthLocation.geodeticc                 C   sh   t || jd}| | jtj}t|dddt| }t	t
|jtjdtj dd|jtj> |j| j> 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
        rv   rH   Fry   rF   rw   )Z
wrap_anglerF   )r$   r    r~   _array_dtyperO   rP   r   Zrepresent_asr   r   r   r   r   r   r   rE   )r>   r    rG   Zllhr"   r"   r#   r   ;  s    zEarthLocation.to_geodeticc                 C   s
   | j d S )z5Longitude of the location, for the default ellipsoid.r   r   r   r"   r"   r#   r   ]  s    zEarthLocation.lonc                 C   s
   | j d S )z4Latitude of the location, for the default ellipsoid.r	   r   r   r"   r"   r#   r   b  s    zEarthLocation.latc                 C   s
   | j d S )z2Height of the location, for the default ellipsoid.   r   r   r"   r"   r#   r   g  s    zEarthLocation.heightc                 C   s   |   S z1Convert to a tuple with X, Y, and Z as quantities)to_geocentricr   r"   r"   r#   
geocentricm  s    zEarthLocation.geocentricc                 C   s   | j | j| jfS r   r`   r   r"   r"   r#   r   r  s    zEarthLocation.to_geocentricc                 C   sH   |r&| j dkr&|jr&tj| |jdd} ddlm} || j| j| j|dS )a  
        Generates an `~astropy.coordinates.ITRS` object with the location of
        this object at the requested ``obstime``.

        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.

        Returns
        -------
        itrs : `~astropy.coordinates.ITRS`
            The new object in the ITRS frame
        r	   T)Zsubok)ITRS)r:   r;   r<   obstime)	sizerD   rQ   Zbroadcast_tobuiltin_framesr   r:   r;   r<   )r>   r   r   r"   r"   r#   get_itrsv  s    zEarthLocation.get_itrszAn `~astropy.coordinates.ITRS` object  with
                                     for the location of this object at the
                                     default ``obstime``.)docc                 C   s6   ddl m} | |\}}t||jd< |||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_cartesianZdifferentials)r>   r   r   r   velr"   r"   r#   get_gcrs  s    zEarthLocation.get_gcrsc           
      C   s\   t |}|t | }t|d t ddd}t| j| j| jd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   rH   Fr   rm   )r   r   OMEGA_EARTHr:   r;   r<   Z	transformZcross)
r>   r   Zref_to_itrsZgcrs_to_refZref_to_gcrsZitrs_to_gcrsZrot_vec_gcrsZ	itrs_cartposr   r"   r"   r#   _get_gcrs_posvel  s    

zEarthLocation._get_gcrs_posvelc                 C   s&   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)Z/builtin_frames.intermediate_rotation_transformsr   r   r   )r>   r   r   r   r"   r"   r#   r     s
    zEarthLocation.get_gcrs_posvel)sunjupitermoonc                    s  ddl m  t|}d|v r&|d |d tjtjtjd t	j
 tjd}|| g }t	j
t	tjt	j
 f}|D ]}z,||| t	jd t	jd  |g W qz ty } ztd| d	|W Y d
}~qzd
}~0  t	jy }	 z|	 jd7  _ W Y d
}	~	qzd
}	~	0 0 qz fdd|D fddd
d D }
|
t| j  dd t||
D }t|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   ra   r   zbody "z" does not have a mass.N)zD"masses" argument values must be masses or gravitational parameters.c                    s   g | ]} |qS r"   r"   )rJ   rW   )r   r   r"   r#   
<listcomp>      z8EarthLocation.gravitational_redshift.<locals>.<listcomp>c                    s   g | ]}| d     qS )rH   )norm)rJ   r   )	positionsr"   r#   r     r   rH   c                 S   s    g | ]\}}| t j | qS r"   )constsc)rJ   ZGMZdistancer"   r"   r#   r      r   )Zsolar_systemr   listremoveappendr   ZGM_sunZGM_jupGrO   ZkgZGM_earthupdatero   tor{   r   KeyErrorre   rj   r   r   r   zipsum)r>   r   ZbodiesZmassesZ_massesZGMsZM_GM_equivalencybodyerrexcZ	distancesZ	redshiftsr"   )r   r   r   r#   gravitational_redshift  s8     


,&z$EarthLocation.gravitational_redshiftc                 C   s   | d S )z.The X component of the geocentric coordinates.r:   r"   r   r"   r"   r#   r:   &  s    zEarthLocation.xc                 C   s   | d S )z.The Y component of the geocentric coordinates.r;   r"   r   r"   r"   r#   r;   +  s    zEarthLocation.yc                 C   s   | d S )z.The Z component of the geocentric coordinates.r<   r"   r   r"   r"   r#   r<   0  s    zEarthLocation.zc                    s4   t  |}|j| ju r$|| jS |tjS d S r   )rr   __getitem__rC   r~   rt   rO   rP   )r>   itemresultrs   r"   r#   r   5  s    zEarthLocation.__getitem__c                    s"   t  | t|dr|j| _d S Nrz   )rr   __array_finalize__hasattrrz   )r>   objrs   r"   r#   r   <  s    
z EarthLocation.__array_finalize__c                    s"   | j dkrtdn
t  S d S )Nr"   z*0-d EarthLocation arrays cannot be indexed)rD   
IndexErrorrr   __len__r   rs   r"   r#   r   A  s    

zEarthLocation.__len__c                 C   sD   |  | jtj}|g kr| j}| jj|||d}| | j| j	S )z"Helper method for to and to_value.)equivalencies)
r~   r   rQ   ZndarrayZ_equivalenciesrE   r   rC   r   rD   )r>   rE   r   Z
array_viewZ	new_arrayr"   r"   r#   	_to_valueG  s
    zEarthLocation._to_value)N)ru   N)FN)FF)N)N),r\   r]   r^   r_   rz   rQ   rC   Zfloat64rq   r   r9   rU   rl   classmethodrd   rg   r   r   r   r   propertyr    setterr   r   r   r   r   r   r   r   Zitrsr   r   r   r   r:   r;   r<   r   r   r   r   __classcell__r"   r"   rs   r#   r      sl   

0.
Cf
1



"




"
D


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                       sP   e Zd ZdZeeejdZ fddZ	d fdd	Z
d	d
 Zedd Z  ZS )r   zBase geodetic representation.r   c                    s*   t  jf i | d| jv r&| t| j< d S r   )rr   __init_subclass____dict__r   rz   )ri   rk   rs   r"   r#   r   o  s    
z,BaseGeodeticRepresentation.__init_subclass__NTc                    sZ   |d u rt || jsdtj> }t j||||d | jjtjsVt	| jj
 dd S )Nr   rm   z& requires height with units of length.)r0   rt   rO   r{   rr   __init__r   rE   Zis_equivalentZUnitTypeErrorr\   )r>   r   r   r   rF   rs   r"   r#   r   t  s
    
z#BaseGeodeticRepresentation.__init__c                 C   s,   t tt | j| j| j| j}t|dddS )zs
        Converts WGS84 geodetic coordinates to 3D rectangular (geocentric)
        cartesian coordinates.
        rH   Fr   )erfaZgd2gcrI   rz   r   r   r   r   )r>   rG   r"   r"   r#   r|   }  s    z'BaseGeodeticRepresentation.to_cartesianc                 C   s2   t tt | j|jdd\}}}| |||ddS )z{
        Converts 3D rectangular cartesian coordinates (assumed geocentric) to
        WGS84 geodetic coordinates.
        rH   rx   Frm   )r   Zgc2gdrI   rz   r}   )ri   Zcartr   r   r   r"   r"   r#   r     s    

z)BaseGeodeticRepresentation.from_cartesian)NNT)r\   r]   r^   r_   r   r   rO   rP   Zattr_classesr   r   r|   r   r   r   r"   r"   rs   r#   r   g  s   		r   c                   @   s   e Zd ZdZdZdS )r   z:Representation of points in WGS84 3D geodetic coordinates.r   Nr\   r]   r^   r_   rz   r"   r"   r"   r#   r     s   r   c                   @   s   e Zd ZdZdZdS )r   z:Representation of points in WGS72 3D geodetic coordinates.ZWGS72Nr   r"   r"   r"   r#   r     s   r   c                   @   s   e Zd ZdZdZdS )r   z:Representation of points in GRS80 3D geodetic coordinates.ZGRS80Nr   r"   r"   r"   r#   r     s   r   )Nr   )9warningsr   collectionsr2   r+   Zurllib.requestr*   Zurllib.errorZurllib.parseZnumpyrQ   r   Zastropyr   rO   r   r   Zastropy.units.quantityr   Zastropy.utilsr   Zastropy.utils.decoratorsr   Zastropy.utils.exceptionsr   Zanglesr
   r   r   Zrepresentationr   r   r   Zmatrix_utilitiesr   errorsr   __all__
namedtupler   r   cycleZdayr   r   Zdimensionless_anglesr   r$   r8   r9   rP   r   Zgeodetic_base_docr   r   r   r   r"   r"   r"   r#   <module>   sT   
'A     4)