# RDKit to params
Create or modify Rosetta params files (topology files) from scratch, RDKit mols or another params file.
> RDKit and Pyrosetta are optional module, but most of the useful functionality comes from the former!
To install from pip type:
pip install rdkit-to-params
To install the latest version (probably the same) from GitHub
git clone https://github.com/matteoferla/rdkit_to_params.git
pip install .
(To install rdkit, `conda install -c conda-forge rdkit` or `apt-get`).
## Website
For a web app using this see [https://direvo.mutanalyst.com/params](https://direvo.mutanalyst.com/params).
For the code running the website, see:
* [templates](https://github.com/matteoferla/DirEvo_tools/tree/master/direvo/templates/params)
* [views](https://github.com/matteoferla/DirEvo_tools/blob/master/direvo/views/params.py)
## Legal thingamabob
The author, Matteo Ferla, is not affiliated with either Rosetta or RDKit and the presence of the latter's
name in the package's title is completely coincidental.
And yes, I am copying my legal mumbojumbo from South Park.
## Rationale
This is a fresh rewrite of ``mol_to_params.py``. For three reasons:
* I cannot share my 2to3 port and modd ed module-version of ``mol_to_params.py`` due to licence.
* I want to modify `params` files and more as opposed to use a standalone script.
* RDKit does not save ``mol2`` files, yet knows about atom names and Gasteiger-Massilli charges and more...
It sounds mad, but did not actually take too long.
## Roundtrip
Native amino acid params files can be found in the Rosetta folder
`rosetta/main/database/chemical/residue_type_sets/fa_standard/residue_types/l-caa`
Let's do a roundtrip changing an atomname:
import pyrosetta
pyrosetta.init(extra_options='-mute all') # required for test
from rdkit_to_params import Params
p = Params.load('PHE.params')
p.IO_STRING[0].name3 = 'PHX'
p.IO_STRING[0].name1 = 'Z'
p.AA = 'UNK' #If it's not one of the twenty (plus extras), UNK!
del p.ROTAMER_AA[0]
p.rename_atom(' CB ', ' CX ') # this renames
p.dump('fake.params')
p.test().dump_pdb('test.pdb')
`p.test()` returns a pyrosetta pose. The static method `params_to_pose('something.params', name3)` accepts a params file
import nglview
pose = Params.params_to_pose('some_topology_I_found.params', name3)
view = nglview.show_rosetta(pose)
view
## From mol object
### Requirements
For the sake of sanity, `EmbedMolecule`, `Chem.AddHs(mol)` or any other operation is assumed to have been done beforehand.
And that the user is going to do `Chem.MolToPDBFile(params.mol)` or `Chem.MolToPDBBlock(params.mol)` or use the bound methods of `Params`,
`dump_pdb` and `dump_pdb_conf` (see below).
The molecule should preferably be **not** Kekulised.
3letter name of residue is either from the title row (``_Name``) if a 3letter word or from the PDBInfo or 'LIG'.
Dummy atom (*/R) is assumed to be a CONNECT —ligand only atm.
Here is a conversion to an amino acid from a SMILES (quickest way):
import pyrosetta
pyrosetta.init(extra_options='-mute all')
from rdkit_to_params import Params
p = Params.from_smiles('*C(=O)C(Cc1ccccc1)[NH]*', #recognised as amino acid.
name='PHX', #optional.
atomnames={3: 'CZ'} #optional, rando atom name as see in previous edit
)
print(p.is_aminoacid()) # True
p.dump('fake.params')
p.test().dump_pdb('test.pdb')
Chem.MolToPDBFile(mol, 'ref.pdb')
Here is a conversion to a ligand the circuitous way, just for fun:
import pyrosetta
pyrosetta.init(extra_options='-mute all')
# note that pyrosetta needs to be started before rdkit.
from rdkit_to_params import Params
# make the molecule in RDKit or chemdraw or download it or whatever.
mol = Chem.MolFromSmiles('NC(C(=O)O)Cc1ccccc1')
mol = AllChem.AddHs(mol)
AllChem.EmbedMolecule(mol)
AllChem.MMFFOptimizeMolecule(mol)
# add names to the mol beforehand
Params.add_names(mol, names=['N', 'CA', 'C', 'O', 'OXT', 'CB'], name='PHZ')
# parameterise
p = Params.from_mol(mol, name='PHZ')
p.test().dump_pdb('test.pdb')
Chem.MolToPDBFile('ref.pdb')
The class method `add_names` is based upon atom index
(which is derived from the SMILES or sdf/mol file unless atoms have been replaced).
The instance method `rename_by_substructure` accepts a substructure and a list of atom names in the order they are in the substructure.
Note that conformer generation is not fully automatic and is not done by default.
# make your conformers as you desire
AllChem.EmbedMultipleConfs(mol, numConfs=10) # or whatever you choose. This is a somewhat important decision.
AllChem.AlignMolConformers(mol) # I do not know if the conformers need to be aligned for Rosetta
# params time!
p = Params.from_mol(mol, name='LIG')
p.dump_pdb_conf('LIG_conf.pdb')
p.PDB_ROTAMERS.append('LIG_conf.pdb')
p.dump('my_params.params')
Note `dump_pdb` and `dump_pdb_conf` will save the molecule(s) without the dummy atoms, to stop this add `stripped=False`.
## From SMILES string
The above is actually a bit convoluted for example purposes as `Params.from_smiles`, accepts a SMILES string.
## From SMILES string and PDB for names
In some cases one has a PDB file with a ligand that needs parameterising.
Assuming one has also the smiles of the ligand (PubChem has an super easy search), one can do
p = Params.from_smiles_w_pdbfile(pdb_file, smiles, 'XXX') # the name has to match.
The smiles does not need to match full. It can contain more atoms or even one`*` (CONNECT).
The smiles gets parameterised. So be suse to add correct charges properly —hydrogens are added.
It could be used for scaffold hopping, but if position matters so much,
you may be interested in [Fragmenstein](https://github.com/matteoferla/Fragmenstein).
For more see [autogenerated documentation](sphinx-documentation.md). Sphinx with markdown cannot deal with typehinting,
so checking the code might be clearer.
## Rename
A key part is the atom names ——this can happen at . The following renaming methods are present:
* `p.rename(???)`: "overloaded" method that directs to the others
* `p.rename_from_str('XX,YY,ZZ')` or `p.rename_from_str('0:XX,3:YY')`
* `p.rename_from_list(['XX','YY', 'ZZ'])`
* `p.rename_from_dict({0:'XX',3:'YY'})`
* `p.rename_from_template(Chem.Mol)`
* `p.rename_by_substructure(Chem.Mol, ['XX','YY', 'ZZ'])` where the list is the atom idx in substructure
Note, ``retype_by_name`` does not have all these options (only atomname -> Rosetta atomtype).
The class method ``add_names`` simply uses these, but returns a mol
### DIY
If you have two mol objects from whatever routes, the basic operation is:
p = Params.load_mol(mol, generic=False, name='LIG')
p.rename_from_template(template) # or whatever middle step
p.convert_mol()
Note that `convert_mol` should be called once and is already called in the two `from_XXX` classmethods.
p = Params.from_mol(...)
p.convert_mol() # No!!!
p.mol # is the mol...
p2 = Params.load_mol(p.mol)
p2.convert_mol() # Yes
## Constraints
The selfstanding class `Constraints` is for generating constraint files, which are a must with covalent attachments
in order to stop janky topologies.
The class is instantiated with a pair of SMILES, each with at least a real atom and with one attachment point,
the first is the ligand and the second is its peptide target. The names of the heavy atoms and the Rosetta residue "numbers".
from rdkit_to_params import Constraints
c = Constraints(smiles=('*C(=N)', '*SC'), names= ['*', 'CX', 'NY', '*', 'SG', 'CB'], ligand_res= '1B', target_res='145A')
c.dump('con.con')
# individual strings can be accessed
c.atom_pair_constraint
c.angle_constraint
c.dihedral_constaint
c.custom_constaint # if you want to add your own before `str`
评论0