Download backend/api/main.py from OpenPeerAI/CancerAtHomeV2: direct link, hf CLI and curl.
- Browser
- Download file 9.58 kB
-
https://huggingface.co/OpenPeerAI/CancerAtHomeV2/resolve/9a9322605d16de5b6ed93c1925fa7d9c25cf4e9f/backend/api/main.py
- Command line
-
hf download hf://OpenPeerAI/CancerAtHomeV2@9a9322605d16de5b6ed93c1925fa7d9c25cf4e9f/backend/api/main.py
-
curl -L -o main.py https://huggingface.co/OpenPeerAI/CancerAtHomeV2/resolve/9a9322605d16de5b6ed93c1925fa7d9c25cf4e9f/backend/api/main.py
9.58 kB
| """ | |
| FastAPI Main Application | |
| Backend API for Cancer@Home | |
| """ | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.responses import HTMLResponse | |
| from strawberry.fastapi import GraphQLRouter | |
| from pathlib import Path | |
| import uvicorn | |
| from backend.neo4j.graphql_schema import schema | |
| from backend.neo4j.db_manager import DatabaseManager | |
| from backend.boinc.client import BOINCClient, BOINCTaskManager | |
| from backend.gdc.client import GDCClient | |
| from backend.pipeline import ( | |
| FASTQProcessor, | |
| BLASTRunner, | |
| VariantCaller | |
| ) | |
| # Initialize FastAPI | |
| app = FastAPI( | |
| title="Cancer@Home v2", | |
| description="Distributed cancer genomics research platform", | |
| version="2.0.0" | |
| ) | |
| # CORS middleware | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # GraphQL endpoint | |
| graphql_app = GraphQLRouter(schema) | |
| app.include_router(graphql_app, prefix="/graphql") | |
| # Serve frontend static files | |
| frontend_path = Path("frontend/dist") | |
| if frontend_path.exists(): | |
| app.mount("/static", StaticFiles(directory=str(frontend_path)), name="static") | |
| async def root(): | |
| """Serve main dashboard""" | |
| html_file = Path("frontend/index.html") | |
| if html_file.exists(): | |
| with open(html_file, 'r') as f: | |
| return f.read() | |
| # Fallback HTML | |
| return """ | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Cancer@Home v2</title> | |
| <style> | |
| body { | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| margin: 0; | |
| padding: 0; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| } | |
| .container { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 40px 20px; | |
| } | |
| h1 { | |
| font-size: 3em; | |
| margin-bottom: 20px; | |
| } | |
| .card { | |
| background: rgba(255, 255, 255, 0.1); | |
| border-radius: 10px; | |
| padding: 30px; | |
| margin: 20px 0; | |
| backdrop-filter: blur(10px); | |
| } | |
| .links { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); | |
| gap: 20px; | |
| margin-top: 30px; | |
| } | |
| .link-card { | |
| background: rgba(255, 255, 255, 0.15); | |
| border-radius: 8px; | |
| padding: 20px; | |
| text-decoration: none; | |
| color: white; | |
| transition: transform 0.2s; | |
| } | |
| .link-card:hover { | |
| transform: translateY(-5px); | |
| background: rgba(255, 255, 255, 0.25); | |
| } | |
| .link-card h3 { | |
| margin-top: 0; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>๐งฌ Cancer@Home v2</h1> | |
| <div class="card"> | |
| <h2>Welcome to Cancer@Home</h2> | |
| <p>A distributed computing platform for cancer genomics research</p> | |
| </div> | |
| <div class="links"> | |
| <a href="/api/docs" class="link-card"> | |
| <h3>๐ API Documentation</h3> | |
| <p>Interactive API docs with Swagger UI</p> | |
| </a> | |
| <a href="/graphql" class="link-card"> | |
| <h3>๐ GraphQL Playground</h3> | |
| <p>Query cancer data with GraphQL</p> | |
| </a> | |
| <a href="http://localhost:7474" class="link-card"> | |
| <h3>๐ Neo4j Browser</h3> | |
| <p>Visualize graph database</p> | |
| </a> | |
| <a href="/api/health" class="link-card"> | |
| <h3>๐ Health Check</h3> | |
| <p>Check system status</p> | |
| </a> | |
| </div> | |
| </div> | |
| </body> | |
| </html> | |
| """ | |
| async def health_check(): | |
| """Health check endpoint""" | |
| db = DatabaseManager() | |
| try: | |
| db.execute_query("RETURN 1") | |
| neo4j_status = "healthy" | |
| except Exception as e: | |
| neo4j_status = f"unhealthy: {str(e)}" | |
| finally: | |
| db.close() | |
| return { | |
| "status": "healthy", | |
| "neo4j": neo4j_status, | |
| "version": "2.0.0" | |
| } | |
| # BOINC API Endpoints | |
| async def get_boinc_tasks(status: str = None): | |
| """Get BOINC tasks""" | |
| client = BOINCClient() | |
| tasks = client.list_tasks(status=status) | |
| return {"tasks": [vars(t) for t in tasks]} | |
| async def submit_boinc_task(workunit_type: str, input_file: str): | |
| """Submit new BOINC task""" | |
| manager = BOINCTaskManager() | |
| if workunit_type == "variant_calling": | |
| task_id = manager.submit_variant_calling(input_file) | |
| elif workunit_type == "blast_search": | |
| task_id = manager.submit_blast_search(input_file) | |
| else: | |
| task_id = manager.client.submit_task(workunit_type, input_file) | |
| return {"task_id": task_id, "status": "submitted"} | |
| async def get_boinc_statistics(): | |
| """Get BOINC statistics""" | |
| client = BOINCClient() | |
| stats = client.get_statistics() | |
| return stats | |
| # GDC API Endpoints | |
| async def get_gdc_projects(): | |
| """Get available GDC projects""" | |
| projects = [ | |
| {"id": "TCGA-BRCA", "name": "Breast Cancer", "cases": 1098}, | |
| {"id": "TCGA-LUAD", "name": "Lung Adenocarcinoma", "cases": 585}, | |
| {"id": "TCGA-COAD", "name": "Colon Adenocarcinoma", "cases": 461}, | |
| {"id": "TCGA-GBM", "name": "Glioblastoma", "cases": 617}, | |
| {"id": "TARGET-AML", "name": "Acute Myeloid Leukemia", "cases": 238}, | |
| ] | |
| return {"projects": projects} | |
| async def search_gdc_files(project_id: str, limit: int = 10): | |
| """Search GDC files for a project""" | |
| client = GDCClient() | |
| files = client.get_project_files(project_id, limit=limit) | |
| return {"files": [vars(f) for f in files]} | |
| async def download_gdc_file(file_id: str): | |
| """Download a file from GDC""" | |
| client = GDCClient() | |
| file_path = client.download_file(file_id) | |
| if file_path: | |
| return {"status": "success", "file_path": str(file_path)} | |
| else: | |
| raise HTTPException(status_code=500, detail="Download failed") | |
| # Pipeline API Endpoints | |
| async def run_fastq_qc(file_path: str): | |
| """Run FASTQ quality control""" | |
| processor = FASTQProcessor() | |
| stats = processor.calculate_statistics(Path(file_path)) | |
| return {"statistics": stats} | |
| async def run_blast(query_file: str): | |
| """Run BLAST search""" | |
| runner = BLASTRunner() | |
| output_file = runner.run_blastn(Path(query_file)) | |
| if output_file: | |
| hits = runner.parse_results(output_file) | |
| return { | |
| "status": "success", | |
| "output_file": str(output_file), | |
| "total_hits": len(hits), | |
| "hits": hits[:10] # Return first 10 hits | |
| } | |
| else: | |
| raise HTTPException(status_code=500, detail="BLAST search failed") | |
| async def call_variants(alignment_file: str, reference_genome: str): | |
| """Call variants from alignment""" | |
| caller = VariantCaller() | |
| vcf_file = caller.call_variants( | |
| Path(alignment_file), | |
| Path(reference_genome) | |
| ) | |
| variants = caller.filter_variants(vcf_file) | |
| return { | |
| "status": "success", | |
| "vcf_file": str(vcf_file), | |
| "total_variants": len(variants), | |
| "variants": [vars(v) for v in variants] | |
| } | |
| # Neo4j Query Endpoints | |
| async def get_database_summary(): | |
| """Get database summary statistics""" | |
| db = DatabaseManager() | |
| query = """ | |
| MATCH (g:Gene) WITH count(g) as genes | |
| MATCH (m:Mutation) WITH genes, count(m) as mutations | |
| MATCH (p:Patient) WITH genes, mutations, count(p) as patients | |
| MATCH (c:CancerType) WITH genes, mutations, patients, count(c) as cancer_types | |
| RETURN genes, mutations, patients, cancer_types | |
| """ | |
| result = db.execute_query(query) | |
| db.close() | |
| return result[0] if result else {} | |
| async def get_gene_info(symbol: str): | |
| """Get gene information""" | |
| db = DatabaseManager() | |
| from backend.neo4j.db_manager import GeneRepository | |
| repo = GeneRepository(db) | |
| gene = repo.get_gene_by_symbol(symbol) | |
| if gene: | |
| mutations = repo.get_gene_mutations(gene['gene_id']) | |
| db.close() | |
| return { | |
| "gene": gene, | |
| "mutations": mutations, | |
| "mutation_count": len(mutations) | |
| } | |
| db.close() | |
| raise HTTPException(status_code=404, detail="Gene not found") | |
| if __name__ == "__main__": | |
| uvicorn.run(app, host="0.0.0.0", port=5000) | |