
    IR-eHA                         d Z ddlZddlZddlmZ ddlZg dZ G d d          Z G d deej	        	          Z
 G d
 de          Zd Zd Zd ZdS )z>The ShapedLikeNDArray mixin class and shape-related functions.    N)zip_longest)NDArrayShapeMethodsShapedLikeNDArraycheck_broadcastIncompatibleShapeErrorsimplify_basic_indexunbroadcastc                   f    e Zd ZdZd Zd Zd Zd Zd Zd Z	e
d             Zd	 Zd
 Zd ZddZdS )r   a  Mixin class to provide shape-changing methods.

    The class proper is assumed to have some underlying data, which are arrays
    or array-like structures. It must define a ``shape`` property, which gives
    the shape of those data, as well as an ``_apply`` method that creates a new
    instance in which a `~numpy.ndarray` method has been applied to those.

    Furthermore, for consistency with `~numpy.ndarray`, it is recommended to
    define a setter for the ``shape`` property, which, like the
    `~numpy.ndarray.shape` property allows in-place reshaping the internal data
    (and, unlike the ``reshape`` method raises an exception if this is not
    possible).

    This class only provides the shape-changing methods and is meant in
    particular for `~numpy.ndarray` subclasses that need to keep track of
    other arrays.  For other classes, `~astropy.utils.shapes.ShapedLikeNDArray`
    is recommended.

    c                 .    |                      d|          S )N__getitem___applyselfitems     4lib/python3.11/site-packages/astropy/utils/shapes.pyr   zNDArrayShapeMethods.__getitem__0   s    {{=$///    c                 $     | j         dg|R i |S )zReturn an instance containing copies of the internal data.

        Parameters are as for :meth:`~numpy.ndarray.copy`.
        copyr   r   argskwargss      r   r   zNDArrayShapeMethods.copy3   s&    
 t{63D333F333r   c                 $     | j         dg|R i |S )a  Returns an instance containing the same data with a new shape.

        Parameters are as for :meth:`~numpy.ndarray.reshape`.  Note that it is
        not always possible to change the shape of an array without copying the
        data (see :func:`~numpy.reshape` documentation). If you want an error
        to be raise if the data is copied, you should assign the new shape to
        the shape attribute (note: this may not be implemented for all classes
        using ``NDArrayShapeMethods``).
        reshaper   r   s      r   r   zNDArrayShapeMethods.reshape:   s&     t{96t666v666r   c                 $     | j         dg|R i |S )ah  Return an instance with the array collapsed into one dimension.

        Parameters are as for :meth:`~numpy.ndarray.ravel`. Note that it is
        not always possible to unravel an array without copying the data.
        If you want an error to be raise if the data is copied, you should
        should assign shape ``(-1,)`` to the shape attribute.
        ravelr   r   s      r   r   zNDArrayShapeMethods.ravelF   s&     t{74T444V444r   c                 $     | j         dg|R i |S )zReturn a copy with the array collapsed into one dimension.

        Parameters are as for :meth:`~numpy.ndarray.flatten`.
        flattenr   r   s      r   r   zNDArrayShapeMethods.flattenP   s&    
 t{96t666v666r   c                 $     | j         dg|R i |S )zReturn an instance with the data transposed.

        Parameters are as for :meth:`~numpy.ndarray.transpose`.  All internal
        data are views of the data of the original.
        	transposer   r   s      r   r    zNDArrayShapeMethods.transposeW   s&     t{;8888888r   c                 D    | j         dk     r| S |                                 S )zReturn an instance with the data transposed.

        Parameters are as for :attr:`~numpy.ndarray.T`.  All internal
        data are views of the data of the original.
           )ndimr    r   s    r   TzNDArrayShapeMethods.T_   s$     9q==K>>###r   c                 $     | j         dg|R i |S )zReturn an instance with the given axes interchanged.

        Parameters are as for :meth:`~numpy.ndarray.swapaxes`:
        ``axis1, axis2``.  All internal data are views of the data of the
        original.
        swapaxesr   r   s      r   r'   zNDArrayShapeMethods.swapaxesk   s&     t{:7777777r   c                 $     | j         dg|R i |S )zReturn an instance with the specified diagonals.

        Parameters are as for :meth:`~numpy.ndarray.diagonal`.  All internal
        data are views of the data of the original.
        diagonalr   r   s      r   r)   zNDArrayShapeMethods.diagonalt   s&     t{:7777777r   c                 $     | j         dg|R i |S )zReturn an instance with single-dimensional shape entries removed.

        Parameters are as for :meth:`~numpy.ndarray.squeeze`.  All internal
        data are views of the data of the original.
        squeezer   r   s      r   r+   zNDArrayShapeMethods.squeeze|   s&     t{96t666v666r   Nraisec                 V    |t          d          S |                     d|||          S )zReturn a new instance formed from the elements at the given indices.

        Parameters are as for :meth:`~numpy.ndarray.take`, except that,
        obviously, no output array can be given.
        Nz$cannot pass 'out' argument to 'take.take)axismode)NotImplementedErrorr   )r   indicesr/   outr0   s        r   r.   zNDArrayShapeMethods.take   s2     ?&'MNNN{{67D{AAAr   )NNr,   )__name__
__module____qualname____doc__r   r   r   r   r   r    propertyr%   r'   r)   r+   r.    r   r   r   r      s         60 0 04 4 4
7 
7 
75 5 57 7 79 9 9 	$ 	$ X	$8 8 88 8 87 7 7	B 	B 	B 	B 	B 	Br   r   c                      e Zd ZdZeej        d                         Zej        d             Zed             Z	ed             Z
ed             Zd Zd Zd	 Zd
 Zej        ej        ej        ej        ej        ej        ej        ej        ej        ej        ej        ej        ej        hZd ej        j         j!        D             Z"de"ej#        <   d Z$dS )r   a  Mixin class to provide shape-changing methods.

    The class proper is assumed to have some underlying data, which are arrays
    or array-like structures. It must define a ``shape`` property, which gives
    the shape of those data, as well as an ``_apply`` method that creates a new
    instance in which a `~numpy.ndarray` method has been applied to those.

    Furthermore, for consistency with `~numpy.ndarray`, it is recommended to
    define a setter for the ``shape`` property, which, like the
    `~numpy.ndarray.shape` property allows in-place reshaping the internal data
    (and, unlike the ``reshape`` method raises an exception if this is not
    possible).

    This class also defines default implementations for ``ndim`` and ``size``
    properties, calculating those from the ``shape``.  These can be overridden
    by subclasses if there are faster ways to obtain those numbers.

    c                     dS )z!The shape of the underlying data.Nr9   r$   s    r   shapezShapedLikeNDArray.shape         r   c                     dS )a  Create a new instance, with ``method`` applied to underlying data.

        The method is any of the shape-changing methods for `~numpy.ndarray`
        (``reshape``, ``swapaxes``, etc.), as well as those picking particular
        elements (``__getitem__``, ``take``, etc.). It will be applied to the
        underlying arrays (e.g., ``jd1`` and ``jd2`` in `~astropy.time.Time`),
        with the results used to create a new instance.

        Parameters
        ----------
        method : str
            Method to be applied to the instance's internal data arrays.
        args : tuple
            Any positional arguments for ``method``.
        kwargs : dict
            Any keyword arguments for ``method``.

        Nr9   )methodr   r   s      r   r   zShapedLikeNDArray._apply   r=   r   c                 *    t          | j                  S )z?The number of dimensions of the instance and underlying arrays.)lenr<   r$   s    r   r#   zShapedLikeNDArray.ndim   s     4:r   c                 (    d}| j         D ]}||z  }|S )z5The size of the object, as calculated from its shape.   r<   )r   sizeshs      r   rE   zShapedLikeNDArray.size   s*     * 	 	BBJDDr   c                     | j         dk    S )Nr9   rD   r$   s    r   isscalarzShapedLikeNDArray.isscalar   s    zRr   c                 d    | j         rt          d| j        j        d          | j        d         S )NzScalar z object has no len()r   )rH   	TypeError	__class__r4   r<   r$   s    r   __len__zShapedLikeNDArray.__len__   s8    = 	WUdn&=UUUVVVz!}r   c                     | j         dk    S )z>Any instance should evaluate to True, except when it is empty.r   )rE   r$   s    r   __bool__zShapedLikeNDArray.__bool__   s    y1}r   c                     	 |                      d|          S # t          $ r& | j        rt          d| j        j        d           w xY w)Nr   scalar z object is not subscriptable.)r   
IndexErrorrH   rJ   _ShapedLikeNDArray__classr4   r   s     r   r   zShapedLikeNDArray.__getitem__   sj    	;;}d333 	 	 	} Tdl3TTT   	s	    0Ac                 j      j         rt          d j        j        d           fd} |            S )NrP   z object is not iterable.c               3   ^   K   t          t                              D ]} |          V  d S N)rangerA   )idxr   s    r   	self_iterz-ShapedLikeNDArray.__iter__.<locals>.self_iter   s=      SYY''    3i   r   )rH   rJ   rK   r4   )r   rX   s   ` r   __iter__zShapedLikeNDArray.__iter__   sY    = 	M$.1MMM  	  	  	  	  	  y{{r   c           
      x    i | ]7}|d vt          t          |          ddddddd                    ||          8S ))alensort	partitionmaxminroundallany)amaxaminaroundround_alltruesometrue)getattrnpget).0names     r   
<dictcomp>zShapedLikeNDArray.<dictcomp>  se        444 	D
 
 #dD//444r   r   c                    | j         v rt          j        u r                    dd           nTt          j        t          j        t          j        hv r/t          |          dk    rt          fd|D                       S | |d         urt          S  | j
        g|dd         R i S | |d         u rH| j        v r?t          | | j                 d          }|!t          |          r ||dd         i S |S  j        |i S )z%Wrap numpy functions that make sense.subokTrC   c              3   *   K   | ]} |fi V  d S rU   r9   )rl   argfunctionr   s     r   	<genexpr>z7ShapedLikeNDArray.__array_function__.<locals>.<genexpr>/  s5      EEXXc44V44EEEEEEr   r   N)_APPLICABLE_FUNCTIONSrj   broadcast_to
setdefault
atleast_1d
atleast_2d
atleast_3drA   tupleNotImplementedr   _METHOD_FUNCTIONSri   callable__wrapped__)r   rs   typesr   r   r?   s    `  ` r   __array_function__z$ShapedLikeNDArray.__array_function__$  sO   t1112?** !!'40000R]BM2=IIIIIMMEEEEEEEEEEE47""%%4;x=$qrr(===f=== 47??x4+AAAT4#9(#CTJJF!F## "!6486v666 "M $x#T4V444r   N)%r4   r5   r6   r7   r8   abcabstractmethodr<   r   r#   rE   rH   rL   rN   r   rY   rj   moveaxisrollaxisrx   ry   rz   expand_dimsrv   flipfliplrflipudrot90rolldeleteru   corefromnumeric__all__r}   r   r   r9   r   r   r   r      s        4 0 0  X0 	  (   X   X     X   
  	 	 	  " 	







	
	


	&  G'/   "(bg5 5 5 5 5r   r   )	metaclassc                        e Zd Z fdZ xZS )r   c                 P    t                                          ||||           d S rU   )super__init__)r   shape_ashape_a_idxshape_bshape_b_idxrK   s        r   r   zIncompatibleShapeError.__init__G  s'    +wDDDDDr   )r4   r5   r6   r   __classcell__)rK   s   @r   r   r   F  sA        E E E E E E E E Er   r   c                     t          |           dk    rdS t          |           dk    r| d         S d | D             }g }t          |ddiD ]f}d}d}t          |          D ];\  }}|dk    r|dk    r|}|}||k    rt          | |         || |         |          <|                    |           gt          |ddd                   S )a  
    Determines whether two or more Numpy arrays can be broadcast with each
    other based on their shape tuple alone.

    Parameters
    ----------
    *shapes : tuple
        All shapes to include in the comparison.  If only one shape is given it
        is passed through unmodified.  If no shapes are given returns an empty
        `tuple`.

    Returns
    -------
    broadcast : `tuple`
        If all shapes are mutually broadcastable, returns a tuple of the full
        broadcast shape.
    r   r9   rC   c              3   4   K   | ]}t          |          V  d S rU   )reversed)rl   r<   s     r   rt   z"check_broadcast.<locals>.<genexpr>b  s(      ;;5x;;;;;;r   	fillvalueN)rA   r   	enumerater   appendr{   )shapesreversed_shapes
full_shapedimsmax_dimmax_dim_idxrW   dims           r   r   r   K  s   $ 6{{ar	V		ay;;F;;;OJ_::: # #!$ 	 	HCaxx!||!,;'fSk3    
 	'""""DDbD!"""r   c                 
   | j         dk    r| S | t          d | j        D                                } t          d t	          | j                  D             | j                   }|                     | j        |d                   S )a  
    Given an array, return a new array that is the smallest subset of the
    original array that can be re-broadcasted back to the original array.

    See https://stackoverflow.com/questions/40845769/un-broadcasting-numpy-arrays
    for more details.
    r   c              3   `   K   | ])}|d k    rt          d d          nt          d          V  *dS )r   rC   N)slice)rl   strides     r   rt   zunbroadcast.<locals>.<genexpr>  s<      XXfkkuQ{{{uT{{XXXXXXr   c              3   ,   K   | ]\  }}|d k    |V  dS )rC   Nr9   )rl   iss      r   rt   zunbroadcast.<locals>.<genexpr>  s*      99v11q55555599r   N)r#   r{   stridesnextr   r<   r   )arrayfirst_not_unitys     r   r	   r	   {  s     zQXX%-XXXXXE
 995;//9995: O ==_%5%56777r   c          	         t          |          }t          | t          t          f          s| f} t          |           }t          |v r|                    t                    dk    rt          d          |                    t                    }|                    t                     |t          |          z
  }t          |          D ]2}||z   }|
                    |t          d||         d                     3t          |          |k    rt          d|  d| d          t          |          D ]}|t          |          k     r||         }t          |t                    rFt          |                    ||                             }	|	d         dk    rd|	d<   t          |	 ||<   yt          |t          j                  r<t           j        j                            t)          |          ||                   ||<   t          d	|           |                    t          d||         d                     t          |          S )
aH  
    Given a Numpy basic index, return a tuple of integers and slice objects
    with no default values (`None`) if possible.

    If one of the dimensions has a slice and the step is negative and the stop
    value of the slice was originally `None`, the new stop value of the slice
    may still be set to `None`.

    For more information on valid basic indices, see
    https://numpy.org/doc/stable/user/basics.indexing.html#basic-indexing

    Parameters
    ----------
    basic_index
        A valid Numpy basic index
    shape
        The shape of the array being indexed
    rC   z0an index can only have a single ellipsis ('...')r   z&The dimensionality of the basic index z- can not be greater than the dimensionality (z) of the data.r   Nz)Unexpected index element in basic index: )rA   
isinstancer{   listEllipsiscountrQ   indexremoverV   insertr   
ValueErrorr2   numbersIntegralrj   r   
multiarraynormalize_axis_indexintr   )
basic_indexr<   r#   	new_indexe_indn_er   indslcr2   s
             r   r   r     sK   & u::DkE4=11 %"n[!!I9??8$$q((OPPP ))"""S^^#s 	; 	;A!)CS%5:q"9"9::::
9~~=[ = =(,= = =
 
 	

 4[[ 4 4s9~~A,C#u%% Ts{{584455 1:##!%GAJ$g	!C!122 T!w1FFHHeAh   	! !!RS!R!RSSSU1eAh223333r   )r7   r   r   	itertoolsr   numpyrj   r   r   ABCMetar   r   r   r   r	   r   r9   r   r   <module>r      s2   D D 



  ! ! ! ! ! !      yB yB yB yB yB yB yB yBxs5 s5 s5 s5 s5+s{ s5 s5 s5 s5lE E E E EZ E E E
-# -# -#`8 8 8.@ @ @ @ @r   