Skip to content

Commit

Permalink
added the ability to use regular expressions to match @atom type name…
Browse files Browse the repository at this point in the history
…s appearing in pair_coeff commands. Regular expressions can also match @bond, @Angle, @dihedral, and @improper type names when they appear in bond_coeff, angle_coeff, dihedral_coeff, and improper_coeff commands.  None of this new functionality has been tested yet.  Hopefully I did not break anything.
  • Loading branch information
jewettaij committed Jul 8, 2020
1 parent 6222c4c commit b1ba71f
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 41 deletions.
25 changes: 13 additions & 12 deletions doc/moltemplate_manual_src/moltemplate_manual.tex
Original file line number Diff line number Diff line change
Expand Up @@ -577,8 +577,8 @@ \subsection{Moltemplate commands}
commands to define Atoms, Bonds, Angles, Coeffs, etc...
\textit{(If that molecule type exists already,
then this will append additional \textbf{content} to its definition.)}
\textbf{new} and \textbf{delete} commands can be used
to create or delete molecular subunits \textit{within} this molecule.
%\textbf{new} and \textbf{delete} commands can be used
%to create or delete molecular subunits \textit{within} this molecule.
(See the \textit{SPCE}, \textit{Monomer}, and \textit{Butane}
molecules, and the \textit{TraPPE} namespace
defined in sections \ref{sec:spce_example}, \ref{sec:2bead},
Expand Down Expand Up @@ -675,10 +675,11 @@ \subsection{Moltemplate commands}
\} \\
\end{tabular}
&
Create a new molecule \textbf{type} based on multiple existing molecule types.
Define a new object \textbf{type}
based one or more existing object types.
Atom types, bond types, angle types (etc) which are defined in
\textit{Mol1}, or \textit{Mol2}, ... are available inside the
new molecule.
new object.
\textit{Additional content}
(including more \textit{write()} or \textit{write\_once()}
or \textit{new} commands)
Expand Down Expand Up @@ -715,18 +716,18 @@ \subsection{Moltemplate commands}
\textbf{delete} \textit{molecule}
&
Delete the \textit{molecule} instance.
(This command can appear inside a molecule's definition
to delete a specific molecular subunit within a molecule. In that case,
it will be carried out in every copy of that molecule type.
\textbf{delete} can also be used to delete specific
%(This command can appear inside a molecule's definition
% to delete a specific molecular subunit within a molecule. In that case,
% it will be carried out in every copy of that molecule type.)
(\textbf{delete} can also be used to delete
atoms, bonds, angles, dihedrals, and improper interactions.)
See section \ref{sec:delete}.
\\
\hline
\textbf{delete} \textit{molecules}[\textit{range}]
&
Delete a range of molecules specified by
\mbox{\textit{molecule}[\textit{range}]}.
\mbox{\textit{molecules}[\textit{range}]}.
(This also works for multidimensional arrays.
See sections \ref{sec:delete} and \ref{sec:delete_holes}.)
\\
Expand Down Expand Up @@ -774,7 +775,7 @@ \subsection{Moltemplate commands}
\textbf{import} \textit{file}
&
Insert the contents of file \textit{file} here,
preventing circular inclusions.
preventing circular (self-referential) inclusions.
\textit{(recommended)}
\\
\hline
Expand Down Expand Up @@ -1039,7 +1040,7 @@ \subsection{Coordinate transformations}
\mbox{$x_0,y_0,z_0$} which specify the point around which
you want the scaling to occur.
(This point will be a \textit{fixed point}.
Of omitted, the origin is used.)
If omitted, the origin is used.)
\\
\hline
\begin{tabular}[t]{l}
Expand Down Expand Up @@ -4418,7 +4419,7 @@ \subsection*{Regular expressions}
Regular-expressions can also be used to match potential atom and bond types.
(To use regular expressions, surround the atom and
bond types on either side by slashes.
For example: \mbox{@atom:C[1-5]/}, should match
For example: \mbox{/@atom:C[1-5]/}, should match
\mbox{@atom:C1} through \mbox{@atom:C6}.)
\textit{Note: This feature has not been tested as of 2019-9-03.}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ nanotube = new GrapheneXZ.move(0, 5.457193512764, 0) # 5.45 = R
#2.13= d*1.5


# Note: The length is 12 hexegons, the circumference is
# 14 hexegons (~=25.56 and 34.43 Angstroms, respectively).
# Note: The length is 12 hexagons, the circumference is
# 14 hexagons (~=25.56 and 34.43 Angstroms, respectively).


# Move all of the unit-cells in the nanotube between the two graphene sheets.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ wat = new SPCE [9].move(3.5526287, 0, 0 )
[9].move(1.77631435, 3.3133, 0 )
[6].move( 0, 0, 3.45)

# Optional: Center the water box at the origin. (Not really necessary.)
# Optional: Move the water below the graphene sheets

wat[*][*][*].move(-23.9802437, -14.90985, 11.47)

Expand Down
2 changes: 1 addition & 1 deletion moltemplate/nbody_by_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Author: Andrew Jewett (jewett.aij at g mail)
# http://www.chem.ucsb.edu/~sheagroup
# License: 3-clause BSD License (See LICENSE.TXT)
# Copyright (c) 2011, Regents of the University of California
# Copyright (c) 2013, Regents of the University of California
# All rights reserved.

man_page_text = """
Expand Down
102 changes: 77 additions & 25 deletions moltemplate/postprocess_coeffs.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@


import sys
import re
import gc

try:
Expand All @@ -58,8 +59,8 @@
g_module_name = g_filename
if g_filename.rfind('.py') != -1:
g_module_name = g_filename[:g_filename.rfind('.py')]
g_date_str = '2018-6-09'
g_version_str = '0.2.0'
g_date_str = '2020-7-07'
g_version_str = '0.3.0'
g_program_name = g_filename
#sys.stderr.write(g_program_name+' v'+g_version_str+' '+g_date_str+' ')

Expand Down Expand Up @@ -156,49 +157,72 @@ def main():
if (not line_orig) or (line_orig == ''):
break
tokens = line_orig.strip().split('@')
# If the second token is surrounded by '/' characters, interpret
# it as a regular expression.
token1_is_re = ((len(tokens) >= 2) and
(len(tokens[1]) >= 2) and
(tokens[1][0] == '/') and (tokens[1][-1] == '/'))
# If the second token contains wildcard characters, interpret
# it as a wildcard (ie. glob) expression.
token1_is_wild = ((len(tokens) >= 2) and
HasWildcard(tokens[1]) #does it contain '*' or '?'
and
(tokens[1][0] != '{')) #(ignore * or ? in {})

if ((len(tokens) >= 2) and
(tokens[0].find('bond_coeff') == 0) and
#does this token contain '*' or '?'
HasWildcard(tokens[1]) and
(tokens[1][0:1] != '{')): #(don't pattern match * in {})?'
left_paren, typepattern, text_after = ExtractVarName(tokens[1])
(token1_is_re or token1_is_wild)):
if token1_is_re:
regex_str = typestr[1:-1]
left_paren = text_after = ''
typepattern = re.compile(regex_str)
else:
left_paren, typepattern, text_after = ExtractVarName(tokens[1])
for btype in bond_types:
if MatchesPattern(btype, typepattern):
#assert(left_paren == '')
tokens[1] = btype + text_after
sys.stdout.write('@'.join(tokens) + '\n')

elif ((len(tokens) >= 2) and
(tokens[0].find('angle_coeff') == 0) and
#does this token contain '*' or '?'
HasWildcard(tokens[1]) and
(tokens[1][0:1] != '{')):
left_paren, typepattern, text_after = ExtractVarName(tokens[1])
(tokens[0].find('angle_coeff') == 0) and
(token1_is_re or token1_is_wild)):
if token1_is_re:
regex_str = typestr[1:-1]
left_paren = text_after = ''
typepattern = re.compile(regex_str)
else:
left_paren, typepattern, text_after = ExtractVarName(tokens[1])
for antype in angle_types:
if MatchesPattern(antype, typepattern):
#assert(left_paren == '')
tokens[1] = antype + text_after
sys.stdout.write('@'.join(tokens) + '\n')

elif ((len(tokens) >= 2) and
(tokens[0].find('dihedral_coeff') == 0) and
#does this token contain '*' or '?'
HasWildcard(tokens[1]) and
(tokens[1][0:1] != '{')): #(don't pattern match * in {})
left_paren, typepattern, text_after = ExtractVarName(tokens[1])
(tokens[0].find('dihedral_coeff') == 0) and
(token1_is_re or token1_is_wild)):
if token1_is_re:
regex_str = typestr[1:-1]
left_paren = text_after = ''
typepattern = re.compile(regex_str)
else:
left_paren, typepattern, text_after = ExtractVarName(tokens[1])
for dtype in dihedral_types:
if MatchesPattern(dtype, typepattern):
#assert(left_paren == '')
tokens[1] = dtype + text_after
sys.stdout.write('@'.join(tokens) + '\n')

elif ((len(tokens) >= 2) and
(tokens[0].find('improper_coeff') == 0) and
#does this token contain '*' or '?'
HasWildcard(tokens[1]) and
(tokens[1][0:1] != '{')): #(don't pattern match * in {})
left_paren, typepattern, text_after = ExtractVarName(tokens[1])
(tokens[0].find('improper_coeff') == 0) and
(token1_is_re or token1_is_wild)):
if token1_is_re:
regex_str = typestr[1:-1]
left_paren = text_after = ''
typepattern = re.compile(regex_str)
else:
left_paren, typepattern, text_after = ExtractVarName(tokens[1])
for itype in improper_types:
if MatchesPattern(itype, typepattern):
#assert(left_paren == '')
Expand Down Expand Up @@ -258,16 +282,44 @@ def main():
text_after2 = ''
typepattern2 = tokens[2]
del tokens[3]
if (HasWildcard(tokens[1]) and
(tokens[1][0:1] != '{')): #(don't pattern match * in {})

################
# If surrounded by '/' characters, the token is meant to be
# interpreted as a regular expression.
token1_is_re = ((len(tokens[1]) >= 2) and
(tokens[1][0] == '/') and
(tokens[1][-1] == '/'))
token2_is_re = ((len(tokens[2]) >= 2) and
(tokens[2][0] == '/') and
(tokens[2][-1] == '/'))
# If the token contains wildcard characters, interpret
# it as a wildcard (ie. glob) expression.
token1_is_wild = (HasWildcard(tokens[1]) #contain '*' or '?'
and (tokens[1][0] != '{')) #ignore * in {}
token2_is_wild = (HasWildcard(tokens[2]) #contain '*' or '?'
and (tokens[2][0] != '{')) #ignore * in {}
################


if token1_is_re:
atom_types1 = atom_types
regex_str = tokens[1][1:-1]
typepattern1 = re.compile(regex_str)
elif token1_is_wild:
atom_types1 = atom_types
else:
atom_types1 = set([typepattern1])
if (HasWildcard(tokens[2]) and
(tokens[2][0:1] != '{')): #(don't pattern match * in {})

if token2_is_re:
atom_types2 = atom_types
regex_str = tokens[2][1:-1]
typepattern2 = re.compile(regex_str)
elif token2_is_wild:
atom_types2 = atom_types
else:
atom_types2 = set([typepattern2])


for atype1 in atom_types1:
#sys.stderr.write('atype1 = \"'+str(atype1)+'\"\n')
if MatchesPattern(atype1, typepattern1):
Expand Down

0 comments on commit b1ba71f

Please sign in to comment.