Microbiome Stability Scoring Explorer
Upload raw FASTA, translate a MicrobeAtlas sample into representative OTU sequences,
or build a synthetic community by taxonomy. Every route ends in the same pipeline:
ProkBERT mean pooling, large-notext scoring, and linked embedding views.
"""
)
with gr.Tabs():
with gr.Tab("Raw FASTA"):
with gr.Column(elem_classes=["soft-card"]):
gr.Markdown(
"Upload genes directly in FASTA format. Sequences longer than 1024 nt are trimmed and only the first 800 records are used."
)
fasta_in = gr.File(
label="FASTA file",
file_types=[".fa", ".fasta", ".fna", ".txt"],
type="filepath",
)
fasta_run_btn = gr.Button("Analyze FASTA", variant="primary")
with gr.Tab("Import From MicrobeAtlas"):
with gr.Column(elem_classes=["soft-card"]):
gr.Markdown(
f"""
Bring in a taxa file exported from MicrobeAtlas. Go to
[MicrobeAtlas sample detail]({MICROBEATLAS_SAMPLE_URL}), click `Download`, and upload the taxa TSV here.
OTU IDs from `SHORT_TID` are translated to representative sequences using `otus.97.allinfo`.
"""
)
microbeatlas_in = gr.File(
label="MicrobeAtlas taxa TSV",
file_types=[".tsv", ".txt"],
type="filepath",
)
if os.path.exists(EXAMPLE_SAMPLE_PATH):
gr.Examples(
examples=[[EXAMPLE_SAMPLE_PATH]],
inputs=[microbeatlas_in],
label="Use example",
)
else:
gr.Markdown(
"Example file not bundled in this deployment. Upload a MicrobeAtlas taxa TSV exported from the sample page above."
)
microbeatlas_run_btn = gr.Button("Translate And Analyze", variant="primary")
with gr.Tab("Build A Community"):
with gr.Column(elem_classes=["soft-card"]):
gr.Markdown(
"Search the OTU index by OTU ID, taxon label, or taxonomy string. Matching OTUs appear directly below as you type, so you can add them without opening another widget."
)
with gr.Row():
taxa_query = gr.Textbox(
label="Search taxa",
placeholder="Try Nitrospira, Lysobacter, Gammaproteobacteria, 97_8697 ...",
scale=6,
)
community_search_status = gr.Markdown(elem_classes=["section-note"])
taxa_matches = gr.CheckboxGroup(
label="Matching OTUs",
choices=[],
value=[],
elem_classes=["search-results"],
)
with gr.Row():
community_add_btn = gr.Button("Add Selected OTUs", variant="primary")
community_clear_btn = gr.Button("Clear Community")
community_run_btn = gr.Button("Analyze Community", variant="secondary")
with gr.Accordion("Community Members", open=True):
community_table = gr.Dataframe(
headers=["id", "taxonomy"],
label="Current community",
wrap=True,
elem_classes=["fixed-table"],
)
community_status = gr.Markdown(elem_classes=["section-note"])
with gr.Accordion("Analysis Results", open=True):
run_summary = gr.Textbox(label="Run summary")
with gr.Row():
input_umap_plot = gr.Plot(label="Input embedding UMAP")
final_umap_plot = gr.Plot(label="Final embedding UMAP")
logits_plot = gr.Plot(label="Stability score distribution")
with gr.Accordion("Top-scoring members", open=False):
top_download = gr.DownloadButton("Download top members TSV")
top_table = gr.Dataframe(
headers=["id", "stability_score", "taxonomy"],
label="Top members by stability score",
wrap=True,
elem_classes=["fixed-table"],
)
with gr.Accordion("Analyzed members", open=False):
member_download = gr.DownloadButton("Download analyzed members TSV")
member_table = gr.Dataframe(
headers=["id", "stability_score", "taxonomy"],
label="Members used in the run",
wrap=True,
elem_classes=["fixed-table"],
)
fasta_run_btn.click(
fn=analyze_fasta,
inputs=[fasta_in],
outputs=[run_summary, input_umap_plot, final_umap_plot, logits_plot, top_table, member_table, top_download, member_download],
)
microbeatlas_run_btn.click(
fn=analyze_microbeatlas,
inputs=[microbeatlas_in],
outputs=[run_summary, input_umap_plot, final_umap_plot, logits_plot, top_table, member_table, top_download, member_download],
)
taxa_query.change(
fn=search_taxa,
inputs=[taxa_query],
outputs=[taxa_matches, community_search_status],
)
community_add_btn.click(
fn=add_to_community,
inputs=[taxa_matches, community_state],
outputs=[community_state, community_table, community_status],
)
community_clear_btn.click(
fn=clear_community,
outputs=[community_state, community_table, community_status],
)
community_run_btn.click(
fn=analyze_community,
inputs=[community_state],
outputs=[run_summary, input_umap_plot, final_umap_plot, logits_plot, top_table, member_table, top_download, member_download],
)
if __name__ == "__main__":
demo.queue().launch()