from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from contextlib import asynccontextmanager from pathlib import Path import sys from .routes import classification_router, gestational_age_router, feedback_router from .services.model import model_service # Get assets directory - handle both development and PyInstaller frozen modes def get_assets_dir() -> Path: """Get the assets directory, works in both development and frozen (PyInstaller) modes.""" if getattr(sys, 'frozen', False): # Running as PyInstaller bundle - assets are in _MEIPASS/assets base_path = Path(sys._MEIPASS) assets = base_path / "assets" print(f"[Frozen Mode] Base path: {base_path}") print(f"[Frozen Mode] Assets path: {assets}") return assets else: # Development mode - assets are in project root assets = Path(__file__).parent.parent.parent / "assets" print(f"[Dev Mode] Assets path: {assets}") return assets ASSETS_DIR = get_assets_dir() @asynccontextmanager async def lifespan(app: FastAPI): """Load model on startup, cleanup on shutdown.""" print("🚀 Starting FetalCLIP API...") model_service.load_model(ASSETS_DIR) yield print("👋 Shutting down FetalCLIP API...") app = FastAPI( title="FetalCLIP API", description=""" ## FetalCLIP - Foundation Model for Fetal Ultrasound Analysis This API provides two main capabilities: ### 1. Fetal View Classification Classify ultrasound images into 13 anatomical view categories using zero-shot learning. ### 2. Gestational Age Estimation Estimate gestational age from fetal brain ultrasounds with head circumference percentiles. --- Built with ❤️ using PyTorch and OpenCLIP """, version="1.0.0", lifespan=lifespan, docs_url="/docs", redoc_url="/redoc" ) # CORS middleware for frontend app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:5173", "http://localhost:3000", "http://127.0.0.1:5173", "tauri://localhost"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include routers app.include_router(classification_router) app.include_router(gestational_age_router) app.include_router(feedback_router) @app.get("/", tags=["Health"]) async def root(): """API root - health check.""" return JSONResponse(content={ "name": "FetalCLIP API", "version": "1.0.0", "status": "healthy", "docs": "/docs" }) @app.get("/health", tags=["Health"]) async def health_check(): """Detailed health check.""" return JSONResponse(content={ "status": "healthy", "model_loaded": model_service.model is not None, "device": str(model_service.device), "available_views": len(model_service.list_plane) })