Skip to content

Commit

Permalink
makie
Browse files Browse the repository at this point in the history
  • Loading branch information
cossio committed Jan 22, 2023
1 parent dfa78dd commit cc66832
Show file tree
Hide file tree
Showing 10 changed files with 1,415 additions and 90 deletions.
7 changes: 7 additions & 0 deletions Artifacts.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[RF00162_trimmed]
git-tree-sha1 = "de354c34ade084ac3634c94c2ea4ede8ed721ea8"
lazy = true

[[RF00162_trimmed.download]]
sha256 = "c90ab58f8c2b290dc44f9aac6ea2c5d03d476acf7f96fd938d68bbf36c20d9bf"
url = "https://gist.github.com/cossio/16360fcfdbddbd13430d485f0000e379/raw/de354c34ade084ac3634c94c2ea4ede8ed721ea8.tar.gz"
6 changes: 2 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ authors = "Jorge Fernandez-de-Cossio-Diaz <[email protected]>"
version = "0.2.2-DEV"

[deps]
PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"

[compat]
julia = "1.6"
PyPlot = "2.9"
Colors = "0.12"
7 changes: 7 additions & 0 deletions docs/Artifacts.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[RF00162_trimmed]
git-tree-sha1 = "de354c34ade084ac3634c94c2ea4ede8ed721ea8"
lazy = true

[[RF00162_trimmed.download]]
sha256 = "c90ab58f8c2b290dc44f9aac6ea2c5d03d476acf7f96fd938d68bbf36c20d9bf"
url = "https://gist.github.com/cossio/16360fcfdbddbd13430d485f0000e379/raw/de354c34ade084ac3634c94c2ea4ede8ed721ea8.tar.gz"
11 changes: 3 additions & 8 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
[deps]
AlgebraOfGraphics = "cbdf2221-f076-402e-a563-3d30da359d67"
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
GitHub = "bc5e4493-9b4d-5f90-b8aa-2b2bcaad7a26"
Gzip_jll = "be1be57a-8558-53c3-a7e5-50095f79957e"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
LogExpFunctions = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
MLDatasets = "eb30cadb-4394-5ae3-aed4-317e484a6458"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Rfam = "38c5b72b-a3f0-437e-9f79-f3da4655de63"
SequenceLogos = "7a3f67ce-6eeb-4904-9da4-2cbd106a5944"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
41 changes: 30 additions & 11 deletions docs/src/literate/rfam.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,23 @@
# SequenceLogos examples with RFAM
=#

import GitHub
import PyPlot
import SequenceLogos
using Downloads: download
using LazyArtifacts: LazyArtifacts, @artifact_str
import Makie
import CairoMakie
using Statistics: mean
using LogExpFunctions: xlogx

# Fetch RNA family alignment RF00162 from RFAM (pre-stored as a Github Gist)

data = GitHub.gist("b63e87024fac287a1800b1555276a04b")
url = data.files["RF00162-trimmed.afa"]["raw_url"]
path = download(url; timeout = Inf)
import PyPlot

# Fetch RNA family alignment RF00162 from RFAM (pre-stored as a Github Gist)
fasta_path = joinpath(artifact"RF00162_trimmed", "RF00162-trimmed.afa")
nothing #hide

# Parse lines

seqs = String[]
for line in eachline(path)
for line in eachline(fasta_path)
if startswith(line, '>')
continue
else
Expand All @@ -37,10 +36,30 @@ function onehot(s::String)
return reshape(collect(s), 1, length(s)) .== collect(NTs)
end
X = reshape(reduce(hcat, onehot.(seqs)), 5, :, length(seqs));
p = reshape(mean(X; dims=3), size(X)[1:2]...)
xlog2x(x) = xlogx(x) / log(oftype(x,2))
H = sum(-xlog2x.(p); dims=1)

weights = cons = p .* (log2(5) .- H)

letters = collect(NTs)
colors = [:red, :red, :blue, :blue, :black]

fig = Makie.Figure()
ax = Makie.Axis(fig[1,1], width=600, height=100)
SequenceLogos.makie_sequence_logo!(ax, cons, letters, colors)
Makie.resize_to_layout!(fig)
fig

function plot_example()
fig = Makie.Figure()
ax = Makie.Axis(fig[1,1], width=600, height=100)
SequenceLogos.makie_sequence_logo!(ax, cons, letters, colors)
Makie.resize_to_layout!(fig)
fig
end

# Sequence logo

xlog2x(x) = xlogx(x) / log(oftype(x,2))
logo_from_matrix(w::AbstractMatrix) = SequenceLogos.logo_from_matrix(w, replace(NTs, '-' => ''))


Expand Down
18 changes: 14 additions & 4 deletions src/SequenceLogos.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
module SequenceLogos

include("logo.jl")
include("color_funs.jl")
include("pyplot.jl")
include("bio.jl")
import Makie

using LazyArtifacts: LazyArtifacts, @artifact_str
import Makie

#include("logo.jl")
#include("color_funs.jl")
#include("pyplot.jl")
#include("bio.jl")
include("makie.jl")

function __example_fasta()
return joinpath(artifact"RF00162_trimmed", "RF00162-trimmed.afa")
end

end # module
99 changes: 54 additions & 45 deletions src/makie.jl
Original file line number Diff line number Diff line change
@@ -1,64 +1,73 @@
import CairoMakie
import Makie

struct SeqLogo{W<:AbstractMatrix,L<:AbstractVecOrMat,C<:AbstractVecOrMat}
weights::W
letters::L
colors::C
function SeqLogo{W,L,C}(weights::W, letters::L, colors::C) where {W<:AbstractMatrix,L<:AbstractVector,C<:AbstractVector}
@assert size(weights, 1) == length(letters) == length(colors)
return new{W,L,C}(weights, letters, colors)
end
function SeqLogo{W,L,C}(weights::W, letters::L, colors::C) where {W<:AbstractMatrix,L<:AbstractMatrix,C<:AbstractMatrix}
@assert size(weights) == size(letters) == size(colors)
return new{W,L,C}(weights, letters, colors)
end
end

function SeqLogo(weights::W, letters::L, colors::C) where {W,L,C}
return SeqLogo{W,L,C}(weights, letters, colors)
end

function sort_logo(logo::SeqLogo)
weights = similar(logo.weights)
letters = similar(logo.letters, size(weights))
colors = similar(logo.colors, size(weights))
for i in axes(weights, 1)
p = sortperm(logo.weights[i,:])
weights[i, :] .= logo.weights[i, p]
letters[i, :] .= logo.letters[p]
colors[i, :] .= logo.colors[p]
end
return SeqLogo(weights, letters, colors)
end

function makie_sequence_logo!(
ax::Makie.Axis, weights::AbstractMatrix, letters::AbstractMatrix, colors::AbstractMatrix
)
@assert size(weights) == size(letters) == size(colors)

# for i in axes(weights, 2)
# y_pos = y_neg = 0.0
# for k in axes(weights, 1)
# if weights[k,i] > 0
# y = y_pos
# y_pos += weights[k,i]
# elseif weights[k,i] < 0
# y = y_neg
# y_neg += weights[k,i]
# end

# Makie.text!(
# ax, i, y; text=string(letters[k,i]),
# textsize=abs(weights[k,i]), scale=Makie.Vec2(1/abs(weights[k,i]), 1),
# color=colors[k,i],
# markerspace=:data, align=(:center, :baseline), font="Arial bold"
# )
# Makie.scale
# end
# end


# return nothing

x = repeat((1:size(weights, 2))', size(weights, 1), 1)
y = zero(weights)
for i in axes(weights, 1)
for i in axes(weights, 2)
y_pos = y_neg = 0.0
for j in axes(weights, 2)
if weights[i,j] > 0
y_pos += weights[i,j]
y[i,j] = y_pos
elseif weights[i,j] < 0
y_neg += weights[i,j]
y[i,j] = y_neg
for k in axes(weights, 1)
if weights[k,i] > 0
y[k,i] = y_pos + weights[k,i]/2
y_pos += weights[k,i]
elseif weights[k,i] < 0
y[k,i] = y_neg + weights[k,i]/2
y_neg += weights[k,i]
end
end
end

Makie.text!(ax, vec(x), vec(y); text=vec(letters), textsize=vec(abs.(weights)))
Makie.text!(
ax, vec(x), vec(y); text=vec(letters),
fontsize=vec([Makie.Vec2(1, abs(w)) for w in weights]),
color=vec(colors),
markerspace=:data, align=(:center, :baseline), font="Arial"
)
end

function makie_sequence_logo!(
ax::Makie.Axis, weights::AbstractMatrix, letters::AbstractVector, colors::AbstractVector
)
@assert size(weights, 1) == length(letters) == length(colors)
weights_sorted, letters_sorted, colors_sorted = sort_sequence_logo(weights, letters, colors)
return makie_seqlogo!(ax, weights_sorted, letters_sorted, colors_sorted)
sorted_weights, sorted_letters, sorted_colors = sort_logo(weights, letters, colors)
return makie_sequence_logo!(ax, sorted_weights, sorted_letters, sorted_colors)
end

function sort_logo(weights::AbstractMatrix, letters::AbstractVector, colors::AbstractVector)
@assert size(weights, 1) == length(letters) == length(colors)
sorted_weights = similar(weights)
sorted_letters = similar(letters, size(weights))
sorted_colors = similar(colors, size(weights))
for i in axes(weights, 2)
p = sortperm(weights[:,i])
sorted_weights[:,i] .= weights[p,i]
sorted_letters[:,i] .= letters[p]
sorted_colors[:,i] .= colors[p]
end
return sorted_weights, sorted_letters, sorted_colors
end
Loading

0 comments on commit cc66832

Please sign in to comment.