
     iK                         d Z ddlZddlZddlZ	 ddlZddlZn# e$ r  ed          dw xY wddlZd Z	d Z
d Zd Zd Z	 dd
ZdS )aW  Streamplots (2D)  --- :mod:`MDAnalysis.visualization.streamlines`
=================================================================

:Authors: Tyler Reddy and Matthieu Chavent
:Year: 2014
:Copyright: Lesser GNU Public License v2.1+


The :func:`generate_streamlines` function can generate a 2D flow field from a
MD trajectory, for instance, lipid molecules in a flat membrane. It can make
use of multiple cores to perform the analyis in parallel (using
:mod:`multiprocessing`).

See Also
--------
MDAnalysis.visualization.streamlines_3D : streamplots in 3D


.. autofunction:: generate_streamlines

    Nz2d streamplot module requires: matplotlib.path for its path.Path.contains_points method. The installation instructions for the matplotlib module can be found here: http://matplotlib.org/faq/installing_faq.html?highlight=installc                 H    | \  }}}}t           j        ||||||f         }|S )u  Produce a 2D grid for the simulation system.

    The grid is based on the tuple of Cartesian Coordinate limits calculated in
    an earlier step.

    Parameters
    ----------
    tuple_of_limits : tuple
        ``x_min, x_max, y_min, y_max``
    grid_spacing : float
        grid size in all directions in ångström

    Returns
    -------
    grid : array
       ``numpy.mgrid[x_min:x_max:grid_spacing, y_min:y_max:grid_spacing]``
    )npmgrid)tuple_of_limitsgrid_spacingx_minx_maxy_miny_maxgrids          n/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/visualization/streamlines.pyproduce_gridr   @   s6    $ "1E5%8E%,eE,.FFGDK    c                 $   | \  }}t          j        ||f          }g }g }d}||j        d         dz
  k     rd}||j        d         dz
  k     r}|||f         }	||dz   |f         }
||dz   |dz   f         }|||dz   f         }|                    |	|
||g           |                    ||g           |dz  }||j        d         dz
  k     }|dz  }||j        d         dz
  k     t          j        ||          }t          j        ||          }||||gS )aK  Split the grid into blocks of vertices.

    Take the overall `grid` for the system and split it into lists of
    square vertices that can be distributed to each core.

    Parameters
    ----------
    grid : numpy.array
        2D array
    num_cores : int
        number of partitions to generate

    Returns
    -------
    list_square_vertex_arrays_per_core : array of arrays
         split the list of square vertices
         ``[[v1,v2,v3,v4],[v1,v2,v3,v4],...,...]`` into roughly equally-sized
         sublists to be distributed over the available cores on the system
    list_parent_index_values : array of arrays
         arrays of `[[row, column], [row, column], ...]`` for each core
    current_row : int
         last row + 1
    current_column : int
         last column + 1

    Note
    ----
    Limited to 2D for now.

    r      )r   dstackshapeappendarray_split)r   	num_coresx_arrayy_arraygrid_vertex_cartesian_arraylist_all_squares_in_gridlist_parent_index_valuescurrent_columncurrent_row!bottom_left_vertex_current_square"bottom_right_vertex_current_squaretop_right_vertex_current_squaretop_left_vertex_current_square"list_square_vertex_arrays_per_cores                 r   
split_gridr#   W   s   B GW"$)Wg,>"?"? 	  	  N
6<Q?!C
C
C 7=a@1DDD0K+1- 2M"K/2. /J"K!O3/+ .Ia/.* %++5632	   %++[.,IJJJ1K1 7=a@1DDD2 	!; 6<Q?!C
C
C@ *, )* *&  "~ )    	+ 	 r   c                     g }| D ]]}t           j                            |          }t          j        |                    |                    }|                    |           ^|S )a7  
    Produce a list of indices for particles of interest in the current frame.
    The list is ordered according to the order of the squares in the grid.
    Each entry in the list is a tuple of indices for the particles in that square.
    The list is the same length as the number of squares in the grid.
    )
matplotlibpathPathr   wherecontains_pointsr   )vertex_coord_list%relevant_particle_coordinate_array_xylist_indices_point_in_polygonsquare_verticespath_objectindex_list_in_polygons         r   1_produce_list_indices_point_in_polygon_this_framer0      st     %'!, D D o**?;; "''(MNN!
 !
 	&,,-BCCCC((r   c                     g }| D ]\}|d         j         dk    s|                    d           )||         }t          j        |d          }|                    |           ]|S )a  
    Produce a list of centroids for the particles in the current frame.
    The list is ordered according to the order of the squares in the grid.
    Each entry in the list is a numpy array of the centroid coordinates for the particles in that square.
    The list is the same length as the number of squares in the grid.
    If there are no particles in a square, the entry is None.
    r   N)axis)sizer   r   average)list_indices_in_polygonr+   list_centroids_this_frameindices"current_coordinate_array_in_squarecurrent_square_indices_centroids         r   "_produce_list_centroids_this_framer:      s     !#* N N
!##%,,T2222 6g> / /1j2/ / /+ &,,-LMMMM$$r   c                    t          j        | |          }g }	g }
|j        D ]4}|j        |k     r|                    |          j        dddf         }t          ||          }t          ||          }|
rt          |
|          }g }t          ||	          D ][\  }}|||	                    ddg           !|	                    t          j        ||                                                     \t          j        |          }t          j        || |          }|dd         }	|dd         }
n|dd         }	|dd         }
|j        |k    r n6t          t          ||                                                    S )z}Run the analysis on one core.

    The code to perform on a given core given the list of square vertices assigned to it.
    .Nr   )
MDAnalysisUniverse
trajectoryframeselect_atoms	positionsr0   r:   zipr   r   subtracttolistarraycliplist)topology_file_pathtrajectory_file_path#list_square_vertex_arrays_this_coreMDA_selectionstart_frame	end_framereconstruction_index_listmaximum_delta_magnitudeuniverse_objectlist_previous_frame_centroidslist_previous_frame_indicestsr+   "list_indices_in_squares_this_frame$list_centroids_in_squares_this_frame7list_centroids_this_frame_using_indices_from_last_framexy_deltas_to_writesquare_1_centroidsquare_2_centroids                      r   per_core_workr[      s"    !)0 O %'!"$( F F8k!!0?0L0L1
 1

C"H1- >35  	+ /25  	- (/	P
 3/9  D "$8;G-9 9  4!#4 %,0A0I&--q!f5555&---/@  &((    "$*<!=!= "$"(('" " 5QQQ7 * +MQQQ*O'' 5QQQ7 * +MQQQ*O'8iE  -/A/H/H/J/JKKLLLr   maximumc                    |dk    rt          j                    }n|}t          j        dd           g fd}||||	f}t	          ||          }t          ||          \  }}}}t          j        |          }t          ||          D ]*\  }}|                    t          | |||||||
f|           +|
                                 |                                 t          j        ||f          }t          j        ||f          }D ]\  }}|                                d	         }|                                d
         }t          |d	                   |
k    rd	|||f<   n|d	         |||f<   t          |d
                   |
k    rd	|||f<   |d
         |||f<   t          j        |dz  |dz  z             }t          j        |          }t          j        |          }||||fS )a`  Produce the x and y components of a 2D streamplot data set.

    Parameters
    ----------
    topology_file_path : str
            Absolute path to the topology file
    trajectory_file_path : str
            Absolute path to the trajectory file. It will normally be desirable
            to filter the trajectory with a tool such as GROMACS
            :program:`g_filter` (see :footcite:p:`Chavent2014`)
    grid_spacing : float
            The spacing between grid lines (angstroms)
    MDA_selection : str
            MDAnalysis selection string
    start_frame : int
            First frame number to parse
    end_frame : int
            Last frame number to parse
    xmin : float
            Minimum coordinate boundary for x-axis (angstroms)
    xmax : float
            Maximum coordinate boundary for x-axis (angstroms)
    ymin : float
            Minimum coordinate boundary for y-axis (angstroms)
    ymax : float
            Maximum coordinate boundary for y-axis (angstroms)
    maximum_delta_magnitude : float
            Absolute value of the largest displacement tolerated for the
            centroid of a group of particles ( angstroms). Values above this
            displacement will not count in the streamplot (treated as
            excessively large displacements crossing the periodic boundary)
    num_cores : int or 'maximum' (optional)
            The number of cores to use. (Default 'maximum' uses all available
            cores)

    Returns
    -------
    dx_array : array of floats
            An array object containing the displacements in the x direction
    dy_array : array of floats
            An array object containing the displacements in the y direction
    average_displacement : float
            :math:`\frac{\sum\sqrt[]{dx^2 + dy^2}}{N}`
    standard_deviation_of_displacement : float
            standard deviation of :math:`\sqrt[]{dx^2 + dy^2}`

    Examples
    --------
    Generate 2D streamlines and plot::

        import matplotlib, matplotlib.pyplot, np
        import MDAnalysis, MDAnalysis.visualization.streamlines

        u1, v1, average_displacement, standard_deviation_of_displacement =
            MDAnalysis.visualization.streamlines.generate_streamlines('testing.gro', 'testing_filtered.xtc',
                    grid_spacing=20, MDA_selection='name PO4', start_frame=2, end_frame=3,
                    xmin=-8.73000049591, xmax= 1225.96008301,
                    ymin= -12.5799999237, ymax=1224.34008789,
                    maximum_delta_magnitude=1.0, num_cores=16)
        x = np.linspace(0, 1200, 61)
        y = np.linspace(0, 1200, 61)
        speed = np.sqrt(u1*u1 + v1*v1)
        fig = matplotlib.pyplot.figure()
        ax = fig.add_subplot(111, aspect='equal')
        ax.set_xlabel('x ($\AA$)')
        ax.set_ylabel('y ($\AA$)')
        ax.streamplot(x, y, u1, v1, density=(10,10), color=speed, linewidth=3*speed/speed.max())
        fig.savefig('testing_streamline.png',dpi=300)

    .. image:: testing_streamline.png


    References
    ----------
    .. footbibliography::


    See Also
    --------
    MDAnalysis.visualization.streamlines_3D.generate_streamlines_3d

    r\   warnraise)alloverc                 2                         |            d S )N)extend)delta_arrayparent_list_deltass    r   log_result_to_parentz2generate_streamlines.<locals>.log_result_to_parent  s    !!+.....r   )r   r   )r   r   )argscallbackr   r      )multiprocessing	cpu_countr   seterrr   r#   PoolrC   apply_asyncr[   closejoinzerosrE   abssqrtr4   std) rI   rJ   r   rL   rM   rN   xminxmaxyminymaxrP   r   rf   r   r   r"   r   
total_rowstotal_columnspoolvertex_sublistindex_sublistdx_arraydy_arrayindex_arrayrd   index_1index_2displacement_arrayaverage_displacement"standard_deviation_of_displacementre   s                                   @r   generate_streamlinesr   A  s   B I#-//			I&w''''/ / / / / T4.O'l  D 		222* 	**D),*,D* * 
 
% 	"$'	 * 	 	
 	
 	
 	
 	JJLLLIIKKKx]344Hx]344H 		8 8 	 $$&&q)$$&&q){1~"999)*HWg%&&)4QHWg%&{1~"999)*HWg%&&)4QHWg%&& 1x{!:;;:&899)+0B)C)C& 	*	 r   )r\   )__doc__rj   numpyr   scipyr%   matplotlib.pathImportErrorr=   r   r#   r0   r:   r[   r    r   r   <module>r      s  0 *         	   
+	J 
       .Z Z Z|) ) )&% % %6[M [M [MT k k k k k ks    +