a
    ߙfb%                     @   s^   d 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gZdd	giZG d
d dejZdS )z`
This module contains the classes and utility functions for distance and
cartesian coordinates.
    N)units)AstropyWarning   )AngleDistance*Zscipyc                       sf   e Zd ZdZejZdZd fdd	Ze	dd	 Z
dd
dZe	dd Zedd Ze	dd Z  ZS )r   a
  
    A one-dimensional distance.

    This can be initialized in one of five ways:

    * A distance ``value`` (array or float) and a ``unit``
    * A `~astropy.units.Quantity` object
    * A redshift and (optionally) a cosmology.
    * Providing a distance modulus
    * Providing a parallax

    Parameters
    ----------
    value : scalar or `~astropy.units.Quantity` ['length']
        The value of this distance.
    unit : `~astropy.units.UnitBase` ['length']
        The units for this distance, *if* ``value`` is not a
        `~astropy.units.Quantity`. Must have dimensions of distance.
    z : float
        A redshift for this distance.  It will be converted to a distance
        by computing the luminosity distance for this redshift given the
        cosmology specified by ``cosmology``. Must be given as a keyword
        argument.
    cosmology : `~astropy.cosmology.Cosmology` or None
        A cosmology that will be used to compute the distance from ``z``.
        If `None`, the current cosmology will be used (see
        `astropy.cosmology` for details).
    distmod : float or `~astropy.units.Quantity`
        The distance modulus for this distance. Note that if ``unit`` is not
        provided, a guess will be made at the unit between AU, pc, kpc, and Mpc.
    parallax : `~astropy.units.Quantity` or `~astropy.coordinates.Angle`
        The parallax in angular units.
    dtype : `~numpy.dtype`, optional
        See `~astropy.units.Quantity`.
    copy : bool, optional
        See `~astropy.units.Quantity`.
    order : {'C', 'F', 'A'}, optional
        See `~astropy.units.Quantity`.
    subok : bool, optional
        See `~astropy.units.Quantity`.
    ndmin : int, optional
        See `~astropy.units.Quantity`.
    allow_negative : bool, optional
        Whether to allow negative distances (which are possible is some
        cosmologies).  Default: ``False``.

    Raises
    ------
    `~astropy.units.UnitsError`
        If the ``unit`` is not a distance.
    ValueError
        If value specified is less than 0 and ``allow_negative=False``.

        If ``z`` is provided with a ``unit`` or ``cosmology`` is provided
        when ``z`` is *not* given, or ``value`` is given as well as ``z``.

        If none of ``value``, ``z``, ``distmod``, or ``parallax`` were given.


    Examples
    --------
    >>> from astropy import units as u
    >>> from astropy.cosmology import WMAP5, WMAP7
    >>> d1 = Distance(10, u.Mpc)
    >>> d2 = Distance(40, unit=u.au)
    >>> d3 = Distance(value=5, unit=u.kpc)
    >>> d4 = Distance(z=0.23)
    >>> d5 = Distance(z=0.23, cosmology=WMAP5)
    >>> d6 = Distance(distmod=24.47)
    >>> d7 = Distance(Distance(10 * u.Mpc))
    >>> d8 = Distance(parallax=21.34*u.mas)
    TNFr   c              
      s  t dd ||||fD }|dkr,tdn|dkr<td|d urp|d u r`ddlm} | }||}d}n|d urtd	|d ur| |}|d u rt|j	
 }|d
krtj}n&|dkrtj}n|dk rtj}ntj}d}nZ|d ur@|d u rtj}|j|t d}d}t|dk r@|r8tdt ntdt j| |||||	|
|d}tjdd  t|j	dk }W d    n1 s0    Y  |s|rtd|S )Nc                 s   s   | ]}|d uV  qd S )N ).0xr   r   <lib/python3.9/site-packages/astropy/coordinates/distances.py	<genexpr>g       z#Distance.__new__.<locals>.<genexpr>r   zQnone of `value`, `z`, `distmod`, or `parallax` were given to Distance constructorr   zZmore than one of `value`, `z`, `distmod`, or `parallax` were given to Distance constructordefault_cosmologyFzHA `cosmology` was given but `z` was not provided in Distance constructor      )ZequivalencieszNegative parallaxes are converted to NaN distances even when `allow_negative=True`, because negative parallaxes cannot be transformed into distances. See discussion in this paper: https://arxiv.org/abs/1507.02105a
  Some parallaxes are negative, which are notinterpretable as distances. See the discussion in this paper: https://arxiv.org/abs/1507.02105 . If you want parallaxes to pass through, with negative parallaxes instead becoming NaN, use the `allow_negative=True` argument.)dtypecopyordersubokndminignore)ZinvalidzXDistance must be >= 0.  Use the argument 'allow_negative=True' to allow negative values.)sum
ValueErrorastropy.cosmologyr   getluminosity_distance_distmod_to_pcnplog10valueZmeanuZMpcZkpcZAUpcto_valueparallaxanywarningswarnr   super__new__Zerrstate)clsr!   Zunitz	cosmologydistmodr%   r   r   r   r   r   Zallow_negativeZ
n_not_noner   Z
meanlogvalZdistanceZany_negative	__class__r   r   r*   c   s\    




0zDistance.__new__c                 C   s   |   S )zShort for ``self.compute_z()``)	compute_zselfr   r   r   r,      s    z
Distance.zc                 K   sH   ddl m} |du r(ddl m} | }|dd ||j| fi |S )a  
        The redshift for this distance assuming its physical distance is
        a luminosity distance.

        Parameters
        ----------
        cosmology : `~astropy.cosmology.Cosmology` or None
            The cosmology to assume for this calculation, or `None` to use the
            current cosmology (see `astropy.cosmology` for details).
        **atzkw
            keyword arguments for :func:`~astropy.cosmology.z_at_value`

        Returns
        -------
        z : `~astropy.units.Quantity`
            The redshift of this distance given the provided ``cosmology``.

        Warnings
        --------
        This method can be slow for large arrays.
        The redshift is determined using :func:`astropy.cosmology.z_at_value`,
        which handles vector inputs (e.g. an array of distances) by
        element-wise calling of :func:`scipy.optimize.minimize_scalar`.
        For faster results consider using an interpolation table;
        :func:`astropy.cosmology.z_at_value` provides details.

        See Also
        --------
        :func:`astropy.cosmology.z_at_value` : Find the redshift corresponding to a
            :meth:`astropy.cosmology.FLRW.luminosity_distance`.
        r   )
z_at_valueNr   Zztolg|=)r   r4   r   r   
setdefaultr   )r3   r-   Zatzkwr4   r   r   r   r   r1      s     zDistance.compute_zc                 C   s,   dt | tj d }tj|tjddS )z3The distance modulus as a `~astropy.units.Quantity`      @Fr   )r   r    r$   r"   r#   Quantitymag)r3   valr   r   r   r.      s    zDistance.distmodc                 C   s,   t |t j}| d|jd d  t jddS )N
      r6   Fr7   )r"   r8   r9   r!   r#   )r+   Zdmr   r   r   r      s    zDistance._distmod_to_pcc                 C   s   t | tjt S )z<The parallax angle as an `~astropy.coordinates.Angle` object)r   tor"   Zmilliarcsecondr%   r2   r   r   r   r%      s    zDistance.parallax)NNNNNNNTNFr   F)N)__name__
__module____qualname____doc__r"   mZ_equivalent_unitZ _include_easy_conversion_membersr*   propertyr,   r1   r.   classmethodr   r%   __classcell__r   r   r/   r   r      s    I   Y

)

)rA   r'   Znumpyr   Zastropyr   r"   Zastropy.utils.exceptionsr   Zanglesr   __all__Z__doctest_requires__ZSpecificTypeQuantityr   r   r   r   r   <module>   s   
