Spaces:
Sleeping
Sleeping
More robust CSV upload added and submission button added for mobile users
Browse files
app.py
CHANGED
@@ -6,7 +6,7 @@ from datetime import datetime
|
|
6 |
from rdkit import Chem
|
7 |
from rdkit.Chem import Draw
|
8 |
import os, pathlib
|
9 |
-
|
10 |
from model import load_model
|
11 |
from utils import smiles_to_data
|
12 |
from torch_geometric.loader import DataLoader
|
@@ -64,21 +64,39 @@ uploaded_file = st.file_uploader("...or upload a CSV file", type=["csv"])
|
|
64 |
|
65 |
smiles_list = []
|
66 |
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
|
83 |
# Run Inference
|
84 |
if smiles_list:
|
@@ -89,7 +107,7 @@ if smiles_list:
|
|
89 |
valid_pairs = [(smi, data) for smi, data in zip(smiles_list, data_list) if data is not None]
|
90 |
|
91 |
if not valid_pairs:
|
92 |
-
st.warning("No valid molecules found
|
93 |
else:
|
94 |
valid_smiles, valid_data = zip(*valid_pairs)
|
95 |
loader = DataLoader(valid_data, batch_size=64)
|
@@ -121,14 +139,10 @@ if smiles_list:
|
|
121 |
conn.commit()
|
122 |
|
123 |
# Download Results
|
124 |
-
result_df = pd.DataFrame({
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
data=result_df.to_csv(index=False).encode('utf-8'),
|
132 |
-
file_name="homolumo_predictions.csv",
|
133 |
-
mime="text/csv"
|
134 |
-
)
|
|
|
6 |
from rdkit import Chem
|
7 |
from rdkit.Chem import Draw
|
8 |
import os, pathlib
|
9 |
+
from io import StringIO
|
10 |
from model import load_model
|
11 |
from utils import smiles_to_data
|
12 |
from torch_geometric.loader import DataLoader
|
|
|
64 |
|
65 |
smiles_list = []
|
66 |
|
67 |
+
with st.form("input_form"):
|
68 |
+
smiles_input = st.text_area("Enter SMILES string(s)", placeholder="C1=CC=CC=C1, CC(=O)Oc1ccccc1C(=O)O", height=120)
|
69 |
+
uploaded_file = st.file_uploader("…or upload a CSV file", type=["csv"])
|
70 |
+
run_button = st.form_submit_button("Run Prediction")
|
71 |
+
|
72 |
+
# Process only after the user presses the button
|
73 |
+
if run_button:
|
74 |
+
# CSV path
|
75 |
+
if uploaded_file is not None:
|
76 |
+
try:
|
77 |
+
data = uploaded_file.getvalue() # read bytes
|
78 |
+
df = pd.read_csv(StringIO(data.decode("utf-8")), comment="#")
|
79 |
+
|
80 |
+
# choose the SMILES column
|
81 |
+
if df.shape[1] == 1:
|
82 |
+
smiles_col = df.iloc[:, 0]
|
83 |
+
elif "smiles" in [c.lower() for c in df.columns]:
|
84 |
+
smiles_col = df[[c for c in df.columns if c.lower() == "smiles"][0]]
|
85 |
+
else:
|
86 |
+
st.error("CSV must have a single column or a column named 'SMILES'" f"Found columns: {', '.join(df.columns)}")
|
87 |
+
smiles_col = None
|
88 |
+
|
89 |
+
if smiles_col is not None:
|
90 |
+
smiles_list = smiles_col.dropna().astype(str).tolist()
|
91 |
+
st.success(f"{len(smiles_list)} SMILES loaded from CSV")
|
92 |
+
except Exception as e:
|
93 |
+
st.error(f"Could not read CSV: {e}")
|
94 |
+
|
95 |
+
# Textarea path
|
96 |
+
elif smiles_input.strip():
|
97 |
+
raw_input = smiles_input.replace("\n", ",")
|
98 |
+
smiles_list = [s.strip() for s in raw_input.split(",") if s.strip()]
|
99 |
+
st.success(f"{len(smiles_list)} SMILES parsed from text")
|
100 |
|
101 |
# Run Inference
|
102 |
if smiles_list:
|
|
|
107 |
valid_pairs = [(smi, data) for smi, data in zip(smiles_list, data_list) if data is not None]
|
108 |
|
109 |
if not valid_pairs:
|
110 |
+
st.warning("No valid molecules found")
|
111 |
else:
|
112 |
valid_smiles, valid_data = zip(*valid_pairs)
|
113 |
loader = DataLoader(valid_data, batch_size=64)
|
|
|
139 |
conn.commit()
|
140 |
|
141 |
# Download Results
|
142 |
+
result_df = pd.DataFrame({"SMILES": valid_smiles,
|
143 |
+
"Predicted HOMO-LUMO Gap (eV)": [round(p, 4) for p in predictions]})
|
144 |
+
|
145 |
+
st.download_button(label="Download Predictions as CSV",
|
146 |
+
data=result_df.to_csv(index=False).encode('utf-8'),
|
147 |
+
file_name="homolumo_predictions.csv",
|
148 |
+
mime="text/csv")
|
|
|
|
|
|
|
|