def test_multiple_insertion_codes(tmpdir): from dabble.param import CharmmWriter # Generate the file p = str(tmpdir) molid = molecule.load("mae", os.path.join(dir, "3PTB_1lig_prepped.mae")) w = CharmmWriter(molid=molid, tmp_dir=p, forcefield="charmm", hmr=False, override_defaults=False) w.write(os.path.join(p, "test")) # Load the output file and start checking it m2 = molecule.load("psf", os.path.join(p, "test.psf"), "pdb", os.path.join(p, "test.pdb")) molecule.set_top(m2) # Check the entire protein is there and connected assert len(atomsel("protein or resname ACE NMA NME")) == 3229 assert len(set(atomsel("protein or resname ACE NMA NME").fragment)) == 1 # Check the calcium ion is present assert atomsel("element Ca").resname == ["CAL"] # Check residues with insertion codes assert set(atomsel("resid 184").resname) == set(["GLY", "TYR"]) assert set(atomsel("resid 188").resname) == set(["GLY", "LYS"]) assert set(atomsel("resid 221").resname) == set(["ALA", "GLN"]) assert set(atomsel("resid 245").resname) == set(["ASN", "NMA"]) assert set(atomsel("all").insertion) == set([" ", "A"]) # Check the ligand is there assert len(atomsel("resname BAMI")) == 18
def get_topologies(cls, forcefield, water_model): """ Gets the path to GROMACS-format topologies for a given force field """ # Amber, Charmm, and OPLS handled by conversion if forcefield == "charmm": return CharmmWriter.get_topologies(forcefield, water_model) if forcefield == "amber": return AmberWriter.get_topologies(forcefield, water_model) if forcefield == "opls": return CharmmWriter.get_topologies(forcefield, water_model) # No forcefields really ship with gromacs right now because # I found an error in the OPLS AA/M gromacs implementation and # they won't respond to my emails # Use GROMACS forcefield for the remaining ones #if forcefield == "opls": # ffdir = "oplsaam.ff" #elif forcefield == "gromos": # ffdir = "gromos54a7.ff" raise DabbleError("Unsupported forcefield %s" % forcefield)
def test_multiligand_psf_opls(tmpdir): """ Charmm parameters, OPLS AA/M format """ from dabble.param import CharmmWriter p = str(tmpdir) molid = molecule.load("mae", os.path.join(dir, "test_multiligand_correct.mae")) # lipid unsupported w = CharmmWriter(tmp_dir=p, molid=molid, forcefield="opls", extra_topos=[os.path.join(dir, "dalp_opls.rtf")], extra_params=[os.path.join(dir, "dalp_opls.prm")]) with pytest.raises(ValueError): w.write(os.path.join(p, "test")) # No lipid should work molecule.delete(molid) molid = molecule.load("mae", os.path.join(dir, "B2AR_10ALPs.mae")) w = CharmmWriter(tmp_dir=p, molid=molid, forcefield="opls", extra_topos=[os.path.join(dir, "dalp_opls.rtf")], extra_params=[os.path.join(dir, "dalp_opls.prm")]) w.write(os.path.join(p, "test")) check_result("psf", p, solvent=False, lipid=False)
def write(self, filename): """ Writes the parameter and topology files. Args: filename (str): File name to write. Gromacs suffix will be added. """ self.outprefix = filename # Charmm forcefield if "charmm" in self.forcefield or "opls" in self.forcefield: psfgen = CharmmWriter(molid=self.molid, tmp_dir=self.tmp_dir, lipid_sel=self.lipid_sel, forcefield=self.forcefield, water_model=self.water_model, hmr=self.hmr, extra_topos=self.extra_topos, extra_params=self.extra_params, override_defaults=self.override) print("Writing intermediate psf") psfgen.write(self.outprefix) self._psf_to_gromacs() elif "amber" in self.forcefield: prmgen = AmberWriter(molid=self.molid, tmp_dir=self.tmp_dir, forcefield=self.forcefield, water_model=self.water_model, hmr=self.hmr, lipid_sel=self.lipid_sel, extra_topos=self.extra_topos, extra_params=self.extra_params, override_defaults=self.override) print("Writing intermediate prmtop") prmgen.write(self.outprefix) self._amber_to_gromacs() # Now native GROMACS style for gromos or opls else: # Currently unsupported raise DabbleError("Forcefield '%s' not supported for gromacs" % self.forcefield) print("Using the following topology files and/or directories:") for top in self.topologies: print(" - %s" % os.path.split(top)[1]) self._set_atom_names() self._run_pdb2gmx()
def test_relaxin_disulfides_charmm(tmpdir): """ Tests these disulfides with charmm """ from dabble.param import CharmmWriter from vmd import molecule # Build the system p = str(tmpdir) molid = molecule.load("mae", os.path.join(dir, "2MV1_dowserwat.mae")) w = CharmmWriter(tmp_dir=p, molid=molid) w.write(os.path.join(p, "test")) # Check the built system m2 = molecule.load("psf", os.path.join(p, "test.psf")) check_correctness(m2)
def get_parameters(cls, forcefield, water_model): """ Get the path to GROMACS-format parameter files for a given force field """ # Amber and Charmm handled by converstion if forcefield == "charmm": return CharmmWriter.get_parameters(forcefield, water_model) if forcefield == "amber": return AmberWriter.get_parameters(forcefield, water_model) if forcefield == "opls": return CharmmWriter.get_parameters(forcefield, water_model) # Gromacs topologies and parameters are the same directories return GromacsWriter.get_topologies(forcefield, water_model)
def test_multiligand_psf_charmm(tmpdir): """ Checks the parameterization of a system with multiple ligands """ from dabble.param import CharmmWriter p = str(tmpdir) # Parameterize the multiple ligand system with charmm parameters molid = molecule.load("mae", os.path.join(dir, "test_multiligand_correct.mae")) w = CharmmWriter(tmp_dir=p, molid=molid, lipid_sel="lipid", extra_topos=[os.path.join(dir, "alprenolol.rtf")]) w.write(os.path.join(p, "test")) # Check result check_result("psf", p)
def test_multiligand_psf_amber(tmpdir): """ Checks multiple ligands, AMBER parameters, CHARMM format """ from dabble.param import CharmmWriter p = str(tmpdir) # AMBER params not supported for lipids with CHARMM output molid = molecule.load("mae", os.path.join(dir, "test_multiligand_correct.mae")) w = CharmmWriter(tmp_dir=p, molid=molid, forcefield="amber", extra_topos=[os.path.join(dir, "alp.off")], extra_params=[os.path.join(dir, "alp.frcmod")]) w.write(os.path.join(p, "test")) check_result("psf", p)
def write_final_system(out_fmt, out_name, molid, **kwargs): """ Writes the final output in whatever format(s) are requested. Always writes a mae format file as well Args: out_name (str): Filename to output to out_fmt (str): format to write the output to molid (int): VMD molecule_id to write tmp_dir (str): Directory to put temporary files in extra_topos (list of str): Extra topology files to use extra_params (list of str): Extra parameter files to use extra_streams (list of str): Extra stream files to use lipid_sel (str): Lipid selection hmassrepartition (bool): Whether or not to repartition hydrogen masses forcefield (str): Force field to use, defaults to charmm water_model (str): Water model to use, defaults to tip3 debug_verbose (bool): Extra debug output from tleap Returns: (str) main final filename written """ # Set defaults for extra keyword options # Do this explicitly here if kwargs.get('tmp_dir') is None: kwargs['tmp_dir'] = os.getcwd() if kwargs.get('lipid_sel') is None: kwargs['lipid_sel'] = "lipid or resname POPS POPG" if kwargs.get('forcefield') is None: kwargs['forcefield'] = "charmm" if kwargs.get('water_model') is None: kwargs['water_model'] = "tip3" if kwargs.get('debug_verbose') is None: kwargs['debug_verbose'] = False # Write a mae file always, removing the prefix from the output file mae_name = '.'.join(out_name.rsplit('.')[:-1]) + '.mae' write_ct_blocks(molid=molid, sel='beta 1', output_filename=mae_name, tmp_dir=kwargs.get('tmp_dir', os.getcwd())) temp_mol = molecule.load('mae', mae_name) if out_fmt == "desmond": atomsel('all', molid=temp_mol).write("dms", out_name) # For pdb, write an AMBER leap compatible pdb, don't trust the VMD # pdb writing routine elif out_fmt == "pdb": atomsel("all", molid=temp_mol).write("pdb", out_name) # If we want a parameterized format like amber or charmm, a psf must # first be written which does the atom typing, etc elif out_fmt == "charmm": writer = CharmmWriter(molid=temp_mol, tmp_dir=kwargs['tmp_dir'], forcefield=kwargs['forcefield'], water_model=kwargs['water_model'], lipid_sel=kwargs['lipid_sel'], extra_topos=kwargs.get('extra_topos', []), debug_verbose=kwargs.get('debug_verbose', False)) writer.write(mae_name.replace(".mae", "")) # For amber format files, invoke the parmed chamber routine elif out_fmt == "amber": print("Writing AMBER format files with %s parameters. " "This may take a moment...\n" % kwargs.get("forcefield")) writeit = AmberWriter(molid=temp_mol, tmp_dir=kwargs['tmp_dir'], forcefield=kwargs['forcefield'], water_model=kwargs['water_model'], lipid_sel=kwargs.get('lipid_sel'), hmr=kwargs.get('hmassrepartition'), extra_topos=kwargs.get('extra_topos', []), extra_params=kwargs.get('extra_params', []), debug_verbose=kwargs.get('debug_verbose')) writeit.write(mae_name.replace(".mae", "")) # For gromacs files, use either topotools or parmed depending on # forcefield. GromacsWriter handles this for us elif out_fmt == "gromacs": if "charmm" in kwargs.get('forcefield'): print("Writing Gromacs format files with CHARMM parameters. " "This may take a moment...\n") else: print("Writing Gromacs format files with Amber parameters. " "This may take a moment...\n") writeit = GromacsWriter(molid=temp_mol, tmp_dir=kwargs['tmp_dir'], forcefield=kwargs['forcefield'], water_model=kwargs['water_model']) writeit.write(mae_name.replace(".mae", "")) # LAMMPS has its own writer elif out_fmt == "lammps": writeit = LammpsWriter(molid=temp_mol, *kwargs) writeit.write(mae_name.replace(".mae", "")) molecule.delete(temp_mol) return out_name
def __init__(self, molid, **kwargs): """ Creates an AMBER Writer. Args: molid (int): VMD molecule ID of system to write tmp_dir (str): Directory for temporary files. Defaults to "." forcefield (str): charmm, or amber water_model (str): Water model to use lipid_sel (str): Lipid selection string. Defaults to "lipid" hmr (bool): If hydrogen masses should be repartitioned. Defaults to False. extra_topos (list of str): Additional topology (.str, .off, .lib) to include. extra_params (list of str): Additional parameter sets (.str, .frcmod) override_defaults (bool): If set, omits default amber ff14 parameters. debug_verbose (bool): Prints additional output, like from tleap. """ # Initialize standard MoleculeWriter items super(AmberWriter, self).__init__(molid, **kwargs) self.prompt_params = False # Set forcefield default topologies and parameters self.forcefield = kwargs.get("forcefield", "amber") self.water_model = kwargs.get("water_model", "tip3") if self.forcefield == "charmm": # Import CharmmWriter as needed to avoid circular imports from dabble.param import CharmmWriter # Topologies used will be found and returned by CharmmWriter self.topologies = CharmmWriter.get_topologies( self.forcefield, self.water_model) self.parameters = CharmmWriter.get_parameters( self.forcefield, self.water_model) # Duplicate code here for clarity elif self.forcefield == "opls": from dabble.param import CharmmWriter self.topologies = CharmmWriter.get_topologies( self.forcefield, self.water_model) self.parameters = CharmmWriter.get_parameters( self.forcefield, self.water_model) elif self.forcefield == "amber": # This will raise DabbleError if AMBERHOME is unset self.topologies = self.get_topologies(self.forcefield, self.water_model) self.parameters = self.get_parameters(self.forcefield, self.water_model) self.parameters = [] else: raise DabbleError("Unsupported forcefield: %s" % self.forcefield) # Handle override if self.override: self.topologies = [] self.parameters = [] # Now extra topologies and parameters self.topologies.extend(self.extra_topos) self.parameters.extend(self.extra_params) # Initialize matcher only now that all topologies have been set if self.forcefield == "amber": self.matcher = AmberMatcher(topologies=self.topologies)
def write(self, filename): """ Writes the parameter and topology files Args: filename (str): File name to write. File type suffix will be added. """ self.outprefix = filename # Charmm forcefield if "charmm" in self.forcefield or "opls" in self.forcefield: from dabble.param import CharmmWriter charmmw = CharmmWriter(molid=self.molid, tmp_dir=self.tmp_dir, forcefield=self.forcefield, water_model=self.water_model, lipid_sel=self.lipid_sel, extra_topos=self.extra_topos, extra_params=self.extra_params, override_defaults=self.override, debug_verbose=self.debug) charmmw.write(self.outprefix) self._psf_to_prmtop() # Amber forcefield elif "amber" in self.forcefield: # Print info about topologies print("Using the following topologies:") for top in self.topologies: print(" - %s" % os.path.split(top)[1]) # Assign atom types print("Assigning AMBER atom types...") conect = self._rename_atoms_amber() # Create temporary pdb files that will be leap inputs pdbs = [] pdbs.append(self._write_lipids()) prot_pdbseqs = self._write_protein() pdbs.extend(self._write_solvent()) ligfiles = self._write_ligands() # Now invoke leap to create the prmtop and inpcrd outfile = self._run_leap(ligfiles, prot_pdbseqs, pdbs, conect) # Repartion hydrogen masses if requested if self.hmr: print("\nRepartitioning hydrogen masses...") parm = AmberParm(prm_name=outfile + ".prmtop", xyz=outfile + ".inpcrd") action = HMassRepartition(parm, "dowater") action.execute() write = parmout(action.parm, "%s.prmtop" % self.outprefix) write.execute() parm = write.parm # Check validity of output prmtop using parmed parm = AmberParm(prm_name=self.outprefix + ".prmtop", xyz=self.outprefix + ".inpcrd") print("\nChecking for problems with the prmtop...") print(" Verify all warnings!") action = checkValidity(parm) action.execute() else: raise DabbleError("Unhandled forcefield: %s" % self.forcefield)
def test_covalent_ligand_patches(tmpdir): """ Tests covalently bound ligand parameterization with the graph. One hydrogen atom should be renamed in the palmitoylcysteine. Also tests for detection of phosphorylations on amino acids. """ from vmd import atomsel, molecule from dabble.param import CharmmWriter # Parameterize with charmm parameters p = str(tmpdir) molid = molecule.load( "mae", os.path.join(dir, "rho_arr_CYP_prepped_aligned_dowsered.mae")) w = CharmmWriter(tmp_dir=p, molid=molid, lipid_sel="lipid", extra_topos=[os.path.join(dir, "CYP_v1.str")]) w.write(os.path.join(p, "test")) # Load the result m2 = molecule.load("psf", os.path.join(p, "test.psf")) molecule.set_top(m2) # Sanity check the system was built completely # Some resids match because of insertion codes assert len(set(atomsel("protein or resname ACE NMA").resid)) == 697 assert len(set(atomsel("protein or resname ACE NMA").residue)) == 699 assert len(set(atomsel("resname ACE NMA").resid)) == 4 assert len(atomsel("water")) == 654 assert len(set(atomsel("all").fragment)) == 220 # Check for palmitoylation assert len(atomsel("resname CYP")) == 116 assert set(atomsel("resname CYP").resid) == set([322, 323]) # Check for protonation on Asp83 assert len(atomsel("resid 83 and resname ASP")) == 13 assert len(atomsel("resid 331 and resname ASP")) == 12 assert "OH1" in atomsel("resid 83 and resname ASP").type assert "OH1" not in atomsel("resid 331 and resname ASP").type # Check for protonation on Glu134A assert len(atomsel("resid 134 and resname GLU")) == 16 assert len(atomsel("resid 247 and resname GLU")) == 15 assert "OB" in atomsel("resid 134 and resname GLU").type assert "OB" not in atomsel("resid 331 and resname GLU").type # Check that Ser98 is normal assert len(atomsel("resid 98 and resname SER")) == 11 assert "P" not in atomsel("resid 98 and resname SER").type assert "OH1" in atomsel("resid 98 and resname SER").type # Check for phosphorylation on Ser334 assert len(atomsel("resid 334 and resname SER")) == 14 assert "P" in atomsel("resid 334 and resname SER").type assert "OH1" not in atomsel("resid 334 and resname SER").type # Check for phosphorylation on Ser338 assert len(atomsel("resid 338 and resname SER")) == 14 assert "P" in atomsel("resid 338 and resname SER").type assert "OH1" not in atomsel("resid 338 and resname SER").type