Source Code Structure
The application has been refactored into a modular structure for better maintainability and debugging.
Directory Structure
src/
βββ config.js # Application configuration and constants
βββ state.js # Application state management
βββ main.js # Main entry point
β
βββ models/ # AI Model management
β βββ modelLoader.js # Load and initialize ONNX models
β βββ inference.js # Run model predictions
β βββ yoloDetection.js # YOLO-specific detection logic
β
βββ processing/ # Data processing
β βββ imagePreprocessing.js # Image preprocessing for models
β βββ postprocessing.js # Model output postprocessing
β βββ yoloPostprocessing.js # YOLO-specific postprocessing with NMS
β
βββ ui/ # UI components and handlers
β βββ eventHandlers.js # Setup all event listeners
β βββ imageDisplay.js # Image preview and display
β βββ loading.js # Loading overlay controls
β βββ quickEval.js # Quick evaluation handlers
β βββ results.js # Results display and formatting
β βββ tabs.js # Tab switching logic
β βββ toast.js # Toast notifications
β βββ workflow.js # Main workflow logic
β βββ zoom.js # Zoom controls
β
βββ utils/ # Utility functions
βββ imageUtils.js # Image manipulation helpers
βββ mathUtils.js # Math operations (softmax, etc.)
Module Responsibilities
Core Modules
config.js
- Model paths configuration
- Detection thresholds and parameters
- Label mappings
- ONNX Runtime configuration
- Zoom settings
state.js
- Centralized application state
- State getters and setters
- Current image, models, embryos tracking
main.js
- Application initialization
- Orchestrates model loading
- Sets up event listeners
- Entry point for the app
Model Modules
models/modelLoader.js
- Initialize ONNX Runtime
- Load label mappings from config files
- Load all 4 ONNX models (classifier, quality, grader, YOLO)
- Provide model status
models/inference.js
- Run classification (embryo yes/no)
- Run quality check (poor/good)
- Run grading (Gardner scale)
- Orchestrate full embryo evaluation pipeline
models/yoloDetection.js
- Detect embryos using YOLO model
- Check YOLO availability
Processing Modules
processing/imagePreprocessing.js
- Preprocess images for SigLIP models (224x224)
- Preprocess images for YOLO (640x640)
- Normalize with mean/std
processing/postprocessing.js
- Postprocess classification results
- Postprocess grading results with all predictions
- Apply softmax to logits
processing/yoloPostprocessing.js
- Parse YOLO output format [1, 5, 8400]
- Apply confidence threshold
- Non-Maximum Suppression (NMS)
- Calculate IoU (Intersection over Union)
- Crop detected embryo regions
UI Modules
ui/eventHandlers.js
- Central event listener setup
- Handle image uploads
- Wire up all UI interactions
ui/imageDisplay.js
- Display images in main/quick previews
- Show cropped embryos
- Manage image visibility
ui/loading.js
- Show/hide loading overlay
- Update progress bar
- Display loading messages
ui/quickEval.js
- Quick evaluation workflow
- Clear quick evaluation results
ui/results.js
- Format and display results
- Interpret Gardner grades
- Show top-5 predictions
- Display classification status
- Generate image quality tips
ui/tabs.js
- Switch between main workflow and quick evaluation
- Manage tab state
ui/toast.js
- Show success/error/info toast notifications
- Auto-dismiss after 3 seconds
ui/workflow.js
- Main workflow orchestration
- Classify uploaded images
- Process single/multiple embryo modes
- Navigate between detected embryos
- Evaluate selected embryos
ui/zoom.js
- Adjust zoom level
- Reset zoom
- Apply zoom transform
Utility Modules
utils/imageUtils.js
- Load images from URLs/data URIs
- Crop image regions with padding
- Read files as data URLs
utils/mathUtils.js
- Softmax function
- Mean calculation
- Value clamping
Benefits of Modular Structure
- Easier Debugging: Each module has a specific responsibility, making it easier to locate and fix bugs
- Better Testing: Individual modules can be tested in isolation
- Code Reusability: Functions can be easily imported and reused across different parts of the app
- Maintainability: Changes to one module don't affect others if interfaces remain stable
- Readability: Smaller files are easier to understand and navigate
- Collaboration: Multiple developers can work on different modules simultaneously
How to Add New Features
Adding a New Model
- Add model path to
config.js - Load model in
models/modelLoader.js - Create inference function in
models/inference.js - Add preprocessing in
processing/imagePreprocessing.jsif needed - Add postprocessing in
processing/postprocessing.js
Adding a New UI Component
- Create new file in
ui/directory - Export relevant functions
- Import and wire up in
ui/eventHandlers.js - Update
main.jsif initialization is needed
Modifying Detection Parameters
- Update thresholds in
config.js - No code changes needed elsewhere
Import/Export Pattern
All modules use ES6 modules:
// Export
export function myFunction() { ... }
export const myConstant = 42;
// Import
import { myFunction, myConstant } from './module.js';
Debugging Tips
- Check browser console: All errors are logged with descriptive messages
- Check Network tab: Verify models are loading correctly
- Breakpoints: Set breakpoints in specific modules to debug
- State inspection: Check
appStatein console to see current state - Module isolation: Test individual functions by importing in console
Backup
The original monolithic app.js has been backed up as app.js.backup.