Theory¶
Spruce TK is used to process PDB or mmCIF files containing the structures, resulting from X-ray crystallography, Nuclear Magnetic Resonance (NMR) spectroscopy, or electron microscopy (EM) experiments. into molecules usable for molecular modeling. Due to the nature of the experiments and data, some processing is required before use in modeling.
Spruce TK provides an end-to-end preparation workflow using the OEMakeDesignUnits
API.
Options (see OEMakeDesignUnitOptions and associated options classes) are available to
control for the desired behavior. Metadata (see OEStructureMetadata) can be supplied
to infuse experimental data, like the proper variant sequence and also fix common problems reading
from PDB files (e.g. bond order perception). Spruce has a built-in Chemical Components Dictionary matching 3-letter
residue codes to SMILES, derived from the corresponding one at the RCSB, but curated to fix improper SMILES.
The workflow automatically runs through the following steps to produce OEDesignUnit objects:
Biological unit extraction (see
OEExtractBioUnits
)If structure is from X-ray, it will also generate packing residues for visualization of crystal contacts
Alternate location assignment or enumeration (see the
OEAlternateLocationOption
namespace)Splits the system into components, e.g. identifying ligands, cofactors, excipients.
Building missing side-chains, modeling loops, and capping chain breaks (see
OEBuildSidechains
,OEBuildLoops
, andOECapTermini
)Hydrogen placement and optimization, including searching ligand tautomer states (see
OEProtonateDesignUnit
)Assignment of partial charges to the entire system (see OEDesignUnitCharges)
Superposition to a common reference frame (see OEStructuralSuperposition and OESecondaryStructureSuperposition)
An OEInteractionHintContainer encoded for visualization and more
An estimate of the model quality using Iridium [Warren-2012] stored in OEIridiumData.
Note
Multiple design units are often produced. This results from multiple biological units generated during step 1, and further expanding that set when enumerating the alternate locations in step 3. The Iridium categorization (see Categorization) should be helpful in choosing which (if not all) of the produced units to use in downstream modeling tasks. We find that the Iridium categories are also helpful for managing modeling expectations, having a quality measure of the input data for modeling.
Note
Included with Spruce TK is a large database of loop templates generated by parsing the structures in the public PDB repository pulled from the RCSB. This database is available from db-downloads. in a platform-independent format. The SPRUCE loop database is large (~13G) and will take time to download with a good internet connection. When the download is complete, move the file to a convenient location, a network drive is not recommended for performance.
To use it during prep (OEMakeDesignUnits), set the path in SetLoopDBFilename method on the OELoopBuilderOptions class.
The database can be appended to (updated) using the LoopDB_Builder utility app, that ships with the SPRUCE apps. This would be in the event that the user has a collection of internal/proprietary structures, or if specific structures are released to the public PDB between OpenEye updates of the database that are crucial for a given target that is less well described by the existing templates.
Definitions¶
Biological Unit (BU) - the biologically relevant unit for a protein to use in modeling. For example, in Trypsin the BU is a monomer, in HIV Protease the BU is a homo-dimer. See Biological Unit below.
Asymmetric Unit (ASU) - the contents of a PDB or mmCIF file from X-ray contain an asymmetric unit as the output of the experiment. This is sometimes equivalent to the BU, but often requires manipulation to create a correct BU.
Design Unit (DU) - the result of preparation in Spruce is a collection of molecules from a single BU, extracted and ready to use for modeling tasks. See Design Unit below for more details.
Alternate locations (alt locs) - X-ray experiments can often contain results with atoms occupying more than one location. Crystallographers denote this with a measure of the amount of time an atom occupies a given set of coordinates. A well resolved atom will have an occupancy of 1.0, meaning that 100% of the time it is in that location. Sometimes, the atom exists in two positions, alternate locations, and these appear in the input file with single letter designations and with occupancy < 1.0.
Biological Unit¶
In short, the biological unit (BU) is an object that contains the biologically relevant parts of an ASU, which have not been split into various molecular components and are not yet prepped for modeling. For a more detailed explanation of BUs, refer to Introduction to Biological Assemblies and the PDB Archive hosted at the RCSB.
A BU can be constructed from a single PDB from the PDB’s own header remarks, or by using a sequence
alignment to an input reference protein. To extract a BU or set of BUs from a PDB, one should use the helper
function in Spruce TK called
OEExtractBioUnits
. The following example shows
how to extract BUs from the PDB remarks:
OEIter<OEMolBase> bioUnit;
bioUnit = OEExtractBioUnits(extractProt, opts);
Using the same function, one can also extract BUs from a PDB using an input reference protein. The following example shows
how to use OEExtractBioUnits
to extract BUs from a given reference:
OEIter<OEMolBase> bioUnit;
bioUnit = OEExtractBioUnits(extractProt, refProt, opts);
Design Unit¶
The design unit (DU) is an object that contains the extracted and prepared parts of a single BU, ready for modeling. The parts include:
Protein
Ligand (not always, an apo DU will not contain a ligand)
Site residues
Packing residues (if any exist near the site)
Excipients (if any exist near the site)
One can interact with each part of the DU through APIs. The APIs are listed here OEDesignUnit.
Proton Placement and Optimization¶
Traditionally, most biomolecular structures have been generated with either no
explicit hydrogens or only polar hydrogens. However, having all atoms explicitly
represented and positioned to make appropriate hydrogen bonds is sometimes necessary.
The function OEPlaceHydrogens
does this by adding and
placing hydrogens and by “flipping” certain functional groups
(e.g., sidechain amides and imidazoles) as required for an optimal hydrogen bonding network.
Spruce TK leverages this functionality, but builds on top of this by taking the
ligand protomer and tautomer states into account in the OEProtonateDesignUnit
function. The function identifies the heterogens (ligands, cofactors, etc.) in the structure and
enumerates their states using the OEGetReasonableTautomers
function or
by using user supplied states.
The hydrogen bonding network of the biomolecule is then optimized in the presence of each state
independently and the most favorable state of the complex is chosen based on interaction energies.
If a binding site holds two heterogens, e.g. a ligand and a cofactor and each have multiple tautomer
states, the combinatorial number of states are optimized and evaluated. To do this efficiently
only the binding site(s) are initially optimized. After selecting the appropriate states of each of
the binding sites the remaining parts of the system is optimized keeping these states fixed.
Protein Sidechain Modeling¶
Amino acid sidechains are sometimes missing in protein structures due to low or
missing density from X-ray diffraction crystallography experiments. This can be due
to e.g. high flexibility making assignment of a specific location of the atoms difficult.
However, most molecule simulation software requires a position of these atoms, and the
lack of them can cause incorrect results. Partial sidechains are identified with OEGetPartialResidues
.
Using OEBuildSidechains
these residues are then divided into groups based
on proximity and side-chain orientation. The groups are independently optimized taking into account their local
environment. In each group the sidechains are built out and a standard rotamer library from the
OERotamerLibrary
namespace is used. For each side-chain the set of rotamers
are evaluated based on an interaction energy with the nearest environment and the most favorable state is
chosen. In the case where multiple residues are being built in a group, an iterative procedure attempts to
find the optimal energy for the entire set of residues. In the event a sidechain cannot be built due to
poor input geometry causing clashes the entire cluster is skipped. Water locations that block
side-chain rotamers result in those water molecules being deleted (optional) since their placement is most likely an artifact.
Protein Loop Modeling¶
Similarly to missing side-chains above there are sometimes gaps in protein structures, where the position
of the entire amino acid residues could not be resolved based on the experimental data.
The function OEBuildLoops
is able to build missing gaps (loops). The workflow is illustrated
by the figure below. The function identifies missing loops, by comparing the SEQRES section of the
PDB header with the structure using a sequence alignment. The user can optionally input their
own sequence using OESequenceMetadata if the SEQRES in the header is incorrect or missing.
With the gaps identified, the function loops for templates matching the gap, filters them based on the
ability to fit the gap without clashing, and eventually does an optimization of the top candidates
in the local environment before picking the most favorable conformation.
If multiple results are desired, these can be retrieved using OEBuildSingleLoop
.
The loop template database is built using all the structures in the PDB downloaded from the RCSB, and can be downloaded from db-downloads.
Protein Superposition¶
A protein can be structurally superimposed on to a reference protein structure using the OESpruce TK. Proteins can be superimposed with either atomic coordinates in the OEStructuralSuperposition class, or with secondary structure elements using the OESecondaryStructureSuperposition class.
The OEStructuralSuperposition class can superimpose proteins using any of the following four methods:
The global method (default for OEStructuralSuperposition). This method uses all matching heavy atoms from the reference and fit proteins as the region for performing the superposition calculation (see
OESuperpositionType::Global
).The Difference Distance Matrix method. This method calculates the pairwise distance matrix of C-alpha atoms for both the reference and fit proteins, then takes the difference of these two matrices to find the difference distance matrix (DDM).
For a given conformation a, the elements of the distance matrix \(D_{ij}^a\) are the distances between atoms i and j in a molecule,
\[D_{ij}^a = |r_i - r_j|\]where \(r_i\) and \(r_j\) are the Cartesian coordinate vectors of atoms i and j. The elements \(\Delta_{ij}^{ab}\) of the difference-distance matrix for two conformations a and b are
\[\Delta_{ij}^{ab} = D_{ij}^a - D_{ij}^b.\]If \(\Delta_{ij}^{ab}\) is positive, the interatomic vector between between i and j in conformation b is contracted with respect to a. Conversely, negative elements of the DDM indicate an expansion of the interatomic vector.
The longest contiguous region of the resulting difference distance matrix (DDM) is used for the structural superposition calculation (see
OESuperpositionType::DDM
).The weighted-DDM method. This method uses the DDM matrix, and calculates Gaussian weighting factors for all matching C-alpha atoms. These Gaussian weights are used as a weighting function in the superposition calculation (see
OESuperpositionType::Weighted
).The site residue method. This method uses a set of site residues (given as a set of unique residue strings) as a constraint on the protein superposition. Site residues must be set with the
SetSiteResidues
member function of the OESuperpositionOptions class (seeOESuperpositionType::Site
).
The OESecondaryStructureSuperposition class can superimpose proteins using the following method:
The secondary structure superposition method. This method takes two proteins and performs a structural superposition on them based on the shape overlap of the secondary structure elements of the two proteins.
Note
All structural superposition methods in the OEStructuralSuperposition class have a corresponding score from the sequence alignment that was used to find the matching atoms of both proteins. This score comes from the output of the OESequenceAlignment class, where a larger score indicates a better sequence alignment, and scores below a small threshold (around 200) should be considered a bad alignment.
Note
All structural superposition methods in the OEStructuralSuperposition class have a corresponding RMSD value for superposition that can be loosely associated with the quality of the superposition. The OESecondaryStructureSuperposition class does not have an RMSD value, but instead uses the Tanimoto score from the underlying shape overlap calculation.
How to Correctly Read a PDB File¶
Reading a PDB file correctly for use in subsequent modeling tasks can be challenging.
To correctly read a PDB, one must be aware that PDB header information as well as
information about alternate location codes within the PDB file will be lost unless
a specific combination of PDB-centric OEIFlavor
’s are used.
Furthermore, the protein itself must be processed by
OEAltLocationFactory
in order to create a
molecule with all alternate location atoms retained. Spruce handles this for the user,
so they are not handled by this reader. However, for uses other than Spruce the user
needs to either, enumerate the different alternate locations, or pick a specific location.
With that in mind, we recommend reading PDB files for use in OESpruce TK using
the following pattern as shown in ReadProteinFromPDB below:
bool ReadProteinFromPDB(const string& pdbFile, OEChem::OEMolBase& mol)
{
unsigned int pdbFlavor = OEIFlavor::PDB::Default
| OEIFlavor::PDB::DATA
| OEIFlavor::PDB::ALTLOC;
oemolistream ifs;
ifs.SetFlavor(OEFormat::PDB, pdbFlavor);
if (!ifs.open(pdbFile))
{
OEThrow.Warning("Unable to open %s for reading.", pdbFile.c_str());
return false;
}
if (!OEReadMolecule(ifs, mol))
{
OEThrow.Warning("Unable to read molecule from %s.", pdbFile.c_str());
return false;
}
ifs.close();
return (mol);
}
Note
The mmCIF reader was designed to read all the necessary input by default, and therefore no
specific OEIFlavor
’s are necessary to read them.