Initial commit - BraceIQMed platform with frontend, API, and brace generator

This commit is contained in:
2026-01-29 14:34:05 -08:00
commit 745f9f827f
187 changed files with 534688 additions and 0 deletions

137
brace-generator/app.py Normal file
View 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
)