1 import IPython
2
3 if IPython.release.version < '0.11':
4 raise ImportError('this module requires at least v0.11 of IPython')
5 elif IPython.release.version < '2.0':
6 install_nbextension=None
7 _canUse3D=False
8 else:
9 try:
10 try:
11 from notebook.nbextensions import install_nbextension
12 _canUse3D=True
13 except ImportError:
14
15 from IPython.html.nbextensions import install_nbextension
16 _canUse3D=True
17 except ImportError:
18
19
20 _canUse3D=False
21 sys.stderr.write("*"*44)
22 sys.stderr.write("\nCannot import nbextensions\n")
23 sys.stderr.write("Current IPython/Jupyter version is %s\n"%
24 IPython.release.version)
25 sys.stderr.write("Disabling 3D rendering\n")
26 sys.stderr.write("*"*44)
27 sys.stderr.write("\n")
28 import traceback
29 traceback.print_exc()
30
31 from rdkit import Chem
32 from rdkit.Chem import rdchem, rdChemReactions
33 from rdkit.Chem import Draw
34 from rdkit.Chem.Draw import rdMolDraw2D
35 from rdkit.six import BytesIO,StringIO
36 import copy
37 import os
38 import json
39 import uuid
40 import numpy
41 try:
42 import Image
43 except ImportError:
44 from PIL import Image
45
46 from IPython.display import SVG
47
48 molSize = (450, 150)
49 highlightSubstructs = True
50 kekulizeStructures = True
51
52 ipython_useSVG = False
53 ipython_3d = False
54 molSize_3d = (450, 450)
55 drawing_type_3d = "ball and stick"
56 camera_type_3d = "perspective"
57 shader_3d = "lambert"
58
59
60
61 Chem.WrapLogs()
62
64 """For IPython notebook, renders 3D webGL objects."""
65
66 if not ipython_3d or not mol.GetNumConformers():
67 return None
68
69 try:
70 import imolecule
71 except ImportError:
72 raise ImportError("Cannot import 3D rendering. Please install "
73 "with `pip install imolecule`.")
74
75 conf = mol.GetConformer()
76 if not conf.Is3D():
77 return None
78
79 mol = Chem.Mol(mol)
80 try:
81 Chem.Kekulize(mol)
82 except Exception:
83 mol = Chem.Mol(mol)
84 size = molSize_3d
85
86
87 atomps = numpy.array([list(conf.GetAtomPosition(x))
88 for x in range(mol.GetNumAtoms())])
89 avgP = numpy.average(atomps, 0)
90 atomps -= avgP
91
92
93 atoms = [{"element": atom.GetSymbol(),
94 "location": list(atomps[atom.GetIdx()])}
95 for atom in mol.GetAtoms()]
96 bonds = [{"atoms": [bond.GetBeginAtomIdx(),
97 bond.GetEndAtomIdx()],
98 "order": int(bond.GetBondTypeAsDouble())}
99 for bond in mol.GetBonds()]
100 mol = {"atoms": atoms, "bonds": bonds}
101 return imolecule.draw({"atoms": atoms, "bonds": bonds}, format="json",
102 size=molSize_3d, drawing_type=drawing_type_3d,
103 camera_type=camera_type_3d, shader=shader_3d,
104 display_html=False)
105
106
108 if hasattr(mol,'__sssAtoms'):
109 highlightAtoms=mol.__sssAtoms
110 else:
111 highlightAtoms=[]
112 try:
113 mol.GetAtomWithIdx(0).GetExplicitValence()
114 except RuntimeError:
115 mol.UpdatePropertyCache(False)
116
117 if not hasattr(rdMolDraw2D,'MolDraw2DCairo'):
118 mc = copy.deepcopy(mol)
119 try:
120 img = Draw.MolToImage(mc,size=molSize,kekulize=kekulizeStructures,
121 highlightAtoms=highlightAtoms)
122 except ValueError:
123 mc = copy.deepcopy(mol)
124 img = Draw.MolToImage(mc,size=molSize,kekulize=False,
125 highlightAtoms=highlightAtoms)
126 bio = BytesIO()
127 img.save(bio,format='PNG')
128 return bio.getvalue()
129 else:
130 nmol = rdMolDraw2D.PrepareMolForDrawing(mol,kekulize=kekulizeStructures)
131 d2d = rdMolDraw2D.MolDraw2DCairo(molSize[0],molSize[1])
132 d2d.DrawMolecule(nmol,highlightAtoms=highlightAtoms)
133 d2d.FinishDrawing()
134 return d2d.GetDrawingText()
135
157
158
165
173
174
182
183
184
186 """displayhook function for PIL Images, rendered as PNG"""
187 bio = BytesIO()
188 img.save(bio,format='PNG')
189 return bio.getvalue()
190
191 _MolsToGridImageSaved = None
206
223
224 InstallIPythonRenderer()
225
226
243