re-type commited on
Commit
63e23c8
·
verified ·
1 Parent(s): 39b502f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +141 -97
app.py CHANGED
@@ -398,7 +398,7 @@ Tree Analysis: {'✅ OK' if 'Found' in simplified_ml_output else '❌ Failed'}
398
  error_msg = f"❌ Pipeline Error: {str(e)}"
399
  return error_msg, "", "", "", "", None, None, None, None, error_msg, error_msg
400
 
401
- async def run_pipeline_from_file(fasta_file_obj, similarity_score, build_ml_tree):
402
  try:
403
  dna_input = read_fasta_file(fasta_file_obj)
404
  if not dna_input:
@@ -493,7 +493,7 @@ async def analyze_file(
493
  content = await file.read()
494
  temp_file.write(content)
495
  temp_file_path = temp_file.name
496
- result = await run_pipeline_from_file(temp_file_path, similarity_score, build_ml_tree)
497
  return AnalysisResponse(
498
  boundary_output=result[0] or "",
499
  keras_output=result[1] or "",
@@ -516,14 +516,13 @@ async def analyze_file(
516
  except:
517
  pass
518
 
519
- # --- Gradio Interface ---
520
  # --- Gradio Interface ---
521
  def create_gradio_interface():
522
  logger.info("Attempting to create Gradio interface...")
523
  try:
524
  with gr.Blocks(
525
  title="🧬 Gene Analysis Pipeline",
526
- theme="default", # Simplify theme to reduce resource usage
527
  css="""
528
  .gradio-container { max-width: 1200px !important; }
529
  .status-box { padding: 10px; border-radius: 5px; margin: 5px 0; }
@@ -631,115 +630,160 @@ def create_gradio_interface():
631
  label="Analysis Report",
632
  value="<div style='text-align: center; padding: 20px; color: #666;'>No report generated yet.</div>"
633
  )
 
 
634
  analyze_btn.click(
635
  fn=run_pipeline,
636
  inputs=[dna_input, similarity_score, build_ml_tree],
637
  outputs=[
638
- boundary_output, keras_output, ml_tree_output,
639
- tree_analysis_output, summary_output,
640
- aligned_file, tree_file, gr.State(), gr.State(),
641
- tree_html, report_html
642
  ]
643
  )
 
644
  analyze_file_btn.click(
645
  fn=run_pipeline_from_file,
646
  inputs=[file_input, file_similarity_score, file_build_ml_tree],
647
  outputs=[
648
- boundary_output, keras_output, ml_tree_output,
649
- tree_analysis_output, summary_output,
650
- aligned_file, tree_file, gr.State(), gr.State(),
651
- tree_html, report_html
652
  ]
653
  )
654
- gr.Markdown("## 🔬 Example Sequences")
655
- example_sequences = [
656
- ["ATGGACTTCCAAATTAACAACCTCAACAACCTCAACAACATCAACAACATCAACAACATCAACAACATCAACAAC", 90.0, False],
657
- ["ATGAAACAAATTAACAACCTCAACAACCTCAACAACATCAACAACATCAACAACATCAACAACATCAACAACATCAACAACATCAACAACATCAACAACATCAACAACATCAACAAC", 85.0, True]
658
- ]
659
- gr.Examples(
660
- examples=example_sequences,
661
- inputs=[dna_input, similarity_score, build_ml_tree],
662
- label="Click to load example sequences"
663
- )
664
- with gr.Accordion("❓ Help & Information", open=False):
665
- gr.Markdown("""
666
- ### 🧬 Gene Analysis Pipeline
667
- This tool performs comprehensive analysis of F gene sequences:
668
- **🎯 Boundary Detection**: Identifies F gene regions within your sequence
669
- **🧠 F Gene Validation**: Validates sequence as F gene using deep learning
670
- **🌲 Phylogenetic Placement**: Places sequence in reference phylogeny
671
- **🌳 Tree Analysis**: Finds similar sequences and builds interactive trees
672
- ### 📋 Input Requirements
673
- - DNA sequences in ATCG format
674
- - Minimum 10 bp for basic analysis
675
- - Minimum 100 bp for phylogenetic placement
676
- - FASTA files supported for upload
677
- ### ⚙️ Parameters
678
- - **Similarity Threshold**: Minimum % similarity for tree analysis (1-99%)
679
- - **Build ML Tree**: Enable phylogenetic placement (requires MAFFT/IQ-TREE)
680
- ### 📊 Output Files
681
- - Alignment files (.fa format)
682
- - Tree files (.treefile format)
683
- - Interactive HTML visualizations
684
- """)
685
- logger.info("Gradio interface created successfully")
686
- return iface
687
  except Exception as e:
688
- logger.error(f"Failed to create Gradio interface: {str(e)}", exc_info=True)
689
- return None
690
- # --- Application Startup ---
691
- def mount_gradio_app():
692
- logger.info("Mounting Gradio app...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
693
  try:
 
694
  gradio_app = create_gradio_interface()
695
- if gradio_app:
696
- global app
697
- app = gr.mount_gradio_app(app, gradio_app, path="/gradio")
698
- logger.info("✅ Gradio interface mounted at /gradio")
699
- else:
700
  logger.error("❌ Failed to create Gradio interface")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
701
  except Exception as e:
702
- logger.error(f"❌ Failed to mount Gradio app: {str(e)}", exc_info=True)
703
-
704
- # Initialize Gradio
705
- mount_gradio_app()
 
 
 
 
 
 
 
 
 
 
706
 
707
- # --- Main Application ---
708
  if __name__ == "__main__":
709
- import argparse
710
- parser = argparse.ArgumentParser(description="🧬 Gene Analysis Pipeline")
711
- parser.add_argument("--host", default="0.0.0.0", help="Host address")
712
- parser.add_argument("--port", type=int, default=7860, help="Port number")
713
- parser.add_argument("--reload", action="store_true", help="Enable auto-reload")
714
- parser.add_argument("--gradio-only", action="store_true", help="Run Gradio interface only")
715
- args = parser.parse_args()
716
- if args.gradio_only:
717
- logger.info("🚀 Starting Gradio interface only...")
718
- iface = create_gradio_interface()
719
- if iface:
720
- iface.launch(
721
- server_name=args.host,
722
- server_port=args.port,
723
- share=False,
724
- show_error=True
725
- )
726
- else:
727
- logger.error("❌ Failed to create Gradio interface")
728
- sys.exit(1)
729
- else:
730
- logger.info(f"🚀 Starting Gene Analysis Pipeline on {args.host}:{args.port}")
731
- logger.info("📊 API Documentation: http://localhost:7860/docs")
732
- logger.info("🧬 Gradio Interface: http://localhost:7860/gradio")
733
- try:
734
- uvicorn.run(
735
- "app:app" if args.reload else app,
736
- host=args.host,
737
- port=args.port,
738
- reload=args.reload,
739
- log_level="info"
740
- )
741
- except KeyboardInterrupt:
742
- logger.info("🛑 Application stopped by user")
743
- except Exception as e:
744
- logger.error(f"❌ Application failed: {e}")
745
- sys.exit(1)
 
398
  error_msg = f"❌ Pipeline Error: {str(e)}"
399
  return error_msg, "", "", "", "", None, None, None, None, error_msg, error_msg
400
 
401
+ def run_pipeline_from_file(fasta_file_obj, similarity_score, build_ml_tree):
402
  try:
403
  dna_input = read_fasta_file(fasta_file_obj)
404
  if not dna_input:
 
493
  content = await file.read()
494
  temp_file.write(content)
495
  temp_file_path = temp_file.name
496
+ result = run_pipeline_from_file(temp_file_path, similarity_score, build_ml_tree)
497
  return AnalysisResponse(
498
  boundary_output=result[0] or "",
499
  keras_output=result[1] or "",
 
516
  except:
517
  pass
518
 
 
519
  # --- Gradio Interface ---
520
  def create_gradio_interface():
521
  logger.info("Attempting to create Gradio interface...")
522
  try:
523
  with gr.Blocks(
524
  title="🧬 Gene Analysis Pipeline",
525
+ theme=gr.themes.Default(), # Use proper theme object
526
  css="""
527
  .gradio-container { max-width: 1200px !important; }
528
  .status-box { padding: 10px; border-radius: 5px; margin: 5px 0; }
 
630
  label="Analysis Report",
631
  value="<div style='text-align: center; padding: 20px; color: #666;'>No report generated yet.</div>"
632
  )
633
+
634
+ # Event handlers
635
  analyze_btn.click(
636
  fn=run_pipeline,
637
  inputs=[dna_input, similarity_score, build_ml_tree],
638
  outputs=[
639
+ boundary_output, keras_output, ml_tree_output, tree_analysis_output,
640
+ summary_output, aligned_file, tree_file, gr.File(visible=False),
641
+ gr.File(visible=False), tree_html, report_html
 
642
  ]
643
  )
644
+
645
  analyze_file_btn.click(
646
  fn=run_pipeline_from_file,
647
  inputs=[file_input, file_similarity_score, file_build_ml_tree],
648
  outputs=[
649
+ boundary_output, keras_output, ml_tree_output, tree_analysis_output,
650
+ summary_output, aligned_file, tree_file, gr.File(visible=False),
651
+ gr.File(visible=False), tree_html, report_html
 
652
  ]
653
  )
654
+
655
+ gr.Markdown("""
656
+ ## 📖 Instructions
657
+
658
+ ### 🧬 Input Methods:
659
+ - **Text Input**: Paste your DNA sequence directly
660
+ - **File Upload**: Upload a FASTA file (.fasta, .fa, .fas, .txt)
661
+
662
+ ### ⚙️ Parameters:
663
+ - **Similarity Threshold**: Minimum similarity percentage for phylogenetic tree analysis (1-99%)
664
+ - **Build ML Tree**: Enable for maximum likelihood phylogenetic placement (computationally intensive)
665
+
666
+ ### 📊 Analysis Steps:
667
+ 1. **Boundary Detection**: Identifies F gene regions within your sequence
668
+ 2. **F Gene Validation**: Validates the sequence as an F gene using neural networks
669
+ 3. **Phylogenetic Placement**: Places sequence in reference phylogenetic tree (optional)
670
+ 4. **Tree Analysis**: Builds similarity-based phylogenetic tree with interactive visualization
671
+
672
+ ### 🔬 Results:
673
+ - **Interactive Tree**: Explore phylogenetic relationships
674
+ - **Detailed Report**: Comprehensive analysis including evolutionary insights
675
+ - **Downloadable Files**: Alignment and tree files for further analysis
676
+
677
+ ### ⚠️ Notes:
678
+ - Sequences should be in DNA format (A, T, G, C, N)
679
+ - Minimum 10 bp for basic analysis, 100 bp for phylogenetic placement
680
+ - ML tree generation may take several minutes for large sequences
681
+ """)
682
+
683
+ logger.info("✅ Gradio interface created successfully")
684
+ return iface
685
+
 
686
  except Exception as e:
687
+ logger.error(f"❌ Failed to create Gradio interface: {e}")
688
+ # Fallback simple interface
689
+ try:
690
+ simple_iface = gr.Interface(
691
+ fn=lambda x: f"Error creating interface: {str(e)}",
692
+ inputs=gr.Textbox(label="Input"),
693
+ outputs=gr.Textbox(label="Output"),
694
+ title="🧬 Gene Analysis Pipeline - Error"
695
+ )
696
+ logger.info("⚠️ Fallback interface created")
697
+ return simple_iface
698
+ except Exception as fallback_error:
699
+ logger.error(f"❌ Even fallback interface failed: {fallback_error}")
700
+ return None
701
+
702
+ # --- App Mounting and Launch ---
703
+ def main():
704
+ """Main function to launch the application."""
705
+ logger.info("🚀 Starting Gene Analysis Pipeline...")
706
+
707
  try:
708
+ # Create Gradio interface
709
  gradio_app = create_gradio_interface()
710
+
711
+ if gradio_app is None:
 
 
 
712
  logger.error("❌ Failed to create Gradio interface")
713
+ return
714
+
715
+ # Mount Gradio app to FastAPI
716
+ try:
717
+ app.mount("/gradio", gradio_app.queue(), name="gradio")
718
+ logger.info("✅ Gradio mounted to FastAPI at /gradio")
719
+ except Exception as e:
720
+ logger.error(f"❌ Failed to mount Gradio: {e}")
721
+ # Try alternative mounting
722
+ try:
723
+ gradio_app = gr.mount_gradio_app(app, gradio_app, path="/gradio")
724
+ logger.info("✅ Gradio mounted using alternative method")
725
+ except Exception as alt_error:
726
+ logger.error(f"❌ Alternative mounting also failed: {alt_error}")
727
+
728
+ # Launch configuration
729
+ port = int(os.environ.get("PORT", 7860))
730
+ host = "0.0.0.0"
731
+
732
+ logger.info(f"🌐 Launching on {host}:{port}")
733
+ logger.info(f"📱 FastAPI docs: http://{host}:{port}/docs")
734
+ logger.info(f"🧬 Gradio interface: http://{host}:{port}/gradio")
735
+
736
+ # Launch the server
737
+ uvicorn.run(
738
+ app,
739
+ host=host,
740
+ port=port,
741
+ log_level="info",
742
+ access_log=True,
743
+ reload=False # Set to True for development
744
+ )
745
+
746
  except Exception as e:
747
+ logger.error(f"❌ Failed to launch application: {e}")
748
+ # Fallback: Launch only Gradio
749
+ try:
750
+ logger.info("🔄 Attempting fallback Gradio-only launch...")
751
+ gradio_app = create_gradio_interface()
752
+ if gradio_app:
753
+ gradio_app.launch(
754
+ server_name="0.0.0.0",
755
+ server_port=7860,
756
+ share=False,
757
+ debug=False
758
+ )
759
+ except Exception as fallback_error:
760
+ logger.error(f"❌ Fallback launch failed: {fallback_error}")
761
 
 
762
  if __name__ == "__main__":
763
+ main()
764
+
765
+ # Alternative entry points for different deployment scenarios
766
+ def launch_gradio_only():
767
+ """Launch only Gradio interface (for simpler deployments)"""
768
+ logger.info("🚀 Launching Gradio-only mode...")
769
+ gradio_app = create_gradio_interface()
770
+ if gradio_app:
771
+ gradio_app.launch(
772
+ server_name="0.0.0.0",
773
+ server_port=int(os.environ.get("PORT", 7860)),
774
+ share=False,
775
+ debug=False
776
+ )
777
+
778
+ def launch_fastapi_only():
779
+ """Launch only FastAPI (for API-only deployments)"""
780
+ logger.info("🚀 Launching FastAPI-only mode...")
781
+ port = int(os.environ.get("PORT", 8000))
782
+ uvicorn.run(
783
+ app,
784
+ host="0.0.0.0",
785
+ port=port,
786
+ log_level="info",
787
+ access_log=True,
788
+ reload=False
789
+ )