melvinalves commited on
Commit
3b8f083
·
verified ·
1 Parent(s): 166688e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -32
app.py CHANGED
@@ -42,7 +42,7 @@ def load_hf_encoder(repo_id, subfolder=None, base_tok=None):
42
  """
43
  • repo_id : repositório HF ou caminho local
44
  • subfolder : subpasta onde vivem pesos/config (None se não houver)
45
- • base_tok : repo para o tokenizer (None usa repo_id)
46
  Converte tf_model.h5 → PyTorch on-the-fly (from_tf=True).
47
  """
48
  if base_tok is None:
@@ -100,7 +100,7 @@ GO = mlb.classes_
100
  st.set_page_config(page_title="Predição de Funções Moleculares de Proteínas",
101
  page_icon="🧬", layout="centered")
102
 
103
- # CSS global: fundo branco, divisão de colunas e margem do logo
104
  st.markdown(
105
  """
106
  <style>
@@ -108,14 +108,11 @@ st.markdown(
108
  .block-container { padding-top: 1.5rem; }
109
  textarea { font-size: 0.9rem !important; }
110
 
111
- /* traço vertical entre as colunas de resultados */
112
  div[data-testid="column"]:first-child {
113
  border-right: 1px solid #E0E0E0;
114
- padding-right: 1.2rem;
115
  }
116
-
117
- /* margem extra para o logo */
118
- img.logo { margin-top: 0.5rem; }
119
  </style>
120
  """,
121
  unsafe_allow_html=True
@@ -124,8 +121,7 @@ st.markdown(
124
  # Logo (coloca logo.png na raiz do Space)
125
  LOGO_PATH = "logo.png"
126
  if os.path.exists(LOGO_PATH):
127
- st.markdown(f"<img src='{LOGO_PATH}' width='180' class='logo'/>",
128
- unsafe_allow_html=True)
129
 
130
  st.title("Predição de Funções Moleculares de Proteínas (GO:MF)")
131
 
@@ -143,49 +139,57 @@ def parse_fasta_multiple(fasta_str):
143
  if not entry.strip():
144
  continue
145
  lines = entry.strip().splitlines()
146
- if i > 0:
147
  header = lines[0].strip()
148
  seq = "".join(lines[1:]).replace(" ", "").upper()
149
- else:
150
  header = f"Seq_{i+1}"
151
  seq = "".join(lines).replace(" ", "").upper()
152
  if seq:
153
  parsed.append((header, seq))
154
  return parsed
155
 
156
- # ——————————————————— FUNÇÕES AUXILIARES ——————————————————— #
157
  def go_link(go_id, name=""):
158
- """Markdown link para QuickGO."""
159
  url = f"https://www.ebi.ac.uk/QuickGO/term/{go_id}"
160
  label = f"{go_id} — {name}" if name else go_id
161
  return f"[{label}]({url})"
162
 
163
- def uni_url(header):
164
- """URL UniProt (primeiro token do header)."""
165
- return f"https://www.uniprot.org/uniprotkb/{header.split()[0]}"
166
-
167
- # ——————————————————— MOSTRAR RESULTADOS ——————————————————— #
168
  def mostrar(header, y_pred):
169
- """Expander com botão UniProt + duas colunas de resultados."""
170
- with st.expander(header, expanded=True):
171
- # botão que abre UniProt noutra aba (necessita Streamlit ≥1.23)
172
- try:
173
- st.link_button("🔗 Ver na UniProt", uni_url(header), type="primary")
174
- except AttributeError:
175
- st.markdown(f"[🔗 Ver na UniProt]({uni_url(header)})")
176
 
177
- st.markdown("---")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
 
179
  col1, col2 = st.columns(2)
180
 
181
- # --- coluna 1 : termos acima do threshold
182
  with col1:
183
  st.markdown(f"**GO terms com prob ≥ {THRESH}**")
184
  hits = mlb.inverse_transform((y_pred >= THRESH).astype(int))[0]
185
  if hits:
186
  for go_id in hits:
187
  name, defin = GO_INFO.get(go_id, ("— sem nome —", ""))
188
- defin = re.sub(r'^\\s*\"?(.+?)\"?\\s*(\\[[^\\]]*\\])?\\s*$', r'\\1',
189
  defin or "")
190
  st.markdown(f"- {go_link(go_id, name)}")
191
  if defin:
@@ -193,7 +197,7 @@ def mostrar(header, y_pred):
193
  else:
194
  st.code("— nenhum —")
195
 
196
- # --- coluna 2 : top-N mais prováveis
197
  with col2:
198
  st.markdown(f"**Top {TOP_N} GO terms mais prováveis**")
199
  for rank, idx in enumerate(np.argsort(-y_pred[0])[:TOP_N], start=1):
@@ -210,22 +214,23 @@ if predict_clicked:
210
 
211
  for header, seq in parsed_seqs:
212
  with st.spinner(f"A processar {header}… (pode demorar alguns minutos)"):
213
- # ---------- EMBEDDINGS ----------
214
  emb_pb = embed_seq(FINETUNED_PB, seq, CHUNK_PB)
215
  emb_bfd = embed_seq(FINETUNED_BFD, seq, CHUNK_PB)
216
  emb_esm = embed_seq(BASE_ESM, seq, CHUNK_ESM)
217
 
218
- # ---------- PREDIÇÕES ----------
219
  y_pb = mlp_pb.predict(emb_pb)
220
  y_bfd = mlp_bfd.predict(emb_bfd)
221
  y_esm = mlp_esm.predict(emb_esm)[:, :597] # alinhar nº de termos
222
 
 
223
  X = np.concatenate([y_pb, y_bfd, y_esm], axis=1)
224
  y_ens = stacking.predict(X)
225
 
226
  mostrar(header, y_ens)
227
 
228
- # ——————————————————— LISTA COMPLETA ——————————————————— #
229
  with st.expander("Mostrar lista completa dos 597 GO terms possíveis", expanded=False):
230
  cols = st.columns(3)
231
  for i, go_id in enumerate(GO):
 
42
  """
43
  • repo_id : repositório HF ou caminho local
44
  • subfolder : subpasta onde vivem pesos/config (None se não houver)
45
+ • base_tok : repo para o tokenizer (None => usa repo_id)
46
  Converte tf_model.h5 → PyTorch on-the-fly (from_tf=True).
47
  """
48
  if base_tok is None:
 
100
  st.set_page_config(page_title="Predição de Funções Moleculares de Proteínas",
101
  page_icon="🧬", layout="centered")
102
 
103
+ # Fundo branco + separador de colunas
104
  st.markdown(
105
  """
106
  <style>
 
108
  .block-container { padding-top: 1.5rem; }
109
  textarea { font-size: 0.9rem !important; }
110
 
111
+ /* traço vertical entre primeiras colunas */
112
  div[data-testid="column"]:first-child {
113
  border-right: 1px solid #E0E0E0;
114
+ padding-right: 1rem !important;
115
  }
 
 
 
116
  </style>
117
  """,
118
  unsafe_allow_html=True
 
121
  # Logo (coloca logo.png na raiz do Space)
122
  LOGO_PATH = "logo.png"
123
  if os.path.exists(LOGO_PATH):
124
+ st.image(LOGO_PATH, width=180)
 
125
 
126
  st.title("Predição de Funções Moleculares de Proteínas (GO:MF)")
127
 
 
139
  if not entry.strip():
140
  continue
141
  lines = entry.strip().splitlines()
142
+ if i > 0: # bloco típico FASTA
143
  header = lines[0].strip()
144
  seq = "".join(lines[1:]).replace(" ", "").upper()
145
+ else: # sequência sem '>'
146
  header = f"Seq_{i+1}"
147
  seq = "".join(lines).replace(" ", "").upper()
148
  if seq:
149
  parsed.append((header, seq))
150
  return parsed
151
 
152
+ # ——————————————————— FUNÇÕES AUXILIARES DE LAYOUT ——————————————————— #
153
  def go_link(go_id, name=""):
154
+ """Cria link para página do GO term (QuickGO)."""
155
  url = f"https://www.ebi.ac.uk/QuickGO/term/{go_id}"
156
  label = f"{go_id} — {name}" if name else go_id
157
  return f"[{label}]({url})"
158
 
159
+ # ——————————————————— FUNÇÃO PRINCIPAL DE RESULTADOS ——————————————————— #
 
 
 
 
160
  def mostrar(header, y_pred):
161
+ """Mostra resultados (botão UniProt + duas colunas)."""
162
+ prot_id = header.split()[0]
163
+ prot_url = f"https://www.uniprot.org/uniprotkb/{prot_id}"
 
 
 
 
164
 
165
+ with st.expander(header, expanded=True):
166
+ # Botão «Visitar UniProt»
167
+ st.markdown(
168
+ f"""
169
+ <div style="text-align:right; margin-bottom:0.5rem;">
170
+ <a href="{prot_url}" target="_blank">
171
+ <button style="
172
+ background:#2b8cbe;border:none;border-radius:4px;
173
+ padding:0.35rem 0.8rem;color:#fff;font-size:0.9rem;
174
+ cursor:pointer;">
175
+ Visitar UniProt
176
+ </button>
177
+ </a>
178
+ </div>
179
+ """,
180
+ unsafe_allow_html=True
181
+ )
182
 
183
  col1, col2 = st.columns(2)
184
 
185
+ # ——— coluna 1 : termos acima do threshold
186
  with col1:
187
  st.markdown(f"**GO terms com prob ≥ {THRESH}**")
188
  hits = mlb.inverse_transform((y_pred >= THRESH).astype(int))[0]
189
  if hits:
190
  for go_id in hits:
191
  name, defin = GO_INFO.get(go_id, ("— sem nome —", ""))
192
+ defin = re.sub(r'^\\s*"?(.+?)"?\\s*(\\[[^\\]]*\\])?\\s*$', r'\\1',
193
  defin or "")
194
  st.markdown(f"- {go_link(go_id, name)}")
195
  if defin:
 
197
  else:
198
  st.code("— nenhum —")
199
 
200
+ # ——— coluna 2 : top-N mais prováveis
201
  with col2:
202
  st.markdown(f"**Top {TOP_N} GO terms mais prováveis**")
203
  for rank, idx in enumerate(np.argsort(-y_pred[0])[:TOP_N], start=1):
 
214
 
215
  for header, seq in parsed_seqs:
216
  with st.spinner(f"A processar {header}… (pode demorar alguns minutos)"):
217
+ # ———————————— EMBEDDINGS ———————————— #
218
  emb_pb = embed_seq(FINETUNED_PB, seq, CHUNK_PB)
219
  emb_bfd = embed_seq(FINETUNED_BFD, seq, CHUNK_PB)
220
  emb_esm = embed_seq(BASE_ESM, seq, CHUNK_ESM)
221
 
222
+ # ———————————— PREDIÇÕES MLPs ———————————— #
223
  y_pb = mlp_pb.predict(emb_pb)
224
  y_bfd = mlp_bfd.predict(emb_bfd)
225
  y_esm = mlp_esm.predict(emb_esm)[:, :597] # alinhar nº de termos
226
 
227
+ # ———————————— STACKING ———————————— #
228
  X = np.concatenate([y_pb, y_bfd, y_esm], axis=1)
229
  y_ens = stacking.predict(X)
230
 
231
  mostrar(header, y_ens)
232
 
233
+ # ——————————————————— LISTA COMPLETA DE TERMOS SUPORTADOS ——————————————————— #
234
  with st.expander("Mostrar lista completa dos 597 GO terms possíveis", expanded=False):
235
  cols = st.columns(3)
236
  for i, go_id in enumerate(GO):