fix: validate start_date <= end_date in PredictRequest (closes #43) - #50
fix: validate start_date <= end_date in PredictRequest (closes #43)#50kriti2110 wants to merge 68 commits into
Conversation
- Expanded config.yaml with per-analysis-type configuration for deforestation, ice melting, and flooding including band configs, alert thresholds, and model paths - Added config/train.yaml for production training configuration - Expanded db.py with full SQLite schema: organisations, subscriptions, alerts tables; API key generation; all CRUD operations - Added requirements-install.txt for streamlined dependency installation Co-authored-by: Adeolu Mary Oshadare <nifemi996@gmail.com> Co-authored-by: John Edoh Onuh <onuhj47@gmail.com> Co-authored-by: Francis Umo <Francisumoh@360yahoo.com> Co-authored-by: Olufemi Taiwo <olufemitaiwo23@gmail.com> Co-authored-by: Godswill Chukwu Okoroafor <godswillchukwu21@gmail.com>
- Added inference/pipeline.py: full GEE-integrated inference engine with NDVI computation, model loading, file and bbox inference paths, synthetic NDVI fallback with bbox-seeded reproducibility - Updated inference/__init__.py to export run_inference, run_inference_from_file, run_inference_from_gee - Added analysis/ module: base class, registry, and dedicated analysers for deforestation, flooding and ice melting detection - Added training/ module: production trainer with EMA, checkpointing, early stopping, and combined loss functions (BCE + Dice + Focal) - Updated models/unet.py with minor architecture improvements - Updated __init__.py package exports Co-authored-by: Adeolu Mary Oshadare <nifemi996@gmail.com> Co-authored-by: Francis Umo <Francisumoh@360yahoo.com> Co-authored-by: Godswill Chukwu Okoroafor <godswillchukwu21@gmail.com> Co-authored-by: Victor Mbachu <victor.c.mbachu@gmail.com>
- Expanded api/main.py with full production API: organisation and NGO management, subscription system, alert and notification endpoints, all three analysis types wired to inference pipeline, run history, file upload endpoint, health check and API key authentication - Added run_api.sh: server startup script with venv activation, environment setup and uvicorn hot-reload configuration - Added docs/API_REFERENCE.md: full endpoint reference with request and response schemas for all routes Co-authored-by: Adeolu Mary Oshadare <nifemi996@gmail.com> Co-authored-by: John Edoh Onuh <onuhj47@gmail.com> Co-authored-by: Olufemi Taiwo <olufemitaiwo23@gmail.com> Co-authored-by: Victor Mbachu <victor.c.mbachu@gmail.com> Co-authored-by: Godswill Chukwu Okoroafor <godswillchukwu21@gmail.com>
- Fixed repository clone URL to Climate-Vision/ClimateVision - Updated Quick Start to use run_api.sh instead of raw uvicorn command - Corrected tech stack: SQLite (not PostgreSQL), Google Maps API (not Leaflet) - Fixed API Reference doc link to docs/API_REFERENCE.md - Updated Phase 3 roadmap to reflect Google Maps and Recharts as completed - Fixed Star History tracking link Co-authored-by: Adeolu Mary Oshadare <nifemi996@gmail.com> Co-authored-by: John Edoh Onuh <onuhj47@gmail.com> Co-authored-by: Francis Umo <Francisumoh@360yahoo.com> Co-authored-by: Olufemi Taiwo <olufemitaiwo23@gmail.com> Co-authored-by: Godswill Chukwu Okoroafor <godswillchukwu21@gmail.com> Co-authored-by: Victor Mbachu <victor.c.mbachu@gmail.com> Co-authored-by: Paul <46930375+cutewizzy11@users.noreply.github.com>
…ipts - prepare_data.py: GEE + synthetic Sentinel-2 patch downloader with Dynamic World forest labels, train/val/test split, normalizer fitting - train.py: production Attention U-Net training entry-point with YAML config, focal+dice loss, EMA weights, cosine LR schedule, early stopping - run_training.py: end-to-end training + inference pipeline - evaluate.py: per-class IoU/F1/precision/recall on held-out test set - export_model.py: ONNX and TorchScript model export - infer.py: CLI inference runner for single images or GEE bbox Co-Authored-By: Emmanuel Edoh <edoh-Onuh@users.noreply.github.com> Co-Authored-By: Godswill Okoroafor <godswillchukwu21@gmail.com> Co-Authored-By: Gold Okpa <okpagold@gmail.com> Co-Authored-By: Victor Mbachu <victor.c.mbachu@gmail.com>
- pipeline.py: authenticate GEE via service account key when GEE_SERVICE_ACCOUNT and GEE_SERVICE_ACCOUNT_KEY env vars are set; falls back to synthetic NDVI when GEE is unavailable instead of zeros - .gitignore: protect secrets/ directory and *.json key files Co-Authored-By: Gold Okpa <okpagold@gmail.com>
Notebook handles: GEE service account auth, multi-region patch download (Amazon/Congo/Borneo), Attention U-Net training on T4 GPU, evaluation, and checkpoint download back to local machine. Co-Authored-By: Gold Okpa <okpagold@gmail.com>
- prepare_data.py: reads GEE_SERVICE_ACCOUNT / GEE_SERVICE_ACCOUNT_KEY env vars to authenticate via service account instead of requiring earthengine authenticate - notebook: sets env vars with absolute key path in Cell 3 so all subprocess calls in Cells 5 and 6 inherit them automatically Co-Authored-By: Gold Okpa <okpagold@gmail.com>
Split each region into 0.5° tiles at 30m resolution instead of downloading the whole bbox at 10m (which hit GEE's pixel grid cap). Each tile is ~1850x1850px — well under the 32768 limit. Patches are accumulated across tiles until max_patches is reached. Co-Authored-By: Gold Okpa <okpagold@gmail.com>
…E limit Previous 30m/0.5° tiles were ~130MB each, exceeding GEE's 48MB cap. At 100m resolution each 0.25° tile is ~1.5MB — well within limits. Also fixes NameError on profile when all tiles failed, and adds a clear error exit when no patches are extracted. Co-Authored-By: Gold Okpa <okpagold@gmail.com>
… config - App.tsx: main application shell with routing, global state and sidebar navigation between Dashboard, Analysis, NGO and Settings - api.ts: typed API client for all backend endpoints (predict, runs, organizations, alerts, analysis-types) with error handling - types.ts: shared TypeScript interfaces for Run, Organization, Alert, NDVIStats, InferenceResult and API responses - styles.css: design-system CSS variables (cv-* tokens), component base styles, skeleton loader, scrollbar and animation utilities - tailwind.config.js: extended theme with cv-* color palette, shadow tokens, and custom font stack matching the dark forest UI - main.tsx: React 18 createRoot entry-point with StrictMode - index.html: updated meta tags, font preload and app title - package.json: added lucide-react, recharts, react-router-dom deps - .env.example: documents VITE_GOOGLE_MAPS_API_KEY and VITE_API_BASE_URL Co-Authored-By: Emmanuel Edoh <edoh-Onuh@users.noreply.github.com> Co-Authored-By: Adeolu Mary Oshadare <nifemi996@gmail.com> Co-Authored-By: Gold Okpa <okpagold@gmail.com> Co-Authored-By: Victor Mbachu <victor.c.mbachu@gmail.com>
- Validate bbox has exactly 4 values [west, south, east, north] - Enforce longitude bounds (-180 to 180) and latitude bounds (-90 to 90) - Ensure west < east and south < north - Validate date strings follow YYYY-MM-DD format - Ensure start_date is earlier than end_date
- Add offset query parameter for cursor-based pagination
- Return total record count alongside results for frontend page controls
- Restructure response to {total, limit, offset, runs} envelope
- Refactor WHERE clause building to avoid SQL injection via safe parameterisation
- Returns total run count, completed runs in last 7 days - Breakdown by status (pending, running, completed, failed) - Breakdown by analysis type (deforestation, ice_melting, flooding) - Alert summary: total alerts and unacknowledged count - Feeds directly into the frontend Dashboard KPI summary cards
- Log every request: method, path, status code, duration_ms, client IP - Attach X-Response-Time-Ms header to all responses for frontend monitoring - Uses Starlette BaseHTTPMiddleware for non-blocking request interception - Helps trace slow endpoints and detect unusual access patterns in production
- Reduce from 874 lines to ~100 lines (~5000 words to 596 words) - Move installation to top (line 18) - visible without scrolling - Replace imaginary API examples with real working curl + uvicorn commands - Replace fabricated benchmarks with honest in-progress markers - Remove community growth strategy, team descriptions, and execution plan - Add satellite band details to analysis types table - Keep citation, contributing, and docs links
…lufemi-improvements feat(api): Olufemi - API validation, pagination, stats & audit logging
- Add React components: Map, Charts, Layout, UI elements - Add contexts: AppContext, ToastContext - Add hooks: useGeocoding, useRunPolling - Add pages: Analytics, NewAnalysis, RunHistory, Settings, Upload - Update SETUP_COMPLETE.md Co-authored-by: Adeolu Mary Oshadare <nifemi996@gmail.com> Co-authored-by: John Edoh Onuh <onuhj47@gmail.com> Co-authored-by: Francis Umo <Francisumoh@360yahoo.com> Co-authored-by: Olufemi Taiwo <olufemitaiwo23@gmail.com> Co-authored-by: Godswill Chukwu Okoroafor <godswillchukwu21@gmail.com> Co-authored-by: Victor Mbachu <victor.c.mbachu@gmail.com> Co-authored-by: Paul <46930375+cutewizzy11@users.noreply.github.com> Co-authored-by: Gold Okpa <okpagold@gmail.com>
Prevent accidental commits of large .pth model files that exceed GitHub's 100MB limit.
Add centralized constants for API config, map settings, analysis types, polling intervals, and UI configurations.
…role-document Merged by Mary Oshadare
…e-document Merged by Mary Oshadare
…mate-Vision#7) * feat(data): add GEE tile downloader with analysis-aware band selection - Downloads real Sentinel-2 composites via Google Earth Engine - Reads required bands from config.yaml per analysis_type - Includes SCL band for downstream cloud masking - Synthetic fallback with explicit is_synthetic flag when GEE unavailable - Fix .gitignore so src/climatevision/data/ is no longer ignored * feat(data): add analysis-specific Sentinel-2 band mapping utilities - get_bands_for_analysis() reads correct bands from config.yaml - get_band_indices() maps band names to canonical 13-band stack positions - is_analysis_enabled() and list_enabled_analysis_types() for config validation - Includes SCL band helpers for downstream cloud masking * feat(data): integrate SCL cloud masking and export new pipeline modules - apply_scl_cloud_mask() masks cloudy pixels using Sentinel-2 SCL band - Default clear labels: vegetation, bare soils, water, snow - Update __init__.py to expose gee_downloader and band_mapping utilities * refactor(data): address PR review feedback - Remove duplicated config logic in gee_downloader.py; import from band_mapping - Cache config.yaml load in band_mapping.py via lru_cache - Read synthetic tile size from config.yaml instead of hardcoding 256 - Remove unused json import in gee_downloader.py - Add shape validation in apply_scl_cloud_mask --------- Co-authored-by: Adeolu Mary Oshadare <adeolu@placeholder.com>
…ing (Climate-Vision#8) * feat(inference): make pipeline analysis-aware with dynamic model loading - _load_model() now accepts analysis_type and reads in_channels/num_classes from config.yaml - Per-analysis-type model cache prevents cross-contamination between deforestation/ice/flood models - _find_best_checkpoint() prefers config.yaml weight path per analysis type - run_inference() accepts analysis_type, pads/crops to correct n_channels, and returns dynamic class counts - run_inference_from_file() and run_inference_from_gee() propagate analysis_type parameter * feat(api): wire analysis_type into prediction endpoints - Pass body.analysis_type to run_inference_from_gee() in /api/predict - Pass analysis_type to run_inference_from_file() in /api/predict/upload - Enables the API to load the correct model and return correct class counts per analysis type --------- Co-authored-by: Olufemi Taiwo <Olufemitaiwo23@gmail.com>
… flag, add config health validation - Add cv_dev development key bypass for local testing - Require X-API-Key on all mutation endpoints (POST predict, orgs, alerts, subscriptions) - Surface is_synthetic at root of inference response for frontend demo banners - Expand /api/health to validate config alignment (bands vs in_channels, classes vs num_classes)
- Add FastAPI test client fixture - Create CI workflow for Python (flake8, pytest) and frontend (npm build) - Bootstrap tests/ directory structure
- Parametrize UNet init for all 3 analysis types (4ch/2cl, 4ch/3cl, 3ch/3cl) - Validate forward pass output shapes - Add Siamese change detection forward shape test
- Link to 6 active good-first-issue and help-wanted issues - Add claim workflow for new contributors - Include time estimates and skill-building map
- ../components/map/ -> ../components/Map/ - Fixes vite build failure on Linux (case-sensitive filesystem)
- Fixes pip install failure for gdal and rasterio on Ubuntu runners - Adds libgdal-dev, gdal-bin, libgl1-mesa-glx
- gdal Python package requires exact system GDAL version matching - rasterio covers all GDAL functionality we actually use - Simplify CI system deps to libgl1 only (for opencv runtime)
- Fixes ModuleNotFoundError: No module named 'climatevision' - pip install -e . registers src/ as an importable package
- ForestDataset with DataLoader support - Training/validation augmentation pipelines - Synthetic tile generation for demo/fallback mode
- Add DONE/PENDING task list for April 2026 sprint - Include actual .github/workflows/ci.yml code in role doc - Update local CI check commands to match current workflow
Adds field-level OpenAPI descriptions to start_date/end_date in PredictRequest making the ordering constraint explicit. Removes the redundant 400 route-level check that bypassed the Pydantic model validator. Adds pytest coverage for valid ranges (mocking inference), reversed ranges, and equal dates — both asserting 422 and verifying the validator error message. Closes Climate-Vision#43 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Goldokpa
left a comment
There was a problem hiding this comment.
Validation logic missing — tests will fail
Thanks for the contribution and for adding tests! There's a gap in the implementation though: the diff removes the inline if body.start_date > body.end_date: raise HTTPException(400) from predict_json and adds description= strings to the start_date / end_date fields, but description is documentation-only — Pydantic won't enforce it.
There's no @field_validator or @model_validator added that actually checks start_date <= end_date, so:
test_predict_reversed_date_range_returns_422will fail — the API will accept the reversed range and proceed to inference (returning 200 with the mock, or 500 in real runs).test_predict_equal_dates_returns_422will also fail for the same reason, and it changes the contract from the previous behavior (the old check used strict>, so equal dates were allowed). Worth confirming whether equal dates should now be rejected — that's a deliberate behavior change and probably needs a note in the PR description.
Suggested fix — add a model validator on PredictRequest, e.g.:
from pydantic import model_validator
@model_validator(mode="after")
def _check_date_range(self) -> "PredictRequest":
if self.start_date and self.end_date and self.start_date > self.end_date:
raise ValueError("start_date must be on or before end_date")
return selfThat makes Pydantic raise during model construction, which FastAPI surfaces as 422 — matching the new tests. (Decide > vs >= based on whether equal dates should be allowed, and align the test accordingly.)
Happy to re-review once that's in.
|
👋 Friendly ping, @kriti2110 — could you take another look at the review above? The key fix is keeping the inline |
|
📢 Heads-up: repo history was rewritten today (2026-05-18) We force-pushed a cleaned history across all branches to remove an internal directory from past commits. Your code and this PR are unaffected — only the commit SHAs underneath have shifted. GitHub will re-render the diff against the new base automatically. If you have a local clone, please bring it back in sync before pushing anything else: # Option A (simplest): fresh start
git clone https://github.com/Climate-Vision/ClimateVision.git
# Option B: rebase the existing PR branch in your fork
git fetch origin
git checkout <your-branch>
git rebase origin/main # likely no conflicts
git push --force-with-leaseDo not Apologies for the interruption — really appreciate your patience here. If anything looks off after rebasing, leave a comment and I'll help unblock right away. Thanks for contributing 🙏 |
fix: validate start_date <= end_date in PredictRequest (#50, rebased)
|
Merged into main via #90 (rebased onto current main after the history update; your commits/authorship preserved). Thanks @kriti2110! |
fix: validate start_date <= end_date in PredictRequest (#50, rebased)
Summary
descriptionfields tostart_dateandend_dateinPredictRequestso the OpenAPI docs explicitly state the ordering constraintstart_date > end_datecheck that raised a 400 — the existingmodel_validator(mode="after")already handles this and correctly returns 422tests/test_api.py:run_inference_from_gee)start > end) → 422 with validator error message in bodystart == end) → 422Test plan
pytest tests/test_api.py::test_predict_valid_date_range_reaches_inferencepassespytest tests/test_api.py::test_predict_reversed_date_range_returns_422passespytest tests/test_api.py::test_predict_equal_dates_returns_422passes/docsshow date ordering constraint in field descriptionsCloses #43
🤖 Generated with Claude Code