@@ -233,24 +233,24 @@ class MolSys(MolecularSystemBase):
233233 Name of molecular system
234234 """
235235 def __init__ (
236- self ,
237- record_types : np .ndarray ,
238- atomids : np .ndarray ,
239- names : np .ndarray ,
240- altlocs : np .ndarray ,
241- resnames : np .ndarray ,
242- resnums : np .ndarray ,
243- icodes : np .ndarray ,
244- chains : np .ndarray ,
245- trajectory : np .ndarray ,
246- occupancies : np .ndarray ,
247- bs : np .ndarray ,
248- segs : np .ndarray ,
249- atypes : np .ndarray ,
250- charges : np .ndarray ,
251- bonds : ArrayLike = None ,
252- name : str = 'Noname_MolSys'
253-
236+ self ,
237+ record_types : np .ndarray ,
238+ atomids : np .ndarray ,
239+ names : np .ndarray ,
240+ altlocs : np .ndarray ,
241+ resnames : np .ndarray ,
242+ resnums : np .ndarray ,
243+ icodes : np .ndarray ,
244+ chains : np .ndarray ,
245+ trajectory : np .ndarray ,
246+ occupancies : np .ndarray ,
247+ bs : np .ndarray ,
248+ segs : np .ndarray ,
249+ atypes : np .ndarray ,
250+ charges : np .ndarray ,
251+ chiral : ArrayLike = None ,
252+ bonds : ArrayLike = None ,
253+ name : str = "Noname_MolSys" ,
254254 ):
255255
256256 self .molsys = self
@@ -268,6 +268,7 @@ def __init__(
268268 self .segs = segs .copy ()
269269 self .atypes = atypes .copy ()
270270 self .charges = charges .copy ()
271+ self .chiral = chiral .copy () if chiral is not None else None
271272 self ._fname = name
272273
273274 self .ix = np .arange (len (self .atomids ))
@@ -310,6 +311,7 @@ def __init__(
310311 'chain' : self .chains ,
311312 'occupancies' : self .occupancies ,
312313 'b' : self .bs ,
314+ 'chiral' : self .chiral ,
313315 'segid' : self .chains ,
314316 'type' : self .atypes ,
315317 'charges' : self .charges ,
@@ -341,7 +343,8 @@ def __init__(
341343 '!=' : operator .ne ,
342344 'byres' : partial (byres , molsys = self .molsys ),
343345 'within' : update_wrapper (partial (within , molsys = self .molsys ), within ),
344- 'around' : update_wrapper (partial (within , molsys = self .molsys ), within )}
346+ 'around' : update_wrapper (partial (within , molsys = self .molsys ), within ),
347+ 'point' : update_wrapper (partial (point , molsys = self .molsys ), point ),}
345348
346349
347350 # Aliases
@@ -783,6 +786,12 @@ def process_statement(statement, logickws, subjectkws):
783786 continue
784787
785788 stat_split = stat .split ()
789+ if stat_split [0 ] not in logickws and stat_split [0 ] not in subjectkws :
790+ raise ValueError (
791+ f"Invalid selection keyword: { stat_split [0 ]} . All selections statements and substatements must start "
792+ f"with a valid selection keyword"
793+ )
794+
786795 subject = None
787796 values = []
788797 while len (stat_split ) > 0 :
@@ -810,6 +819,9 @@ def process_statement(statement, logickws, subjectkws):
810819 mask = operation (mask , tmp ) if operation else tmp
811820 operation = None
812821
822+ elif not values and hasattr (operation , 'novals' ):
823+ mask = operation (mask , np .ones_like (mask , dtype = bool ))
824+
813825 return mask
814826
815827
@@ -879,7 +891,7 @@ def check_operation(operation, stat_split, logickws):
879891 operation : callable
880892 A simplified version of the provided operation now accounting for the user provided parameters.
881893 """
882- advanced_operators = (logickws ['within' ], logickws ['around' ], logickws ['byres' ])
894+ advanced_operators = (logickws ['within' ], logickws ['around' ], logickws ['byres' ], logickws [ 'point' ] )
883895 if operation in advanced_operators :
884896 outer_operation = logickws ['and' ]
885897 args = [stat_split .pop (i ) for i in range (1 , 1 + operation .nargs )]
@@ -915,7 +927,7 @@ def build_operator(stat_split, logickws):
915927 operation = logickws ['and' ]
916928 unary_operators = (logickws ['not' ], logickws ['byres' ])
917929 binary_operators = (logickws ['and' ], logickws ['or' ])
918- advanced_operators = (logickws ['within' ], logickws ['around' ])
930+ advanced_operators = (logickws ['within' ], logickws ['around' ], logickws [ 'point' ] )
919931
920932 while _io := logickws .get (stat_split [0 ], False ):
921933
@@ -936,6 +948,9 @@ def toperation(a, b, operation, _io):
936948
937949 operation = partial (toperation , operation = operation , _io = _io )
938950
951+ if hasattr (_io .func , 'novals' ):
952+ operation .novals = _io .func .novals
953+
939954 elif _io in binary_operators :
940955 if operation != logickws ['and' ]:
941956 raise RuntimeError ('Cannot have two binary logical operators in succession' )
@@ -1323,7 +1338,7 @@ def unot(mask):
13231338
13241339def within (distance , mask , molsys ):
13251340 """
1326- Advanced logic operator to identify atoms within a user defined distance.
1341+ Advanced logic operator to identify atoms within a user defined distance of another selection .
13271342
13281343 Parameters
13291344 ----------
@@ -1355,6 +1370,44 @@ def within(distance, mask, molsys):
13551370within .nargs = 1
13561371
13571372
1373+ def point (x , y , z , distance , mask , molsys ):
1374+ """
1375+ Advanced logic operator to identify atoms within a user defined distance of a point in cartesian space.
1376+
1377+ Parameters
1378+ ----------
1379+ x : float
1380+ The x coordinate of the point in cartesian space.
1381+ y : float
1382+ The y coordinate of the point in cartesian space.
1383+ z : float
1384+ The z coordinate of the point in cartesian space.
1385+ distance : float
1386+ The distance window defining which atoms will be included in the selection.
1387+ mask : np.ndarray
1388+ A boolean array defining a subset of atoms of a :class:`~MolSys` from which the distance cutoff will be
1389+ measured by.
1390+ molsys : :class:`~MolSys`
1391+ A chiLife :class:`~MolSys` from which to select atoms from .
1392+
1393+ Returns
1394+ -------
1395+ out_mask : np.ndarray
1396+ A boolean array defining a subset of atoms of a :class:`~MolSys` that are within the user defined distance
1397+ of the user defined selection.
1398+ """
1399+
1400+ tree1 = cKDTree (molsys .coords [mask ])
1401+ args = tree1 .query_ball_point (np .array ([x , y , z ], dtype = float ), distance )
1402+ out_mask = np .zeros_like (mask , dtype = bool )
1403+ out_mask [args ] = True
1404+
1405+ return out_mask
1406+
1407+
1408+ point .nargs = 4
1409+ point .novals = True
1410+
13581411def concat_molsys (systems ):
13591412 """
13601413 Function to concatenate two or more :class:`~MolSys` objects into a single :class:`~MolSys` object. Atoms will be
0 commit comments