a
    DfvB                     @   s   d dl Z d dlmZ d dlm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dlmZmZ d	d
lmZmZmZ d	dlmZ dZde  ZG dd deZG dd deZdS )    N)
cmp_to_key)cycle   )Dataset)	Dimension)	Operation)get_param_valuesunique_array   )	EdgePathsGraphNodes)quadratic_bezier   
   c                   @   sH  e Zd ZdZejddZejdddZej	ddd	d
Z
ej	dddZejdddZd<ddZdd Zedd Zedd Zedd Zedd Zdd Zedd Zedd Zed d! Zed"d# Zd$d% Zed&d' Zed(d) Zed*d+ Zed,d- Zd.d/ Zed0d1 Z d2d3 Z!d4d5 Z"d6d7 Z#ed8d9 Z$d:d; Z%dS )=_layout_sankeyz
    Computes a Sankey diagram from a Graph element for internal use in
    the Sankey element constructor.

    Adapted from d3-sankey under BSD-3 license.

    Source: https://github.com/d3/d3-sankey/tree/v0.12.3
    )r   r   i  i  default   z
        Width of the nodes.)r   docNTz<
        Number of pixels of padding relative to the bounds.)r   Z
allow_Noner       z:
        Number of iterations to run the layout algorithm.z)
        Sort nodes in ascending breadth.c                 C   s>   | j |fi | j\}}}t|}t|j||ffd|i|S Nsankey)layoutpr   Sankeydata)selfelementkeynodesedgesgraphparams r$   e/nfs/NAS7/SABIOD/METHODE/ermites/ermites_venv/lib/python3.9/site-packages/holoviews/element/sankey.py_process+   s    z_layout_sankey._processc           
   	   K   s&  t | || _g g d}| || | | | | | | | | | | | 	|}g }|d D ]H}|
t|d |d gt|d |d g|d ft|d   ql|jjd	kr|jj}n2|jjr|jjd d
 |jjdd   }n|jj}|j|||jjd}||}	||	|fS )N)r    linksr    x0x1y0y1indexvalues   r   kdimsvdims)paramZParamOverridesr   computeNodeLinkscomputeNodeValuescomputeNodeDepthscomputeNodeHeightscomputeNodeBreadthscomputeLinkBreadthscomputePathsappendnpmeantupler    Zndimsr1   	node_typer2   	edge_type)
r   r   r#   r"   pathsZ	node_datanoder1   r    r!   r$   r$   r%   r   0   s2    








"
z_layout_sankey.layoutc                    s
   j jd }i } j jr4t fdd j jD  }ntt g}t j ||D ],\}}|g g |d}|d | |||< qR fdd  dd	 D }	t	t|	 D ]Z\}
\}}}|| ||  }}t
|
|||d
}|d | |d | |d | qdS )z
        Populate the sourceLinks and targetLinks for each node.
        Also, if the source and target are not objects, assume they are indices.
        r/   c                 3   s   | ]} j |V  qd S N)r    dimension_values.0dr   r$   r%   	<genexpr>S   s   z2_layout_sankey.computeNodeLinks.<locals>.<genexpr>)r,   sourceLinkstargetLinksr-   r    c                    s   g | ]}  |qS r$   )rD   rE   rH   r$   r%   
<listcomp>\       z3_layout_sankey.computeNodeLinks.<locals>.<listcomp>Nr.   )r,   sourcetargetvaluer'   rJ   rK   )r    r1   r2   zipr   r>   rD   r;   Z
dimensions	enumeratedict)clsr   r"   r,   Znode_mapr-   idxvalsrB   r'   isrctgtrP   rN   rO   linkr$   rH   r%   r4   J   s$    

z_layout_sankey.computeNodeLinksc                 C   sR   |d D ]D}t dd |d D }t dd |d D }t||g|d< qdS )	zX
        Compute the value (size) of each node by summing the associated links.
        r    c                 S   s   g | ]}|d  qS rP   r$   rF   lr$   r$   r%   rL   j   rM   z4_layout_sankey.computeNodeValues.<locals>.<listcomp>rJ   c                 S   s   g | ]}|d  qS r[   r$   r\   r$   r$   r%   rL   k   rM   rK   rP   N)r<   summax)rT   r"   rB   Z
source_valZ
target_valr$   r$   r%   r5   d   s    z _layout_sankey.computeNodeValuesc                 C   sl   |d }d}|rhg }|D ](}||d< |d D ]}| |d  q,q|}|d7 }|t|d krtdq|S )Nr    r   depthrJ   rO   r
   ,Sankey diagrams only support acyclic graphs.r;   lenRecursionError)rT   r"   r    r`   
next_nodesrB   rZ   r$   r$   r%   r6   n   s    
z _layout_sankey.computeNodeDepthsc                 C   sl   |d }d}|rhg }|D ](}||d< |d D ]}| |d  q,q|}|d7 }|t|d krtdq|S )Nr    r   heightrK   rN   r
   ra   rb   )rT   r"   r    rf   re   rB   rZ   r$   r$   r%   r7   ~   s    
z!_layout_sankey.computeNodeHeightsc           	   	   C   s   t dd |d D d }| jjd | jjd  }}| jj}|| | |d  }dd t|D }|d D ]l}t dt|d t|d	 r|d
 n|d |d< ||d |  |d< |d | |d< ||d  | qj|S )Nc                 s   s   | ]}|d  V  qdS )r`   Nr$   )rF   xr$   r$   r%   rI      rM   z4_layout_sankey.computeNodeColumns.<locals>.<genexpr>r    r
   r   r   c                 S   s   g | ]}g qS r$   r$   )rF   _r$   r$   r%   rL      rM   z5_layout_sankey.computeNodeColumns.<locals>.<listcomp>rJ   r`   columnr(   r)   )	r_   r   bounds
node_widthrangeminmathfloorr;   )	r   r"   Zdepth_upper_boundr(   r)   ZdxZkxcolumnsrB   r$   r$   r%   computeNodeColumns   s*    
z!_layout_sankey.computeNodeColumnsc                 C   s   t |d |d  S )Nr*   )intrT   abr$   r$   r%   ascendingBreadth   s    z_layout_sankey.ascendingBreadthc                 C   s@   d|d v r,d|d v r,|  |d |d nd p>|d |d  S )Nr*   rN   r,   rv   rs   r$   r$   r%   ascendingSourceBreadth   s    

z%_layout_sankey.ascendingSourceBreadthc                 C   s@   d|d v r,d|d v r,|  |d |d nd p>|d |d  S )Nr*   rO   r,   rw   rs   r$   r$   r%   ascendingTargetBreadth   s    

z%_layout_sankey.ascendingTargetBreadthc                 C   s:   |D ]0}|d j t| jd |d j t| jd qd S )NrJ   r   rK   sortr   ry   rx   )rT   r    rg   r$   r$   r%   reorderLinks   s    z_layout_sankey.reorderLinksc           
         s   | j j\}}t fdd|D }|D ]}}|D ]J}||d< ||d |  |d< |d   }|d D ]}|d | |d< qnq:|   t|d  }t|D ]8\}	}|d  ||	d  7  < |d  ||	d  7  < q| | q.d S )	Nc                 3   s8   | ]0} t |d     tdd |D  V  qdS )r
   c                 s   s   | ]}|d  V  qdS )rP   Nr$   )rF   rB   r$   r$   r%   rI      rM   zB_layout_sankey.initializeNodeBreadths.<locals>.<genexpr>.<genexpr>N)rc   r^   )rF   cpyr*   r+   r$   r%   rI      s   z8_layout_sankey.initializeNodeBreadths.<locals>.<genexpr>r*   rP   r+   rJ   widthr
   )r   rj   rm   rc   rR   r}   )
r   rp   r   rh   kyr    yrB   rZ   rW   r$   r   r%   initializeNodeBreadths   s"    z%_layout_sankey.initializeNodeBreadthsc                 C   s|   |d t |d d | d  }|d D ]$}|d |u r< qN||d | 7 }q(|d D ] }|d |u rj qx||d 8 }qV|S )	Nr*   rK   r
   r   rN   r   rJ   rO   rc   rT   rN   rO   r   r   rZ   r$   r$   r%   	sourceTop   s     z_layout_sankey.sourceTopc                 C   s|   |d t |d d | d  }|d D ]$}|d |u r< qN||d | 7 }q(|d D ] }|d |u rj qx||d 8 }qV|S )	Nr*   rJ   r
   r   rO   r   rK   rN   r   r   r$   r$   r%   	targetTop   s     z_layout_sankey.targetTopc                 C   sZ   ||d  D ]H}||d  | }|t krH|d  |7  < |d  |7  < |d | }qd S )Nr*   r+   _Y_EPSrT   r    r   rW   alphar   rB   dyr$   r$   r%   resolveCollisionsTopToBottom   s    z+_layout_sankey.resolveCollisionsTopToBottomc                 C   sb   |dkr^|| }|d | | }|t krH|d  |8  < |d  |8  < |d | }|d8 }q d S )Nr   r+   r*   r
   r   r   r$   r$   r%   resolveCollisionsBottomToTop   s    z+_layout_sankey.resolveCollisionsBottomToTopc           	      C   s   | j j\}}}}t|d }|| }| ||d | |d || | ||d | |d || | ||t|d || | ||d|| d S )Nr   r*   r
   r+   r   )r   rj   rc   r   r   )	r   r    r   r   rh   r*   r+   rW   subjectr$   r$   r%   resolveCollisions  s    z _layout_sankey.resolveCollisionsc                 C   sT   |d D ]}|d d j t| jd q|d D ]}|d d j t| jd q0d S )NrK   rN   rJ   rz   rO   r{   )rT   rB   rZ   r$   r$   r%   reorderNodeLinks  s    z_layout_sankey.reorderNodeLinksc              	   C   s   |dd  D ]}|D ]}d}d}|d D ]B}	|	d }
|	d |d |
d   }||  |
||| 7 }||7 }q(|dkrvq|| |d  | }|d  |7  < |d  |7  < | | q| jjr|jt| jd	 | ||| qd S )
Nr
   r   rK   rN   rP   ri   r*   r+   rz   )r   r   r   	node_sortr|   r   rv   r   )r   rp   r   betar   ri   rO   r   wrZ   rN   vr   r$   r$   r%   relaxLeftToRight  s$    
z_layout_sankey.relaxLeftToRightc              	   C   s   |ddd D ]}|D ]}d}d}|d D ]B}	|	d }
|	d |
d |d   }||  ||
|| 7 }||7 }q*|dkrxq|| |d	  | }|d	  |7  < |d
  |7  < | | q| jjr|jt| jd | ||| qdS )z:Reposition each node based on its outgoing (source) links.Nr/   r   rJ   rO   rP   ri   r*   r+   rz   )r   r   r   r   r|   r   rv   r   )r   rp   r   r   r   ri   rN   r   r   rZ   rO   r   r   r$   r$   r%   relaxRightToLeft1  s$    
z_layout_sankey.relaxRightToLeftc                 C   s   |  |}| jj\}}}}ttt|}d}| jjd ur@| jjn |dkr^t|| |d  |n|}| || t	| jj
D ]F}	d|	 }
td|
 |	d | jj
 }| ||
|| | ||
|| qz|d D ]}t|d t|d< qd S )N   r
   gGz?r    r+   )rq   r   rj   r_   maprc   node_paddingrm   r   rl   
iterationsr   r   round_Y_N_DECIMAL_DIGITS)r   r"   rp   rh   r*   r+   Zmax_column_sizeZmax_default_paddingr   rW   r   r   rB   r$   r$   r%   r8   F  s$    


z"_layout_sankey.computeNodeBreadthsc                 C   s   |d D ]0}|d j t| jd |d j t| jd q|d D ]l}|d }|}|d D ]$}||d d  |d< ||d 7 }qZ|d D ]$}||d d  |d< ||d 7 }qqBd S )	Nr    rJ   rz   rK   r*   r   r   r+   r{   )rT   r"   rB   r*   r+   rZ   r$   r$   r%   r9   \  s    z"_layout_sankey.computeLinkBreadthsc                 C   s  g }|d D ]}|d |d  }}|d }|d }|| d }|d |d d  }	|d |d d  }
|d	 |d d  }|d	 |d d  }t ||	g||
gg}t||
f||f||
f||f}t ||g||gg}t||f||	f||f||	f}t ||||g}|| q|S )
Nr'   rN   rO   r)   r(   r   r*   r   r+   )r<   arrayr   concatenater;   )r   r"   rA   rZ   rN   rO   r(   r)   ZxmidZy0_upperZy0_lowerZy1_upperZy1_lowerstartZbottomZmidtopZspliner$   r$   r%   r:   l  sB    z_layout_sankey.computePaths)N)&__name__
__module____qualname____doc__r3   ZNumericTuplerj   Numberrk   ZIntegerr   r   Booleanr   r&   r   classmethodr4   r5   r6   r7   rq   rv   rx   ry   r}   r   r   r   r   r   r   r   r   r   r8   r9   r:   r$   r$   r$   r%   r      sV   	


	











	


r   c                       sP   e Zd ZdZejd ddZejedgdZ	d fdd	Z
d fd	d
	Z  ZS )r   zt
    Sankey is an acyclic, directed Graph type that represents the flow
    of some quantity between its nodes.
    T)r   ZconstantValuer   Nc                    s  |d u rg }t |tr6|ddt|   }|\}}}n|d d   }}}|dd }|oht |toht |t }	tt| j|f||d| |	rH|d u r| j	ddd}
| j	ddd}t
t|
|g}t|d	}n8t |ts
zt|}W n ty   t|d	}Y n0 |jstd
|| _t | \}}}|| _|| _|| _nRt || jsjtdt| d|| _t || jstdt| || _|| _|   d S )NrC   r.   r   r0   r   F)expandedr
   r,   zCould not determine index in supplied node data. Ensure data has at least one key dimension, which matches the node ids on the edges.z%Expected Nodes object in data, found .z,Expected EdgePaths object in data, found %s.)
isinstancer>   rc   popr   r   superr   __init__rD   r	   r<   r   r   	Exceptionr1   
ValueError_nodesr   instancer   Z
_edgepaths_sankeyr?   	TypeErrortyper@   	_validate)r   r   r1   r2   r#   r!   r    Z	edgepathsZsankey_graphZcomputerX   rY   r-   r"   	__class__r$   r%   r     sJ    
zSankey.__init__c                    s2   |d u r| j |d< t j||||g|R i |S r   )r   r   clone)r   r   Zshared_datanew_typerZ   argsZ	overridesr   r$   r%   r     s    
zSankey.clone)NN)NTNT)r   r   r   r   r3   StringgroupListr   r2   r   r   __classcell__r$   r$   r   r%   r     s
   *r   )rn   	functoolsr   	itertoolsr   numpyr<   r3   Z	core.datar   Zcore.dimensionr   Zcore.operationr   Z	core.utilr   r	   Zgraphsr   r   r   utilr   r   r   r   r   r$   r$   r$   r%   <module>   s"   
   