B
    \uJ                 @   s   d Z ddlmZ ddlZddlmZ ddlZddlm	Z	m
Z
 dd ZG d	d
 d
eZG dd deZG dd deZG dd deZG dd deZdd Zdd Zdd Zdd Zdd ZdS )z4
    High-level access to HDF5 dataspace selections
    )absolute_importN)xrange   )h5sh5rc          	   C   s  t |ts|f}t|dkr|d }t |trD|j| kr@td|S t |tjrdt| }||  |S t |t	j
rt	||}| |jkrtdt| |dS xn|D ]f}t |ts|tk	ry(t| t |tjr|jdkrt W q tk
r   t| }||  |S X qW t| }||  |S )a"   High-level routine to generate a selection from arbitrary arguments
    to __getitem__.  The arguments should be the following:

    shape
        Shape of the "source" dataspace.

    args
        Either a single argument or a tuple of arguments.  See below for
        supported classes of argument.

    dsid
        A h5py.h5d.DatasetID instance representing the source dataset.

    Argument classes:

    Single Selection instance
        Returns the argument.

    numpy.ndarray
        Must be a boolean mask.  Returns a PointSelection instance.

    RegionReference
        Returns a Selection instance.

    Indices, slices, ellipses only
        Returns a SimpleSelection instance

    Indices, slices, ellipses, lists or boolean index arrays
        Returns a FancySelection instance.
       r   zMismatched selection shapez,Reference shape does not match dataset shape)spaceid)r   )
isinstancetuplelen	Selectionshape	TypeErrornpndarrayPointSelectionr   ZRegionReferenceZ
get_regionsliceEllipsisint	ExceptionFancySelectionSimpleSelection)r   argsdsidargZselsida r   2lib/python3.7/site-packages/h5py/_hl/selections.pyselect   s<    






r   c               @   s    e Zd ZdZdd Zdd ZdS )_RegionProxyz
        Thin proxy object which takes __getitem__-style index arguments and
        produces RegionReference objects.  Example:

        >>> dset = myfile['dataset']
        >>> myref = dset.regionref[0:100,20:30]
        >>> data = dset[myref]

    c             C   s
   || _ dS )z& Supply a h5py.h5d.DatasetID instance N)id)selfr   r   r   r   __init__m   s    z_RegionProxy.__init__c             C   s(   t | jj|| j}t| jdtj|jS )z Takes arbitrary selection terms and produces a RegionReference
        object.  Selection must be compatible with the dataset.
        .)r   r!   r   r   ZcreateZDATASET_REGION)r"   r   Z	selectionr   r   r   __getitem__q   s    z_RegionProxy.__getitem__N)__name__
__module____qualname____doc__r#   r%   r   r   r   r   r    a   s   
r    c               @   sZ   e Zd ZdZdddZedd Zedd Zed	d
 Zedd Z	dd Z
dd ZdS )r   a  
        Base class for HDF5 dataspace selections.  Subclasses support the
        "selection protocol", which means they have at least the following
        members:

        __init__(shape)   => Create a new selection on "shape"-tuple
        __getitem__(args) => Perform a selection with the range specified.
                             What args are allowed depends on the
                             particular subclass in use.

        id (read-only) =>      h5py.h5s.SpaceID instance
        shape (read-only) =>   The shape of the dataspace.
        mshape  (read-only) => The shape of the selection region.
                               Not guaranteed to fit within "shape", although
                               the total number of points is less than
                               product(shape).
        nselect (read-only) => Number of selected points.  Always equal to
                               product(mshape).

        broadcast(target_shape) => Return an iterable which yields dataspaces
                                   for read, based on target_shape.

        The base class represents "unshaped" selections (1-D).
    Nc             C   sN   |dk	r|| _ |j| _n2t|}|| _t|tjft| | _ | j   dS )z= Create a selection.  Shape may be None if spaceid is given. N)	_idr   _shaper
   r   Zcreate_simpleZ	UNLIMITEDr   
select_all)r"   r   r   r   r   r   r#      s    
zSelection.__init__c             C   s   | j S )z SpaceID instance )r*   )r"   r   r   r   r!      s    zSelection.idc             C   s   | j S )z Shape of whole dataspace )r+   )r"   r   r   r   r      s    zSelection.shapec             C   s
   | j  S )z' Number of elements currently selected )r*   get_select_npoints)r"   r   r   r   nselect   s    zSelection.nselectc             C   s   | j fS )z0 Shape of selection (always 1-D for this class) )r.   )r"   r   r   r   mshape   s    zSelection.mshapec             c   s$   t || jkrtd| jV  dS )z" Get an iterable for broadcasting z7Broadcasting is not supported for point-wise selectionsN)r   productr.   r   r*   )r"   target_shaper   r   r   	broadcast   s    zSelection.broadcastc             C   s   t dd S )Nz$This class does not support indexing)NotImplementedError)r"   r   r   r   r   r%      s    zSelection.__getitem__)N)r&   r'   r(   r)   r#   propertyr!   r   r.   r/   r2   r%   r   r   r   r   r   x   s   
r   c               @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )r   z
        Represents a point-wise selection.  You can supply sequences of
        points to the three methods append(), prepend() and set(), or a
        single boolean array to __getitem__.
    c             C   sn   t j|ddd}t|jdkr.d|jd f|_| j tjkrDtj}t|dkr\| j	  n| j
|| dS )z7 Internal method which actually performs the selection Cu8)orderdtyper   r   N)r   Zasarrayr   r   r*   get_select_typer   
SEL_POINTS
SELECT_SETselect_noneZselect_elements)r"   pointsopr   r   r   _perform_selection   s    z!PointSelection._perform_selectionc             C   sP   t |tjr|jjdks td|j| jks4tdt| }| 	| | S )z9 Perform point-wise selection from a NumPy boolean array bz6PointSelection __getitem__ only works with bool arraysz-Boolean indexing array has incompatible shape)
r	   r   r   r8   Zkindr   r   Z	transposenonzeroset)r"   r   r=   r   r   r   r%      s    
zPointSelection.__getitem__c             C   s   |  |tj dS )z@ Add the sequence of points to the end of the current selection N)r?   r   ZSELECT_APPEND)r"   r=   r   r   r   append   s    zPointSelection.appendc             C   s   |  |tj dS )zF Add the sequence of points to the beginning of the current selection N)r?   r   ZSELECT_PREPEND)r"   r=   r   r   r   prepend   s    zPointSelection.prependc             C   s   |  |tj dS )z@ Replace the current selection with the given sequence of pointsN)r?   r   r;   )r"   r=   r   r   r   rB      s    zPointSelection.setN)	r&   r'   r(   r)   r?   r%   rC   rD   rB   r   r   r   r   r      s   r   c               @   s4   e Zd ZdZedd Zdd Zdd Zdd	 Zd
S )r   z A single "rectangular" (regular) selection composed of only slices
        and integer arguments.  Can participate in broadcasting.
    c             C   s   | j S )z Shape of current selection )_mshape)r"   r   r   r   r/      s    zSimpleSelection.mshapec             O   sF   t j| |f|| t| j}d| | jd| d| f| _| j| _d S )N)r   )r   )F)r   r#   r   r   _selrE   )r"   r   r   kwdsrankr   r   r   r#      s    
zSimpleSelection.__init__c             C   s   t |ts|f}| jdkrLt|dkr>|d tdfkr>td| j  | S t| j|\}}}}| j	||| ||||f| _
tdd t||D | _| S )Nr   r   z7Invalid index for scalar dataset (only ..., () allowed)c             s   s   | ]\}}|s|V  qd S )Nr   ).0xyr   r   r   	<genexpr>  s    z.SimpleSelection.__getitem__.<locals>.<genexpr>)r	   r
   r   r   r   r   r*   r,   _handle_simpleselect_hyperslabrF   ziprE   )r"   r   startcountstepscalarr   r   r   r%      s    


zSimpleSelection.__getitem__c             c   s  | j dkr:t|dkr$td| | j  | jV  dS | j\}}}}t|}t|}g }xtt	d|d D ]b}	t|dks||	  r|
d ql| }
|
dks||	  |
kr|
|
 qltd|| jf qlW tdd |D rtd|| jf |  t|}td	d
 t||D }tt|}|dkr@| jV  nd| j }|d| || xFt	|D ]:}	tdd
 tt|	||||D }|| |V  qfW dS )z Return an iterator over target dataspaces for broadcasting.

        Follows the standard NumPy broadcasting rules against the current
        selection shape (self.mshape).
        r   r   zCan't broadcast %s to scalarNr   zCan't broadcast %s -> %sc             S   s   g | ]}|d kqS )r   r   )rI   nr   r   r   
<listcomp>-  s    z-SimpleSelection.broadcast.<locals>.<listcomp>c             s   s   | ]\}}|| V  qd S )Nr   )rI   rJ   rK   r   r   r   rL   5  s    z,SimpleSelection.broadcast.<locals>.<genexpr>)r   c             s   s&   | ]\}}}}|| | | V  qd S )Nr   )rI   rJ   rK   zsr   r   r   rL   >  s    )r   r   r0   r   r*   r,   rF   r   listr   rC   popr/   anyreverser
   rO   r   copyrN   Zunravel_indexZoffset_simple)r"   r1   rP   rQ   rR   rS   rH   targetZtshapeidxtZchunksZnchunksr   offsetr   r   r   r2     s>    




$
zSimpleSelection.broadcastN)	r&   r'   r(   r)   r4   r/   r#   r%   r2   r   r   r   r   r      s
   r   c               @   s4   e Zd ZdZedd Zdd Zdd Zdd	 Zd
S )r   a(  
        Implements advanced NumPy-style selection operations in addition to
        the standard slice-and-int behavior.

        Indexing arguments may be ints, slices, lists of indicies, or
        per-axis (1D) boolean arrays.

        Broadcasting is not supported for these selections.
    c             C   s   | j S )N)rE   )r"   r   r   r   r/   O  s    zFancySelection.mshapec             O   s    t j| |f|| | j| _d S )N)r   r#   r   rE   )r"   r   r   rG   r   r   r   r#   S  s    zFancySelection.__init__c          	      sJ  t |ts|f}t|t| j}i }xt|D ]\}}t |ts.t|dr||jt	dkr|t|jdkrpt
d| d }yt|||< W n t
k
r   Y q.X t|}t|d d |dd  }tdd |D r.t
d	q.W t|dkrt
d
t|dkrt
dtt| d  t fdd| D sHt
d| g }xJt D ]>}t|}x$t|D ]\}	}
|
| ||	< qnW || qVW | j  x@t|D ]4\}}t| j|\}}}}| jj|||tjd qW t|}xDtt|D ]4}||krt|| ||< n|| rd||< qW tdd |D | _d S )Nr8   boolr   z#Boolean indexing arrays must be 1-Dr   c             s   s   | ]\}}||kV  qd S )Nr   )rI   ZfstZsndr   r   r   rL   n  s    z-FancySelection.__getitem__.<locals>.<genexpr>z-Indexing elements must be in increasing orderzMOnly one indexing vector or array is currently allowed for advanced selectionz Advanced selection inappropriatec             3   s   | ]}t | kV  qd S )N)r   )rI   rJ   )vectorlengthr   r   rL   w  s    z3All sequence arguments must have the same length %s)r>   c             s   s   | ]}|d kr|V  qdS )r   Nr   )rI   rJ   r   r   r   rL     s    )r	   r
   _expand_ellipsisr   r   	enumerater   hasattrr8   r   r   rA   rX   rO   rZ   valuesallr   sixZ	iteritemsrC   r*   r<   rM   rN   r   Z	SELECT_ORrE   )r"   r   Zsequenceargsr^   r   Zlist_argZadjacentZ	argvectorentryZpositionseqZvectorrP   rQ   rR   rS   r/   r   )rc   r   r%   W  sT    




zFancySelection.__getitem__c             c   s   || j kstd| jV  d S )Nz4Broadcasting is not supported for complex selections)r/   r   r*   )r"   r1   r   r   r   r2     s    
zFancySelection.broadcastN)	r&   r'   r(   r)   r4   r/   r#   r%   r2   r   r   r   r   r   C  s
   
@r   c             C   s   t dd | D }|dkr$tdn|dkrBt| |krB| tf } g }t| }x@| D ]8}|tkr|tdddf|| d   qT|| qTW t||krtd|S )z7 Expand ellipsis objects and fill in missing axes.
    c             s   s   | ]}|t krd V  qdS )r   N)r   )rI   r   r   r   r   rL     s    z#_expand_ellipsis.<locals>.<genexpr>r   zOnly one ellipsis may be used.r   NzArgument sequence too long)sum
ValueErrorr   r   extendr   rC   r   )r   rH   Zn_elZ
final_argsZn_argsr   r   r   r   rd     s    


"rd   c          	   C   s   t |t| }g }g }g }g }xt|| D ]\}}t|trRt||\}}	}
d}n>ytt||\}}	}
d}W n  tk
r   td| Y nX |	| |	|	 |	|
 |	| q*W t
|t
|t
|t
|fS )aU   Process a "simple" selection tuple, containing only slices and
        integer objects.  Return is a 4-tuple with tuples for start,
        count, step, and a flag which tells if the axis is a "scalar"
        selection (indexed by an integer).

        If "args" is shorter than "shape", the remaining axes are fully
        selected.
    FTz.Illegal index "%s" (must be a slice or number))rd   r   rO   r	   r   _translate_slice_translate_intr   r   rC   r
   )r   r   rP   rQ   rR   rS   r   lengthrJ   rK   rV   rW   r   r   r   rM     s&    	



rM   c             C   sD   | dk r||  } d|   kr$|k s:n t d| |d f | ddfS )zk Given an integer index, return a 3-tuple
        (start, count, step)
        for hyperslab selection
    r   zIndex (%s) out of range (0-%s)r   )rm   )exprq   r   r   r   rp     s
    rp   c             C   sN   |  |\}}}|dk r$td| ||k r0dS d|| d |  }|||fS )z Given a slice object, return a 3-tuple
        (start, count, step)
        for use with the hyperslab selection routines
    r   zStep must be >= 1 (got %d))r   r   r   )indicesrm   )rr   rq   rP   stoprR   rQ   r   r   r   ro     s    ro   c                s8    } }|tjkrdS |tjkrH|tjkr6dS |tjkr^t S n|tjkr^t	d| 
  tj}|tjkrd| S |tjkrjS |tjkr fS |tjkrt	d|  dkrd| S dd  D \}| t|f  fdd	tfd
dt|D }t| kr4 fS |S )a0   Given a dataspace, try to deduce the shape of the selection.

    Returns one of:
        * A tuple with the selection shape, same length as the dataspace
        * A 1D selection shape for point-based and multiple-hyperslab selections
        * None, for unselected scalars and for NULL dataspaces
    NzUnrecognized dataspace class %s)r   z Unrecognized selection method %sr   c             s   s   | ]}t |V  qd S )N)r   Zarray)rI   rJ   r   r   r   rL   %  s    zguess_shape.<locals>.<genexpr>c                sr   | dkrdS   }||  d7  <   }||  d8  < |   }|jt|t|tjd | } | S )a   Determine the number of elements selected along a particular axis.

        To do this, we "mask off" the axis by making a hyperslab selection
        which leaves only the first point along the axis.  For a 2D dataset
        with selection box shape (X, Y), for axis 1, this would leave a
        selection of shape (X, 1).  We count the number of points N_leftover
        remaining in the selection and compute the axis selection length by
        N_axis = N/N_leftover.
        r   )r>   )r\   rN   r
   r   ZSELECT_NOTBr-   )r   ZaxisrP   rQ   Z
masked_sidZ
N_leftover)Nbottomcornerboxshaper   r   
get_n_axis*  s    zguess_shape.<locals>.get_n_axisc             3   s   | ]} |V  qd S )Nr   )rI   rJ   )rx   r   r   r   rL   F  s    )Zget_simple_extent_typer9   r   ZNULLZSCALARZSEL_NONEZSEL_ALLr
   ZSIMPLEr   r-   r   r   r:   ZSEL_HYPERSLABSZget_select_boundsr   Zonesr   r0   )r   Z	sel_classZsel_typerH   Z	topcornerr   r   )ru   rv   rw   rx   r   r   guess_shape  s<    	


 
 





ry   )r)   Z
__future__r   ri   Z	six.movesr   Znumpyr    r   r   r   objectr    r   r   r   r   rd   rM   rp   ro   ry   r   r   r   r   <module>   s    FC.ZY!