annabossler commited on
Commit
956ff48
·
verified ·
1 Parent(s): 8d596b7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -234
app.py CHANGED
@@ -9,7 +9,6 @@ from gradio_molecule3d import Molecule3D
9
  from simulation_scripts_orbmol import load_orbmol_model, run_md_simulation, run_relaxation_simulation
10
  import hashlib
11
 
12
- # ==== Configuración Molecule3D ====
13
  DEFAULT_MOLECULAR_REPRESENTATIONS = [
14
  {
15
  "model": 0,
@@ -39,50 +38,36 @@ DEFAULT_MOLECULAR_SETTINGS = {
39
  "disableFog": False,
40
  }
41
 
42
- # ==== Conversión a PDB para Molecule3D ====
43
  def convert_to_pdb_for_viewer(file_path):
44
- """Convierte cualquier archivo a PDB para Molecule3D"""
45
  if not file_path or not os.path.exists(file_path):
46
  return None
47
-
48
  try:
49
  atoms = read(file_path)
50
-
51
  cache_dir = os.path.join(tempfile.gettempdir(), "gradio")
52
  os.makedirs(cache_dir, exist_ok=True)
53
-
54
  pdb_path = os.path.join(cache_dir, f"mol_{hashlib.md5(file_path.encode()).hexdigest()[:12]}.pdb")
55
-
56
  write(pdb_path, atoms, format="proteindatabank")
57
-
58
  return pdb_path
59
  except Exception as e:
60
  print(f"Error converting to PDB: {e}")
61
  return None
62
 
63
- # ==== OrbMol SPE ====
64
  def predict_molecule(structure_file, task_name, charge=0, spin_multiplicity=1):
65
- """Single Point Energy + fuerzas (OrbMol)"""
66
  try:
67
  calc = load_orbmol_model(task_name)
68
  if not structure_file:
69
  return "Error: Please upload a structure file", "Error", None
70
-
71
  file_path = structure_file
72
  if not os.path.exists(file_path):
73
  return f"Error: File not found: {file_path}", "Error", None
74
  if os.path.getsize(file_path) == 0:
75
  return f"Error: Empty file: {file_path}", "Error", None
76
-
77
  atoms = read(file_path)
78
-
79
  if task_name in ["OMol", "OMol-Direct"]:
80
  atoms.info = {"charge": int(charge), "spin": int(spin_multiplicity)}
81
-
82
  atoms.calc = calc
83
  energy = atoms.get_potential_energy()
84
  forces = atoms.get_forces()
85
-
86
  lines = [
87
  f"Model: {task_name}",
88
  f"Total Energy: {energy:.6f} eV",
@@ -93,22 +78,17 @@ def predict_molecule(structure_file, task_name, charge=0, spin_multiplicity=1):
93
  lines.append(f"Atom {i+1}: [{fc[0]:.4f}, {fc[1]:.4f}, {fc[2]:.4f}] eV/Å")
94
  max_force = float(np.max(np.linalg.norm(forces, axis=1)))
95
  lines += ["", f"Max Force: {max_force:.4f} eV/Å"]
96
-
97
  pdb_file = convert_to_pdb_for_viewer(file_path)
98
-
99
  return "\n".join(lines), f"Calculation completed with {task_name}", pdb_file
100
-
101
  except Exception as e:
102
  import traceback
103
  traceback.print_exc()
104
  return f"Error during calculation: {e}", "Error", None
105
 
106
- # ==== Wrappers MD y Relax ====
107
  def md_wrapper(structure_file, task_name, charge, spin, steps, tempK, timestep_fs, ensemble):
108
  try:
109
  if not structure_file:
110
  return ("Error: Please upload a structure file", None, "", "", "", None)
111
-
112
  traj_path, log_text, script_text, explanation = run_md_simulation(
113
  structure_file,
114
  int(steps),
@@ -121,11 +101,8 @@ def md_wrapper(structure_file, task_name, charge, spin, steps, tempK, timestep_f
121
  int(spin),
122
  )
123
  status = f"MD completed: {int(steps)} steps at {int(tempK)} K ({ensemble})"
124
-
125
  pdb_file = convert_to_pdb_for_viewer(traj_path)
126
-
127
  return (status, traj_path, log_text, script_text, explanation, pdb_file)
128
-
129
  except Exception as e:
130
  import traceback
131
  traceback.print_exc()
@@ -135,7 +112,6 @@ def relax_wrapper(structure_file, task_name, steps, fmax, charge, spin, relax_ce
135
  try:
136
  if not structure_file:
137
  return ("Error: Please upload a structure file", None, "", "", "", None)
138
-
139
  traj_path, log_text, script_text, explanation = run_relaxation_simulation(
140
  structure_file,
141
  int(steps),
@@ -146,178 +122,59 @@ def relax_wrapper(structure_file, task_name, steps, fmax, charge, spin, relax_ce
146
  bool(relax_cell),
147
  )
148
  status = f"Relaxation finished (<={int(steps)} steps, fmax={float(fmax)} eV/Å)"
149
-
150
  pdb_file = convert_to_pdb_for_viewer(traj_path)
151
-
152
  return (status, traj_path, log_text, script_text, explanation, pdb_file)
153
-
154
  except Exception as e:
155
  import traceback
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
- # -------- HOME TAB --------
163
  with gr.Tab("Home"):
164
- with gr.Row():
165
- # Columna izquierda con acordeones
166
- with gr.Column(scale=1):
167
- gr.Markdown("## Learn more about OrbMol")
168
-
169
- with gr.Accordion("What is OrbMol?", open=False):
170
- gr.Markdown("""
171
- 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 at the level of advanced quantum chemistry methods.
172
-
173
- The models combine the transferability of universal potentials with quantum-level accuracy, making them suitable for a wide range of applications in chemistry, materials science, and drug discovery.
174
- """)
175
-
176
- with gr.Accordion("Available Models", open=False):
177
- gr.Markdown("""
178
- **OMol** and **OMol-Direct**
179
- - **Training dataset**: OMol25 (>100M calculations on small molecules, biomolecules, metal complexes, and electrolytes)
180
- - **Level of theory**: ωB97M-V/def2-TZVPD with non-local dispersion; solvation treated explicitly
181
- - **Inputs**: total charge & spin multiplicity
182
- - **Applications**: biology, organic chemistry, protein folding, small-molecule drugs, organic liquids, homogeneous catalysis
183
- - **Caveats**: trained only on aperiodic systems → periodic/inorganic cases may not work well
184
- - **Difference**: OMol enforces energy–force consistency; OMol-Direct relaxes this for efficiency
185
-
186
- **OMat**
187
- - **Training dataset**: OMat24 (>100M inorganic calculations, from Materials Project, Alexandria, and far-from-equilibrium samples)
188
- - **Level of theory**: PBE/PBE+U with Materials Project settings; VASP 54 pseudopotentials; no dispersion
189
- - **Inputs**: No support for spin and charge. Spin polarization included but magnetic state cannot be selected
190
- - **Applications**: inorganic discovery, photovoltaics, alloys, superconductors, electronic/optical materials
191
- - **Caveats**: magnetic effects may be incompletely captured
192
- """)
193
-
194
- with gr.Accordion("Supported File Formats", open=False):
195
- gr.Markdown("""
196
- OrbMol supports the following molecular structure formats:
197
- - `.xyz` - XYZ coordinate files
198
- - `.pdb` - Protein Data Bank format
199
- - `.cif` - Crystallographic Information File
200
- - `.traj` - ASE trajectory format
201
- - `.mol` - MDL Molfile
202
- - `.sdf` - Structure Data File
203
-
204
- All formats are automatically converted internally for processing.
205
- """)
206
-
207
- with gr.Accordion("How to Use", open=False):
208
- gr.Markdown("""
209
- **Single Point Energy**: Upload a molecular structure and select a model to calculate energies and forces.
210
-
211
- **Molecular Dynamics**: Run time-dependent simulations to observe molecular behavior at different temperatures and conditions.
212
-
213
- **Relaxation/Optimization**: Find the minimum-energy configuration of your molecular structure.
214
-
215
- Each tab provides specific parameters you can adjust to customize your calculations.
216
- """)
217
-
218
- with gr.Accordion("Technical Foundation", open=False):
219
- gr.Markdown("""
220
- All models are based on the **Orb-v3 architecture**, the latest generation of Orb universal interatomic potentials.
221
-
222
- Key features:
223
- - Graph neural network architecture
224
- - Equivariant message passing
225
- - Multi-task learning across different quantum chemistry methods
226
- - Billions of training examples across diverse chemical spaces
227
- - Sub-kcal/mol accuracy on test sets
228
- """)
229
-
230
- with gr.Accordion("Resources & Support", open=False):
231
- gr.Markdown("""
232
- - [Orb-v3 paper](https://arxiv.org/abs/2504.06231)
233
- - [Orb-Models GitHub repository](https://github.com/orbital-materials/orb-models)
234
- - For issues/questions, please open a GitHub issue or contact the developers
235
-
236
- **Citation**: If you use OrbMol in your research, please cite the Orb-v3 paper and the relevant dataset papers (OMol25/OMat24).
237
- """)
238
-
239
- # Columna derecha con contenido principal
240
- with gr.Column(scale=2):
241
- gr.Image("logo_color_text.png",
242
- show_share_button=False,
243
- show_download_button=False,
244
- show_label=False,
245
- show_fullscreen_button=False)
246
-
247
- gr.Markdown("# OrbMol — Quantum-Accurate Molecular Predictions")
248
-
249
- gr.Markdown("""
250
- Welcome to the OrbMol demo! This interactive platform allows you to explore the capabilities of our quantum-accurate machine learning models for molecular simulations.
251
 
252
- ## Quick Start
253
-
254
- Use the tabs above to access different functionalities:
255
-
256
- 1. **Single Point Energy**: Calculate energies and forces for a given molecular structure
257
- 2. **Molecular Dynamics**: Run MD simulations using OrbMol-trained potentials
258
- 3. **Relaxation / Optimization**: Optimize molecular structures to their minimum-energy configurations
259
-
260
- Simply upload a molecular structure file in any supported format (`.xyz`, `.pdb`, `.cif`, `.traj`, `.mol`, `.sdf`) and select the appropriate model for your system.
261
-
262
- ## Model Selection Guide
263
-
264
- **Choose OMol/OMol-Direct for:**
265
- - Organic molecules and biomolecules
266
- - Drug-like compounds
267
- - Metal-organic complexes
268
- - Molecules in solution
269
- - Systems where you need to specify charge and spin
270
-
271
- **Choose OMat for:**
272
- - Inorganic crystals and materials
273
- - Periodic systems
274
- - Bulk materials and alloys
275
- - Solid-state compounds
276
-
277
- Explore the accordions on the left to learn more about each model's capabilities, training data, and limitations.
278
- """)
279
-
280
- gr.Markdown("## Try an Example")
281
- gr.Markdown("""
282
- To get started quickly, navigate to any of the calculation tabs above and try one of these examples:
283
- - **Single Point Energy**: Upload a small molecule to see energy and force predictions
284
- - **Molecular Dynamics**: Run a short simulation at 300K to observe thermal motion
285
- - **Relaxation**: Optimize a distorted structure to find its equilibrium geometry
286
- """)
287
-
288
- # -------- SPE --------
289
  with gr.Tab("Single Point Energy"):
290
  with gr.Row():
291
  with gr.Column(scale=2):
292
  gr.Markdown("# OrbMol — Quantum-Accurate Molecular Predictions")
293
  gr.Markdown("**Supported formats:** .xyz, .pdb, .cif, .traj, .mol, .sdf")
294
-
295
- xyz_input = gr.File(
296
- label="Upload Structure File",
297
- file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"],
298
- file_count="single"
299
- )
300
- task_name_spe = gr.Radio(
301
- ["OMol", "OMat", "OMol-Direct"],
302
- value="OMol",
303
- label="Model Type"
304
- )
305
  with gr.Row():
306
  charge_input = gr.Slider(-10, 10, 0, step=1, label="Charge")
307
  spin_input = gr.Slider(1, 11, 1, step=1, label="Spin Multiplicity")
308
-
309
  run_spe = gr.Button("Run OrbMol Prediction", variant="primary")
310
-
311
  with gr.Column(variant="panel", min_width=500):
312
  spe_out = gr.Textbox(label="Energy & Forces", lines=15, interactive=False)
313
  spe_status = gr.Textbox(label="Status", interactive=False)
314
-
315
- spe_viewer = Molecule3D(
316
- label="Input Structure Viewer",
317
- reps=DEFAULT_MOLECULAR_REPRESENTATIONS,
318
- config=DEFAULT_MOLECULAR_SETTINGS
319
- )
320
-
321
  task_name_spe.change(
322
  lambda x: (
323
  gr.update(visible=x in ["OMol", "OMol-Direct"]),
@@ -326,29 +183,14 @@ To get started quickly, navigate to any of the calculation tabs above and try on
326
  [task_name_spe],
327
  [charge_input, spin_input]
328
  )
329
-
330
- run_spe.click(
331
- predict_molecule,
332
- [xyz_input, task_name_spe, charge_input, spin_input],
333
- [spe_out, spe_status, spe_viewer]
334
- )
335
 
336
- # -------- MD --------
337
  with gr.Tab("Molecular Dynamics"):
338
  with gr.Row():
339
  with gr.Column(scale=2):
340
  gr.Markdown("## Molecular Dynamics Simulation")
341
-
342
- xyz_md = gr.File(
343
- label="Upload Structure File",
344
- file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"],
345
- file_count="single"
346
- )
347
- task_name_md = gr.Radio(
348
- ["OMol", "OMat", "OMol-Direct"],
349
- value="OMol",
350
- label="Model Type"
351
- )
352
  with gr.Row():
353
  charge_md = gr.Slider(-10, 10, 0, step=1, label="Charge")
354
  spin_md = gr.Slider(1, 11, 1, step=1, label="Spin Multiplicity")
@@ -359,21 +201,13 @@ To get started quickly, navigate to any of the calculation tabs above and try on
359
  timestep_md = gr.Slider(0.1, 5.0, 1.0, step=0.1, label="Timestep (fs)")
360
  ensemble_md = gr.Radio(["NVE", "NVT"], value="NVE", label="Ensemble")
361
  run_md_btn = gr.Button("Run MD Simulation", variant="primary")
362
-
363
  with gr.Column(variant="panel", min_width=520):
364
  md_status = gr.Textbox(label="MD Status", interactive=False)
365
  md_traj = gr.File(label="Trajectory (.traj)", interactive=False)
366
-
367
- md_viewer = Molecule3D(
368
- label="MD Result Viewer",
369
- reps=DEFAULT_MOLECULAR_REPRESENTATIONS,
370
- config=DEFAULT_MOLECULAR_SETTINGS
371
- )
372
-
373
  md_log = gr.Textbox(label="Log", interactive=False, lines=15)
374
  md_script = gr.Code(label="Reproduction Script", language="python", interactive=False, lines=20)
375
  md_explain = gr.Markdown()
376
-
377
  task_name_md.change(
378
  lambda x: (
379
  gr.update(visible=x in ["OMol", "OMol-Direct"]),
@@ -382,29 +216,14 @@ To get started quickly, navigate to any of the calculation tabs above and try on
382
  [task_name_md],
383
  [charge_md, spin_md]
384
  )
385
-
386
- run_md_btn.click(
387
- md_wrapper,
388
- [xyz_md, task_name_md, charge_md, spin_md, steps_md, temp_md, timestep_md, ensemble_md],
389
- [md_status, md_traj, md_log, md_script, md_explain, md_viewer]
390
- )
391
 
392
- # -------- Relax --------
393
  with gr.Tab("Relaxation / Optimization"):
394
  with gr.Row():
395
  with gr.Column(scale=2):
396
  gr.Markdown("## Structure Relaxation/Optimization")
397
-
398
- xyz_rlx = gr.File(
399
- label="Upload Structure File",
400
- file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"],
401
- file_count="single"
402
- )
403
- task_name_rlx = gr.Radio(
404
- ["OMol", "OMat", "OMol-Direct"],
405
- value="OMol",
406
- label="Model Type"
407
- )
408
  with gr.Row():
409
  steps_rlx = gr.Slider(1, 2000, 300, step=1, label="Max Steps")
410
  fmax_rlx = gr.Slider(0.001, 0.5, 0.05, step=0.001, label="Fmax (eV/Å)")
@@ -413,21 +232,13 @@ To get started quickly, navigate to any of the calculation tabs above and try on
413
  spin_rlx = gr.Slider(1, 11, 1, step=1, label="Spin")
414
  relax_cell = gr.Checkbox(False, label="Relax Unit Cell")
415
  run_rlx_btn = gr.Button("Run Optimization", variant="primary")
416
-
417
  with gr.Column(variant="panel", min_width=520):
418
  rlx_status = gr.Textbox(label="Status", interactive=False)
419
  rlx_traj = gr.File(label="Trajectory (.traj)", interactive=False)
420
-
421
- rlx_viewer = Molecule3D(
422
- label="Optimized Structure Viewer",
423
- reps=DEFAULT_MOLECULAR_REPRESENTATIONS,
424
- config=DEFAULT_MOLECULAR_SETTINGS
425
- )
426
-
427
  rlx_log = gr.Textbox(label="Log", interactive=False, lines=15)
428
  rlx_script = gr.Code(label="Reproduction Script", language="python", interactive=False, lines=20)
429
  rlx_explain = gr.Markdown()
430
-
431
  task_name_rlx.change(
432
  lambda x: (
433
  gr.update(visible=x in ["OMol", "OMol-Direct"]),
@@ -436,12 +247,7 @@ To get started quickly, navigate to any of the calculation tabs above and try on
436
  [task_name_rlx],
437
  [charge_rlx, spin_rlx]
438
  )
439
-
440
- run_rlx_btn.click(
441
- relax_wrapper,
442
- [xyz_rlx, task_name_rlx, steps_rlx, fmax_rlx, charge_rlx, spin_rlx, relax_cell],
443
- [rlx_status, rlx_traj, rlx_log, rlx_script, rlx_explain, rlx_viewer]
444
- )
445
 
446
  if __name__ == "__main__":
447
- demo.launch(server_name="0.0.0.0", server_port=7860, show_error=True)
 
9
  from simulation_scripts_orbmol import load_orbmol_model, run_md_simulation, run_relaxation_simulation
10
  import hashlib
11
 
 
12
  DEFAULT_MOLECULAR_REPRESENTATIONS = [
13
  {
14
  "model": 0,
 
38
  "disableFog": False,
39
  }
40
 
 
41
  def convert_to_pdb_for_viewer(file_path):
 
42
  if not file_path or not os.path.exists(file_path):
43
  return None
 
44
  try:
45
  atoms = read(file_path)
 
46
  cache_dir = os.path.join(tempfile.gettempdir(), "gradio")
47
  os.makedirs(cache_dir, exist_ok=True)
 
48
  pdb_path = os.path.join(cache_dir, f"mol_{hashlib.md5(file_path.encode()).hexdigest()[:12]}.pdb")
 
49
  write(pdb_path, atoms, format="proteindatabank")
 
50
  return pdb_path
51
  except Exception as e:
52
  print(f"Error converting to PDB: {e}")
53
  return None
54
 
 
55
  def predict_molecule(structure_file, task_name, charge=0, spin_multiplicity=1):
 
56
  try:
57
  calc = load_orbmol_model(task_name)
58
  if not structure_file:
59
  return "Error: Please upload a structure file", "Error", None
 
60
  file_path = structure_file
61
  if not os.path.exists(file_path):
62
  return f"Error: File not found: {file_path}", "Error", None
63
  if os.path.getsize(file_path) == 0:
64
  return f"Error: Empty file: {file_path}", "Error", None
 
65
  atoms = read(file_path)
 
66
  if task_name in ["OMol", "OMol-Direct"]:
67
  atoms.info = {"charge": int(charge), "spin": int(spin_multiplicity)}
 
68
  atoms.calc = calc
69
  energy = atoms.get_potential_energy()
70
  forces = atoms.get_forces()
 
71
  lines = [
72
  f"Model: {task_name}",
73
  f"Total Energy: {energy:.6f} eV",
 
78
  lines.append(f"Atom {i+1}: [{fc[0]:.4f}, {fc[1]:.4f}, {fc[2]:.4f}] eV/Å")
79
  max_force = float(np.max(np.linalg.norm(forces, axis=1)))
80
  lines += ["", f"Max Force: {max_force:.4f} eV/Å"]
 
81
  pdb_file = convert_to_pdb_for_viewer(file_path)
 
82
  return "\n".join(lines), f"Calculation completed with {task_name}", pdb_file
 
83
  except Exception as e:
84
  import traceback
85
  traceback.print_exc()
86
  return f"Error during calculation: {e}", "Error", None
87
 
 
88
  def md_wrapper(structure_file, task_name, charge, spin, steps, tempK, timestep_fs, ensemble):
89
  try:
90
  if not structure_file:
91
  return ("Error: Please upload a structure file", None, "", "", "", None)
 
92
  traj_path, log_text, script_text, explanation = run_md_simulation(
93
  structure_file,
94
  int(steps),
 
101
  int(spin),
102
  )
103
  status = f"MD completed: {int(steps)} steps at {int(tempK)} K ({ensemble})"
 
104
  pdb_file = convert_to_pdb_for_viewer(traj_path)
 
105
  return (status, traj_path, log_text, script_text, explanation, pdb_file)
 
106
  except Exception as e:
107
  import traceback
108
  traceback.print_exc()
 
112
  try:
113
  if not structure_file:
114
  return ("Error: Please upload a structure file", None, "", "", "", None)
 
115
  traj_path, log_text, script_text, explanation = run_relaxation_simulation(
116
  structure_file,
117
  int(steps),
 
122
  bool(relax_cell),
123
  )
124
  status = f"Relaxation finished (<={int(steps)} steps, fmax={float(fmax)} eV/Å)"
 
125
  pdb_file = convert_to_pdb_for_viewer(traj_path)
 
126
  return (status, traj_path, log_text, script_text, explanation, pdb_file)
 
127
  except Exception as e:
128
  import traceback
129
  traceback.print_exc()
130
  return (f"Error: {e}", None, "", "", "", None)
131
 
 
132
  with gr.Blocks(theme=gr.themes.Ocean(), title="OrbMol Demo") as demo:
133
  with gr.Tabs():
 
134
  with gr.Tab("Home"):
135
+ gr.Image("logo_color_text.png", show_share_button=False, show_download_button=False, show_label=False, show_fullscreen_button=False)
136
+ gr.Markdown("# OrbMol Quantum-Accurate Molecular Predictions")
137
+ gr.Markdown("Welcome to the OrbMol demo! Use the tabs above to access different functionalities:")
138
+ gr.Markdown("1. **Single Point Energy**: Calculate energies and forces for a given molecular structure.")
139
+ gr.Markdown("2. **Molecular Dynamics**: Run MD simulations using OrbMol-trained potentials.")
140
+ gr.Markdown("3. **Relaxation / Optimization**: Optimize molecular structures to their minimum-energy configurations.")
141
+ gr.Markdown("Supported file formats: `.xyz`, `.pdb`, `.cif`, `.traj`, `.mol`, `.sdf`.")
142
+ gr.Markdown("## Pretrained Models")
143
+ gr.Markdown("**OMol** and **OMol-Direct**")
144
+ gr.Markdown("- **Training dataset**: OMol25 (>100M calculations on small molecules, biomolecules, metal complexes, and electrolytes).")
145
+ gr.Markdown("- **Level of theory**: wB97M-V/def2-TZVPD with non-local dispersion; solvation treated explicitly.")
146
+ gr.Markdown("- **Inputs**: total charge & spin multiplicity.")
147
+ gr.Markdown("- **Applications**: biology, organic chemistry, protein folding, small-molecule drugs, organic liquids, homogeneous catalysis.")
148
+ gr.Markdown("- **Caveats**: trained only on aperiodic systems → periodic/inorganic cases may not work well.")
149
+ gr.Markdown("- **Difference**: OMol enforces energy–force consistency; OMol-Direct relaxes this for efficiency.")
150
+ gr.Markdown("**OMat**")
151
+ gr.Markdown("- **Training dataset**: OMat24 (>100M inorganic calculations, from Materials Project, Alexandria, and far-from-equilibrium samples).")
152
+ gr.Markdown("- **Level of theory**: PBE/PBE+U with Materials Project settings; VASP 54 pseudopotentials; no dispersion.")
153
+ gr.Markdown("- **Inputs**: No support for spin and charge. Spin polarization included but magnetic state cannot be selected.")
154
+ gr.Markdown("- **Applications**: inorganic discovery, photovoltaics, alloys, superconductors, electronic/optical materials.")
155
+ gr.Markdown("- **Caveats**: magnetic effects may be incompletely captured.")
156
+ gr.Markdown("## Technical Foundation")
157
+ gr.Markdown("All models are based on the **Orb-v3 architecture**, the latest generation of Orb universal interatomic potentials, combining transferability with quantum-level accuracy.")
158
+ gr.Markdown("## Resources & Support")
159
+ gr.Markdown("- [Orb-v3 paper](https://arxiv.org/abs/2504.06231)")
160
+ gr.Markdown("- [Orb-Models GitHub repository](https://github.com/orbital-materials/orb-models)")
161
+ gr.Markdown("- For issues/questions, please open a GitHub issue or contact the developers.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ xyz_input = gr.File(label="Upload Structure File", file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"], file_count="single")
169
+ task_name_spe = gr.Radio(["OMol", "OMat", "OMol-Direct"], value="OMol", label="Model Type")
 
 
 
 
 
 
 
 
 
170
  with gr.Row():
171
  charge_input = gr.Slider(-10, 10, 0, step=1, label="Charge")
172
  spin_input = gr.Slider(1, 11, 1, step=1, label="Spin Multiplicity")
 
173
  run_spe = gr.Button("Run OrbMol Prediction", variant="primary")
 
174
  with gr.Column(variant="panel", min_width=500):
175
  spe_out = gr.Textbox(label="Energy & Forces", lines=15, interactive=False)
176
  spe_status = gr.Textbox(label="Status", interactive=False)
177
+ spe_viewer = Molecule3D(label="Input Structure Viewer", reps=DEFAULT_MOLECULAR_REPRESENTATIONS, config=DEFAULT_MOLECULAR_SETTINGS)
 
 
 
 
 
 
178
  task_name_spe.change(
179
  lambda x: (
180
  gr.update(visible=x in ["OMol", "OMol-Direct"]),
 
183
  [task_name_spe],
184
  [charge_input, spin_input]
185
  )
186
+ run_spe.click(predict_molecule, [xyz_input, task_name_spe, charge_input, spin_input], [spe_out, spe_status, spe_viewer])
 
 
 
 
 
187
 
 
188
  with gr.Tab("Molecular Dynamics"):
189
  with gr.Row():
190
  with gr.Column(scale=2):
191
  gr.Markdown("## Molecular Dynamics Simulation")
192
+ xyz_md = gr.File(label="Upload Structure File", file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"], file_count="single")
193
+ task_name_md = gr.Radio(["OMol", "OMat", "OMol-Direct"], value="OMol", label="Model Type")
 
 
 
 
 
 
 
 
 
194
  with gr.Row():
195
  charge_md = gr.Slider(-10, 10, 0, step=1, label="Charge")
196
  spin_md = gr.Slider(1, 11, 1, step=1, label="Spin Multiplicity")
 
201
  timestep_md = gr.Slider(0.1, 5.0, 1.0, step=0.1, label="Timestep (fs)")
202
  ensemble_md = gr.Radio(["NVE", "NVT"], value="NVE", label="Ensemble")
203
  run_md_btn = gr.Button("Run MD Simulation", variant="primary")
 
204
  with gr.Column(variant="panel", min_width=520):
205
  md_status = gr.Textbox(label="MD Status", interactive=False)
206
  md_traj = gr.File(label="Trajectory (.traj)", interactive=False)
207
+ md_viewer = Molecule3D(label="MD Result Viewer", reps=DEFAULT_MOLECULAR_REPRESENTATIONS, config=DEFAULT_MOLECULAR_SETTINGS)
 
 
 
 
 
 
208
  md_log = gr.Textbox(label="Log", interactive=False, lines=15)
209
  md_script = gr.Code(label="Reproduction Script", language="python", interactive=False, lines=20)
210
  md_explain = gr.Markdown()
 
211
  task_name_md.change(
212
  lambda x: (
213
  gr.update(visible=x in ["OMol", "OMol-Direct"]),
 
216
  [task_name_md],
217
  [charge_md, spin_md]
218
  )
219
+ run_md_btn.click(md_wrapper, [xyz_md, task_name_md, charge_md, spin_md, steps_md, temp_md, timestep_md, ensemble_md], [md_status, md_traj, md_log, md_script, md_explain, md_viewer])
 
 
 
 
 
220
 
 
221
  with gr.Tab("Relaxation / Optimization"):
222
  with gr.Row():
223
  with gr.Column(scale=2):
224
  gr.Markdown("## Structure Relaxation/Optimization")
225
+ xyz_rlx = gr.File(label="Upload Structure File", file_types=[".xyz", ".pdb", ".cif", ".traj", ".mol", ".sdf"], file_count="single")
226
+ task_name_rlx = gr.Radio(["OMol", "OMat", "OMol-Direct"], value="OMol", label="Model Type")
 
 
 
 
 
 
 
 
 
227
  with gr.Row():
228
  steps_rlx = gr.Slider(1, 2000, 300, step=1, label="Max Steps")
229
  fmax_rlx = gr.Slider(0.001, 0.5, 0.05, step=0.001, label="Fmax (eV/Å)")
 
232
  spin_rlx = gr.Slider(1, 11, 1, step=1, label="Spin")
233
  relax_cell = gr.Checkbox(False, label="Relax Unit Cell")
234
  run_rlx_btn = gr.Button("Run Optimization", variant="primary")
 
235
  with gr.Column(variant="panel", min_width=520):
236
  rlx_status = gr.Textbox(label="Status", interactive=False)
237
  rlx_traj = gr.File(label="Trajectory (.traj)", interactive=False)
238
+ rlx_viewer = Molecule3D(label="Optimized Structure Viewer", reps=DEFAULT_MOLECULAR_REPRESENTATIONS, config=DEFAULT_MOLECULAR_SETTINGS)
 
 
 
 
 
 
239
  rlx_log = gr.Textbox(label="Log", interactive=False, lines=15)
240
  rlx_script = gr.Code(label="Reproduction Script", language="python", interactive=False, lines=20)
241
  rlx_explain = gr.Markdown()
 
242
  task_name_rlx.change(
243
  lambda x: (
244
  gr.update(visible=x in ["OMol", "OMol-Direct"]),
 
247
  [task_name_rlx],
248
  [charge_rlx, spin_rlx]
249
  )
250
+ run_rlx_btn.click(relax_wrapper, [xyz_rlx, task_name_rlx, steps_rlx, fmax_rlx, charge_rlx, spin_rlx, relax_cell], [rlx_status, rlx_traj, rlx_log, rlx_script, rlx_explain, rlx_viewer])
 
 
 
 
 
251
 
252
  if __name__ == "__main__":
253
+ demo.launch(server_name="0.0.0.0", server_port=7860, show_error=True)