# Brace Generator Integration Guide ## Overview This document describes how the GPU-based brace generator is integrated into the Braceflow frontend via AWS Lambda functions. ## Architecture ``` Frontend (React) │ ├── Upload X-ray │ └── POST /cases → Create case │ └── POST /cases/{caseId}/upload-url → Get presigned URL │ └── PUT to S3 → Upload file directly │ └── Generate Brace └── POST /cases/{caseId}/generate-brace └── Lambda: braceflow_invoke_brace_generator └── Download image from S3 └── Call EC2 GPU server /analyze/upload └── Download outputs from GPU server └── Upload outputs to S3 └── Update database with results └── Return results with presigned URLs ``` ## API Endpoints ### 1. Create Case ``` POST /cases ``` **Response:** ```json { "caseId": "case-20260125-abc123" } ``` ### 2. Get Upload URL ``` POST /cases/{caseId}/upload-url ``` **Request Body:** ```json { "filename": "ap.jpg", "contentType": "image/jpeg" } ``` **Response:** ```json { "url": "https://braceflow-uploads-xxx.s3.amazonaws.com/...", "s3Key": "cases/case-xxx/input/ap.jpg" } ``` ### 3. Generate Brace ``` POST /cases/{caseId}/generate-brace ``` **Request Body:** ```json { "experiment": "experiment_3", "config": { "brace_height_mm": 400, "torso_width_mm": 280, "torso_depth_mm": 200 } } ``` **Response:** ```json { "caseId": "case-20260125-abc123", "status": "brace_generated", "experiment": "experiment_3", "model": "ScolioVis", "vertebrae_detected": 17, "cobb_angles": { "PT": 12.5, "MT": 28.3, "TL": 15.2 }, "curve_type": "S-shaped", "rigo_classification": { "type": "A3", "description": "Major thoracic with compensatory lumbar" }, "mesh": { "vertices": 6204, "faces": 12404 }, "outputs": { "stl": { "s3Key": "cases/.../brace.stl", "url": "https://..." }, "ply": { "s3Key": "cases/.../brace.ply", "url": "https://..." }, "visualization": { "s3Key": "cases/.../viz.png", "url": "https://..." }, "landmarks": { "s3Key": "cases/.../landmarks.json", "url": "https://..." } }, "processing_time_ms": 3250 } ``` ### 4. Get Brace Outputs ``` GET /cases/{caseId}/brace-outputs ``` **Response:** ```json { "caseId": "case-20260125-abc123", "status": "brace_generated", "analysis": { "experiment": "experiment_3", "model": "ScolioVis", "cobb_angles": { "PT": 12.5, "MT": 28.3, "TL": 15.2 }, "curve_type": "S-shaped", "rigo_classification": { "type": "A3", "description": "..." } }, "outputs": [ { "filename": "brace.stl", "type": "stl", "s3Key": "cases/.../brace.stl", "size": 1234567, "url": "https://...", "expiresIn": 3600 } ] } ``` --- ## Frontend Implementation ### API Client (`src/api/braceflowApi.ts`) The API client includes these functions: ```typescript // Create a new case export async function createCase(body?: { notes?: string }): Promise<{ caseId: string }>; // Get presigned URL for S3 upload export async function getUploadUrl(caseId: string, filename: string, contentType: string): Promise<{ url: string; s3Key: string }>; // Upload file directly to S3 export async function uploadToS3(presignedUrl: string, file: File): Promise; // Invoke brace generator Lambda export async function generateBrace(caseId: string, options?: { experiment?: string; config?: Record }): Promise; // Get brace outputs with presigned URLs export async function getBraceOutputs(caseId: string): Promise; // Full workflow helper export async function analyzeXray(file: File, options?: { experiment?: string; config?: Record }): Promise<{ caseId: string; result: GenerateBraceResponse }>; ``` ### Types ```typescript export type CobbAngles = { PT?: number; MT?: number; TL?: number; }; export type RigoClassification = { type: string; description: string; curve_pattern?: string; }; export type AnalysisResult = { experiment?: string; model?: string; vertebrae_detected?: number; cobb_angles?: CobbAngles; curve_type?: string; rigo_classification?: RigoClassification; mesh_info?: { vertices?: number; faces?: number }; outputs?: Record; processing_time_ms?: number; }; export type BraceOutput = { filename: string; type: "stl" | "ply" | "obj" | "image" | "json" | "other"; s3Key: string; size: number; url: string; expiresIn: number; }; ``` --- ## Routes | Route | Page | Description | |-------|------|-------------| | `/analyze` | BraceAnalysisPage | New analysis with X-ray upload | | `/cases/:caseId/analysis` | BraceAnalysisPage | View existing case analysis | | `/generate` | ShellGenerationPage | Direct brace generation (legacy) | --- ## Page: BraceAnalysisPage Located at `src/pages/BraceAnalysisPage.tsx` ### Features 1. **Upload Panel** - Drag-and-drop X-ray upload 2. **3D Viewer** - Interactive brace model preview 3. **Analysis Results** - Displays: - Overall severity assessment - Curve type classification - Cobb angles (PT, MT, TL) - Rigo-Chêneau classification - Mesh information 4. **Downloads** - All generated files with presigned S3 URLs ### Layout Three-column layout: - Left: Upload panel with case ID display - Center: 3D brace viewer with processing info - Right: Analysis results and download links --- ## Components ### Reusable Components | Component | Location | Description | |-----------|----------|-------------| | `UploadPanel` | `src/components/rigo/UploadPanel.tsx` | Drag-and-drop file upload | | `BraceViewer` | `src/components/rigo/BraceViewer.tsx` | 3D model viewer (React Three Fiber) | | `AnalysisResults` | `src/components/rigo/AnalysisResults.tsx` | Analysis display component | --- ## Lambda Functions ### braceflow_invoke_brace_generator Located at: `braceflow_lambda/braceflow_invoke_brace_generator/index.mjs` **Process:** 1. Validate environment and request 2. Get case from database 3. Update status to `processing_brace` 4. Download X-ray from S3 5. Call GPU server `/analyze/upload` 6. Download outputs from GPU server `/download/{caseId}/{filename}` 7. Upload outputs to S3 8. Update database with analysis results 9. Return results with presigned URLs **Environment Variables:** - `DB_HOST`, `DB_PORT`, `DB_USER`, `DB_PASSWORD`, `DB_NAME` - `BRACE_GENERATOR_URL` - EC2 GPU server URL - `BUCKET_NAME` - S3 bucket name ### braceflow_get_brace_outputs Located at: `braceflow_lambda/braceflow_get_brace_outputs/index.mjs` **Process:** 1. Get case from database 2. List files in S3 `cases/{caseId}/outputs/` 3. Generate presigned URLs for each file 4. Return files list with analysis data --- ## S3 Structure ``` braceflow-uploads-{date}/ ├── cases/ │ └── {caseId}/ │ ├── input/ │ │ └── ap.jpg # Original X-ray │ └── outputs/ │ ├── brace_{caseId}.stl # 3D printable model │ ├── brace_{caseId}_adaptive.ply # Adaptive mesh │ ├── brace_{caseId}.png # Visualization │ └── brace_{caseId}.json # Landmarks data ``` --- ## Database Schema ```sql CREATE TABLE brace_cases ( case_id VARCHAR(64) PRIMARY KEY, status ENUM('created', 'processing_brace', 'brace_generated', 'brace_failed'), current_step VARCHAR(64), analysis_result JSON, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); ``` --- ## Deployment ### Deploy Lambda Functions ```powershell cd braceflow_lambda/deploy .\deploy-brace-generator-lambdas.ps1 -BraceGeneratorUrl "http://YOUR_EC2_IP:8000" ``` ### Add API Gateway Routes ``` POST /cases/{caseId}/generate-brace → braceflow_invoke_brace_generator GET /cases/{caseId}/brace-outputs → braceflow_get_brace_outputs ``` --- ## Running Locally ### Frontend ```bash cd braceflow npm install npm run dev # Open http://localhost:5173 ``` Navigate to `/analyze` to use the new brace analysis page. ### Testing 1. Go to http://localhost:5173/analyze 2. Upload an X-ray image 3. Wait for analysis to complete 4. View results and download files --- ## Troubleshooting ### Common Issues 1. **CORS errors**: Ensure API Gateway has CORS configured 2. **Timeout errors**: Lambda timeout is 120s, may need increase for large images 3. **S3 access denied**: Check Lambda role has S3 permissions 4. **GPU server unreachable**: Check EC2 security group allows port 8000 ### Checking Lambda Logs ```bash aws logs tail /aws/lambda/braceflow_invoke_brace_generator --follow ```