Initial commit - BraceIQMed platform with frontend, API, and brace generator
This commit is contained in:
137
brace-generator/app.py
Normal file
137
brace-generator/app.py
Normal file
@@ -0,0 +1,137 @@
|
||||
"""
|
||||
FastAPI server for Brace Generator.
|
||||
|
||||
Provides REST API for:
|
||||
- X-ray analysis and landmark detection
|
||||
- Cobb angle measurement
|
||||
- Rigo-Chêneau classification
|
||||
- Adaptive brace generation (STL/PLY)
|
||||
|
||||
Usage:
|
||||
uvicorn server.app:app --host 0.0.0.0 --port 8000
|
||||
|
||||
Or with Docker:
|
||||
docker run -p 8000:8000 --gpus all brace-generator
|
||||
"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
# Add parent directories to path for imports
|
||||
server_dir = Path(__file__).parent
|
||||
brace_generator_dir = server_dir.parent
|
||||
spine_dir = brace_generator_dir.parent
|
||||
|
||||
sys.path.insert(0, str(spine_dir))
|
||||
sys.path.insert(0, str(brace_generator_dir))
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
import torch
|
||||
|
||||
from .config import config
|
||||
from .routes import router
|
||||
from .services import BraceService
|
||||
|
||||
|
||||
# Global service instance (initialized on startup)
|
||||
brace_service: BraceService = None
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
"""Initialize and cleanup resources."""
|
||||
global brace_service
|
||||
|
||||
print("=" * 60)
|
||||
print("Brace Generator Server Starting")
|
||||
print("=" * 60)
|
||||
|
||||
# Ensure directories exist
|
||||
config.ensure_dirs()
|
||||
|
||||
# Initialize service with model
|
||||
device = config.get_device()
|
||||
print(f"Device: {device}")
|
||||
|
||||
if device == "cuda":
|
||||
print(f"GPU: {torch.cuda.get_device_name(0)}")
|
||||
print(f"GPU Memory: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.1f} GB")
|
||||
|
||||
print(f"Loading model: {config.MODEL}")
|
||||
brace_service = BraceService(device=device, model=config.MODEL)
|
||||
print("Model loaded successfully!")
|
||||
|
||||
# Make service available to routes
|
||||
app.state.brace_service = brace_service
|
||||
|
||||
print("=" * 60)
|
||||
print(f"Server ready at http://{config.HOST}:{config.PORT}")
|
||||
print("=" * 60)
|
||||
|
||||
yield
|
||||
|
||||
# Cleanup
|
||||
print("Shutting down...")
|
||||
del brace_service
|
||||
|
||||
|
||||
# Create FastAPI app
|
||||
app = FastAPI(
|
||||
title="Brace Generator API",
|
||||
description="""
|
||||
API for generating scoliosis braces from X-ray images.
|
||||
|
||||
## Features
|
||||
- Vertebrae landmark detection (ScolioVis model)
|
||||
- Cobb angle measurement (PT, MT, TL)
|
||||
- Rigo-Chêneau classification
|
||||
- Adaptive brace generation with research-based deformations
|
||||
|
||||
## Experiments
|
||||
- **standard**: Original template-based pipeline
|
||||
- **experiment_3**: Research-based adaptive deformation (Guy et al. 2024)
|
||||
""",
|
||||
version="1.0.0",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
# CORS middleware
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=config.CORS_ORIGINS,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# Include routes
|
||||
app.include_router(router)
|
||||
|
||||
|
||||
# Exception handlers
|
||||
@app.exception_handler(HTTPException)
|
||||
async def http_exception_handler(request, exc):
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content={"error": exc.detail}
|
||||
)
|
||||
|
||||
|
||||
@app.exception_handler(Exception)
|
||||
async def general_exception_handler(request, exc):
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content={"error": "Internal server error", "detail": str(exc)}
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(
|
||||
"server.app:app",
|
||||
host=config.HOST,
|
||||
port=config.PORT,
|
||||
reload=config.DEBUG
|
||||
)
|
||||
Reference in New Issue
Block a user