{"id":5739,"date":"2020-06-02T00:56:21","date_gmt":"2020-06-01T23:56:21","guid":{"rendered":"https:\/\/www.blopig.com\/blog\/?p=5739"},"modified":"2020-06-02T00:56:24","modified_gmt":"2020-06-01T23:56:24","slug":"visualising-macromolecules-and-grids-in-jupyter-notebooks-with-nglview","status":"publish","type":"post","link":"https:\/\/www.blopig.com\/blog\/2020\/06\/visualising-macromolecules-and-grids-in-jupyter-notebooks-with-nglview\/","title":{"rendered":"Visualising macromolecules and grids in Jupyter Notebooks with nglview"},"content":{"rendered":"\n<p>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.<\/p>\n\n\n\n<p>I have recently started using <a href=\"https:\/\/github.com\/arose\/nglview\">NGLview<\/a>, an IPython\/Jupyter widget, to do this. It is based on the <a href=\"https:\/\/github.com\/arose\/ngl\">NGL viewer<\/a>, an embeddable webapp for macromolecular visualisation. The nglvew module documentation can be found <a href=\"http:\/\/nglviewer.org\/nglview\/latest\/api.html\">here<\/a>, and in addition to handling the usual formats for molecular structure (.pdb, .mol2, .sdf, .pqr, <em>etc<\/em>.) and map density(.ccp4 and more), it supports visualising trajectories and even <a href=\"https:\/\/github.com\/arose\/nglview#movie-making\">making movies<\/a>.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>I have been using nglview to look at the results from the <a href=\"https:\/\/github.com\/prcurran\/hotspots\">fragment hotspot maps<\/a> 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.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from pathlib import Path\nimport nglview\nfrom ipywidgets import interactive, VBox<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def load_data(base_path):\n    \"\"\"\n    Loads the protein and hotspot maps\n    :param base_path: path to directory holding the results \n                      of the hotspot calculation\n    \"\"\"\n    probes = ['donor', 'acceptor', 'apolar']\n\n    view = nglview.NGLWidget()\n    view.add_component(str(Path(base_path, \"protein.pdb\")))\n    for p in probes:\n        view.add_component(str(Path(base_path, f\"{p}.ccp4\")))\n\n    return view\n\nclass InteractiveHotspot():\n    def __init__(self, hotspot_path):\n        self.view = load_data(hotspot_path)\n\n    def get_component_index(self, component_name):\n        \"\"\"\n        Given the name of the loaded file (or a partial string),\n        returns the component index if loaded\n        \"\"\"\n        all_components = self.view._ngl_component_names\n        component_idx = all_components.index([i for i in all_components \n                                              if component_name in i][0])\n\n        return component_idx\n\n    def threshold_isosurface(self, probe_name, threshold):\n        \"\"\"\n        Controls the representation of the map for specific probe\n        :param probe_name: string, one of 'donor', 'acceptor', 'apolar'\n        :param threshold: threshold value for displaying the hotspot map\n        \"\"\"\n        colour_dict = {'donor': 'blue',\n                       'acceptor': 'red',\n                       'apolar': '#FFF176'}\n        comp_idx = self.get_component_index(probe_name)\n        repr_params = [{'type': 'surface',\n                        'params': {'opacity': 0.4,\n                                   'isolevelType': 'value',\n                                   'isolevel': threshold,\n                                   'color': colour_dict[probe_name]}}]\n\n        self.view.set_representations(repr_params, component=comp_idx)<\/pre>\n\n\n\n<p>In the code snippet below, the hotspot results are housed in the folder .\/my_hotspots, which contains a .pdb file for the protein (&#8216;protein.pdb&#8217;) and three .ccp4 grids holding the hotspot maps for the 3 probe types (&#8216;acceptor.ccp4&#8217;, &#8216;donor.ccp4&#8217;, &#8216;apolar.ccp4)<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">hotspot_result_path = Path(\"my_hotspots\")\nhotspot = InteractiveHotspot(hotspot_result_path)<\/pre>\n\n\n\n<p>The next cell sets up the viewer and controls widgets.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">controls = interactive(hotspot.threshold_isosurface, \n                       probe_name=['donor', 'acceptor', 'apolar'], \n                       threshold=range(30))\nVBox([hotspot.view, controls])<\/pre>\n\n\n\n<p>We can now look for &#8216;warm spots&#8217; within the binding site&#8230;<br><\/p>\n\n\n\n<p><img decoding=\"async\" loading=\"lazy\" width=\"383\" height=\"282\" src=\"https:\/\/lh5.googleusercontent.com\/AVw5bd96A_2N3xu4SdPcGPqqqCOHUx7PITLGtXcF22SbZSGymqKDtvEO652RqKDXWmQ7fRn9AiVHW7wxGWhTgBaWYWGaAyGRH0NUllrhreROFXG4LTYnPh6WztxNPkEalGoGrQlf\"><\/p>\n\n\n\n<p>The hottest spots show interactions that are likely to drive fragment binding. <\/p>\n\n\n\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/lh6.googleusercontent.com\/UfnNybIqRzMQMU2w5Wee-hGb0AHCUqRdweP5VM2AWLt-YjequPQK7_0xSZ1w1LxsTU1gcUQdSN1yeOamaSqBO118RsSbMiaMuDXu7heEiv0jDYTZckunpLD6xNhhEG0dmSOS7WKb\" width=\"370\" height=\"311\"><\/p>\n\n\n\n<p>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. <\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">hotspot.view.add_ball_and_stick('1944')<\/pre>\n\n\n\n<p><img decoding=\"async\" loading=\"lazy\" width=\"433\" height=\"263\" src=\"https:\/\/lh3.googleusercontent.com\/LqZo4AFYZDWZyHIqAsbmN65nKBp9ZgyJXDkhxvnDI7hGHMkxP1xGxF5zBpZfP8o9ml-7SlJkESZ3rS4w19EEOlnaE6X8IgKoK8q2UH-ATTvxCnEFquA21aQ1xiZp18am0uqpaUF3\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">References:<\/h2>\n\n\n\n<p><strong>NGLview:<\/strong><br>Hai Nguyen, David A Case, Alexander S Rose; NGLview &#8211; Interactive molecular graphics for Jupyter notebooks, Bioinformatics, , btx789,\u00a0<a href=\"https:\/\/doi.org\/10.1093\/bioinformatics\/btx789\">https:\/\/doi.org\/10.1093\/bioinformatics\/btx789<\/a><\/p>\n\n\n\n<p><strong>NGL viewer:<\/strong><br>AS Rose, AR Bradley, Y Valasatava, JM Duarte, A Prli\u0107 and PW Rose.\u00a0<em>NGL viewer: web-based molecular graphics for large complexes.<\/em>\u00a0Bioinformatics: bty419, 2018.\u00a0<a href=\"http:\/\/dx.doi.org\/10.1093\/bioinformatics\/bty419\">doi:10.1093\/bioinformatics\/bty419<\/a><\/p>\n\n\n\n<p>AS Rose and PW Hildebrand.\u00a0<em>NGL Viewer: a web application for molecular visualization.<\/em>\u00a0Nucl Acids Res (1 July 2015) 43 (W1): W576-W579 first published online April 29, 2015.\u00a0<a href=\"https:\/\/doi.org\/10.1093\/nar\/gkv402\">doi:10.1093\/nar\/gkv402<\/a><\/p>\n\n\n\n<p><strong>Fragment Hotspot Maps:<\/strong><br>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 <em>Hotspots API: A Python Package for the Detection of Small Molecule Binding Hotspots and Application to Structure-Based Drug Design<\/em>. Journal of Chemical Information and Modeling\u00a0<strong>2020<\/strong><em>60<\/em>\u00a0(4), 1911-1916<br>DOI: 10.1021\/acs.jcim.9b00996<\/p>\n\n\n\n<p>Chris J. Radoux, Tjelvar S. G. Olsson, Will R. Pitt, Colin R. Groom, and Tom L. Blundell <em>Identifying Interactions that Determine Fragment Binding at Protein Hotspots.<\/em> Journal of Medicinal Chemistry\u00a0<strong>2016<\/strong><em>59<\/em>\u00a0(9), 4314-4325<br>DOI: 10.1021\/acs.jmedchem.5b01980<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":59,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","wikipediapreview_detectlinks":true,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"ngg_post_thumbnail":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[29,274,228,227],"tags":[320,154,321],"ppma_author":[538],"class_list":["post-5739","post","type-post","status-publish","format-standard","hentry","category-code","category-molecular-recognition","category-protein-structure","category-python-code","tag-hotspots","tag-jupyter","tag-nglview"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"authors":[{"term_id":538,"user_id":59,"is_guest":0,"slug":"mihaela","display_name":"Mihaela Smilova","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/a422eaec6fce7de94e43875a04a32290ee9cbafab1a172db27b9e7cfa9aa5a97?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts\/5739","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/users\/59"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/comments?post=5739"}],"version-history":[{"count":6,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts\/5739\/revisions"}],"predecessor-version":[{"id":5751,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts\/5739\/revisions\/5751"}],"wp:attachment":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/media?parent=5739"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/categories?post=5739"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/tags?post=5739"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=5739"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}