def solvate(struct='top/protein.pdb', top='top/system.top', distance=0.9, boxtype='dodecahedron', concentration=0, cation='NA', anion='CL', water='spc', solvent_name='SOL', with_membrane=False, ndx = 'main.ndx', mainselection = '"Protein"', dirname='solvate', **kwargs): """Put protein into box, add water, add counter-ions. Currently this really only supports solutes in water. If you need to embedd a protein in a membrane then you will require more sophisticated approaches. However, you *can* supply a protein already inserted in a bilayer. In this case you will probably want to set *distance* = ``None`` and also enable *with_membrane* = ``True`` (using extra big vdw radii for typical lipids). .. Note:: The defaults are suitable for solvating a globular protein in a fairly tight (increase *distance*!) dodecahedral box. :Arguments: *struct* : filename pdb or gro input structure *top* : filename Gromacs topology *distance* : float When solvating with water, make the box big enough so that at least *distance* nm water are between the solute *struct* and the box boundary. Set *boxtype* to ``None`` in order to use a box size in the input file (gro or pdb). *boxtype* or *bt*: string Any of the box types supported by :class:`~gromacs.tools.Editconf` (triclinic, cubic, dodecahedron, octahedron). Set the box dimensions either with *distance* or the *box* and *angle* keywords. If set to ``None`` it will ignore *distance* and use the box inside the *struct* file. *bt* overrides the value of *boxtype*. *box* List of three box lengths [A,B,C] that are used by :class:`~gromacs.tools.Editconf` in combination with *boxtype* (``bt`` in :program:`editconf`) and *angles*. Setting *box* overrides *distance*. *angles* List of three angles (only necessary for triclinic boxes). *concentration* : float Concentration of the free ions in mol/l. Note that counter ions are added in excess of this concentration. *cation* and *anion* : string Molecule names of the ions. This depends on the chosen force field. *water* : string Name of the water model; one of "spc", "spce", "tip3p", "tip4p". This should be appropriate for the chosen force field. If an alternative solvent is required, simply supply the path to a box with solvent molecules (used by :func:`~gromacs.genbox`'s *cs* argument) and also supply the molecule name via *solvent_name*. *solvent_name* Name of the molecules that make up the solvent (as set in the itp/top). Typically needs to be changed when using non-standard/non-water solvents. ["SOL"] *with_membrane* : bool ``True``: use special ``vdwradii.dat`` with 0.1 nm-increased radii on lipids. Default is ``False``. *ndx* : filename How to name the index file that is produced by this function. *mainselection* : string A string that is fed to :class:`~gromacs.tools.Make_ndx` and which should select the solute. *dirname* : directory name Name of the directory in which all files for the solvation stage are stored. *includes* List of additional directories to add to the mdp include path *kwargs* Additional arguments are passed on to :class:`~gromacs.tools.Editconf` or are interpreted as parameters to be changed in the mdp file. """ structure = realpath(struct) topology = realpath(top) # arguments for editconf that we honour editconf_keywords = ["box", "bt", "angles", "c", "center", "aligncenter", "align", "translate", "rotate", "princ"] editconf_kwargs = dict((k,kwargs.pop(k,None)) for k in editconf_keywords) editconf_boxtypes = ["triclinic", "cubic", "dodecahedron", "octahedron", None] # needed for topology scrubbing scrubber_kwargs = {'marker': kwargs.pop('marker',None)} # sanity checks and argument dependencies bt = editconf_kwargs.pop('bt') boxtype = bt if bt else boxtype # bt takes precedence over boxtype if not boxtype in editconf_boxtypes: msg = "Unsupported boxtype {boxtype!r}: Only {boxtypes!r} are possible.".format(**vars()) logger.error(msg) raise ValueError(msg) if editconf_kwargs['box']: distance = None # if box is set then user knows what she is doing... # handle additional include directories (kwargs are also modified!) mdp_kwargs = cbook.add_mdp_includes(topology, kwargs) if water.lower() in ('spc', 'spce'): water = 'spc216' elif water.lower() == 'tip3p': water = 'spc216' logger.warning("TIP3P water model selected: using SPC equilibrated box " "for initial solvation because it is a reasonable starting point " "for any 3-point model. EQUILIBRATE THOROUGHLY!") # By default, grompp should not choke on a few warnings because at # this stage the user cannot do much about it (can be set to any # value but is kept undocumented...) grompp_maxwarn = kwargs.pop('maxwarn',10) # clean topology (if user added the marker; the default marker is # ; Gromacs auto-generated entries follow: n_removed = cbook.remove_molecules_from_topology(topology, **scrubber_kwargs) with in_dir(dirname): logger.info("[{dirname!s}] Solvating with water {water!r}...".format(**vars())) if boxtype is None: hasBox = False ext = os.path.splitext(structure)[1] if ext == '.gro': hasBox = True elif ext == '.pdb': with open(structure) as struct: for line in struct: if line.startswith('CRYST'): hasBox = True break if not hasBox: msg = "No box data in the input structure {structure!r} and boxtype is set to None".format(**vars()) logger.exception(msg) raise MissingDataError(msg) distance = boxtype = None # ensures that editconf just converts editconf_kwargs.update({'f': structure, 'o': 'boxed.gro', 'bt': boxtype, 'd': distance}) gromacs.editconf(**editconf_kwargs) if with_membrane: vdwradii_dat = get_lipid_vdwradii() # need to clean up afterwards logger.info("Using special vdW radii for lipids {0!r}".format(vdw_lipid_resnames)) try: gromacs.genbox(p=topology, cp='boxed.gro', cs=water, o='solvated.gro') except: if with_membrane: # remove so that it's not picked up accidentally utilities.unlink_f(vdwradii_dat) raise logger.info("Solvated system with %s", water) with open('none.mdp','w') as mdp: mdp.write('; empty mdp file\ninclude = {include!s}\nrcoulomb = 1\nrvdw = 1\nrlist = 1\n'.format(**mdp_kwargs)) qtotgmx = cbook.grompp_qtot(f='none.mdp', o='topol.tpr', c='solvated.gro', p=topology, stdout=False, maxwarn=grompp_maxwarn) qtot = round(qtotgmx) logger.info("[{dirname!s}] After solvation: total charge qtot = {qtotgmx!r} = {qtot!r}".format(**vars())) if concentration != 0: logger.info("[{dirname!s}] Adding ions for c = {concentration:f} M...".format(**vars())) # target concentration of free ions c ==> # N = N_water * c/c_water # add ions for concentration to the counter ions (counter ions are less free) # # get number of waters (count OW ... works for SPC*, TIP*P water models) rc,output,junk = gromacs.make_ndx(f='topol.tpr', o='ow.ndx', input=('keep 0', 'del 0', 'a OW*', 'name 0 OW', '', 'q'), stdout=False) groups = cbook.parse_ndxlist(output) gdict = {g['name']: g for g in groups} # overkill... N_water = gdict['OW']['natoms'] # ... but dict lookup is nice N_ions = int(N_water * concentration/CONC_WATER) # number of monovalents else: N_ions = 0 # neutralize (or try -neutral switch of genion???) n_cation = n_anion = 0 if qtot > 0: n_anion = int(abs(qtot)) elif qtot < 0: n_cation = int(abs(qtot)) n_cation += N_ions n_anion += N_ions if n_cation != 0 or n_anion != 0: # sanity check: assert qtot + n_cation - n_anion < 1e-6 logger.info("[{dirname!s}] Adding n_cation = {n_cation:d} and n_anion = {n_anion:d} ions...".format(**vars())) gromacs.genion(s='topol.tpr', o='ionized.gro', p=topology, pname=cation, nname=anion, np=n_cation, nn=n_anion, input=solvent_name) else: # fake ionized file ... makes it easier to continue without too much fuzz try: os.unlink('ionized.gro') except OSError, err: if err.errno != errno.ENOENT: raise os.symlink('solvated.gro', 'ionized.gro') qtot = cbook.grompp_qtot(f='none.mdp', o='ionized.tpr', c='ionized.gro', p=topology, stdout=False, maxwarn=grompp_maxwarn) if abs(qtot) > 1e-4: wmsg = "System has non-zero total charge qtot = {qtot:g} e.".format(**vars()) warnings.warn(wmsg, category=BadParameterWarning) logger.warn(wmsg) # make main index try: make_main_index('ionized.tpr', selection=mainselection, ndx=ndx) except GromacsError, err: # or should I rather fail here? wmsg = "Failed to make main index file %r ... maybe set mainselection='...'.\n"\ "The error message was:\n%s\n" % (ndx, str(err)) logger.warn(wmsg) warnings.warn(wmsg, category=GromacsFailureWarning)
def solvate(struct='top/protein.pdb', top='top/system.top', distance=0.9, boxtype='dodecahedron', concentration=0, cation='NA', anion='CL', water='spc', solvent_name='SOL', with_membrane=False, ndx='main.ndx', mainselection='"Protein"', dirname='solvate', **kwargs): """Put protein into box, add water, add counter-ions. Currently this really only supports solutes in water. If you need to embedd a protein in a membrane then you will require more sophisticated approaches. However, you *can* supply a protein already inserted in a bilayer. In this case you will probably want to set *distance* = ``None`` and also enable *with_membrane* = ``True`` (using extra big vdw radii for typical lipids). .. Note:: The defaults are suitable for solvating a globular protein in a fairly tight (increase *distance*!) dodecahedral box. :Arguments: *struct* : filename pdb or gro input structure *top* : filename Gromacs topology *distance* : float When solvating with water, make the box big enough so that at least *distance* nm water are between the solute *struct* and the box boundary. Set *boxtype* to ``None`` in order to use a box size in the input file (gro or pdb). *boxtype* or *bt*: string Any of the box types supported by :class:`~gromacs.tools.Editconf` (triclinic, cubic, dodecahedron, octahedron). Set the box dimensions either with *distance* or the *box* and *angle* keywords. If set to ``None`` it will ignore *distance* and use the box inside the *struct* file. *bt* overrides the value of *boxtype*. *box* List of three box lengths [A,B,C] that are used by :class:`~gromacs.tools.Editconf` in combination with *boxtype* (``bt`` in :program:`editconf`) and *angles*. Setting *box* overrides *distance*. *angles* List of three angles (only necessary for triclinic boxes). *concentration* : float Concentration of the free ions in mol/l. Note that counter ions are added in excess of this concentration. *cation* and *anion* : string Molecule names of the ions. This depends on the chosen force field. *water* : string Name of the water model; one of "spc", "spce", "tip3p", "tip4p". This should be appropriate for the chosen force field. If an alternative solvent is required, simply supply the path to a box with solvent molecules (used by :func:`~gromacs.genbox`'s *cs* argument) and also supply the molecule name via *solvent_name*. *solvent_name* Name of the molecules that make up the solvent (as set in the itp/top). Typically needs to be changed when using non-standard/non-water solvents. ["SOL"] *with_membrane* : bool ``True``: use special ``vdwradii.dat`` with 0.1 nm-increased radii on lipids. Default is ``False``. *ndx* : filename How to name the index file that is produced by this function. *mainselection* : string A string that is fed to :class:`~gromacs.tools.Make_ndx` and which should select the solute. *dirname* : directory name Name of the directory in which all files for the solvation stage are stored. *includes* List of additional directories to add to the mdp include path *kwargs* Additional arguments are passed on to :class:`~gromacs.tools.Editconf` or are interpreted as parameters to be changed in the mdp file. """ structure = realpath(struct) topology = realpath(top) # arguments for editconf that we honour editconf_keywords = [ "box", "bt", "angles", "c", "center", "aligncenter", "align", "translate", "rotate", "princ" ] editconf_kwargs = dict((k, kwargs.pop(k, None)) for k in editconf_keywords) editconf_boxtypes = [ "triclinic", "cubic", "dodecahedron", "octahedron", None ] # needed for topology scrubbing scrubber_kwargs = {'marker': kwargs.pop('marker', None)} # sanity checks and argument dependencies bt = editconf_kwargs.pop('bt') boxtype = bt if bt else boxtype # bt takes precedence over boxtype if not boxtype in editconf_boxtypes: msg = "Unsupported boxtype {boxtype!r}: Only {boxtypes!r} are possible.".format( **vars()) logger.error(msg) raise ValueError(msg) if editconf_kwargs['box']: distance = None # if box is set then user knows what she is doing... # handle additional include directories (kwargs are also modified!) mdp_kwargs = cbook.add_mdp_includes(topology, kwargs) if water.lower() in ('spc', 'spce'): water = 'spc216' elif water.lower() == 'tip3p': water = 'spc216' logger.warning( "TIP3P water model selected: using SPC equilibrated box " "for initial solvation because it is a reasonable starting point " "for any 3-point model. EQUILIBRATE THOROUGHLY!") # By default, grompp should not choke on a few warnings because at # this stage the user cannot do much about it (can be set to any # value but is kept undocumented...) grompp_maxwarn = kwargs.pop('maxwarn', 10) # clean topology (if user added the marker; the default marker is # ; Gromacs auto-generated entries follow: n_removed = cbook.remove_molecules_from_topology(topology, **scrubber_kwargs) with in_dir(dirname): logger.info( "[{dirname!s}] Solvating with water {water!r}...".format(**vars())) if boxtype is None: hasBox = False ext = os.path.splitext(structure)[1] if ext == '.gro': hasBox = True elif ext == '.pdb': with open(structure) as struct: for line in struct: if line.startswith('CRYST'): hasBox = True break if not hasBox: msg = "No box data in the input structure {structure!r} and boxtype is set to None".format( **vars()) logger.exception(msg) raise MissingDataError(msg) distance = boxtype = None # ensures that editconf just converts editconf_kwargs.update({ 'f': structure, 'o': 'boxed.gro', 'bt': boxtype, 'd': distance }) gromacs.editconf(**editconf_kwargs) if with_membrane: vdwradii_dat = get_lipid_vdwradii() # need to clean up afterwards logger.info("Using special vdW radii for lipids {0!r}".format( vdw_lipid_resnames)) try: gromacs.genbox(p=topology, cp='boxed.gro', cs=water, o='solvated.gro') except: if with_membrane: # remove so that it's not picked up accidentally utilities.unlink_f(vdwradii_dat) raise logger.info("Solvated system with %s", water) with open('none.mdp', 'w') as mdp: mdp.write( '; empty mdp file\ninclude = {include!s}\nrcoulomb = 1\nrvdw = 1\nrlist = 1\n' .format(**mdp_kwargs)) qtotgmx = cbook.grompp_qtot(f='none.mdp', o='topol.tpr', c='solvated.gro', p=topology, stdout=False, maxwarn=grompp_maxwarn) qtot = round(qtotgmx) logger.info( "[{dirname!s}] After solvation: total charge qtot = {qtotgmx!r} = {qtot!r}" .format(**vars())) if concentration != 0: logger.info( "[{dirname!s}] Adding ions for c = {concentration:f} M...". format(**vars())) # target concentration of free ions c ==> # N = N_water * c/c_water # add ions for concentration to the counter ions (counter ions are less free) # # get number of waters (count OW ... works for SPC*, TIP*P water models) rc, output, junk = gromacs.make_ndx(f='topol.tpr', o='ow.ndx', input=('keep 0', 'del 0', 'a OW*', 'name 0 OW', '', 'q'), stdout=False) groups = cbook.parse_ndxlist(output) gdict = {g['name']: g for g in groups} # overkill... N_water = gdict['OW']['natoms'] # ... but dict lookup is nice N_ions = int(N_water * concentration / CONC_WATER) # number of monovalents else: N_ions = 0 # neutralize (or try -neutral switch of genion???) n_cation = n_anion = 0 if qtot > 0: n_anion = int(abs(qtot)) elif qtot < 0: n_cation = int(abs(qtot)) n_cation += N_ions n_anion += N_ions if n_cation != 0 or n_anion != 0: # sanity check: assert qtot + n_cation - n_anion < 1e-6 logger.info( "[{dirname!s}] Adding n_cation = {n_cation:d} and n_anion = {n_anion:d} ions..." .format(**vars())) gromacs.genion(s='topol.tpr', o='ionized.gro', p=topology, pname=cation, nname=anion, np=n_cation, nn=n_anion, input=solvent_name) else: # fake ionized file ... makes it easier to continue without too much fuzz try: os.unlink('ionized.gro') except OSError, err: if err.errno != errno.ENOENT: raise os.symlink('solvated.gro', 'ionized.gro') qtot = cbook.grompp_qtot(f='none.mdp', o='ionized.tpr', c='ionized.gro', p=topology, stdout=False, maxwarn=grompp_maxwarn) if abs(qtot) > 1e-4: wmsg = "System has non-zero total charge qtot = {qtot:g} e.".format( **vars()) warnings.warn(wmsg, category=BadParameterWarning) logger.warn(wmsg) # make main index try: make_main_index('ionized.tpr', selection=mainselection, ndx=ndx) except GromacsError, err: # or should I rather fail here? wmsg = "Failed to make main index file %r ... maybe set mainselection='...'.\n"\ "The error message was:\n%s\n" % (ndx, str(err)) logger.warn(wmsg) warnings.warn(wmsg, category=GromacsFailureWarning)
def solvate_sol(struct='top/protein.pdb', top='top/system.top', distance=0.9, boxtype='dodecahedron', water='tip4p', solvent_name='SOL', with_membrane=False, dirname='solvate', **kwargs): structure = realpath(struct) topology = realpath(top) # arguments for editconf that we honour editconf_keywords = ["box", "bt", "angles", "c", "center", "aligncenter", "align", "translate", "rotate", "princ"] editconf_kwargs = dict((k,kwargs.pop(k,None)) for k in editconf_keywords) editconf_boxtypes = ["triclinic", "cubic", "dodecahedron", "octahedron", None] # needed for topology scrubbing scrubber_kwargs = {'marker': kwargs.pop('marker',None)} # sanity checks and argument dependencies bt = editconf_kwargs.pop('bt') boxtype = bt if bt else boxtype # bt takes precedence over boxtype if not boxtype in editconf_boxtypes: msg = "Unsupported boxtype {boxtype!r}: Only {boxtypes!r} are possible.".format(**vars()) logger.error(msg) raise ValueError(msg) if editconf_kwargs['box']: distance = None # if box is set then user knows what she is doing... if water.lower() in ('spc', 'spce'): water = 'spc216' elif water.lower() == 'tip3p': water = 'spc216' logger.warning("TIP3P water model selected: using SPC equilibrated box " "for initial solvation because it is a reasonable starting point " "for any 3-point model. EQUILIBRATE THOROUGHLY!") # clean topology (if user added the marker; the default marker is # ; Gromacs auto-generated entries follow: n_removed = cbook.remove_molecules_from_topology(topology, **scrubber_kwargs) with in_dir(dirname): logger.info("[{dirname!s}] Solvating with water {water!r}...".format(**vars())) if boxtype is None: hasBox = False ext = os.path.splitext(structure)[1] if ext == '.gro': hasBox = True elif ext == '.pdb': with open(structure) as struct: for line in struct: if line.startswith('CRYST'): hasBox = True break if not hasBox: msg = "No box data in the input structure {structure!r} and boxtype is set to None".format(**vars()) logger.exception(msg) raise MissingDataError(msg) distance = boxtype = None # ensures that editconf just converts editconf_kwargs.update({'f': structure, 'o': 'boxed.gro', 'bt': boxtype, 'd': distance}) gromacs.editconf(**editconf_kwargs) if with_membrane: vdwradii_dat = get_lipid_vdwradii() # need to clean up afterwards logger.info("Using special vdW radii for lipids {0!r}".format(vdw_lipid_resnames)) try: gromacs.genbox(p=topology, cp='boxed.gro', cs=water, o='solvated.gro') except: if with_membrane: # remove so that it's not picked up accidentally utilities.unlink_f(vdwradii_dat) raise logger.info("Solvated system with %s", water) return {'struct': realpath(dirname, 'solvated.gro'),}
def solvate_sol(struct='top/protein.pdb', top='top/system.top', distance=0.9, boxtype='dodecahedron', water='tip4p', solvent_name='SOL', with_membrane=False, dirname='solvate', **kwargs): structure = realpath(struct) topology = realpath(top) # arguments for editconf that we honour editconf_keywords = [ "box", "bt", "angles", "c", "center", "aligncenter", "align", "translate", "rotate", "princ" ] editconf_kwargs = dict((k, kwargs.pop(k, None)) for k in editconf_keywords) editconf_boxtypes = [ "triclinic", "cubic", "dodecahedron", "octahedron", None ] # needed for topology scrubbing scrubber_kwargs = {'marker': kwargs.pop('marker', None)} # sanity checks and argument dependencies bt = editconf_kwargs.pop('bt') boxtype = bt if bt else boxtype # bt takes precedence over boxtype if not boxtype in editconf_boxtypes: msg = "Unsupported boxtype {boxtype!r}: Only {boxtypes!r} are possible.".format( **vars()) logger.error(msg) raise ValueError(msg) if editconf_kwargs['box']: distance = None # if box is set then user knows what she is doing... if water.lower() in ('spc', 'spce'): water = 'spc216' elif water.lower() == 'tip3p': water = 'spc216' logger.warning( "TIP3P water model selected: using SPC equilibrated box " "for initial solvation because it is a reasonable starting point " "for any 3-point model. EQUILIBRATE THOROUGHLY!") # clean topology (if user added the marker; the default marker is # ; Gromacs auto-generated entries follow: n_removed = cbook.remove_molecules_from_topology(topology, **scrubber_kwargs) with in_dir(dirname): logger.info( "[{dirname!s}] Solvating with water {water!r}...".format(**vars())) if boxtype is None: hasBox = False ext = os.path.splitext(structure)[1] if ext == '.gro': hasBox = True elif ext == '.pdb': with open(structure) as struct: for line in struct: if line.startswith('CRYST'): hasBox = True break if not hasBox: msg = "No box data in the input structure {structure!r} and boxtype is set to None".format( **vars()) logger.exception(msg) raise MissingDataError(msg) distance = boxtype = None # ensures that editconf just converts editconf_kwargs.update({ 'f': structure, 'o': 'boxed.gro', 'bt': boxtype, 'd': distance }) gromacs.editconf(**editconf_kwargs) if with_membrane: vdwradii_dat = get_lipid_vdwradii() # need to clean up afterwards logger.info("Using special vdW radii for lipids {0!r}".format( vdw_lipid_resnames)) try: gromacs.genbox(p=topology, cp='boxed.gro', cs=water, o='solvated.gro') except: if with_membrane: # remove so that it's not picked up accidentally utilities.unlink_f(vdwradii_dat) raise logger.info("Solvated system with %s", water) return { 'struct': realpath(dirname, 'solvated.gro'), }
#!/usr/bin/env python import sys import os import gromacs import numpy as np solute = sys.argv[1] outname = solute.split(".")[0] + "_b" + ".gro" gromacs.editconf(f=solute, box=list((input("Enter the box size: ").split())), o=outname) # center=list(input("Enter the position for solute: ").split()),
#!/usr/bin/env python import gromacs import sys, os grofile = sys.argv[1] gromacs.editconf(f=grofile, translate=list(input("Enter the translate vector: ").split()), o="out.gro")
def add_box_mutation(self): """ Function to add the solvent and run a minimization of the local amino acid with the waters included Output: system.gro -- file containing the complete system minimized after the mutation """ # Read the solvent os.system("grep ATOM {path}/solvent/solvent_{itera}.pdb | grep -v ENDMDL > {path}/solvent.pdb".format(path=self.path,itera=self.last_iteration)) # Concatenate complex and system os.system("cat {path}/complex.pdb {path}/solvent.pdb > {path}/system.pdb".format(path=self.path)) rc,sout,serr=gromacs.editconf(f=self.path+"/system.pdb", o=self.path+"/system_mod.pdb", stdout=False) os.system("mv {}/system_mod.pdb {}/system.pdb".format(self.path,self.path)) # Make an index of the system rc,sout,serr=gromacs.make_ndx(f=self.path+"/system.pdb", o=self.path+"/index.ndx", stdout=False, input=('chain {} \n q'.format(self.pep_chain))) # Copy the topol files of the target chains, which are the same always if self.target=="protein": for ch in self.chain_join: os.system("cp {}/topol_Protein_chain_{}.itp {}/system_Protein_chain_{}.itp".format(self.path,ch,self.path,ch)) if self.target=="drug": for ch in self.chain_join: os.system("cp {}/topol_Drug_chain_{}.itp {}/system_Drug_chain_{}.itp".format(self.path,ch,self.path,ch)) # Copy the topol.top to system.top os.system("cp {}/topol.top {}/system.top".format(self.path,self.path)) os.system("cp {}/complex_Protein_chain_{}.itp {}/system_Protein_chain_{}.itp".format(self.path,self.pep_chain,self.path,self.pep_chain)) os.system("sed -i 's/topol_/system_/g' {}/system.top".format(self.path)) # Select water and ions within 0.2 distance of the residue rc,sout,serr=gromacs.make_ndx(f=self.path+"/system.pdb", o=self.path+"/index.ndx", stdout=False, input=('chain {}'.format(self.pep_chain),'q')) rc,sout,serr=gromacs.select(f=self.path+"/system.pdb", n=self.path+"/index.ndx", s=self.path+"/system.pdb", on=self.path+"/index_sol.ndx", stdout=False, select="group Water_and_ions and same residue as within 0.2 of (group ch{} and resnr {})".format(self.pep_chain,self.pep_position)) # Solve the issue with atoms overlapped with the selected residue values=[x.strip() for x in open(self.path+"/index_sol.ndx")] atomsSOL=[] for i,v in enumerate(values): if i!=0: info=v.split() atomsSOL=atomsSOL+info # List of the atoms that will be deleted atomsDelete=[] # Check the overlapped atoms for a in atomsSOL: # Obtain the list of atoms from the index file bash = "awk '$2 == '{}' {{print $6','$7','$8}}' {}/system.pdb".format(a,self.path) coordinates = subprocess.check_output(['bash','-c', bash]) comp=coordinates.strip().split() comparison=[] for c in comp: comparison.append(float(c)) ndComp=np.array(comparison) distancesSOL=[] # Read the structure in biopython parser = PDBParser() structure = parser.get_structure('PEP', self.path+"/system.pdb") model = structure[0] # Check the distances with all the atoms from the selected residue for residue in model[self.pep_chain]: resC=residue.get_resname() resNumber=residue.get_full_id()[3][1] if resNumber==self.pep_position: for atom in residue: idAtom = atom.get_id() if idAtom[0].isdigit() == False: if resC=="ILE" and idAtom=="CD": idAtom="CD1" diff = atom.coord - ndComp diffValue=np.sqrt(np.sum(diff * diff)) distancesSOL.append(float(diffValue)) # Threshold to determine which atoms can be overlapped if min(distancesSOL)<1.0: if a not in atomsDelete: atomsDelete.append(a) # Selection of the final atoms that will be included in the index final_index=[] for element in atomsSOL: flag=0 for delete in atomsDelete: if abs(int(element)-int(delete))<=2: flag=1 if flag==0: final_index.append(element) # Update of the index sol file new_index=open(self.path+"/index_sol2.ndx","w") new_index.write("{}\n".format(values[0])) group=[] counter=1 for ele in final_index: if counter <15: group.append(ele) counter+=1 else: group.append(ele) new_index.write(" ".join(group)+" \n") counter=1 group=[] new_index.write(" ".join(group)+" ") new_index.close() # Update the file os.system("mv {}/index_sol2.ndx {}/index_sol.ndx".format(self.path,self.path)) ref_ndx = NDX() ref_ndx.read(self.path+"/index.ndx") bash="grep '\[' {}/index.ndx | wc -l".format(self.path) number_index = subprocess.check_output(['bash','-c', bash]) index_ref=int(number_index)-1 #index_ref=len(ref_ndx)-1 # Create the side chain index in a template file os.system("echo 'name 0 overlap' > %s/template" %self.path) os.system("echo '\"SideChain\" & \"ch{}\" & r {}' >> {}/template".format(self.pep_chain,str(self.pep_position),self.path)) os.system("echo '\"overlap\" | \"SideChain_&_ch{}_&_r_{}\"' >> {}/template".format(self.pep_chain,str(self.pep_position),self.path)) os.system("echo '\"System\" &! \"overlap_SideChain_&_ch{}_&_r_{}\"' >> {}/template".format(self.pep_chain,str(self.pep_position),self.path)) os.system("echo 'q' >> {}/template".format(self.path)) # Create an index joining both created before os.system("gmx -quiet make_ndx -f {path}/system.pdb -n {path}/index_sol.ndx {path}/index.ndx -o {path}/total_index.ndx < {path}/template".format(path=self.path)) os.system("sed -i 's/System_&_\!overlap_SideChain_&_ch{}_&_r_{}/to_block/g' {}/total_index.ndx".format(self.pep_chain,str(self.pep_position),self.path)) # Generate the gro file rc,sout,serr=gromacs.editconf(f=self.path+"/system.pdb", o=self.path+"/system.gro", stdout=False) # Prepare the files for the minimization and run rc,sout,serr=gromacs.grompp(f=self.path+"/mdp/minim_overlap.mdp", o=self.path+"/systemNEW.tpr", p=self.path+"/system.top", n=self.path+"/total_index.ndx", c=self.path+"/system.gro", stdout=False) gromacs.utilities.unlink_gmx("mdout.mdp") print("Running second minimization ...") rc,sout,serr=gromacs.mdrun(deffnm=self.path+"/systemNEW", stdout=False) # Copy the system.gro file that will be used to run the last minimization os.system("cp {}/systemNEW.gro {}/system.gro".format(self.path,self.path)) os.system("sed -i '$ d' {}/system.gro".format(self.path)) os.system("tail -n1 {path}/npt-pbc.gro >> {path}/system.gro".format(path=self.path)) # Delete temporal files os.system("rm {path}/complex.pdb {path}/solvent.pdb {path}/systemNEW* {path}/template {path}/index.ndx {path}/index_sol.ndx {path}/total_index.ndx *.itp".format(path=self.path))
def run_minim_complex(self,run_minim=False): """ Function to run a local minimization on the side chain that was mutated Arguments: run_minim -- boolean flag that will control if the minimization is run or not Output: complex.pdb -- new complex pdb with the minimization and the new itp files """ # Get the chain with the peptide to generate a novel itp file os.system("python3 {}/src/scores/get_chains.py {}/complex.pdb {}".format(self.path_scores,self.path,self.path)) rc,sout,serr=gromacs.pdb2gmx(f=self.path+"/complex_"+self.pep_chain+".pdb", p=self.path+"/binder.top", o=self.path+"/complex_"+self.pep_chain+".gro", stdout=False, input=('6','6')) os.system("sed -i '/forcefield/d' {}/binder.top".format(self.path)) os.system("sed -i '/\[ system \]/,$d' {}/binder.top".format(self.path)) os.system("mv {}/binder.top {}/complex_Protein_chain_{}.itp".format(self.path,self.path,self.pep_chain)) rc,sout,serr=gromacs.editconf(f=self.path+"/complex_"+self.pep_chain+".gro", o=self.path+"/complex_"+self.pep_chain+".pdb", stdout=False) # Fix the amino acid nomenclature os.system("for i in ASP ARG HIS HIE HID HIP LYS GLU SER THR ASN GLN CYS CYX GLY PRO ALA VAL ILE LEU MET PHE TYR TRP; do sed -i s/\"$i \"/\"$i {}\"/g {}/complex_{}.pdb; done".format(self.pep_chain,self.path,self.pep_chain)) for i,ch in enumerate(self.chain_join): if i==0: os.system("grep ATOM {}/complex_{}.pdb > {}/complex.pdb".format(self.path,ch,self.path)) os.system("echo 'TER' >> {}/complex.pdb".format(self.path)) else: os.system("grep ATOM {}/complex_{}.pdb >> {}/complex.pdb".format(self.path,ch,self.path)) os.system("echo 'TER' >> {}/complex.pdb".format(self.path)) # Get the new complex.pdb and the peptide chain itp file and delete temporal files os.system("grep ATOM {}/complex_{}.pdb >> {}/complex.pdb".format(self.path,self.pep_chain,self.path)) os.system("echo 'TER' >> {}/complex.pdb".format(self.path)) os.system("rm {}/complex_*.pdb".format(self.path)) os.system("rm {}/complex_*.gro".format(self.path)) os.system("rm {}/chains.seq".format(self.path)) os.system("head -n -18 {}/complex_Protein_chain_{}.itp > {}/temp; mv {}/temp {}/complex_Protein_chain_{}.itp".format(self.path,self.pep_chain,self.path,self.path,self.path,self.pep_chain)) # Copy the topol files of the target chains, which are the same always # Copy the topol files of the target chains, which are the same always if self.target=="protein": for ch in self.chain_join: os.system("cp {}/topol_Protein_chain_{}.itp {}/complex_Protein_chain_{}.itp".format(self.path,ch,self.path,ch)) if self.target=="drug": for ch in self.chain_join: os.system("cp {}/topol_Drug_chain_{}.itp {}/complex_Drug_chain_{}.itp".format(self.path,ch,self.path,ch)) # Copy the topol.top to complex.top and delete all the additional atoms os.system("cp {}/topol.top {}/complex.top".format(self.path,self.path)) os.system("sed -i '/Ion/d' {}/complex.top".format(self.path)) os.system("sed -i '/SOL/d' {}/complex.top".format(self.path)) os.system("sed -i '/NA/d' {}/complex.top".format(self.path)) os.system("sed -i '/CL/d' {}/complex.top".format(self.path)) os.system("sed -i '/solvent/d' {}/complex.top".format(self.path)) os.system("sed -i 's/topol_/complex_/g' {}/complex.top".format(self.path)) # Get a pdb of the complex where an index will be created rc,sout,serr=gromacs.make_ndx(f=self.path+"/complex.pdb", o=self.path+"/reference.ndx", stdout=False, input=('q')) ref_ndx = NDX() ref_ndx.read(self.path+"/reference.ndx") #index_ref=len(ref_ndx)-1 bash="grep '\[' {}/reference.ndx | wc -l".format(self.path) number_index = subprocess.check_output(['bash','-c', bash]) index_ref=int(number_index)-1 gromacs.utilities.unlink_gmx(self.path+"/reference.ndx") # Create the side chain index input_for_ndx=() counter=index_ref input_for_ndx+=('chain {}'.format(self.pep_chain),); counter+=1 input_for_ndx+=('name {} binder'.format(counter),); input_for_ndx+=('"SideChain" & "binder"'+' & r {}'.format(self.pep_position),); counter+=1 input_for_ndx+=('"System" &! {}'.format(counter),); counter+=1 input_for_ndx+=('name {} scmut'.format(counter),); sentence="" for i,ch in enumerate(self.chain_join): if i==0: sentence=sentence+"chain {}".format(ch) else: sentence=sentence+" | chain {}".format(ch) input_for_ndx+=(sentence,); counter+=1 input_for_ndx+=('name {} target'.format(counter),) input_for_ndx+=('\"target\" | \"binder\"',); counter+=1 input_for_ndx+=('name {} complex'.format(counter),) input_for_ndx+=('q',) # Generate the index file rc,sout,serr=gromacs.make_ndx(f=self.path+"/complex.pdb", o=self.path+"/scmut.ndx", stdout=False, input=input_for_ndx) # Generate the gro file rc,sout,serr=gromacs.editconf(f=self.path+"/complex.pdb", o=self.path+"/complex.gro", stdout=False) # Add a small box for the residues os.system("sed -i '$ d' {}/complex.gro".format(self.path)) os.system('echo " 20.0 20.0 20.0" >> {path}/complex.gro'.format(path=self.path)) # Prepare the files for the minimization rc,sout,serr=gromacs.grompp(f=self.path+"/mdp/minim_scmut.mdp", o=self.path+"/complex.tpr", p=self.path+"/complex.top", n=self.path+"/scmut.ndx", c=self.path+"/complex.gro", stdout=False) gromacs.utilities.unlink_gmx("mdout.mdp") # Run the minimization of the side chain alone and the residues around it if run_minim: # Run the minimization print("Running first minimization ...") rc,sout,serr=gromacs.mdrun(deffnm=self.path+"/complex", stdout=False) # Get the complex pdb file rc,sout,serr=gromacs.trjconv(f=self.path+"/complex.gro",s=self.path+"/complex.tpr", n=self.path+"/scmut.ndx", o=self.path+"/min_complex.pdb",stdout=False,input=("complex")) os.system("rm posre.itp {path}/complex.tpr {path}/complex.top; grep -v ENDMDL {path}/min_complex.pdb | grep -v MODEL > {path}/complex.pdb; rm {path}/min_complex.pdb {path}/complex.log {path}/complex.trr {path}/complex.edr {path}/scmut.ndx".format(path=self.path))
#tr_vector= np.asarray([0, 0, u1.dimensions[2]/10]) #print(tr_vector) ###SET UP THE PROTEIN BOX print("This stage is to setup protein box to combine to membrane box!!!") #boxsize = input("enter the box size: ").split() z_box = float(input("enter the box size along z: ")) x_box = u1.dimensions[0] / 10 y_box = u1.dimensions[1] / 10 boxsize = [x_box, y_box, z_box] #print(boxsize) #print(type(z_box)) center = [ x_box / 2, y_box / 2, float(input("enter the coordinates you want to place protein along z: ")) ] filename = input("provide the file name of residue: ") outname = filename.split(".")[0] outname_b = outname + "_b" + ".gro" gromacs.editconf(f=filename, o=outname_b, box=boxsize, center=center) outname_bw = outname + "_bw" + ".gro" gromacs.solvate(cp=outname_b, o="out.gro") gromacs.editconf(f="out.gro", translate=tr_vector, o=outname_bw) # ## #### COMBINE MEMBRANE GRO FILE AND PEPTIDE GRO FILE u2 = mda.Universe(outname_bw) u12 = mda.Merge(u2.atoms, u1.atoms) u12.atoms.write(str(sys.argv[1]).split(".")[0] + "_" + outname + ".gro")
os.rename( protein_name + '.D00000001', './inactives/incomplete/' + protein_name + '_inactive_logFile') modelname = ('./inactives/incomplete/' + protein_name + '_inactive.pdb') briefname = ('./inactives/incomplete/' + protein_name + '_inactive') briefername = (protein_name + '_inactive') dir_name = ('./inactives/incomplete/') is_active = 0 for filename in glob.glob("./" + protein_name + "*"): os.remove(filename) #mutate_model.py gromacs.editconf(f=modelname, resnr=first_res, o=modelname) if re.search('no_mutation', mutation) is not None: print 'No mutations here' else: print "Looks like we've got a mutation. Let's check it out. \n" different_mutations = re.split('&', mutation) for mutant_res in range(0, len(different_mutations)): is_mutated = re.search(r"([a-z])([0-9]+)([a-z])", different_mutations[mutant_res], re.I) if is_mutated: mutations_list = is_mutated.groups() respos = mutations_list[1] restyp = pdb.Polypeptide.one_to_three( mutations_list[0]) #get three letter code
dir_name = ('./inactives/complete/') is_active = 0 else: os.rename(protein_name+'.B99990001.pdb', './inactives/incomplete/'+protein_name+'_inactive.pdb') os.rename(protein_name+'.D00000001', './inactives/incomplete/'+protein_name+'_inactive_logFile') modelname = ('./inactives/incomplete/'+protein_name+'_inactive.pdb') briefname = ('./inactives/incomplete/'+protein_name+'_inactive') briefername = (protein_name+'_inactive') dir_name = ('./inactives/incomplete/') is_active = 0 for filename in glob.glob("./"+protein_name+"*"): os.remove(filename) #mutate_model.py gromacs.editconf(f = modelname, resnr = first_res, o = modelname) if re.search('no_mutation', mutation) is not None: print 'No mutations here' else: print "Looks like we've got a mutation. Let's check it out. \n" different_mutations = re.split('&', mutation) for mutant_res in range(0, len(different_mutations)): is_mutated = re.search(r"([a-z])([0-9]+)([a-z])", different_mutations[mutant_res], re.I) if is_mutated: mutations_list = is_mutated.groups() respos = mutations_list[1] restyp = pdb.Polypeptide.one_to_three(mutations_list[0]) #get three letter code #makes use of the optimize function in modeller