Vaishnav14220 commited on
Commit
32797f8
·
1 Parent(s): a3b274d

Replace 3Dmol.js with Plotly for interactive 3D molecule viewer with atom labels

Browse files
Files changed (2) hide show
  1. app.py +95 -76
  2. requirements.txt +2 -1
app.py CHANGED
@@ -80,14 +80,13 @@ def name_to_3d_molecule(name: str) -> tuple:
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()
@@ -96,81 +95,99 @@ def name_to_3d_molecule(name: str) -> tuple:
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>
107
- <p style="text-align: center;"><strong>SMILES:</strong> {canonical_smiles}</p>
108
-
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
174
 
175
  except Exception as e:
176
  raise gr.Error(f"Error creating molecule: {str(e)}")
@@ -221,12 +238,14 @@ molecule_3d_interface = gr.Interface(
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
 
232
 
 
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()
 
95
  # Get SMILES string
96
  canonical_smiles = Chem.MolToSmiles(mol_2d)
97
 
98
+ # Create 3D visualization using Plotly
99
+ import plotly.graph_objects as go
100
+
101
+ # Get atom positions and elements
102
+ conf = mol.GetConformer()
103
+ atoms = mol.GetAtoms()
104
+
105
+ x_coords = []
106
+ y_coords = []
107
+ z_coords = []
108
+ elements = []
109
+ atom_labels = []
110
+
111
+ for i, atom in enumerate(atoms):
112
+ pos = conf.GetAtomPosition(i)
113
+ x_coords.append(pos.x)
114
+ y_coords.append(pos.y)
115
+ z_coords.append(pos.z)
116
+ element = atom.GetSymbol()
117
+ elements.append(element)
118
+ atom_labels.append(f"{element}{i}")
119
+
120
+ # Define color scheme for common elements (Jmol colors)
121
+ color_map = {
122
+ 'H': '#FFFFFF', 'C': '#909090', 'N': '#3050F8', 'O': '#FF0D0D',
123
+ 'F': '#90E050', 'Cl': '#1FF01F', 'Br': '#A62929', 'I': '#940094',
124
+ 'P': '#FF8000', 'S': '#FFFF30', 'B': '#FFB5B5', 'Si': '#F0C8A0'
125
+ }
126
+
127
+ colors = [color_map.get(e, '#FF1493') for e in elements]
128
+
129
+ # Create 3D scatter plot for atoms with labels
130
+ atoms_trace = go.Scatter3d(
131
+ x=x_coords, y=y_coords, z=z_coords,
132
+ mode='markers+text',
133
+ marker=dict(size=10, color=colors, line=dict(color='black', width=1)),
134
+ text=atom_labels,
135
+ textposition='top center',
136
+ textfont=dict(size=10, color='black'),
137
+ name='Atoms',
138
+ hovertext=[f"{lbl}<br>Pos: ({x:.2f}, {y:.2f}, {z:.2f})"
139
+ for lbl, x, y, z in zip(atom_labels, x_coords, y_coords, z_coords)],
140
+ hoverinfo='text'
141
+ )
142
 
143
+ # Create bonds
144
+ bond_x = []
145
+ bond_y = []
146
+ bond_z = []
147
+
148
+ for bond in mol.GetBonds():
149
+ i = bond.GetBeginAtomIdx()
150
+ j = bond.GetEndAtomIdx()
151
+ pos_i = conf.GetAtomPosition(i)
152
+ pos_j = conf.GetAtomPosition(j)
153
+ bond_x.extend([pos_i.x, pos_j.x, None])
154
+ bond_y.extend([pos_i.y, pos_j.y, None])
155
+ bond_z.extend([pos_i.z, pos_j.z, None])
156
+
157
+ bonds_trace = go.Scatter3d(
158
+ x=bond_x, y=bond_y, z=bond_z,
159
+ mode='lines',
160
+ line=dict(color='#888888', width=4),
161
+ name='Bonds',
162
+ hoverinfo='skip'
163
+ )
164
+
165
+ # Create figure
166
+ fig = go.Figure(data=[bonds_trace, atoms_trace])
167
+
168
+ fig.update_layout(
169
+ title=dict(text=f"{name}<br>SMILES: {canonical_smiles}", x=0.5, xanchor='center'),
170
+ scene=dict(
171
+ xaxis=dict(showbackground=False, showgrid=True, zeroline=False, showticklabels=False, title=''),
172
+ yaxis=dict(showbackground=False, showgrid=True, zeroline=False, showticklabels=False, title=''),
173
+ zaxis=dict(showbackground=False, showgrid=True, zeroline=False, showticklabels=False, title=''),
174
+ bgcolor='white'
175
+ ),
176
+ showlegend=False,
177
+ width=800,
178
+ height=700,
179
+ margin=dict(l=0, r=0, t=50, b=0)
180
+ )
181
+
182
+ # Generate 2D structure HTML
183
+ html_2d = f"""
184
+ <div style="text-align: center; padding: 20px;">
185
+ <h4>2D Structure</h4>
186
+ <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;">
187
+ </div>
 
 
 
 
188
  """
189
 
190
+ return html_2d, fig, sdf_content
191
 
192
  except Exception as e:
193
  raise gr.Error(f"Error creating molecule: {str(e)}")
 
238
  fn=name_to_3d_molecule,
239
  inputs=gr.Textbox(label="Chemical Name", placeholder="e.g., benzene, aspirin, caffeine, glucose"),
240
  outputs=[
241
+ gr.HTML(label="2D Structure"),
242
+ gr.Plot(label="3D Interactive Molecule Viewer - Rotate and Zoom!"),
243
  gr.Textbox(label="3D SDF Content (Optional - for external viewers)", lines=10, max_lines=20, visible=False)
244
  ],
245
  api_name="name_to_molecule",
246
+ description="View 2D structure and interactive 3D molecule with atom labels. Click and drag to rotate, scroll to zoom!",
247
  cache_examples=False,
248
+ examples=[["benzene"], ["aspirin"], ["caffeine"], ["glucose"]],
249
  )
250
 
251
 
requirements.txt CHANGED
@@ -2,4 +2,5 @@
2
  rdkit
3
  gradio==4.44.1
4
  huggingface_hub==0.19.4
5
- cirpy
 
 
2
  rdkit
3
  gradio==4.44.1
4
  huggingface_hub==0.19.4
5
+ cirpy
6
+ plotly