Visualising macromolecules and grids in Jupyter Notebooks with nglview

If you do most of your work in Jupyter notebooks, it can be convenient to have a quick visualisation tool to view the results of your latest computation from within the notebook, without having to flick between the notebook and your favourite molecule viewer.

I have recently started using NGLview, an IPython/Jupyter widget, to do this. It is based on the NGL viewer, an embeddable webapp for macromolecular visualisation. The nglvew module documentation can be found here, and in addition to handling the usual formats for molecular structure (.pdb, .mol2, .sdf, .pqr, etc.) and map density(.ccp4 and more), it supports visualising trajectories and even making movies.

I have been using nglview to look at the results from the fragment hotspot maps algorithm. This involves visualising a protein/binding site of interest, as well as three grid maps, which point to areas of favourable interaction for donor, acceptor and apolar fragment-like probes. A key point of this visualisation is being able to control the threshold at which the maps are displayed: higher thresholds indicate stronger interactions.

from pathlib import Path
import nglview
from ipywidgets import interactive, VBox
def load_data(base_path):
    """
    Loads the protein and hotspot maps
    :param base_path: path to directory holding the results 
                      of the hotspot calculation
    """
    probes = ['donor', 'acceptor', 'apolar']

    view = nglview.NGLWidget()
    view.add_component(str(Path(base_path, "protein.pdb")))
    for p in probes:
        view.add_component(str(Path(base_path, f"{p}.ccp4")))

    return view

class InteractiveHotspot():
    def __init__(self, hotspot_path):
        self.view = load_data(hotspot_path)

    def get_component_index(self, component_name):
        """
        Given the name of the loaded file (or a partial string),
        returns the component index if loaded
        """
        all_components = self.view._ngl_component_names
        component_idx = all_components.index([i for i in all_components 
                                              if component_name in i][0])

        return component_idx

    def threshold_isosurface(self, probe_name, threshold):
        """
        Controls the representation of the map for specific probe
        :param probe_name: string, one of 'donor', 'acceptor', 'apolar'
        :param threshold: threshold value for displaying the hotspot map
        """
        colour_dict = {'donor': 'blue',
                       'acceptor': 'red',
                       'apolar': '#FFF176'}
        comp_idx = self.get_component_index(probe_name)
        repr_params = [{'type': 'surface',
                        'params': {'opacity': 0.4,
                                   'isolevelType': 'value',
                                   'isolevel': threshold,
                                   'color': colour_dict[probe_name]}}]

        self.view.set_representations(repr_params, component=comp_idx)

In the code snippet below, the hotspot results are housed in the folder ./my_hotspots, which contains a .pdb file for the protein (‘protein.pdb’) and three .ccp4 grids holding the hotspot maps for the 3 probe types (‘acceptor.ccp4’, ‘donor.ccp4’, ‘apolar.ccp4)

hotspot_result_path = Path("my_hotspots")
hotspot = InteractiveHotspot(hotspot_result_path)

The next cell sets up the viewer and controls widgets.

controls = interactive(hotspot.threshold_isosurface, 
                       probe_name=['donor', 'acceptor', 'apolar'], 
                       threshold=range(30))
VBox([hotspot.view, controls])

We can now look for ‘warm spots’ within the binding site…

The hottest spots show interactions that are likely to drive fragment binding.

The example presented here is the bromodomain BAZ2B (PDB 4RVR, ligand removed). Bromodomains have an almost universally conserved asparagine residue that acts as key pharmacophoric feature. In this structure, this is residue Asn 1944.

hotspot.view.add_ball_and_stick('1944')

References:

NGLview:
Hai Nguyen, David A Case, Alexander S Rose; NGLview – Interactive molecular graphics for Jupyter notebooks, Bioinformatics, , btx789, https://doi.org/10.1093/bioinformatics/btx789

NGL viewer:
AS Rose, AR Bradley, Y Valasatava, JM Duarte, A Prlić and PW Rose. NGL viewer: web-based molecular graphics for large complexes. Bioinformatics: bty419, 2018. doi:10.1093/bioinformatics/bty419

AS Rose and PW Hildebrand. NGL Viewer: a web application for molecular visualization. Nucl Acids Res (1 July 2015) 43 (W1): W576-W579 first published online April 29, 2015. doi:10.1093/nar/gkv402

Fragment Hotspot Maps:
Peter R. Curran, Chris J. Radoux, Mihaela D. Smilova, Richard A. Sykes, Alicia P. Higueruelo, Anthony R. Bradley, Brian D. Marsden, David R. Spring, Tom L. Blundell, Andrew R. Leach, William R. Pitt, and Jason C. Cole Hotspots API: A Python Package for the Detection of Small Molecule Binding Hotspots and Application to Structure-Based Drug Design. Journal of Chemical Information and Modeling 202060 (4), 1911-1916
DOI: 10.1021/acs.jcim.9b00996

Chris J. Radoux, Tjelvar S. G. Olsson, Will R. Pitt, Colin R. Groom, and Tom L. Blundell Identifying Interactions that Determine Fragment Binding at Protein Hotspots. Journal of Medicinal Chemistry 201659 (9), 4314-4325
DOI: 10.1021/acs.jmedchem.5b01980

Author