annabossler commited on
Commit
18b592b
verified
1 Parent(s): 8ac00e3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +129 -28
app.py CHANGED
@@ -7,8 +7,9 @@ from ase.io import read, write
7
  from ase.io.trajectory import Trajectory
8
  from gradio_molecule3d import Molecule3D
9
  import hashlib
 
10
 
11
- # ==== Molecule3D viewer preparation con debug ====
12
  def prepare_molecule_for_viewer(traj_path):
13
  """Convert trajectory to format compatible with Molecule3D viewer"""
14
  if not traj_path or not os.path.exists(traj_path):
@@ -24,25 +25,99 @@ def prepare_molecule_for_viewer(traj_path):
24
  # Debug info
25
  print(f"Preparing viewer: {len(traj)} frames, {len(traj[-1])} atoms")
26
 
27
- # Crear PDB temporal persistente (no se elimina autom谩ticamente)
28
- temp_pdb = tempfile.NamedTemporaryFile(suffix='.pdb', delete=False, mode='w')
 
29
 
30
- # Escribir contenido PDB
 
 
 
 
 
 
 
 
 
 
31
  atoms = traj[-1]
32
- write(temp_pdb.name, atoms, format='pdb')
33
- temp_pdb.close() # Cerrar el archivo para que se pueda leer
34
 
35
- # Verificar que el archivo se cre贸
36
- if os.path.exists(temp_pdb.name):
37
- file_size = os.path.getsize(temp_pdb.name)
38
- print(f"PDB created: {temp_pdb.name}, size: {file_size} bytes")
39
- return temp_pdb.name
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  else:
41
- print("PDB file was not created")
42
  return None
43
 
44
  except Exception as e:
45
  print(f"Error preparing molecule for viewer: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  return None
47
 
48
  # ==== OrbMol SPE ====
@@ -66,15 +141,15 @@ def predict_molecule(structure_file, charge=0, spin_multiplicity=1):
66
  try:
67
  calc = _load_orbmol_calc()
68
  if not structure_file:
69
- return "Error: Please upload a structure file", "Error"
70
 
71
  file_path = structure_file
72
 
73
  if not os.path.exists(file_path):
74
- return f"Error: File not found: {file_path}", "Error"
75
 
76
  if os.path.getsize(file_path) == 0:
77
- return f"Error: Empty file: {file_path}", "Error"
78
 
79
  atoms = read(file_path)
80
  atoms.info = {"charge": int(charge), "spin": int(spin_multiplicity)}
@@ -89,9 +164,12 @@ def predict_molecule(structure_file, charge=0, spin_multiplicity=1):
89
  max_force = float(np.max(np.linalg.norm(forces, axis=1)))
90
  lines += ["", f"Max Force: {max_force:.4f} eV/脜"]
91
 
92
- return "\n".join(lines), "Calculation completed with OrbMol"
 
 
 
93
  except Exception as e:
94
- return f"Error during calculation: {e}", "Error"
95
 
96
  # ==== Simulaciones (helpers) ====
97
  from simulation_scripts_orbmol import (
@@ -99,7 +177,7 @@ from simulation_scripts_orbmol import (
99
  run_relaxation_simulation,
100
  )
101
 
102
- # ==== Wrappers con debug ====
103
  def md_wrapper(structure_file, charge, spin, steps, tempK, timestep_fs, ensemble):
104
  try:
105
  if not structure_file:
@@ -111,7 +189,7 @@ def md_wrapper(structure_file, charge, spin, steps, tempK, timestep_fs, ensemble
111
  traj_path, log_text, script_text, explanation = run_md_simulation(
112
  file_path,
113
  int(steps),
114
- 20,
115
  float(timestep_fs),
116
  float(tempK),
117
  "NVT" if ensemble == "NVT" else "NVE",
@@ -122,14 +200,16 @@ def md_wrapper(structure_file, charge, spin, steps, tempK, timestep_fs, ensemble
122
 
123
  print(f"MD completed, trajectory: {traj_path}")
124
 
125
- # Preparar archivo PDB para el visor 3D
126
  pdb_file = prepare_molecule_for_viewer(traj_path)
127
- print(f"PDB file for viewer: {pdb_file}")
128
 
129
  return (status, traj_path, log_text, script_text, explanation, pdb_file)
130
 
131
  except Exception as e:
132
  print(f"MD Wrapper Error: {e}")
 
 
133
  return (f"Error: {e}", None, "", "", "", None)
134
 
135
  def relax_wrapper(structure_file, steps, fmax, charge, spin, relax_cell):
@@ -152,14 +232,16 @@ def relax_wrapper(structure_file, steps, fmax, charge, spin, relax_cell):
152
 
153
  print(f"Relaxation completed, trajectory: {traj_path}")
154
 
155
- # Preparar archivo PDB para el visor 3D
156
  pdb_file = prepare_molecule_for_viewer(traj_path)
157
- print(f"PDB file for viewer: {pdb_file}")
158
 
159
  return (status, traj_path, log_text, script_text, explanation, pdb_file)
160
 
161
  except Exception as e:
162
  print(f"Relax Wrapper Error: {e}")
 
 
163
  return (f"Error: {e}", None, "", "", "", None)
164
 
165
  # ==== UI ====
@@ -186,8 +268,27 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="OrbMol Demo") as demo:
186
  with gr.Column(variant="panel", min_width=500):
187
  spe_out = gr.Textbox(label="Energy & Forces", lines=15, interactive=False)
188
  spe_status = gr.Textbox(label="Status", interactive=False, max_lines=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
 
190
- run_spe.click(predict_molecule, [xyz_input, charge_input, spin_input], [spe_out, spe_status])
191
 
192
  # -------- MD --------
193
  with gr.Tab("Molecular Dynamics"):
@@ -217,9 +318,9 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="OrbMol Demo") as demo:
217
  md_status = gr.Textbox(label="MD Status", interactive=False)
218
  md_traj = gr.File(label="Trajectory (.traj)", interactive=False)
219
 
220
- # Molecule3D viewer con configuraciones adicionales
221
  md_viewer = Molecule3D(
222
- label="3D Structure Viewer",
223
  reps=[
224
  {
225
  "model": 0,
@@ -283,9 +384,9 @@ with gr.Blocks(theme=gr.themes.Ocean(), title="OrbMol Demo") as demo:
283
  rlx_status = gr.Textbox(label="Status", interactive=False)
284
  rlx_traj = gr.File(label="Trajectory (.traj)", interactive=False)
285
 
286
- # Molecule3D viewer con configuraciones adicionales
287
  rlx_viewer = Molecule3D(
288
- label="3D Structure Viewer",
289
  reps=[
290
  {
291
  "model": 0,
 
7
  from ase.io.trajectory import Trajectory
8
  from gradio_molecule3d import Molecule3D
9
  import hashlib
10
+ import shutil
11
 
12
+ # ==== Molecule3D viewer preparation CORREGIDO ====
13
  def prepare_molecule_for_viewer(traj_path):
14
  """Convert trajectory to format compatible with Molecule3D viewer"""
15
  if not traj_path or not os.path.exists(traj_path):
 
25
  # Debug info
26
  print(f"Preparing viewer: {len(traj)} frames, {len(traj[-1])} atoms")
27
 
28
+ # Crear directorio cache de Gradio si no existe
29
+ gradio_cache_dir = os.path.join(tempfile.gettempdir(), "gradio")
30
+ os.makedirs(gradio_cache_dir, exist_ok=True)
31
 
32
+ # Crear PDB temporal PERSISTENTE en el directorio cache de Gradio
33
+ unique_id = hashlib.md5(str(traj_path).encode() + str(os.path.getmtime(traj_path)).encode()).hexdigest()[:12]
34
+ pdb_filename = f"molecule_{unique_id}.pdb"
35
+ pdb_path = os.path.join(gradio_cache_dir, pdb_filename)
36
+
37
+ # Si ya existe, no lo recreamos
38
+ if os.path.exists(pdb_path) and os.path.getsize(pdb_path) > 0:
39
+ print(f"PDB already exists: {pdb_path}")
40
+ return pdb_path
41
+
42
+ # Tomar el 煤ltimo frame de la trayectoria
43
  atoms = traj[-1]
 
 
44
 
45
+ # Escribir PDB con elementos en min煤sculas (como requiere gradio_molecule3d)
46
+ try:
47
+ # Usar ASE para escribir PDB
48
+ write(pdb_path, atoms, format='pdb')
49
+
50
+ # Post-procesar para asegurar formato correcto
51
+ with open(pdb_path, 'r') as f:
52
+ content = f.read()
53
+
54
+ # Asegurar que los s铆mbolos de elementos est茅n en formato correcto
55
+ lines = content.split('\n')
56
+ processed_lines = []
57
+
58
+ for line in lines:
59
+ if line.startswith(('ATOM', 'HETATM')):
60
+ # Formato PDB: columnas espec铆ficas para elemento
61
+ processed_lines.append(line)
62
+ else:
63
+ processed_lines.append(line)
64
+
65
+ with open(pdb_path, 'w') as f:
66
+ f.write('\n'.join(processed_lines))
67
+
68
+ except Exception as write_error:
69
+ print(f"Error writing PDB: {write_error}")
70
+ return None
71
+
72
+ # Verificar que el archivo se cre贸 correctamente
73
+ if os.path.exists(pdb_path) and os.path.getsize(pdb_path) > 0:
74
+ file_size = os.path.getsize(pdb_path)
75
+ print(f"PDB created successfully: {pdb_path}, size: {file_size} bytes")
76
+
77
+ # Verificar contenido b谩sico del PDB
78
+ with open(pdb_path, 'r') as f:
79
+ first_lines = f.read(200)
80
+ print(f"PDB content preview: {first_lines[:100]}...")
81
+
82
+ return pdb_path
83
  else:
84
+ print("PDB file was not created properly")
85
  return None
86
 
87
  except Exception as e:
88
  print(f"Error preparing molecule for viewer: {e}")
89
+ import traceback
90
+ traceback.print_exc()
91
+ return None
92
+
93
+ # ==== Funci贸n para convertir archivo inicial a PDB para SPE ====
94
+ def prepare_input_for_viewer(structure_file):
95
+ """Convert input structure file to PDB for Molecule3D viewer"""
96
+ if not structure_file or not os.path.exists(structure_file):
97
+ return None
98
+
99
+ try:
100
+ atoms = read(structure_file)
101
+
102
+ # Crear directorio cache de Gradio si no existe
103
+ gradio_cache_dir = os.path.join(tempfile.gettempdir(), "gradio")
104
+ os.makedirs(gradio_cache_dir, exist_ok=True)
105
+
106
+ # Crear PDB para visualizaci贸n
107
+ unique_id = hashlib.md5(str(structure_file).encode()).hexdigest()[:12]
108
+ pdb_filename = f"input_{unique_id}.pdb"
109
+ pdb_path = os.path.join(gradio_cache_dir, pdb_filename)
110
+
111
+ write(pdb_path, atoms, format='pdb')
112
+
113
+ if os.path.exists(pdb_path) and os.path.getsize(pdb_path) > 0:
114
+ print(f"Input PDB created: {pdb_path}")
115
+ return pdb_path
116
+ else:
117
+ return None
118
+
119
+ except Exception as e:
120
+ print(f"Error preparing input for viewer: {e}")
121
  return None
122
 
123
  # ==== OrbMol SPE ====
 
141
  try:
142
  calc = _load_orbmol_calc()
143
  if not structure_file:
144
+ return "Error: Please upload a structure file", "Error", None
145
 
146
  file_path = structure_file
147
 
148
  if not os.path.exists(file_path):
149
+ return f"Error: File not found: {file_path}", "Error", None
150
 
151
  if os.path.getsize(file_path) == 0:
152
+ return f"Error: Empty file: {file_path}", "Error", None
153
 
154
  atoms = read(file_path)
155
  atoms.info = {"charge": int(charge), "spin": int(spin_multiplicity)}
 
164
  max_force = float(np.max(np.linalg.norm(forces, axis=1)))
165
  lines += ["", f"Max Force: {max_force:.4f} eV/脜"]
166
 
167
+ # Preparar PDB para visualizaci贸n
168
+ pdb_file = prepare_input_for_viewer(file_path)
169
+
170
+ return "\n".join(lines), "Calculation completed with OrbMol", pdb_file
171
  except Exception as e:
172
+ return f"Error during calculation: {e}", "Error", None
173
 
174
  # ==== Simulaciones (helpers) ====
175
  from simulation_scripts_orbmol import (
 
177
  run_relaxation_simulation,
178
  )
179
 
180
+ # ==== Wrappers con debug y Molecule3D ====
181
  def md_wrapper(structure_file, charge, spin, steps, tempK, timestep_fs, ensemble):
182
  try:
183
  if not structure_file:
 
189
  traj_path, log_text, script_text, explanation = run_md_simulation(
190
  file_path,
191
  int(steps),
192
+ 20, # pre-relax steps
193
  float(timestep_fs),
194
  float(tempK),
195
  "NVT" if ensemble == "NVT" else "NVE",
 
200
 
201
  print(f"MD completed, trajectory: {traj_path}")
202
 
203
+ # Preparar archivo PDB para el visor Molecule3D
204
  pdb_file = prepare_molecule_for_viewer(traj_path)
205
+ print(f"PDB file for Molecule3D: {pdb_file}")
206
 
207
  return (status, traj_path, log_text, script_text, explanation, pdb_file)
208
 
209
  except Exception as e:
210
  print(f"MD Wrapper Error: {e}")
211
+ import traceback
212
+ traceback.print_exc()
213
  return (f"Error: {e}", None, "", "", "", None)
214
 
215
  def relax_wrapper(structure_file, steps, fmax, charge, spin, relax_cell):
 
232
 
233
  print(f"Relaxation completed, trajectory: {traj_path}")
234
 
235
+ # Preparar archivo PDB para el visor Molecule3D
236
  pdb_file = prepare_molecule_for_viewer(traj_path)
237
+ print(f"PDB file for Molecule3D: {pdb_file}")
238
 
239
  return (status, traj_path, log_text, script_text, explanation, pdb_file)
240
 
241
  except Exception as e:
242
  print(f"Relax Wrapper Error: {e}")
243
+ import traceback
244
+ traceback.print_exc()
245
  return (f"Error: {e}", None, "", "", "", None)
246
 
247
  # ==== UI ====
 
268
  with gr.Column(variant="panel", min_width=500):
269
  spe_out = gr.Textbox(label="Energy & Forces", lines=15, interactive=False)
270
  spe_status = gr.Textbox(label="Status", interactive=False, max_lines=1)
271
+
272
+ # Viewer para SPE
273
+ spe_viewer = Molecule3D(
274
+ label="Input Structure Viewer",
275
+ reps=[
276
+ {
277
+ "model": 0,
278
+ "chain": "",
279
+ "resname": "",
280
+ "style": "stick",
281
+ "color": "whiteCarbon",
282
+ "residue_range": "",
283
+ "around": 0,
284
+ "byres": False,
285
+ "visible": True,
286
+ "opacity": 1.0
287
+ }
288
+ ]
289
+ )
290
 
291
+ run_spe.click(predict_molecule, [xyz_input, charge_input, spin_input], [spe_out, spe_status, spe_viewer])
292
 
293
  # -------- MD --------
294
  with gr.Tab("Molecular Dynamics"):
 
318
  md_status = gr.Textbox(label="MD Status", interactive=False)
319
  md_traj = gr.File(label="Trajectory (.traj)", interactive=False)
320
 
321
+ # Molecule3D viewer para MD
322
  md_viewer = Molecule3D(
323
+ label="Final Structure Viewer (Last MD Frame)",
324
  reps=[
325
  {
326
  "model": 0,
 
384
  rlx_status = gr.Textbox(label="Status", interactive=False)
385
  rlx_traj = gr.File(label="Trajectory (.traj)", interactive=False)
386
 
387
+ # Molecule3D viewer para Relaxation
388
  rlx_viewer = Molecule3D(
389
+ label="Optimized Structure Viewer",
390
  reps=[
391
  {
392
  "model": 0,