{"id":115,"date":"2012-11-01T11:55:02","date_gmt":"2012-11-01T11:55:02","guid":{"rendered":"http:\/\/nextmovesoftware.com\/blog\/?p=115"},"modified":"2015-06-22T17:08:46","modified_gmt":"2015-06-22T16:08:46","slug":"visualising-a-hierarchy-of-substructures-part-ii","status":"publish","type":"post","link":"https:\/\/nextmovesoftware.com\/blog\/2012\/11\/01\/visualising-a-hierarchy-of-substructures-part-ii\/","title":{"rendered":"Visualising a hierarchy of substructures Part II"},"content":{"rendered":"<p>In an <a href=\"http:\/\/nextmovesoftware.com\/blog\/2012\/10\/09\/visualising-a-hierarchy-of-substructures\/\">earlier post<\/a>, I described a simple procedure to generate a hierarchy of substructures, and depicted the hierarchy with GraphViz. Pat Walters at Vertex realised that it is possible to add images as node labels in GraphViz and updated the script so that the image includes the actual chemical depictions (see below). He has also adapted the script to use OpenEye&#8217;s OEChem.<\/p>\n<p><b>Update (8\/11\/2012)<\/b>: Wolf-D. Ihlenfeldt has <a href=\"http:\/\/85.214.192.197\/Projects\/HierarchicalSubstructures\/\">implemented this with the Cactvs Toolkit<\/a> and in addition has shown how to integrate the graph display with Knime.<\/p>\n<style type=\"text\/css\">\n<!--\npre { font-family: monospace; color: #000000; background-color: #ffffff; }\n.Special { color: #6a5acd; }\n.Constant { color: #ff00ff; }\n.Identifier { color: #008080; }\n.Statement { color: #804040; font-weight: bold; }\n.PreProc { color: #a020f0; }\n.Comment { color: #0000ff; }\n-->\n<\/style>\n<p style=\"text-align: center;\"><a href=\"http:\/\/nextmovesoftware.com\/blog\/wp-content\/uploads\/2012\/11\/heirarchy.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-121\" title=\"hierarchy\" src=\"\/\/nextmovesoftware.com\/blog\/wp-content\/uploads\/2012\/11\/heirarchy.jpg\" alt=\"\" width=\"874\" height=\"837\" srcset=\"https:\/\/nextmovesoftware.com\/blog\/wp-content\/uploads\/2012\/11\/heirarchy.jpg 874w, https:\/\/nextmovesoftware.com\/blog\/wp-content\/uploads\/2012\/11\/heirarchy-300x287.jpg 300w\" sizes=\"(max-width: 874px) 100vw, 874px\" \/><\/a><\/p>\n<pre><span class=\"Comment\">#!\/usr\/bin\/env python<\/span>\r\n\r\n<span class=\"PreProc\">import<\/span> copy\r\n<span class=\"PreProc\">import<\/span> pickle\r\n<span class=\"PreProc\">import<\/span> os\r\n\r\n<span class=\"PreProc\">from<\/span> openeye.oechem <span class=\"PreProc\">import<\/span> *\r\n<span class=\"PreProc\">from<\/span> openeye.oedepict <span class=\"PreProc\">import<\/span> *\r\n\r\n<span class=\"Statement\">def<\/span> <span class=\"Identifier\">mol2image<\/span>(mol,imageFileName,width=<span class=\"Constant\">200<\/span>,height=<span class=\"Constant\">200<\/span>):\r\n    clearcoords = <span class=\"Identifier\">True<\/span>\r\n    suppressH   = <span class=\"Identifier\">False<\/span>\r\n    opts = OE2DMolDisplayOptions(width, height, OEScale_AutoScale)\r\n    itf = OEInterface()\r\n    OESetup2DMolDisplayOptions(opts, itf)\r\n    OEPrepareDepiction(mol, clearcoords, suppressH)\r\n    disp = OE2DMolDisplay(mol, opts)\r\n    ofs = oeofstream(imageFileName)\r\n    name,ext = os.path.splitext(imageFileName)\r\n    OERenderMolecule(ofs,ext[<span class=\"Constant\">1<\/span>:],disp)\r\n\r\n<span class=\"Statement\">def<\/span> <span class=\"Identifier\">create_tree<\/span>(structures):\r\n    tree = {<span class=\"Constant\">\"Root\"<\/span>:{}}\r\n    stack = [(tree[<span class=\"Constant\">\"Root\"<\/span>], structures.keys())]\r\n\r\n    <span class=\"Statement\">while<\/span> <span class=\"Identifier\">len<\/span>(stack) &gt; <span class=\"Constant\">0<\/span>:\r\n        leaf, subset = stack.pop()\r\n\r\n        max_matches = (<span class=\"Constant\">\"\"<\/span>, [])\r\n        <span class=\"Statement\">for<\/span> name <span class=\"Statement\">in<\/span> subset:\r\n            smiles = structures[name]\r\n            smarts = OESubSearch(smiles)\r\n            matches = []\r\n            <span class=\"Statement\">for<\/span> nameb <span class=\"Statement\">in<\/span> subset:\r\n                <span class=\"Statement\">if<\/span> nameb != name:\r\n                    molb = OEGraphMol()\r\n                    OEParseSmiles(molb,structures[nameb])\r\n                    <span class=\"Statement\">if<\/span> smarts.SingleMatch(molb):\r\n                        matches.append(nameb)\r\n            <span class=\"Statement\">if<\/span> <span class=\"Identifier\">len<\/span>(matches) &gt;= <span class=\"Identifier\">len<\/span>(max_matches[<span class=\"Constant\">1<\/span>]):\r\n                max_matches = (name, matches)\r\n        <span class=\"Statement\">if<\/span> <span class=\"Identifier\">False<\/span>: <span class=\"Comment\"># Debug statement<\/span>\r\n            <span class=\"Identifier\">print<\/span> max_matches\r\n\r\n        <span class=\"Statement\">for<\/span> name <span class=\"Statement\">in<\/span> [max_matches[<span class=\"Constant\">0<\/span>]] + max_matches[<span class=\"Constant\">1<\/span>]:\r\n            subset.remove(name)\r\n        leaf[max_matches[<span class=\"Constant\">0<\/span>]] = {}\r\n        <span class=\"Statement\">if<\/span> <span class=\"Identifier\">len<\/span>(subset) &gt; <span class=\"Constant\">0<\/span>:\r\n            stack.append( (leaf, subset) )\r\n        <span class=\"Statement\">if<\/span> <span class=\"Identifier\">len<\/span>(max_matches[<span class=\"Constant\">1<\/span>]) &gt; <span class=\"Constant\">0<\/span>:\r\n            stack.append( (leaf[max_matches[<span class=\"Constant\">0<\/span>]], copy.deepcopy(max_matches[<span class=\"Constant\">1<\/span>])))\r\n\r\n    <span class=\"Statement\">with<\/span> <span class=\"Identifier\">open<\/span>(<span class=\"Constant\">\"tmp.pickle\"<\/span>, <span class=\"Constant\">\"w\"<\/span>) <span class=\"Statement\">as<\/span> f:\r\n        pickle.dump(tree, f)\r\n\r\n<span class=\"Statement\">def<\/span> <span class=\"Identifier\">fix<\/span>(name):\r\n    <span class=\"Statement\">return<\/span> name.replace(<span class=\"Constant\">\"-\"<\/span>, <span class=\"Constant\">\"_\"<\/span>).replace(<span class=\"Constant\">\"1\"<\/span>, <span class=\"Constant\">\"one\"<\/span>).replace(<span class=\"Constant\">\"2\"<\/span>, <span class=\"Constant\">\"two\"<\/span>).replace(<span class=\"Constant\">\"3\"<\/span>, <span class=\"Constant\">\"three\"<\/span>).replace(<span class=\"Constant\">\"5\"<\/span>, <span class=\"Constant\">\"five\"<\/span>).replace(<span class=\"Constant\">\",\"<\/span>, <span class=\"Constant\">\"_\"<\/span>)\r\n\r\n<span class=\"Statement\">def<\/span> <span class=\"Identifier\">visit<\/span>(name, leafdict):\r\n    <span class=\"Statement\">for<\/span> x, y <span class=\"Statement\">in<\/span> leafdict.iteritems():\r\n        <span class=\"Statement\">if<\/span> name != <span class=\"Constant\">\"Root\"<\/span>:\r\n            <span class=\"Identifier\">print<\/span> <span class=\"Constant\">' %s -&gt; %s;'<\/span> % (name,x)\r\n        <span class=\"Identifier\">print<\/span> <span class=\"Constant\">' %s [label=&lt;&lt;TABLE&gt;&lt;TR&gt;&lt;TD&gt;&lt;IMG SRC=\"%s\/%s.png\"\/&gt;&lt;\/TD&gt;&lt;\/TR&gt;&lt;\/TABLE&gt;&gt;];'<\/span> % (x,os.getcwd(),x)\r\n        visit(x, y)\r\n\r\n<span class=\"Statement\">if<\/span> __name__ == <span class=\"Constant\">\"__main__\"<\/span>:\r\n    structureDict = <span class=\"Identifier\">dict<\/span>([(<span class=\"Constant\">'001'<\/span>, <span class=\"Constant\">'C(O)[C@@H](O1)[C@@H](O)[C@H](O)[C@@H](O)[CH]1(O)'<\/span>),\r\n                       (<span class=\"Constant\">'002'<\/span>, <span class=\"Constant\">'C(O)[C@@H](O1)[C@@H](O)[C@H](O)[C@H](O)[CH]1(O)'<\/span>),\r\n                       (<span class=\"Constant\">'003'<\/span>, <span class=\"Constant\">'C(O)[C@@H](O1)[C@@H](O)[C@H](O)[C@@H](O)[C@H]1(O)'<\/span>),\r\n                       (<span class=\"Constant\">'004'<\/span>, <span class=\"Constant\">'C(O)[C@@H](O1)[C@@H](O)[C@H](O)[C@@H](O)[C@@H]1(O)'<\/span>),\r\n                       (<span class=\"Constant\">'005'<\/span>, <span class=\"Constant\">'C(O)[CH](O1)[CH](O)[CH](O)[CH](O)[CH]1(O)'<\/span>),\r\n                       (<span class=\"Constant\">'006'<\/span>, <span class=\"Constant\">'c1ccccc1'<\/span>),\r\n                       (<span class=\"Constant\">'007'<\/span>, <span class=\"Constant\">'c1ccccc1Br'<\/span>),\r\n                       (<span class=\"Constant\">'008'<\/span>, <span class=\"Constant\">'c1ccc(Br)cc1Br'<\/span>),\r\n                       (<span class=\"Constant\">'009'<\/span>, <span class=\"Constant\">'c1cccc(Br)c1Br'<\/span>),\r\n                       (<span class=\"Constant\">'010'<\/span>, <span class=\"Constant\">'c1c(Br)cc(Br)cc1Br'<\/span>)])\r\n\r\n    <span class=\"Statement\">for<\/span> k <span class=\"Statement\">in<\/span> <span class=\"Identifier\">sorted<\/span>(structureDict.keys()):\r\n        imageFileName = <span class=\"Constant\">\"%s.png\"<\/span> % (k)\r\n        smi = structureDict[k]\r\n        mol = OEGraphMol()\r\n        OEParseSmiles(mol,smi)\r\n        mol2image(mol,imageFileName)\r\n\r\n    create_tree(structureDict)\r\n    <span class=\"Statement\">with<\/span> <span class=\"Identifier\">open<\/span>(<span class=\"Constant\">\"tmp.pickle\"<\/span>, <span class=\"Constant\">\"r\"<\/span>) <span class=\"Statement\">as<\/span> f:\r\n        tree = pickle.load(f)\r\n    <span class=\"Identifier\">print<\/span> <span class=\"Constant\">\"digraph graphname {\"<\/span>\r\n    <span class=\"Identifier\">print<\/span> <span class=\"Constant\">\"node [shape=plaintext];\"<\/span>\r\n    visit(<span class=\"Constant\">\"Root\"<\/span>, tree[<span class=\"Constant\">\"Root\"<\/span>])\r\n    <span class=\"Identifier\">print<\/span> <span class=\"Constant\">\"}\"<\/span>\r\n\r\n<span class=\"Constant\">\"\"\"<\/span>\r\n<span class=\"Constant\">Redirect the output to a file and then convert to a graph as follows:<\/span>\r\n<span class=\"Constant\">\"C:\\Program Files (x86)\\Graphviz 2.28<\/span><span class=\"Special\">\\b<\/span><span class=\"Constant\">in\\dot.exe\" -Tpng -ooutput.png dot_input.txt<\/span>\r\n<span class=\"Constant\">\"\"\"<\/span><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>In an earlier post, I described a simple procedure to generate a hierarchy of substructures, and depicted the hierarchy with GraphViz. Pat Walters at Vertex realised that it is possible to add images as node labels in GraphViz and updated the script so that the image includes the actual chemical depictions (see below). He has &hellip; <a href=\"https:\/\/nextmovesoftware.com\/blog\/2012\/11\/01\/visualising-a-hierarchy-of-substructures-part-ii\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Visualising a hierarchy of substructures Part II<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/nextmovesoftware.com\/blog\/wp-json\/wp\/v2\/posts\/115"}],"collection":[{"href":"https:\/\/nextmovesoftware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nextmovesoftware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nextmovesoftware.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nextmovesoftware.com\/blog\/wp-json\/wp\/v2\/comments?post=115"}],"version-history":[{"count":11,"href":"https:\/\/nextmovesoftware.com\/blog\/wp-json\/wp\/v2\/posts\/115\/revisions"}],"predecessor-version":[{"id":1476,"href":"https:\/\/nextmovesoftware.com\/blog\/wp-json\/wp\/v2\/posts\/115\/revisions\/1476"}],"wp:attachment":[{"href":"https:\/\/nextmovesoftware.com\/blog\/wp-json\/wp\/v2\/media?parent=115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nextmovesoftware.com\/blog\/wp-json\/wp\/v2\/categories?post=115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nextmovesoftware.com\/blog\/wp-json\/wp\/v2\/tags?post=115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}