Spaces:
Running
Running
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +142 -65
src/streamlit_app.py
CHANGED
|
@@ -1293,81 +1293,158 @@ if atoms is not None:
|
|
| 1293 |
show_optimized_structure_download_button()
|
| 1294 |
os.unlink(tmp_filepath_opt)
|
| 1295 |
|
| 1296 |
-
# Convert trajectory to XYZ for download
|
| 1297 |
-
@st.fragment
|
| 1298 |
-
def show_trajectory():
|
| 1299 |
-
|
| 1300 |
-
|
| 1301 |
-
|
| 1302 |
-
|
| 1303 |
-
|
| 1304 |
|
| 1305 |
-
|
| 1306 |
-
|
| 1307 |
-
|
| 1308 |
|
| 1309 |
-
|
| 1310 |
-
|
| 1311 |
-
|
| 1312 |
-
|
| 1313 |
|
| 1314 |
-
|
| 1315 |
-
|
| 1316 |
-
|
| 1317 |
-
|
| 1318 |
-
|
| 1319 |
-
|
| 1320 |
-
|
| 1321 |
-
|
| 1322 |
-
|
| 1323 |
-
|
| 1324 |
-
|
| 1325 |
-
|
| 1326 |
-
|
| 1327 |
-
|
| 1328 |
|
| 1329 |
-
|
| 1330 |
-
|
| 1331 |
-
|
| 1332 |
|
| 1333 |
-
|
| 1334 |
-
|
| 1335 |
-
|
| 1336 |
-
|
| 1337 |
-
|
| 1338 |
-
|
| 1339 |
|
| 1340 |
-
|
| 1341 |
-
|
| 1342 |
-
|
| 1343 |
-
|
| 1344 |
-
|
| 1345 |
-
|
| 1346 |
-
|
| 1347 |
|
| 1348 |
-
|
| 1349 |
-
|
| 1350 |
-
|
| 1351 |
-
|
| 1352 |
-
|
| 1353 |
-
|
| 1354 |
-
|
| 1355 |
-
|
| 1356 |
-
|
| 1357 |
-
|
| 1358 |
-
|
| 1359 |
-
|
| 1360 |
-
|
| 1361 |
-
|
| 1362 |
-
|
| 1363 |
|
| 1364 |
-
|
| 1365 |
-
|
| 1366 |
|
| 1367 |
-
|
| 1368 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1369 |
|
| 1370 |
-
show_trajectory()
|
| 1371 |
except Exception as e:
|
| 1372 |
st.error(f"🔴 Calculation error: {str(e)}")
|
| 1373 |
st.error("Please check the structure, model compatibility, and parameters. For FairChem UMA, ensure the task type (omol, omat etc.) is appropriate for your system (e.g. omol for molecules, omat for materials).")
|
|
|
|
| 1293 |
show_optimized_structure_download_button()
|
| 1294 |
os.unlink(tmp_filepath_opt)
|
| 1295 |
|
| 1296 |
+
# # Convert trajectory to XYZ for download
|
| 1297 |
+
# @st.fragment
|
| 1298 |
+
# def show_trajectory():
|
| 1299 |
+
# if os.path.exists(traj_filename):
|
| 1300 |
+
# try:
|
| 1301 |
+
# from ase.io import read
|
| 1302 |
+
# from ase.visualize import view
|
| 1303 |
+
# import py3Dmol
|
| 1304 |
|
| 1305 |
+
# trajectory = read(traj_filename, index=':')
|
| 1306 |
+
# st.markdown("### Optimization Trajectory")
|
| 1307 |
+
# st.write(f"Captured {len(trajectory)} optimization steps")
|
| 1308 |
|
| 1309 |
+
# # Store the trajectory in session state
|
| 1310 |
+
# if "traj_frames" not in st.session_state:
|
| 1311 |
+
# st.session_state.traj_frames = trajectory
|
| 1312 |
+
# st.session_state.traj_index = 0
|
| 1313 |
|
| 1314 |
+
# # Navigation Buttons
|
| 1315 |
+
# col1, col2, col3, col4 = st.columns(4)
|
| 1316 |
+
# with col1:
|
| 1317 |
+
# if st.button("⏮ First"):
|
| 1318 |
+
# st.session_state.traj_index = 0
|
| 1319 |
+
# with col2:
|
| 1320 |
+
# if st.button("◀ Previous") and st.session_state.traj_index > 0:
|
| 1321 |
+
# st.session_state.traj_index -= 1
|
| 1322 |
+
# with col3:
|
| 1323 |
+
# if st.button("Next ▶") and st.session_state.traj_index < len(st.session_state.traj_frames) - 1:
|
| 1324 |
+
# st.session_state.traj_index += 1
|
| 1325 |
+
# with col4:
|
| 1326 |
+
# if st.button("Last ⏭"):
|
| 1327 |
+
# st.session_state.traj_index = len(st.session_state.traj_frames) - 1
|
| 1328 |
|
| 1329 |
+
# # Show current frame
|
| 1330 |
+
# current_atoms = st.session_state.traj_frames[st.session_state.traj_index]
|
| 1331 |
+
# st.write(f"Frame {st.session_state.traj_index + 1}/{len(st.session_state.traj_frames)}")
|
| 1332 |
|
| 1333 |
+
# # Convert to xyz string for py3Dmol
|
| 1334 |
+
# def atoms_to_xyz_string(atoms):
|
| 1335 |
+
# xyz_str = f"{len(atoms)}\nStep {st.session_state.traj_index}, Energy = {atoms.get_potential_energy():.6f} eV\n"
|
| 1336 |
+
# for atom in atoms:
|
| 1337 |
+
# xyz_str += f"{atom.symbol} {atom.position[0]:.6f} {atom.position[1]:.6f} {atom.position[2]:.6f}\n"
|
| 1338 |
+
# return xyz_str
|
| 1339 |
|
| 1340 |
+
# xyz_str = atoms_to_xyz_string(current_atoms)
|
| 1341 |
+
# view = py3Dmol.view(width=400, height=400)
|
| 1342 |
+
# view.addModel(xyz_str, "xyz")
|
| 1343 |
+
# view.setStyle({'stick': {}})
|
| 1344 |
+
# view.zoomTo()
|
| 1345 |
+
# view.setBackgroundColor("white")
|
| 1346 |
+
# st.components.v1.html(view._make_html(), height=400, width=400)
|
| 1347 |
|
| 1348 |
+
# # Download entire trajectory
|
| 1349 |
+
# @st.fragment
|
| 1350 |
+
# def show_trajectory_download_button():
|
| 1351 |
+
# trajectory_xyz = ""
|
| 1352 |
+
# for i, atoms in enumerate(st.session_state.traj_frames):
|
| 1353 |
+
# trajectory_xyz += f"{len(atoms)}\nStep {i}, Energy = {atoms.get_potential_energy():.6f} eV\n"
|
| 1354 |
+
# for atom in atoms:
|
| 1355 |
+
# trajectory_xyz += f"{atom.symbol} {atom.position[0]:.6f} {atom.position[1]:.6f} {atom.position[2]:.6f}\n"
|
| 1356 |
+
# st.download_button(
|
| 1357 |
+
# label="Download Optimization Trajectory (XYZ)",
|
| 1358 |
+
# data=trajectory_xyz,
|
| 1359 |
+
# file_name="optimization_trajectory.xyz",
|
| 1360 |
+
# mime="chemical/x-xyz"
|
| 1361 |
+
# )
|
| 1362 |
+
# show_trajectory_download_button()
|
| 1363 |
|
| 1364 |
+
# except Exception as e:
|
| 1365 |
+
# st.warning(f"Could not process trajectory: {e}")
|
| 1366 |
|
| 1367 |
+
# finally:
|
| 1368 |
+
# os.unlink(traj_filename)
|
| 1369 |
+
|
| 1370 |
+
# show_trajectory()
|
| 1371 |
+
@st.fragment
|
| 1372 |
+
def show_trajectory_and_controls():
|
| 1373 |
+
from ase.io import read
|
| 1374 |
+
import py3Dmol
|
| 1375 |
+
|
| 1376 |
+
if "traj_frames" not in st.session_state:
|
| 1377 |
+
if os.path.exists(traj_filename):
|
| 1378 |
+
try:
|
| 1379 |
+
trajectory = read(traj_filename, index=":")
|
| 1380 |
+
st.session_state.traj_frames = trajectory
|
| 1381 |
+
st.session_state.traj_index = 0
|
| 1382 |
+
except Exception as e:
|
| 1383 |
+
st.error(f"Error reading trajectory: {e}")
|
| 1384 |
+
return
|
| 1385 |
+
finally:
|
| 1386 |
+
os.unlink(traj_filename)
|
| 1387 |
+
else:
|
| 1388 |
+
st.warning("Trajectory file not found.")
|
| 1389 |
+
return
|
| 1390 |
+
|
| 1391 |
+
trajectory = st.session_state.traj_frames
|
| 1392 |
+
index = st.session_state.traj_index
|
| 1393 |
+
|
| 1394 |
+
st.markdown("### Optimization Trajectory")
|
| 1395 |
+
st.write(f"Captured {len(trajectory)} optimization steps")
|
| 1396 |
+
|
| 1397 |
+
# Navigation Buttons
|
| 1398 |
+
col1, col2, col3, col4 = st.columns(4)
|
| 1399 |
+
with col1:
|
| 1400 |
+
if st.button("⏮ First"):
|
| 1401 |
+
st.session_state.traj_index = 0
|
| 1402 |
+
with col2:
|
| 1403 |
+
if st.button("◀ Previous") and index > 0:
|
| 1404 |
+
st.session_state.traj_index -= 1
|
| 1405 |
+
with col3:
|
| 1406 |
+
if st.button("Next ▶") and index < len(trajectory) - 1:
|
| 1407 |
+
st.session_state.traj_index += 1
|
| 1408 |
+
with col4:
|
| 1409 |
+
if st.button("Last ⏭"):
|
| 1410 |
+
st.session_state.traj_index = len(trajectory) - 1
|
| 1411 |
+
|
| 1412 |
+
# Show current frame
|
| 1413 |
+
current_atoms = trajectory[st.session_state.traj_index]
|
| 1414 |
+
st.write(f"Frame {st.session_state.traj_index + 1}/{len(trajectory)}")
|
| 1415 |
+
|
| 1416 |
+
def atoms_to_xyz_string(atoms, step_idx=None):
|
| 1417 |
+
xyz_str = f"{len(atoms)}\n"
|
| 1418 |
+
if step_idx is not None:
|
| 1419 |
+
xyz_str += f"Step {step_idx}, Energy = {atoms.get_potential_energy():.6f} eV\n"
|
| 1420 |
+
else:
|
| 1421 |
+
xyz_str += f"Energy = {atoms.get_potential_energy():.6f} eV\n"
|
| 1422 |
+
for atom in atoms:
|
| 1423 |
+
xyz_str += f"{atom.symbol} {atom.position[0]:.6f} {atom.position[1]:.6f} {atom.position[2]:.6f}\n"
|
| 1424 |
+
return xyz_str
|
| 1425 |
+
|
| 1426 |
+
xyz_str = atoms_to_xyz_string(current_atoms, st.session_state.traj_index)
|
| 1427 |
+
|
| 1428 |
+
view = py3Dmol.view(width=400, height=400)
|
| 1429 |
+
view.addModel(xyz_str, "xyz")
|
| 1430 |
+
view.setStyle({'stick': {}})
|
| 1431 |
+
view.zoomTo()
|
| 1432 |
+
view.setBackgroundColor("white")
|
| 1433 |
+
st.components.v1.html(view._make_html(), height=400, width=400)
|
| 1434 |
+
|
| 1435 |
+
# Download button for entire trajectory
|
| 1436 |
+
trajectory_xyz = ""
|
| 1437 |
+
for i, atoms in enumerate(trajectory):
|
| 1438 |
+
trajectory_xyz += atoms_to_xyz_string(atoms, i)
|
| 1439 |
+
st.download_button(
|
| 1440 |
+
label="Download Optimization Trajectory (XYZ)",
|
| 1441 |
+
data=trajectory_xyz,
|
| 1442 |
+
file_name="optimization_trajectory.xyz",
|
| 1443 |
+
mime="chemical/x-xyz"
|
| 1444 |
+
)
|
| 1445 |
+
|
| 1446 |
+
show_trajectory_and_controls()
|
| 1447 |
|
|
|
|
| 1448 |
except Exception as e:
|
| 1449 |
st.error(f"🔴 Calculation error: {str(e)}")
|
| 1450 |
st.error("Please check the structure, model compatibility, and parameters. For FairChem UMA, ensure the task type (omol, omat etc.) is appropriate for your system (e.g. omol for molecules, omat for materials).")
|