Customizing Molecular Visualizations in Jupyter
Customizing Molecular Visualizations in Jupyter
A constant when working with molecules and quantum chemistry is the need to visualize a structure or a transformation. Traditionally, I’d write an .xyz
or .mol
file and open the structure in a different visualization program, but when I want to work interactively this becomes a pain
To circumvent this, I decided a while back it was time to have a visualizer I could fully customize in Jupyter. My first plugin worked with the NGLViewer plugin to JupyterLab. This worked for a time, but it depends on the Jupyter widgets framework which is as of yet still underbaked and prone to all sorts of nasty dependency issues and clashes. This wasn’t sustainable and I wanted a system that could be constructed as static HTML. This way I could visualize in my notebook, but I could also just write the HTML to a file and load it up in a browser or send it off to my collaborators.
To support that, I decided (a year ago) on using two different systems to keep my options open. First I would write a JSMol plugin that uses embedded JSMol in a cell to run the visualization. In practice, this looks like
from Psience.Molecools import Molecule
mol = Molecule.from_string('cyclohexanol')
mol
Behind the scenes, this just uses an embeddable version of JSMol I tweaked from the source and a rich HTML construction library I built to support JHTML. This molecules get exported directly into the HTML and so can easily be shared as well as visualized.
Animation Support
Much of my work involves mapping out chemical dynamics, so being able to visualizem molecules as coordinates distort is important. I’ve had the tools to get the appropriate derivatives for transformations for years, but now it’s possible to do visualize this more generally
int_mol = mol.modify(internals='auto') # pick reasonable internal coordinates
int_mol.animate_coordinate(-1)
Better Script Support
The JSMol interface can also be a little bit finnicky, so I added a (very ugly) system for running scripts and doing screen recordings
int_mol.animate_coordinate(0, include_script_interface=True)
X3D
JSMol is great, but sometimes you want a richer rendering environment and more direct control. For that, I added support for rendering with X3D
mol.plot(backend='x3d', highlight_atoms=[0, 1, 2])
This gives you complete control over the rendering process, but of course means you need to render everything yourself. Still, it allows you to, render interesting scenes like plotting the intersections of the van der Waals spheres of your atoms
mol2 = Molecule.from_string('CO')
fig = mol2.plot(backend='x3d')
mol2.get_surface().plot(figure=fig,
sphere_style={'transparency':.8},
plot_intersections=True
)