Fragmenstein: Merging, linking and placing compounds by stitching bound compounds together like a reanimated corpse.
For manuscript data see manuscript data repository For authors see Authors
Fragmenstein can perform two different tasks.
- Combine hits
- Place a given followup molecule (SMILES) based on series of hits
Like Frankenstein's creation it may violate the laws of chemistry. Trigonal planar topologies may be tetrahedral, bonds unnaturally long etc. This monstrosity is therefore then energy minimised with strong constraints within the protein.
There are four main classes —named after characters from the Fragmenstein book and movies:
Monster
makes the stitched together molecules indepent of the protein — documentationIgor
uses PyRosetta to minimise in the protein the fragmenstein monster followup — documentationVictor
is a pipeline that calls the parts, with several features, such as warhead switching —documentationLaboratory
does all the combinatorial operations with Victor (specific case)
NB. In the absence of pyrosetta
(which requires an academic licence), all bar Igor
work.
Additionally, there are a few minor classes.
One of these is mRMSD
, a multiple RMSD variant which does not superpose/align and bases which atoms
to use on coordinates —documentation
The class Walton
performs geometric manipulations of compounds, to set them up to demonstrate
features of Fragmenstein (like captain Walton, it does not partake in the plot, but is key to the narration)
There are two module hosted elsewhere:
Rectifier
from molecular_rectifier is a class that corrects mistakes in the molecule automatically merged byMonster
.Params
from rdkit to params module parameterises the ligands
It can also merge and link fragment hits by itself and find the best scoring mergers. For details about linking see linking notes. It uses the same overlapping position clustering, but also has a decent amount of impossible/uncommon chemistry prevention.
Monster:
from fragmenstein import Monster
monster = Monster(hits=[hits_a, hit_b])
monster.combine()
monster.positioned_mol #: RDKit.Chem.Mol
Victor:
from fragmenstein import Victor
import pyrosetta
pyrosetta.init( extra_options='-no_optH false -mute all -ex1 -ex2 -ignore_unrecognized_res false -load_PDB_components false -ignore_waters false')
victor = Victor(hits=[hits_a, hit_b],
pdb_filename='foo.pdb', # or pdb_block='ATOM 1 MET ...'
covalent_resi=1) # if not covalent, just put the first residue or something.
victor.combine()
victor.minimized_mol
The PyRosetta init step can be done with the helper function:
Igor.init_pyrosetta()
The two seem similar, but Victor places with Monster and minimises with Igor. As a result it has energy scores
victor.ddG
Fragmenstein is not really a docking algorithm as it does not find the pose with the lowest energy within a given volume. Consequently, it is a method to find how faithful is a given followup to the hits provided. Hence the minimised pose should be assessed by the RMSD metric or similar and the ∆∆G score used solely as a cutoff —lower than zero.
For a large number of combination:
from fragmenstein import Laboratory
lab = Laboratory(pdbblock=pdbblock, covalent_resi=None)
combinations:pd.DataFrame = lab.combine(hits, n_cores=28)
Here is an interactive example of placed molecules.
It is rather tolerant to erroneous/excessive submissions (by automatically excluding them) and can energy minimise strained conformations.
Three mapping approaches were tested, but the key is that hits are pairwise mapped to each other by means of one-to-one atom matching based upon position as opposed to similarity which is easily led astray. For example, note here that the benzene and the pyridine rings overlap, not the two pyridine rings:
Monster:
from fragmenstein import Monster
monster = Monster(hits=[hits_a, hit_b])
monster.place_smiles('CCO')
monster.positioned_mol
Victor:
from fragmenstein import Victor, Igor
Igor.init_pyrosetta()
victor = Victor(hits=[hits_a, hit_b], pdb_filename='foo.pdb')
victor.place('CCO')
victor.minimized_mol
For a lengthier example see example notes or documentation.
Some demo data is provided in the demo
submodule.
from fragmenstein.demo import MPro, Mac1
pdbblock: str = Mac1.get_template()
for hitname in Mac1.get_hit_list():
Mac1.get_hit(hitname)
...
To use SAR-COV-2 MPro as a test bed, the following may be helpful:
fragmenstein.MProVictor
, a derived class (ofVictor
), with various presents specific for MPro.fragemenstein.get_mpro_template()
, returns the PDB block (str) of MProfragemenstein.get_mpro_molblock(xnumber)
, returns the mol block (str) of a MPro hit from Fragalysisfragemenstein.get_mpro_mol(xnumber)
, as above but returns aChem.Mol
instance.
Python 3.6 or above. Install from pipy
python -m pip install fragmenstein
⚠️ PyRosetta no longer runs on CentOS 7 due to old kernel headers (cf. blog post).
Pyrosetta requires a password to be downloaded (academic licence) obtained by https://els2.comotion.uw.edu/product/pyrosetta. This is a different licence from the Rosetta one. The username of the Rosetta binaries is formatted variant of "academic user", while the PyRosetta is the name of a researcher whose name bares an important concept in protein folding, like boltzmann + constant (but is not that). Pyrosetta can be downloaded via a browser from http://www.pyrosetta.org/dow. Or in the terminal via:
curl -u 👾👾👾:👾👾👾https://graylab.jhu.edu/download/PyRosetta4/archive/release/PyRosetta4.Release.python38.linux/PyRosetta4.Release.python38.linux.release-NNN.tar.bz2 -o a.tar.bz2
tar -xf a.tar.bz2
cd PyRosetta4.Release.python38.linux
sudo pip3 install .
or using conda
or using install_pyrosetta
from the pyrosetta-help
package.
pip install pyrosetta-help
PYROSETTA_USERNAME=👾👾👾 PYROSETTA_PASSWORD=👾👾👾 install_pyrosetta
The PYROSETTA_USERNAME
and PYROSETTA_PASSWORD
are environment variables,
which should not be shared publicly (i.e. store them as private environmental variables
in your target application).
Fragmenstein was created to see how reasonable are the molecules of fragment mergers submitted in the COVID moonshot project, because after all the underlying method is fragment based screening. This dataset has some unique peculiarities that potentially are not encountered in other projects.
The strength of Fragmenstein is as a python module, but there is a command line interface.
fragmenstein monster combine -i hit1.mol hit2.mol >> combo.mol
fragmenstein monster place -i hit1.mol hit2.mol -s 'CCO' >> placed.mol
fragmenstein victor combine -i hit1.mol hit2.mol -t protein.pdb -o output >> combo.mol
fragmenstein victor combine -i hit1.mol hit2.mol -s 'NCO' -n molname -t protein.pdb -o output >> placed.mol
fragmenstein laboratory combine -i hits.sdf -o output -d output.csv -s output.sdf -c 24
Author | Role | Homepage | Department | Badges |
---|---|---|---|---|
Matteo Ferla | main developer | WCHG | Wellcome Centre for Human Genetics, University of Oxford | |
Rubén Sánchez-Garcia | discussion/code | Stats | Department of Statistics, University of Oxford | |
Rachael Skyner | discussion/editing/code | |||
Stefan Gahbauer | discussion | |||
Jenny Taylor | PI | WCHG | Wellcome Centre for Human Genetics, University of Oxford | |
Brian Marsden | PI | CMD | CMD, Oxford | |
Charlotte Deane | PI | |||
Frank von Delft | PI | CMD | Diamond Lightsource / CMD, Oxford |
- ChemRXiv preprint — TBA
- Steph Wills's fragment network merges repo contains useful filtering algorithms
- Fragmenstein is used in Schuller et. al. 2021
- Figures for the upcoming manuscript are in a separate repo
- The conversion of a rdkit Chem.Mol that cannot be sanitised to an analogue that can is done by the molecular rectifier package
- The conversion of a rdkit Chem.Mol to a PyRosetta residue type (a "params file") is done via the rdkit-to-params package
- The pipeline demo colab notebook uses Brian Shoichet's SmallWorld webapp, interfaced via its API in Python
- The playground demo colab notebook features a JSME widget — JSME is a popular JS only molecular editor