r3dmol icon indicating copy to clipboard operation
r3dmol copied to clipboard

Color by b-factor

Open halg3 opened this issue 1 year ago • 3 comments

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!

halg3 avatar Jul 12 '24 00:07 halg3

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.

swsoyee avatar Jul 12 '24 09:07 swsoyee

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).

jvolkening avatar Aug 02 '24 21:08 jvolkening

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

Requirements

  • lDDT_per_residue
  • pdb file
  • libraries colorspace, tidyverse
# 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

bananabenana avatar Oct 08 '24 08:10 bananabenana

Thanks for your efforts to develop an excellent R package!

Yes, visualize the B-factor is possible.

library(bio3d)
library(r3dmol)

pdb <- read.pdb('t.pdb')
pdb_data <- m_bio3d(pdb)

scheme <- list(
    prop = 'b',
    gradient = 'rwb',
    min = min(pdb$atom$b),
    max = max(pdb$atom$b)
)

r3dmol() %>%
  m_add_model(data = pdb_data) %>%
  m_zoom_to() %>%
  m_add_surface(style = m_style_surface(opacity = 0.9, colorScheme=scheme) )

However, it seems that only preset gradient colors are supported (rwb, sinebow, roygb, according to 3dmol.js documents). 3dmol.js also support custom linear colors, which should be also supported like this:

scheme <- list(
    prop = 'b',
    gradient = 'linear',
    min = min(pdb$atom$b),
    max = max(pdb$atom$b),
    colors = c("yellow", "green")
)

But it doesn't work.

I tested a similar function in py3Dmol, it worked well.

import py3Dmol

view = py3Dmol.view(width=600, height=400)
view.addModel(open('t.pdb').read(), "pdb")
view.addSurface(
    py3Dmol.MS, 
    {
    "opacity": 1,
    "colorscheme": {
        'prop': 'b',
        'gradient' : 'linear',
        'colors': ['green', 'yellow', 'red'],
        'min': 10,
        'max': 200
        }
    }
)
view.zoomTo()
view.show()

I don't know why r3dmol can not use custom linear colors. This is a very useful application.

Any help of you is greatly appreciated!

william-swl avatar Jul 23 '25 14:07 william-swl