Spaces:
Running
Running
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +61 -58
src/streamlit_app.py
CHANGED
|
@@ -68,12 +68,6 @@ except Exception as e:
|
|
| 68 |
|
| 69 |
os.environ["STREAMLIT_WATCHER_TYPE"] = "none"
|
| 70 |
|
| 71 |
-
# Initialize session state
|
| 72 |
-
if 'optimization_results' not in st.session_state:
|
| 73 |
-
st.session_state.optimization_results = None
|
| 74 |
-
if 'trajectory_data' not in st.session_state:
|
| 75 |
-
st.session_state.trajectory_data = None
|
| 76 |
-
|
| 77 |
# YAML data for FairChem reference energies
|
| 78 |
ELEMENT_REF_ENERGIES_YAML = """
|
| 79 |
oc20_elem_refs:
|
|
@@ -1251,53 +1245,37 @@ if atoms is not None:
|
|
| 1251 |
if task == "Cell + Geometry Optimization":
|
| 1252 |
results["Final Cell Parameters"] = np.round(calc_atoms.cell.cellpar(), 4).tolist()
|
| 1253 |
|
| 1254 |
-
st.success("Calculation completed successfully!")
|
| 1255 |
-
# Store results and trajectory in session state
|
| 1256 |
-
st.session_state.optimization_results = results
|
| 1257 |
-
st.session_state.optimized_atoms = calc_atoms.copy()
|
| 1258 |
-
|
| 1259 |
-
# Process trajectory
|
| 1260 |
-
if os.path.exists(traj_filename):
|
| 1261 |
-
try:
|
| 1262 |
-
trajectory = read(traj_filename, index=':')
|
| 1263 |
-
trajectory_xyz = ""
|
| 1264 |
-
for i, atoms in enumerate(trajectory):
|
| 1265 |
-
trajectory_xyz += f"{len(atoms)}\n"
|
| 1266 |
-
try:
|
| 1267 |
-
energy = atoms.get_potential_energy()
|
| 1268 |
-
trajectory_xyz += f"Step {i}: Energy = {energy:.6f} eV\n"
|
| 1269 |
-
except:
|
| 1270 |
-
trajectory_xyz += f"Step {i}: Optimization trajectory\n"
|
| 1271 |
-
|
| 1272 |
-
for atom in atoms:
|
| 1273 |
-
trajectory_xyz += f"{atom.symbol} {atom.position[0]:.6f} {atom.position[1]:.6f} {atom.position[2]:.6f}\n"
|
| 1274 |
-
|
| 1275 |
-
st.session_state.trajectory_data = {
|
| 1276 |
-
'xyz_content': trajectory_xyz,
|
| 1277 |
-
'num_steps': len(trajectory)
|
| 1278 |
-
}
|
| 1279 |
-
except Exception as e:
|
| 1280 |
-
st.warning(f"Could not process trajectory: {e}")
|
| 1281 |
-
finally:
|
| 1282 |
-
os.unlink(traj_filename)
|
| 1283 |
-
|
| 1284 |
-
# Display results if available
|
| 1285 |
-
if st.session_state.optimization_results:
|
| 1286 |
st.success("Calculation completed successfully!")
|
| 1287 |
st.markdown("### Results")
|
| 1288 |
-
for key, value in
|
| 1289 |
st.write(f"**{key}:** {value}")
|
| 1290 |
|
| 1291 |
-
if
|
| 1292 |
st.markdown("### Optimized Structure")
|
| 1293 |
-
|
| 1294 |
-
|
| 1295 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1296 |
st.components.v1.html(opt_view._make_html(), width=400, height=400)
|
| 1297 |
|
| 1298 |
-
# Download optimized structure
|
| 1299 |
with tempfile.NamedTemporaryFile(delete=False, suffix=".xyz", mode="w+") as tmp_file_opt:
|
| 1300 |
-
write(tmp_file_opt.name,
|
| 1301 |
tmp_filepath_opt = tmp_file_opt.name
|
| 1302 |
|
| 1303 |
with open(tmp_filepath_opt, 'r') as file_opt:
|
|
@@ -1307,23 +1285,48 @@ if atoms is not None:
|
|
| 1307 |
label="Download Optimized Structure (XYZ)",
|
| 1308 |
data=xyz_content_opt,
|
| 1309 |
file_name="optimized_structure.xyz",
|
| 1310 |
-
mime="chemical/x-xyz"
|
| 1311 |
-
key="download_opt_structure" # Unique key prevents conflicts
|
| 1312 |
)
|
| 1313 |
os.unlink(tmp_filepath_opt)
|
|
|
|
|
|
|
|
|
|
| 1314 |
|
| 1315 |
-
|
| 1316 |
-
|
| 1317 |
-
|
| 1318 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1319 |
|
| 1320 |
-
|
| 1321 |
-
|
| 1322 |
-
|
| 1323 |
-
file_name="optimization_trajectory.xyz",
|
| 1324 |
-
mime="chemical/x-xyz",
|
| 1325 |
-
key="download_trajectory" # Unique key prevents conflicts
|
| 1326 |
-
)
|
| 1327 |
|
| 1328 |
except Exception as e:
|
| 1329 |
st.error(f"🔴 Calculation error: {str(e)}")
|
|
|
|
| 68 |
|
| 69 |
os.environ["STREAMLIT_WATCHER_TYPE"] = "none"
|
| 70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
# YAML data for FairChem reference energies
|
| 72 |
ELEMENT_REF_ENERGIES_YAML = """
|
| 73 |
oc20_elem_refs:
|
|
|
|
| 1245 |
if task == "Cell + Geometry Optimization":
|
| 1246 |
results["Final Cell Parameters"] = np.round(calc_atoms.cell.cellpar(), 4).tolist()
|
| 1247 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1248 |
st.success("Calculation completed successfully!")
|
| 1249 |
st.markdown("### Results")
|
| 1250 |
+
for key, value in results.items():
|
| 1251 |
st.write(f"**{key}:** {value}")
|
| 1252 |
|
| 1253 |
+
if "Optimization" in task and "Final Energy" in results: # Check if opt was successful
|
| 1254 |
st.markdown("### Optimized Structure")
|
| 1255 |
+
# Need get_structure_viz function that takes atoms obj
|
| 1256 |
+
def get_structure_viz_simple(atoms_obj_viz):
|
| 1257 |
+
xyz_str_viz = f"{len(atoms_obj_viz)}\nStructure\n"
|
| 1258 |
+
for atom_viz in atoms_obj_viz:
|
| 1259 |
+
xyz_str_viz += f"{atom_viz.symbol} {atom_viz.position[0]:.6f} {atom_viz.position[1]:.6f} {atom_viz.position[2]:.6f}\n"
|
| 1260 |
+
view_viz = py3Dmol.view(width=400, height=400)
|
| 1261 |
+
view_viz.addModel(xyz_str_viz, "xyz")
|
| 1262 |
+
view_viz.setStyle({'stick': {}})
|
| 1263 |
+
if any(atoms_obj_viz.pbc): # Show cell for optimized periodic structures
|
| 1264 |
+
cell_viz = atoms_obj_viz.get_cell()
|
| 1265 |
+
if cell_viz is not None and cell_viz.any():
|
| 1266 |
+
# Simplified cell drawing for brevity, use get_structure_viz2 if full cell needed
|
| 1267 |
+
view_viz.addUnitCell({'box': {'lx':cell_viz.lengths()[0],'ly':cell_viz.lengths()[1],'lz':cell_viz.lengths()[2],
|
| 1268 |
+
'hx':cell_viz.cellpar()[3],'hy':cell_viz.cellpar()[4],'hz':cell_viz.cellpar()[5]}})
|
| 1269 |
+
|
| 1270 |
+
view_viz.zoomTo()
|
| 1271 |
+
view_viz.setBackgroundColor('white')
|
| 1272 |
+
return view_viz
|
| 1273 |
+
|
| 1274 |
+
opt_view = get_structure_viz2(calc_atoms, style=viz_style, show_unit_cell=True, width=400, height=400)
|
| 1275 |
st.components.v1.html(opt_view._make_html(), width=400, height=400)
|
| 1276 |
|
|
|
|
| 1277 |
with tempfile.NamedTemporaryFile(delete=False, suffix=".xyz", mode="w+") as tmp_file_opt:
|
| 1278 |
+
write(tmp_file_opt.name, calc_atoms, format="xyz")
|
| 1279 |
tmp_filepath_opt = tmp_file_opt.name
|
| 1280 |
|
| 1281 |
with open(tmp_filepath_opt, 'r') as file_opt:
|
|
|
|
| 1285 |
label="Download Optimized Structure (XYZ)",
|
| 1286 |
data=xyz_content_opt,
|
| 1287 |
file_name="optimized_structure.xyz",
|
| 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)}")
|