AtomPlot

This example shows how to animate the flow of protein residue "frames", linearly interpolating between a point sampled from a gaussian, to a target protein structure.

Setup

using ProteinChains # reexports Backboner.Frames
using Manifolds, LinearAlgebra, Statistics

function initial_frames(frames₁::Frames)
    M = Rotations(3)
    E = Euclidean(3)
    R₁ = eachslice(frames₁.rotations, dims=3)
    t₁ = eachslice(frames₁.translations, dims=2)
    μ = mean(t₁)
    σ = std(t₁)
    R₀ = stack(rand(M, length(R₁)))
    t₀ = stack(rand(E, length(t₁))) .* σ .+ μ
    Frames(R₀, t₀)
end

function interpolate_frames(frames₀::Frames, frames₁::Frames, t::Number)
    M = Rotations(3)
    E = Euclidean(3)
    Rₜ = stack(axes(frames₀.rotations, 3)) do i
        R₀, R₁ = frames₀.rotations[:,:,i], frames₁.rotations[:,:,i]
        exp(M, R₀, t * log(M, R₀, R₁))
    end
    tₜ = stack(axes(frames₀.translations, 2)) do i
        t₀, t₁ = frames₀.translations[:,i], frames₁.translations[:,i]
        exp(E, t₀, t * log(E, t₀, t₁))
    end
    return Frames(Rₜ, tₜ)
end;

Animation

using GLMakie, ProtPlot, Printf
set_theme!(theme_black())

time = Observable(0.0)

fig = Figure(size=(800,600))
ax = Axis3(fig[1,1], title=(@lift "time = $(@sprintf("%.2f", $time))"),
    perspectiveness=0.2, aspect=:data, viewmode=:fit)

chain = pdb"1M4X"A
frames₁ = Frames(chain)
frames₀ = initial_frames(frames₁)
framesₜ = @lift interpolate_frames(frames₀, frames₁, $time)

p = atomplot!(ax, framesₜ;
    color=repeat(range(0, 1, size(frames₁.rotations, 3)), inner=3), colormap=:jet);
[ Info: Downloading file from PDB: 1M4X
record(fig, "frames.mp4", -0.2:0.01:1.5, framerate=48) do t
    if 0 < t <= 1
        time[] = t
    end
    if t == 1.2
        ribbon!(ax.scene, frames₁)
        delete!(ax, p)
    end
    autolimits!(ax)
end;


This page was generated using Literate.jl.