File size: 5,199 Bytes
4414a85
13d9c1a
4414a85
20b5ead
74f7072
 
20b5ead
1049d12
20b5ead
 
 
 
 
 
 
 
13d9c1a
 
 
 
20b5ead
 
13d9c1a
 
20b5ead
 
 
13d9c1a
 
 
 
 
 
 
 
 
20b5ead
 
74f7072
20b5ead
 
 
 
 
 
 
 
 
 
 
13d9c1a
b259c01
20b5ead
b259c01
20b5ead
 
b259c01
20b5ead
 
 
 
13d9c1a
736c721
20b5ead
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
736c721
20b5ead
 
 
 
 
 
 
 
 
 
05c0429
 
20b5ead
d28b333
20b5ead
 
c3303b0
20b5ead
2e1731a
20b5ead
 
 
 
 
 
c3303b0
20b5ead
 
 
 
 
b259c01
20b5ead
 
 
 
 
c3303b0
20b5ead
c3303b0
20b5ead
 
dd9b023
a961900
20b5ead
 
 
 
 
 
 
 
 
 
 
 
 
 
a961900
20b5ead
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
import streamlit as st
import py3Dmol
from rdkit import Chem
from rdkit.Chem import AllChem, Draw
import streamlit.components.v1 as components

# --- Helper Functions ---

def smi_to_3d_mol(smiles):
    """
    Converts a SMILES string to an RDKit Mol object with 3D coordinates.
    """
    try:
        mol = Chem.MolFromSmiles(smiles)
        if mol is None:
            return None
        mol = Chem.AddHs(mol)
        AllChem.EmbedMolecule(mol)
        AllChem.MMFFOptimizeMolecule(mol, maxIters=200)
        return mol
    except Exception as e:
        st.error(f"Error processing SMILES: {e}")
        return None

def render_3d_viewer(mol, style="stick", size=(500, 500), surface=False, opacity=0.5):
    """
    Creates a py3Dmol viewer and returns its HTML representation for Streamlit.
    """
    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 the viewer's HTML/JS representation for Streamlit
    return viewer.js()

def render_2d_image(name, ingredients):
    """
    Displays the name and a 2D image of a molecule in a Streamlit column.
    """
    mol = Chem.MolFromSmiles(ingredients)
    if mol:
        st.write(f"**{name}**")
        img = Draw.MolToImage(mol)
        st.image(img, caption=ingredients)
    else:
        st.warning(f"Could not generate molecule for '{name}'.")


# --- Main Streamlit App ---

st.set_page_config(layout="wide")
st.title('⚛️🧬 Molecule Modeler 🧬⚛️')

# --- Interactive 3D Viewer Section ---
st.header("Interactive 3D Molecule Viewer")
# Create two columns for the input and the viewer
c1, c2 = st.columns([1, 2]) # Input column is 1/3 of the width

with c1:
    st.write('Enter a SMILES string below to generate a 3D model.')
    compound_smiles = st.text_input(
        'SMILES Input',
        'CC(=O)Oc1ccccc1C(=O)O' # Default: Aspirin
    )
    style = st.selectbox('Select Viewer Style', ['stick', 'sphere', 'line', 'carton'])
    show_surface = st.checkbox('Show Molecular Surface')
    opacity = 0.5
    if show_surface:
        opacity = st.slider('Surface Opacity', 0.1, 1.0, 0.5)

    st.write('**What is SMILES?**')
    st.info('''
    The **Simplified Molecular-Input Line-Entry System (SMILES)** is a text-based representation of a molecule's structure.
    - [Learn more on Wikipedia](https://en.wikipedia.org/wiki/Simplified_molecular-input_line-entry_system)
    - [Find compounds on PubChem](https://pubchem.ncbi.nlm.nih.gov/).
    ''')


# Process input and display the 3D viewer in the second column
with c2:
    if compound_smiles:
        mol_3d = smi_to_3d_mol(compound_smiles)
        if mol_3d:
            st.write('**3D Chemical Structure**')
            viewer_html = render_3d_viewer(mol_3d, style=style, surface=show_surface, opacity=opacity)
            components.html(viewer_html, height=500, width=500)
        else:
            st.error("Invalid SMILES string. Could not generate the molecule.")
    else:
        st.info("Enter a SMILES string to generate a 3D model.")


st.divider()

# --- Predefined Molecules Section ---
st.header("Molecule Examples (2D)")

col1, col2, col3 = st.columns(3)

with col1:
    st.subheader("Common Molecules")
    render_2d_image("Ibuprofen", "CC(C)CC1=CC=C(C=C1)C(C)C(=O)O")
    render_2d_image("Caffeine", "CN1C=NC2=C1C(=O)N(C(=O)N2C)C")
    render_2d_image("Ethanol", "CCO")
    render_2d_image("Glucose", "OC[C@@H](O1)[C@@H](O)[C@H](O)[C@@H](O)[C@H](O)1")

with col2:
    st.subheader("Vitamins")
    render_2d_image("Thiamine (B1)", "OCCc1c(C)[n+](cs1)Cc2cnc(C)nc2N")
    render_2d_image("Vitamin E", "CC(C)CCC[C@@H](C)CCC[C@@H](C)CCC[C@]1(C)CCc2c(C)c(O)c(C)c(C)c2O1")
    render_2d_image("Vitamin D3", "C[C@@H](CCCC(C)C)[C@H]1CC[C@H]2/C(=C/C=C/3\C(=C)CCC[C@H]3O)/CC[C@]12C")

with col3:
    st.subheader("COVID-19 Antivirals")
    render_2d_image("Favipiravir", "C1=C(N=C(C(=O)N1)C(=O)N)F")
    render_2d_image("Remdesivir", "CCC(CC)COC(=O)[C@H](C)N[P@](=O)(OC[C@@H]1[C@H]([C@H]([C@](O1)(C#N)C2=CC=C3N2N=CN=C3N)O)O)OC4=CC=CC=C4")
    render_2d_image("Ritonavir", "CC(C)C1=NC(=CS1)CN(C)C(=O)N[C@@H](C(C)C)C(=O)N[C@@H](CC2=CC=CC=C2)C[C@@H]([C@H](CC3=CC=CC=C3)NC(=O)OCC4=CN=CS4)O")

st.divider()

# --- Markdown Section with SMILES Lists ---
st.header("Drug Information & SMILES Strings")

markDown = '''
### Opioids
* **Fentanyl:** `CCC(=O)N(C1CCN(CC1)CCC2=CC=CC=C2)C3=CC=CC=C3`
* **Hydrocodone:** `CN1CC[C@]23[C@@H]4[C@H]1CC5=C2C(=C(C=C5)OC)O[C@H]3C(=O)CC4`
* **Oxycodone:** `CN1CC[C@]23[C@@H]4C(=O)CC[C@]2([C@H]1CC5=C3C(=C(C=C5)OC)O4)O`

### CNS Depressants
* **Diazepam (Valium):** `CN1C(=O)CN=C(C2=C1C=CC(=C2)Cl)C3=CC=CC=C3`
* **Alprazolam (Xanax):** `CC1=NN=C2N1C3=C(C=C(C=C3)Cl)C(=NC2)C4=CC=CC=C4`
* **Zolpidem (Ambien):** `CC1=CC=C(C=C1)C2=C(N3C=C(C=CC3=N2)C)CC(=O)N(C)C`

### Stimulants
* **Dextroamphetamine:** `C[C@@H](CC1=CC=CC=C1)N`
* **Methylphenidate (Ritalin):** `COC(=O)C(C1CCCCN1)C2=CC=CC=C2`
* **Amphetamine (base):** `CC(N)CC1=CC=CC=C1`
'''
st.markdown(markDown)