UTR-CODE / src /web_page /webui_optimization.py
xinHesysu's picture
Update src/web_page/webui_optimization.py
a9090c5 verified
Raw History Blame Contribute Delete
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="📥",
)