swsoyee / r3dmol

🧬 An R package for visualizing molecular data in 3D
https://swsoyee.github.io/r3dmol/
Other
89 stars 4 forks source link

Color by b-factor #53

Open halg3 opened 4 months ago

halg3 commented 4 months ago

Hello!

I had taken a look through the vignette, and I did not see a function that allows users to color 3D models by the b-factor found within a pdb file (eg. coloring models produced by AlphaFold by pLDDT scores, as stored in the b-factor field). I was wondering if such a function does exist, or if there is a way that I could achieve this.

Thank you so much for such a useful package!

swsoyee commented 4 months ago

Hello, thank you for using r3dmol.

I'm not familiar with this area of research, so I'm unsure about what a B factor is. As far as I remember, such a function hasn't been developed in our tool.

You might want to check the official documentation for 3dmol.js to see if there's a built-in function for coloring based on B factors. If there's any mention of it in the documentation, a similar approach should be feasible in r3dmol as well.

If you find the documentation but are unsure how to implement it, feel free to share the link with me, and I'll take a look. I believe coloring based on a specific series of positions should achieve this goal.

jvolkening commented 3 months ago

Hi @halg3,

I happened to be looking for the same functionality today. With guidance from this Gist I was able to do it with cartoon rendering by using the colorfunc property, e.g. the following will color from white to blue over the range 20-100:

library(dplyr)
library(r3dmol)

pdb <- get_pdb_data_somehow()

color_by_b <- "function(atom) {
        var scale = d3.scaleLinear().domain([20,100]).range(['white','blue']);
        var c = scale(atom.b);
        return d3.rgb(c).hex();
}"

r3dmol() %>%
    m_add_model(pdb, format='pdb') %>%
    m_set_style(style = m_style_cartoon(colorfunc = color_by_b)) %>%
    m_zoom_to()

This uses D3, so you also need to include that javascript library in your final document (e.g. with include: if you're using RMarkdown).

bananabenana commented 1 month ago

I have also been colouring by lDDT scores, and I used the following approach, which is probably overengineered:

Requirements

# Load/create lDDT_per_residue (example)
lDDT_per_residue <- tibble::tibble(
  Residue_position = c(1, 2, 3, 4, 5, 6, 7),
  lDDT_score = c(0.971, 0.982, 0.992, 0.983, 0.997, 0.998, 0.999),
)

# Generate a color palette with 100 colors (lDDT ranges from 0-1)
lddt_palette <- sequential_hcl(palette = "Heat", n = 100, rev = TRUE)

# Map lDDT scores to colours by setting n=100 breaks
lDDT_per_residue<- lDDT_per_residue %>%
  mutate(
    lddt_colour = lddt_palette[as.numeric(cut(lDDT_score, breaks = 100))],
    )

# Load pdb
pdb <- bio3d::read.pdb("model.pdb")

# Vis model
structure_vis <- r3dmol() %>% 
  m_add_models(m_bio3d(pdb)) %>% 
  m_set_background_color(gray(0.9)) %>% 
  m_add_outline() 

# Apply colours to residues
for (i in 1:nrow(lDDT_per_residue)) {
  structure_vis<- conservation_structure %>%
    m_set_style(sel = m_sel(resi = lDDT_per_residue$Residue_position[i]), 
                style = m_style_cartoon(color = lDDT_per_residue$lddt_colour[i]))
}
structure_vis