U
    e»{j:O  ã                   @  sŠ   d Z ddlmZ ddlZddlZddlmZmZm	Z	 dgZ
e d¡Zdd	„ Zd
d„ ZG dd„ dƒZG dd„ dejƒZddddœdd„ZdS )z6
This module defines structured units and quantities.
é    )ÚannotationsNé   )ÚUNITYÚUnitÚUnitBaseÚStructuredUnitÚOc                 C  sJ   g }| j D ]6}| j| d }|j r6| |t|ƒg¡ q
| |¡ q
t|ƒS )z-Recursively extract field names from a dtype.r   )ÚnamesÚfieldsÚappendÚ_names_from_dtypeÚtuple)Údtyper	   ÚnameÚsubdtype© r   úW/var/www/html/bwave/python/venv/lib/python3.8/site-packages/astropy/units/structured.pyr      s    
r   c                 C  sø   g }| D ]æ}t |tƒr.t|ƒdkr.| |¡ qt |tƒrœt|ƒdkrœt |d tƒrœt|d ƒdkrœt |d tƒrœt|d ƒdkrœ| |d t|d ƒg¡ qt |tƒrÞt|ƒdkrÞt|ƒ}d dd„ |D ƒ¡}| ||g¡ qtd|›d�ƒ‚qt|ƒS )	a[  Recursively normalize, inferring upper level names for unadorned tuples.

    Generally, we want the field names to be organized like dtypes, as in
    ``(['pv', ('p', 'v')], 't')``.  But we automatically infer upper
    field names if the list is absent from items like ``(('p', 'v'), 't')``,
    by concatenating the names inside the tuple.
    r   é   r   Ú c                 S  s"   g | ]}t |tƒr|d  n|‘qS ©r   )Ú
isinstanceÚlist©Ú.0Úir   r   r   Ú
<listcomp>8   s     z$_normalize_names.<locals>.<listcomp>zinvalid entry zY. Should be a name, tuple of names, or 2-element list of the form [name, tuple of names].)	r   ÚstrÚlenr   r   r   Ú_normalize_namesÚjoinÚ
ValueError)r	   Úresultr   Z	new_tupler   r   r   r   !   s2    ÿ
þýüûú
ÿr   c                      s6  e Zd ZdZd?‡ fdd„	Zdd„ Zedd„ ƒZd	d
„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zd@‡ fdd„	ZdAdd„Zedd„ ƒZedd„ ƒZdd„ Zed d!„ ƒZeƒ fd"d#„Zg fd$d%„Zg fd&d'„Zejg fd(d)„ZdBd+d,„Zd-d.„ ZdZd/d0„ Zd1d2„ Zd3d4„ Z d5d6„ Z!d7d8„ Z"d9d:„ Z#d;d<„ Z$d=d>„ Z%‡  Z&S )Cr   a�	  Container for units for a structured Quantity.

    Parameters
    ----------
    units : unit-like, tuple of unit-like, or `~astropy.units.StructuredUnit`
        Tuples can be nested.  If a `~astropy.units.StructuredUnit` is passed
        in, it will be returned unchanged unless different names are requested.
    names : tuple of str, tuple or list; `~numpy.dtype`; or `~astropy.units.StructuredUnit`, optional
        Field names for the units, possibly nested. Can be inferred from a
        structured `~numpy.dtype` or another `~astropy.units.StructuredUnit`.
        For nested tuples, by default the name of the upper entry will be the
        concatenation of the names of the lower levels.  One can pass in a
        list with the upper-level name and a tuple of lower-level names to
        avoid this.  For tuples, not all levels have to be given; for any level
        not passed in, default field names of 'f0', 'f1', etc., will be used.

    Notes
    -----
    It is recommended to initialze the class indirectly, using
    `~astropy.units.Unit`.  E.g., ``u.Unit('AU,AU/day')``.

    When combined with a structured array to produce a structured
    `~astropy.units.Quantity`, array field names will take precedence.
    Generally, passing in ``names`` is needed only if the unit is used
    unattached to a `~astropy.units.Quantity` and one needs to access its
    fields.

    Examples
    --------
    Various ways to initialize a `~astropy.units.StructuredUnit`::

        >>> import astropy.units as u
        >>> su = u.Unit('(AU,AU/day),yr')
        >>> su
        Unit("((AU, AU / d), yr)")
        >>> su.field_names
        (['f0', ('f0', 'f1')], 'f1')
        >>> su['f1']
        Unit("yr")
        >>> su2 = u.StructuredUnit(((u.AU, u.AU/u.day), u.yr), names=(('p', 'v'), 't'))
        >>> su2 == su
        True
        >>> su2.field_names
        (['pv', ('p', 'v')], 't')
        >>> su3 = u.StructuredUnit((su2['pv'], u.day), names=(['p_v', ('p', 'v')], 't'))
        >>> su3.field_names
        (['p_v', ('p', 'v')], 't')
        >>> su3.keys()
        ('p_v', 't')
        >>> su3.values()
        (Unit("(AU, AU / d)"), Unit("d"))

    Structured units share most methods with regular units::

        >>> su.physical_type
        ((PhysicalType('length'), PhysicalType({'speed', 'velocity'})), PhysicalType('time'))
        >>> su.si
        Unit("((1.49598e+11 m, 1.73146e+06 m / s), 3.15576e+07 s)")

    Nc                   s¨  d }|d k	rxt |tƒr&|jj}|j}nRt |tjƒr`|js@tdƒ‚t dd„ |jD ƒ¡}t	|ƒ}nt |t
ƒsp|f}t|ƒ}t |t
ƒsºt|ƒ}t |tƒr´|d ks¦|j|krª|S | ¡ }n|f}|d krÞt
dd„ tt|ƒƒD ƒƒ}nt|ƒt|ƒkrötdƒ‚g }t||ƒD ]^\}}t |tƒ�r0| ||d ƒ}|d }n&t|ƒ}|d k	�rVt |tƒ�rVtd	ƒ‚| |¡ �qtƒ  | ¡}|d k�rŽt d
d„ |D ƒ¡}t t
|ƒ|¡d |_|S )Nz(dtype should be structured, with fields.c                 S  s   g | ]}|t f‘qS r   )ÚDTYPE_OBJECT©r   r   r   r   r   r   ‹   s     z*StructuredUnit.__new__.<locals>.<listcomp>c                 s  s   | ]}d |› �V  qdS )ÚfNr   r   r   r   r   Ú	<genexpr>¡   s     z)StructuredUnit.__new__.<locals>.<genexpr>z,lengths of units and field names must match.r   r   zKunits do not match in depth with field names from dtype or structured unit.c                 S  s&   g | ]}t |tƒr|d  n|tf‘qS r   )r   r   r"   r#   r   r   r   r   »   s   ÿr   )r   r   Ú_unitsr   Úfield_namesÚnpr
   r    r	   r   r   r   r   ÚvaluesÚranger   Úzipr   r   ÚsuperÚ__new__Úarray)ÚclsÚunitsr	   r   Z	convertedÚunitr   Úself©Ú	__class__r   r   r-   ‚   sX    






ÿ
þÿzStructuredUnit.__new__c                 C  s   dS )z?When de-serializing, e.g. pickle, start with a blank structure.)r   Nr   ©r2   r   r   r   Ú__getnewargs__Ä   s    zStructuredUnit.__getnewargs__c                 C  s   t dd„ |  ¡ D ƒƒS )z6Possibly nested tuple of the field names of the parts.c                 s  s*   | ]"\}}t |tƒr||jgn|V  qd S ©N)r   r   r'   )r   r   r1   r   r   r   r%   Ë   s   ÿz-StructuredUnit.field_names.<locals>.<genexpr>)r   Úitemsr5   r   r   r   r'   È   s    þzStructuredUnit.field_namesc                 C  s   t | jjjƒS r7   )r   r&   r   r	   r5   r   r   r   Ú__len__Ñ   s    zStructuredUnit.__len__c                 C  s
   | j | S r7   )r&   )r2   Úitemr   r   r   Ú__getitem__Ô   s    zStructuredUnit.__getitem__c                 C  s
   | j  ¡ S r7   )r&   r:   r5   r   r   r   r)   Ø   s    zStructuredUnit.valuesc                 C  s
   | j jjS r7   ©r&   r   r	   r5   r   r   r   ÚkeysÛ   s    zStructuredUnit.keysc                 C  s   t t| jjj| j ¡ ƒƒS r7   )r   r+   r&   r   r	   r:   r5   r   r   r   r8   Þ   s    zStructuredUnit.itemsc                 c  s   | j jjE d H  d S r7   r<   r5   r   r   r   Ú__iter__á   s    zStructuredUnit.__iter__c                   s^   t ‡ fdd„|  ¡ D ƒƒ}t || jj¡d }|dk	rF| ||jf¡S tƒ  | j	¡}||_|S )aq  Apply func recursively.

        Parameters
        ----------
        func : callable
            Function to apply to all parts of the structured unit,
            recursing as needed.
        cls : type, optional
            If given, should be a subclass of `~numpy.void`. By default,
            will return a new `~astropy.units.StructuredUnit` instance.
        c                 3  s   | ]}ˆ |ƒV  qd S r7   r   ©r   Úpart©Úfuncr   r   r%   ñ   s     z4StructuredUnit._recursively_apply.<locals>.<genexpr>r   N)
r   r)   r(   r.   r&   r   Úviewr,   r-   r4   )r2   rB   r/   ZappliedÚresultsr!   r3   rA   r   Ú_recursively_applyå   s    z!StructuredUnit._recursively_applyTc                 C  sä   |rt |tƒr|d }q|tkr0tft| ƒ }n0t |tƒrJt| ƒt|ƒkr`td|› d| › d�ƒ‚g }t|  ¡ |ƒD ]f\\}}}t |tƒr¢| 	||j
|dd�f¡ qrt |¡}|j}|jdkrÆt t¡}| 	|||jf¡ qrt |¡S )aï  Get structured dtype according to value, using our field names.

        This is useful since ``np.array(value)`` would treat tuples as lower
        levels of the array, rather than as elements of a structured array.
        The routine does presume that the type of the first tuple is
        representative of the rest.  Used in ``_get_converter``.

        For the special value of ``UNITY``, all fields are assumed to be 1.0,
        and hence this will return an all-float dtype.

        r   zcannot interpret value z
 for unit Ú.F)Úenter_listsÚiu)r   r   r   r   r   r    r+   r8   r   r   Ú_recursively_get_dtyper(   r.   r   ÚkindÚfloatÚshape)r2   ÚvaluerG   Údescrr   r1   r@   Z
part_dtyper   r   r   rI   ü   s&    


ÿ


z%StructuredUnit._recursively_get_dtypec                 C  s   |   t d¡¡S )z*The `StructuredUnit` instance in SI units.Úsi©rE   ÚoperatorÚ
attrgetterr5   r   r   r   rO     s    zStructuredUnit.sic                 C  s   |   t d¡¡S )z+The `StructuredUnit` instance in cgs units.ÚcgsrP   r5   r   r   r   rS   $  s    zStructuredUnit.cgsc                 C  s   | j t d¡td�S )NÚ_get_physical_type_id©r/   )rE   rQ   ÚmethodcallerÚ	Structurer5   r   r   r   rT   *  s     ÿz$StructuredUnit._get_physical_type_idc                 C  s   | j t d¡td�S )z!Physical types of all the fields.Úphysical_typerU   )rE   rQ   rR   rW   r5   r   r   r   rX   /  s     ÿzStructuredUnit.physical_typec                 C  s   |   tjd|d�¡S )a\  The `StructuredUnit` composed of only irreducible units.

        Parameters
        ----------
        bases : sequence of `~astropy.units.UnitBase`, optional
            The bases to decompose into.  When not provided,
            decomposes down to any irreducible units.  When provided,
            the decomposed result will only contain the given units.
            This will raises a `UnitsError` if it's not possible
            to do so.

        Returns
        -------
        `~astropy.units.StructuredUnit`
            With the unit for each field containing only irreducible units.
        Ú	decompose)Úbases)rE   rQ   rV   )r2   rZ   r   r   r   rY   6  s    zStructuredUnit.decomposec                 C  sl   zt |ƒ}W n tk
r"   Y dS X t| ƒt|ƒkr8dS t|  ¡ | ¡ ƒD ]\}}|j||d�sJ dS qJdS )aÿ  `True` if all fields are equivalent to the other's fields.

        Parameters
        ----------
        other : `~astropy.units.StructuredUnit`
            The structured unit to compare with, or what can initialize one.
        equivalencies : list of tuple, optional
            A list of equivalence pairs to try if the units are not
            directly convertible.  See :ref:`unit_equivalencies`.
            The list will be applied to all fields.

        Returns
        -------
        bool
        F©ÚequivalenciesT)r   Ú	Exceptionr   r+   r)   Úis_equivalent)r2   Úotherr\   Ú	self_partÚ
other_partr   r   r   r^   I  s    zStructuredUnit.is_equivalentc                   sN   t |tˆƒƒsˆj|ˆd�}‡fdd„tˆ ¡ | ¡ ƒD ƒ‰ ‡ ‡fdd„}|S )N©r	   c                   s   g | ]\}}|j |ˆ d �‘qS )r[   )Ú_get_converter)r   r`   ra   r[   r   r   r   k  s   ÿz1StructuredUnit._get_converter.<locals>.<listcomp>c                   s`   t | dƒst | ˆ | ¡¡} t | ¡}t|jjˆ ƒD ]\}}|| | ƒ||< q4|jrX|S |d S )Nr   r   )	Úhasattrr(   r.   rI   Z
empty_liker+   r   r	   rL   )rM   r!   r   Z
converter_)Ú
convertersr2   r   r   Ú	converterp  s    

z0StructuredUnit._get_converter.<locals>.converter)r   Útyper4   r+   r)   )r2   r_   r\   rf   r   )re   r\   r2   r   rc   g  s    
þ	zStructuredUnit._get_converterc                 C  s    |t jkrt}| j||d�|ƒS )aÂ  Return values converted to the specified unit.

        Parameters
        ----------
        other : `~astropy.units.StructuredUnit`
            The unit to convert to.  If necessary, will be converted to
            a `~astropy.units.StructuredUnit` using the dtype of ``value``.
        value : array-like, optional
            Value(s) in the current unit to be converted to the
            specified unit.  If a sequence, the first element must have
            entries of the correct type to represent all elements (i.e.,
            not have, e.g., a ``float`` where other elements have ``complex``).
            If not given, assumed to have 1. in all fields.
        equivalencies : list of tuple, optional
            A list of equivalence pairs to try if the units are not
            directly convertible.  See :ref:`unit_equivalencies`.
            This list is in addition to possible global defaults set by, e.g.,
            `set_enabled_equivalencies`.
            Use `None` to turn off all equivalencies.

        Returns
        -------
        values : scalar or array
            Converted value(s).

        Raises
        ------
        UnitsError
            If units are inconsistent
        r[   )r(   Ú_NoValuer   rc   )r2   r_   rM   r\   r   r   r   Úto{  s    
zStructuredUnit.toÚgenericc                   s^   ‡ fdd„|   ¡ D ƒ}t| ƒdkr&dnd}ˆ  d¡rNdd„ |D ƒ}d| d }| d	 |¡¡S )
aÁ  Output the unit in the given format as a string.

        Units are separated by commas.

        Parameters
        ----------
        format : `astropy.units.format.Base` instance or str
            The name of a format or a formatter object.  If not
            provided, defaults to the generic format.

        Notes
        -----
        Structured units can be written to all formats, but can be
        re-read only with 'generic'.

        c                   s   g | ]}|  ˆ ¡‘qS r   ©Ú	to_stringr?   ©Úformatr   r   r   ±  s     z,StructuredUnit.to_string.<locals>.<listcomp>r   z({})z({},)Úlatexc                 S  s   g | ]}|d d… ‘qS )r   éÿÿÿÿr   r?   r   r   r   r   µ  s     ú$z, )r)   r   Ú
startswithrn   r   )r2   rn   ÚpartsZout_fmtr   rm   r   rl      s    
zStructuredUnit.to_stringc                 C  s
   |   d¡S )Nro   rk   r5   r   r   r   Ú_repr_latex_¹  s    zStructuredUnit._repr_latex_c                   s¬   t ˆ tƒr4ztˆ dd�‰ W n tk
r2   t Y S X t ˆ tƒrft‡ fdd„|  ¡ D ƒƒ}| j|| d�S t ˆ t	ƒrttS zddl
m} |ˆ | d�W S  tk
r¦   t Y S X d S )	NÚsilent©Zparse_strictc                 3  s   | ]}|ˆ  V  qd S r7   r   r?   ©r_   r   r   r%   Å  s     z)StructuredUnit.__mul__.<locals>.<genexpr>rb   r   ©ÚQuantity)r1   )r   r   r   r]   ÚNotImplementedr   r   r)   r4   r   Úquantityry   )r2   r_   Ú	new_unitsry   r   rw   r   Ú__mul__¾  s    



zStructuredUnit.__mul__c                 C  s
   |   |¡S r7   )r}   ©r2   r_   r   r   r   Ú__rmul__Ò  s    zStructuredUnit.__rmul__c                   sj   t ˆ tƒr4ztˆ dd�‰ W n tk
r2   t Y S X t ˆ tƒrft‡ fdd„|  ¡ D ƒƒ}| j|| d�S tS )Nru   rv   c                 3  s   | ]}|ˆ  V  qd S r7   r   r?   rw   r   r   r%   Ý  s     z-StructuredUnit.__truediv__.<locals>.<genexpr>rb   )	r   r   r   r]   rz   r   r   r)   r4   )r2   r_   r|   r   rw   r   Ú__truediv__Õ  s    


zStructuredUnit.__truediv__c                 C  s<   zddl m} ||| ddd�W S  tk
r6   t Y S X d S )Nr   rx   FT)ÚcopyZsubok)r{   ry   r]   rz   )r2   Úmry   r   r   r   Ú__rlshift__á  s
    zStructuredUnit.__rlshift__c                 C  s   |   ¡ S r7   rk   r5   r   r   r   Ú__str__é  s    zStructuredUnit.__str__c                 C  s   d|   ¡ › d�S )NzUnit("z")rk   r5   r   r   r   Ú__repr__ì  s    zStructuredUnit.__repr__c                 C  s6   zt |ƒ}W n tk
r$   t Y S X |  ¡ | ¡ kS r7   )r   r]   rz   r)   r~   r   r   r   Ú__eq__ï  s
    
zStructuredUnit.__eq__c                 C  sD   t |t| ƒƒs4zt|ƒ}W n tk
r2   t Y S X |  ¡ | ¡ kS r7   )r   rg   r   r]   rz   r)   r~   r   r   r   Ú__ne__÷  s    
zStructuredUnit.__ne__)N)N)T)rj   )'Ú__name__Ú
__module__Ú__qualname__Ú__doc__r-   r6   Úpropertyr'   r9   r;   r)   r=   r8   r>   rE   rI   rO   rS   rT   rX   ÚsetrY   r^   rc   r(   rh   ri   rl   rt   Z__array_ufunc__r}   r   r€   rƒ   r„   r…   r†   r‡   Ú__classcell__r   r   r3   r   r   D   sF   =B

#


%
c                   @  s    e Zd ZdZdd„ Zdd„ ZdS )rW   aR  Single element structure for physical type IDs, etc.

    Behaves like a `~numpy.void` and thus mostly like a tuple which can also
    be indexed with field names, but overrides ``__eq__`` and ``__ne__`` to
    compare only the contents, not the field names.  Furthermore, this way no
    `FutureWarning` about comparisons is given.

    c                 C  s    t |tjƒr| ¡ }|  ¡ |kS r7   ©r   r(   Úvoidr:   r~   r   r   r   r†     s    zStructure.__eq__c                 C  s    t |tjƒr| ¡ }|  ¡ |kS r7   r�   r~   r   r   r   r‡     s    zStructure.__ne__N)rˆ   r‰   rŠ   r‹   r†   r‡   r   r   r   r   rW     s   rW   zUnitBase | StructuredUnitznp.dtype)r1   r   Úreturnc                 C  sd   t | tƒr| S g }|jD ]8}|j| d }|jdk	rF| t| |ƒ¡ q| | ¡ qtt|ƒ|jd�S )a0  Make a `StructuredUnit` of one unit, with the structure of a `numpy.dtype`.

    Parameters
    ----------
    unit : UnitBase
        The unit that will be filled into the structure.
    dtype : `numpy.dtype`
        The structure for the StructuredUnit.

    Returns
    -------
    StructuredUnit
    r   Nrb   )r   r   r	   r
   r   Ú_structured_unit_like_dtyper   )r1   r   r0   r   r   r   r   r   r’     s    


r’   )r‹   Ú
__future__r   rQ   Únumpyr(   Úcorer   r   r   Ú__all__r   r"   r   r   r   r�   rW   r’   r   r   r   r   Ú<module>   s   
#   @