Spaces:
Running
Running
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +44 -4
src/streamlit_app.py
CHANGED
|
@@ -1219,13 +1219,14 @@ if atoms is not None:
|
|
| 1219 |
|
| 1220 |
elif "Optimization" in task: # Handles both Geometry and Cell+Geometry Opt
|
| 1221 |
opt_atoms_obj = FrechetCellFilter(calc_atoms) if task == "Cell + Geometry Optimization" else calc_atoms
|
| 1222 |
-
|
|
|
|
| 1223 |
if optimizer_type == "BFGS":
|
| 1224 |
-
opt = BFGS(opt_atoms_obj)
|
| 1225 |
elif optimizer_type == "LBFGS":
|
| 1226 |
-
opt = LBFGS(opt_atoms_obj)
|
| 1227 |
else: # FIRE
|
| 1228 |
-
opt = FIRE(opt_atoms_obj)
|
| 1229 |
|
| 1230 |
# opt.attach(streamlit_log, interval=1) # Removed lambda for simplicity if streamlit_log is defined correctly
|
| 1231 |
opt.attach(lambda: streamlit_log(opt), interval=1)
|
|
@@ -1287,6 +1288,45 @@ if atoms is not None:
|
|
| 1287 |
mime="chemical/x-xyz"
|
| 1288 |
)
|
| 1289 |
os.unlink(tmp_filepath_opt)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1290 |
|
| 1291 |
except Exception as e:
|
| 1292 |
st.error(f"🔴 Calculation error: {str(e)}")
|
|
|
|
| 1219 |
|
| 1220 |
elif "Optimization" in task: # Handles both Geometry and Cell+Geometry Opt
|
| 1221 |
opt_atoms_obj = FrechetCellFilter(calc_atoms) if task == "Cell + Geometry Optimization" else calc_atoms
|
| 1222 |
+
# Create temporary trajectory file
|
| 1223 |
+
traj_filename = tempfile.NamedTemporaryFile(delete=False, suffix=".traj").name
|
| 1224 |
if optimizer_type == "BFGS":
|
| 1225 |
+
opt = BFGS(opt_atoms_obj, trajectory=traj_filename)
|
| 1226 |
elif optimizer_type == "LBFGS":
|
| 1227 |
+
opt = LBFGS(opt_atoms_obj, trajectory=traj_filename)
|
| 1228 |
else: # FIRE
|
| 1229 |
+
opt = FIRE(opt_atoms_obj, trajectory=traj_filename)
|
| 1230 |
|
| 1231 |
# opt.attach(streamlit_log, interval=1) # Removed lambda for simplicity if streamlit_log is defined correctly
|
| 1232 |
opt.attach(lambda: streamlit_log(opt), interval=1)
|
|
|
|
| 1288 |
mime="chemical/x-xyz"
|
| 1289 |
)
|
| 1290 |
os.unlink(tmp_filepath_opt)
|
| 1291 |
+
|
| 1292 |
+
# Convert trajectory to XYZ for download
|
| 1293 |
+
from ase.io import read
|
| 1294 |
+
|
| 1295 |
+
if os.path.exists(traj_filename):
|
| 1296 |
+
try:
|
| 1297 |
+
# Read trajectory and convert to XYZ
|
| 1298 |
+
trajectory = read(traj_filename, index=':') # Read all frames
|
| 1299 |
+
|
| 1300 |
+
# Create XYZ content
|
| 1301 |
+
trajectory_xyz = ""
|
| 1302 |
+
for i, atoms in enumerate(trajectory):
|
| 1303 |
+
trajectory_xyz += f"{len(atoms)}\n"
|
| 1304 |
+
# Try to get energy if available
|
| 1305 |
+
try:
|
| 1306 |
+
energy = atoms.get_potential_energy()
|
| 1307 |
+
trajectory_xyz += f"Step {i}: Energy = {energy:.6f} eV\n"
|
| 1308 |
+
except:
|
| 1309 |
+
trajectory_xyz += f"Step {i}: Optimization trajectory\n"
|
| 1310 |
+
|
| 1311 |
+
for atom in atoms:
|
| 1312 |
+
trajectory_xyz += f"{atom.symbol} {atom.position[0]:.6f} {atom.position[1]:.6f} {atom.position[2]:.6f}\n"
|
| 1313 |
+
|
| 1314 |
+
st.markdown("### Optimization Trajectory")
|
| 1315 |
+
st.write(f"Captured {len(trajectory)} optimization steps")
|
| 1316 |
+
|
| 1317 |
+
st.download_button(
|
| 1318 |
+
label="Download Optimization Trajectory (XYZ)",
|
| 1319 |
+
data=trajectory_xyz,
|
| 1320 |
+
file_name="optimization_trajectory.xyz",
|
| 1321 |
+
mime="chemical/x-xyz"
|
| 1322 |
+
)
|
| 1323 |
+
|
| 1324 |
+
except Exception as e:
|
| 1325 |
+
st.warning(f"Could not process trajectory: {e}")
|
| 1326 |
+
|
| 1327 |
+
finally:
|
| 1328 |
+
# Clean up trajectory file
|
| 1329 |
+
os.unlink(traj_filename)
|
| 1330 |
|
| 1331 |
except Exception as e:
|
| 1332 |
st.error(f"🔴 Calculation error: {str(e)}")
|