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