diff --git a/README.md b/README.md index 7edd9a1..7802926 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,13 @@ This is a port of the [Arpeggio](https://github.com/PDBeurope/arpeggio/) library - Identify protein-protein interactions - [x] Steric clashes - [x] VdW interactions - - [ ] Hydrophobic interactions + - [x] Hydrophobic interactions - [ ] Aromatic interactions - [ ] Cation-pi interactions - [x] Ionic interactions - [x] Hydrogen bonds - [x] Weak hydrogen bonds + - [ ] Disulfide bonds - [ ] Covalent bonds - [ ] Output results in various formats (e.g., JSON, CSV) - [ ] Bundle into a `PyO3` extension module diff --git a/src/interactions/complex.rs b/src/interactions/complex.rs index c32e60f..0896e1e 100644 --- a/src/interactions/complex.rs +++ b/src/interactions/complex.rs @@ -1,7 +1,7 @@ -use super::hbond::*; -use super::ionic::*; -use super::structs::{InteractingEntity, Interaction, ResultEntry}; -use super::vdw::*; +use super::{ + find_hydrogen_bond, find_hydrophobic_contact, find_ionic_bond, find_vdw_contact, + find_weak_hydrogen_bond, InteractingEntity, Interaction, ResultEntry, +}; use crate::utils::parse_groups; use pdbtbx::*; @@ -136,6 +136,16 @@ impl Interactions for InteractionComplex { }); atomic_contacts.extend(ionic_bonds); + // Hydrophobic contacts + let hydrophobic_contacts = + find_hydrophobic_contact(&x.0, &x.1).map(|intxn| ResultEntry { + interaction: intxn, + ligand: hierarchy_to_entity(&x.0), + receptor: hierarchy_to_entity(&x.1), + distance: x.0.atom().distance(x.1.atom()), + }); + atomic_contacts.extend(hydrophobic_contacts); + Some(atomic_contacts) }) .flatten() diff --git a/src/interactions/hydrophobic.rs b/src/interactions/hydrophobic.rs new file mode 100644 index 0000000..83cee40 --- /dev/null +++ b/src/interactions/hydrophobic.rs @@ -0,0 +1,68 @@ +use super::structs::Interaction; + +use pdbtbx::*; + +const HYDROPHOBIC_CONTACT_DIST: f64 = 4.5; + +/// Search for hydrophobic contacts. +/// +/// Check if the distance between two hydrophobics is within [`HYDROPHOBIC_CONTACT_DIST`]. +pub fn find_hydrophobic_contact( + entity1: &AtomConformerResidueChainModel, + entity2: &AtomConformerResidueChainModel, +) -> Option { + let e1_atom = entity1.atom(); + let e2_atom = entity2.atom(); + match is_hydrophobic(entity1.residue().name().unwrap(), e1_atom.name()) + & is_hydrophobic(entity2.residue().name().unwrap(), e2_atom.name()) + & (e1_atom.distance(e2_atom) <= HYDROPHOBIC_CONTACT_DIST) + { + true => Some(Interaction::HydrophobicContact), + false => None, + } +} + +/// Check if the entity has an atom that belongs to the hydrophobic category. +fn is_hydrophobic(res_name: &str, atom_name: &str) -> bool { + // Carbon beta of all other than Glycine/Serine + if (atom_name == "CB") & (res_name != "SER") { + return true; + } + matches!( + (res_name, atom_name), + ("ARG", "CG") | ("GLN", "CG") + | ("GLU", "CG") + | ("ILE", "CG1") + | ("ILE", "CD1") + | ("ILE", "CG2") + | ("LEU", "CG") + | ("LEU", "CD1") + | ("LEU", "CD2") + | ("LYS", "CG") + | ("LYS", "CD") + | ("MET", "CG") + | ("MET", "SD") // sulfur in CYS has a hydrogen and is polarized + | ("MET", "CE") + | ("PHE", "CG") + | ("PHE", "CD1") + | ("PHE", "CD2") + | ("PHE", "CE1") + | ("PHE", "CE2") + | ("PHE", "CZ") + | ("PRO", "CG") + | ("THR", "CG2") + | ("TRP", "CG") + | ("TRP", "CD2") + | ("TRP", "CE3") + | ("TRP", "CZ3") + | ("TRP", "CH2") + | ("TRP", "CZ2") + | ("TYR", "CG") + | ("TYR", "CD1") + | ("TYR", "CD2") + | ("TYR", "CE1") + | ("TYR", "CE2") + | ("VAL", "CG1") + | ("VAL", "CG2") + ) +} diff --git a/src/interactions/mod.rs b/src/interactions/mod.rs index c651cf5..d890480 100644 --- a/src/interactions/mod.rs +++ b/src/interactions/mod.rs @@ -1,5 +1,12 @@ pub mod complex; pub mod hbond; +pub mod hydrophobic; pub mod ionic; pub mod structs; pub mod vdw; + +use hbond::{find_hydrogen_bond, find_weak_hydrogen_bond}; +use hydrophobic::find_hydrophobic_contact; +use ionic::find_ionic_bond; +use structs::*; +use vdw::find_vdw_contact;