
     i                        d Z ddlZddlZddlZddlZddlZddlZddlZddlZ	ddl
mZ ddlmZ ddlmZmZmZ dZdZd	Zd
 Zd Zd Zi Zi ZdZ G d de          Z G d dee          Z G d de          Z G d de          Z d Z! G d de          Z" G d dee"          Z# G d de#          Z$ G d de#          Z% G d  d!e%          Z& G d" d#e%          Z' G d$ d%e%          Z( G d& d'e#          Z) G d( d)e#          Z* G d* d+e#          Z+ G d, d-e#          Z, G d. d/e#          Z- G d0 d1e-          Z. G d2 d3e-          Z/ G d4 d5e#          Z0 G d6 d7e#          Z1 G d8 d9e#          Z2 G d: d;e#          Z3 G d< d=e#          Z4 G d> d?e#          Z5 G d@ dAe#          Z6 G dB dCe#          Z7 G dD dEe#          Z8 G dF dGe#          Z9 G dH dIe#          Z: G dJ dKe:          Z; G dL dMe:          Z< G dN dOe#          Z= G dP dQe#          Z> G dR dSe#          Z? G dT dUe=          Z@ G dV dWe>          ZA G dX dYe>          ZB G dZ d[e>          ZC G d\ d]e#          ZD G d^ d_e#          ZE G d` dae          ZF eF            ZG ejH        eI dbdcd          ZJeJejK        eJjI        <   de ZLdS )fa  Atom selection Hierarchy --- :mod:`MDAnalysis.core.selection`
=============================================================

This module contains objects that represent selections. They are
constructed and then applied to the group.

In general, :meth:`Parser.parse` creates a :class:`Selection` object
from a selection string. This :class:`Selection` object is then passed
an :class:`~MDAnalysis.core.groups.AtomGroup` through its
:meth:`~MDAnalysis.core.groups.AtomGroup.apply` method to apply the
``Selection`` to the ``AtomGroup``.

This is all invisible to the user through the
:meth:`~MDAnalysis.core.groups.AtomGroup.select_atoms` method of an
:class:`~MDAnalysis.core.groups.AtomGroup`.

    N   )unique_int_1d)	distances)SelectionErrorNoDataErrorSelectionWarningz-?\d*\.?\d*(?:e[-+]?\d+)?z-?\d+z\s*(?:[:-]| to )\s*c                 6    | t           v p| t          v p| dv p| du S )a  Is val a selection keyword?

    Returns False on any of the following strings:
      - keys in SELECTIONDICT (tokens from Selection objects)
      - keys in OPERATIONS (tokens from LogicOperations)
      - (Parentheses)
      - The value `None` (used as EOF in selection strings)
    ()N)_SELECTIONDICT_OPERATIONS)vals    c/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/MDAnalysis/core/selection.py
is_keywordr   D   s9     	~ 	+	*	 $;	    c                     g }t          | d                   sQ|                                 }|                    |                    d                     t          | d                   Q|S )a  Pop tokens from the left until you hit a keyword

    Keywords can be escaped with a backslash to allow their use as names,
    e.g. '\protein'

    Parameters
    ----------
    tokens : collections.deque
        deque of strings, some tokens some not

    Returns
    -------
    values : list of strings
        All non keywords found until a keyword was hit

    Note
    ----
    This function pops the values from the deque

    Examples
    --------
    grab_not_keywords(['H', 'and','resname', 'MET'])
    >>> ['H']

    grab_not_keywords(['H', 'Ca', 'N', 'and','resname', 'MET'])
    >>> ['H', 'Ca' ,'N']

    grab_not_keywords(['and','resname', 'MET'])
    >>> []
    r   \)r   popleftappendremoveprefix)tokensvaluesr   s      r   grab_not_keywordsr   U   si    > F## .nnc&&t,,--- ## . Mr   c                    g d}| r|                      d          }||v rx	 d          d| d|                      d           d<   n# t          $ rC d                               d| dd                    |            }t          d|           w xY wrD|dd         dv s'|d         d	k    st	          fd
|D                       rd          d| d<   n                    |           | S )a5  Join range values that are separated by whitespace

    Parameters
    ----------
    values: list
        list of value strings

    Returns
    -------
    values: list of strings

    Examples
    --------
    join_separated_values(['37', 'to', '22'])
    >>> ['37 to 22']

    .. versionadded:: 2.0.0
    )to:-r    zInvalid expression given: Nr   )z--r   r   c              3   N   K   | ]}d                               |          V   dS )r   N)endswith).0x_valuess     r   	<genexpr>z(join_separated_values.<locals>.<genexpr>   s5      ??q72;''**??????r   )pop
IndexErrorjoinr   anyr   )r   
DELIMITERSvgivenr%   s       @r   join_separated_valuesr.   |   s^   & G!J
 JJqMM
??K!(BBqBB6::a==BB K K K88G,,EEqEE388F3C3CEE$%I%%I%IJJJK  	bqbE\!!ts{{????J?????  %R[..1..GBKKNN1!  " Ns   &A	 	AB)updatingc                       e Zd Zd ZdS )_Operationmetac                     t                               t           |||           	 | t          |d         <   d S # t          $ r Y d S w xY wNtoken)type__init__r   KeyErrorclsnamebases	classdicts       r   r6   z_Operationmeta.__init__   sV    dD%333	.1K	'*+++ 	 	 	DD	s   6 
AAN__name__
__module____qualname__r6    r   r   r1   r1      s#            r   r1   c                       e Zd Zd Zd ZdS )LogicOperationc                 0    || _         || _        || _        d S N)rsellselparser)selfrG   rF   rH   s       r   r6   zLogicOperation.__init__   s    		r   c                 X     | j         |i |                    | j        j                  S N)sorted_applyasuniquerH   rL   rI   argskwargss      r   applyzLogicOperation.apply   /    t{D+F++44DK<N4OOOr   Nr>   r?   r@   r6   rS   rA   r   r   rC   rC      s7          
P P P P Pr   rC   )	metaclassc                       e Zd ZdZdZd ZdS )AndOperationand   c                     | j                             |          }| j                            |          }t          j        |j        |j                  }||         S rE   )rF   rS   rG   npisinindices)rI   grouprF   rG   masks        r   rN   zAndOperation._apply   sI    yu%%yu%% wt|T\22Dzr   Nr>   r?   r@   r4   
precedencerN   rA   r   r   rX   rX      s-        EJ    r   rX   c                       e Zd ZdZdZd ZdS )OrOperationorrZ   c                    | j                             |          }| j                            |          }t          j        |j        |j                                      t          j                  }|j        j	        |         S rE   )
rG   rS   rF   r\   union1dr^   astypeint32universeatoms)rI   r_   rG   rF   idxs        r   rN   zOrOperation._apply   s_    yu%%yu%% jt|44;;BHEE~#C((r   Nra   rA   r   r   rd   rd      s-        EJ) ) ) ) )r   rd   c                 F     t          j                    fd            }|S )zb
    Decorator to return empty AtomGroups from the apply() function
    without evaluating it
    c                 F    t          |          dk    r|S  | |          S )Nr   )len)rI   r_   funcs     r   rN   z%return_empty_on_apply.<locals>._apply   s)    u::??LtD%   r   )	functoolswraps)rp   rN   s   ` r   return_empty_on_applyrs      s:     _T! ! ! ! !
 Mr   c                       e Zd Zd ZdS )_Selectionmetac                     t                               t           |||           	 | t          |d         <   | t          |d                                         <   d S # t          $ r Y d S w xY wr3   )r5   r6   r   lowerr7   r8   s       r   r6   z_Selectionmeta.__init__   sq    dD%333	14N9W-.9<N9W-3355666 	 	 	DD	s   2A 
A&%A&Nr=   rA   r   r   ru   ru      s#            r   ru   c                       e Zd Zd Zd ZdS )	Selectionc                     || _         d S rE   )rH   )rI   rH   r   s      r   r6   zSelection.__init__   s    r   c                 X     | j         |i |                    | j        j                  S rK   rM   rP   s      r   rS   zSelection.apply   rT   r   NrU   rA   r   r   ry   ry      s7          P P P P Pr   ry   c                       e Zd ZdZd ZdS )AllSelectionallc                 6    ||j         j        u r|S |d d          S rE   )rj   rk   rI   r_   s     r   rN   zAllSelection._apply  s&    
 EN(((LQQQxr   N)r>   r?   r@   r4   rN   rA   r   r   r}   r}     s(        E    r   r}   c                        e Zd Z fdZ xZS )UnarySelectionc                     t                                          ||           |                    | j                  }|| _        d S rE   superr6   parse_expressionrb   sel)rI   rH   r   r   	__class__s       r   r6   zUnarySelection.__init__  s=    (((%%do66r   )r>   r?   r@   r6   __classcell__r   s   @r   r   r     s8                r   r   c                       e Zd ZdZdZd ZdS )NotSelectionnot   c                     | j                             |          }|t          j        |j        |j                            S rE   )r   rS   r\   r]   r^   )rI   r_   notsels      r   rN   zNotSelection._apply  s3    &&bgemV^<<<==r   Nra   rA   r   r   r   r     s-        EJ> > > > >r   r   c                       e Zd ZdZdZd ZdS )GlobalSelectionglobalr   c                 T    | j                             |j        j                  j        S rE   )r   rS   rj   rk   uniquer   s     r   rN   zGlobalSelection._apply"  s    x~~en233::r   Nra   rA   r   r   r   r     s-        EJ; ; ; ; ;r   r   c                        e Zd ZdZdZdZd ZdS )ByResSelectionz
    Selects all atoms that are in the same segment and residue as selection

    .. versionchanged:: 1.0.0
       Use :code:`"resindices"` instead of :code:`"resids"` (see #2669 and #2672)
    byres   c                     | j                             |          }t          |j                  }t	          j        |j        |          }||         S rE   )r   rS   r   
resindicesr\   r]   )rI   r_   res
unique_resr`   s        r   rN   zByResSelection._apply1  sB    hnnU##"3>22
wu'44T{r   N)r>   r?   r@   __doc__r4   rb   rN   rA   r   r   r   r   &  s9          EJ    r   r   c                   <     e Zd ZdZdZ fdZed             Z xZS )AroundSelectionaroundr   c                     t                                          ||           |j        | _        t          |                                          | _        |                    | j                  | _        d S rE   	r   r6   periodicfloatr   cutoffr   rb   r   rI   rH   r   r   s      r   r6   zAroundSelection.__init__=  Z    (((FNN,,--**4?;;r   c                    g }| j                             |          }|t          j        |j        |j                            }|r|s|g          S | j        r|j        nd }t          j        |j	        |j	        | j
        |d          }|j        dk    rt          j        |d d df                   }|t          j        |t          j                           S NFboxreturn_distancesr   r   dtype)r   rS   r\   r]   r^   r   
dimensionsr   capped_distance	positionsr   sizesortasarrayint64)rI   r_   r^   r   sysr   pairss          r   rN   zAroundSelection._applyC  s    hnnU##RWU]CK8889 	# 	r7N"&-9eT)MMK"
 
 
 :>>geAAAqDk**G2:gRX66677r   	r>   r?   r@   r4   rb   r6   rs   rN   r   r   s   @r   r   r   9  s^        EJ< < < < < 8 8 8 8 8 8 8r   r   c                   <     e Zd ZdZdZ fdZed             Z xZS )SphericalLayerSelectionsphlayerr   c                 :   t                                          ||           |j        | _        t          |                                          | _        t          |                                          | _        |                    | j                  | _	        d S rE   
r   r6   r   r   r   inRadiusexRadiusr   rb   r   r   s      r   r6   z SphericalLayerSelection.__init___  s    (((fnn..//fnn..//**4?;;r   c                 
   g }| j                             |          }t          |          dk    r|g          S | j        r|j        nd }|                                                    dd                              t          j	                  }t          j        ||j        | j        | j        |d          }|j        dk    rt          j        |d d df                   }|t          j        |t          j                           S )Nr   r   rZ   F)
min_cutoffr   r   r   )r   rS   ro   r   r   center_of_geometryreshaperh   r\   float32r   r   r   r   r   r   r   r   r   rI   r_   r^   r   r   refr   s          r   rN   zSphericalLayerSelection._applyf  s    hnnU##s88q==9"&-9eT$$&&..q!44;;BJGG)OM}"
 
 
 :>>geAAAqDk**GRZrx88899r   r   r   s   @r   r   r   [  s^        EJ< < < < < : : : : : : :r   r   c                   <     e Zd ZdZdZ fdZed             Z xZS )IsoLayerSelectionisolayerr   c                 :   t                                          ||           |j        | _        t          |                                          | _        t          |                                          | _        |                    | j                  | _	        d S rE   r   r   s      r   r6   zIsoLayerSelection.__init__  r   r   c                    g }| j                             |          }|t          j        |j        |j                            }|r|s|g          S | j        r|j        nd }t          j        |j	        |j	        | j
        |d          }t          j        |j	        |j	        | j        |d          }|j        dk    rt          j        t          j        |d d df                             }|j        dk    rMt          j        t          j        |d d df                             }	|t          j        ||	                    }n|}|t          j        |t          j                           S r   )r   rS   r\   r]   r^   r   r   r   r   r   r   r   r   r   r   r   r   )
rI   r_   r^   r   r   r   pairs_outerpairs_innersys_ind_outersys_ind_inners
             r   rN   zIsoLayerSelection._apply  sc   hnnU##RWU]CK8889 	# 	r7N"&-9eT/MMM"
 
 
  /MMM"
 
 
 aGBIk!!!Q$.?$@$@AAM!## "	+aaad2C(D(D E E')N)N(NO'2:gRX66677r   r   r   s   @r   r   r   }  s^        EJ< < < < < !8 !8 !8 !8 !8 !8 !8r   r   c                   <     e Zd ZdZdZ fdZed             Z xZS )SphericalZoneSelectionsphzoner   c                     t                                          ||           |j        | _        t          |                                          | _        |                    | j                  | _        d S rE   r   r   s      r   r6   zSphericalZoneSelection.__init__  r   r   c                    g }| j                             |          }t          |          dk    r|g          S | j        r|j        nd }|                                                    dd                              t          j	                  }t          j        ||j        | j        |d          }|j        dk    rt          j        |d d df                   }|t          j        |t          j                           S )Nr   r   rZ   Fr   r   )r   rS   ro   r   r   r   r   rh   r\   r   r   r   r   r   r   r   r   r   r   s          r   rN   zSphericalZoneSelection._apply  s    hnnU##s88q==9"&-9eT$$&&..q!44;;BJGG)$+3
 
 
 :>>geAAAqDk**GRZrx88899r   r   r   s   @r   r   r     s^        EJ< < < < < : : : : : : :r   r   c                   $    e Zd Zed             ZdS )CylindricalSelectionc                    | j                             |          }t          |          dk    r|g          S |j        |                                z
  }| j        r|j        |j        d d         }| j        | j        z
  }d| j	        z  |d         k    r1t          d                    d| j	        z  |d                             d| j	        z  |d         k    r1t          d                    d| j	        z  |d                             ||d         k    r)t          d                    ||d                             t          j        |j        dd          dk              r.||d d         t          j        ||d d         z            z  z  }n|j        j        j        j        }||d         t          j        |d d df         |d         d         z            d d d f         z  z  }||d         t          j        |d d df         |d         d         z            d d d f         z  z  }||d         t          j        |d d df         |d         d         z            d d d f         z  z  }|d d df         | j        k    |d d df         | j        k     z  }||         }||         }|d d df         dz  |d d df         dz  z   }|| j	        dz  k     }	 ||| j        dz  k    z  }n# t(          $ r Y nw xY w||         S )	Nr   rZ   r   zThe diameter of the cylinder selection ({:.3f}) is larger than the unit cell's x dimension ({:.3f}). Can only do selections where it is smaller or equal.r   zThe diameter of the cylinder selection ({:.3f}) is larger than the unit cell's y dimension ({:.3f}). Can only do selections where it is smaller or equal.zThe total length of the cylinder selection in z ({:.3f}) is larger than the unit cell's z dimension ({:.3f}). Can only do selections where it is smaller or equal.g     V@)r   rS   ro   r   r   r   r   zmaxzminr   NotImplementedErrorformatr\   r~   rintrj   
trajectorytstriclinic_dimensionsr   AttributeError)	rI   r_   r   vecsr   cyl_z_hheighttriboxr`   radiis	            r   rN   zCylindricalSelection._apply  sC   hnnU##s88q==9!7!7!9!99= "	P!1!9"2A2&C I	1M4= 3q6))) va$-/Q88	   4= 3q6))) va$-/Q88	   s1v%%) vmSV44	   ve&qrr*d233 PBQB"'$RaR."9"999 25Jq	BGDAJ1,E$F$Fqqq$w$OOOq	BGDAJ1,E$F$Fqqq$w$OOOq	BGDAJ1,E$F$Fqqq$w$OOO QQQT
TY&41:	+ABDzd QQQT
a$qqq!t*/1t}a''	EDM1,,,DD 	 	 	D	 T{s   K, ,
K98K9N)r>   r?   r@   rs   rN   rA   r   r   r   r     s.        : : : : :r   r   c                   &     e Zd ZdZdZ fdZ xZS )CylindricalZoneSelectioncyzoner   c                    t                                          ||           |j        | _        t          |                                          | _        t          |                                          | _        t          |                                          | _        |                    | j	                  | _
        d S rE   )r   r6   r   r   r   r   r   r   r   rb   r   r   s      r   r6   z!CylindricalZoneSelection.__init__  s    (((fnn..//&..**++	&..**++	**4?;;r   r>   r?   r@   r4   rb   r6   r   r   s   @r   r   r     sB        EJ< < < < < < < < <r   r   c                   &     e Zd ZdZdZ fdZ xZS )CylindricalLayerSelectioncylayerr   c                    t                                          ||           |j        | _        t          |                                          | _        t          |                                          | _        t          |                                          | _        t          |                                          | _        |	                    | j
                  | _        d S rE   )r   r6   r   r   r   r   r   r   r   r   rb   r   r   s      r   r6   z"CylindricalLayerSelection.__init__  s    (((fnn..//fnn..//&..**++	&..**++	**4?;;r   r   r   s   @r   r   r     sB        EJ< < < < < < < < <r   r   c                   8     e Zd ZdZ fdZed             Z xZS )PointSelectionpointc                    t                                          ||           |j        | _        t          |                                          }t          |                                          }t          |                                          }t          j        |||gt
          j                  | _        t          |                                          | _	        d S Nr   )
r   r6   r   r   r   r\   arrayr   r   r   )rI   rH   r   r$   yzr   s         r   r6   zPointSelection.__init__&  s    (((&..""##&..""##&..""##8Q1IRZ888FNN,,--r   c                 (   g }| j         r|j        nd }t          j        | j        d d d f         |j        | j        |d          }|j        dk    rt          j	        |d d df                   }|t          j
        |t          j                           S r   )r   r   r   r   r   r   r   r   r\   r   r   r   )rI   r_   r^   r   r   s        r   rN   zPointSelection._apply/  s    "&-9eT)HT111WOK"
 
 
 :>>geAAAqDk**GRZrx88899r   )r>   r?   r@   r4   r6   rs   rN   r   r   s   @r   r   r   #  sY        E. . . . . : : : : : : :r   r   c                   (     e Zd ZdZ fdZd Z xZS )AtomSelectionatomc                     t                                          ||           |                                | _        t	          |                                          | _        |                                | _        d S rE   )r   r6   r   segidintresidr:   r   s      r   r6   zAtomSelection.__init__D  s\    (((^^%%
))**
NN$$			r   c                     ||j         | j        k             }|r||j        | j        k             }|r||j        | j        k             }|j        S rE   )namesr:   residsr   segidsr   r   )rI   r_   subs      r   rN   zAtomSelection._applyJ  sS    EK49,- 	0cjDJ./C 	0cjDJ./Czr   r>   r?   r@   r4   r6   rN   r   r   s   @r   r   r   A  sL        E% % % % %      r   r   c                   ,     e Zd ZdZdZ fdZd Z xZS )BondedSelectionbondedr   c                     t                                          ||           |                    | j                  | _        d S rE   r   r   s      r   r6   zBondedSelection.__init__W  s8    (((**4?;;r   c                 P   | j                             |          }|j        st          j        d           |g          S |j        }t          j        |j                                                  }g }|	                    |d d df         t          j
        |d d df         |                              |	                    |d d df         t          j
        |d d df         |                              t          j        | }|j        j        t          j        |                   S )NzBonded selection has 0 bondsr   r   )r   rS   bondswarningswarnr^   r\   r   
to_indicesr   r]   rg   rj   rk   r   )rI   r_   grpgrpidxbixrl   s         r   rN   zBondedSelection._apply[  s    hnnU##{ 	M89999 hu{--//00

3qqq!t9RWSAY778999

3qqq!t9RWSAY778999j#~#BIcNN33r   )r>   r?   r@   r4   rb   r6   rN   r   r   s   @r   r  r  S  sQ        EJ< < < < <4 4 4 4 4 4 4r   r  c                   (     e Zd ZdZ fdZd Z xZS )SelgroupSelectionr_   c                 6   t                                          ||           |                                }|t          v r"t	          d                    |                    	 |j        |         | _        d S # t          $ r d| }t          |          d w xY w)NzJThe '{}' keyword is reserved and cannot be used as a selection group name.zFailed to find group: )
r   r6   r   _RESERVED_KWARGS	TypeErrorr   	selgroupsr  r7   
ValueError)rI   rH   r   grpnameerrmsgr   s        r   r6   zSelgroupSelection.__init__u  s    (((..""&&&228&//  	/'0DHHH 	/ 	/ 	/7g77FV$$$.	/s   $A8 8 Bc                 Z    t          j        |j        | j        j                  }||         S rE   )r\   r]   r^   r  )rI   r_   r`   s      r   rN   zSelgroupSelection._apply  s$    wu}dh&677T{r   r  r   s   @r   r  r  r  sL        E/ / / / /      r   r  c                   8     e Zd ZdZ fdZed             Z xZS )SingleCharSelectionzbfor when an attribute is just a single character, eg RSChirality

    .. versionadded:: 2.1.0
    c                     t                                          ||           t          |          }|s(t          d                    |d                             || _        d S NzUnexpected token '{0}'r   r   r6   r   r  r   r   rI   rH   r   valsr   s       r   r6   zSingleCharSelection.__init__  _    ((( (( 	I5<<VAYGGHHHr   c                 p    t          || j                  }t          j        || j                  }||         S rE   )getattrfieldr\   r]   r   )rI   r_   attrr`   s       r   rN   zSingleCharSelection._apply  s0    udj))wtT[))T{r   r>   r?   r@   r   r6   rs   rN   r   r   s   @r   r  r    s^         
           r   r  c                   8     e Zd ZdZ fdZed             Z xZS )_ProtoStringSelectionz}Selections based on text attributes

    .. versionchanged:: 1.0.0
        Supports multiple wildcards, based on fnmatch
    c                     t                                          ||           t          |          }|s(t          d                    |d                             || _        d S r  r   r!  s       r   r6   z_ProtoStringSelection.__init__  r#  r   c                 d   t          |j        j        | j                  }g }|j                                        D ]:\  }t          fd| j        D                       r|                    |           ;|j	        t          || j
                           }|t          j        ||                   S )Nc              3   B   K   | ]}t          j        |          V  d S rE   )fnmatchfnmatchcase)r#   r   nms     r   r&   z/_ProtoStringSelection._apply.<locals>.<genexpr>  s0      GGC7&r3//GGGGGGr   )r%  rj   	_topologyr&  namedictitemsr*   r   r   nmidxlevelr\   r]   )rI   r_   nmattrmatchesixr4  r0  s         @r   rN   z_ProtoStringSelection._apply  s     14:>>o++-- 	# 	#FBGGGG4;GGGGG #r""" WUDJ778RWUG,,--r   r(  r   s   @r   r*  r*    s^              . . . . . . .r   r*  c                        e Zd ZdZdZdZd ZdS )AromaticSelectionz}Select aromatic atoms.

    Aromaticity is available in the `aromaticities` attribute and is made
    available through RDKitaromaticaromaticitiesc                     ||j                  S rE   )r<  r   s     r   rN   zAromaticSelection._apply  s    U())r   N)r>   r?   r@   r   r4   r&  rN   rA   r   r   r:  r:    s9         
 EE* * * * *r   r:  c                   ,     e Zd ZdZdZ fdZd Z xZS )SmartsSelectionat  Select atoms based on SMARTS queries.

    Uses RDKit to run the query and converts the result to MDAnalysis.
    Supports chirality.

    .. versionchanged:: 2.2.0
       ``rdkit_wargs`` and ``smarts_kwargs`` can now be passed to control
       the behaviour of the RDKit converter and RDKit's ``GetSubstructMatches``
       respectively.
       The default ``maxMatches`` value passed to ``GetSubstructMatches`` has
       been changed from ``1000`` to ``max(1000, n_atoms * 10)`` in order to
       limit cases where too few matches were generated. A warning is now also
       thrown if ``maxMatches`` has been reached.
    smartsc                 
   t                                          ||           g }ddd}|d         dv st          |d                   s|d         dv r5||d         xx         dz  cc<   |d         dk    r|d         |d         k     rnH|                                }|                    |           |d         dv rt          |d                   d                    |          | _        |j        | _        |j        | _        d S )Nr   r
   r   r   r    )	r   r6   r   r   r   r)   patternrdkit_kwargssmarts_kwargs)rI   rH   r   rC  counterr   r   s         r   r6   zSmartsSelection.__init__  s   ((( ""Qi:%%Zq	-B-B%ayJ&&q	"""a'""" !9##(E(E..""CNN3 Qi:%%Zq	-B-B% www''"/#1r   c           	         	 ddl m} n# t          $ r t          d          w xY w|                    | j                  }|st          | j        d           |j        di | j        }| j        	                    dd           | j        	                    dt          d	t          |          d
z                        |j        |fi | j        }t          |          | j        d         k    rt          j        d           t          j        d |D                       }t          j        t%          |j                  |          }||         S )Nr   )ChemzRDKit is required for SMARTS-based atom selection but it's not installed. Try installing it with 
conda install -c conda-forge rdkitz is not a valid SMARTS queryRDKITuseChiralityT
maxMatchesi  
   aJ  Your smarts-based atom selection returned the maxnumber of matches. This indicates that not allmatching atoms were selected. When callingatom_group.select_atoms(), the default valueof maxMatches is max(100, len(atom_group * 10)). To fix this, add the following argument to select_atoms: 
smarts_kwargs={maxMatches: <higher_value>}c                     g | ]	}|D ]}|
S rA   rA   )r#   matchrl   s      r   
<listcomp>z*SmartsSelection._apply.<locals>.<listcomp>  s%    GGGUGG#SGGGGr   )rI  )rdkitrH  ImportErrorMolFromSmartsrC  r  
convert_torD  rE  
setdefaultmaxro   GetSubstructMatchesr  r  r\   r   r]   rangen_atoms)rI   r_   rH  rC  molr7  r^   r`   s           r   rN   zSmartsSelection._apply  s|   	""""""" 	 	 	5  	 $$T\22 	NLLLMMMe<<$*;<<%%nd;;;%%lCc%jj2o4N4NOOO)#)'HHT5GHHw<<4-l;;;M=	 	 	 )GGgGGGHHwuU]++W55T{s   	 #)r>   r?   r@   r   r4   r6   rN   r   r   s   @r   r?  r?    sX          E2 2 2 2 26             r   r?  c                   8     e Zd ZdZdZ fdZd Zd Zd Z xZ	S )ResidSelectionzSelect atoms based on numerical fields

    Allows the use of ':', '-' and 'to' to specify a range of values
    For example

      resid 1:10
    r   c                 ^   t                                          ||           t          |          }|s(t          d                    |d                             t          |          }g }g }|D ]+}t          j        dt           ddz   |          }|4|	                                }t          |d                   |d         f}	d}
ndt           dt           }|dt           dz  }t          j        ||          }|"t          d	                    |                    |	                                }t          |d                   |d         f}	t          |d
                   |d         f}
|                    |	           |                    |
           -|| _        || _        d S )NUnexpected token: '{0}'r   r   r   z(\w?)$r   )NNz)(\w?)zFailed to parse value: {0}r   rZ   )r   r6   r   r  r   r.   rerN  INT_PATTERNgroupsr   RANGE_PATTERNr   lowersuppers)rI   rH   r   r   rc  rb  r   m1r   rw   upperrC  selranger   s                r   r6   zResidSelection.__init__'  s   ((("6** 	J6==fQiHHIII&v..  	! 	!C,k,,,y8#>>B:iikkCFSV+" BkAA-AA3{33338GS11#$%A%H%H%M%MNNNoo''CFSV+CFSV+MM%   MM%    r   c                 \   |j         }	 |j        }ng# t          t          f$ rS d }t	          d | j        D                       st	          d | j        D                       rd}t          |          d Y nw xY w||                     ||          }n| 	                    |          }||         S )Nc              3   &   K   | ]}|d          V  dS r   NrA   r#   r,   s     r   r&   z(ResidSelection._apply.<locals>.<genexpr>T  s&      --A1Q4------r   c              3   &   K   | ]}|d          V  dS ri  rA   rj  s     r   r&   z(ResidSelection._apply.<locals>.<genexpr>T  s7       5 5!5 5 5 5 5 5r   z@Selection specified icodes, while the topology doesn't have any.)
r  icodesr   r   r*   rc  rb  r  _sel_with_icodes_sel_without_icodes)rI   r_   r"  rl  r  r`   s         r   rN   zResidSelection._applyL  s    |	3\FF, 
	3 
	3 
	3F------- 3 5 5"k5 5 5 2 2 3(  !((d23 3
	3 ~((v66DD++D11DT{s    A!A54A5c                     t          j        t          |          t                    }t	          | j        | j                  D ](\  \  }}\  }}|||k    }|||k    z  }n||k    }||z  })|S r   )r\   zerosro   boolziprc  rb  )rI   r"  r`   u_resid_l_residthismasks          r   rn  z"ResidSelection._sel_without_icodesd  s    xD		...*-dk4;*G*G 	 	&LWa,7A"7?DGO+7?HDDr   c                    t          j        t          |          t                    }t	          | j        | j                  D ]\  \  }}\  }}|||k    r||k    }|||k    z  }|||k    z  }n||k    }	|	||k    z  }	|	}t          j        |dz   |          }
t          |
          r$|
d         |
d         }}||k    }|||k    z  }||z  }||k    }|||k    z  }||z  }n||k    }|||k    z  }||z  }|S )Nr   r   r   r   )r\   rp  ro   rq  rr  rc  rb  arange)rI   r"  rl  r`   rs  u_icoderu  l_icoderv  	startmaskmidmid_begmid_endmidmaskendmasks                  r   rm  zResidSelection._sel_with_icodess  sP   xD		...69K7
 7
 &	 &	2Wg 2' " g%%#wH' 11H' 11HH !%I7!22I(H )GaK99C3xx ,+.q63r7"&'/47?2 G+ #goGv00G'HH7?Fg--HDDr   )
r>   r?   r@   r   r4   r6   rN   rn  rm  r   r   s   @r   r[  r[    sw          E# # # # #J  0  , , , , , , ,r   r[  c                   (     e Zd ZdZ fdZd Z xZS )BoolSelectionzSelection for boolean valuesc                 2   t                                          ||           t          |          }|sdg}g | _        |D ]U}|                                }|dk    rd}n|dk    rd}nt          d| d          | j                            |           Vd S )NtruefalseFT'zB' is an invalid value for boolean selection. Use 'True' or 'False')r   r6   r   r   rw   r  r   )rI   rH   r   r   r   rw   bvalr   s          r   r6   zBoolSelection.__init__  s    ((("6** 	XF 	% 	%CIIKKE& , , , ,  
 Kt$$$$	% 	%r   c                     t          || j                  }t          j        t	          |          t
                    }| j        D ]}|||k    z  }||         S r   )r%  r&  r\   rp  ro   rq  r   )rI   r_   r"  r`   r   s        r   rN   zBoolSelection._apply  sX    udj))xD		...; 	  	 CDCKDDT{r   )r>   r?   r@   r   r6   rN   r   r   s   @r   r  r    sM        &&% % % % %*      r   r  c                   H     e Zd ZdZdZde de de dZeZ	 fdZ
d Z xZS )RangeSelectionzRange selection for int valuesr   r   r   c                    t                                          ||           |j        | _        |j        | _        t	          |          }|s(t          d                    |d                             t          |          }g }g }|D ]}	 |                     |          }d }nk# t
          $ r^ t          j
        | j        |          }	|	sd| }
t          |
          d t          | j        |	                                          \  }}Y nw xY w|                    |           |                    |           || _        || _        d S )Nr]  r   zFailed to parse number: )r   r6   rtolatolr   r  r   r.   r   r^  rN  rC  mapr`  r   rb  rc  )rI   rH   r   r   rc  rb  r   rw   re  rf  r  r   s              r   r6   zRangeSelection.__init__  s]   (((K	K	"6** 	J6==fQiHHIII&v.. 	! 	!C	B

3 B B B8DL#66 7===F$V,,$6"4:x/@/@AAuuuB MM%   MM%    s   B%%A%DDc                    t          j        t          |          t                    }t	          || j                  | j        z   }t          | j        | j	                  D ]"\  }}|||k    }|||k    z  }n||k    }||z  }#||         S r   )
r\   rp  ro   rq  r%  r&  value_offsetrr  rc  rb  )rI   r_   r`   r"  re  rw   rv  s          r   rN   zRangeSelection._apply  s    xE

$///udj))D,==T[99 	 	LE5 5=DEM)5=HDDT{r   )r>   r?   r@   r   r  r_  ra  rC  r   r   r6   rN   r   r   s   @r   r  r    sx        ((L>+>>>>>>>GE    @      r   r  c                   4    e Zd ZdZde de de dZeZd Z	dS )FloatRangeSelectionz Range selection for float valuesr   r   c           
         t          j        t          |          t                    }t	          || j                  | j        z   }t          | j        | j	                  D ]y\  }}|||k    }|||k    z  }n]|dz
  |dz   }}d}	d|	 d| j
         d| d| d	}
t          j        |
t          	           t          j        ||| j        | j        
          }||z  }z||         S )Nr   r   z7https://docs.python.org/3.8/tutorial/floatingpoint.htmlzUsing float equality to select atoms is not recommended because of inherent limitations in representing numbers on computers (see zA for more). Instead, we recommend using a range to select, e.g. 'r    z to zt'. If you still want to compare floats, use the `atol` and `rtol` keywords to modify the tolerance for `np.isclose`.)categoryr  r  )r\   rp  ro   rq  r%  r&  r  rr  rc  rb  r4   r  r  r   iscloser  r  )rI   r_   r`   r"  re  rw   rv  lowhighfpmsgs              r   rN   zFloatRangeSelection._apply  s,   xE

$///udj))D,==T[99 	 	LE5 5=DEM)!AIuqyTN( ')( (
 )-
( (
 69( (
 ?C( ( (  c,<====:%didi   HDDT{r   N)
r>   r?   r@   r   FLOAT_PATTERNra  rC  r   r   rN   rA   r   r   r  r    sN        **B-BB-BB-BBBGE    r   r  c                       e Zd ZdZdZdZdS )ByNumSelectionbynumr^   r   N)r>   r?   r@   r4   r&  r  rA   r   r   r  r    s        EELLLr   r  c                   $    e Zd ZdZdZh dZd ZdS )ProteinSelectiona  Consists of all residues with  recognized residue names.

    Recognized residue names in :attr:`ProteinSelection.prot_res`.

      * from the CHARMM force field::
         awk '/RESI/ {printf "'"'"%s"'"',",$2 }' top_all27_prot_lipid.rtf

      * manually added special CHARMM, OPLS/AA and Amber residue names.

    See Also
    --------
    :func:`MDAnalysis.lib.util.convert_aa_code`


    .. versionchanged:: 1.0.1
       prot_res changed to set (from numpy array)
       performance improved by ~100x on larger systems
    protein>h   ACEALAARGASFASHASNASPCMECYMCYSCYXDABGLHGLNGLUGLYHIDHIEHIPHISHSDHSEHSPHYPILELEULYNLYSMETMSENMEORNPHEPROQLNSERTHRTRPTYRVALALADARGNASN1ASPHCALACARGCASFCASNCASPCCYSCCYXCGLNCGLUCGLYCHIDCHIECHIPCILECLEUCLYSCMETCPHECPROCSERCTHRCTRPCTYRCVALCYS1CYS2CYSHGLUHHIS1HIS2HISAHISBHISDHISEHISHLYSHNALANARGNASNNASPNCYSNCYXNGLNNGLUNGLYNHIDNHIENHIPNILENLEUNLYSNMETNPHENPRONSERNTHRNTRPNTYRNVALPGLUc                      |j         j        j        } fd|j                                        D             }|j        |j                 }|t          j        ||                   S )Nc                 ,    g | ]\  }}|j         v |S rA   prot_resr#   r0  r8  rI   s      r   rO  z+ProteinSelection._apply.<locals>.<listcomp>  s4     
 
 
RT]"" """r   )	rj   r1  resnamesr2  r3  r4  r   r\   r]   )rI   r_   resname_attrr7  r4  s   `    r   rN   zProteinSelection._apply  sp    ~/8
 
 
 
(17799
 
 
 "5#34RWUG,,--r   N)r>   r?   r@   r   r4   r  rN   rA   r   r   r  r  #  sI         & Ep p pHd. . . . .r   r  c                   $    e Zd ZdZdZh dZd ZdS )NucleicSelectiona  All atoms in nucleic acid residues with recognized residue names.

    Recognized residue names:

    * from the CHARMM force field ::
        awk '/RESI/ {printf "'"'"%s"'"',",$2 }' top_all27_prot_na.rtf
    * recognized: 'ADE', 'URA', 'CYT', 'GUA', 'THY'
    * recognized (CHARMM in Gromacs): 'DA', 'DU', 'DC', 'DG', 'DT'

    .. versionchanged:: 0.8
       additional Gromacs selections
    .. versionchanged:: 1.0.1
       nucl_res changed to set (from numpy array)
       performance improved by ~100x on larger systems
    nucleic>"   ACGTUDADCDGDTRARCRGRUADECYTDA3DA5DC3DC5DG3DG5DT3DT5GUARA3RA5RC3RC5RG3RG5RU3RU5THYURAc                      |j         j        j        }|j        |j                 } fd|j                                        D             }t          j        ||          }||         S )Nc                 ,    g | ]\  }}|j         v |S rA   nucl_resr  s      r   rO  z+NucleicSelection._apply.<locals>.<listcomp>  s0     
 
 
BB$-<O<OB<O<O<Or   	rj   r1  r  r4  r   r2  r3  r\   r]   rI   r_   r  r4  r7  r`   s   `     r   rN   zNucleicSelection._apply  ss    >+4u/0
 
 
 
'06688
 
 
 wug&&T{r   N)r>   r?   r@   r   r4   r9  rN   rA   r   r   r  r    sF           E# # #HJ	 	 	 	 	r   r  c                   $    e Zd ZdZdZh dZd ZdS )WaterSelectiona5  All atoms in water residues with recognized water residue names.

    Recognized residue names:

    * recognized 3 Letter resnames: 'H2O', 'HOH', 'OH2', 'HHO', 'OHH'
        'TIP', 'T3P', 'T4P', 'T5P', 'SOL', 'WAT'

    * recognized 4 Letter resnames: 'TIP2', 'TIP3', 'TIP4'

    .. versionadded:: 2.9.0
    water>   H2OHHOHOHOH2OHHSOLT3PT4PT5PTIPWATTIP2TIP3TIP4c                      |j         j        j        }|j        |j                 } fd|j                                        D             }t          j        ||          }||         S )Nc                 ,    g | ]\  }}|j         v |S rA   )	water_resr  s      r   rO  z)WaterSelection._apply.<locals>.<listcomp>"  s4     
 
 
RT^## ###r   r:  r;  s   `     r   rN   zWaterSelection._apply  ss    >+4u/0
 
 
 
$-3355
 
 

 wug&&T{r   N)r>   r?   r@   r   r4   rO  rN   rA   r   r   r=  r=    sE        
 
 E  I"    r   r=  c                   $    e Zd ZdZdZh dZd ZdS )BackboneSelectiona1  A BackboneSelection contains all atoms with name 'N', 'CA', 'C', 'O'.

    This excludes OT* on C-termini
    (which are included by, eg VMD's backbone selection).


    .. versionchanged:: 1.0.1
       bb_atoms changed to set (from numpy array)
       performance improved by ~100x on larger systems
    backbone>   r  NOCAc                     |j         j        j        }|j         j        j        } fd|j                                        D             }|j        |j                 }|t          j	        ||                   } fd|j                                        D             }|j        |j
                 }|t          j	        ||                   }|j        S )Nc                 ,    g | ]\  }}|j         v |S rA   bb_atomsr  s      r   rO  z,BackboneSelection._apply.<locals>.<listcomp>@  4     
 
 
RT]"" """r   c                 ,    g | ]\  }}|j         v |S rA   r  r  s      r   rO  z,BackboneSelection._apply.<locals>.<listcomp>I  0     
 
 
BB$-<O<OB<O<O<Or   rj   r1  r  r  r2  r3  r4  r8  r\   r]   r   r   rI   r_   	atomnamesr  name_matchesr4  resname_matchess   `      r   rN   zBackboneSelection._apply;      N,2	>+4
 
 
 
%.4466
 
 

 )bge\223
 
 
 
'06688
 
 
 u/0bge_556|r   Nr>   r?   r@   r   r4   rY  rN   rA   r   r   rQ  rQ  ,  s?        	 	 E$$$H    r   rQ  c                   $    e Zd ZdZdZh dZd ZdS )NucleicBackboneSelectiona6  Contains all atoms with name "P", "C5'", C3'", "O3'", "O5'".

    These atoms are only recognized if they are in a residue matched
    by the :class:`NucleicSelection`.


    .. versionchanged:: 1.0.1
       bb_atoms changed to set (from numpy array)
       performance improved by ~100x on larger systems
    nucleicbackbone>   C5'O3'O5'PC3'c                     |j         j        j        }|j         j        j        } fd|j                                        D             }|j        |j                 }|t          j	        ||                   } fd|j                                        D             }|j        |j
                 }|t          j	        ||                   }|j        S )Nc                 ,    g | ]\  }}|j         v |S rA   rX  r  s      r   rO  z3NucleicBackboneSelection._apply.<locals>.<listcomp>f  rZ  r   c                 ,    g | ]\  }}|j         v |S rA   r8  r  s      r   rO  z3NucleicBackboneSelection._apply.<locals>.<listcomp>o  r\  r   r]  r^  s   `      r   rN   zNucleicBackboneSelection._applya  rb  r   Nrc  rA   r   r   re  re  R  s?        	 	 E000H    r   re  c                   $    e Zd ZdZdZh dZd ZdS )BaseSelectionaB  Selection of atoms in nucleobases.

    Recognized atom names (from CHARMM):

     'N9', 'N7', 'C8', 'C5', 'C4', 'N3', 'C2', 'N1', 'C6',
     'O6','N2','N6', 'O2','N4','O4','C5M'


    .. versionchanged:: 1.0.1
       base_atoms changed to set (from numpy array)
       performance improved by ~100x on larger systems
    nucleicbase>   C2C4C5C6C8N1N2N3N4N6N7N9O2O4O6C5Mc                     |j         j        j        }|j         j        j        } fd|j                                        D             }|j        |j                 }|t          j	        ||                   } fd|j                                        D             }|j        |j
                 }|t          j	        ||                   }|j        S )Nc                 ,    g | ]\  }}|j         v |S rA   )
base_atomsr  s      r   rO  z(BaseSelection._apply.<locals>.<listcomp>  s4     
 
 
RT_$$ $$$r   c                 ,    g | ]\  }}|j         v |S rA   r8  r  s      r   rO  z(BaseSelection._apply.<locals>.<listcomp>  r\  r   r]  r^  s   `      r   rN   zBaseSelection._apply  rb  r   N)r>   r?   r@   r   r4   r  rN   rA   r   r   rp  rp  x  sE          E  J&    r   rp  c                   $    e Zd ZdZdZh dZd ZdS )NucleicSugarSelectionzContains all atoms with name C1', C2', C3', C4', O2', O4', O3'.


    .. versionchanged:: 1.0.1
       sug_atoms changed to set (from numpy array)
       performance improved by ~100x on larger systems
    nucleicsugar>   C1'C2'C4'O4'rk  c                     |j         j        j        }|j         j        j        } fd|j                                        D             }|j        |j                 }|t          j	        ||                   } fd|j                                        D             }|j        |j
                 }|t          j	        ||                   }|j        S )Nc                 ,    g | ]\  }}|j         v |S rA   )	sug_atomsr  s      r   rO  z0NucleicSugarSelection._apply.<locals>.<listcomp>  s4     
 
 
RT^## ###r   c                 ,    g | ]\  }}|j         v |S rA   r8  r  s      r   rO  z0NucleicSugarSelection._apply.<locals>.<listcomp>  r\  r   r]  r^  s   `      r   rN   zNucleicSugarSelection._apply  rb  r   N)r>   r?   r@   r   r4   r  rN   rA   r   r   r  r    s?          E333I    r   r  c            	            e Zd ZdZdZ edej        fdej        fdej	        fdej
        fdej        fdej        fg          Zd	Zddddddd
ZddddZ fdZd Z xZS )PropertySelectionzSome of the possible properties:
    x, y, z, radius, mass,

    .. versionchanged:: 2.0.0
        changed == operator to use np.isclose instead of np.equals.
        Added ``atol`` and ``rtol`` keywords to control ``np.isclose``
        tolerance.
    prop><>=<===!=)r  r  r  r  r  r  )r  r  r  r  r  r  r   r$   r   r   c                 h   t                                          ||           |                                }d}d}|dk    rd| _        |                                }nd| _        | j        D ]3}	 |                    |          \  }}|}||z   } n# t          $ r Y 0w xY w||                                }| j        D ]&}||v r |                    |          \  }}|r|}|} n'||                                }|| j        v r||}}| j        |         }|| _	        	 | j
        |         | _        |dk    r+t          j        | j        |j        |j                  | _        n># t           $ r1 d| d| j
                                         d	}	t          |	          dw xY wt%          |          | _        dS )
z~
        Possible splitting around operator:

        prop x < 5
        prop x< 5
        prop x <5
        prop x<5
        NabsTFr  r  zInvalid operator : 'z' Use one of : 'r  )r   r6   r   absolute_op_symbolssplitr  propsopposite_opsr  opsoperatorrq   partialr  r  r7   keysr   value)rI   rH   r   r  operr  possibler$   r   r  r   s             r   r6   zPropertySelection.__init__  s#    	(((~~5== DM>>##DD!DM ( 		 		Hzz(++1
 !|     <>>##D( 	 	H4zz(++1 #DE   =NN$$E DJ%D$T*D		 HTNDM t|| ) 1M&+! ! !  	/ 	/ 	/'t ' 'HMMOO' ' '  V$$$.	/ 5\\


s   /B
BBE   ;Fc                    	 t          || j        | j                           }nx# t          $ r: dt	          | j                                                   }t          |          d t          $ r) | j        | j                 }d| d}t          |          d w xY w	 dddd| j                 }|d d |f         }n# t          $ r Y nw xY w| j        rt          j
        |          }|                     || j                  }||         S )NzExpected one of zThis Universe does not contain z informationr   r   r   r  )r%  r  r  r7   listr  r   r   r  r\   r  r  r  )rI   r_   r   r  r'  colr`   s          r   rN   zPropertySelection._apply>  s7   	3UDJty$9::FF 	3 	3 	3ATZ__->->(?(?AAF ((d2 	3 	3 	3:di(DItIIIF ((d2	3
	$**495C AAAsF^FF  	 	 	D	
 = 	$VF^^F}}VTZ00T{s    # A5BB: :
CC)r>   r?   r@   r   r4   dictr\   greaterlessgreater_equal
less_equalr  	not_equalr  r  r  r  r6   rN   r   r   s   @r   r  r    s          E
$"*"'N2#$2=!2:2< 	
	 	C 5K
  L KkBBEB" B" B" B" B"H      r   r  c                        e Zd ZdZdZdZi ddddddddd	d
dddddddddddddddddddddd Z fd!Zd" Z xZ	S )#SameSelectionz
    Selects all atoms that have the same subkeyword value as any atom in selection

    .. versionchanged:: 1.0.0
       Map :code:`"residue"` to :code:`"resindices"` and :code:`"segment"` to
       :code:`"segindices"` (see #2669 and #2672)
    samer   fragmentNr$   r   r   residuer   segment
segindicesr:   r  r5   typesresnamer  r   r  r   r  massmasseschargechargesradiusr   bfactorbfactorsresnumresnumsc                 ~   t                                          ||           |                                }|| j        vr:t	          d                    || j                                                            || _        |                    d           |	                    | j
                  | _        || _        d S )Nz.Unknown same property : {0}Choose one of : {1}as)r   r6   r   
prop_transr  r   r  r  expectr   rb   r   )rI   rH   r   r  r   s       r   r6   zSameSelection.__init__v  s    (((~~t&&6$ 4 4 6 677  
 	d**4?;;			r   c                    | j                             |          }|s|g          S | j        dk    rBt          j        d |j                  }t          j        |j        |j                  }||         S 	 dddd| j                 }|j	        d d |f         }|j	        d d |f         t          j
        fd|D                                           d          }||         S # t          $ rP | j        | j                 }t          ||          }t          j        t          ||          |          }||         cY S w xY w)	Nr  c                     | |z   S rE   rA   )r$   r   s     r   <lambda>z&SameSelection._apply.<locals>.<lambda>  s
    QU r   r   r   r   r  c                 :    g | ]}t          j        |          S rA   )r\   r  )r#   r,   poss     r   rO  z(SameSelection._apply.<locals>.<listcomp>  s%    ???Qbja00???r   )axis)r   rS   r  rq   reduce	fragmentsr\   r]   r^   r   vstackr*   r7   r  r%  )	rI   r_   r   allfragsr`   pos_idxr"  attrnamer  s	           @r   rN   zSameSelection._apply  s^   hnnU## 	9 9
"" !'(:(:CMJJH75=(*:;;D;	AA..ty9G =G,D/!!!W*-C 9????$???@@DD!DLLD;  	 	 	 ty1H3))D775(33T::D;	s   4C# #AD=<D=)
r>   r?   r@   r   r4   rb   r  r6   rN   r   r   s   @r   r  r  W  s          EJDT 	T 	T	
 	< 	< 	 	 	: 	 	 	 	) 	' 	:  	)!J&          r   r  c                   B    e Zd ZdZi Zd Zd Z	 	 	 	 	 	 ddZd	 Zd
 Z	dS )SelectionParsera  A small parser for selection expressions.  Demonstration of
    recursive descent parsing using Precedence climbing (see
    http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm).  Transforms
    expressions into nested Selection tree.

    For reference, the grammar that we parse is ::

       E(xpression)--> Exp(0)
       Exp(p) -->      P {B Exp(q)}
       P -->           U Exp(q) | "(" E ")" | v
       B(inary) -->    "and" | "or"
       U(nary) -->     "not"
       T(erms) -->     segid [value]
                       | resname [value]
                       | resid [value]
                       | name [value]
                       | type [value]
    c                 H    t          j        | g|R i |}| j        |_        |S rE   )object__new___shared_state__dict__)r9   pkrI   s       r   r  zSelectionParser.__new__  s0    ~c+A+++++)r   c                     | j         d         |k    r| j                                          dS t          d                    | j         d         |                    )z#Anticipate and remove a given tokenr   z'Unexpected token: '{0}' Expected: '{1}'N)r   r   r   r   )rI   r4   s     r   r  zSelectionParser.expect  sY    ;q>U""K!!!!! 6$+a.%00  r   N:0yE>h㈵>Tc	                    || _         || _        || _        || _        |pi | _        |pi | _        || _        || _        |                    dd                              dd          }	t          j
        |	                                dgz             | _        |                     d          }
| j        d         -t          d                    | j        d                             |
S )a  Create a Selection object from a string.

        Parameters
        ----------
        selectstr : str
            The string that describes the selection
        selgroups : AtomGroups
            AtomGroups to be used in `group` selections
        periodic : bool, optional
            for distance based selections, whether to consider
            periodic boundary conditions
        atol : float, optional
            The absolute tolerance parameter for float comparisons.
            Passed to :func:`numpy.isclose`.
        rtol : float, optional
            The relative tolerance parameter for float comparisons.
            Passed to :func:`numpy.isclose`.
        sorted : bool, optional
            Whether to sorted the output AtomGroup.
        rdkit_kwargs : dict, optional
            Arguments passed to the RDKitConverter when using selection based
            on SMARTS queries
        smarts_kwargs : dict, optional
          Arguments passed internally to RDKit's `GetSubstructMatches
          <https://www.rdkit.org/docs/source/rdkit.Chem.rdchem.html#rdkit.Chem.rdchem.Mol.GetSubstructMatches>`_.

        Returns
        -------
        The appropriate Selection object.  Use the .apply method on
        this to perform the selection.

        Raises
        ------
        SelectionError
            If anything goes wrong in creating the Selection object.


        .. versionchanged:: 2.0.0
            Added `atol` and `rtol` keywords to select float values. Added
            `rdkit_kwargs` to pass arguments to the RDKitConverter
        .. versionchanged:: 2.2.0
            Added ``smarts_kwargs`` argument, allowing users to pass a
            a dictionary of arguments to RDKit's ``GetSubstructMatches``.
        r   z ( r   z ) Nr   z2Unexpected token at end of selection string: '{0}')r   r  r  rL   rD  rE  	selectstrr  replacecollectionsdequer  r   r   r   r   )rI   r  r  r   r  r  rL   rD  rE  r   	parsetrees              r   parsezSelectionParser.parse  s    n !		(.B*0b""""3..66sEBB!'$(?@@))!,,	;q>% 6$+a.))   r   c                    |                                  }| j        d         t          v rt          | j        d                  j        |k    rt          | j                                                 }d|j        z   }|                     |          } ||||           }| j        d         t          v r!t          | j        d                  j        |k    |S )Nr   r   )_parse_subexpr   r   rb   r   r   )rI   r  exp1opqexp2s         r   r   z SelectionParser.parse_expression  s    !!##KNk))DKN+6!;;T[00223BBM!A((++D2dD$''D KNk))DKN+6!;; r   c                 ^   | j                                         }|dk    r,|                     d          }|                     d           |S 	 t	          |         | | j                   S # t
          $ r d| d}t          |          d t          $ r}d| d}t          |          d d }~ww xY w)Nr   r   r   zUnknown selection token: 'r  zSelection failed: ')r   r   r   r  r   r7   r   r  )rI   r  expr  es        r   r  zSelectionParser._parse_subexp#  s    [  ""99''**CKKJ	3!"%dDK888 	3 	3 	37"777F ((d2 	3 	3 	3/1///F ((d2	3s   A( ()B,B''B,)Nr  r  TNN)
r>   r?   r@   r   r  r  r  r  r   r  rA   r   r   r  r    s         ( M  
   H H H HT
 
 
3 3 3 3 3r   r  z._selectorsz!Automatically generated selectors)docc                 F   | |t           j        d}|                                  d}|dk    rt          }nt	          |t
                    rt          }nt          j        |t          j	                  rt          }nt          j        |t          j                  rt          }nXt	          |t                    s|t          k    r%t          }|dk    rd|d<   n%|dk    rd|d<   nd	|d<   nt!          d
| d          t#          ||f|          }t%          t           ||           |S )af  Selection class factory for arbitrary TopologyAttrs.

    Normally this should not be used except within the codebase
    or by developers; it is called by the metaclass
    :class:`MDAnalysis.core.topologyattrs._TopologyAttrMeta` to
    auto-generate suitable selection classes by creating a token
    with the topology attribute (singular) name. The function
    uses the provided ``dtype`` to choose which Selection class
    to subclass:

    * :class:`BoolSelection` for booleans
    * :class:`RangeSelection` for integers
    * :class:`FloatRangeSelection` for floats
    * :class:`_ProtoStringSelection` for strings

    Other value types are not yet supported and will raise a
    ValueError. The classes are created in the :mod:`_selectors`
    module to avoid namespace clashes.

    Parameters
    ----------
    singular: str
        singular name of TopologyAttr
    attrname: str
        attribute name of TopologyAttr
    dtype: type
        type of TopologyAttr
    per_object: str
        level of TopologyAttr

    Returns
    -------
    selection: subclass of Selection

    Raises
    ------
    ValueError
        If ``dtype`` is not one of the supported types


    Example
    -------

    The function creates a class inside ``_selectors`` and returns it.
    Normally it should not need to be manually called, as it is created
    for each TopologyAttr::

        >>> gen_selection_class("resname", "resnames", object, "residue")
        <class 'MDAnalysis.core.selection._selectors.ResnameSelection'>

    Simply generating this selector is sufficient for the keyword to be
    accessible by :meth:`~MDAnalysis.core.universe.Universe.select_atoms`,
    as that is automatically handled by
    :class:`~MDAnalysis.core.selections._Selectionmeta`.

    See also
    --------
    :class:`MDAnalysis.core.topologyattrs._TopologyAttrMeta`

    .. versionadded:: 2.0.0
    )r4   r&  r?   ry   U1r  r  r5  r  r   r8  z No base class defined for dtype zK. Define a Selection class manually by subclassing core.selection.Selection)
_selectorsr>   
capitalizer  
issubclassrq  r  r\   
issubdtypeintegerr  floatingr  strr  r*  r  r5   setattr)singularr  r   
per_objectbasedctr:   baseclsr9   s           r   gen_selection_classr  @  sL   ~  )	 G !!##...D}}%	E4	 	  
	ubj	)	) 
 	ubk	*	* 
%	E3		 
5F??'""+GG9$$+GG#GG3u 3 3 3
 
 	
 tgZ
)
)CJc"""Jr   )Mr   r  r^  r.  rq   r   r  r  numpyr\   lib.utilr   libr   
exceptionsr   r   r   r  r_  ra  r   r   r.   r   r   r  r5   r1   r  rC   rX   rd   rs   ru   ry   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r*  r:  r?  r[  r  r  r  r  r  r  r=  rQ  re  rp  r  r  r  r  Parser
ModuleTyper>   r  modulesr  rA   r   r   <module>r     s  0 "     				      



       % $ $ $ $ $       F F F F F F F F F F -  '  "$ $ $N& & &R  !     T   P P P P PV~ P P P P    >   ) ) ) ) ). ) ) )      T   P P P P P. P P P P
 
 
 
 
9 
 
 
    Y   > > > > >> > > >; ; ; ; ;n ; ; ;    ^   &8 8 8 8 8i 8 8 8D: : : : :i : : :D-8 -8 -8 -8 -8	 -8 -8 -8`: : : : :Y : : :8< < < < <9 < < <~
< 
< 
< 
< 
<3 
< 
< 
<< < < < < 4 < < <: : : : :Y : : :<    I   $4 4 4 4 4i 4 4 4>    	   ,    )   .. . . . .I . . .@
* 
* 
* 
* 
*	 
* 
* 
*M M M M Mi M M M`C C C C CY C C CL    I   @3 3 3 3 3Y 3 3 3l" " " " ". " " "J    ^   S. S. S. S. S.y S. S. S.lA A A A Ay A A AH, , , , ,Y , , ,^# # # # #( # # #L# # # # #/ # # #L6 6 6 6 6$ 6 6 6r         ,      F@ @ @ @ @	 @ @ @FM M M M MI M M M`K3 K3 K3 K3 K3f K3 K3 K3^ 
		 U"E  
 $.J  _ _ _ _ _r   