Your first peptide¶
By the end of this page you will have built a cyclic peptide from a sequence string, read the HELM back, inspected its crosslinks, used a non-natural monomer, and computed its mass.
It takes about ten minutes, and assumes you have been through Your first oligonucleotide or are comfortable with the idea that HELMshaker needs a monomer library.
The mass step needs the chem extra:
pip install "helmshaker[chem]"
Step 1: load a library¶
from helmshaker import Molecule, MonomerLibrary
library = MonomerLibrary()
library.load_from_file("../examples/docs_library.json")
print(f"{len(library)} monomers available")
40 monomers available
Step 2: build a peptide from a sequence¶
You do not have to write HELM by hand. from_peptide_sequence takes a sequence
string and works out the HELM, resolving connection points against the library.
linear = Molecule.from_peptide_sequence("CAAAC", monomer_library=library)
print(linear.to_helm())
PEPTIDE1{C.A.A.A.C}$$$$V2.0
Step 3: add a disulfide¶
A crosslink is written MONOMER:POSITION-MONOMER:POSITION. Positions are
1-based. Naming the monomer as well as the position means a typo fails loudly
instead of bridging the wrong pair.
cyclic = Molecule.from_peptide_sequence(
"CAAAC", crosslinks="C:1-C:5", monomer_library=library
)
print(cyclic.to_helm())
PEPTIDE1{C.A.A.A.C}$PEPTIDE1,PEPTIDE1,1:R3-5:R3$$$V2.0
The extra section after the first $ is the connection: residue 1 R3 to residue
5 R3, which is the disulfide.
Step 4: inspect it¶
data = cyclic.data
print("peptides :", data.get_peptide_ids())
print("sequence :", data.get_sequence("PEPTIDE1"))
print("natural analog :", data.get_natural_sequence("PEPTIDE1"))
print("is cyclic :", data.is_cyclic("PEPTIDE1"))
peptides : ['PEPTIDE1'] sequence : ['C', 'A', 'A', 'A', 'C'] natural analog : CAAAC is cyclic : True
for link in data.get_crosslinks("PEPTIDE1"):
print(f" {link.monomer1.id}:{link.attachment1} - {link.monomer2.id}:{link.attachment2}")
C:R3 - C:R3
Step 5: use a non-natural monomer¶
Two spellings reach the same HELM. Dot-delimited lets you name a monomer inline:
print(Molecule.from_peptide_sequence("C.A.Nle.R.N", monomer_library=library).to_helm())
PEPTIDE1{C.A.[Nle].R.N}$$$$V2.0
Or write X as a placeholder and resolve it with a modifier, which reads better
for a long sequence with one substitution:
print(Molecule.from_peptide_sequence("CAXRN", modifiers="X3=Nle", monomer_library=library).to_helm())
PEPTIDE1{C.A.[Nle].R.N}$$$$V2.0
Nle has to exist in the library you pass. If it does not, the grammar cannot
find its connection points and the call fails rather than inventing them.
Step 6: read a HELM back¶
Parsing HELM works the same way for peptides as for oligonucleotides:
capped = Molecule.from_helm("PEPTIDE1{G.A.C.[Nle].[am]}$$$$V2.0", monomer_library=library)
print(capped.data.get_sequence("PEPTIDE1"))
print(capped.data.get_natural_sequence("PEPTIDE1"))
['G', 'A', 'C', 'Nle', 'am'] GACLX
The natural-analog sequence maps Nle to L, its closest proteinogenic
neighbour, and the C-terminal amide cap to X, because no amino acid
corresponds to it.
Step 7: compute the mass¶
This assembles the whole structure from the monomer records, so it needs RDKit and a library whose records carry SMILES.
print("weight :", round(cyclic.molecular_weight(), 3))
print("formula:", cyclic.molecular_formula())
weight : 435.528 formula: C15H25N5O6S2
The disulfide is accounted for: the cyclic form is two hydrogens lighter than the linear one.
print("linear :", round(linear.molecular_weight(), 3), linear.molecular_formula())
print("cyclic :", round(cyclic.molecular_weight(), 3), cyclic.molecular_formula())
linear : 437.544 C15H27N5O6S2 cyclic : 435.528 C15H25N5O6S2
What next¶
- Peptide sequence grammar documents the full syntax
- Load a monomer library pulls a real peptide dictionary from TMR
- Compute mass and structure goes further into structure output