This notebook will demonstrate automated coloring of a complex with a lot of chains by various combinations from a set palette using binderized PyMol. Random shuffles of your color palette will be cycled to color all the chains and metals.The idea being you can find a per chains/metals color list that matches your needs or at least is close. The color lists for the corresponding are generated in a text file as the images are produced. The 'one' closest to what you want you can than use as a basis for further modification.
This builds on all the previous demos plus rather advanced usage of Python and Jupyter notebook magics, and so you should be familiar with the previous demos at least and then play around.
The code is set up to be general. You can run it with the defaults now and it should work. With a little change to the specified places, you can make it address your favorite structure and colors.
As it relies on colors a lot, you should see Demo of Dealing with PyMol colors.
Return to the first page for a list of the demonstrations available.
If you haven't used one of these notebooks before, they're basically web pages in which you can write, edit, and run live code. They're meant to encourage experimentation, so don't feel nervous. Just try running a few cells and see what happens!.
Some tips:
First things first. You'll need a structure. (For testing, leave the one defined below. Later, change the alpha-numeric id code to be your favorite from here.) Running the next cell will specify that.
PDB_id_code = '6q9b'
Now you'll need to specify a palette of colors to iterate over applying them to various chains in various combinations.
You don't need the number of colors to match the number of chains the chains. The idea here is that if the list of colors is less than the number of metals and chains, the list will be cycled around and around again to account for coloring all the chains and metals. If you did want to specify an amount of colors to match the amount of chains and metals, you could do that as well. Or if you supply more colors than needed, then all images produced will only use a subset of the supplied colors.
Running the next cell will specify the colors.
my_colors_as_strings = ["slate","violet","violetpurple","lightblue","my_color","Gray30","white"]
Most of the colors used in this demonstration are inherited from Pymol itself, see Demo of Dealing with PyMol colors. However, for one color we'll use the methods outlined in Demo of Dealing with PyMol colors to specify a custom color. The critical point is that for each custom color listed here, you need to specify it in the large code black below. The specific line necessary here is the following:
cmd.set_color ("my_color", [*hex_to_rgb("#7D80B0")])
You may wish to expand the amount of custom colors to match your needs later.
You'll need to specify an orientation for the molecule unless you want the default way it was specified. See Demo of Setting an Orientation if how to do that is unclear to you.
orientation_string = "-0.984500647, 0.043761615, 0.169820756, 0.167749062, 0.517372191, 0.839159250, -0.051139157, 0.854639351, -0.516694129, 0.000000000, 0.000000000, -623.999755859, 376.089996338, 316.122253418, 360.227386475, 491.966186523, 756.033325195, -20.000000000"
The following will specify how many shuffles of the combinations you want to run through for sampling.
shuffles_to_do = 20
With the structure,color list, orientation, and amount of shuffles set, the code below can be used to make samples of colors applied to various chains.
Like in other notebooks, a code block is sent to PyMol. The code block is stored as a doc string, which is a fancy way of saying text between '''
. Here the code block is rather large because of the complexity happening to examine the structure for the number of chains and metals and then applying color from a palette to that, and iterate over it shuffling the combinations applied. Before it is sent to PyMol, that code block is further edited to incorporate settings from above. (*Remember: if you apply additional custom colors, you'll need the follow the example from my_color
to add assignment of any listed colors to the block as well.)
text_2_save_templ = '''#!/usr/bin/python
import sys, os
# pymol environment
moddir='/opt/pymol-svn/modules'
sys.path.insert(0, moddir)
os.environ['PYMOL_PATH'] = os.path.join(moddir, 'pymol/pymol_path')
import pymol
cmd = pymol.cmd
# end of set-up
# get the structure & load it into PyMol
cmd.fetch('the_STRUCTURE_PLACEHOLDER')
cmd.zoom()
# set my preferred starting point for representation
cmd.set ("ray_opaque_background", 0)
cmd.set ("cartoon_fancy_helices", 1)
cmd.bg_color ("white")
cmd.set ("cartoon_side_chain_helper", "on")
cmd.hide ("everything", "all")
#set desired orientation
def set_my_view():
cmd.set_view("the_ORIENTATION_PLACEHOLDER")
set_my_view()
# Generate an image for a few color combinations ( NOT ALL)
number_shuffles_to_run = the_SHUFFLE_NUMBER_PLACEHOLDER
# define any custom colors
def hex_to_rgb(value):
#based on https://stackoverflow.com/a/214657/8508004
value = value.lstrip('#')
lv = len(value)
return tuple(int(value[i:i + lv // 3], 16) for i in range(0, lv, lv // 3))
cmd.set_color ("my_color", [*hex_to_rgb("#7D80B0")])
# specify the palette of colors to use
color_list = the_COLOR_LIST_PLACEHOLDER
# determine ids of loaded chains, see `iterating over residue secondary structure and color.md`
names_of_structures_loaded = cmd.get_names()
the_chains = cmd.get_chains(names_of_structures_loaded[0])
print ("There are {} chains.".format(len(the_chains)))
stored.elems = []
cmd.iterate ("metals", "stored.elems.append(elem)")
the_metals = list(set(stored.elems))
if the_metals:
print ("There are {} metal ions.".format(len(the_metals)))
the_chains_n_metals = the_chains + the_metals
the_chains_as_selections = ["chain {}".format(x) for x in the_chains]
the_metals_as_selections = ["resn {}".format(x) for x in the_metals]
items_to_color = the_chains_as_selections + the_metals_as_selections
#base display styling
cmd.show ("surface", "polymer.protein")
#show metals as speheres
for sm in the_metals_as_selections:
cmd.show ("spheres", sm)
cmd.set ("fog_start", 0.70) #move fog back farther so not hitting main part as much
import random
from itertools import cycle
f=open('color_lists.txt','w')
for x in range(number_shuffles_to_run):
random.seed(x)
random.shuffle(color_list)
pymol_colors = cycle(color_list)
applied = []
for i in items_to_color:
clr_4_now = next(pymol_colors)
cmd.color(clr_4_now,i)
applied.append((i,clr_4_now))
cmd.png("img_{}.png".format(x), width=500, height=500, dpi=72, ray=1, quiet=0)
f.write("seed {}: {}\\n".format(x,applied)) #note double
# backslash to escape necessary or get `SyntaxError: EOL while scanning string
# literal` when hit that line
f.flush();os.fsync(f.fileno()) #added so even if task gets killed, I get
# color list for what processed thus far; based on
#https://stackoverflow.com/a/19756479/8508004
f.close()
'''
text_2_save = text_2_save_templ.replace("the_STRUCTURE_PLACEHOLDER",PDB_id_code)
text_2_save = text_2_save.replace("the_COLOR_LIST_PLACEHOLDER",str(my_colors_as_strings))
text_2_save = text_2_save.replace("the_ORIENTATION_PLACEHOLDER",orientation_string)
text_2_save = text_2_save.replace("the_SHUFFLE_NUMBER_PLACEHOLDER",str(shuffles_to_do))
%store text_2_save >script.py
!pymol -cq script.py
Writing 'text_2_save' (str) to file 'script.py'. ExecutiveLoad-Detail: Detected mmCIF There are 29 chains. Ray: render time: 102.25 sec. = 35.2 frames/hour (102.25 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_0.png". Ray: render time: 89.88 sec. = 40.1 frames/hour (192.13 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_1.png". Ray: render time: 97.66 sec. = 36.9 frames/hour (289.78 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_2.png". Ray: render time: 94.57 sec. = 38.1 frames/hour (384.36 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_3.png". Ray: render time: 91.03 sec. = 39.5 frames/hour (475.39 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_4.png". Ray: render time: 92.28 sec. = 39.0 frames/hour (567.67 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_5.png". Ray: render time: 92.81 sec. = 38.8 frames/hour (660.48 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_6.png". Ray: render time: 90.51 sec. = 39.8 frames/hour (750.99 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_7.png". Ray: render time: 89.91 sec. = 40.0 frames/hour (840.89 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_8.png". Ray: render time: 89.34 sec. = 40.3 frames/hour (930.23 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_9.png". Ray: render time: 93.71 sec. = 38.4 frames/hour (1023.94 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_10.png". Ray: render time: 92.49 sec. = 38.9 frames/hour (1116.43 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_11.png". Ray: render time: 91.85 sec. = 39.2 frames/hour (1208.28 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_12.png". Ray: render time: 99.13 sec. = 36.3 frames/hour (1307.41 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_13.png". Ray: render time: 90.68 sec. = 39.7 frames/hour (1398.08 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_14.png". Ray: render time: 87.82 sec. = 41.0 frames/hour (1485.90 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_15.png". Ray: render time: 93.51 sec. = 38.5 frames/hour (1579.41 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_16.png". Ray: render time: 98.10 sec. = 36.7 frames/hour (1677.51 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_17.png". Ray: render time: 88.95 sec. = 40.5 frames/hour (1766.46 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_18.png". Ray: render time: 93.10 sec. = 38.7 frames/hour (1859.56 sec. accum.). ScenePNG: wrote 500x500 pixel image to file "img_19.png".
!tar czf color_shuffles.tar.gz *.png color_lists.txt
Download the color_shuffles.tar.gz
file made to your local computer. That inlcudes the images as well as a file listing the corresponding color list for each image.
To preview the images produced here, run the next cell.
from IPython.display import Image
from IPython.display import display
img = {}
for x in range(shuffles_to_do):
img[x] = Image(filename="img_{}.png".format(x))
display(img[x])
print("ABOVE: img_{}.png".format(x))
ABOVE: img_0.png
ABOVE: img_1.png
ABOVE: img_2.png
ABOVE: img_3.png
ABOVE: img_4.png
ABOVE: img_5.png
ABOVE: img_6.png
ABOVE: img_7.png
ABOVE: img_8.png
ABOVE: img_9.png
ABOVE: img_10.png
ABOVE: img_11.png
ABOVE: img_12.png
ABOVE: img_13.png
ABOVE: img_14.png
ABOVE: img_15.png
ABOVE: img_16.png
ABOVE: img_17.png
ABOVE: img_18.png
ABOVE: img_19.png
Or we can cycle through randomly displaying a small subset for a short time to see if any look particularly striking by running the next cell.
You may need to zoom out in your browser's view setting to see all three displayed.
This cell will run on and on, and so you'll need to end it running the display cycle by hitting the 'stop' button above to interrupte the kernel.
If you want to spend less time displaying each set, interrupt the display cycle the lower the number in time.sleep(5)
and run the cell again. Increase that value to display each set for a longer duration during the cycle.
#display(HTML('<b>Fold change in ratios when the mito data is considered relative the total RNA RNA-seq data:</b>'))
import IPython.display as ipd
import time
import os
import sys
import random
def display_subset():
img = {}
for x in random.sample(range(shuffles_to_do), 3):
img[x] = ipd.Image(filename="img_{}.png".format(x))
ipd.display(img[x])
ipd.display(ipd.HTML('ABOVE: <font size=5><b>img_{}.png</b></font>'.format(x)))
time.sleep(5)
ipd.clear_output(wait=True)
while True:
display_subset()
See the next notebook for applying a chosen color combination.
Return to the first page for a list of the demonstrations available.