Spaces:
Running
Running
Gilmullin Almaz
commited on
Commit
·
629ce7d
1
Parent(s):
3f82781
Enhance two-way synchronization for molecule input in handle_molecule_input function
Browse files
app.py
CHANGED
|
@@ -219,7 +219,7 @@ def setup_sidebar():
|
|
| 219 |
|
| 220 |
|
| 221 |
def handle_molecule_input():
|
| 222 |
-
"""3. Molecule Input: Managing the input area for molecule data."""
|
| 223 |
st.header("Molecule input")
|
| 224 |
st.markdown(
|
| 225 |
"""
|
|
@@ -228,42 +228,74 @@ def handle_molecule_input():
|
|
| 228 |
* Draw it + Apply
|
| 229 |
"""
|
| 230 |
)
|
| 231 |
-
# Use st.session_state.ketcher to persist drawn molecule
|
| 232 |
-
molecule_text_input = st.text_input(
|
| 233 |
-
"SMILES:", value=st.session_state.ketcher, key="smiles_text_input_key"
|
| 234 |
-
)
|
| 235 |
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
#
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
#
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
)
|
| 250 |
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
st.session_state.
|
| 261 |
-
st.session_state.
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 265 |
|
| 266 |
-
return
|
| 267 |
|
| 268 |
|
| 269 |
def setup_planning_options():
|
|
|
|
| 219 |
|
| 220 |
|
| 221 |
def handle_molecule_input():
|
| 222 |
+
"""3. Molecule Input: Managing the input area for molecule data with two-way synchronization."""
|
| 223 |
st.header("Molecule input")
|
| 224 |
st.markdown(
|
| 225 |
"""
|
|
|
|
| 228 |
* Draw it + Apply
|
| 229 |
"""
|
| 230 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
|
| 232 |
+
# Initialize shared_smiles in session state if it doesn't exist.
|
| 233 |
+
if "shared_smiles" not in st.session_state:
|
| 234 |
+
st.session_state.shared_smiles = st.session_state.get("ketcher", DEFAULT_MOL)
|
| 235 |
+
|
| 236 |
+
# Initialize a counter for changing Ketcher's key to force re-render
|
| 237 |
+
if "ketcher_render_count" not in st.session_state:
|
| 238 |
+
st.session_state.ketcher_render_count = 0
|
| 239 |
+
|
| 240 |
+
# Callback for text input change
|
| 241 |
+
def text_input_changed_callback():
|
| 242 |
+
new_text_value = st.session_state.smiles_text_input_key_for_sync # Key of the text_input
|
| 243 |
+
if new_text_value != st.session_state.shared_smiles:
|
| 244 |
+
st.session_state.shared_smiles = new_text_value
|
| 245 |
+
# Update the legacy st.session_state.ketcher for compatibility
|
| 246 |
+
st.session_state.ketcher = new_text_value
|
| 247 |
+
# Increment the counter to change Ketcher's key, forcing it to re-render with the new SMILES
|
| 248 |
+
st.session_state.ketcher_render_count += 1
|
| 249 |
+
# An implicit rerun is triggered by on_change, no need for st.rerun() here.
|
| 250 |
+
|
| 251 |
+
# SMILES Text Input
|
| 252 |
+
st.text_input(
|
| 253 |
+
"SMILES:",
|
| 254 |
+
value=st.session_state.shared_smiles,
|
| 255 |
+
key="smiles_text_input_key_for_sync", # Unique key for this widget
|
| 256 |
+
on_change=text_input_changed_callback,
|
| 257 |
+
help="Enter SMILES string and press Enter. The drawing will update, and vice-versa."
|
| 258 |
)
|
| 259 |
|
| 260 |
+
# Ketcher Component
|
| 261 |
+
# The key is made dynamic using ketcher_render_count.
|
| 262 |
+
# When text_input_changed_callback increments ketcher_render_count,
|
| 263 |
+
# Ketcher's key changes, forcing it to re-initialize with the current st.session_state.shared_smiles.
|
| 264 |
+
ketcher_key = f"ketcher_widget_for_sync_{st.session_state.ketcher_render_count}"
|
| 265 |
+
smile_code_output_from_ketcher = st_ketcher(st.session_state.shared_smiles, key=ketcher_key)
|
| 266 |
+
|
| 267 |
+
# Synchronize if Ketcher changed the SMILES (user drew and applied)
|
| 268 |
+
if smile_code_output_from_ketcher != st.session_state.shared_smiles:
|
| 269 |
+
st.session_state.shared_smiles = smile_code_output_from_ketcher
|
| 270 |
+
st.session_state.ketcher = smile_code_output_from_ketcher
|
| 271 |
+
# When Ketcher changes the SMILES, we don't need to change ketcher_render_count.
|
| 272 |
+
# The text input will update automatically because its 'value' is tied to shared_smiles.
|
| 273 |
+
# We need to rerun to make the text_input widget reflect the change from Ketcher immediately.
|
| 274 |
+
st.rerun()
|
| 275 |
+
|
| 276 |
+
current_smiles_for_planning = st.session_state.shared_smiles
|
| 277 |
+
|
| 278 |
+
# Warning logic (simplified for relevance to this function's scope)
|
| 279 |
+
last_planned_smiles = st.session_state.get("target_smiles")
|
| 280 |
+
if (last_planned_smiles and
|
| 281 |
+
current_smiles_for_planning != last_planned_smiles and
|
| 282 |
+
st.session_state.get("planning_done", False)):
|
| 283 |
+
st.warning(
|
| 284 |
+
"Molecule structure has changed since the last successful planning run. "
|
| 285 |
+
"Results shown below (if any) are for the previous molecule. "
|
| 286 |
+
"Please re-run planning for the current structure."
|
| 287 |
+
)
|
| 288 |
+
# Resetting states would typically happen here, as in your original full script.
|
| 289 |
+
# For brevity in this targeted fix, I'm omitting the state reset lines,
|
| 290 |
+
# assuming they are correctly handled in your main script structure.
|
| 291 |
+
# Example: st.session_state.planning_done = False etc.
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
# Ensure st.session_state.ketcher is consistent for other parts of the app
|
| 295 |
+
if st.session_state.get("ketcher") != current_smiles_for_planning:
|
| 296 |
+
st.session_state.ketcher = current_smiles_for_planning
|
| 297 |
|
| 298 |
+
return current_smiles_for_planning
|
| 299 |
|
| 300 |
|
| 301 |
def setup_planning_options():
|