Download src/web_page/webui_optimization.py from xinHesysu/UTR-CODE: direct link, hf CLI and curl.
- Browser
- Download file 7.1 kB
-
https://huggingface.co/spaces/xinHesysu/UTR-CODE/resolve/main/src/web_page/webui_optimization.py
- Command line
-
hf download hf://spaces/xinHesysu/UTR-CODE/src/web_page/webui_optimization.py
-
curl -L -o webui_optimization.py https://huggingface.co/spaces/xinHesysu/UTR-CODE/resolve/main/src/web_page/webui_optimization.py
7.1 kB
| import numpy as np | |
| import pandas as pd | |
| import plotly.express as px | |
| import streamlit as st | |
| def saturated_mutations(dna_seq): | |
| dna_seq = dna_seq.upper().replace("U", "T") | |
| dna_seq = "".join(c for c in dna_seq if c in "ATCG") | |
| n = len(dna_seq) | |
| bases = np.array(list("ATCG")) | |
| seq_array = np.array(list(dna_seq)) | |
| replace_matrix = np.array([bases[bases != base] for base in seq_array]) | |
| result = np.tile(seq_array, (3 * n, 1)) | |
| rows = np.repeat(np.arange(n), 3) | |
| result[np.arange(3 * n), rows] = replace_matrix.flatten() | |
| result = np.vstack([seq_array, result]) | |
| return ["".join(row) for row in result] | |
| if __name__ == "__main__": | |
| model = st.session_state["model"] | |
| input_format = st.session_state["input_format"] | |
| predict = st.session_state["predict"] | |
| mrna_env = st.session_state["mrna_env"] | |
| UTR3_GLUC = st.session_state["UTR3_GLUC"] | |
| CDS_GLUC = st.session_state["CDS_GLUC"] | |
| st.set_page_config(layout="wide") | |
| st.title("UTR-CODE") | |
| with st.form("single_input_form"): | |
| utr5_input = st.text_area( | |
| "5' UTR:", | |
| key="utr5_input", | |
| max_chars=1000, | |
| help="Only 'A', 'C', 'G', 'T' and 'U' is allowed, other characters will be ignored", | |
| ) | |
| with st.expander("Optional Input"): | |
| optional_input_col1, optional_input_col2 = st.columns(2) | |
| with optional_input_col1: | |
| cds_input = st.text_area( | |
| "CDS", | |
| value=CDS_GLUC, | |
| key="cds_input", | |
| max_chars=4500, | |
| help="GLUC's CDS is used by default.", | |
| ) | |
| with optional_input_col2: | |
| utr3_input = st.text_area( | |
| "3' UTR:", | |
| value=UTR3_GLUC, | |
| key="utr3_input", | |
| max_chars=4000, | |
| help="GLUC's UTR3 is used by default.", | |
| ) | |
| mutation_rounds = st.slider( | |
| "ISM Rounds", | |
| min_value=1, | |
| max_value=10, | |
| value=5, | |
| step=1, | |
| label_visibility="visible", | |
| ) | |
| submitted = st.form_submit_button("Submit", use_container_width=True) | |
| if submitted: | |
| if not "".join([c for c in utr5_input.upper() if c in "ATCGU"]): | |
| st.warning("Please input 5' UTR") | |
| elif any(c not in "ATCGU\n\t, " for c in f"{utr5_input.upper()}{cds_input.upper()}{utr3_input.upper()}"): | |
| st.warning("Only 'A', 'C', 'G', 'T' and 'U' is allowed.") | |
| else: | |
| utr5_optimize_use = "".join( | |
| [c for c in utr5_input.upper().replace("U", "T") if c in "ATCG"] | |
| ) | |
| results = dict() | |
| utr, cds = input_format(utr5_optimize_use, cds_input, utr3_input) | |
| results[0] = { | |
| "rpf": (np.expm1(predict(model, utr, cds, mrna_env)[0]) / 5) / 108.7144 , | |
| "seq": utr5_optimize_use, | |
| "base_change": "Origin", | |
| } | |
| cds_seq = [ | |
| cds_input, | |
| ] * (3 * len(utr5_input) + 1) | |
| utr3_seq = [ | |
| utr3_input, | |
| ] * (3 * len(utr5_input) + 1) | |
| progress_bar = st.empty() | |
| progress_bar = st.progress(0, f"Progress: 0%") | |
| progress_text = st.empty() | |
| chart_placeholder = st.empty() | |
| for i in range(1, mutation_rounds + 1): | |
| used_seq = saturated_mutations(utr5_optimize_use) | |
| utr, cds = input_format(used_seq, cds_seq, utr3_seq) | |
| result = predict(model, utr, cds, mrna_env) | |
| best_idx = np.argmax(result) | |
| max_val = result[best_idx] | |
| base_change = next( | |
| ( | |
| f"{i+1}:{c1}->{c2}" | |
| for i, (c1, c2) in enumerate( | |
| zip(utr5_optimize_use, used_seq[best_idx]) | |
| ) | |
| if c1 != c2 | |
| ), | |
| "No change", | |
| ) | |
| utr5_optimize_use = used_seq[best_idx] | |
| results[i] = { | |
| "rpf": (np.expm1(max_val) / 5) / 108.7144, | |
| "seq": utr5_optimize_use, | |
| "base_change": base_change, | |
| } | |
| progress_bar.progress( | |
| i / mutation_rounds, | |
| f"Progress: {i / mutation_rounds * 100:.0f}%", | |
| ) | |
| df = pd.DataFrame( | |
| [ | |
| { | |
| "Round": k, | |
| "Predicted Value": float(v["rpf"]), | |
| "UTR5 Sequence": v["seq"], | |
| "Base Change": v["base_change"], | |
| } | |
| for k, v in results.items() | |
| ] | |
| ) | |
| fig = px.line( | |
| df, | |
| x="Round", | |
| y="Predicted Value", | |
| text="Base Change", | |
| markers=True, | |
| ) | |
| fig.update_layout( | |
| template="plotly_white", | |
| title="UTR5 Optimization Progress", | |
| title_font_family="Arial, sans-serif", | |
| title_font_color="black", | |
| xaxis_title="Mutation Round", | |
| yaxis_title="Predicted Value (RPF)", | |
| xaxis_title_font=dict(color="black"), | |
| yaxis_title_font=dict(color="black"), | |
| font_family="Arial, sans-serif", | |
| font_color="black", | |
| margin=dict(l=50, r=50, t=80, b=50), | |
| ) | |
| fig.update_xaxes( | |
| showgrid=False, | |
| showline=True, | |
| linecolor="black", | |
| tickcolor="black", | |
| ticks="outside", | |
| tickfont_color="black", | |
| ) | |
| fig.update_yaxes( | |
| showgrid=False, | |
| showline=True, | |
| linecolor="black", | |
| tickcolor="black", | |
| ticks="outside", | |
| tickfont_color="black", | |
| tickformat=".2f", | |
| ) | |
| fig.update_traces( | |
| textposition="top center", | |
| marker=dict(color="#cf3326", line=dict(color="#cf3326")), | |
| line=dict(color="#cf3326"), | |
| textfont_color="black", | |
| ) | |
| fig.update_xaxes(dtick=1) | |
| chart_placeholder.plotly_chart(fig, use_container_width=True) | |
| progress_bar.empty() | |
| st.download_button( | |
| "Download Result", | |
| data=df.to_csv(index=False), | |
| file_name="results.csv", | |
| mime="text/csv", | |
| use_container_width=True, | |
| icon="📥", | |
| ) | |