Vaishnav14220 commited on
Commit
a3b274d
·
1 Parent(s): 31f1505

Add interactive 3D molecule viewer with 3Dmol.js

Browse files
Files changed (1) hide show
  1. app.py +63 -22
app.py CHANGED
@@ -80,31 +80,27 @@ def name_to_3d_molecule(name: str) -> tuple:
80
  # Import needed modules
81
  import io
82
  import base64
 
83
  from rdkit.Chem.Draw import rdMolDraw2D
84
 
85
  # Generate 2D image for preview
86
  mol_2d = Chem.MolFromSmiles(smiles) # Get 2D version
87
 
88
  # Create drawer for 2D structure
89
- drawer = rdMolDraw2D.MolDraw2DCairo(600, 600)
90
  drawer.DrawMolecule(mol_2d)
91
  drawer.FinishDrawing()
92
  img_2d_data = drawer.GetDrawingText()
93
  img_2d_str = base64.b64encode(img_2d_data).decode()
94
 
95
- # Create 3D structure image with atom indices
96
- drawer_3d = rdMolDraw2D.MolDraw2DCairo(600, 600)
97
- drawer_3d.drawOptions().addAtomIndices = True
98
- AllChem.Compute2DCoords(mol)
99
- drawer_3d.DrawMolecule(mol)
100
- drawer_3d.FinishDrawing()
101
- img_3d_data = drawer_3d.GetDrawingText()
102
- img_3d_str = base64.b64encode(img_3d_data).decode()
103
-
104
  # Get SMILES string
105
  canonical_smiles = Chem.MolToSmiles(mol_2d)
 
 
 
 
106
 
107
- # Create HTML with both views
108
  html_content = f"""
109
  <div style="padding: 20px;">
110
  <h3 style="text-align: center;">{name}</h3>
@@ -113,20 +109,65 @@ def name_to_3d_molecule(name: str) -> tuple:
113
  <div style="display: flex; gap: 20px; justify-content: center; flex-wrap: wrap; margin-top: 20px;">
114
  <div style="text-align: center;">
115
  <h4>2D Structure</h4>
116
- <img src="data:image/png;base64,{img_2d_str}" style="max-width: 600px; width: 100%; border: 1px solid #ddd; border-radius: 8px; padding: 10px; background: white;">
117
  </div>
118
 
119
  <div style="text-align: center;">
120
- <h4>3D Structure with Atom Labels</h4>
121
- <img src="data:image/png;base64,{img_3d_str}" style="max-width: 600px; width: 100%; border: 1px solid #ddd; border-radius: 8px; padding: 10px; background: white;">
122
- <p style="margin-top: 10px; font-size: 12px; color: #666;">3D optimized structure with atom indices</p>
123
  </div>
124
  </div>
125
-
126
- <div style="margin-top: 20px; padding: 15px; background-color: #e7f3ff; border: 2px solid #2196F3; border-radius: 8px; max-width: 800px; margin-left: auto; margin-right: auto;">
127
- <p style="color: #0d47a1; margin: 0;"><strong>💡 Tip:</strong> The SDF content below contains full 3D coordinates. Copy and paste into molecular viewers like PyMOL, Avogadro, or ChimeraX for interactive 3D visualization.</p>
128
- </div>
129
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  """
131
 
132
  return html_content, sdf_content
@@ -180,11 +221,11 @@ molecule_3d_interface = gr.Interface(
180
  fn=name_to_3d_molecule,
181
  inputs=gr.Textbox(label="Chemical Name", placeholder="e.g., benzene, aspirin, caffeine, glucose"),
182
  outputs=[
183
- gr.HTML(label="2D and 3D Molecular Structures"),
184
- gr.Textbox(label="3D SDF Content (for PyMOL, Avogadro, ChimeraX)", lines=10, max_lines=20, visible=True)
185
  ],
186
  api_name="name_to_molecule",
187
- description="View 2D structure and 3D optimized structure with atom labels. Copy the SDF content to view in external molecular viewers.",
188
  cache_examples=False,
189
  )
190
 
 
80
  # Import needed modules
81
  import io
82
  import base64
83
+ import json
84
  from rdkit.Chem.Draw import rdMolDraw2D
85
 
86
  # Generate 2D image for preview
87
  mol_2d = Chem.MolFromSmiles(smiles) # Get 2D version
88
 
89
  # Create drawer for 2D structure
90
+ drawer = rdMolDraw2D.MolDraw2DCairo(500, 500)
91
  drawer.DrawMolecule(mol_2d)
92
  drawer.FinishDrawing()
93
  img_2d_data = drawer.GetDrawingText()
94
  img_2d_str = base64.b64encode(img_2d_data).decode()
95
 
 
 
 
 
 
 
 
 
 
96
  # Get SMILES string
97
  canonical_smiles = Chem.MolToSmiles(mol_2d)
98
+
99
+ # Escape SDF for JavaScript
100
+ sdf_json = json.dumps(sdf_content)
101
+ viewer_id = f"viewer_{abs(hash(name))}"
102
 
103
+ # Create HTML with 3Dmol.js viewer
104
  html_content = f"""
105
  <div style="padding: 20px;">
106
  <h3 style="text-align: center;">{name}</h3>
 
109
  <div style="display: flex; gap: 20px; justify-content: center; flex-wrap: wrap; margin-top: 20px;">
110
  <div style="text-align: center;">
111
  <h4>2D Structure</h4>
112
+ <img src="data:image/png;base64,{img_2d_str}" style="max-width: 500px; width: 100%; border: 1px solid #ddd; border-radius: 8px; padding: 10px; background: white;">
113
  </div>
114
 
115
  <div style="text-align: center;">
116
+ <h4>3D Interactive Viewer</h4>
117
+ <div id="{viewer_id}" style="width: 500px; height: 500px; border: 1px solid #ddd; border-radius: 8px; background: white; position: relative;"></div>
 
118
  </div>
119
  </div>
 
 
 
 
120
  </div>
121
+
122
+ <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
123
+ <script src="https://3dmol.csb.pitt.edu/build/3Dmol-min.js"></script>
124
+ <script>
125
+ (function() {{
126
+ var sdfData = {sdf_json};
127
+ var viewerId = "{viewer_id}";
128
+
129
+ function init3DMol() {{
130
+ try {{
131
+ var element = document.getElementById(viewerId);
132
+ if (!element) {{
133
+ console.error('Viewer element not found:', viewerId);
134
+ return;
135
+ }}
136
+
137
+ var config = {{ backgroundColor: 'white' }};
138
+ var viewer = $3Dmol.createViewer(element, config);
139
+
140
+ viewer.addModel(sdfData, "sdf");
141
+ viewer.setStyle({{}}, {{
142
+ stick: {{ radius: 0.15, colorscheme: 'Jmol' }},
143
+ sphere: {{ radius: 0.4, colorscheme: 'Jmol' }}
144
+ }});
145
+
146
+ viewer.addLabels({{ elem: true }}, {{
147
+ fontSize: 12,
148
+ fontColor: 'black',
149
+ backgroundColor: 'white',
150
+ backgroundOpacity: 0.7
151
+ }});
152
+
153
+ viewer.zoomTo();
154
+ viewer.render();
155
+ viewer.zoom(1.2);
156
+
157
+ console.log('3DMol viewer initialized successfully');
158
+ }} catch (e) {{
159
+ console.error('Error initializing 3DMol viewer:', e);
160
+ }}
161
+ }}
162
+
163
+ // Wait for both jQuery and 3Dmol to load
164
+ if (typeof $3Dmol !== 'undefined') {{
165
+ init3DMol();
166
+ }} else {{
167
+ setTimeout(init3DMol, 1000);
168
+ }}
169
+ }})();
170
+ </script>
171
  """
172
 
173
  return html_content, sdf_content
 
221
  fn=name_to_3d_molecule,
222
  inputs=gr.Textbox(label="Chemical Name", placeholder="e.g., benzene, aspirin, caffeine, glucose"),
223
  outputs=[
224
+ gr.HTML(label="2D and 3D Interactive Molecular Viewer"),
225
+ gr.Textbox(label="3D SDF Content (Optional - for external viewers)", lines=10, max_lines=20, visible=False)
226
  ],
227
  api_name="name_to_molecule",
228
+ description="View 2D structure and interactive 3D molecule viewer with atom labels. Rotate and zoom the 3D structure!",
229
  cache_examples=False,
230
  )
231