
    g8                         d dl Z d dlmZmZ d dlmZ d dlmZ  ej                  d      Z	d Z
de j                  dz  d	fd
Z G d de      Zy)    N)
exceptionsoptional_imports)utils)
graph_objsnumpyc                 b   t         du rt        d      t        t        |       dz
        D ]4  }| |dz      | |   z
  | d   | d   z
  z
  dkD  s!t	        j
                  d       t        t        |      dz
        D ]4  }||dz      ||   z
  |d   |d   z
  z
  dkD  s!t	        j
                  d       y)	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   PlotlyError)xyindexs      ^/var/www/dash_apps/app1/venv/lib/python3.12/site-packages/plotly/figure_factory/_streamline.pyvalidate_streamliner   
   s     
U{JKKs1vz" uqy\AeH$1!5?((C 
 s1vz" uqy\AeH$1!5?((C     r	   	   g
ףp=
?c           	         t        j                  | |       t        j                  ||       t        | |       t        j                  ||       t	        | ||||||      j                         \  }}	t	        | ||||||      j                         \  }
}t        j                  d||
z   |	|z   dd|}|g}t        j                  d      }t        j                  ||      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   modeclosest)	hovermode)datalayout )r   validate_equal_lengthr   validate_positive_scalars_Streamlinesum_streamlinesget_streamline_arrowsr   ScatterLayoutFigure)r   r   uvr   angler   kwargsstreamline_xstreamline_yarrow_xarrow_y
streamliner   r   s                  r   create_streamliner1   %   s    R 
1%	1%1	##GM!,	1aGUK"o L, #	1aGUK GW ## 

 L7$:LRJ <D3F$v66r   c                   @    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zy
)r"   zB
    Refer to FigureFactory.create_streamline() for docstring
    c                 ~   t         j                  |      | _        t         j                  |      | _        t         j                  |      | _        t         j                  |      | _        || _        || _        t        d|z        | _	        | j                  d   | j                  d   z
  | _
        | j                  d   | j                  d   z
  | _        | j                  | _        | j                  | _        t         j                  | j                  | j                  f      | _        t!        | j                        t#        | j                  dz
        z  | _        t!        | j                        t#        | j                  dz
        z  | _        g | _        | j                  | j                  d   | j                  d   z
  z  | _        | j
                  | j                  d   | j                  d   z
  z  | _        t         j+                  | j                  dz  | j
                  dz  z         | _        | xj                  t!        | j                        z  c_        | xj
                  t!        | j                        z  c_        g | _        g | _        | j3                          | j5                         \  }	}
| j7                         \  }}y )N   r	   r      )r
   arrayr   r   r(   r)   r*   r   intr   delta_xdelta_yval_xval_y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_ys                r   __init__z_Streamline.__init__   s   !!!!
&2<(vvay466!9,vvay466!9,VV
VV
 XXt||T\\:;
TVVuT\\A-='>>TVVuT\\A-='>> 466":q	12466":q	12WWTVVQY23
 	#dff+#dff+		%)%9%9%;"l!779(r   c                 n    t        || j                  z  dz         t        || j                  z  dz         fS )zQ
        Set up positions for trajectories to be used with rk4 function.
              ?)r8   r@   rA   )rH   xiyis      r   	blank_posz_Streamline.blank_pos   s5     R$..(C/0#rDNN7Jc6Q2RSSr   c                 `   t        |t        j                        r5|j                  t              | _        |j                  t              | _        n t	        |      | _        t	        |      | _        || j                  | j                  f   }|| j                  | j                  dz   f   }|| j                  dz   | j                  f   }|| j                  dz   | j                  dz   f   }|| j                  z
  }|| j                  z
  }	|d|z
  z  ||z  z   }
|d|z
  z  ||z  z   }|
d|	z
  z  ||	z  z   S )zK
        Set up for RK4 function, based on Bokeh's streamline code
        r	   )	
isinstancer
   ndarrayastyper8   r   r   r;   r<   )rH   arN   rO   a00a01a10a11xtyta0a1s               r   value_atz_Streamline.value_at   s    b"**%YYs^DFYYs^DFRDJRDJ

DJJ&'

DJJN*+

Q

*+

Q

Q./$**_$**_AF^cBh&AF^cBh&QV}rBw&&r   c                      fd} fd} fdg g  fd} ||||      \  }}} ||||      \  }	}
}||	z   }|
ddd   |dd z   }|ddd   |dd z   }t        |      dk  ry|dkD  r* j                  ||      \  }}d j                  ||f<   ||fS t              D ]  \  }}d	 j                  ||f<    y)
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                     dj                  j                  | |      z  }j                  j                  | |      }j                  j                  | |      }||z  ||z  fS Ng      ?r^   rD   r(   r)   rN   rO   dt_dsuivirH   s        r   fz$_Streamline.rk4_integrate.<locals>.f   s]    $--

B;;Etvvr2.Btvvr2.B:rEz))r   c                     dj                  j                  | |      z  }j                  j                  | |      }j                  j                  | |      }| |z  | |z  fS ra   rb   rc   s        r   gz$_Streamline.rk4_integrate.<locals>.g   sa    $--

B;;Etvvr2.Btvvr2.B3;e++r   c                     d| cxk  xr t        j                        dz
  k  nc xr& d|cxk  xr t        j                        dz
  k  S c S )Nr   r	   )r   r   r   )rN   rO   rH   s     r   <lambda>z+_Streamline.rk4_integrate.<locals>.<lambda>   s>    R 9#dff+/ 9 Wa2>WDFFVW>W >W r   c                    d}d}| }|}j                  ||      \  }}g }	g }
 ||      rC|	j                  |       |
j                  |       	  |||      \  }} ||d|z  |z  z   |d|z  |z  z         \  }} ||d|z  |z  z   |d|z  |z  z         \  }} ||||z  z   |||z  z         \  }}|||d|z  z   d|z  z   |z   z  dz  z  }|||d|z  z   d|z  z   |z   z  dz  z  } ||      sn||z  }j                  ||      \  }}||k7  s||k7  rMj                  ||f   dk(  r8dj                  ||f<   j                  |       j                  |       |}|}nn|dkD  rn ||      rC||	|
fS # t        $ r Y w xY w)Ng{Gz?r   rM   r6   g      @r	   )rP   append
IndexErrorr>   )x0y0rg   dsstotalrN   rO   xbybxf_trajyf_trajk1xk1yk2xk2yk3xk3yk4xk4ynew_xbnew_ybcheckrH   
xb_changes
yb_changess                        r   rk4z&_Streamline.rk4_integrate.<locals>.rk4   s   BFBB^^B+FBGGB-r"r" RyHC cBhn!4b38c>6IJHC cBhn!4b38c>6IJHC b3hR#X>HC bC!c'MAG3c9:S@@bC!c'MAG3c9:S@@R}"!%B!7R<6R<zz&&.1Q656

66>2"))&1"))&1##A:5 B-6 7G++' " s   A E5 5	F FNr5   r	   g?r   )r   rP   r>   zip)rH   ro   rp   rg   ri   r   sfru   rv   sbxb_trajyb_trajrr   x_trajy_trajinitxbinitybrs   rt   r   r   r   s   `                  @@@r   rk4_integratez_Streamline.rk4_integrate   s    	*	, Y

#	,J  #2r1~GW"2r1~GWb2,2,v;?C<!^^B3NFF)*DJJvv~&6>!j*5 'B%&

2r6"'r   c                    |dk  s#|| j                   k\  s|dk  s|| j                   k\  ry| j                  ||f   dk(  rK| j                  || j                  z  || j                  z        }|| j
                  j                  |       yyy)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>   r   r@   rA   rB   rm   )rH   rs   rt   ts       r   trajz_Streamline.traj  s     6R4<<'26R4<<5G::b"f"""2#6T^^8KLA}!!((+  #r   c                    t        | j                  dz        D ]  }t        | j                  d|z  z
        D ]v  }| j                  ||z   |       | j                  ||z   | j                  dz
  |z
         | j                  |||z          | j                  | j                  dz
  |z
  ||z          x  | j                  D cg c]7  }t        j                  |d         | j                  z  | j                  d   z   9 c}| _        | j                  D cg c]7  }t        j                  |d         | j                  z  | j                  d   z   9 c}| _        t        t        | j                              D ]X  }| j                  |   j                         | j                  |<   | j                  |   j                  t        j                         Z t        t        | j                              D ]X  }| j                  |   j                         | j                  |<   | j                  |   j                  t        j                         Z yc c}w c c}w )z=
        Get streamlines by building trajectory set.
        r6   r	   r   N)r   r   r   rB   r
   r7   r9   r   rE   r:   r   rF   r   tolistrm   nan)rH   indentrN   r   r   s        r   rG   z_Streamline.get_streamlines#  s    DLLA-. 	BFDLL1v:56 B		"v+v.		"v+t||a'7&'@A		&"v+.		$,,*V3R&[A	B	B @D?P?P
:;BHHQqTNT\\)DFF1I5
	 @D?P?P
:;BHHQqTNT\\)DFF1I5
	 3tyy>* 	,E#yy/668DIIeIIe##BFF+	, 3tyy>* 	,E#yy/668DIIeIIe##BFF+	,

s    <I	<Ic                    t         j                  t        | j                              }t         j                  t        | j                              }t         j                  t        | j                              }t         j                  t        | j                              }t        t        | j                              D ]  }| j                  |   t        t        | j                  |         dz           ||<   | j                  |   t        t        | j                  |         dz        dz
     ||<   | j                  |   t        t        | j                  |         dz           ||<   | j                  |   t        t        | j                  |         dz        dz
     ||<    ||z
  }||z
  }t         j                         }t         j                  dd       t         j                  ||z        }	t        j                  di | |	| j                  z   }
|	| j                  z
  }t         j                  |
      | j                  z  }t         j                  |
      | j                  z  }t         j                  |      | j                  z  }t         j                  |      | j                  z  }t         j                  t        |            }t         j                  t        |            }t         j                  t        |            }t         j                  t        |            }t        t        |            D ]{  }||   dk\  r9||   ||   z
  ||<   ||   ||   z
  ||<   ||   ||   z
  ||<   ||   ||   z
  ||<   D||   ||   z   ||<   ||   ||   z   ||<   ||   ||   z   ||<   ||   ||   z   ||<   } t         j                  t        |            }t         j                  |dd t         j                  ||||g      }|j!                  d      }|j#                         }t         j                  ||||g      }|j!                  d      }|j#                         }||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Fr   )r
   emptyr   rE   rF   r   r8   geterrseterrarctanr*   cosr   sinr   r7   flattenr   )rH   arrow_end_xarrow_end_yarrow_start_xarrow_start_yr   dif_xdif_yorig_errstreamline_angang1ang2seg1_xseg1_yseg2_xseg2_ypoint1_xpoint1_ypoint2_xpoint2_yspacerI   rJ   s                          r   r$   z!_Streamline.get_streamline_arrows=  s    hhDII0hhDII0#dii.2#dii.23tyy>* 	E!%5!1#c$))E:J6Ka6O2P!QK#'99U#3S5)*Q./14$M%  "&5!1#c$))E:J6Ka6O2P!QK#'99U#3S5)*Q./14$M% 	 m+m+99;
		8	455=1
		H,, 0 00 0 00 0 00 0 0088SZ)88SZ)88SZ)88SZ)3u:& 
	EEU|q "-e"4ve}"D"-e"4ve}"D"-e"4ve}"D"-e"4ve}"D"-e"4ve}"D"-e"4ve}"D"-e"4ve}"D"-e"4ve}"D
	E #h-)66a 88X{HeDE##C(??$ 88X{HeDE##C(??$!!r   c                 b    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
        )sumrE   rF   )rH   r,   r-   s      r   r#   z_Streamline.sum_streamlines  s/     499b)499b)\))r   N)__name__
__module____qualname____doc__rK   rP   r^   r   r   rG   r$   r#   r   r   r   r"   r"      s5    :BT'(L\,",4K"Z
*r   r"   )mathplotlyr   r   plotly.figure_factoryr   plotly.graph_objsr   
get_moduler
   r   pir1   objectr"   r   r   r   <module>r      sO     / ' (   )8 1$\7~P*& P*r   