def useTIP3P(self):
        """Change the appropriate lines in the topology file to use ffamber_tip3p."""
    
        print '>> Using TIP3P water <<'
	top = TopologyFile(topfile=self.files.topfile)
	
	# print '>>> top.includes:', top.includes
	# print '>>> top.ifdefs:', top.ifdefs

	# Remove other water models
	i = 0
	TIP3PLine = False
	while i < len(top.includes):
	    if top.includes[i].count('"ffamber_tip3p.itp"') > 0:
		TIP3PLine = True
	    if top.includes[i].count('"spc.itp"') > 0:
		print '>>> REMOVING include:', top.includes.pop(i) # remove any instances of '#include "spc.itp"'
	    elif top.includes[i].count('"flexspc.itp"') > 0:
		print '>>> REMOVING include:', top.includes.pop(i) # remove any instances of '#include "flexspc.itp"'
	    else:
		i += 1
		
        # Remove any "spc.itp" mention from ifdefs too
	#
	# Recall that top.ifdefs are lists of ifdef groups of lines
	# Example:
	#     [ ['#ifdef POSRES\n', '#include "posre.itp"\n', '#endif\n'],
	#       ['#ifdef FLEX_SPC\n', '#include "flexspc.itp"\n', '#else\n', '#include "spc.itp"\n', '#endif\n'], .... ]
	i = 0
	while i < len(top.ifdefs):
	    spcMentioned = False
	    for line in top.ifdefs[i]:
		if line.count('spc.itp') > 0:
		    spcMentioned = True
		    break
	    if spcMentioned:
		top.ifdefs.pop(i)
	    else:
		i += 1
	
	# If there's no line for ffamber_tip3p.itp, add it
	if not TIP3PLine:
	    top.includes.append('#include "ffamber_tip3p.itp"\n')
	    
	# write the new topfile
	top.rebuild_lines()  # This must be done if there are any changes made the the data
	top.write(self.files.next_top())
	self.files.increment_top()
def extractNumberSolventMoleculesFromTopology(intopfile):
    """Extract the number of water molecules from a topology file."""

    top = TopologyFile(topfile=intopfile)
    # print top.nmols

    try:
        numberWaterMolecules = top.nmols['SOL']
    except:
        raise TopologyFileFormatError

    return int(numberWaterMolecules)
    def useTIP3P(self):
        """Change the appropriate lines in the topology file to use ffamber_tip3p."""

        print '>> Using TIP3P water <<'
        top = TopologyFile(topfile=self.files.topfile)

        # print '>>> top.includes:', top.includes
        # print '>>> top.ifdefs:', top.ifdefs

        # Remove other water models
        i = 0
        TIP3PLine = False
        while i < len(top.includes):
            if top.includes[i].count('"ffamber_tip3p.itp"') > 0:
                TIP3PLine = True
            if top.includes[i].count('"spc.itp"') > 0:
                print '>>> REMOVING include:', top.includes.pop(
                    i)  # remove any instances of '#include "spc.itp"'
            elif top.includes[i].count('"flexspc.itp"') > 0:
                print '>>> REMOVING include:', top.includes.pop(
                    i)  # remove any instances of '#include "flexspc.itp"'
            else:
                i += 1

        # Remove any "spc.itp" mention from ifdefs too
#
# Recall that top.ifdefs are lists of ifdef groups of lines
# Example:
#     [ ['#ifdef POSRES\n', '#include "posre.itp"\n', '#endif\n'],
#       ['#ifdef FLEX_SPC\n', '#include "flexspc.itp"\n', '#else\n', '#include "spc.itp"\n', '#endif\n'], .... ]
        i = 0
        while i < len(top.ifdefs):
            spcMentioned = False
            for line in top.ifdefs[i]:
                if line.count('spc.itp') > 0:
                    spcMentioned = True
                    break
            if spcMentioned:
                top.ifdefs.pop(i)
            else:
                i += 1

# If there's no line for ffamber_tip3p.itp, add it
        if not TIP3PLine:
            top.includes.append('#include "ffamber_tip3p.itp"\n')

# write the new topfile
        top.rebuild_lines(
        )  # This must be done if there are any changes made the the data
        top.write(self.files.next_top())
        self.files.increment_top()
    def AddIons(self, np, nn, nwaters):
        """Use the gromacs program genbox to replace water molecules in the current simulation box
	with ions.
	
	REQUIRED
	np        - the number of positive ions species 
	nn        - the number of negative ions species 
	nwaters   - the number of water molecules *currently* in the box  
	
	After the ions are added (and the water molecules replaced), there should be:
	np cations, nn anions, and (nwaters-nn-np) water molecules. 
	"""

        # If we're using the 3.1.4 version of gromacs, we first need to find the index of the solvent group
        # that genbox will use to add the ions.
        if self.system.gmx_version == '3.1.4':

            # Get the solvent group index
            solventGroupIndex = self.getSolventGroupIndexFromGenion()

            # Make a new grofile with the added ions
            genion = 'echo %d | %s/genion -s %s -o %s -pname %s -np %d -pq %d -nname %s -nn %d -nq %d -g genion.log -n %s ' % (
                solventGroupIndex, os.environ['GMXPATH'], self.files.tprfile,
                self.files.next_gro(), self.system.positiveIonName, np,
                self.system.positiveIonCharge, self.system.negativeIonName, nn,
                self.system.negativeIonCharge, self.files.ndxfile)
            self.rungmx(genion)
            self.files.increment_gro(
            )  # must increment filename for any new gmx file

        elif self.system.gmx_version == '3.3':

            # make a new grofile with the added ions
            genion = '%s/genion -s %s -o %s -pname %s -np %d -pq %d -nname %s -nn %d -nq %d -g genion.log' % (
                os.environ['GMXPATH'], self.files.tprfile,
                self.files.next_gro(), self.system.positiveIonName, np,
                self.system.positiveIonCharge, self.system.negativeIonName, nn,
                self.system.negativeIonCharge)
            self.rungmx(genion)
            if (
                    np + nn
            ) > 0:  # genion 3.3 WILL NOT produce a new gro if there is nothing to be done
                self.files.increment_gro(
                )  # must increment filename for any new gmx file

        # Generate a new index file for the ion-ated grofile
        self.makeIndexFile(self.files.grofile, self.files.next_ndx())
        self.files.increment_ndx(
        )  # must increment filename for any new gmx file

        # Generate a new topology file that we will add ions to (and decrease the number of water molecules)
        top = TopologyFile(topfile=self.files.topfile)

        # Add ions to topology file, which will eventually be in blocks that look like so:
        # [ moleculetype ]
        # ; molname       nrexcl
        # K               1
        #
        # [ atoms ]
        # ; id    at-type res-nr  residuename     at-name  cgnr   charge    mass
        # 1       K       1       K               K        1       1        39.098

        ions = IonEnvironmentCalculation(self.system).getIons(
        )  # a list of Ion() objects we will use to build ion molecules

        # Formatting needed for TopologyFileMolecule lines
        blockText = """[ moleculetype ]
; molname       nrexcl
%(molname)s               1

[ atoms ]
; id    atomtype        resnum  residuename    atoname       cgnr   charge      mass
1       %(atom_type)s  1       %(molname)s    %(molname)s   1       %(charge)d  %(mass)f """

        # Make a TopologyMolecule object for the negative ion
        negIonDict = {}
        negIonDict['molname'] = self.system.negativeIonName
        negIonDict['atom_type'] = ions[self.system.negativeIonName].atomType
        negIonDict['charge'] = ions[self.system.negativeIonName].charge
        negIonDict['mass'] = ions[self.system.negativeIonName].atomicMass
        print 'negIonDict', negIonDict
        lines = [s + '\n' for s in ((blockText % negIonDict).split('\n'))]
        print 'lines', lines

        lines = (blockText % negIonDict).split('\n')
        #lines = [(s+'\n') for s in ((blockText%negIonDict).split('\n')) ]
        print 'lines', lines
        negIonMolecule = TopologyFileMolecule(lines)

        # Make a TopologyMolecule object for the positive ion
        posIonDict = {}
        posIonDict['molname'] = self.system.positiveIonName
        posIonDict['atom_type'] = ions[self.system.positiveIonName].atomType
        posIonDict['charge'] = ions[self.system.positiveIonName].charge
        posIonDict['mass'] = ions[self.system.positiveIonName].atomicMass
        lines = (blockText % posIonDict).split('\n')
        # lines = [(s+'\n') for s in () ]
        print 'lines', lines
        posIonMolecule = TopologyFileMolecule(lines)

        # Add the ion molecules to the topology file
        top.AddMolecule(
            negIonMolecule,
            nn)  # arguments: opologyFileMolecule object, NumberOfMolecules
        top.AddMolecule(posIonMolecule, np)

        # The number of water molecules needs to be changed to reflect the current count
        numberWatersAfterGenion = nwaters - nn - np
        top.nmols['SOL'] = str(numberWatersAfterGenion)

        # Rebuild all the lines in the topfile and save it
        top.rebuild_lines()
        top.write(self.files.next_top())
        self.files.increment_top(
        )  # PrepWorker must increment filename for any new gmx file
    def AddIons(self, np, nn, nwaters):
	"""Use the gromacs program genbox to replace water molecules in the current simulation box
	with ions.
	
	REQUIRED
	np        - the number of positive ions species 
	nn        - the number of negative ions species 
	nwaters   - the number of water molecules *currently* in the box  
	
	After the ions are added (and the water molecules replaced), there should be:
	np cations, nn anions, and (nwaters-nn-np) water molecules. 
	"""
    
        # If we're using the 3.1.4 version of gromacs, we first need to find the index of the solvent group
	# that genbox will use to add the ions.
	if self.system.gmx_version == '3.1.4':
	    
	    # Get the solvent group index
	    solventGroupIndex = self.getSolventGroupIndexFromGenion()
	    	
	    # Make a new grofile with the added ions	   
	    genion = 'echo %d | %s/genion -s %s -o %s -pname %s -np %d -pq %d -nname %s -nn %d -nq %d -g genion.log -n %s '%(solventGroupIndex, os.environ['GMXPATH'], self.files.tprfile, self.files.next_gro(), self.system.positiveIonName, np, self.system.positiveIonCharge, self.system.negativeIonName, nn, self.system.negativeIonCharge, self.files.ndxfile)
	    self.rungmx( genion )
	    self.files.increment_gro()    # must increment filename for any new gmx file 
	    
	    
	elif self.system.gmx_version == '3.3':
	    
	    # make a new grofile with the added ions
	    genion = '%s/genion -s %s -o %s -pname %s -np %d -pq %d -nname %s -nn %d -nq %d -g genion.log'%(os.environ['GMXPATH'], self.files.tprfile, self.files.next_gro(), self.system.positiveIonName, np, self.system.positiveIonCharge, self.system.negativeIonName, nn, self.system.negativeIonCharge)
	    self.rungmx( genion )
	    if (np+nn) > 0:  # genion 3.3 WILL NOT produce a new gro if there is nothing to be done
		self.files.increment_gro()    # must increment filename for any new gmx file 
	    
	# Generate a new index file for the ion-ated grofile  
	self.makeIndexFile(self.files.grofile, self.files.next_ndx())
	self.files.increment_ndx()    # must increment filename for any new gmx file 

	# Generate a new topology file that we will add ions to (and decrease the number of water molecules)
	top = TopologyFile(topfile=self.files.topfile)

	# Add ions to topology file, which will eventually be in blocks that look like so:
	# [ moleculetype ]
	# ; molname       nrexcl
	# K               1
	#
	# [ atoms ]
	# ; id    at-type res-nr  residuename     at-name  cgnr   charge    mass
	# 1       K       1       K               K        1       1        39.098

	ions = IonEnvironmentCalculation(self.system).getIons()  # a list of Ion() objects we will use to build ion molecules
	
	# Formatting needed for TopologyFileMolecule lines
	blockText = """[ moleculetype ]
; molname       nrexcl
%(molname)s               1

[ atoms ]
; id    atomtype        resnum  residuename    atoname       cgnr   charge      mass
1       %(atom_type)s  1       %(molname)s    %(molname)s   1       %(charge)d  %(mass)f """
	
	# Make a TopologyMolecule object for the negative ion
	negIonDict = {}
	negIonDict['molname']   = self.system.negativeIonName
	negIonDict['atom_type'] = ions[self.system.negativeIonName].atomType
	negIonDict['charge']    = ions[self.system.negativeIonName].charge
	negIonDict['mass']      = ions[self.system.negativeIonName].atomicMass
	print 'negIonDict', negIonDict
	lines = [s+'\n' for s in ((blockText%negIonDict).split('\n')) ]
	print 'lines', lines

	lines = (blockText%negIonDict).split('\n')
	#lines = [(s+'\n') for s in ((blockText%negIonDict).split('\n')) ]
	print 'lines', lines
	negIonMolecule = TopologyFileMolecule( lines )
	
	# Make a TopologyMolecule object for the positive ion
	posIonDict = {}
	posIonDict['molname']   = self.system.positiveIonName
	posIonDict['atom_type'] = ions[self.system.positiveIonName].atomType
	posIonDict['charge']    = ions[self.system.positiveIonName].charge
	posIonDict['mass']      = ions[self.system.positiveIonName].atomicMass
	lines = (blockText%posIonDict).split('\n')
	# lines = [(s+'\n') for s in () ]
	print 'lines', lines
	posIonMolecule = TopologyFileMolecule( lines )

	# Add the ion molecules to the topology file
	top.AddMolecule(negIonMolecule, nn)   # arguments: opologyFileMolecule object, NumberOfMolecules 
	top.AddMolecule(posIonMolecule, np)

	# The number of water molecules needs to be changed to reflect the current count
	numberWatersAfterGenion = nwaters-nn-np
	top.nmols['SOL'] = str(numberWatersAfterGenion)
	
	# Rebuild all the lines in the topfile and save it
	top.rebuild_lines()
	top.write(self.files.next_top())
	self.files.increment_top()    # PrepWorker must increment filename for any new gmx file