U
    cc9                     @   sx   d dl mZ d dlZd dlmZmZ d dlmZ d dlm	Z	 e
dZdd Zd	ejd
 dfddZG dd deZdS )    )absolute_importN)
exceptionsoptional_imports)utils)
graph_objsnumpyc                 C   s   t dkrtdtt| d D ]6}| |d  | |  | d | d   dkr tdq tt|d D ]6}||d  ||  |d |d   dkrhtdqhdS )	as  
    Streamline-specific validations

    Specifically, this checks that x and y are both evenly spaced,
    and that the package numpy is available.

    See FigureFactory.create_streamline() for params

    :raises: (ImportError) If numpy is not available.
    :raises: (PlotlyError) If x is not evenly spaced.
    :raises: (PlotlyError) If y is not evenly spaced.
    Fz.FigureFactory.create_streamline requires numpy   r   g-C6?z.x must be a 1 dimensional, evenly spaced arrayz.y must be a 1 dimensional, evenly spaced arrayN)npImportErrorrangelenr   ZPlotlyError)xyindex r   [/var/www/html/project/venv/lib/python3.8/site-packages/plotly/figure_factory/_streamline.pyvalidate_streamline   s    ((r   r   	   g
ףp=
?c                 K   s   t | | t || t| | t j||d t| |||||| \}}	t| |||||| \}
}tjf ||
 |	| dd|}|g}tj	dd}tj
||dS )aa	  
    Returns data for a streamline plot.

    :param (list|ndarray) x: 1 dimensional, evenly spaced list or array
    :param (list|ndarray) y: 1 dimensional, evenly spaced list or array
    :param (ndarray) u: 2 dimensional array
    :param (ndarray) v: 2 dimensional array
    :param (float|int) density: controls the density of streamlines in
        plot. This is multiplied by 30 to scale similiarly to other
        available streamline functions such as matplotlib.
        Default = 1
    :param (angle in radians) angle: angle of arrowhead. Default = pi/9
    :param (float in [0,1]) arrow_scale: value to scale length of arrowhead
        Default = .09
    :param kwargs: kwargs passed through plotly.graph_objs.Scatter
        for more information on valid kwargs call
        help(plotly.graph_objs.Scatter)

    :rtype (dict): returns a representation of streamline figure.

    Example 1: Plot simple streamline and increase arrow size

    >>> from plotly.figure_factory import create_streamline
    >>> import plotly.graph_objects as go
    >>> import numpy as np
    >>> import math

    >>> # Add data
    >>> x = np.linspace(-3, 3, 100)
    >>> y = np.linspace(-3, 3, 100)
    >>> Y, X = np.meshgrid(x, y)
    >>> u = -1 - X**2 + Y
    >>> v = 1 + X - Y**2
    >>> u = u.T  # Transpose
    >>> v = v.T  # Transpose

    >>> # Create streamline
    >>> fig = create_streamline(x, y, u, v, arrow_scale=.1)
    >>> fig.show()

    Example 2: from nbviewer.ipython.org/github/barbagroup/AeroPython

    >>> from plotly.figure_factory import create_streamline
    >>> import numpy as np
    >>> import math

    >>> # Add data
    >>> N = 50
    >>> x_start, x_end = -2.0, 2.0
    >>> y_start, y_end = -1.0, 1.0
    >>> x = np.linspace(x_start, x_end, N)
    >>> y = np.linspace(y_start, y_end, N)
    >>> X, Y = np.meshgrid(x, y)
    >>> ss = 5.0
    >>> x_s, y_s = -1.0, 0.0

    >>> # Compute the velocity field on the mesh grid
    >>> u_s = ss/(2*np.pi) * (X-x_s)/((X-x_s)**2 + (Y-y_s)**2)
    >>> v_s = ss/(2*np.pi) * (Y-y_s)/((X-x_s)**2 + (Y-y_s)**2)

    >>> # Create streamline
    >>> fig = create_streamline(x, y, u_s, v_s, density=2, name='streamline')

    >>> # Add source point
    >>> point = go.Scatter(x=[x_s], y=[y_s], mode='markers',
    ...                    marker_size=14, name='source point')

    >>> fig.add_trace(point) # doctest: +SKIP
    >>> fig.show()
    )densityarrow_scalelines)r   r   modeZclosest)Z	hovermode)datalayout)r   Zvalidate_equal_lengthr   Zvalidate_positive_scalars_Streamlinesum_streamlinesget_streamline_arrowsr   ZScatterZLayoutZFigure)r   r   uvr   angler   kwargsstreamline_xstreamline_yZarrow_xZarrow_y
streamliner   r   r   r   r   create_streamline'   s@    I
              r$   c                   @   sP   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd ZdS )r   zB
    Refer to FigureFactory.create_streamline() for docstring
    c                 K   s  t || _t || _t || _t || _|| _|| _td| | _	| jd | jd  | _
| jd | jd  | _| j| _| j| _t | j	| j	f| _t| jt| j	d  | _t| jt| j	d  | _g | _| j| jd | jd   | _| j| jd | jd   | _t | jd | jd  | _|  jt| j9  _|  jt| j9  _g | _g | _|   |  \}	}
|  \}}d S )N   r   r      )r	   arrayr   r   r   r   r   r   intr   delta_xdelta_yval_xval_yZzerosblankr   float	spacing_x	spacing_ytrajectoriessqrtspeedst_xst_yget_streamlinesr   r   )selfr   r   r   r   r   r   r   r    r!   r"   arrows_xarrows_yr   r   r   __init__   s2    z_Streamline.__init__c                 C   s$   t || j d t || j d fS )zQ
        Set up positions for trajectories to be used with rk4 function.
              ?)r)   r0   r1   )r8   xiyir   r   r   	blank_pos   s    z_Streamline.blank_posc                 C   s   t |tjr*|tj| _|tj| _nt|| _t|| _|| j| jf }|| j| jd f }|| jd | jf }|| jd | jd f }|| j }|| j }	|d|  ||  }
|d|  ||  }|
d|	  ||	  S )zK
        Set up for RK4 function, based on Bokeh's streamline code
        r   )	
isinstancer	   ZndarrayZastyper)   r   r   r,   r-   )r8   ar=   r>   Za00Za01Za10Za11ZxtZytZa0Za1r   r   r   value_at   s    

z_Streamline.value_atc                    s  fdd}fdd}fdd g g  fdd}||||\}}}||||\}	}
}||	 }|
d	d	d
 |dd	  }|d	d	d
 |dd	  }t |dk rd	S |dkr܈||\}}dj||f< ||fS tD ]\}}dj||f< qd	S d	S )z
        RK4 forward and back trajectories from the initial conditions.

        Adapted from Bokeh's streamline -uses Runge-Kutta method to fill
        x and y trajectories then checks length of traj (s in units of axes)
        c                    sD   d   j| | }   j| |}   j| |}|| || fS Ng      ?rB   r4   r   r   r=   r>   Zdt_dsZuivir8   r   r   f   s    z$_Streamline.rk4_integrate.<locals>.fc                    sH   d   j| | }   j| |}   j| |}| | | | fS rC   rD   rE   rG   r   r   g   s    z$_Streamline.rk4_integrate.<locals>.gc                    sD   d|   kot  jd k n  oBd|  ko>t  jd k S   S )Nr   r   )r   r   r   )r=   r>   rG   r   r   <lambda>       z+_Streamline.rk4_integrate.<locals>.<lambda>c                    s  d}d}| }|} ||\}}g }	g }
 ||r|	| |
| z||||\}}||d| |  |d| |  \}}||d| |  |d| |  \}}||||  |||  \}}W n tk
r   Y qY nX |||d|  d|  |  d 7 }|||d|  d|  |  d 7 } ||s8q||7 } ||\}}||ksd||krj||f dkrdj||f< | | |}|}nq|dkr(qq(||	|
fS )Ng{Gz?r   r<   r'   g      @r   )r?   append
IndexErrorr.   )x0y0rH   Zdsstotalr=   r>   xbybxf_trajyf_trajZk1xZk1yZk2xZk2yZk3xZk3yZk4xZk4yZnew_xbZnew_ybcheckr8   Z
xb_changesZ
yb_changesr   r   rk4   sD    

&&"$$

z&_Streamline.rk4_integrate.<locals>.rk4Nr&   r   g?r   )r   r?   r.   zip)r8   rN   rO   rH   rI   rW   ZsfrS   rT   sbZxb_trajZyb_trajrP   Zx_trajZy_trajZinitxbZinitybrQ   rR   r   rU   r   rk4_integrate   s(    %z_Streamline.rk4_integratec                 C   sj   |dk s$|| j ks$|dk s$|| j kr(dS | j||f dkrf| || j || j }|dk	rf| j| dS )z
        Integrate trajectories

        :param (int) xb: results of passing xi through self.blank_pos
        :param (int) xy: results of passing yi through self.blank_pos

        Calculate each trajectory based on rk4 integrate method.
        r   N)r   r.   rZ   r0   r1   r2   rL   )r8   rQ   rR   tr   r   r   traj  s    
$z_Streamline.trajc                    s$  t  jd D ]p}t  jd|  D ]X} || |  ||  jd |   |||    jd | ||  q$q fdd jD  _ fdd jD  _t t jD ]*} j|   j|<  j| t	j
 qt t jD ]*} j|   j|<  j| t	j
 qdS )z=
        Get streamlines by building trajectory set.
        r'   r   c                    s*   g | ]"}t |d   j  jd   qS )r   )r	   r(   r*   r   .0r[   rG   r   r   
<listcomp>0  s    z/_Streamline.get_streamlines.<locals>.<listcomp>c                    s*   g | ]"}t |d   j  jd  qS )r   r   )r	   r(   r+   r   r]   rG   r   r   r_   3  s    N)r   r   r\   r2   r5   r6   r   tolistrL   r	   nan)r8   indentr=   r   r   rG   r   r7   %  s$    

z_Streamline.get_streamlinesc                 C   s  t t| j}t t| j}t t| j}t t| j}tt| jD ]}| j| tt| j| d  ||< | j| tt| j| d d  ||< | j| tt| j| d  ||< | j| tt| j| d d  ||< qN|| }|| }t  }t jddd t 	|| }	t jf | |	| j
 }
|	| j
 }t |
| j }t |
| j }t || j }t || j }t t|}t t|}t t|}t t|}tt|D ]}|| dkr(|| ||  ||< || ||  ||< || ||  ||< || ||  ||< nP|| ||  ||< || ||  ||< || ||  ||< || ||  ||< qt t|}t j|dd< t ||||g}t |}|d}| }t ||||g}t |}|d}| }||fS )a_  
        Makes an arrow for each streamline.

        Gets angle of streamline at 1/3 mark and creates arrow coordinates
        based off of user defined angle and arrow_scale.

        :param (array) st_x: x-values for all streamlines
        :param (array) st_y: y-values for all streamlines
        :param (angle in radians) angle: angle of arrowhead. Default = pi/9
        :param (float in [0,1]) arrow_scale: value to scale length of arrowhead
            Default = .09
        :rtype (list, list) arrows_x: x-values to create arrowhead and
            arrows_y: y-values to create arrowhead
           r   ignore)divideinvalidr   NF)r	   emptyr   r5   r6   r   r)   ZgeterrZseterrZarctanr   cosr   sinra   matrixr(   flattenr`   )r8   Zarrow_end_xZarrow_end_yZarrow_start_xZarrow_start_yr   Zdif_xZdif_yZorig_errZstreamline_angZang1Zang2Zseg1_xZseg1_yZseg2_xZseg2_yZpoint1_xZpoint1_yZpoint2_xZpoint2_yspacer9   r:   r   r   r   r   ?  sd    $$






z!_Streamline.get_streamline_arrowsc                 C   s    t | jg }t | jg }||fS )a  
        Makes all streamlines readable as a single trace.

        :rtype (list, list): streamline_x: all x values for each streamline
            combined into single list and streamline_y: all y values for each
            streamline combined into single list
        )sumr5   r6   )r8   r!   r"   r   r   r   r     s    z_Streamline.sum_streamlinesN)__name__
__module____qualname____doc__r;   r?   rB   rZ   r\   r7   r   r   r   r   r   r   r      s   !NOr   )
__future__r   mathZplotlyr   r   Zplotly.figure_factoryr   Zplotly.graph_objsr   Z
get_moduler	   r   pir$   objectr   r   r   r   r   <module>   s   
  
_