File size: 7,280 Bytes
4414a85
d7d776e
13d9c1a
d7d776e
4414a85
 
 
13d9c1a
 
1049d12
74f7072
 
 
 
 
 
 
1049d12
13d9c1a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cfb3fe2
 
 
 
 
 
 
 
 
 
d7d776e
 
 
 
 
cfb3fe2
 
 
 
 
 
 
d7d776e
cfb3fe2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13d9c1a
 
 
 
 
 
 
 
 
74f7072
13d9c1a
736c721
 
 
 
 
 
 
13d9c1a
736c721
 
 
 
 
 
 
 
 
 
 
 
b8cbfe3
736c721
13d9c1a
bf77c6c
736c721
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
import streamlit as st
import ipywidgets
import py3Dmol

from rdkit import Chem
from rdkit.Chem import Draw
from PIL import Image
from rdkit import Chem
from rdkit.Chem import AllChem
from ipywidgets import interact,fixed,IntSlider
import streamlit as st
import streamlit.components.v1 as components
import py3Dmol
from rdkit import Chem
from rdkit.Chem import Draw
from rdkit.Chem import AllChem


def smi2conf(smiles):
    '''Convert SMILES to rdkit.Mol with 3D coordinates'''
    mol = Chem.MolFromSmiles(smiles)
    if mol is not None:
        mol = Chem.AddHs(mol)
        AllChem.EmbedMolecule(mol)
        AllChem.MMFFOptimizeMolecule(mol, maxIters=200)
        return mol
    else:
        return None

def MolTo3DView(mol, size=(300, 300), style="stick", surface=False, opacity=0.5):
    """Draw molecule in 3D
    
    Args:
    ----
        mol: rdMol, molecule to show
        size: tuple(int, int), canvas size
        style: str, type of drawing molecule
               style can be 'line', 'stick', 'sphere', 'carton'
        surface, bool, display SAS
        opacity, float, opacity of surface, range 0.0-1.0
    Return:
    ----
        viewer: py3Dmol.view, a class for constructing embedded 3Dmol.js views in ipython notebooks.
    """
    assert style in ('line', 'stick', 'sphere', 'carton')
    mblock = Chem.MolToMolBlock(mol)
    viewer = py3Dmol.view(width=size[0], height=size[1])
    viewer.addModel(mblock, 'mol')
    viewer.setStyle({style:{}})
    if surface:
        viewer.addSurface(py3Dmol.SAS, {'opacity': opacity})
    viewer.zoomTo()
    return viewer

def MakeMolecule(name, ingredients):
  st.write(name)
  m = Chem.MolFromSmiles(ingredients)
  im=Draw.MolToImage(m)
  st.image(im)    

def conf_viewer(idx):
    mol = confs[idx]
    return MolTo3DView(mol).show()

def style_selector(idx, s):
    conf = confs[idx]
    return MolTo3DView(conf, style=s).show()
              
@interact
def smi2viewer(smi='CC=O'):
    try:
        conf = smi2conf(smi)
        return MolTo3DView(conf).show()
    except:
        return None

smi = 'COc3nc(OCc2ccc(C#N)c(c1ccc(C(=O)O)cc1)c2P(=O)(O)O)ccc3C[NH2+]CC(I)NC(=O)C(F)(Cl)Br'
conf = smi2conf(smi)
viewer = MolTo3DView(conf, size=(600, 300), style='sphere')
viewer.show()

compound_smiles = 'c1cc(C(=O)O)c(OC(=O)C)cc1'
m = Chem.MolFromSmiles(compound_smiles)
im=Draw.MolToImage(m)
st.image(im)

MakeMolecule("Ethanol", "CCO")
MakeMolecule("Acetic acid", "CC(=O)O")
MakeMolecule("Cyclohexane", "C1CCCCC1")
MakeMolecule("Pyridine", "c1cnccc1")

viewer = MolTo3DView(conf, size=(600, 300), style='sphere')
viewer.show()

smis = [ 'COc3nc(OCc2ccc(C#N)c(c1ccc(C(=O)O)cc1)c2P(=O)(O)O)ccc3C[NH2+]CC(I)NC(=O)C(F)(Cl)Br',
    'CC(NCCNCC1=CC=C(OCC2=C(C)C(C3=CC=CC=C3)=CC=C2)N=C1OC)=O',
    'Cc1c(COc2cc(OCc3cccc(c3)C#N)c(CN3C[C@H](O)C[C@H]3C(O)=O)cc2Cl)cccc1-c1ccc2OCCOc2c1',
    'CCCCC(=O)NCCCCC(=O)NCCCCCC(=O)[O-]',
    "CC(NCCNCC1=CC=C(OCC2=C(C)C(C3=CC=CC=C3)=CC=C2)N=C1OC)=O"]
    
confs = [smi2conf(s) for s in smis]


st.title('SMILES  + RDKit + Py3DMOL :smiley:')
def show(smi, style='stick'):
    mol = Chem.MolFromSmiles(smi)
    mol = Chem.AddHs(mol)
    AllChem.EmbedMolecule(mol)
    AllChem.MMFFOptimizeMolecule(mol, maxIters=200)
    mblock = Chem.MolToMolBlock(mol)

    view = py3Dmol.view(width=400, height=400)
    view.addModel(mblock, 'mol')
    view.setStyle({style:{}})
    view.zoomTo()
    view.show()
    view.render()
    t =view.js()
    f = open('viz.html', 'w')
    f.write(t.startjs)
    f.write(t.endjs)
    f.close()

compound_smiles=st.text_input('SMILES please','CCCCC(=O)NCCCCC(=O)NCCCCCC(=O)[O-]')
m = Chem.MolFromSmiles(compound_smiles)

#Draw.MolToFile(m,'mol.png')

show(compound_smiles)
HtmlFile = open("viz.html", 'r', encoding='utf-8')
source_code = HtmlFile.read() 
c1,c2=st.beta_columns(2)
with c1:
  st.write('Molecule :coffee:')
with c2:
  components.html(source_code, height = 400,width=400)

################ Sidebar ####################
with st.sidebar.beta_expander('Rule One (Atoms and Bonds)'):
  st.markdown('''
## Atoms
|If |then |
|----|----|
| Non-aromatic atoms |Uper case letters |
| Aromatic atoms |lower case letters |
|Atomic symbols has more than one letter | The second is lower case |
## Bonds
| Bond type| Bond symbol |
|---|---|
|Simple | - |
|Double|=|
|Triple|#|
|Aromatic|*|
| Disconnected structures|. |
### Example:
 CC   👉 There is a non-aromatic carbon attached to another non-aromatic carbon by a single bond.
🛑 A bond between two lower case atom symbols is *aromatic*.
''')

with st.sidebar.beta_expander('Rule Two (Simple Chains)'):
  st.markdown('''
  ## Simple chains
  * Structures are hydrogen suppresed (Molecules represented without hydrogens)
  * If enough bonds are not identified by the user, the system will assume that connections
  are satisfied by hidrogens.
  * The user can explicitly identify hydrogen bonds, but if so the interpreter will assume that all of them are fully identified.
  Note:
  
  *Because SMILES allows entry of all elements in the periodic table, 
  and also utilizes hydrogen suppression, the user should be aware of chemicals with two letters 
  that could be misinterpreted by the computer. For example, 'Sc' could be interpreted as a **sulfur**
  atom connected to an aromatic **carbon** by a single bond, or it could be the symbol for **scandium**. 
  The SMILES interpreter gives priority to the interpretation of a single bond connecting a sulfur atom and an aromatic carbon. 
  To identify scandium the user should enter [Sc]*.
  ''')

with st.sidebar.beta_expander('Rule Three (Branches)'):
  st.markdown('''
  ## Branches
  * A branch from a chain is specified by placing the SMILES symbol(s) for the branch between parenthesis. 
  * The string in parentheses is placed directly after the symbol for the atom to which it is connected. 
  * If it is connected by a double or triple bond, the bond symbol immediately follows the left parenthesis.
  ''')

with st.sidebar.beta_expander('Rule Four (Rings)'):
  st.markdown('''
  ## Rings
  * SMILES allows a user to identify ring structures by using numbers to identify the opening and closing ring atom.
  For example, in C1CCCCC1, the first carbon has a number '1' which connects by a single bond with the last carbon which also has a number '1'. 
  The resulting structure is cyclohexane. Chemicals that have multiple rings may be identified by using different numbers for each ring.
  * If a double, single, or aromatic bond is used for the ring closure, the bond symbol is placed before the ring closure number.
  ''')

with st.sidebar.beta_expander('Rule Five (Charged atoms)'):
  st.markdown('''
  ## Charged atoms
  Charges on an atom can be used to override the knowledge regarding valence that is built into SMILES software. 
  The format for identifying a charged atom consists of the atom followed by brackets which enclose the charge on the atom. 
  The number of charges may be explicitly stated ({-1}) or not ({-}). 
  ''')
st.sidebar.markdown('Original Author: José Manuel Nápoles ([@napoles3d](https://twitter.com/napoles3D)). Find original app in https://share.streamlit.io/napoles-uach/st_smiles/main/smiles.py')
st.sidebar.write('Info about SMILES: https://archive.epa.gov/med/med_archive_03/web/html/smiles.html')