Spaces:
No application file
No application file
Update app.py
Browse files
app.py
CHANGED
|
@@ -475,16 +475,6 @@ def build_maximum_likelihood_tree(f_gene_sequence):
|
|
| 475 |
|
| 476 |
# --- NEW Tree Analysis Function (Using the new analyzer API) ---
|
| 477 |
def analyze_sequence_for_tree(sequence: str, matching_percentage: float) -> tuple:
|
| 478 |
-
"""
|
| 479 |
-
Analyze sequence and create phylogenetic tree using the new analyzer API
|
| 480 |
-
|
| 481 |
-
Args:
|
| 482 |
-
sequence (str): DNA sequence to analyze
|
| 483 |
-
matching_percentage (float): Similarity threshold percentage
|
| 484 |
-
|
| 485 |
-
Returns:
|
| 486 |
-
tuple: (status_message, html_file_path)
|
| 487 |
-
"""
|
| 488 |
try:
|
| 489 |
if not analyzer:
|
| 490 |
return "❌ Error: Tree analyzer not initialized. Please check if the CSV data file is available.", None
|
|
@@ -495,16 +485,13 @@ def analyze_sequence_for_tree(sequence: str, matching_percentage: float) -> tupl
|
|
| 495 |
if not (1 <= matching_percentage <= 99):
|
| 496 |
return "❌ Error: Matching percentage must be between 1 and 99.", None
|
| 497 |
|
| 498 |
-
# Validate inputs
|
| 499 |
sequence = sequence.strip()
|
| 500 |
if len(sequence) < 10:
|
| 501 |
return "❌ Error: Invalid or missing sequence. Must be ≥10 nucleotides.", None
|
| 502 |
|
| 503 |
-
# Find query sequence
|
| 504 |
if not analyzer.find_query_sequence(sequence):
|
| 505 |
return "❌ Error: Sequence not accepted.", None
|
| 506 |
|
| 507 |
-
# Find similar sequences
|
| 508 |
matched_ids, actual_percentage = analyzer.find_similar_sequences(matching_percentage)
|
| 509 |
|
| 510 |
if not matched_ids:
|
|
@@ -512,13 +499,10 @@ def analyze_sequence_for_tree(sequence: str, matching_percentage: float) -> tupl
|
|
| 512 |
|
| 513 |
logging.info(f"Found {len(matched_ids)} similar sequences at {actual_percentage:.2f}% similarity")
|
| 514 |
|
| 515 |
-
# Build tree structure
|
| 516 |
analyzer.build_tree_structure_with_ml_safe(matched_ids)
|
| 517 |
|
| 518 |
-
# Create interactive tree
|
| 519 |
fig = analyzer.create_interactive_tree(matched_ids, actual_percentage)
|
| 520 |
|
| 521 |
-
# Save to temporary file that Gradio can access
|
| 522 |
temp_dir = tempfile.gettempdir()
|
| 523 |
output_path = os.path.join(temp_dir, 'phylogenetic_tree_interactive.html')
|
| 524 |
fig.write_html(output_path)
|
|
@@ -669,47 +653,41 @@ def run_pipeline(dna_input, similarity_score=95.0, build_ml_tree=False):
|
|
| 669 |
html_file = None
|
| 670 |
tree_html_content = "No tree generated"
|
| 671 |
simplified_ml_output = ""
|
| 672 |
-
|
| 673 |
if analyzer and processed_sequence and len(processed_sequence) >= 10:
|
| 674 |
-
|
| 675 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
|
| 688 |
-
|
| 689 |
-
|
| 690 |
-
|
| 691 |
-
|
| 692 |
-
|
| 693 |
-
|
| 694 |
-
|
| 695 |
-
|
| 696 |
-
|
| 697 |
-
|
| 698 |
-
logging.info(f"Tree analysis completed successfully. HTML saved to: {html_filename}")
|
| 699 |
-
else:
|
| 700 |
-
simplified_ml_output = tree_result or "❌ Failed to generate tree visualization"
|
| 701 |
-
logging.warning("Tree analysis failed or no HTML output generated")
|
| 702 |
-
|
| 703 |
except Exception as e:
|
| 704 |
simplified_ml_output = f"❌ Simplified ML tree analysis failed: {str(e)}"
|
| 705 |
logging.error(f"Simplified ML tree analysis failed: {e}")
|
| 706 |
elif not analyzer:
|
| 707 |
-
|
| 708 |
elif len(processed_sequence) < 10:
|
| 709 |
-
|
| 710 |
else:
|
| 711 |
-
|
| 712 |
-
|
| 713 |
# Prepare final outputs
|
| 714 |
final_boundary_output = f"F gene sequence ({len(processed_sequence)} bp):\n{boundary_output}"
|
| 715 |
final_keras_output = f"F gene validation: {keras_output}"
|
|
@@ -831,13 +809,7 @@ def create_gradio_interface():
|
|
| 831 |
elem_classes=["output-html"]
|
| 832 |
)
|
| 833 |
|
| 834 |
-
|
| 835 |
-
extracted_sequence = gr.Textbox(
|
| 836 |
-
label="Extracted F Gene Sequence",
|
| 837 |
-
lines=10,
|
| 838 |
-
interactive=False,
|
| 839 |
-
info="The F gene sequence extracted by the boundary model"
|
| 840 |
-
)
|
| 841 |
|
| 842 |
with gr.Tab("Download Files"):
|
| 843 |
tree_file = gr.File(
|
|
|
|
| 475 |
|
| 476 |
# --- NEW Tree Analysis Function (Using the new analyzer API) ---
|
| 477 |
def analyze_sequence_for_tree(sequence: str, matching_percentage: float) -> tuple:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 478 |
try:
|
| 479 |
if not analyzer:
|
| 480 |
return "❌ Error: Tree analyzer not initialized. Please check if the CSV data file is available.", None
|
|
|
|
| 485 |
if not (1 <= matching_percentage <= 99):
|
| 486 |
return "❌ Error: Matching percentage must be between 1 and 99.", None
|
| 487 |
|
|
|
|
| 488 |
sequence = sequence.strip()
|
| 489 |
if len(sequence) < 10:
|
| 490 |
return "❌ Error: Invalid or missing sequence. Must be ≥10 nucleotides.", None
|
| 491 |
|
|
|
|
| 492 |
if not analyzer.find_query_sequence(sequence):
|
| 493 |
return "❌ Error: Sequence not accepted.", None
|
| 494 |
|
|
|
|
| 495 |
matched_ids, actual_percentage = analyzer.find_similar_sequences(matching_percentage)
|
| 496 |
|
| 497 |
if not matched_ids:
|
|
|
|
| 499 |
|
| 500 |
logging.info(f"Found {len(matched_ids)} similar sequences at {actual_percentage:.2f}% similarity")
|
| 501 |
|
|
|
|
| 502 |
analyzer.build_tree_structure_with_ml_safe(matched_ids)
|
| 503 |
|
|
|
|
| 504 |
fig = analyzer.create_interactive_tree(matched_ids, actual_percentage)
|
| 505 |
|
|
|
|
| 506 |
temp_dir = tempfile.gettempdir()
|
| 507 |
output_path = os.path.join(temp_dir, 'phylogenetic_tree_interactive.html')
|
| 508 |
fig.write_html(output_path)
|
|
|
|
| 653 |
html_file = None
|
| 654 |
tree_html_content = "No tree generated"
|
| 655 |
simplified_ml_output = ""
|
| 656 |
+
|
| 657 |
if analyzer and processed_sequence and len(processed_sequence) >= 10:
|
| 658 |
+
try:
|
| 659 |
+
logging.info(f"Starting simplified ML tree analysis with F gene sequence length: {len(processed_sequence)}")
|
| 660 |
+
|
| 661 |
+
tree_result, html_path = analyze_sequence_for_tree(processed_sequence, similarity_score)
|
| 662 |
+
|
| 663 |
+
if html_path and os.path.exists(html_path):
|
| 664 |
+
output_dir = "output"
|
| 665 |
+
os.makedirs(output_dir, exist_ok=True)
|
| 666 |
+
|
| 667 |
+
safe_seq_name = re.sub(r'[^a-zA-Z0-9]', '_', processed_sequence[:20])
|
| 668 |
+
html_filename = os.path.join(output_dir, f"tree_{safe_seq_name}_{uuid.uuid4().hex[:8]}.html")
|
| 669 |
+
|
| 670 |
+
shutil.copy2(html_path, html_filename)
|
| 671 |
+
html_file = html_filename
|
| 672 |
+
|
| 673 |
+
with open(html_filename, 'r', encoding='utf-8') as f:
|
| 674 |
+
tree_html_content = f.read()
|
| 675 |
+
|
| 676 |
+
simplified_ml_output = tree_result
|
| 677 |
+
logging.info(f"Tree analysis completed successfully. HTML saved to: {html_filename}")
|
| 678 |
+
else:
|
| 679 |
+
simplified_ml_output = tree_result or "❌ Failed to generate tree visualization"
|
| 680 |
+
logging.warning("Tree analysis failed or no HTML output generated")
|
| 681 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 682 |
except Exception as e:
|
| 683 |
simplified_ml_output = f"❌ Simplified ML tree analysis failed: {str(e)}"
|
| 684 |
logging.error(f"Simplified ML tree analysis failed: {e}")
|
| 685 |
elif not analyzer:
|
| 686 |
+
simplified_ml_output = "❌ Tree analyzer not available (CSV data not loaded)"
|
| 687 |
elif len(processed_sequence) < 10:
|
| 688 |
+
simplified_ml_output = "❌ Sequence too short for tree analysis (minimum 10 bp)"
|
| 689 |
else:
|
| 690 |
+
simplified_ml_output = "Tree analysis skipped"
|
|
|
|
| 691 |
# Prepare final outputs
|
| 692 |
final_boundary_output = f"F gene sequence ({len(processed_sequence)} bp):\n{boundary_output}"
|
| 693 |
final_keras_output = f"F gene validation: {keras_output}"
|
|
|
|
| 809 |
elem_classes=["output-html"]
|
| 810 |
)
|
| 811 |
|
| 812 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 813 |
|
| 814 |
with gr.Tab("Download Files"):
|
| 815 |
tree_file = gr.File(
|