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).")
|