Skip to content

Commit

Permalink
Add support for head-to-sidechain cyclization seen in lasso peptides
Browse files Browse the repository at this point in the history
  • Loading branch information
althonos committed Mar 1, 2022
1 parent b09b1e1 commit 59599ff
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 7 deletions.
77 changes: 70 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ pub enum Error {
/// ```
DuplicateCrossLink(u16),

/// A requested cyclization is invalid.
///
/// This issue can occur when a requested cycle cannot be created from the
/// amino acid residues at the given location.
InvalidCyclization(u16, AminoAcid, Cyclization),

/// Too many cross-links were created.
///
/// This can occur when a protein contains too many cross-links, which will
Expand All @@ -89,6 +95,14 @@ impl std::fmt::Display for Error {
Error::InvalidCrossLink(i, aa, _) => {
write!(f, "invalid cross-link for residue {} ({})", i, aa.as_code())
}
Error::InvalidCyclization(i, aa, _) => {
write!(
f,
"invalid cyclization for residue {} ({})",
i,
aa.as_code()
)
}
}
}
}
Expand Down Expand Up @@ -341,6 +355,13 @@ pub enum Cyclization {

/// Head-to-tail cyclization, resulting in an homodetic cyclic peptide.
HeadToTail,

/// Head-to-sidechain cyclization, resulting in a lasso peptide.
///
/// This cyclization process forms an isopeptidic bond between the
/// amine group of the N-terminal amino acid and the carboxyl group of
/// an Asp or Glu residue.
Lasso(u16),
}

impl Default for Cyclization {
Expand Down Expand Up @@ -405,6 +426,7 @@ impl<S> Protein<S> {
follower: &mut F,
index: u16,
cross_links: &HashMap<u16, (Rnum, CrossLink)>,
cyclization: &Cyclization,
) -> Result<(), Error> {
const CARBON_TH2: AtomKind = AtomKind::Bracket {
symbol: BracketSymbol::Element(Element::C),
Expand Down Expand Up @@ -436,6 +458,18 @@ impl<S> Protein<S> {
}
}

// only some amino-acids can cyclized
match cyclization {
Cyclization::Lasso(n) if n == &index => match aa {
AminoAcid::Asp => (),
AminoAcid::Glu => (),
other => {
return Err(Error::InvalidCyclization(index, other, *cyclization));
}
},
_ => (),
}

// visit the alpha carbon and the residue
match aa {
AminoAcid::Dhb => {
Expand Down Expand Up @@ -757,9 +791,16 @@ impl<S> Protein<S> {
// residue
follower.extend(BondKind::Elided, AtomKind::Aliphatic(Aliphatic::C));
follower.extend(BondKind::Elided, AtomKind::Aliphatic(Aliphatic::C));
match cyclization {
Cyclization::Lasso(n) if n == &index => {
follower.join(BondKind::Elided, Rnum::R0);
}
_ => {
follower.extend(BondKind::Elided, AtomKind::Aliphatic(Aliphatic::O));
follower.pop(1);
}
}
follower.extend(BondKind::Double, AtomKind::Aliphatic(Aliphatic::O));
follower.pop(1);
follower.extend(BondKind::Elided, AtomKind::Aliphatic(Aliphatic::O));
follower.pop(3);
}

Expand All @@ -770,9 +811,16 @@ impl<S> Protein<S> {
follower.extend(BondKind::Elided, AtomKind::Aliphatic(Aliphatic::C));
follower.extend(BondKind::Elided, AtomKind::Aliphatic(Aliphatic::C));
follower.extend(BondKind::Elided, AtomKind::Aliphatic(Aliphatic::C));
match cyclization {
Cyclization::Lasso(n) if n == &index => {
follower.join(BondKind::Elided, Rnum::R0);
}
_ => {
follower.extend(BondKind::Elided, AtomKind::Aliphatic(Aliphatic::O));
follower.pop(1);
}
}
follower.extend(BondKind::Double, AtomKind::Aliphatic(Aliphatic::O));
follower.pop(1);
follower.extend(BondKind::Elided, AtomKind::Aliphatic(Aliphatic::O));
follower.pop(4);
}

Expand Down Expand Up @@ -837,12 +885,21 @@ where
if let Some((index, aa)) = aa_iter.next() {
// N-terminus: create a the N of the primary amine.
follower.root(AtomKind::Aliphatic(Aliphatic::N));
if self.cyclization == Cyclization::HeadToTail {
if matches!(
self.cyclization,
Cyclization::HeadToTail | Cyclization::Lasso(_)
) {
follower.join(BondKind::Elided, Rnum::R0);
}

// visit residue
Self::visit_residue(aa, follower, index as u16 + 1, &self.cross_links)?;
Self::visit_residue(
aa,
follower,
index as u16 + 1, // user-provided indices start at 1
&self.cross_links,
&self.cyclization,
)?;

// add the carboxy group to the β carbon.
follower.extend(BondKind::Double, AtomKind::Aliphatic(Aliphatic::O));
Expand All @@ -851,7 +908,13 @@ where
while let Some((index, aa)) = aa_iter.next() {
// next amino acid: create the N atom of the carboxamide and visit residue.
follower.extend(BondKind::Elided, AtomKind::Aliphatic(Aliphatic::N));
Self::visit_residue(aa, follower, index as u16 + 1, &self.cross_links)?;
Self::visit_residue(
aa,
follower,
index as u16 + 1,
&self.cross_links,
&self.cyclization,
)?;
// add the carboxy group to the β carbon.
follower.extend(BondKind::Double, AtomKind::Aliphatic(Aliphatic::O));
follower.pop(1);
Expand Down
11 changes: 11 additions & 0 deletions tests/pubchem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,14 @@ test_peptide!(
[Gly, Cys, Cys, Ser, Asp, Pro, Arg, Cys, Ala, Trp, Arg, Cys],
cross_links = [CrossLink::Cystine(2, 8), CrossLink::Cystine(3, 12)]
);

// lasso cyclization
test_peptide!(
test_microcin_j25,
57397977,
[
Gly, Gly, Ala, Gly, His, Val, Pro, Glu, Tyr, Phe, Val, Gly, Ile, Gly, Thr, Pro, Ile, Ser,
Phe, Tyr, Gly
],
cyclization = Cyclization::Lasso(8)
);

0 comments on commit 59599ff

Please sign in to comment.