Spaces:
Runtime error
Runtime error
Replace Psi4/psikit with PySCF for molecular orbital calculations on HF Spaces
Browse files- app.py +45 -37
- force_rebuild.txt +1 -1
- requirements.txt +2 -1
app.py
CHANGED
|
@@ -112,27 +112,12 @@ def smiles_to_molecular_orbitals(smiles_input: str, name_input: str) -> str:
|
|
| 112 |
raise gr.Error("Please provide a molecule with 30 atoms or fewer for orbital visualization.")
|
| 113 |
|
| 114 |
try:
|
| 115 |
-
|
| 116 |
except ImportError:
|
| 117 |
return (
|
| 118 |
-
"<p><strong>
|
| 119 |
-
"Install
|
| 120 |
-
"
|
| 121 |
-
"<p><strong>Alternative online tools:</strong></p>"
|
| 122 |
-
"<ul>"
|
| 123 |
-
"<li><a href='https://www.webmo.net/' target='_blank'>WebMO</a> - Web-based molecular modeling</li>"
|
| 124 |
-
"<li><a href='https://gaussian.com/' target='_blank'>Gaussian</a> - Quantum chemistry software</li>"
|
| 125 |
-
"<li><a href='https://www.chemcraftprog.com/' target='_blank'>ChemCraft</a> - Molecular visualization</li>"
|
| 126 |
-
"</ul>"
|
| 127 |
-
f"<p>You can copy this SMILES to these tools: <code>{canonical_smiles}</code></p>"
|
| 128 |
-
)
|
| 129 |
-
|
| 130 |
-
try:
|
| 131 |
-
import psi4 # Check if psi4 is available
|
| 132 |
-
except ImportError:
|
| 133 |
-
return (
|
| 134 |
-
"<p><strong>Psi4 is not available on this platform.</strong> "
|
| 135 |
-
"Molecular orbital calculations require Psi4, which is not supported on Hugging Face Spaces.</p>"
|
| 136 |
"<p><strong>Alternative online tools:</strong></p>"
|
| 137 |
"<ul>"
|
| 138 |
"<li><a href='https://www.webmo.net/' target='_blank'>WebMO</a> - Web-based molecular modeling</li>"
|
|
@@ -154,18 +139,43 @@ def smiles_to_molecular_orbitals(smiles_input: str, name_input: str) -> str:
|
|
| 154 |
original_cwd = os.getcwd()
|
| 155 |
os.chdir(tmpdir)
|
| 156 |
try:
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
)
|
| 167 |
-
|
| 168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
html_sections: list[str] = []
|
| 171 |
if name_input.strip():
|
|
@@ -173,9 +183,10 @@ def smiles_to_molecular_orbitals(smiles_input: str, name_input: str) -> str:
|
|
| 173 |
f"<p><strong>Resolved '{name_input.strip()}' to SMILES:</strong> {canonical_smiles}</p>"
|
| 174 |
)
|
| 175 |
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
|
|
|
| 179 |
view = py3Dmol.view(width=500, height=400)
|
| 180 |
view.addModel(mol_block, "mol")
|
| 181 |
view.setStyle({"stick": {}})
|
|
@@ -197,9 +208,6 @@ def smiles_to_molecular_orbitals(smiles_input: str, name_input: str) -> str:
|
|
| 197 |
if not html_sections:
|
| 198 |
return "<p>Could not prepare HOMO/LUMO visualizations.</p>"
|
| 199 |
|
| 200 |
-
if not html_sections:
|
| 201 |
-
return "<p>Could not prepare HOMO/LUMO visualizations.</p>"
|
| 202 |
-
|
| 203 |
return "".join(html_sections)
|
| 204 |
except Exception as exc: # pragma: no cover - runtime heavy
|
| 205 |
return f"<p>Unable to compute molecular orbitals: {exc}</p>"
|
|
|
|
| 112 |
raise gr.Error("Please provide a molecule with 30 atoms or fewer for orbital visualization.")
|
| 113 |
|
| 114 |
try:
|
| 115 |
+
import pyscf # type: ignore[import]
|
| 116 |
except ImportError:
|
| 117 |
return (
|
| 118 |
+
"<p><strong>PySCF is not available.</strong> "
|
| 119 |
+
"Install it with <code>pip install pyscf</code> "
|
| 120 |
+
"for molecular orbital calculations.</p>"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
"<p><strong>Alternative online tools:</strong></p>"
|
| 122 |
"<ul>"
|
| 123 |
"<li><a href='https://www.webmo.net/' target='_blank'>WebMO</a> - Web-based molecular modeling</li>"
|
|
|
|
| 139 |
original_cwd = os.getcwd()
|
| 140 |
os.chdir(tmpdir)
|
| 141 |
try:
|
| 142 |
+
# Generate 3D coordinates with RDKit
|
| 143 |
+
mol_3d = Chem.AddHs(mol)
|
| 144 |
+
AllChem.EmbedMolecule(mol_3d, randomSeed=42)
|
| 145 |
+
AllChem.MMFFOptimizeMolecule(mol_3d)
|
| 146 |
+
|
| 147 |
+
# Extract coordinates and atomic numbers
|
| 148 |
+
coords = []
|
| 149 |
+
atoms = []
|
| 150 |
+
for atom in mol_3d.GetAtoms():
|
| 151 |
+
pos = mol_3d.GetConformer().GetAtomPosition(atom.GetIdx())
|
| 152 |
+
coords.append([pos.x, pos.y, pos.z])
|
| 153 |
+
atoms.append(atom.GetSymbol())
|
| 154 |
+
|
| 155 |
+
# Set up PySCF molecule
|
| 156 |
+
mol_pyscf = pyscf.gto.Mole()
|
| 157 |
+
mol_pyscf.atom = list(zip(atoms, coords))
|
| 158 |
+
mol_pyscf.basis = 'sto-3g' # Small basis set for speed
|
| 159 |
+
mol_pyscf.build()
|
| 160 |
+
|
| 161 |
+
# Run Hartree-Fock calculation
|
| 162 |
+
mf = pyscf.scf.RHF(mol_pyscf)
|
| 163 |
+
mf.kernel()
|
| 164 |
+
|
| 165 |
+
# Get HOMO and LUMO indices
|
| 166 |
+
nocc = mol_pyscf.nelectron // 2
|
| 167 |
+
homo_idx = nocc - 1
|
| 168 |
+
lumo_idx = nocc
|
| 169 |
+
|
| 170 |
+
# Generate cube files for HOMO and LUMO
|
| 171 |
+
from pyscf.tools import cubegen
|
| 172 |
+
cube_files = []
|
| 173 |
+
for idx, label in [(homo_idx, 'HOMO'), (lumo_idx, 'LUMO')]:
|
| 174 |
+
cube_file = f'{label.lower()}.cube'
|
| 175 |
+
cubegen.orbital(mol_pyscf, cube_file, mf.mo_coeff[:, idx])
|
| 176 |
+
cube_files.append((cube_file, label))
|
| 177 |
+
|
| 178 |
+
mol_block = Chem.MolToMolBlock(mol_3d)
|
| 179 |
|
| 180 |
html_sections: list[str] = []
|
| 181 |
if name_input.strip():
|
|
|
|
| 183 |
f"<p><strong>Resolved '{name_input.strip()}' to SMILES:</strong> {canonical_smiles}</p>"
|
| 184 |
)
|
| 185 |
|
| 186 |
+
for cube_file, label in cube_files:
|
| 187 |
+
if not Path(cube_file).exists():
|
| 188 |
+
continue
|
| 189 |
+
cube_data = Path(cube_file).read_text()
|
| 190 |
view = py3Dmol.view(width=500, height=400)
|
| 191 |
view.addModel(mol_block, "mol")
|
| 192 |
view.setStyle({"stick": {}})
|
|
|
|
| 208 |
if not html_sections:
|
| 209 |
return "<p>Could not prepare HOMO/LUMO visualizations.</p>"
|
| 210 |
|
|
|
|
|
|
|
|
|
|
| 211 |
return "".join(html_sections)
|
| 212 |
except Exception as exc: # pragma: no cover - runtime heavy
|
| 213 |
return f"<p>Unable to compute molecular orbitals: {exc}</p>"
|
force_rebuild.txt
CHANGED
|
@@ -1,2 +1,2 @@
|
|
| 1 |
# Force rebuild
|
| 2 |
-
2025-11-08
|
|
|
|
| 1 |
# Force rebuild
|
| 2 |
+
2025-11-08 v3
|
requirements.txt
CHANGED
|
@@ -5,4 +5,5 @@ huggingface_hub==0.19.4
|
|
| 5 |
cirpy
|
| 6 |
pubchempy
|
| 7 |
psikit
|
| 8 |
-
py3Dmol
|
|
|
|
|
|
| 5 |
cirpy
|
| 6 |
pubchempy
|
| 7 |
psikit
|
| 8 |
+
py3Dmol
|
| 9 |
+
pyscf
|