diff --git a/tools/moltemplate/src/lttree_postprocess.py b/tools/moltemplate/src/lttree_postprocess.py new file mode 100755 index 0000000000..bb040c98a1 --- /dev/null +++ b/tools/moltemplate/src/lttree_postprocess.py @@ -0,0 +1,326 @@ +#!/usr/bin/env python + +""" + lttree_postprocess.py + This is a stand-alone python script which checks the files created by + lttree.py to insure that the standard instance-variables ($variables) + have all been defined. This script performs a task which is very similar + to the task performed by lttree_check.py. This script attempts to detect + mistakes in the names of $atom, $bond, $angle, $dihedral, $improper, & $mol + variables. + +""" + +import sys +from lttree_styles import * +from ttree_lex import ExtractCatName + +g_program_name = 'lttree_postprocess.py' +atom_style = 'full' +ttree_assignments_fname = 'ttree_assignments.txt' +defined_mols = set([]) +defined_atoms = set([]) +defined_bonds = set([]) +defined_angles = set([]) +defined_dihedrals = set([]) +defined_impropers = set([]) + +g_no_check_msg = \ + '(To override this error, run moltemplate using the \"-nocheck\" argument.)\n' + +if len(sys.argv) > 1: + for i in range(0,len(sys.argv)): + if ((sys.argv[i].lower() == '-atomstyle') or + (sys.argv[i].lower() == '-atom-style') or + (sys.argv[i].lower() == '-atom_style')): + if i+1 >= len(sys.argv): + raise InputError('Error('+g_program_name+'): The '+sys.argv[i]+' flag should be followed by a LAMMPS\n' + ' atom_style name (or single quoted string containing a space-separated\n' + ' list of column names such as: atom-ID atom-type q x y z molecule-ID.)\n') + + atom_style = sys.argv[i+1] + elif ((sys.argv[i].lower() == '-ttreeassignments') or + (sys.argv[i].lower() == '-ttree-assignments') or + (sys.argv[i].lower() == '-ttree_assignments')): + if i+1 >= len(sys.argv): + raise InputError('Error('+g_program_name+'): The '+sys.argv[i]+' flag should be followed by \n' + ' a file containing the variable bindings created by ttree/moltemplate.\n') + ttree_assignments_fname = sys.argv[i+1] + else: + pass # ignore other arguments (they are intended for lttree.py) + + +atom_column_names = AtomStyle2ColNames(atom_style) +i_atomid = 0 +i_molid = -1 +for i in range(0,len(atom_column_names)): + if atom_column_names[i].lower() == 'atom-id': + i_atomid = i + elif atom_column_names[i].lower() == 'molecule-id': + i_molid = i +i_max_column = max(i_atomid, i_molid) + + +# The following variables are defined in "lttree_styles.py" +#data_atoms="Data Atoms" +#data_masses="Data Masses" +#data_velocities="Data Velocities" +#data_bonds="Data Bonds" +#data_angles="Data Angles" +#data_dihedrals="Data Dihedrals" +#data_impropers="Data Impropers" + + +g_program_name = 'lttree_postprocess.py' +g_version_str = '0.4' +g_date_str = '2012-12-12' +sys.stderr.write(g_program_name+' v'+g_version_str+' '+g_date_str+'\n') + +try: + # ------------ defined_atoms ------------ + try: + f = open(data_atoms+'.template', 'r') + except: + raise InputError('Error('+g_program_name+'): Unable to open file\n'+ + '\"'+data_atoms+'.template\"\n' + ' for reading. (Do your files lack a \"'+data_atoms+'\" section?)\n' + +g_no_check_msg+'\n') + + for line_orig in f: + ic = line_orig.find('#') + if ic != -1: + line = line_orig[:ic] + else: + line = line_orig.rstrip('\n') + + tokens = line.strip().split() + if len(tokens) == 0: + pass + elif len(tokens) <= i_max_column: + raise InputError('Error('+g_program_name+'): The following line from\n' + ' "\"'+data_atoms+'.template\" has bad format:\n\n' + +line_orig+'\n' + ' This my probably an internal error. (Feel free to contact the developer.)\n' + +g_no_check_msg+'\n') + else: + defined_atoms.add(tokens[i_atomid]) + if i_molid != -1: + defined_mols.add(tokens[i_molid]) + + f.close() + + + # ------------ defined_bonds ------------ + try: + f = open(data_bonds+'.template', 'r') + + for line_orig in f: + ic = line_orig.find('#') + if ic != -1: + line = line_orig[:ic] + else: + line = line_orig.rstrip('\n') + + tokens = line.strip().split() + if len(tokens) == 0: + pass + elif len(tokens) < 4: + raise InputError('Error('+g_program_name+'): The following line from\n' + ' "\"'+data_bonds+'.template\" has bad format:\n\n' + +line_orig+'\n' + ' This my probably an internal error. (Feel free to contact the developer.)\n' + +g_no_check_msg+'\n') + else: + defined_bonds.add(tokens[0]) + f.close() + except: + pass # Defining bonds (stored in the data_bonds file) is optional + + + # ------------ defined_angles ------------ + try: + f = open(data_angles+'.template', 'r') + for line_orig in f: + ic = line_orig.find('#') + if ic != -1: + line = line_orig[:ic] + else: + line = line_orig.rstrip('\n') + + tokens = line.strip().split() + if len(tokens) == 0: + pass + elif len(tokens) < 5: + raise InputError('Error('+g_program_name+'): The following line from\n' + ' "\"'+data_angles+'.template\" has bad format:\n\n' + +line_orig+'\n' + ' This my probably an internal error. (Feel free to contact the developer.)\n' + +g_no_check_msg+'\n') + else: + defined_angles.add(tokens[0]) + f.close() + except: + pass # Defining angles (stored in the data_angles file) is optional + + + # ------------ defined_dihedrals ------------ + try: + f = open(data_dihedrals+'.template', 'r') + for line_orig in f: + ic = line_orig.find('#') + if ic != -1: + line = line_orig[:ic] + else: + line = line_orig.rstrip('\n') + + tokens = line.strip().split() + if len(tokens) == 0: + pass + elif len(tokens) < 6: + raise InputError('Error('+g_program_name+'): The following line from\n' + ' "\"'+data_dihedrals+'.template\" has bad format:\n\n' + +line_orig+'\n' + ' This my probably an internal error. (Feel free to contact the developer.)\n' + +g_no_check_msg+'\n') + else: + defined_dihedrals.add(tokens[0]) + f.close() + except: + pass #Defining dihedrals (stored in the data_dihedrals file) is optional + + + # ------------ defined_impropers ------------ + try: + f = open(data_impropers+'.template', 'r') + + for line_orig in f: + ic = line_orig.find('#') + if ic != -1: + line = line_orig[:ic] + else: + line = line_orig.rstrip('\n') + + tokens = line.strip().split() + if len(tokens) == 0: + pass + elif len(tokens) < 6: + raise InputError('Error('+g_program_name+'): The following line from\n' + ' "\"'+data_impropers+'.template\" has bad format:\n\n' + +line_orig+'\n' + ' This my probably an internal error. (Feel free to contact the developer.)\n' + +g_no_check_msg+'\n') + else: + defined_impropers.add(tokens[0]) + f.close() + except: + pass #Defining impropers (stored in the data_impropers file) is optional + + + + + # ---- Check ttree_assignments to make sure variables are defined ---- + + try: + f = open(ttree_assignments_fname, 'r') + except: + raise InputError('Error('+g_program_name+'): Unable to open file\n'+ + '\"'+ttree_assignments_fname+'\"\n' + ' for reading. (Do your files lack a \"'+data_atoms+'\" section?)\n' + +g_no_check_msg+'\n') + + for line_orig in f: + + ic = line_orig.find('#') + if ic != -1: + line = line_orig[:ic] + usage_location_str = 'near ' + line_orig[ic+1:] + else: + line = line_orig.rstrip('\n') + usage_location_str = '' + + tokens = line.strip().split() + if len(tokens) == 0: + pass + if len(tokens) > 0: + # This file contains a list of variables of the form: + # + # @/atom:MoleculeType1:C 1 + # @/atom:MoleculeType2:N 2 + # : + # $/atom:molecule1141:C2 13578 + # $/atom:molecule1142:N1 13579 + # + # We only care about instance variables (which use the '$' prefix) + # Lines in this file with a different prefix ('@') which don't + # contain '$' should be ignored. + i_prefix = tokens[0].find('$') + if i_prefix != -1: + descr_str = tokens[0][i_prefix+1:] + cat_name = ExtractCatName(descr_str) + + if ((cat_name == 'atom') and + (tokens[0] not in defined_atoms)): + raise InputError('Error('+g_program_name+'): '+usage_location_str+'\n'+ + ' Reference to undefined $atom:\n\n' + ' '+tokens[0]+' (<--full name)\n\n'+ + ' (If that atom belongs to a molecule (or other subunit), make sure that\n'+ + ' you specified the correct path which leads to it (using / and ..))\n\n'+ + g_no_check_msg) + + elif ((cat_name == 'bond') and + (tokens[0] not in defined_bonds)): + raise InputError('Error('+g_program_name+'): '+usage_location_str+'\n'+ + ' Reference to undefined $bond:\n\n' + ' '+tokens[0]+' (<--full name)\n\n'+ + ' (If that bond belongs to a molecule (or other subunit), make sure that\n'+ + ' you specified the correct path which leads to it (using / and ..))\n\n'+ + g_no_check_msg) + + elif ((cat_name == 'angle') and + (tokens[0] not in defined_angles)): + raise InputError('Error('+g_program_name+'): '+usage_location_str+'\n'+ + ' Reference to undefined $angle:\n\n'+ + ' '+tokens[0]+' (<--full name)\n\n'+ + ' (If that angle belongs to a molecule (or other subunit), make sure that\n'+ + ' you specified the correct path which leads to it (using / and ..))\n\n'+ + g_no_check_msg) + + elif ((cat_name == 'dihedral') and + (tokens[0] not in defined_dihedrals)): + raise InputError('Error('+g_program_name+'): '+usage_location_str+'\n\n'+ + ' Reference to undefined $dihedral:\n\n' + ' '+tokens[0]+' (<--full name)\n\n'+ + ' (If that dihedral belongs to a molecule (or other subunit), make sure that\n'+ + ' you specified the correct path which leads to it (using / and ..))\n\n'+ + g_no_check_msg) + + elif ((cat_name == 'improper') and + (tokens[0] not in defined_impropers)): + raise InputError('Error('+g_program_name+'): '+usage_location_str+'\n'+ + ' Reference to undefined $improper:\n\n' + ' '+tokens[0]+' (<--full name)\n\n'+ + ' (If that improper belongs to a molecule (or other subunit), make sure that\n'+ + ' you specified the correct path which leads to it (using / and ..))\n\n'+ + g_no_check_msg) + + elif ((cat_name == 'mol') and + (tokens[0] not in defined_mols)): + raise InputError('Error('+g_program_name+'): '+usage_location_str+'\n'+ + ' Reference to undefined $mol (molecule-ID) variable:\n\n' + ' '+tokens[0]+' (<--full name)\n\n'+ + ' (If that molecule is part of a larger molecule, then make sure that\n'+ + ' you specified the correct path which leads to it (using / and ..))\n\n'+ + g_no_check_msg) + + + f.close() + + sys.stderr.write(g_program_name+': -- No errors detected. --\n') + exit(0) + + + +except (ValueError, InputError) as err: + sys.stderr.write('\n'+str(err)+'\n') + sys.exit(1) +