annabossler commited on
Commit
5dcd4f0
·
verified ·
1 Parent(s): 7142a20

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +156 -239
app.py CHANGED
@@ -1,13 +1,11 @@
1
  import os
2
  os.environ["TORCH_DYNAMO_DISABLE"] = "1"
3
- import subprocess
4
- import sys
5
- from pathlib import Path
6
  import tempfile
7
  import numpy as np
8
  import gradio as gr
9
  from ase.io import read, write
10
  from ase.io.trajectory import Trajectory
 
11
  from simulation_scripts_orbmol import load_orbmol_model, run_md_simulation, run_relaxation_simulation
12
  import hashlib
13
 
@@ -158,247 +156,166 @@ def relax_wrapper(structure_file, task_name, steps, fmax, charge, spin, relax_ce
158
  traceback.print_exc()
159
  return (f"Error: {e}", None, "", "", "", None)
160
 
161
- # ==== MAIN FUNCTION ====
162
- def main():
163
- with gr.Blocks(theme=gr.themes.Ocean(), title="OrbMol Demo") as demo:
164
- with gr.Tabs():
165
- # -------- HOME --------
166
- with gr.Tab("Home"):
167
- with gr.Row():
168
- with gr.Column(scale=1):
169
- gr.Markdown("## Learn more about OrbMol")
170
-
171
- with gr.Accordion("What is OrbMol?", open=False):
172
- gr.Markdown("""
173
- OrbMol is a suite of quantum-accurate machine learning models for molecular predictions. Built on the **Orb-v3 architecture**, OrbMol provides fast and accurate calculations of energies, forces, and molecular properties.
174
- """)
175
-
176
- with gr.Accordion("Available Models", open=False):
177
- gr.Markdown("""
178
- **OMol** and **OMol-Direct**
179
- - Training dataset: OMol25 (>100M calculations)
180
- - Level of theory: ωB97M-V/def2-TZVPD
181
- - Applications: biology, organic chemistry, drug discovery
182
-
183
- **OMat**
184
- - Training dataset: OMat24 (>100M inorganic calculations)
185
- - Level of theory: PBE/PBE+U
186
- - Applications: materials discovery, photovoltaics, alloys
187
- """)
188
-
189
- with gr.Accordion("Supported File Formats", open=False):
190
- gr.Markdown("""
191
- Supported formats: `.xyz`, `.pdb`, `.cif`, `.traj`, `.mol`, `.sdf`
192
- """)
193
-
194
- with gr.Accordion("Resources & Support", open=False):
195
- gr.Markdown("""
196
- - [Orb-v3 paper](https://arxiv.org/abs/2504.06231)
197
- - [Orb-Models GitHub](https://github.com/orbital-materials/orb-models)
198
- """)
199
 
200
- with gr.Column(scale=2):
201
- gr.Image("logo_color_text.png",
202
- show_share_button=False,
203
- show_download_button=False,
204
- show_label=False,
205
- show_fullscreen_button=False)
206
-
207
- gr.Markdown("# OrbMol — Quantum-Accurate Molecular Predictions")
208
- gr.Markdown("""
209
- Welcome to OrbMol! Use the tabs above to access:
210
-
211
- 1. **Single Point Energy**: Calculate energies and forces
212
- 2. **Molecular Dynamics**: Run MD simulations
213
- 3. **Relaxation / Optimization**: Optimize structures
214
-
215
- Supported formats: `.xyz`, `.pdb`, `.cif`, `.traj`, `.mol`, `.sdf`
216
- """)
217
-
218
- # -------- SPE --------
219
- with gr.Tab("Single Point Energy"):
220
- with gr.Row():
221
- with gr.Column(scale=2):
222
- gr.Markdown("# OrbMol — Quantum-Accurate Molecular Predictions")
223
- gr.Markdown("**Supported formats:** .xyz, .pdb, .cif, .traj, .mol, .sdf")
224
-
225
- xyz_input = gr.File(
226
- label="Upload Structure File",
227
- file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"],
228
- file_count="single"
229
- )
230
- task_name_spe = gr.Radio(
231
- ["OMol", "OMat", "OMol-Direct"],
232
- value="OMol",
233
- label="Model Type"
234
- )
235
- with gr.Row():
236
- charge_input = gr.Slider(-10, 10, 0, step=1, label="Charge")
237
- spin_input = gr.Slider(1, 11, 1, step=1, label="Spin Multiplicity")
238
-
239
- run_spe = gr.Button("Run OrbMol Prediction", variant="primary")
240
-
241
- with gr.Column(variant="panel", min_width=500):
242
- spe_out = gr.Textbox(label="Energy & Forces", lines=15, interactive=False)
243
- spe_status = gr.Textbox(label="Status", interactive=False)
244
-
245
- spe_viewer = Molecule3D(
246
- label="Input Structure Viewer",
247
- reps=DEFAULT_MOLECULAR_REPRESENTATIONS,
248
- config=DEFAULT_MOLECULAR_SETTINGS
249
- )
250
-
251
- task_name_spe.change(
252
- lambda x: (
253
- gr.update(visible=x in ["OMol", "OMol-Direct"]),
254
- gr.update(visible=x in ["OMol", "OMol-Direct"])
255
- ),
256
- [task_name_spe],
257
- [charge_input, spin_input]
258
- )
259
-
260
- run_spe.click(
261
- predict_molecule,
262
- [xyz_input, task_name_spe, charge_input, spin_input],
263
- [spe_out, spe_status, spe_viewer]
264
- )
265
-
266
- # -------- MD --------
267
- with gr.Tab("Molecular Dynamics"):
268
- with gr.Row():
269
- with gr.Column(scale=2):
270
- gr.Markdown("## Molecular Dynamics Simulation")
271
-
272
- xyz_md = gr.File(
273
- label="Upload Structure File",
274
- file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"],
275
- file_count="single"
276
- )
277
- task_name_md = gr.Radio(
278
- ["OMol", "OMat", "OMol-Direct"],
279
- value="OMol",
280
- label="Model Type"
281
- )
282
- with gr.Row():
283
- charge_md = gr.Slider(-10, 10, 0, step=1, label="Charge")
284
- spin_md = gr.Slider(1, 11, 1, step=1, label="Spin Multiplicity")
285
- with gr.Row():
286
- steps_md = gr.Slider(10, 2000, 100, step=10, label="Steps")
287
- temp_md = gr.Slider(10, 1500, 300, step=10, label="Temperature (K)")
288
- with gr.Row():
289
- timestep_md = gr.Slider(0.1, 5.0, 1.0, step=0.1, label="Timestep (fs)")
290
- ensemble_md = gr.Radio(["NVE", "NVT"], value="NVE", label="Ensemble")
291
- run_md_btn = gr.Button("Run MD Simulation", variant="primary")
292
-
293
- with gr.Column(variant="panel", min_width=520):
294
- md_status = gr.Textbox(label="MD Status", interactive=False)
295
- md_traj = gr.File(label="Trajectory (.traj)", interactive=False)
296
-
297
- md_viewer = Molecule3D(
298
- label="MD Result Viewer",
299
- reps=DEFAULT_MOLECULAR_REPRESENTATIONS,
300
- config=DEFAULT_MOLECULAR_SETTINGS
301
- )
302
-
303
- md_log = gr.Textbox(label="Log", interactive=False, lines=15)
304
- md_script = gr.Code(label="Reproduction Script", language="python", interactive=False, lines=20)
305
- md_explain = gr.Markdown()
306
-
307
- task_name_md.change(
308
- lambda x: (
309
- gr.update(visible=x in ["OMol", "OMol-Direct"]),
310
- gr.update(visible=x in ["OMol", "OMol-Direct"])
311
- ),
312
- [task_name_md],
313
- [charge_md, spin_md]
314
- )
315
-
316
- run_md_btn.click(
317
- md_wrapper,
318
- [xyz_md, task_name_md, charge_md, spin_md, steps_md, temp_md, timestep_md, ensemble_md],
319
- [md_status, md_traj, md_log, md_script, md_explain, md_viewer]
320
- )
321
 
322
- # -------- Relax --------
323
- with gr.Tab("Relaxation / Optimization"):
324
- with gr.Row():
325
- with gr.Column(scale=2):
326
- gr.Markdown("## Structure Relaxation/Optimization")
327
-
328
- xyz_rlx = gr.File(
329
- label="Upload Structure File",
330
- file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"],
331
- file_count="single"
332
- )
333
- task_name_rlx = gr.Radio(
334
- ["OMol", "OMat", "OMol-Direct"],
335
- value="OMol",
336
- label="Model Type"
337
- )
338
- with gr.Row():
339
- steps_rlx = gr.Slider(1, 2000, 300, step=1, label="Max Steps")
340
- fmax_rlx = gr.Slider(0.001, 0.5, 0.05, step=0.001, label="Fmax (eV/Å)")
341
- with gr.Row():
342
- charge_rlx = gr.Slider(-10, 10, 0, step=1, label="Charge")
343
- spin_rlx = gr.Slider(1, 11, 1, step=1, label="Spin")
344
- relax_cell = gr.Checkbox(False, label="Relax Unit Cell")
345
- run_rlx_btn = gr.Button("Run Optimization", variant="primary")
 
 
346
 
347
- with gr.Column(variant="panel", min_width=520):
348
- rlx_status = gr.Textbox(label="Status", interactive=False)
349
- rlx_traj = gr.File(label="Trajectory (.traj)", interactive=False)
350
-
351
- rlx_viewer = Molecule3D(
352
- label="Optimized Structure Viewer",
353
- reps=DEFAULT_MOLECULAR_REPRESENTATIONS,
354
- config=DEFAULT_MOLECULAR_SETTINGS
355
- )
356
-
357
- rlx_log = gr.Textbox(label="Log", interactive=False, lines=15)
358
- rlx_script = gr.Code(label="Reproduction Script", language="python", interactive=False, lines=20)
359
- rlx_explain = gr.Markdown()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
 
361
- task_name_rlx.change(
362
- lambda x: (
363
- gr.update(visible=x in ["OMol", "OMol-Direct"]),
364
- gr.update(visible=x in ["OMol", "OMol-Direct"])
365
- ),
366
- [task_name_rlx],
367
- [charge_rlx, spin_rlx]
368
- )
369
-
370
- run_rlx_btn.click(
371
- relax_wrapper,
372
- [xyz_rlx, task_name_rlx, steps_rlx, fmax_rlx, charge_rlx, spin_rlx, relax_cell],
373
- [rlx_status, rlx_traj, rlx_log, rlx_script, rlx_explain, rlx_viewer]
374
- )
 
 
 
 
 
 
 
 
 
 
375
 
376
- demo.queue(default_concurrency_limit=None)
377
- demo.launch(ssr_mode=False)
 
 
 
 
 
 
 
 
 
 
 
378
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
 
380
  if __name__ == "__main__":
381
- # On load, build and install the gradio_molecule3d fork
382
- subprocess.call(
383
- ["gradio", "cc", "install"], cwd=Path(__file__).parent / "gradio_molecule3d/"
384
- )
385
- subprocess.call(
386
- ["gradio", "cc", "build"], cwd=Path(__file__).parent / "gradio_molecule3d/"
387
- )
388
- subprocess.call(
389
- [
390
- sys.executable,
391
- "-m",
392
- "pip",
393
- "install",
394
- Path(__file__).parent
395
- / "gradio_molecule3d/"
396
- / "dist/gradio_molecule3d-0.0.7-py3-none-any.whl",
397
- ],
398
- cwd=Path(__file__).parent.parent,
399
- )
400
-
401
- # Load gradio_molecule3d only once it's built and installed
402
- from gradio_molecule3d import Molecule3D
403
-
404
- main()
 
1
  import os
2
  os.environ["TORCH_DYNAMO_DISABLE"] = "1"
 
 
 
3
  import tempfile
4
  import numpy as np
5
  import gradio as gr
6
  from ase.io import read, write
7
  from ase.io.trajectory import Trajectory
8
+ from gradio_molecule3d import Molecule3D
9
  from simulation_scripts_orbmol import load_orbmol_model, run_md_simulation, run_relaxation_simulation
10
  import hashlib
11
 
 
156
  traceback.print_exc()
157
  return (f"Error: {e}", None, "", "", "", None)
158
 
159
+ # ==== UI ====
160
+ with gr.Blocks(theme=gr.themes.Ocean(), title="OrbMol Demo") as demo:
161
+ with gr.Tabs():
162
+ # -------- SPE --------
163
+ with gr.Tab("Single Point Energy"):
164
+ with gr.Row():
165
+ with gr.Column(scale=2):
166
+ gr.Markdown("# OrbMol — Quantum-Accurate Molecular Predictions")
167
+ gr.Markdown("**Supported formats:** .xyz, .pdb, .cif, .traj, .mol, .sdf")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
+ xyz_input = gr.File(
170
+ label="Upload Structure File",
171
+ file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"],
172
+ file_count="single"
173
+ )
174
+ task_name_spe = gr.Radio(
175
+ ["OMol", "OMat", "OMol-Direct"],
176
+ value="OMol",
177
+ label="Model Type"
178
+ )
179
+ with gr.Row():
180
+ charge_input = gr.Slider(-10, 10, 0, step=1, label="Charge")
181
+ spin_input = gr.Slider(1, 11, 1, step=1, label="Spin Multiplicity")
182
+
183
+ run_spe = gr.Button("Run OrbMol Prediction", variant="primary")
184
+
185
+ with gr.Column(variant="panel", min_width=500):
186
+ spe_out = gr.Textbox(label="Energy & Forces", lines=15, interactive=False)
187
+ spe_status = gr.Textbox(label="Status", interactive=False)
188
+
189
+ spe_viewer = Molecule3D(
190
+ label="Input Structure Viewer",
191
+ reps=DEFAULT_MOLECULAR_REPRESENTATIONS,
192
+ config=DEFAULT_MOLECULAR_SETTINGS
193
+ )
194
+
195
+ task_name_spe.change(
196
+ lambda x: (
197
+ gr.update(visible=x in ["OMol", "OMol-Direct"]),
198
+ gr.update(visible=x in ["OMol", "OMol-Direct"])
199
+ ),
200
+ [task_name_spe],
201
+ [charge_input, spin_input]
202
+ )
203
+
204
+ run_spe.click(
205
+ predict_molecule,
206
+ [xyz_input, task_name_spe, charge_input, spin_input],
207
+ [spe_out, spe_status, spe_viewer]
208
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
 
210
+ # -------- MD --------
211
+ with gr.Tab("Molecular Dynamics"):
212
+ with gr.Row():
213
+ with gr.Column(scale=2):
214
+ gr.Markdown("## Molecular Dynamics Simulation")
215
+
216
+ xyz_md = gr.File(
217
+ label="Upload Structure File",
218
+ file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"],
219
+ file_count="single"
220
+ )
221
+ task_name_md = gr.Radio(
222
+ ["OMol", "OMat", "OMol-Direct"],
223
+ value="OMol",
224
+ label="Model Type"
225
+ )
226
+ with gr.Row():
227
+ charge_md = gr.Slider(-10, 10, 0, step=1, label="Charge")
228
+ spin_md = gr.Slider(1, 11, 1, step=1, label="Spin Multiplicity")
229
+ with gr.Row():
230
+ steps_md = gr.Slider(10, 2000, 100, step=10, label="Steps")
231
+ temp_md = gr.Slider(10, 1500, 300, step=10, label="Temperature (K)")
232
+ with gr.Row():
233
+ timestep_md = gr.Slider(0.1, 5.0, 1.0, step=0.1, label="Timestep (fs)")
234
+ ensemble_md = gr.Radio(["NVE", "NVT"], value="NVE", label="Ensemble")
235
+ run_md_btn = gr.Button("Run MD Simulation", variant="primary")
236
 
237
+ with gr.Column(variant="panel", min_width=520):
238
+ md_status = gr.Textbox(label="MD Status", interactive=False)
239
+ md_traj = gr.File(label="Trajectory (.traj)", interactive=False)
240
+
241
+ md_viewer = Molecule3D(
242
+ label="MD Result Viewer",
243
+ reps=DEFAULT_MOLECULAR_REPRESENTATIONS,
244
+ config=DEFAULT_MOLECULAR_SETTINGS
245
+ )
246
+
247
+ md_log = gr.Textbox(label="Log", interactive=False, lines=15)
248
+ md_script = gr.Code(label="Reproduction Script", language="python", interactive=False, lines=20)
249
+ md_explain = gr.Markdown()
250
+
251
+ task_name_md.change(
252
+ lambda x: (
253
+ gr.update(visible=x in ["OMol", "OMol-Direct"]),
254
+ gr.update(visible=x in ["OMol", "OMol-Direct"])
255
+ ),
256
+ [task_name_md],
257
+ [charge_md, spin_md]
258
+ )
259
+
260
+ run_md_btn.click(
261
+ md_wrapper,
262
+ [xyz_md, task_name_md, charge_md, spin_md, steps_md, temp_md, timestep_md, ensemble_md],
263
+ [md_status, md_traj, md_log, md_script, md_explain, md_viewer]
264
+ )
265
 
266
+ # -------- Relax --------
267
+ with gr.Tab("Relaxation / Optimization"):
268
+ with gr.Row():
269
+ with gr.Column(scale=2):
270
+ gr.Markdown("## Structure Relaxation/Optimization")
271
+
272
+ xyz_rlx = gr.File(
273
+ label="Upload Structure File",
274
+ file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"],
275
+ file_count="single"
276
+ )
277
+ task_name_rlx = gr.Radio(
278
+ ["OMol", "OMat", "OMol-Direct"],
279
+ value="OMol",
280
+ label="Model Type"
281
+ )
282
+ with gr.Row():
283
+ steps_rlx = gr.Slider(1, 2000, 300, step=1, label="Max Steps")
284
+ fmax_rlx = gr.Slider(0.001, 0.5, 0.05, step=0.001, label="Fmax (eV/Å)")
285
+ with gr.Row():
286
+ charge_rlx = gr.Slider(-10, 10, 0, step=1, label="Charge")
287
+ spin_rlx = gr.Slider(1, 11, 1, step=1, label="Spin")
288
+ relax_cell = gr.Checkbox(False, label="Relax Unit Cell")
289
+ run_rlx_btn = gr.Button("Run Optimization", variant="primary")
290
 
291
+ with gr.Column(variant="panel", min_width=520):
292
+ rlx_status = gr.Textbox(label="Status", interactive=False)
293
+ rlx_traj = gr.File(label="Trajectory (.traj)", interactive=False)
294
+
295
+ rlx_viewer = Molecule3D(
296
+ label="Optimized Structure Viewer",
297
+ reps=DEFAULT_MOLECULAR_REPRESENTATIONS,
298
+ config=DEFAULT_MOLECULAR_SETTINGS
299
+ )
300
+
301
+ rlx_log = gr.Textbox(label="Log", interactive=False, lines=15)
302
+ rlx_script = gr.Code(label="Reproduction Script", language="python", interactive=False, lines=20)
303
+ rlx_explain = gr.Markdown()
304
 
305
+ task_name_rlx.change(
306
+ lambda x: (
307
+ gr.update(visible=x in ["OMol", "OMol-Direct"]),
308
+ gr.update(visible=x in ["OMol", "OMol-Direct"])
309
+ ),
310
+ [task_name_rlx],
311
+ [charge_rlx, spin_rlx]
312
+ )
313
+
314
+ run_rlx_btn.click(
315
+ relax_wrapper,
316
+ [xyz_rlx, task_name_rlx, steps_rlx, fmax_rlx, charge_rlx, spin_rlx, relax_cell],
317
+ [rlx_status, rlx_traj, rlx_log, rlx_script, rlx_explain, rlx_viewer]
318
+ )
319
 
320
  if __name__ == "__main__":
321
+ demo.launch(server_name="0.0.0.0", server_port=7860, show_error=True)