a
    ~bU                     @   sx   d dl 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 ddlmZmZ G d	d
 d
eZdddZee dS )    N   )util)Element)	NdMapping
item_checksorted_context   )DictInterface)	Interface	DataErrorc                   @   sz  e Zd ZdZdZdZg dZg dZdZe	dd Z
e	d=d	d
Ze	dd Ze	d>ddZe	dd Ze	dd Ze	dd Ze	dd Ze	dd Ze	d?ddZe	d@ddZe	dd  Ze	d!d" Ze	d#d$ Ze	g fd%d&Ze	d'd( Ze	d)d* Ze	d+d, Ze	g dfd-d.Ze	d/d0 Ze	dAd1d2Ze	d3d4 Ze	dBd5d6Z e	d7d8 Z!e	d9d: Z"e	d;d< Z#dS )CMultiInterfacea  
    MultiInterface allows wrapping around a list of tabular datasets
    including dataframes, the columnar dictionary format or 2D tabular
    NumPy arrays. Using the split method the list of tabular data can
    be split into individual datasets.

    The interface makes the data appear a list of tabular datasets as
    a single dataset. The interface may be used to represent geometries
    so the behavior depends on the type of geometry being represented.
     Zmultitabular)
dictionary	dataframearrayZdask)PolygonRingLinePointTc                    s  ddl m}m} g }|j|jd}|d ur2||d< |d urB||d< t trnt rntdd  D rn g nFt ts fdd	| j	D }	|	st t
rt||r g ntd
d\}
} D ]}| j	}t|tr0|j|v rdd	 |D }|d}|d ur"|| jvr"td|| jf ndd	 |D }tj|||||d\}}	}}|
r|
|	krftd| |d |d krtd| |d |d krtd| || |	| }
}q||i fS )N   )PolygonsPath)kdimsvdimsr   r   c                 s   s*   | ]"}t |to td d |D V  qdS )c                 s   s   | ]}t |V  qd S N)r   isscalar).0vr   r   <lib/python3.9/site-packages/holoviews/core/data/multipath.py	<genexpr>,       z0MultiInterface.init.<locals>.<genexpr>.<genexpr>N)
isinstancetupleallr   dr   r   r   r   ,   r    z&MultiInterface.init.<locals>.<genexpr>c                    s(   g | ] }|t jv rt j| qS r   )r
   
interfacesgetZapplies)r   stdatar   r   
<listcomp>/   s   z'MultiInterface.init.<locals>.<listcomp>z9MultiInterface data must be a list of tabular data types.NNc                 S   s"   g | ]}t tj|d r|qS )	has_holeshasattrr
   r&   r'   r   Zdtr   r   r   r+   :   s   	geom_typez5Geometry type '%s' not recognized, must be one of %s.c                 S   s"   g | ]}t tj|d r|qS )r1   r.   r0   r   r   r   r+   A   s   )datatypez8MultiInterface subpaths must all have matching datatype.z5MultiInterface subpaths must all have matching kdims.z5MultiInterface subpaths must all have matching vdims.)elementr   r   r   r   r!   listlenr#   subtypesr"   
issubclass
ValueErrordict	_hole_keyr'   
geom_typesr   r
   Z
initializeappend)clseltyper*   r   r   r   r   new_dataZdims	interfaceZprev_interfaceZ	prev_dimsr%   r2   r1   _r   r)   r   init    sV    








zMultiInterface.initc           
      C   s   |j s
d S ddlm} | j||d}|j D ]}||_ |j|| t||r*|jtu r*|j|}t|t	svt
d| |d }|j |jd j }t|d }	t||	d kr*t
d| q*d S )Nr   r   )validate_vdimsz3Polygons holes must be declared as a list-of-lists.floatr   z_Polygons with holes containing multi-geometries must declare a list of holes for each geometry.)r*   holoviews.elementr   _inner_dataset_templater@   validater!   r	   holesr4   r   r   namenpisnanastypesumr5   )
r=   datasetr   r   dsr%   rI   ZsubholesZcoordsZsplitsr   r   r   rH   P   s$    


zMultiInterface.validatec                 C   s   ddl m}m}m} t|tr$|}nBt|}t|jtrf| |}t	|j
drf|j
|}|d urf|S t||rtdS t||rdS t||rdS d S )Nr   )r   r   Pointsr1   r   r   r   )rF   r   r   rQ   r!   typer*   r4   rG   r/   r@   r1   r7   )r=   rO   r   r   rQ   r>   rP   r1   r   r   r   r1   f   s     




zMultiInterface.geom_typec                 C   sB   ddl m} t|dddu r"|jng }||jd | j|j||dS )z
        Returns a Dataset template used as a wrapper around the data
        contained within the multi-interface dataset.
        r   DatasetlevelNr   )r2   r   r   Z_validate_vdims) rT   getattrr   r*   r6   r   )r=   rO   rD   rT   r   r   r   r   rG   z   s    z&MultiInterface._inner_dataset_templatec                    sV   |  |}g }t|jD ]8\ }||_|j| fdd| D }|| q|S )Nc                    s"   i | ]\}}||  d   qS r   r   r   kr   ir   r   
<dictcomp>   r    z)MultiInterface.assign.<locals>.<dictcomp>)rG   	enumerater*   r@   assignitemsr<   )r=   rO   r?   rP   assignedr%   newr   r[   r   r_      s    
 zMultiInterface.assignc                 C   s"   |j s
tS | |}|j||S r   )r*   rE   rG   r@   dimension_type)r=   rO   dimrP   r   r   r   rc      s    
zMultiInterface.dimension_typec                 C   s|   |j s
dS g }| |}t|dd }||}|d urL||jd u rL||fS |j D ]}||_ ||j|| qRt	|S )Nr,   rU   r   )
r*   rG   rW   get_dimensionr   r<   r@   ranger   Z	max_range)r=   rO   rd   ZrangesrP   rU   r%   r   r   r   rf      s    


zMultiInterface.rangec                 C   s<   |j s
dS | |}|j D ]}||_ |j|r dS qdS )NFT)r*   rG   r@   r-   )r=   rO   rP   r%   r   r   r   r-      s    

zMultiInterface.has_holesc                 C   s>   g }|j s|S | |}|j D ]}||_ ||j|7 }q|S r   )r*   rG   r@   rI   )r=   rO   rI   rP   r%   r   r   r   rI      s    

zMultiInterface.holesFc           
      C   s   |j s
dS | |}| |}g }|j D ]n}||_ |jj||dd}tt|}	t|	dkrd dS |rr|dkrrq(|	d }	|	|vr(|r dS |	|	 q(dS )z?
        Tests if dimension is scalar in each subpath.
        TF)expandedr   r   r   )
r*   r1   rG   r@   valuesr4   r   unique_iteratorr5   r<   )
r=   rO   rd   Zper_geomr1   rP   Zcombinedr%   rh   uniquer   r   r   r      s&    


zMultiInterface.isscalarNc           
         s   ddl m} |js|jS |dur6dd t||jD S | |}|jf t|jdrf |j|f7  g }|jD ]f}||_|j	||}|j
||}t|t}	t|s|	rp|	rt fdd| D rqp|| qp|S )	z9
        Applies selectiong on all the subpaths.
        r   rC   Nc                 S   s   g | ]\}}|r|qS r   r   )r   br%   r   r   r   r+      r    z)MultiInterface.select.<locals>.<listcomp>
geo_columnc                 3   s4   | ],\}}| vrt |r d n
t|dkV  qdS )Fr   N)r   r   r5   rY   Zskippedr   r   r      s   z(MultiInterface.select.<locals>.<genexpr>)r3   r   r*   ziprG   r:   r/   r@   rl   select_maskselectr!   r9   r5   anyr`   r<   )
r=   rO   Zselection_mask	selectionr   rP   r*   r%   ZselZis_dictr   rm   r   rp      s2    


zMultiInterface.selectc                 C   s<   t dd |jD | }t|tr.|d gS dd |D S )zH
        Allows selecting paths with usual NumPy slicing index.
        c                 S   s   g | ]}d |iqS r   r   )r   pr   r   r   r+      r    z/MultiInterface.select_paths.<locals>.<listcomp>r   c                 S   s   g | ]}|d  qS rs   r   r   sr   r   r   r+      r    )rK   r   r*   r!   r9   )r=   rO   indexrr   r   r   r   select_paths   s    

zMultiInterface.select_pathsc                 K   s   t dd S )Nz%Aggregation currently not implementedNotImplementedError)r=   rO   
dimensionsfunctionkwargsr   r   r   	aggregate   s    zMultiInterface.aggregatec              	      s   fddD fdd j D }i }|dkr6tn|}t|tr\|t  ||d< || g D ]8}|  |dstd| | 	 |dd}	
|	 qntd	d
lm}
 |
}fddtt|	D }g }t|D ]P}|j|tt|}dd t j|D }||fi |}|
||f qt|trtdT td* ||dW  d    W  d    S 1 s0    Y  W d    n1 s0    Y  n||S d S )Nc                    s   g | ]}  |qS r   )re   r$   rO   r   r   r+     r    z*MultiInterface.groupby.<locals>.<listcomp>c                    s   g | ]}| vr|qS r   r   )r   Zkdim)r{   r   r   r+     r    rawr   TzVMultiInterface can only apply groupby on scalar dimensions, %s dimension is not scalarFr   rS   c                 3   s$   | ] t  fd dD V  qdS )c                 3   s   | ]}|  V  qd S r   r   )r   valsr[   r   r   r      r    z3MultiInterface.groupby.<locals>.<genexpr>.<genexpr>N)r"   )r   )rh   r[   r   r      r    z)MultiInterface.groupby.<locals>.<genexpr>c                 S   s   g | ]\}}|r|qS r   r   )r   r*   mr   r   r   r+   $  r    )r   )r   r4   r7   r   updater   Zget_param_valuesr   r8   rh   r<   r"   rV   rT   rf   r5   ri   r@   ro   r9   rn   r*   r   r   r   )r=   rO   r{   Zcontainer_typeZ
group_typer}   r   Zgroup_kwargsr%   r   rT   rP   keysZgrouped_dataZ
unique_keymaskrr   Z
group_datar   )rO   r{   rh   r   groupby  s<    


\zMultiInterface.groupbyc                 C   s   t dd S )Nz,Sampling operation on subpaths not supportedry   )r=   rO   Zsamplesr   r   r   sample.  s    zMultiInterface.samplec                 C   s~   |j sdt| fS | |dkr:t|j t| fS d\}}| |}|j D ]"}||_ |j|\}}||7 }qR||fS )z
        Returns the shape of all subpaths, making it appear like a
        single array of concatenated subpaths separated by NaN values.
        r   r   )r   r   )r*   r5   r{   r1   rG   r@   shape)r=   rO   rowscolsrP   r%   rr   r   r   r   2  s    


zMultiInterface.shapec                 C   sV   |j s
dS | |dkr"t|j S d}| |}|j D ]}||_ ||j|7 }q6|S )z
        Returns the length of the multi-tabular dataset making it appear
        like a single array of concatenated subpaths separated by NaN
        values.
        r   r   )r*   r1   r5   rG   r@   length)r=   rO   r   rP   r%   r   r   r   r   E  s    


zMultiInterface.lengthc                 C   s(   |j stdS | |}|j||S )NrE   )r*   rK   dtyperG   r@   )r=   rO   	dimensionrP   r   r   r   r   W  s    

zMultiInterface.dtypec                    sd    fdd|D }t |dkr6|  |d d }n fdd|D }t|} fdd|D S )Nc                    s   g | ]}  |jqS r   )re   rJ   r$   r   r   r   r+   `  r    z'MultiInterface.sort.<locals>.<listcomp>r   r   Fc                    s   g | ]}  |d qS )F)Zdimension_valuesr$   r   r   r   r+   d  r    c                    s   g | ]} j | qS r   r)   ru   r   r   r   r+   f  r    )r5   rh   Zargsortr   Z
arglexsort)r=   rO   ZbyreverseZsortingZarraysr   r   r   sort^  s    
zMultiInterface.sortc                 C   s
   t |jS r   )boolr*   )r=   rO   r   r   r   nonzeroh  s    zMultiInterface.nonzeroc                 C   s6   g }|  |}|jD ]}||_|||| q|S r   )rG   r*   r<   reindex)r=   rO   r   r   r?   rP   r%   r   r   r   r   l  s    

zMultiInterface.reindexc                 C   sD   |j s|j S g }| |}|j D ]}||_ ||j|| q |S r   )r*   rG   r<   r@   redim)r=   rO   r{   r?   rP   r%   r   r   r   r   u  s    

zMultiInterface.redimc              	   C   s  |j stg S g g  }}d}	| |}
| |}|dk}||jdd v }|j D ]}||
_ |
j|
|d|||}tt	
|dko| }t|
jdr|
j|
nd}|du r|}|dv r|r|r|dks|
d	dg}t||}|r|s|dd }|	|M }	|| t|sqR|| |sR|rR|tjg qR|sFtg S |sX|	r|s|sp|rp|dd
 }|rt|S tg S tjt|td}dd t||D |dd< |S dS )z
        Returns a single concatenated array of all subpaths separated
        by NaN values. If expanded keyword is False an array of arrays
        is returned.
        Tr   Nr   r   r1   r   r   rQ   r   )r   c                 S   s    g | ]\}}|r|d  n|qS rs   r   )r   rv   ar   r   r   r+     r    z)MultiInterface.values.<locals>.<listcomp>)r*   rK   r   rG   r1   r   r@   rh   r5   r   Zunique_arrayr/   ensure_ringr<   ZNaNZconcatenateemptyobjectrn   )r=   rO   r   rg   ZflatZcomputeZ
keep_indexrh   ZscalarsZ
all_scalarrP   r1   Z	is_pointsZis_geomr%   ZdvalsscalargtZgvalsr   r   r   r   rh     sP    









zMultiInterface.valuesc                 K   s|  g }|du r6|j || D ]}|||g q|S |j s@|S | |}|g }	|j || D ]}|g|	_ |dkr|	jf i |}
n|dkr|	jf i |}
n|dv r`t|	jdr|	j|	}|du r|}t|	j d t	rDt	|	j d }
|	j
\}}|dv s||
vs||
vrL|	j|	||
|j< |	j|	||
|j< n|	 }
|durl||
d< ntd| ||
 qb|S )	zr
        Splits a multi-interface Dataset into regular Datasets using
        regular tabular interfaces.
        Nr   r   )columnsr   r1   r   r   z%s datatype not support)r*   r<   cloner1   r   Zdframer/   r@   r!   r9   r   rh   rJ   r   r8   )r=   rO   startendr2   r}   Zobjsr%   r1   rP   objr   ZxdZydr   r   r   split  sH    






zMultiInterface.splitc              
   C   s   t |js|jS |d u s"t|r4|gt |j }nt |t |jksNtdg }| |}|jjdk}t|j|D ]@\}	}
|	|_|r|	|
 }n|}||j||||
| qt|S )NzFAdded dimension values must be scalar or match the length of the data.r   )r5   r*   r   r   r8   rG   r@   r2   rn   r   r   r<   add_dimension)r=   rO   r   Zdim_posrh   Zvdimr?   templateZ
array_typer%   r   rP   r   r   r   r     s     

zMultiInterface.add_dimensionc                    s  |\}}t |ot |}| |}| |dkrr| ||}g }|D ]$}	|	|_||jd d |f j qH|S d g }|jD ]d}	|	|_t|t |r  |  kr krn n&|j|  |f }
|r|
n|
jg  S nt	|t
r|jd ur|j  krqn|jd ur,|j k r, q|jd u r<d nt|j  d}|jd u r\d nt|j  }|jd ur|jd t
||}||j||f j n8 fdd|D }|j||f }t|r||j  7  q|S )Nr   r   zL.iloc step slicing currently not supported forthe multi-tabular data format.c                    s4   g | ],}d |    kr$  k rn q|  qS rs   r   )r   r   countr   r   r   r+     r    z'MultiInterface.iloc.<locals>.<listcomp>)rK   r   rG   r1   rx   r*   r<   ilocr5   r!   slicer   stopmaxminstepZparamZwarning)r=   rO   rw   r   r   r   r   Zgeomsr?   r%   r*   r   r   ZslcZsub_rowsrb   r   r   r   r     sH    

  


zMultiInterface.iloc)T)T)F)N)NN)TTTF)$__name__
__module____qualname____doc__typesr2   r6   r;   ZmulticlassmethodrB   rH   r1   rG   r_   rc   rf   r-   rI   r   rp   rx   r~   r   r   r   r   r   r   r   r   r   rh   r   r   r   r   r   r   r   r   
   sx   
/

	
	





	

)


	


  4
*
r   c           	      C   s   |du r| }t t | djddd }dgt|d  }t|d t| d g }t| | | | ||| }ttdd |D  }|s|S |\}}t j	|t|t|ddS )a,  Ensure the (multi-)geometry forms a ring.

    Checks the start- and end-point of each geometry to ensure they
    form a ring, if not the start point is inserted at the end point.
    If a values array is provided (which must match the geometry in
    length) then the insertion will occur on the values instead,
    ensuring that they will match the ring geometry.

    Args:
        geom: 2-D array of geometry coordinates
        values: Optional array of values

    Returns:
        Array where values have been inserted and ring closing indexes
    NrE   r   )Zaxisr   c                 S   s,   g | ]$\}}}}||k  r||d  fqS rX   )rq   )r   rv   er\   r   r   r   r   r+   9  s   zensure_ring.<locals>.<listcomp>)
rK   whererL   rM   rN   r4   r5   rn   r"   insert)	Zgeomrh   ZbreaksZstartsZendsZzippedZunpackedinsertsZindsr   r   r   r   "  s    "r   )N)ZnumpyrK   rV   r   r3   r   Z	ndmappingr   r   r   r   r	   r@   r
   r   r   r   registerr   r   r   r   <module>   s       
