Skip to content

Commit

Permalink
Draw line segments when there are missing residues
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonOresten committed Apr 5, 2024
1 parent 60c4eff commit de673e8
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
18 changes: 17 additions & 1 deletion src/ribbon/render.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,29 @@ function render!(
protein::AbstractVector{Protein.Chain};
colorscheme::ColorScheme = default_colorscheme,
color_vectors::AbstractVector{<:AbstractVector{<:RGB}} = [colorscheme[LinRange(0, 1, length(chain))] for chain in protein],
plots = nothing,
kwargs...
)
@assert Protein.has_assigned_ss(protein) "Protein must have assigned secondary structure."
@assert length(protein) == length(color_vectors)
@assert length.(protein) == length.(color_vectors)
for (chain, colors) in zip(protein, color_vectors)
render!(container, chain, colors; kwargs...)
subchain_ranges = split_by_resnum(chain)
if length(subchain_ranges) == 1
render!(container, chain, colors; kwargs...)
else
subchains = [chain[r] for r in subchain_ranges]
for (subchain, r) in zip(subchains, subchain_ranges)
render!(container, subchain, colors[r]; kwargs...)
end
# draw lines between start and ends of subchains
for (i, j) in zip(1:length(subchains)-1, 2:length(subchains))
startpoint, endpoint = subchains[i].backbone[end], subchains[j].backbone[begin]
xs, ys, zs = [LinRange(startpoint[i], endpoint[i], 16) for i in 1:3]
p = linesegments!(container, xs, ys, zs; linewidth=3, color=colorant"white", transparency=true)
!isnothing(plots) && push!(plots, p)
end
end
end

return container
Expand Down
21 changes: 21 additions & 0 deletions src/ribbon/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,25 @@ function expand_colors(colors::Vector, N::Integer)
end

return reshape(result[1:N], :, 1)
end

function Base.getindex(chain::Protein.Chain, r::UnitRange{<:Integer})
Protein.Chain(chain.id, chain.backbone[3*r.start-2:3r.stop], modelnum=chain.modelnum, resnums=chain.resnums[r], aavector=chain.aavector[r], ssvector=chain.ssvector[r])
end

# split a chain into subchains if there is a gap in the residue numbering
function split_by_resnum(chain::Protein.Chain)
split_indices = findall(diff(chain.resnums) .!= 1)
if isempty(split_indices)
return [chain]
end

ranges = UnitRange{Int}[]
start_idx = 0
for idx in split_indices
push!(ranges, start_idx+1:idx)
start_idx = idx
end
push!(ranges, start_idx+1:length(chain))
return ranges
end

0 comments on commit de673e8

Please sign in to comment.