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

Show 3D structure as 2D projection with atom indices instead of iframe

Browse files
Files changed (1) hide show
  1. app.py +33 -50
app.py CHANGED
@@ -77,55 +77,34 @@ def name_to_3d_molecule(name: str) -> tuple:
77
  # Generate SDF content
78
  sdf_content = Chem.MolToMolBlock(mol)
79
 
 
 
 
 
 
80
  # Generate 2D image for preview
81
  mol_2d = Chem.MolFromSmiles(smiles) # Get 2D version
82
- img = Draw.MolToImage(mol_2d, size=(400, 400))
83
 
84
- # Convert image to base64
85
- import io
86
- import base64
87
- import json
88
- buffered = io.BytesIO()
89
- img.save(buffered, format="PNG")
90
- img_str = base64.b64encode(buffered.getvalue()).decode()
 
 
 
 
 
 
 
 
91
 
92
  # Get SMILES string
93
  canonical_smiles = Chem.MolToSmiles(mol_2d)
94
-
95
- # Prepare SDF content for JavaScript (escape backticks)
96
- sdf_content_escaped = sdf_content.replace('`', '\\`')
97
-
98
- # Create data URI for the 3D viewer HTML
99
- viewer_html = f"""
100
- <!DOCTYPE html>
101
- <html>
102
- <head>
103
- <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
104
- <script src="https://3dmol.csb.pitt.edu/build/3Dmol-min.js"></script>
105
- <style>
106
- body {{ margin: 0; padding: 0; background: white; }}
107
- #viewer {{ width: 100%; height: 100vh; }}
108
- </style>
109
- </head>
110
- <body>
111
- <div id="viewer"></div>
112
- <script>
113
- $(function() {{
114
- let viewer = $3Dmol.createViewer("viewer", {{backgroundColor: 'white'}});
115
- let sdfData = `{sdf_content_escaped}`;
116
- viewer.addModel(sdfData, "sdf");
117
- viewer.setStyle({{}}, {{stick: {{radius: 0.15, colorscheme: 'Jmol'}}, sphere: {{radius: 0.4, colorscheme: 'Jmol'}}}});
118
- viewer.addLabels({{elem: true}}, {{fontSize: 12, fontColor: 'black', backgroundColor: 'white', backgroundOpacity: 0.7}});
119
- viewer.zoomTo();
120
- viewer.render();
121
- }});
122
- </script>
123
- </body>
124
- </html>
125
- """
126
- viewer_data_uri = "data:text/html;base64," + base64.b64encode(viewer_html.encode()).decode()
127
-
128
- # Create HTML with 2D and 3D viewers side by side
129
  html_content = f"""
130
  <div style="padding: 20px;">
131
  <h3 style="text-align: center;">{name}</h3>
@@ -134,15 +113,19 @@ def name_to_3d_molecule(name: str) -> tuple:
134
  <div style="display: flex; gap: 20px; justify-content: center; flex-wrap: wrap; margin-top: 20px;">
135
  <div style="text-align: center;">
136
  <h4>2D Structure</h4>
137
- <img src="data:image/png;base64,{img_str}" style="max-width: 400px; border: 1px solid #ddd; border-radius: 8px; padding: 10px; background: white;">
138
  </div>
139
 
140
  <div style="text-align: center;">
141
- <h4>3D Interactive Model</h4>
142
- <iframe src="{viewer_data_uri}" style="width: 400px; height: 400px; border: 1px solid #ddd; border-radius: 8px;"></iframe>
143
- <p style="margin-top: 10px; font-size: 12px; color: #666;">Drag to rotate, scroll to zoom</p>
144
  </div>
145
  </div>
 
 
 
 
146
  </div>
147
  """
148
 
@@ -197,11 +180,11 @@ molecule_3d_interface = gr.Interface(
197
  fn=name_to_3d_molecule,
198
  inputs=gr.Textbox(label="Chemical Name", placeholder="e.g., benzene, aspirin, caffeine, glucose"),
199
  outputs=[
200
- gr.HTML(label="2D and 3D Molecular Viewer"),
201
- gr.Textbox(label="3D SDF Content (optional - for external viewers)", lines=10, max_lines=20, visible=False)
202
  ],
203
  api_name="name_to_molecule",
204
- description="View 2D structure and interactive 3D molecule. Drag to rotate the 3D model, scroll to zoom.",
205
  cache_examples=False,
206
  )
207
 
 
77
  # Generate SDF content
78
  sdf_content = Chem.MolToMolBlock(mol)
79
 
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
  <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
 
 
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