ProtoSyn Protein Mutation
In this demo we can use ProtoSyn.jl to mutate amino acids. Different rotamers can be selected for the mutated residue. To use ProtoSyn here you currently have to use a workaround. The getprotosyn()
function downloads the source code, then you can include
it. In the future hopefully it will be built in.
Copy-pastable code
using BioMakie
using GLMakie
using BioStructures
BioMakie.getprotosyn()
include("../protosyn.jl")
struc = retrievepdb("2vb1")
chn = collectresidues(struc[1]["A"], standardselector)
writepdb("2vb1x.pdb", chn)
rot_lib = ProtoSyn.Peptides.load_dunbrack()
res_lib = ProtoSyn.load_grammar_from_file(ProtoSyn.resource_dir*"/Peptides/grammars.yml", "default")
pose = ProtoSyn.Peptides.load("2vb1x.pdb"; bonds_by_distance=true) |> Observable
ProtoSyn.Peptides.cap!(pose[])
ProtoSyn.Peptides.assign_default_atom_names!(pose[])
ProtoSyn.sort_atoms_by_graph!(pose[])
ProtoSyn.Peptides.Calculators.Electrostatics.assign_default_charges!(pose[], res_lib)
pdata = plottingdata(pose)
fig = Figure(resolution = (985,700))
layout = fig[1,1] = GridLayout(11,7)
selected = @lift pdata[:resids][][$(pdata[:selected])] |> unique
selection_text = lift(selected) do sel
if length(sel) == 0
return ""
else
return "$(string(pose[].graph[1][sel[1]]))"
end
end
_plotstruc!(layout[1:10,1:5], pdata; resolution = (600,700))
title = Label(layout[1,6:7]; text = "Mutate Residue", fontsize = 30)
selection_label = Label(layout[2,6:7]; text = "Selection:", fontsize = 20)
vselection = Label(layout[3,6:7]; text = selection_text, fontsize = 16)
clear_button = Button(layout[4,6:7]; label = "Clear selection",
buttoncolor = :pink, fontsize = 18,
width = 140, height = 50)
mutation_label = Label(layout[5,6:7]; text = "Mutate selection to:", fontsize = 20)
mutate_menu = Menu(layout[6,6:7]; options = BioMakie.res3letters[1:20],
cell_color_active = to_color(:lightblue),
cell_color_hover = to_color(:lightgreen),
selection_cell_color_inactive = to_color(:lightblue)
)
mutate_button = Button(layout[7,6:7]; label = "Mutate!",
buttoncolor = :lightgreen, fontsize = 18, width = 80, height = 50
)
rotamer = Observable(1)
rotamer_label = Label(layout[8:9,6]; text = "Change rotamer:", fontsize = 20)
rotamer_button1 = Button(layout[8,7]; label = "ꜛ",
buttoncolor = :lightgreen, fontsize = 40,
tellwidth = false, width = 70, height = 40
)
rotamer_button2 = Button(layout[9,7]; label = "ꜜ",
buttoncolor = :lightgreen, fontsize = 40,
tellwidth = false, width = 70, height = 40
)
on(clear_button.clicks) do s
pdata[:selected][] = Vector{Bool}(undef,length(pdata[:selected][])) .= false
end
on(mutate_button.clicks) do s
selection_text[] = "$(string(pose[].graph[1][selected[][1]]))"
mutletter = BioMakie.resletterdict[mutate_menu.selection[]]
ProtoSyn.Peptides.mutate!(pose[], pose[].graph[1][selected[][1]], res_lib, [mutletter])
fixpose!(pose)
end
on(rotamer_button1.clicks) do s
if length(selected[]) == 0
println("No selection")
else
phi = ProtoSyn.getdihedral(pose[].state, ProtoSyn.Peptides.phi(pose[].graph[1][selected[][1]]))
psi = ProtoSyn.getdihedral(pose[].state, ProtoSyn.Peptides.psi(pose[].graph[1][selected[][1]]))
stack = rot_lib["$(pose[].graph[1][selected[][1]].name)"][phi, psi]
nrotamers = length(stack.rotamers)
if rotamer[] < nrotamers
rotamer[] = rotamer[] + 1
end
ProtoSyn.Peptides.apply!(pose[].state, stack[rotamer[]], pose[].graph[1][selected[][1]])
fixpose!(pose)
end
end
on(rotamer_button2.clicks) do s
if length(selected[]) == 0
println("No selection")
else
phi = ProtoSyn.getdihedral(pose[].state, ProtoSyn.Peptides.phi(pose[].graph[1][selected[][1]]))
psi = ProtoSyn.getdihedral(pose[].state, ProtoSyn.Peptides.psi(pose[].graph[1][selected[][1]]))
stack = rot_lib["$(pose[].graph[1][selected[][1]].name)"][phi, psi]
nrotamers = length(stack.rotamers)
if rotamer[] > nrotamers
rotamer[] = rotamer[] - 1
end
ProtoSyn.Peptides.apply!(pose[].state, stack[rotamer[]], pose[].graph[1][selected[][1]])
fixpose!(pose)
end
end
Load BioMakie and ProtoSyn
Download the protosyn source code from the src directory of BioMakie and include
it. This should install a few packages (SplitApplyCombine, Colors, Meshes, GeometryBasics, OrderedCollections, Distances) and then import ProtoSyn.
using BioMakie
using GLMakie
BioMakie.getprotosyn()
include("../protosyn.jl")
Prepare the structure
To simplify things, we will load a structure with BioStructures and save chain "A" as a PDB file. Then we will load the PDB file with ProtoSyn.
using BioStructures
struc = retrievepdb("2vb1")
chn = collectresidues(struc[1]["A"], standardselector)
writepdb("2vb1x.pdb", chn)
pose = ProtoSyn.Peptides.load("2vb1x.pdb"; bonds_by_distance=true) |> Observable
Get plotting data and plot it
pdata = plottingdata(pose)
fig = Figure()
_plotstruc!(fig, pdata)
Prepare the structure
We can use diagnose
to get an idea of what is missing and of inconsistencies in the structure.
ProtoSyn.Peptides.diagnose(pose[])
We have several issues, including charges, naming, and caps, which are the terminal hydrogens. We can use the following functions to address these issues. First we load the library of amino acids, to get the Peptide/protein-specific data, instead of the default generic data.
res_lib = ProtoSyn.load_grammar_from_file(ProtoSyn.resource_dir*"/Peptides/grammars.yml", "default")
ProtoSyn.Peptides.cap!(pose[])
ProtoSyn.Peptides.assign_default_atom_names!(pose[])
ProtoSyn.sort_atoms_by_graph!(pose[])
ProtoSyn.Peptides.Calculators.Electrostatics.assign_default_charges!(pose[], res_lib)
ProtoSyn.Peptides.diagnose(pose[])
Now the issues should say OK
, except for the atom-level graph. We can ignore this for now. This fixpose!
function below may be convenient for syncing and correcting the structure after making changes. Using pose[] = pose[]
can force Makie to update the pose/figure.
function fixpose!(pose::Observable; res_lib=ProtoSyn.load_grammar_from_file(ProtoSyn.resource_dir*"/Peptides/grammars.yml", "default"))
ProtoSyn.Peptides.cap!(pose[])
ProtoSyn.Peptides.assign_default_atom_names!(pose[])
ProtoSyn.sort_atoms_by_graph!(pose[])
ProtoSyn.Calculators.Electrostatics.assign_default_charges!(pose[],res_lib)
ProtoSyn.Peptides.sync!(pose[])
pose[] = pose[]
end
Mutate the structure
Get information about a residue. In this example we will use residue 128 because it is easy to find on the structure. The long side chain of this arginine extends outward the furthest.
pose[].graph[1][128]
Next lets try mutating it to tyrosine. We can use the mutate!
function to do this. Combine it with fixpose!
to get the updated structure. You should see the side chain change into the phenol ring of tyrosine.
ProtoSyn.Peptides.mutate!(pose[], pose[].graph[1][128], res_lib, ["Y"])
fixpose!(pose)
To choose different rotamers/orientations, we can use the rotamer library. ProtoSyn provides a stack of the most likely rotamers based on the dihedral angles of the residue.
rot_lib = ProtoSyn.Peptides.load_dunbrack()
phi = ProtoSyn.getdihedral(pose[].state, ProtoSyn.Peptides.phi(pose[].graph[1][128]))
psi = ProtoSyn.getdihedral(pose[].state, ProtoSyn.Peptides.psi(pose[].graph[1][128]))
stack = rot_lib["TYR"][phi, psi]
ProtoSyn.Peptides.apply!(pose[].state, stack[3], pose[].graph[1][128])
fixpose!(pose)
This page was generated using Literate.jl.