Hi everyone,
I’m writing for a little package for myself and to maybe share with the community one day, if it’s mature enough. I want to plot sequence motifs of letters (or peptides for those who are curious about the context).
For those that are not familiar with such plots, see a detailed description on this wikipedia page or see take a look at this image:
The question of how to calculate the order and sizes of letters is solved. The problem I face is the actual plotting of letters that are stretched in the y-dimension with the according size, nicely adhering to each other with no gaps or overlaps in the y-axis, and nicely aligned on the x-axis.
I figured that the easiest way to do this is to use CairoMakie.
My plan is the following:
- Define the alphabet of letters (in my case amino acids for the bioinformaticians out there) as individual little images.
- Stack those little images with the according height adjustment one on top of the other for each position on the x-axis.
So far I managed to create images for each letter I need that (more or less) nicely fill out the full canvas box with this function and subsequent figure generation:
using CairoMakie
function render_letter_image(letter::Char; color=:black, fontsize=1200, res=(845, 910))
fig = Figure(figure_padding = 0)
ax = Axis(fig[1, 1],
xgridvisible = false,
ygridvisible = false
)
hidedecorations!(ax)
hidespines!(ax)
limits!(ax, 0, 1, 0, 1)
text_dims = text!(ax, string(letter);
position = (0.5, 0.362),
align = (:center, :center),
color = color,
font = "Helvetica",
fontsize = fontsize
)
resize!(fig.scene, res...) # resizes the canvas
return rotr90(colorbuffer(fig.scene))
end
# example usage
img = render_letter_image('Q')
fig2 = Figure(figure_padding = 0)
ax2 = Axis(fig2[1, 1])
image!(ax2, img)
hidedecorations!(ax2)
hidespines!(ax2)
res2 = (600, 300) # just some random example numbers simulating the hard fixed width and the variable height
resize!(fig2.scene, res2...) # redefine size of letter based on width and height indicated (height is the "bits" axis dimension in the picture above)
fig2 # plot the canvas
My next step would be to simulate the stacking of letters for just one position. as soon as I figure that out I can just do that for each individual position.
Where Im currently stuck is this stacking of figures. How do I solve this? the output of my function above is a colourbuffer
struct. I tried to just stack them like this:
function render_letter_image_vector(images, heights; width = 200)
fig = Figure()
ax = Axis(fig[1, 1],
xgridvisible = false,
ygridvisible = false
)
height_in_plot = cumsum(heights) - (heights ./ 2) # individual letter y positions
for (i, img) in enumerate(images) # images is a vector of colourbuffers
# I have no idea how to approach this stacking in a Axes of a Figure part. Everything I try fails.
# image!(ax, image)# 1, height_in_plot)
end
return fig
end
# my test to try plotting the alphabet I need
images_ex = [render_letter_image(char) for char in "ACDEFGHIKLMNPQRSTVWY"];
heights_ex = rand(20) * 500
sum(heights_ex)*1.03
fig3 = render_letter_image_vector(images_ex, heights_ex)
Is there anyone out there that could assist me? Probably other bioinfarmitcs-proximate people would also be happy about a nice sequence motif plotting option in pure Julia:)
Thanks in advance!