From 537dc664616cdbaee2d1d0fdf041fad5d9fc0701 Mon Sep 17 00:00:00 2001 From: Adeolu Mary Oshadare Date: Sat, 25 Apr 2026 16:39:34 +0100 Subject: [PATCH 1/2] docs: update Mary's role doc with sprint progress and live band mapping code - Add DONE/PENDING task list for April 2026 sprint - Include actual config.yaml band definitions per analysis type - Add SCL cloud masking reference table - Update codebase ownership to reflect active modules --- team_docs/Adeolu_Mary_Oshadare_Role.pdf | Bin 0 -> 12626 bytes team_docs/generate_role_docs.py | 73 ++++++++++++++++++++---- 2 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 team_docs/Adeolu_Mary_Oshadare_Role.pdf diff --git a/team_docs/Adeolu_Mary_Oshadare_Role.pdf b/team_docs/Adeolu_Mary_Oshadare_Role.pdf new file mode 100644 index 0000000000000000000000000000000000000000..51b940ed11df0bbf8565c3f17810938b9b1891cd GIT binary patch literal 12626 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⁣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 R0)af7KmaYR_)7`E{{bDa%+CM- literal 0 HcmV?d00001 diff --git a/team_docs/generate_role_docs.py b/team_docs/generate_role_docs.py index 0c4aaf2..138a9bb 100644 --- a/team_docs/generate_role_docs.py +++ b/team_docs/generate_role_docs.py @@ -174,18 +174,32 @@ def create_adeolu_doc(): pdf.bullet("Build data validation and quality checks for incoming satellite imagery") pdf.bullet("Manage the data/ directory structure (raw, processed, satellite)") pdf.bullet("Create EDA notebooks for spatial data exploration and visualization") - pdf.ln(2) + pdf.ln(1) + + pdf.subsection_title("Sprint Progress - April 2026") + pdf.bullet("DONE: band_mapping.py - analysis-specific band mapping from config.yaml") + pdf.bullet("DONE: gee_downloader.py - GEE tile download with metadata") + pdf.bullet("DONE: preprocessing.py - SCL-based cloud masking") + pdf.bullet("DONE: dataset.py - PyTorch Dataset and DataLoader") + pdf.bullet("DONE: augmentation.py - training/validation transforms") + pdf.bullet("DONE: synthetic.py - synthetic fallback tile generation") + pdf.bullet("PENDING: Real GEE tile download in inference pipeline (not just NDVI stats)") + pdf.bullet("PENDING: Analysis-specific band mapping enforcement in inference preprocessing") + pdf.bullet("PENDING: Cloud masking integration at inference time before model forward pass") + pdf.bullet("PENDING: Synthetic fallback guardrails - clearly label synthetic tiles in metadata") + pdf.ln(1) # Codebase Ownership pdf.section_title("Your Codebase Ownership") pdf.body_text("You are the primary owner of the following files and directories:") pdf.code_block( "src/climatevision/data/ # PRIMARY OWNER - Entire data module\n" - " sentinel2.py # Sentinel-2 downloader & preprocessor\n" - " landsat.py # Landsat data loader\n" - " dataset.py # PyTorch Dataset classes\n" - " preprocess.py # Cloud masking, normalization\n" - " augmentation.py # Data augmentation pipeline\n" + " band_mapping.py # Analysis-specific band mapping (ACTIVE)\n" + " gee_downloader.py # GEE tile downloader (ACTIVE)\n" + " preprocessing.py # Cloud masking, normalization (ACTIVE)\n" + " dataset.py # PyTorch Dataset & DataLoader (ACTIVE)\n" + " augmentation.py # Data augmentation pipeline (ACTIVE)\n" + " synthetic.py # Synthetic tile fallback (ACTIVE)\n" " __init__.py # Module exports\n" "\n" "src/climatevision/utils/\n" @@ -193,8 +207,9 @@ def create_adeolu_doc(): " visualization.py # CO-OWNER - Spatial visualizations\n" "\n" "scripts/\n" - " setup_gee.py # Google Earth Engine setup\n" - " download_data.py # Automated satellite data download\n" + " prepare_data.py # Automated satellite data download\n" + "\n" + "config.yaml # Band mapping & analysis type config\n" "\n" "data/ # Data directory structure\n" " raw/ | processed/ | satellite/\n" @@ -288,7 +303,41 @@ def create_adeolu_doc(): "# Follow browser prompt to authorise your GEE service account" ) - pdf.subsection_title("Step 2: Ingest Satellite Data") + pdf.subsection_title("Step 2: Analysis-Specific Band Mapping") + pdf.body_text("config.yaml defines bands per analysis type. Your band_mapping.py reads this:") + pdf.code_block( + "# config.yaml analysis type band definitions\n" + "deforestation: [B04, B03, B02, B08] # Red, Green, Blue, NIR -> 4ch -> 2cl\n" + "ice_melting: [B02, B03, B04, B11] # Blue, Green, Red, SWIR -> 4ch -> 3cl\n" + "flooding: [B03, B08, B11] # Green, NIR, SWIR -> 3ch -> 3cl\n" + "\n" + "# Python usage\n" + "from climatevision.data.band_mapping import get_bands_for_analysis, get_model_config\n" + "\n" + "bands = get_bands_for_analysis('flooding')\n" + "# -> ['B03', 'B08', 'B11']\n" + "\n" + "cfg = get_model_config('flooding')\n" + "# -> {'in_channels': 3, 'num_classes': 3, 'weights': 'models/unet_flood.pth'}" + ) + pdf.ln(2) + + pdf.subsection_title("Step 3: Cloud Masking with SCL Band") + pdf.body_text("Sentinel-2 Scene Classification Layer (SCL) pixel values:") + pdf.code_block( + "# SCL band values\n" + "KEEP = [4, 5, 6, 7, 10] # vegetation, bare soil, water, low cloud, thin cirrus\n" + "MASK = [0, 1, 2, 3, 8, 9] # NO_DATA, SATURATED, DARK, SHADOW, med/high cloud\n" + "\n" + "# Usage in preprocessing.py\n" + "from climatevision.data.preprocessing import apply_scl_cloud_mask\n" + "\n" + "clean_image = apply_scl_cloud_mask(image, scl_band)\n" + "# image: (C, H, W) scl_band: (H, W) uint8" + ) + pdf.ln(2) + + pdf.subsection_title("Step 4: Ingest Satellite Data") pdf.code_block( "# Download Sentinel-2 imagery for a bounding box and date range\n" "python scripts/prepare_data.py \\\n" @@ -301,7 +350,7 @@ def create_adeolu_doc(): "# Output: GeoTIFF tiles saved to data/raw/amazon_2023/" ) - pdf.subsection_title("Step 3: Preprocess & Build Dataset") + pdf.subsection_title("Step 5: Preprocess & Build Dataset") pdf.code_block( "# Run cloud masking, normalization, and 256x256 tiling\n" "python - <<'EOF'\n" @@ -323,7 +372,7 @@ def create_adeolu_doc(): "EOF" ) - pdf.subsection_title("Step 4: Compute Spectral Indices") + pdf.subsection_title("Step 6: Compute Spectral Indices") pdf.code_block( "# Calculate NDVI, EVI, and moisture indices from raw bands\n" "python - <<'EOF'\n" @@ -336,7 +385,7 @@ def create_adeolu_doc(): "EOF" ) - pdf.subsection_title("Step 5: Commit & Push Your Work") + pdf.subsection_title("Step 7: Commit & Push Your Work") pdf.code_block( "# Switch to your git identity\n" "source team_docs/switch_user.sh adeolu\n" From 5916a56bdfc9eed292ec80cd7b897a6b952a9f37 Mon Sep 17 00:00:00 2001 From: Adeolu Mary Oshadare Date: Sat, 25 Apr 2026 22:31:42 +0100 Subject: [PATCH 2/2] chore: remove team_docs from git tracking and add to .gitignore - team_docs/ should remain local only, never committed - Keeps role PDFs and sensitive team planning docs out of repo --- .gitignore | 1 + team_docs/Adeolu_Mary_Oshadare_Role.pdf | Bin 12626 -> 0 bytes team_docs/Francis_Umo_Role.pdf | Bin 10813 -> 0 bytes team_docs/Olufemi_Taiwo_Role.pdf | Bin 11657 -> 0 bytes team_docs/Victor_Mbachu_Role.pdf | Bin 14819 -> 0 bytes team_docs/generate_role_docs.py | 2361 ----------------------- 6 files changed, 1 insertion(+), 2361 deletions(-) delete mode 100644 team_docs/Adeolu_Mary_Oshadare_Role.pdf delete mode 100644 team_docs/Francis_Umo_Role.pdf delete mode 100644 team_docs/Olufemi_Taiwo_Role.pdf delete mode 100644 team_docs/Victor_Mbachu_Role.pdf delete mode 100644 team_docs/generate_role_docs.py diff --git a/.gitignore b/.gitignore index 4ba3bec..89d344a 100644 --- a/.gitignore +++ b/.gitignore @@ -96,3 +96,4 @@ secrets/ # Large model files models/demo_run/ *.pth +team_docs/ diff --git a/team_docs/Adeolu_Mary_Oshadare_Role.pdf b/team_docs/Adeolu_Mary_Oshadare_Role.pdf deleted file mode 100644 index 51b940ed11df0bbf8565c3f17810938b9b1891cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12626 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⁣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 R0)af7KmaYR_)7`E{{bDa%+CM- diff --git a/team_docs/Francis_Umo_Role.pdf b/team_docs/Francis_Umo_Role.pdf deleted file mode 100644 index a263331af36b82fdb86204eea7bce2f19baf4667..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10813 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 diff --git a/team_docs/Olufemi_Taiwo_Role.pdf b/team_docs/Olufemi_Taiwo_Role.pdf deleted file mode 100644 index 9367f2c2b240b5b35df2a5610f465b23cd90fff2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11657 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 diff --git a/team_docs/generate_role_docs.py b/team_docs/generate_role_docs.py deleted file mode 100644 index 138a9bb..0000000 --- a/team_docs/generate_role_docs.py +++ /dev/null @@ -1,2361 +0,0 @@ -#!/usr/bin/env python3 -""" -Generate personalized ClimateVision role assignment PDFs for each team member. -""" - -from fpdf import FPDF -import os - -OUTPUT_DIR = "/Users/starrexshotit/Desktop/ClimateVision-main/team_docs" -os.makedirs(OUTPUT_DIR, exist_ok=True) - - -class RoleDoc(FPDF): - def __init__(self, member_name): - super().__init__() - self.member_name = member_name - - def header(self): - # Green header bar - self.set_fill_color(34, 120, 74) - self.rect(0, 0, 210, 28, 'F') - self.set_font("Helvetica", "B", 16) - self.set_text_color(255, 255, 255) - self.set_y(5) - self.cell(0, 10, "ClimateVision", align="L", new_x="LMARGIN", new_y="NEXT") - self.set_font("Helvetica", "", 9) - self.cell(0, 6, "Role Assignment & Codebase Ownership", align="L", new_x="LMARGIN", new_y="NEXT") - self.set_text_color(0, 0, 0) - self.ln(10) - - def footer(self): - self.set_y(-15) - self.set_font("Helvetica", "I", 8) - self.set_text_color(130, 130, 130) - self.cell(0, 10, f"ClimateVision | Confidential - Prepared for {self.member_name} | Page {self.page_no()}", align="C") - - def section_title(self, title): - self.set_font("Helvetica", "B", 13) - self.set_text_color(34, 120, 74) - self.cell(0, 8, title, new_x="LMARGIN", new_y="NEXT") - # Underline - self.set_draw_color(34, 120, 74) - self.set_line_width(0.5) - self.line(10, self.get_y(), 200, self.get_y()) - self.ln(4) - self.set_text_color(0, 0, 0) - - def subsection_title(self, title): - self.set_font("Helvetica", "B", 11) - self.set_text_color(50, 50, 50) - self.cell(0, 7, title, new_x="LMARGIN", new_y="NEXT") - self.ln(1) - self.set_text_color(0, 0, 0) - - def _sanitize(self, text): - """Replace unicode chars that latin-1 can't handle.""" - replacements = { - '\u2013': '-', # en dash - '\u2014': '-', # em dash - '\u2018': "'", # left single quote - '\u2019': "'", # right single quote - '\u201c': '"', # left double quote - '\u201d': '"', # right double quote - '\u2022': '-', # bullet - '\u2026': '...', # ellipsis - } - for old, new in replacements.items(): - text = text.replace(old, new) - return text - - def body_text(self, text): - self.set_font("Helvetica", "", 10) - self.multi_cell(0, 5.5, self._sanitize(text)) - self.ln(2) - - def bullet(self, text): - self.set_font("Helvetica", "", 10) - x = self.get_x() - self.cell(6, 5.5, "-", new_x="END") - self.multi_cell(0, 5.5, self._sanitize(text)) - self.ln(1) - - def code_block(self, text): - self.set_font("Courier", "", 9) - self.set_fill_color(240, 240, 240) - lines = text.strip().split("\n") - for line in lines: - self.cell(0, 5, " " + line, fill=True, new_x="LMARGIN", new_y="NEXT") - self.ln(3) - self.set_font("Helvetica", "", 10) - - def key_value(self, key, value): - self.set_font("Helvetica", "B", 10) - self.cell(45, 6, self._sanitize(key) + ":", new_x="END") - self.set_font("Helvetica", "", 10) - self.multi_cell(0, 6, self._sanitize(value)) - self.ln(1) - - def month_block(self, month_title, weeks): - self.set_font("Helvetica", "B", 10) - self.set_fill_color(34, 120, 74) - self.set_text_color(255, 255, 255) - self.cell(0, 7, " " + month_title, fill=True, new_x="LMARGIN", new_y="NEXT") - self.set_text_color(0, 0, 0) - self.ln(2) - for week_title, tasks in weeks: - self.set_font("Helvetica", "B", 10) - self.cell(0, 6, week_title, new_x="LMARGIN", new_y="NEXT") - self.ln(1) - for task in tasks: - self.bullet(task) - self.ln(2) - - -def create_adeolu_doc(): - pdf = RoleDoc("Adeolu Mary Oshadare") - pdf.add_page() - - # Title - pdf.set_font("Helvetica", "B", 18) - pdf.cell(0, 10, "Adeolu Mary Oshadare", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_font("Helvetica", "", 11) - pdf.set_text_color(100, 100, 100) - pdf.cell(0, 7, "Data Science Engineer 2 - Data Pipeline & GIS Lead", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_text_color(0, 0, 0) - pdf.ln(5) - - # Quick Info - pdf.key_value("GitHub", "@Oshgig") - pdf.key_value("Access Level", "Maintainer") - pdf.key_value("Reports To", "@Goldokpa (Project Owner)") - pdf.key_value("Project Duration", "3 Months") - pdf.ln(3) - - # How It Fits Me - pdf.section_title("How This Role Fits You") - pdf.body_text( - "Your B.Tech in Remote Sensing & GIS from FUTA gives you something no one else on this team has - " - "a formal education in exactly the kind of spatial data ClimateVision processes. You understand " - "satellite imagery at a fundamental level: spectral bands, atmospheric correction, spatial resolution, " - "and coordinate reference systems." - ) - pdf.body_text( - "As a GIS Analyst at Charis Tech Hub, you already worked with Google Earth Engine and AWS, writing " - "Python scripts to model and extract insights from large geospatial datasets. That is precisely what " - "ClimateVision's data pipeline needs - someone who can build the bridge between raw Sentinel-2 imagery " - "and the clean, preprocessed tensors our ML models consume." - ) - pdf.body_text( - "Your MSc in Data Science from Hertfordshire added the machine learning layer: Scikit-Learn, TensorFlow, " - "XGBoost, Pandas, and data pipelines. Your credit card fraud detection project showed you can handle " - "imbalanced datasets (SMOTE) and build production-quality ML models - the same skills needed when dealing " - "with satellite imagery where cloud-free forest pixels are the minority class." - ) - pdf.body_text( - "Your experience with Power BI, Tableau, ArcGIS Story Maps, and data storytelling means you can also " - "create the visual outputs that make our satellite data understandable to non-technical stakeholders " - "like conservation NGOs." - ) - pdf.ln(2) - - # Role Description - pdf.section_title("Your Role on ClimateVision") - pdf.body_text( - "You own the entire data layer - everything that happens between raw satellite imagery arriving from " - "APIs and clean, model-ready data being passed to the ML pipeline. You are the gatekeeper of data quality." - ) - pdf.subsection_title("Core Responsibilities") - pdf.bullet("Build and maintain the automated satellite data ingestion pipeline (Sentinel Hub, Google Earth Engine)") - pdf.bullet("Develop preprocessing workflows: cloud masking, atmospheric correction, image normalization, tiling") - pdf.bullet("Create PyTorch Dataset & DataLoader classes for training and inference") - pdf.bullet("Implement data augmentation strategies (rotation, flipping, spectral perturbations)") - pdf.bullet("Engineer spectral features: NDVI, EVI, moisture indices from raw multispectral bands") - pdf.bullet("Build data validation and quality checks for incoming satellite imagery") - pdf.bullet("Manage the data/ directory structure (raw, processed, satellite)") - pdf.bullet("Create EDA notebooks for spatial data exploration and visualization") - pdf.ln(1) - - pdf.subsection_title("Sprint Progress - April 2026") - pdf.bullet("DONE: band_mapping.py - analysis-specific band mapping from config.yaml") - pdf.bullet("DONE: gee_downloader.py - GEE tile download with metadata") - pdf.bullet("DONE: preprocessing.py - SCL-based cloud masking") - pdf.bullet("DONE: dataset.py - PyTorch Dataset and DataLoader") - pdf.bullet("DONE: augmentation.py - training/validation transforms") - pdf.bullet("DONE: synthetic.py - synthetic fallback tile generation") - pdf.bullet("PENDING: Real GEE tile download in inference pipeline (not just NDVI stats)") - pdf.bullet("PENDING: Analysis-specific band mapping enforcement in inference preprocessing") - pdf.bullet("PENDING: Cloud masking integration at inference time before model forward pass") - pdf.bullet("PENDING: Synthetic fallback guardrails - clearly label synthetic tiles in metadata") - pdf.ln(1) - - # Codebase Ownership - pdf.section_title("Your Codebase Ownership") - pdf.body_text("You are the primary owner of the following files and directories:") - pdf.code_block( - "src/climatevision/data/ # PRIMARY OWNER - Entire data module\n" - " band_mapping.py # Analysis-specific band mapping (ACTIVE)\n" - " gee_downloader.py # GEE tile downloader (ACTIVE)\n" - " preprocessing.py # Cloud masking, normalization (ACTIVE)\n" - " dataset.py # PyTorch Dataset & DataLoader (ACTIVE)\n" - " augmentation.py # Data augmentation pipeline (ACTIVE)\n" - " synthetic.py # Synthetic tile fallback (ACTIVE)\n" - " __init__.py # Module exports\n" - "\n" - "src/climatevision/utils/\n" - " geospatial.py # CO-OWNER - Geospatial utilities\n" - " visualization.py # CO-OWNER - Spatial visualizations\n" - "\n" - "scripts/\n" - " prepare_data.py # Automated satellite data download\n" - "\n" - "config.yaml # Band mapping & analysis type config\n" - "\n" - "data/ # Data directory structure\n" - " raw/ | processed/ | satellite/\n" - "\n" - "notebooks/\n" - " 02_data_exploration.ipynb # EDA notebook" - ) - pdf.ln(2) - - # 3-Month Timeline - pdf.section_title("Your 3-Month Delivery Timeline") - pdf.month_block("MONTH 1: Foundation (Weeks 1-4)", [ - ("Week 1-2: Data Ingestion", [ - "Set up Sentinel Hub API and Google Earth Engine authentication", - "Build sentinel2.py - download, parse, and store Sentinel-2 imagery", - "Create landsat.py - Landsat 8/9 data loader with band mapping", - "Implement basic cloud masking using SCL (Scene Classification Layer)", - ]), - ("Week 3-4: PyTorch Data Pipeline", [ - "Build dataset.py - PyTorch Dataset class for satellite image tiles", - "Implement preprocess.py - normalization, atmospheric correction, tiling (256x256)", - "Create data validation checks (band count, resolution, CRS consistency)", - "Write 02_data_exploration.ipynb - EDA notebook with sample visualizations", - ]), - ]) - pdf.month_block("MONTH 2: Advanced Features (Weeks 5-8)", [ - ("Week 5-6: Feature Engineering & Augmentation", [ - "Implement spectral index calculation: NDVI, EVI, SAVI, moisture indices", - "Build augmentation.py using albumentations (rotation, flip, spectral noise)", - "Add temporal compositing - median/max NDVI composites over time windows", - ]), - ("Week 7-8: Scale & Performance", [ - "Integrate Dask for distributed preprocessing of large image collections", - "Optimize data loading with parallel I/O and memory-mapped files", - "Build data caching layer for preprocessed tiles", - ]), - ]) - pdf.month_block("MONTH 3: Production Readiness (Weeks 9-12)", [ - ("Week 9-10: Quality & Validation", [ - "Implement data validation framework (schema checks, anomaly detection)", - "Set up DVC (Data Version Control) for dataset tracking", - "Create data quality reports and monitoring dashboards", - ]), - ("Week 11-12: Documentation & Integration", [ - "Write comprehensive docstrings and module documentation", - "Integration testing with ML pipeline (ensure DataLoader feeds models correctly)", - "Create data pipeline tutorial notebook for onboarding", - ]), - ]) - - # Git Workflow - pdf.section_title("Your Git Workflow") - pdf.body_text("Follow this branching convention for all your work:") - pdf.code_block( - "# Create feature branches from develop\n" - "git checkout develop\n" - "git pull origin develop\n" - "git checkout -b feature/data-sentinel2-loader\n" - "\n" - "# Your branch naming convention:\n" - "feature/data-* (new data features)\n" - "fix/data-* (bug fixes in data module)\n" - "refactor/data-* (restructuring data code)" - ) - pdf.body_text( - "All PRs go to the develop branch. PRs require at least 1 review from another team member. " - "Tag @edoh-Onuh or @franchaise for data-related reviews since they consume your data outputs." - ) - pdf.ln(3) - - # Key Collaborators - pdf.section_title("Your Key Collaborators") - pdf.bullet("@edoh-Onuh (ML Lead) - Your DataLoaders feed directly into their training pipeline. Coordinate on tensor shapes, normalization, and augmentation strategies.") - pdf.bullet("@franchaise (Analytics Lead) - They need processed data for carbon estimation. Align on feature formats and metadata.") - pdf.bullet("Olufemi Taiwo (API Lead) - Inference pipeline uses your preprocessing code. Ensure consistency between training and inference data paths.") - pdf.bullet("@cutewizzy11 (Full-Stack) - Frontend map visualizations may need GeoJSON exports from your geospatial utils.") - - # Code Pipeline - pdf.section_title("Your Code Pipeline") - pdf.body_text("This is your end-to-end working pipeline from environment setup to pushing code.") - - pdf.subsection_title("Step 1: Environment Setup") - pdf.code_block( - "# Clone and install dependencies\n" - "git clone https://github.com/Climate-Vision/ClimateVision.git\n" - "cd ClimateVision\n" - "pip install -r requirements.txt\n" - "\n" - "# Authenticate Google Earth Engine\n" - "python scripts/setup_gee.py\n" - "# Follow browser prompt to authorise your GEE service account" - ) - - pdf.subsection_title("Step 2: Analysis-Specific Band Mapping") - pdf.body_text("config.yaml defines bands per analysis type. Your band_mapping.py reads this:") - pdf.code_block( - "# config.yaml analysis type band definitions\n" - "deforestation: [B04, B03, B02, B08] # Red, Green, Blue, NIR -> 4ch -> 2cl\n" - "ice_melting: [B02, B03, B04, B11] # Blue, Green, Red, SWIR -> 4ch -> 3cl\n" - "flooding: [B03, B08, B11] # Green, NIR, SWIR -> 3ch -> 3cl\n" - "\n" - "# Python usage\n" - "from climatevision.data.band_mapping import get_bands_for_analysis, get_model_config\n" - "\n" - "bands = get_bands_for_analysis('flooding')\n" - "# -> ['B03', 'B08', 'B11']\n" - "\n" - "cfg = get_model_config('flooding')\n" - "# -> {'in_channels': 3, 'num_classes': 3, 'weights': 'models/unet_flood.pth'}" - ) - pdf.ln(2) - - pdf.subsection_title("Step 3: Cloud Masking with SCL Band") - pdf.body_text("Sentinel-2 Scene Classification Layer (SCL) pixel values:") - pdf.code_block( - "# SCL band values\n" - "KEEP = [4, 5, 6, 7, 10] # vegetation, bare soil, water, low cloud, thin cirrus\n" - "MASK = [0, 1, 2, 3, 8, 9] # NO_DATA, SATURATED, DARK, SHADOW, med/high cloud\n" - "\n" - "# Usage in preprocessing.py\n" - "from climatevision.data.preprocessing import apply_scl_cloud_mask\n" - "\n" - "clean_image = apply_scl_cloud_mask(image, scl_band)\n" - "# image: (C, H, W) scl_band: (H, W) uint8" - ) - pdf.ln(2) - - pdf.subsection_title("Step 4: Ingest Satellite Data") - pdf.code_block( - "# Download Sentinel-2 imagery for a bounding box and date range\n" - "python scripts/prepare_data.py \\\n" - " --bbox \"-60,-15,-45,5\" \\\n" - " --start 2023-01-01 \\\n" - " --end 2023-12-31 \\\n" - " --source sentinel2 \\\n" - " --output data/raw/amazon_2023\n" - "\n" - "# Output: GeoTIFF tiles saved to data/raw/amazon_2023/" - ) - - pdf.subsection_title("Step 5: Preprocess & Build Dataset") - pdf.code_block( - "# Run cloud masking, normalization, and 256x256 tiling\n" - "python - <<'EOF'\n" - "from climatevision.data.preprocessing import preprocess_tiles\n" - "preprocess_tiles(\n" - " input_dir='data/raw/amazon_2023/',\n" - " output_dir='data/processed/amazon_2023/',\n" - " tile_size=256,\n" - " cloud_threshold=0.2\n" - ")\n" - "EOF\n" - "\n" - "# Validate the PyTorch dataset loads correctly\n" - "python - <<'EOF'\n" - "from climatevision.data.dataset import SatelliteDataset\n" - "ds = SatelliteDataset('data/processed/amazon_2023/', split='train')\n" - "img, mask = ds[0]\n" - "print(f'Dataset size: {len(ds)} | Image shape: {img.shape} | Mask shape: {mask.shape}')\n" - "EOF" - ) - - pdf.subsection_title("Step 6: Compute Spectral Indices") - pdf.code_block( - "# Calculate NDVI, EVI, and moisture indices from raw bands\n" - "python - <<'EOF'\n" - "from climatevision.utils.geospatial import compute_indices\n" - "compute_indices(\n" - " tile_dir='data/processed/amazon_2023/',\n" - " indices=['ndvi', 'evi', 'moisture'],\n" - " output_dir='data/processed/amazon_2023_features/'\n" - ")\n" - "EOF" - ) - - pdf.subsection_title("Step 7: Commit & Push Your Work") - pdf.code_block( - "# Switch to your git identity\n" - "source team_docs/switch_user.sh adeolu\n" - "\n" - "# Create a feature branch\n" - "git checkout develop\n" - "git pull origin develop\n" - "git checkout -b feature/data-sentinel2-preprocessing\n" - "\n" - "# Stage your files\n" - "git add src/climatevision/data/\n" - "git add scripts/prepare_data.py\n" - "\n" - "# Commit\n" - "git commit -m \"feat(data): add Sentinel-2 cloud masking and tile preprocessing pipeline\"\n" - "\n" - "# Push from your account\n" - "git push adeolu feature/data-sentinel2-preprocessing" - ) - - pdf.output(os.path.join(OUTPUT_DIR, "Adeolu_Mary_Oshadare_Role.pdf")) - print("Created: Adeolu_Mary_Oshadare_Role.pdf") - - -def create_francis_doc(): - pdf = RoleDoc("Francis Umo") - pdf.add_page() - - pdf.set_font("Helvetica", "B", 18) - pdf.cell(0, 10, "Francis Umo", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_font("Helvetica", "", 11) - pdf.set_text_color(100, 100, 100) - pdf.cell(0, 7, "Data Science Engineer 3 - Carbon Analytics & Validation Lead", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_text_color(0, 0, 0) - pdf.ln(5) - - pdf.key_value("GitHub", "@franchaise") - pdf.key_value("Access Level", "Maintainer") - pdf.key_value("Reports To", "@Goldokpa (Project Owner)") - pdf.key_value("Project Duration", "3 Months") - pdf.ln(3) - - # How It Fits Me - pdf.section_title("How This Role Fits You") - pdf.body_text( - "With 8+ years of progressive experience in data analysis and business intelligence, you bring " - "the deepest analytical maturity on this team. While others focus on building models and pipelines, " - "you are the person who makes sure the numbers tell the right story and that the results are trustworthy." - ) - pdf.body_text( - "Your expertise in Python, PostgreSQL, and SQL means you can build the carbon estimation models that " - "require heavy data querying, aggregation, and statistical analysis. At Dataleum, you conducted data " - "quality checks, developed dashboards to monitor financial data, and created reports that reduced fraud " - "by 80% - that same rigour is exactly what's needed when validating whether our ML models are correctly " - "estimating carbon loss from deforestation." - ) - pdf.body_text( - "Your proficiency in Tableau and Power BI is a direct match for building the impact reporting layer. " - "ClimateVision needs to produce clear, visual reports that conservation organizations and government " - "agencies can act on. Your data storytelling background makes you the ideal person to translate " - "raw model outputs into actionable intelligence." - ) - pdf.body_text( - "Your cross-functional collaboration experience - working with IT teams, stakeholders, and bringing " - "analytical models into production - means you understand how to bridge the gap between a data science " - "experiment and a production metric that decision-makers rely on." - ) - pdf.ln(2) - - # Role Description - pdf.section_title("Your Role on ClimateVision") - pdf.body_text( - "You own the analytics and validation layer - everything that turns raw model predictions into " - "meaningful environmental metrics. If the ML model says 'this pixel is deforested,' you quantify " - "what that means in tons of carbon, hectares of forest, and dollars of environmental impact." - ) - pdf.subsection_title("Core Responsibilities") - pdf.bullet("Develop carbon stock estimation models (Random Forest, XGBoost regression)") - pdf.bullet("Build biomass-to-carbon conversion pipelines using allometric equations") - pdf.bullet("Implement uncertainty quantification (bootstrap, Monte Carlo, confidence intervals)") - pdf.bullet("Create ground truth validation framework - compare model outputs to known data") - pdf.bullet("Build statistical testing suite (hypothesis testing, A/B testing for model versions)") - pdf.bullet("Design and generate impact reports (area deforested, carbon lost, trends over time)") - pdf.bullet("Develop KPI dashboards for monitoring model performance and environmental outcomes") - pdf.bullet("Create validation notebooks demonstrating model accuracy across regions") - pdf.ln(2) - - # Codebase Ownership - pdf.section_title("Your Codebase Ownership") - pdf.body_text("You are the primary owner of the following files and directories:") - pdf.code_block( - "src/climatevision/analytics/ # PRIMARY OWNER - New analytics module\n" - " carbon.py # Carbon stock estimation models\n" - " statistics.py # Statistical testing & analysis\n" - " reporting.py # Impact report generation\n" - " validation.py # Ground truth validation framework\n" - " __init__.py # Module exports\n" - "\n" - "src/climatevision/models/\n" - " regression.py # PRIMARY OWNER - Biomass/carbon regression\n" - "\n" - "src/climatevision/utils/\n" - " metrics.py # CO-OWNER - Extend with carbon metrics\n" - "\n" - "notebooks/\n" - " 03_carbon_analysis.ipynb # Carbon estimation analysis\n" - " 04_model_validation.ipynb # Validation & benchmarking\n" - " 05_impact_reporting.ipynb # Reporting notebook\n" - "\n" - "outputs/\n" - " reports/ # Generated impact reports\n" - " dashboards/ # Dashboard configs" - ) - pdf.ln(2) - - # 3-Month Timeline - pdf.section_title("Your 3-Month Delivery Timeline") - pdf.month_block("MONTH 1: Foundation (Weeks 1-4)", [ - ("Week 1-2: Carbon Estimation Models", [ - "Research allometric equations for biomass estimation by forest type", - "Build carbon.py - Random Forest & XGBoost regression for biomass prediction", - "Create feature pipeline: spectral indices -> biomass -> carbon conversion", - "Implement metrics for regression evaluation (RMSE, MAE, R-squared)", - ]), - ("Week 3-4: Validation Framework", [ - "Build validation.py - compare model predictions to ground truth datasets", - "Source and integrate reference data (Global Forest Watch, forest inventory data)", - "Create confusion matrix, precision/recall analysis for segmentation outputs", - "Write 04_model_validation.ipynb with baseline validation results", - ]), - ]) - pdf.month_block("MONTH 2: Advanced Analytics (Weeks 5-8)", [ - ("Week 5-6: Uncertainty & Statistical Testing", [ - "Implement bootstrap confidence intervals for carbon estimates", - "Build Monte Carlo simulation for uncertainty propagation", - "Create statistics.py - hypothesis testing, trend analysis functions", - "Implement A/B testing framework for comparing model versions", - ]), - ("Week 7-8: Impact Reporting", [ - "Build reporting.py - automated report generation (PDF/HTML)", - "Design KPI framework: hectares lost, carbon tons, trend direction", - "Create 05_impact_reporting.ipynb - template for regional impact reports", - "Integrate with PostgreSQL for historical metric storage", - ]), - ]) - pdf.month_block("MONTH 3: Production Readiness (Weeks 9-12)", [ - ("Week 9-10: Dashboard & Integration", [ - "Build dashboard data endpoints (feed metrics to frontend charts)", - "Create time-series analysis for deforestation trend tracking", - "Implement anomaly detection for unusual forest loss patterns", - ]), - ("Week 11-12: Documentation & Case Studies", [ - "Produce 3 regional case study reports (Amazon, Congo, Southeast Asia)", - "Write comprehensive documentation for analytics module", - "Final validation sweep across all model outputs", - "Performance benchmarking and accuracy documentation", - ]), - ]) - - # Git Workflow - pdf.section_title("Your Git Workflow") - pdf.code_block( - "# Create feature branches from develop\n" - "git checkout develop\n" - "git pull origin develop\n" - "git checkout -b feature/analytics-carbon-estimation\n" - "\n" - "# Your branch naming convention:\n" - "feature/analytics-* (new analytics features)\n" - "fix/analytics-* (bug fixes)\n" - "refactor/analytics-* (code restructuring)" - ) - pdf.body_text( - "All PRs go to the develop branch. PRs require at least 1 review. " - "Tag @edoh-Onuh for reviews on model evaluation metrics, and @Oshgig for data format questions." - ) - pdf.ln(3) - - # Key Collaborators - pdf.section_title("Your Key Collaborators") - pdf.bullet("@edoh-Onuh (ML Lead) - Their model predictions are your primary input. Coordinate on output formats, probability thresholds, and confidence scores.") - pdf.bullet("@Oshgig (Data Pipeline Lead) - She provides the preprocessed data you need for carbon regression features. Align on spectral indices and metadata.") - pdf.bullet("Olufemi Taiwo (API Lead) - Your analytics endpoints need to be exposed through the API. Coordinate on response schemas.") - pdf.bullet("@cutewizzy11 (Full-Stack) - Frontend dashboards visualize your metrics. Provide JSON data contracts for charts.") - - # Code Pipeline - pdf.section_title("Your Code Pipeline") - pdf.body_text("Your pipeline starts where the ML model ends - taking prediction masks and turning them into carbon impact numbers and stakeholder reports.") - - pdf.subsection_title("Step 1: Environment Setup") - pdf.code_block( - "git clone https://github.com/Climate-Vision/ClimateVision.git\n" - "cd ClimateVision\n" - "pip install -r requirements.txt\n" - "\n" - "# Verify analytics dependencies\n" - "python -c \"import xgboost, sklearn, mlflow, optuna; print('Analytics stack ready')\"" - ) - - pdf.subsection_title("Step 2: Run Inference to Get Prediction Masks") - pdf.code_block( - "# Generate deforestation masks from a trained model\n" - "python scripts/infer.py \\\n" - " --bbox \"-60,-15,-45,5\" \\\n" - " --date 2023-06-01 \\\n" - " --analysis_type deforestation \\\n" - " --output outputs/masks/\n" - "\n" - "# Output: outputs/masks/deforestation_mask.tif + confidence_scores.npy" - ) - - pdf.subsection_title("Step 3: Estimate Carbon Loss") - pdf.code_block( - "# Run carbon stock estimation on the prediction mask\n" - "python - <<'EOF'\n" - "from climatevision.analytics.carbon import estimate_carbon\n" - "result = estimate_carbon(\n" - " mask_path='outputs/masks/deforestation_mask.tif',\n" - " region='amazon',\n" - " forest_type='tropical_moist'\n" - ")\n" - "print(f\"Deforested area: {result['hectares']:.1f} ha\")\n" - "print(f\"Carbon lost: {result['carbon_tonnes']:.1f} tCO2e\")\n" - "print(f\"Confidence CI: {result['ci_lower']:.1f} - {result['ci_upper']:.1f} tCO2e\")\n" - "EOF" - ) - - pdf.subsection_title("Step 4: Validate Against Ground Truth") - pdf.code_block( - "# Compare model outputs to Global Forest Watch reference data\n" - "python - <<'EOF'\n" - "from climatevision.analytics.validation import validate_predictions\n" - "metrics = validate_predictions(\n" - " pred_mask='outputs/masks/deforestation_mask.tif',\n" - " ground_truth='data/ground_truth/amazon_gfw_2023.tif'\n" - ")\n" - "print(f\"IoU: {metrics['iou']:.3f} | F1: {metrics['f1']:.3f} | Precision: {metrics['precision']:.3f}\")\n" - "EOF" - ) - - pdf.subsection_title("Step 5: Generate Impact Report") - pdf.code_block( - "# Auto-generate a PDF/HTML impact report for stakeholders\n" - "python - <<'EOF'\n" - "from climatevision.analytics.reporting import generate_report\n" - "generate_report(\n" - " region='amazon',\n" - " period='2023-Q2',\n" - " carbon_result=result,\n" - " validation_metrics=metrics,\n" - " output_dir='outputs/reports/'\n" - ")\n" - "EOF\n" - "\n" - "# Output: outputs/reports/amazon_2023-Q2_impact_report.pdf" - ) - - pdf.subsection_title("Step 7: Commit & Push Your Work") - pdf.code_block( - "# Switch to your git identity\n" - "source team_docs/switch_user.sh francis\n" - "\n" - "git checkout develop && git pull origin develop\n" - "git checkout -b feature/analytics-carbon-estimation\n" - "\n" - "git add src/climatevision/analytics/\n" - "git add notebooks/03_carbon_analysis.ipynb\n" - "git commit -m \"feat(analytics): add carbon stock estimation with confidence intervals\"\n" - "\n" - "git push francis feature/analytics-carbon-estimation" - ) - - pdf.output(os.path.join(OUTPUT_DIR, "Francis_Umo_Role.pdf")) - print("Created: Francis_Umo_Role.pdf") - - -def create_olufemi_doc(): - pdf = RoleDoc("Olufemi Taiwo") - pdf.add_page() - - pdf.set_font("Helvetica", "B", 18) - pdf.cell(0, 10, "Olufemi Taiwo", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_font("Helvetica", "", 11) - pdf.set_text_color(100, 100, 100) - pdf.cell(0, 7, "Data Science Engineer 4 - API & Data Quality Lead", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_text_color(0, 0, 0) - pdf.ln(5) - - pdf.key_value("GitHub", "(To be assigned)") - pdf.key_value("Access Level", "Maintainer") - pdf.key_value("Reports To", "@Goldokpa (Project Owner)") - pdf.key_value("Project Duration", "3 Months") - pdf.ln(3) - - # How It Fits Me - pdf.section_title("How This Role Fits You") - pdf.body_text( - "Your current role as Reporting and Data Quality Officer at the Royal Marsden NHS Foundation Trust " - "is the clearest signal for this assignment. Every working day you validate data flows, investigate " - "mismatches across Epic EPR, troubleshoot system errors using SQL, and hold the line on reporting " - "accuracy for senior clinical stakeholders. That obsessive attention to data integrity at every step " - "from input to output is exactly what ClimateVision's API and inference pipeline need." - ) - pdf.body_text( - "At Fidelity Bank, you kept payment platforms reliable around the clock as an Application Support " - "Analyst - triaging incidents, analysing root causes, and producing service reports that guided " - "operational decisions. ClimateVision runs a similar system: satellite images arrive as requests, " - "the API must respond correctly and quickly, and any failure needs to be caught, logged, and " - "escalated before it reaches users. That is your wheelhouse." - ) - pdf.body_text( - "Your Business Intelligence work at Dataleum - building Power BI dashboards, conducting data quality " - "checks, achieving 98% GDPR compliance - means you already understand auditability. In a climate " - "monitoring system used by NGOs and government agencies, every prediction must be traceable, every " - "alert explainable, and every data flow compliant. You build that confidence layer." - ) - pdf.body_text( - "Your ITIL 4 certification is a direct fit for incident management, change control, and problem " - "management in production. Combined with your MSc in Data Science, you are the person who makes " - "the API not just functional, but operationally trustworthy - with structured logging, audit trails, " - "validated schemas, and monitoring that surfaces issues before users notice them." - ) - pdf.ln(2) - - # Role Description - pdf.section_title("Your Role on ClimateVision") - pdf.body_text( - "You own the API layer and the inference pipeline - everything between a trained model and a user " - "receiving a validated, structured response. You ensure the system is reliable, observable, and " - "produces outputs that are correct and auditable. You are the data quality gatekeeper for every " - "prediction that leaves the system." - ) - pdf.subsection_title("Core Responsibilities") - pdf.bullet("Extend and maintain the FastAPI backend (endpoints, authentication, request validation)") - pdf.bullet("Build Pydantic schemas for all API request/response objects - the contract for data quality") - pdf.bullet("Implement structured logging, error handling, and audit trails throughout the inference flow") - pdf.bullet("Build the inference validation layer - catch bad inputs, validate outputs, flag anomalies") - pdf.bullet("Create the deforestation alert system with configurable thresholds and notification routing") - pdf.bullet("Build API monitoring endpoints: health checks, data quality metrics, run status dashboards") - pdf.bullet("Write SQL queries and admin endpoints for operational reporting and data audits") - pdf.bullet("Design and document the API contract (request/response schemas, error codes, versioning)") - pdf.ln(2) - - # Codebase Ownership - pdf.section_title("Your Codebase Ownership") - pdf.body_text("You are the primary owner of the following files and directories:") - pdf.code_block( - "src/climatevision/inference/ # PRIMARY OWNER\n" - " pipeline.py # Core inference pipeline\n" - " batch_processor.py # Batch processing with job queuing\n" - " postprocess.py # Output filtering & thresholding\n" - " alert_generator.py # Deforestation alert system\n" - " __init__.py\n" - "\n" - "src/climatevision/api/ # PRIMARY OWNER\n" - " main.py # FastAPI application\n" - " auth.py # API key authentication\n" - " middleware.py # Request logging, CORS\n" - " schemas.py # Pydantic request/response schemas\n" - " __init__.py\n" - "\n" - "src/climatevision/db.py # CO-OWNER - Database & audit queries\n" - "\n" - "run_api.sh # API startup script\n" - "config.yaml # API & inference config sections" - ) - pdf.ln(2) - - # 3-Month Timeline - pdf.section_title("Your 3-Month Delivery Timeline") - pdf.month_block("MONTH 1: Foundation (Weeks 1-4)", [ - ("Week 1-2: Schemas & Validation", [ - "Build schemas.py - Pydantic models for every API request and response object", - "Extend pipeline.py with input validation: image shape, band count, coordinate bounds", - "Add structured JSON logging throughout the inference flow (request ID, timestamps, errors)", - "Implement output validation - flag predictions outside expected confidence ranges", - ]), - ("Week 3-4: API Hardening", [ - "Implement auth.py - API key authentication and organisation-based access control", - "Build middleware.py - request logging, CORS, request size limits", - "Create /api/health, /api/status, and /api/metrics endpoints for operational monitoring", - "Write API integration tests covering validation edge cases and error responses", - ]), - ]) - pdf.month_block("MONTH 2: Quality & Alerts (Weeks 5-8)", [ - ("Week 5-6: Inference Quality Layer", [ - "Build postprocess.py - confidence thresholding and prediction filtering", - "Implement anomaly detection for unusual inference outputs (flag for review)", - "Create audit log entries for every prediction: input hash, model version, output summary", - "Build batch_processor.py - parallel image processing with per-job status tracking", - ]), - ("Week 7-8: Alert System & Reporting", [ - "Build alert_generator.py - configurable deforestation threshold alerting", - "Implement notification routing (email, webhook) for triggered alerts", - "Write SQL reporting queries for run history, error rates, and data quality KPIs", - "Create admin endpoints for operational dashboards: throughput, failure rates, alert volumes", - ]), - ]) - pdf.month_block("MONTH 3: Observability & Documentation (Weeks 9-12)", [ - ("Week 9-10: Monitoring & Data Quality Reports", [ - "Build a /api/reports endpoint returning data quality metrics over configurable time windows", - "Implement request tracing: correlate API requests to inference runs to alerts", - "Create a data quality dashboard feed (JSON) for the frontend to visualise pipeline health", - "SQL-based audit trail queries: who requested what, when, and with what result", - ]), - ("Week 11-12: Documentation & Launch Readiness", [ - "Write the API reference: all endpoints, schemas, error codes, and usage examples", - "Document the incident response runbook: what each error means and how to resolve it", - "Security review: input sanitisation, SQL injection checks, API key rotation procedures", - "Final integration testing with all team modules - validate end-to-end data flow", - ]), - ]) - - # Git Workflow - pdf.section_title("Your Git Workflow") - pdf.code_block( - "# Create feature branches from develop\n" - "git checkout develop\n" - "git pull origin develop\n" - "git checkout -b feature/api-schemas\n" - "\n" - "# Your branch naming convention:\n" - "feature/api-* (API features & endpoints)\n" - "feature/inference-* (inference pipeline & validation)\n" - "feature/schemas-* (Pydantic schema changes)\n" - "fix/api-* (bug fixes)" - ) - pdf.body_text( - "All PRs go to the develop branch. Tag @cutewizzy11 for API contract reviews (he consumes your " - "endpoints from the frontend) and @edoh-Onuh when touching inference logic that involves model outputs." - ) - pdf.ln(3) - - # Key Collaborators - pdf.section_title("Your Key Collaborators") - pdf.bullet("@edoh-Onuh (ML Lead) - Their trained models are loaded by your inference pipeline. Coordinate on model format (.pth vs ONNX), input shapes, output schemas, and confidence score formats.") - pdf.bullet("@Oshgig (Data Pipeline Lead) - Your inference input validation must match her preprocessing exactly. Align on normalization constants, expected band order, and coordinate formats.") - pdf.bullet("@franchaise (Analytics Lead) - Their analytics endpoints are exposed through your API. Coordinate on response schemas, pagination, and data quality flags in outputs.") - pdf.bullet("@cutewizzy11 (Full-Stack & CI/CD) - He consumes your API from the frontend and manages Docker and deployment. You two define the API contract together - endpoints, schemas, error codes.") - - # Code Pipeline - pdf.section_title("Your Code Pipeline") - pdf.body_text("Your pipeline covers running and validating the FastAPI server, testing all endpoints, enforcing data quality, and maintaining the inference layer.") - - pdf.subsection_title("Step 1: Environment Setup") - pdf.code_block( - "git clone https://github.com/Climate-Vision/ClimateVision.git\n" - "cd ClimateVision\n" - "pip install -r requirements.txt\n" - "\n" - "# Set environment variables\n" - "cp .env.example .env\n" - "# Edit .env: set MODEL_PATH, DB_PATH, API_KEY_SECRET" - ) - - pdf.subsection_title("Step 2: Start the API Server") - pdf.code_block( - "# Start FastAPI in development mode with auto-reload\n" - "uvicorn climatevision.api.main:app \\\n" - " --reload \\\n" - " --host 0.0.0.0 \\\n" - " --port 8000\n" - "\n" - "# Interactive API docs available at:\n" - "# http://localhost:8000/docs\n" - "# http://localhost:8000/redoc" - ) - - pdf.subsection_title("Step 3: Test Prediction Endpoints") - pdf.code_block( - "# Test JSON prediction endpoint\n" - "curl -X POST http://localhost:8000/predict/json \\\n" - " -H \"Content-Type: application/json\" \\\n" - " -d '{\n" - " \"bbox\": [-60, -15, -45, 5],\n" - " \"start_date\": \"2023-01-01\",\n" - " \"end_date\": \"2023-12-31\",\n" - " \"analysis_type\": \"deforestation\"\n" - " }'\n" - "\n" - "# Test file-upload endpoint\n" - "curl -X POST http://localhost:8000/predict/upload \\\n" - " -F \"file=@data/test/sample_tile.tif\" \\\n" - " -F \"analysis_type=flooding\"\n" - "\n" - "# Health check\n" - "curl http://localhost:8000/health" - ) - - pdf.subsection_title("Step 4: Run Data Quality Checks") - pdf.code_block( - "# Validate all run records in the database meet schema requirements\n" - "python - <<'EOF'\n" - "from climatevision.db import get_db_connection, validate_run_schema\n" - "conn = get_db_connection()\n" - "issues = validate_run_schema(conn)\n" - "if issues:\n" - " print(f'Data quality issues found: {len(issues)}')\n" - " for issue in issues:\n" - " print(f' - {issue}')\n" - "else:\n" - " print('All records pass quality checks')\n" - "EOF" - ) - - pdf.subsection_title("Step 5: Register an NGO Organisation") - pdf.code_block( - "# Create an NGO organisation via the API\n" - "curl -X POST http://localhost:8000/organizations \\\n" - " -H \"Content-Type: application/json\" \\\n" - " -d '{\n" - " \"name\": \"Amazon Conservation Trust\",\n" - " \"email\": \"alerts@amazonconservation.org\",\n" - " \"region\": \"amazon\"\n" - " }'\n" - "\n" - "# Add a regional monitoring subscription\n" - "curl -X POST http://localhost:8000/organizations/1/subscriptions \\\n" - " -H \"Content-Type: application/json\" \\\n" - " -d '{\"bbox\": [-60,-15,-45,5], \"analysis_type\": \"deforestation\", \"alert_threshold\": 0.15}'" - ) - - pdf.subsection_title("Step 6: Commit & Push Your Work") - pdf.code_block( - "# Switch to your git identity\n" - "source team_docs/switch_user.sh olufemi\n" - "\n" - "git checkout develop && git pull origin develop\n" - "git checkout -b feature/api-input-validation\n" - "\n" - "git add src/climatevision/api/main.py\n" - "git add src/climatevision/db.py\n" - "git commit -m \"feat(api): add Pydantic input validation and audit logging to predict endpoints\"\n" - "\n" - "# Push from YOUR GitHub account (femi23)\n" - "git push olufemi feature/api-input-validation" - ) - - pdf.output(os.path.join(OUTPUT_DIR, "Olufemi_Taiwo_Role.pdf")) - print("Created: Olufemi_Taiwo_Role.pdf") - - -def create_edoh_doc(): - pdf = RoleDoc("Edoh-Onuh") - pdf.add_page() - - pdf.set_font("Helvetica", "B", 18) - pdf.cell(0, 10, "Edoh-Onuh (John Edoh Onuh)", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_font("Helvetica", "", 11) - pdf.set_text_color(100, 100, 100) - pdf.cell(0, 7, "Data Science Engineer 1 - ML Model Development Lead", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_text_color(0, 0, 0) - pdf.ln(5) - - pdf.key_value("GitHub", "@edoh-Onuh") - pdf.key_value("Access Level", "Maintainer") - pdf.key_value("Reports To", "@Goldokpa (Project Owner)") - pdf.key_value("Project Duration", "3 Months") - pdf.ln(3) - - # How It Fits Me - pdf.section_title("How This Role Fits You") - pdf.body_text( - "Your GitHub portfolio makes the case better than any job description could. You built JED Climate - " - "a full-stack climate intelligence platform - independently. It has a FastAPI analytics engine serving " - "a carbon calculator and climate predictor, PyTorch/TensorFlow ML services, real-time Recharts " - "dashboards for CO2 levels, Arctic ice extent, and sea level rise, and a 14-service Docker Compose " - "local stack. That is almost exactly what ClimateVision is. You already know this problem space." - ) - pdf.body_text( - "Your fintech-fraud-detection repo demonstrates the depth of ML engineering this role needs: " - "XGBoost, Random Forest, and Neural Network ensembles with sub-100ms inference latency, SHAP/LIME " - "explainability, concept drift detection, and a production-grade FastAPI serving layer. The same " - "engineering discipline - fast, explainable, reliable model inference - is exactly what ClimateVision's " - "deforestation detection pipeline requires." - ) - pdf.body_text( - "Your classification track record is consistent and strong: diabetes risk prediction (Scikit-learn), " - "fraud detection (XGBoost + Neural Networks), text classification (NLP), and time series forecasting " - "(Tesla stock). Every one of those is a direct analogue to forest vs. non-forest pixel segmentation - " - "the core problem you will be solving here with U-Net and Siamese architectures." - ) - pdf.body_text( - "Your sustainable energy analysis and JED Climate's environmental dashboards show you genuinely " - "understand the climate data domain - spectral trends, temporal signals, and what makes environmental " - "metrics meaningful. That context matters when you are tuning a model to detect 5% forest loss " - "in Sentinel-2 imagery at 10-metre resolution." - ) - pdf.ln(2) - - # Role Description - pdf.section_title("Your Role on ClimateVision") - pdf.body_text( - "You own all deep learning model architectures, the training pipeline, and model evaluation. " - "Your goal is to train models that achieve high accuracy on forest segmentation and change " - "detection, then package them cleanly for the inference pipeline. Carbon regression modelling " - "sits with the Analytics Lead - your focus is purely classification and change detection." - ) - pdf.subsection_title("Core Responsibilities") - pdf.bullet("Improve and extend the U-Net architecture (Attention U-Net, residual connections, multi-scale features)") - pdf.bullet("Train and evaluate the Siamese network for temporal bi-date change detection") - pdf.bullet("Build a complete training pipeline: data loading, training loop, validation, checkpointing") - pdf.bullet("Implement loss functions tuned for satellite imagery class imbalance (Focal Loss, Dice Loss)") - pdf.bullet("Run hyperparameter optimisation using Optuna (learning rate, batch size, architecture depth)") - pdf.bullet("Implement transfer learning from pretrained encoders (ResNet, EfficientNet backbones)") - pdf.bullet("Build model evaluation framework: F1, IoU, precision-recall curves, confusion matrices") - pdf.bullet("Export optimised models to ONNX for production inference speed") - pdf.bullet("Implement experiment tracking with MLflow - log runs, metrics, and artefacts") - pdf.ln(2) - - # Codebase Ownership - pdf.section_title("Your Codebase Ownership") - pdf.body_text("You are the primary owner of the following files and directories:") - pdf.code_block( - "src/climatevision/models/ # PRIMARY OWNER\n" - " unet.py # U-Net & Attention U-Net\n" - " siamese.py # Siamese change detection network\n" - " __init__.py\n" - " # Note: regression.py is owned by @franchaise (Analytics Lead)\n" - "\n" - "src/climatevision/training/ # PRIMARY OWNER - New module\n" - " trainer.py # Training loop & checkpointing\n" - " evaluator.py # Model evaluation framework\n" - " scheduler.py # Learning rate schedulers\n" - " callbacks.py # Early stopping, logging\n" - " __init__.py\n" - "\n" - "src/climatevision/utils/\n" - " metrics.py # CO-OWNER - Loss functions, metrics\n" - "\n" - "scripts/\n" - " run_training.py # Training pipeline script\n" - " train.py # Existing training script\n" - " hyperparameter_search.py # Optuna hyperparameter search\n" - "\n" - "models/ # Trained model weights\n" - "models_pretrained/ # Pretrained backbone weights" - ) - pdf.ln(2) - - # 3-Month Timeline - pdf.section_title("Your 3-Month Delivery Timeline") - pdf.month_block("MONTH 1: Foundation (Weeks 1-4)", [ - ("Week 1-2: Training Infrastructure", [ - "Build trainer.py - complete training loop with mixed-precision, gradient accumulation", - "Implement checkpointing (save best model, resume from checkpoint)", - "Create evaluator.py - F1, IoU, precision, recall, confusion matrix", - "Set up experiment tracking with MLflow - log all runs, hyperparameters, artefacts", - ]), - ("Week 3-4: Baseline Models", [ - "Train baseline U-Net on curated forest segmentation dataset", - "Implement Focal Loss and Dice Loss for forest/non-forest class imbalance", - "Run initial benchmarks: accuracy on Amazon, Congo, Southeast Asia test sets", - "Document baseline results as the performance floor to beat", - ]), - ]) - pdf.month_block("MONTH 2: Advanced Models (Weeks 5-8)", [ - ("Week 5-6: Architecture Improvements", [ - "Implement Attention U-Net with skip connection attention gates", - "Add ResNet/EfficientNet encoder backbone via transfer learning (ImageNet pretrained)", - "Run hyperparameter search with Optuna (learning rate, batch size, depth, dropout)", - "Train Siamese network for bi-temporal change detection", - ]), - ("Week 7-8: Model Optimisation", [ - "Implement model ensemble (U-Net + Attention U-Net prediction averaging)", - "Build Monte Carlo Dropout for per-pixel uncertainty estimation", - "Spatial cross-validation to prevent data leakage across adjacent image tiles", - "Performance benchmarking across all model variants - pick production candidate", - ]), - ]) - pdf.month_block("MONTH 3: Production Models (Weeks 9-12)", [ - ("Week 9-10: Export & Versioning", [ - "Export best-performing models to ONNX format for fast production inference", - "Implement model quantisation and pruning for latency reduction", - "Set up model registry with versioning, metadata, and performance records", - "Create model cards: accuracy, known limitations, training data, bias notes", - ]), - ("Week 11-12: Final Evaluation", [ - "Comprehensive evaluation on held-out test sets across all regions", - "Ablation studies: measure contribution of each architectural choice", - "Write model documentation and training reproduction guide", - "Integration testing with Olufemi's inference pipeline - validate end-to-end", - ]), - ]) - - # Git Workflow - pdf.section_title("Your Git Workflow") - pdf.code_block( - "# Create feature branches from develop\n" - "git checkout develop\n" - "git pull origin develop\n" - "git checkout -b feature/model-attention-unet\n" - "\n" - "# Your branch naming convention:\n" - "feature/model-* (new model architectures)\n" - "feature/training-* (training pipeline features)\n" - "fix/model-* (bug fixes)\n" - "experiment/model-* (experimental architectures)" - ) - pdf.body_text( - "All PRs go to the develop branch. Tag @Oshgig when your models require different data formats, " - "@franchaise when evaluation metrics or output confidence formats change, and Olufemi Taiwo " - "when touching model export formats or inference input shapes." - ) - pdf.ln(3) - - # Key Collaborators - pdf.section_title("Your Key Collaborators") - pdf.bullet("@Oshgig (Data Pipeline Lead) - She builds the DataLoaders you train on. Coordinate on tensor shapes, normalization values, band order, and augmentation strategies.") - pdf.bullet("@franchaise (Analytics Lead) - He owns carbon regression modelling and validates your classification outputs against ground truth. Share model confidence scores and prediction probability formats.") - pdf.bullet("Olufemi Taiwo (API & Data Quality Lead) - He loads your trained models into the inference pipeline. Coordinate on model file format (.pth vs ONNX), expected input shapes, and output schema.") - pdf.bullet("@cutewizzy11 (Full-Stack & CI/CD) - CI/CD pipeline runs your training scripts. Keep scripts deterministic, well-documented, and reproducible.") - - # Code Pipeline - pdf.section_title("Your Code Pipeline") - pdf.body_text("Your pipeline covers model architecture development, training, evaluation, and exporting production-ready checkpoints.") - - pdf.subsection_title("Step 1: Environment Setup") - pdf.code_block( - "git clone https://github.com/Climate-Vision/ClimateVision.git\n" - "cd ClimateVision\n" - "pip install -r requirements.txt\n" - "\n" - "# Verify PyTorch and GPU availability\n" - "python -c \"import torch; print(f'PyTorch {torch.__version__} | CUDA: {torch.cuda.is_available()}')\"" - ) - - pdf.subsection_title("Step 2: Verify Data Is Ready") - pdf.code_block( - "# Confirm @Oshgig's DataLoader feeds correctly into your model\n" - "python - <<'EOF'\n" - "from climatevision.data.dataset import SatelliteDataset\n" - "from torch.utils.data import DataLoader\n" - "ds = SatelliteDataset('data/processed/', split='train')\n" - "loader = DataLoader(ds, batch_size=4, num_workers=2)\n" - "imgs, masks = next(iter(loader))\n" - "print(f'Batch shape: {imgs.shape} | Mask shape: {masks.shape}')\n" - "# Expected: torch.Size([4, 13, 256, 256]) | torch.Size([4, 256, 256])\n" - "EOF" - ) - - pdf.subsection_title("Step 3: Train Baseline U-Net") - pdf.code_block( - "# Train baseline segmentation model\n" - "python scripts/train.py \\\n" - " --model unet \\\n" - " --analysis-type deforestation \\\n" - " --epochs 50 \\\n" - " --batch-size 16 \\\n" - " --lr 1e-4 \\\n" - " --checkpoint-dir models/ \\\n" - " --mlflow-tracking\n" - "\n" - "# Monitor training: open http://localhost:5000 (MLflow UI)\n" - "mlflow ui --port 5000" - ) - - pdf.subsection_title("Step 4: Hyperparameter Search") - pdf.code_block( - "# Run Optuna search over learning rate, batch size, depth\n" - "python scripts/hyperparameter_search.py \\\n" - " --model unet \\\n" - " --n-trials 50 \\\n" - " --study-name unet_deforestation_v1 \\\n" - " --metric val_iou\n" - "\n" - "# Best trial is automatically saved to models/best_hparam_unet.pth" - ) - - pdf.subsection_title("Step 5: Evaluate & Export Model") - pdf.code_block( - "# Full evaluation on held-out test set\n" - "python scripts/evaluate.py \\\n" - " --checkpoint models/best_unet.pth \\\n" - " --split test \\\n" - " --analysis-type deforestation\n" - "\n" - "# Export to ONNX for fast production inference\n" - "python scripts/export_model.py \\\n" - " --checkpoint models/best_unet.pth \\\n" - " --format onnx \\\n" - " --output models/unet_deforestation_v1.onnx" - ) - - pdf.subsection_title("Step 6: Commit & Push Your Work") - pdf.code_block( - "# Switch to your git identity\n" - "source team_docs/switch_user.sh edoh\n" - "\n" - "git checkout develop && git pull origin develop\n" - "git checkout -b feature/model-attention-unet\n" - "\n" - "git add src/climatevision/models/unet.py\n" - "git add src/climatevision/training/\n" - "git commit -m \"feat(model): add attention gates to U-Net encoder skip connections\"\n" - "\n" - "git push edoh feature/model-attention-unet" - ) - - pdf.output(os.path.join(OUTPUT_DIR, "Edoh_Onuh_Role.pdf")) - print("Created: Edoh_Onuh_Role.pdf") - - -def create_victor_doc(): - pdf = RoleDoc("Victor Mbachu") - pdf.add_page() - - pdf.set_font("Helvetica", "B", 18) - pdf.cell(0, 10, "Victor Mbachu", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_font("Helvetica", "", 11) - pdf.set_text_color(100, 100, 100) - pdf.cell(0, 7, "Senior Full-Stack Engineer & Infrastructure Co-Owner", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_text_color(0, 0, 0) - pdf.ln(5) - - pdf.key_value("GitHub", "@cutewizzy11") - pdf.key_value("Access Level", "Co-Owner (Admin)") - pdf.key_value("Reports To", "@Goldokpa (Project Owner)") - pdf.key_value("Project Duration", "3 Months") - pdf.ln(3) - - # How It Fits Me - pdf.section_title("How This Role Fits You") - pdf.body_text( - "At Zeta Global you design and run distributed microservice systems handling over 2 million API " - "requests daily with 99.9% uptime across multiple AWS regions - ECS Fargate clusters, RDS Aurora, " - "SNS/SQS messaging, and blue-green CI/CD deployments provisioned via Terraform. You also serve as " - "on-call engineer with a 15-minute average incident resolution time. That is the production " - "engineering standard ClimateVision needs to reach, and you have already built it professionally." - ) - pdf.body_text( - "At RWS Global you containerised applications with Docker, deployed across dev, staging, and " - "production environments, led a team of 3 engineers in Agile sprints, and maintained GitHub Actions " - "CI/CD pipelines with TDD coverage. The Docker and deployment ownership on this project - " - "previously unassigned - is a natural fit: you do this as part of your day job, not as a " - "stretch task." - ) - pdf.body_text( - "Your stack breadth is the reason you can serve as repository co-owner rather than just a " - "frontend contributor. React, Next.js, Vue, TypeScript, Node.js, PHP/Laravel, Python/Django - " - "you can read and reason about the FastAPI backend, the PyTorch inference pipeline, and the " - "React dashboard with equal confidence. Reviewing PRs across four data scientists requires " - "that range. Your AWS Certified Cloud Practitioner and Professional Scrum Master certifications " - "anchor both the infrastructure ownership and the project coordination function." - ) - pdf.body_text( - "Your AI integration experience - GPT-4 and Anthropic API work at RWS Global and PetMe - " - "means you understand the ML serving layer you are wrapping with a frontend. When @edoh-Onuh " - "exports a model and Olufemi builds the inference API, you are not reading foreign code. You " - "have shipped production AI features before. Your two co-authored papers on agentic AI systems " - "show that engagement runs deeper than implementation." - ) - pdf.ln(2) - - # Role Description - pdf.section_title("Your Role on ClimateVision") - pdf.body_text( - "You own the frontend application, the CI/CD infrastructure, and the Docker/deployment layer. " - "As co-owner you are also the quality gate for all code entering the repository - the one " - "person on the team who can review and reason about every layer of the stack." - ) - pdf.subsection_title("Core Responsibilities - Frontend") - pdf.bullet("Build the React/TypeScript dashboard with interactive Leaflet map for satellite analysis results") - pdf.bullet("Create Recharts components for deforestation trends, carbon metrics, and model performance") - pdf.bullet("Implement api.ts - the fully-typed API client for all FastAPI backend communication") - pdf.bullet("Build the alert notification panel for real-time deforestation alerts") - pdf.bullet("Implement responsive TailwindCSS design for desktop and tablet viewports") - pdf.bullet("Create the deep-dive analysis page with region selector, date range picker, and model comparison") - pdf.ln(1) - - pdf.subsection_title("Core Responsibilities - Infrastructure & CI/CD") - pdf.bullet("Own the Dockerfile - multi-stage production build for the FastAPI + frontend application") - pdf.bullet("Own docker-compose.yml - local development stack wiring API, database, and frontend services") - pdf.bullet("Build and maintain GitHub Actions CI/CD pipelines: lint, type-check, test, and deploy on every PR") - pdf.bullet("Manage production environment configuration - dev/staging/prod separation and secrets management") - pdf.bullet("Serve as first responder for production incidents - triage, diagnose, and coordinate resolution") - pdf.ln(1) - - pdf.subsection_title("Sprint Progress - April 2026") - pdf.bullet("DONE: GitHub Actions CI pipeline (Python flake8 + pytest, frontend npm build)") - pdf.bullet("DONE: Test scaffolding (tests/ directory with pytest fixtures)") - pdf.bullet("DONE: Frontend build fixes (case-sensitive import paths)") - pdf.bullet("DONE: Dependency fixes (removed gdal pip package, added email-validator)") - pdf.bullet("PENDING: Frontend unit tests with Vitest + React Testing Library") - pdf.bullet("PENDING: Auth UI - capture X-API-Key in AppContext") - pdf.bullet("PENDING: WebSocket client for real-time run status") - pdf.bullet("PENDING: Alert notification UI with severity filters") - pdf.bullet("PENDING: Mask overlay on map component") - pdf.bullet("PENDING: Docker Compose for full-stack local dev") - pdf.ln(1) - - pdf.subsection_title("Core Responsibilities - Co-Owner") - pdf.bullet("Review and merge pull requests from all team members (target: <24 hour turnaround)") - pdf.bullet("Manage GitHub issues, milestones, project boards, and sprint planning") - pdf.bullet("Enforce branch protection rules, code quality standards, and API contract consistency") - pdf.bullet("Manage the release process: version tagging, changelog, and release notes") - pdf.ln(2) - - # Codebase Ownership - pdf.section_title("Your Codebase Ownership") - pdf.body_text("You are the primary owner of the following files and directories:") - pdf.code_block( - "frontend/ # PRIMARY OWNER - Entire frontend\n" - " src/\n" - " App.tsx # Main application shell\n" - " api.ts # Typed API client\n" - " main.tsx # Entry point\n" - " styles.css # TailwindCSS styles\n" - " components/ # Component library\n" - " Map.tsx # Leaflet map\n" - " ResultsViewer.tsx # Prediction results\n" - " Charts.tsx # Recharts visualizations\n" - " AlertPanel.tsx # Alert notifications\n" - " Settings.tsx # User settings\n" - " pages/\n" - " Dashboard.tsx # Main dashboard\n" - " Analysis.tsx # Deep analysis view\n" - " History.tsx # Run history\n" - " package.json | vite.config.ts | tsconfig.json\n" - "\n" - "Dockerfile # PRIMARY OWNER - Multi-stage production build\n" - "docker-compose.yml # PRIMARY OWNER - Local development stack\n" - "\n" - ".github/workflows/ # PRIMARY OWNER\n" - " ci.yml # Continuous integration\n" - " deploy.yml # Deployment pipeline\n" - " tests.yml # Test automation\n" - "\n" - "tests/ # CO-OWNER (with all DS engineers)" - ) - pdf.ln(2) - - # 3-Month Timeline - pdf.section_title("Your 3-Month Delivery Timeline") - pdf.month_block("MONTH 1: Foundation (Weeks 1-4)", [ - ("Week 1-2: Infrastructure & CI/CD", [ - "Write multi-stage Dockerfile for optimised API + frontend production image", - "Build docker-compose.yml wiring FastAPI, SQLite/PostgreSQL, and frontend services locally", - "Set up GitHub Actions CI: lint, type-check, pytest, and Vite build on every PR", - "Create branch protection rules: require passing CI and 1 review before merging to develop", - ]), - ("Week 3-4: Frontend Architecture & Core Components", [ - "Configure React Router, Vite, TypeScript strict mode, TailwindCSS, ESLint, and Prettier", - "Build Map.tsx - Leaflet map with GeoJSON overlay for deforestation masks", - "Implement api.ts - fully-typed API client for all FastAPI endpoints", - "Create Dashboard.tsx - main landing page with summary metrics and run status", - ]), - ]) - pdf.month_block("MONTH 2: Feature Development (Weeks 5-8)", [ - ("Week 5-6: Data Visualisation", [ - "Build Charts.tsx - Recharts components for deforestation trend lines, bar charts, gauges", - "Create ResultsViewer.tsx - segmentation masks overlaid on satellite imagery", - "Implement Analysis.tsx - region selector, date picker, model comparison view", - "Set up Vitest and React Testing Library - component test coverage from the start", - ]), - ("Week 7-8: Real-Time & Interactivity", [ - "Build WebSocket integration for live prediction job status updates", - "Create AlertPanel.tsx - real-time deforestation alert notification feed", - "Implement History.tsx - paginated, filterable list of past analysis runs", - "Build Settings.tsx - user preferences and API key management", - ]), - ]) - pdf.month_block("MONTH 3: Production Readiness (Weeks 9-12)", [ - ("Week 9-10: Deployment & Environment Config", [ - "Configure dev/staging/prod environment separation with secrets management", - "Set up deployment pipeline to Vercel (frontend) and Docker-based backend hosting", - "Implement health monitoring and automated alerting for production incidents", - "Performance pass: code splitting, lazy loading, image optimisation, bundle analysis", - ]), - ("Week 11-12: Integration, Testing & Release", [ - "Full end-to-end integration testing against all backend API endpoints", - "Responsive design audit for tablet and large desktop breakpoints", - "Accessibility review: keyboard navigation and screen reader compatibility", - "Manage v1.0 release: changelog, version tag, release notes, and deployment sign-off", - ]), - ]) - - # Git Workflow - pdf.section_title("Your Git Workflow") - pdf.code_block( - "# Create feature branches from develop\n" - "git checkout develop\n" - "git pull origin develop\n" - "git checkout -b feature/frontend-leaflet-map\n" - "\n" - "# Your branch naming convention:\n" - "feature/frontend-* (frontend features)\n" - "feature/infra-* (Docker, CI/CD, deployment)\n" - "feature/ci-* (GitHub Actions changes)\n" - "fix/frontend-* (bug fixes)\n" - "release/v* (release branches)" - ) - pdf.body_text( - "As co-owner, you can merge directly to develop after self-review for frontend-only or infra-only " - "changes. For changes touching shared Python code or API contracts, get a review from @Goldokpa " - "or the relevant module owner." - ) - pdf.ln(3) - - # Key Collaborators - pdf.section_title("Your Key Collaborators") - pdf.bullet("Olufemi Taiwo (API & Data Quality Lead) - He owns the FastAPI schemas, inference validation, and audit logging. You own the Docker image and deployment pipeline that runs his API. Define the API contract together: endpoint URLs, request/response shapes, auth headers, and error formats.") - pdf.bullet("@franchaise (Analytics Lead) - His carbon metrics and KPI data feed your dashboard charts. Align on JSON data contracts, refresh intervals, and pagination formats.") - pdf.bullet("@edoh-Onuh (ML Lead) - Model prediction outputs need to be visualised on the map. Coordinate on GeoJSON output format, confidence score rendering, and how prediction jobs report status via the API.") - pdf.bullet("@Oshgig (Data Pipeline Lead) - Satellite imagery tile previews on the map may draw on her geospatial utilities. Align on tile formats, coordinate systems, and GeoJSON structures.") - - # Code Pipeline - pdf.section_title("Your Code Pipeline") - pdf.body_text("Your pipeline covers frontend development, Docker orchestration, CI/CD management, and full-stack integration testing.") - - pdf.subsection_title("Step 1: Environment Setup") - pdf.code_block( - "git clone https://github.com/Climate-Vision/ClimateVision.git\n" - "cd ClimateVision\n" - "\n" - "# Backend dependencies\n" - "pip install -r requirements.txt\n" - "\n" - "# Frontend dependencies\n" - "cd frontend && npm install && cd .." - ) - - pdf.subsection_title("Step 2: Start Full Local Dev Stack") - pdf.code_block( - "# Option A: Docker Compose (full stack - recommended)\n" - "docker-compose up --build\n" - "# API: http://localhost:8000\n" - "# Frontend: http://localhost:5173\n" - "# MLflow: http://localhost:5000\n" - "\n" - "# Option B: Run services individually for faster iteration\n" - "uvicorn climatevision.api.main:app --reload --port 8000 &\n" - "cd frontend && npm run dev" - ) - - pdf.subsection_title("Step 3: Frontend Development Loop") - pdf.code_block( - "cd frontend\n" - "\n" - "# Run linting and type checks\n" - "npm run lint\n" - "npm run type-check\n" - "\n" - "# Run component tests\n" - "npm run test\n" - "\n" - "# Build production bundle and check for errors\n" - "npm run build\n" - "\n" - "# Preview production build locally\n" - "npm run preview" - ) - - pdf.subsection_title("Step 4: Current CI/CD Configuration") - pdf.body_text("The following .github/workflows/ci.yml is live and runs on every PR to main/develop:") - pdf.code_block( - "name: CI\n" - "on:\n" - " push:\n" - " branches: [main, develop]\n" - " pull_request:\n" - " branches: [main, develop]\n" - "\n" - "jobs:\n" - " python:\n" - " runs-on: ubuntu-latest\n" - " steps:\n" - " - uses: actions/checkout@v4\n" - " - uses: actions/setup-python@v5\n" - " with: {python-version: '3.11'}\n" - " - run: sudo apt-get update && sudo apt-get install -y libgl1\n" - " - run: pip install -r requirements.txt && pip install -e .\n" - " - run: flake8 src/ --select=E9,F63,F7,F82\n" - " - run: pytest tests/ -v --tb=short\n" - "\n" - " frontend:\n" - " runs-on: ubuntu-latest\n" - " defaults: {run: {working-directory: frontend}}\n" - " steps:\n" - " - uses: actions/checkout@v4\n" - " - uses: actions/setup-node@v4\n" - " with: {node-version: '20', cache: 'npm'}\n" - " - run: npm ci\n" - " - run: npm run build" - ) - pdf.ln(2) - - pdf.subsection_title("Step 5: Build & Test Docker Image") - pdf.code_block( - "# Build production Docker image\n" - "docker build -t climatevision:latest .\n" - "\n" - "# Run container and verify it starts cleanly\n" - "docker run -p 8000:8000 climatevision:latest\n" - "\n" - "# Check all services are healthy inside the container\n" - "curl http://localhost:8000/health\n" - "\n" - "# Inspect image size and layers\n" - "docker image inspect climatevision:latest | grep Size" - ) - - pdf.subsection_title("Step 6: Run Full CI Checks Locally") - pdf.code_block( - "# Simulate the GitHub Actions CI pipeline before pushing\n" - "\n" - "# 1. Python: lint and tests\n" - "flake8 src/ --count --select=E9,F63,F7,F82 --show-source --statistics\n" - "flake8 src/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics\n" - "pytest tests/ -v --tb=short\n" - "\n" - "# 2. Frontend: build\n" - "cd frontend && npm run build\n" - "\n" - "# 3. Docker build succeeds\n" - "docker-compose build" - ) - - pdf.subsection_title("Step 6: Commit & Push Your Work") - pdf.code_block( - "# Switch to your git identity\n" - "source team_docs/switch_user.sh victor\n" - "\n" - "git checkout develop && git pull origin develop\n" - "git checkout -b feature/frontend-leaflet-map\n" - "\n" - "git add frontend/src/components/Map.tsx\n" - "git add frontend/src/api.ts\n" - "git commit -m \"feat(frontend): add Leaflet map with GeoJSON deforestation overlay\"\n" - "\n" - "git push victor feature/frontend-leaflet-map\n" - "\n" - "# As co-owner: review and merge PRs from the team\n" - "# gh pr review --approve\n" - "# gh pr merge --squash" - ) - - pdf.output(os.path.join(OUTPUT_DIR, "Victor_Mbachu_Role.pdf")) - print("Created: Victor_Mbachu_Role.pdf") - - -def create_godswill_doc(): - pdf = RoleDoc("Godswill Okoroafor Chukwu") - pdf.add_page() - - pdf.set_font("Helvetica", "B", 18) - pdf.cell(0, 10, "Godswill Okoroafor Chukwu", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_font("Helvetica", "", 11) - pdf.set_text_color(100, 100, 100) - pdf.cell(0, 7, "Data Science Engineer 5 - ML Training, Experiment Tracking & Insights Lead", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_text_color(0, 0, 0) - pdf.ln(5) - - pdf.key_value("GitHub", "(To be assigned)") - pdf.key_value("Access Level", "Maintainer") - pdf.key_value("Reports To", "@Goldokpa (Project Owner)") - pdf.key_value("Project Duration", "3 Months") - pdf.ln(3) - - # How It Fits Me - pdf.section_title("How This Role Fits You") - pdf.body_text( - "Your MSc in Big Data and Data Science Technology (Distinction) from Northumbria University is the " - "academic backbone this role demands. You have not just studied machine learning - you have delivered " - "it in production environments. At Amdari Inc., you built predictive and forecasting models that drove " - "strategic revenue decisions, applied clustering to identify at-risk student groups, and automated " - "reporting pipelines that cut manual processing time significantly. Every one of those deliverables " - "maps directly onto what ClimateVision needs from its ML training and insights layer." - ) - pdf.body_text( - "Where @edoh-Onuh architects the deep learning models (U-Net, Siamese networks), you are the engineer " - "who drives those models through rigorous training cycles, tracks every experiment, measures every " - "metric, and extracts insights from the results. Your experience running classification, regression, " - "and clustering pipelines in Python - combined with your Data Scientist role at Amdari - means you " - "understand the full lifecycle: data in, model trained, results validated, insights delivered." - ) - pdf.body_text( - "Your proficiency in Power BI and Looker Studio is a strategic asset here. ClimateVision generates " - "real predictions - deforestation percentages, ice extent loss, flood area - that conservation NGOs " - "and research partners need presented clearly. You build the reporting layer that translates raw model " - "outputs into KPI dashboards, trend reports, and alert summaries that non-technical stakeholders " - "can act on. That is the last mile between a working model and measurable real-world impact." - ) - pdf.body_text( - "Your background in automating recurring reporting processes with Python and designing cross-functional " - "dashboards means you also own the bridge between the ML pipeline and the business intelligence layer. " - "With your DataCamp Associate Data Scientist certification and Full Stack Data Science qualification " - "from 10Alytics, you bring both the theoretical depth and the applied toolkit that this role requires." - ) - pdf.ln(2) - - # Role Description - pdf.section_title("Your Role on ClimateVision") - pdf.body_text( - "You own the training analytics, experiment tracking, and insights reporting pipeline - the layer that " - "connects raw model outputs to actionable environmental intelligence. While the ML Lead builds model " - "architectures and the Data Pipeline Lead ingests satellite imagery, you are the engineer who runs " - "training experiments at scale, tracks what works and why, measures model impact, and delivers " - "structured insights to teams and stakeholders. You are the system's analytical conscience." - ) - pdf.subsection_title("Core Responsibilities") - pdf.bullet("Orchestrate model training runs using scripts/train.py and scripts/run_training.py with full experiment tracking via MLflow") - pdf.bullet("Design and execute hyperparameter tuning experiments using Optuna to maximise IoU, F1, and Dice scores") - pdf.bullet("Build and maintain the model evaluation pipeline - benchmarking across deforestation, ice melting, and flooding tasks") - pdf.bullet("Implement clustering analysis on prediction outputs to identify regional environmental patterns and hotspots") - pdf.bullet("Develop forecasting models to project deforestation trends, ice melt rates, and flood risk over time") - pdf.bullet("Automate KPI reporting pipelines that summarise model performance and environmental metrics for NGO stakeholders") - pdf.bullet("Design and maintain Power BI / Looker Studio dashboards tracking training progress, model accuracy, and climate impact") - pdf.bullet("Create data quality reports that validate training datasets and flag anomalies before they reach the model") - pdf.bullet("Produce regional impact analysis notebooks showing before/after environmental change metrics") - pdf.bullet("Feed structured insight data to the API layer and React dashboard for live reporting") - pdf.ln(2) - - # Codebase Ownership - pdf.section_title("Your Codebase Ownership") - pdf.body_text("You are the primary owner of the following files and directories:") - pdf.code_block( - "scripts/ # PRIMARY OWNER - Training & evaluation scripts\n" - " train.py # Model training entry point\n" - " run_training.py # Training orchestration & scheduling\n" - " evaluate.py # Model evaluation & benchmarking\n" - " infer.py # Single inference runner\n" - "\n" - "src/climatevision/training/\n" - " trainer.py # CO-OWNER - Training loop, EMA, mixed precision\n" - " losses.py # CO-OWNER - Focal Loss, Dice Loss tuning\n" - "\n" - "src/climatevision/utils/\n" - " metrics.py # CO-OWNER - IoU, F1, Dice, recall tracking\n" - " visualization.py # CO-OWNER - Training curve & result plots\n" - "\n" - "notebooks/\n" - " 06_training_analysis.ipynb # Experiment tracking & training insights\n" - " 07_model_benchmarking.ipynb # Cross-task model performance comparison\n" - " 08_regional_insights.ipynb # Clustering & trend analysis by region\n" - "\n" - "outputs/\n" - " reports/training/ # Training run reports\n" - " dashboards/kpi/ # KPI dashboard configs\n" - "\n" - "logs/ # Training logs & MLflow run artifacts\n" - "models/ # Model checkpoints (coordinate with ML Lead)" - ) - pdf.ln(2) - - # Key Impact Areas - pdf.section_title("Your High-Impact Contributions") - pdf.body_text( - "Your work directly determines whether ClimateVision's models are as accurate as possible and whether " - "their outputs are trusted by the organisations that rely on them. Three areas define your impact:" - ) - pdf.subsection_title("1. Experiment-Driven Model Improvement") - pdf.body_text( - "Every training run you log is a data point. By systematically tracking learning rate schedules, " - "augmentation strategies, loss function weights, and batch sizes via MLflow and Optuna, you will " - "build the evidence base that drives model accuracy from baseline to production-grade. Your tuning " - "work is the difference between a model that detects 65% of deforestation events and one that " - "detects 85%." - ) - pdf.subsection_title("2. Regional Clustering & Trend Forecasting") - pdf.body_text( - "Your clustering expertise turns raw pixel predictions into geographic intelligence. By grouping " - "regions with similar deforestation trajectories or flood risk patterns, you reveal insights that " - "no single prediction run can show. Paired with time-series forecasting models, you can project " - "where the next environmental crisis is developing before it becomes catastrophic - giving NGO " - "partners the lead time they need to act." - ) - pdf.subsection_title("3. Stakeholder-Ready Reporting") - pdf.body_text( - "Raw model metrics mean nothing to a conservation officer or a policy researcher. Your Power BI " - "and automated Python reporting pipelines convert IoU scores and segmentation masks into carbon " - "loss estimates, hectare counts, and trend alerts that stakeholders can put in a board report. " - "This is the last mile of impact - and you own it." - ) - pdf.ln(2) - - # 3-Month Timeline - pdf.section_title("Your 3-Month Delivery Timeline") - pdf.month_block("MONTH 1: Foundation (Weeks 1-4)", [ - ("Week 1-2: Training Infrastructure & Experiment Tracking", [ - "Set up MLflow tracking server and connect to scripts/train.py", - "Instrument trainer.py to log all hyperparameters, metrics, and artifacts per run", - "Run baseline training experiments for deforestation, ice melting, and flooding tasks", - "Document baseline IoU, F1, and Dice scores per analysis type", - ]), - ("Week 3-4: Evaluation Pipeline", [ - "Build scripts/evaluate.py - full evaluation suite with per-class metrics", - "Extend metrics.py with precision-recall curves and confusion matrix exports", - "Create 07_model_benchmarking.ipynb - cross-task performance comparison", - "Identify top 3 weaknesses in baseline models and propose tuning strategies", - ]), - ]) - pdf.month_block("MONTH 2: Optimisation & Insights (Weeks 5-8)", [ - ("Week 5-6: Hyperparameter Tuning", [ - "Set up Optuna study for learning rate, batch size, loss weights, and augmentation", - "Run tuning experiments targeting IoU improvement of at least 10% over baseline", - "Log all trials in MLflow with full reproducibility (seed, config, checkpoint)", - "Implement best-config automatic checkpoint promotion pipeline", - ]), - ("Week 7-8: Clustering & Trend Forecasting", [ - "Build regional clustering pipeline using K-Means / DBSCAN on prediction outputs", - "Develop time-series forecasting models for deforestation and ice melt trends", - "Create 08_regional_insights.ipynb - hotspot identification and trend projections", - "Generate first set of regional environmental trend reports", - ]), - ]) - pdf.month_block("MONTH 3: Reporting & Production Readiness (Weeks 9-12)", [ - ("Week 9-10: KPI Dashboard & Automated Reporting", [ - "Build automated Python reporting pipeline - weekly model performance summaries", - "Design Power BI / Looker Studio KPI dashboard (accuracy trends, alert counts, coverage)", - "Expose dashboard data via API endpoints coordinated with Olufemi", - "Automate NGO-facing impact reports: area affected, confidence scores, trend direction", - ]), - ("Week 11-12: Documentation & Final Benchmarks", [ - "Write 06_training_analysis.ipynb - full experiment history and lessons learned", - "Produce final benchmark report comparing all model versions across 3 months", - "Document all MLflow experiments, best checkpoints, and recommended configs", - "Deliver 3 regional case study insight reports to the team for stakeholder use", - ]), - ]) - - # Git Workflow - pdf.section_title("Your Git Workflow") - pdf.body_text("Follow this branching convention for all your work:") - pdf.code_block( - "# Create feature branches from develop\n" - "git checkout develop\n" - "git pull origin develop\n" - "git checkout -b feature/training-mlflow-setup\n" - "\n" - "# Your branch naming convention:\n" - "feature/training-* (training pipeline features)\n" - "feature/insights-* (reporting and analytics features)\n" - "fix/training-* (bug fixes in training scripts)\n" - "experiment/tuning-* (hyperparameter experiment branches)" - ) - pdf.body_text( - "All PRs go to the develop branch. PRs require at least 1 review. " - "Tag @edoh-Onuh for model architecture questions and @franchaise for analytics overlap reviews. " - "Always attach MLflow run IDs in PRs that change training logic so reviewers can verify metrics." - ) - pdf.ln(3) - - # Key Collaborators - pdf.section_title("Your Key Collaborators") - pdf.bullet("@edoh-Onuh (ML Model Development Lead) - You run the training experiments on their model architectures. Coordinate on loss function choices, training hyperparameters, and checkpoint formats. Their architecture decisions constrain your tuning search space.") - pdf.bullet("@Oshgig (Data Pipeline Lead) - Your training runs consume her PyTorch DataLoaders. Align on tensor shapes, normalization ranges, augmentation strategies, and the data split structure (train/val/test).") - pdf.bullet("@franchaise (Carbon Analytics Lead) - Your model evaluation outputs are the input to their carbon estimation and validation work. Provide segmentation mask formats, confidence scores, and per-class metrics in agreed schemas.") - pdf.bullet("Olufemi Taiwo (API & Data Quality Lead) - Your KPI reporting data needs to be surfaced via API endpoints. Coordinate on response formats, refresh cycles, and how training run metadata is exposed to the dashboard.") - pdf.bullet("Victor Mbachu (Full-Stack & Infrastructure) - Your dashboard configs and reporting outputs feed the React frontend visualisations. Align on JSON contracts for time-series charts, gauge metrics, and alert summaries.") - - # Code Pipeline - pdf.section_title("Your Code Pipeline") - pdf.body_text("Your pipeline covers experiment tracking setup, running and tuning training jobs, evaluating model performance, and generating insight reports for stakeholders.") - - pdf.subsection_title("Step 1: Environment Setup") - pdf.code_block( - "git clone https://github.com/Climate-Vision/ClimateVision.git\n" - "cd ClimateVision\n" - "pip install -r requirements.txt\n" - "\n" - "# Verify ML and analytics stack\n" - "python -c \"import torch, mlflow, optuna, sklearn; print('ML stack ready')\"\n" - "\n" - "# Start MLflow tracking server\n" - "mlflow server --host 0.0.0.0 --port 5000 &\n" - "# Dashboard: http://localhost:5000" - ) - - pdf.subsection_title("Step 2: Run a Training Experiment") - pdf.code_block( - "# Run a tracked training job\n" - "python scripts/run_training.py \\\n" - " --config config/deforestation.yaml \\\n" - " --mlflow-tracking \\\n" - " --experiment-name deforestation_v1\n" - "\n" - "# All metrics, params, and checkpoints auto-logged to MLflow\n" - "# View results: http://localhost:5000/#/experiments" - ) - - pdf.subsection_title("Step 3: Hyperparameter Tuning with Optuna") - pdf.code_block( - "# Launch an Optuna study to find the best training config\n" - "python - <<'EOF'\n" - "import optuna, mlflow\n" - "from climatevision.training.trainer import train_with_config\n" - "\n" - "def objective(trial):\n" - " config = {\n" - " 'lr': trial.suggest_float('lr', 1e-5, 1e-3, log=True),\n" - " 'batch_size': trial.suggest_categorical('batch_size', [8, 16, 32]),\n" - " 'dropout': trial.suggest_float('dropout', 0.1, 0.5),\n" - " }\n" - " return train_with_config(config, metric='val_iou')\n" - "\n" - "study = optuna.create_study(direction='maximize', study_name='unet_deforestation')\n" - "study.optimize(objective, n_trials=50)\n" - "print(f'Best IoU: {study.best_value:.4f}')\n" - "print(f'Best params: {study.best_params}')\n" - "EOF" - ) - - pdf.subsection_title("Step 4: Evaluate & Benchmark Models") - pdf.code_block( - "# Evaluate best checkpoint across all analysis types\n" - "python scripts/evaluate.py \\\n" - " --checkpoint models/best_unet.pth \\\n" - " --split test \\\n" - " --analysis-type deforestation \\\n" - " --export-metrics outputs/reports/training/deforestation_eval.json\n" - "\n" - "# Compare all model versions logged in MLflow\n" - "python - <<'EOF'\n" - "import mlflow\n" - "runs = mlflow.search_runs(experiment_names=['deforestation_v1'],\n" - " order_by=['metrics.val_iou DESC'])\n" - "print(runs[['run_id','metrics.val_iou','params.lr','params.batch_size']].head(10))\n" - "EOF" - ) - - pdf.subsection_title("Step 5: Generate Stakeholder KPI Report") - pdf.code_block( - "# Run clustering on prediction outputs to find regional hotspots\n" - "python - <<'EOF'\n" - "from sklearn.cluster import KMeans\n" - "import numpy as np, json\n" - "predictions = np.load('outputs/masks/deforestation_confidence.npy')\n" - "kmeans = KMeans(n_clusters=5, random_state=42).fit(predictions.reshape(-1, 1))\n" - "hotspot_regions = np.where(kmeans.labels_ == kmeans.cluster_centers_.argmax())[0]\n" - "print(f'High-risk tiles identified: {len(hotspot_regions)}')\n" - "EOF\n" - "\n" - "# Auto-generate weekly KPI summary report\n" - "python - <<'EOF'\n" - "from climatevision.analytics.reporting import generate_kpi_report\n" - "generate_kpi_report(\n" - " metrics_dir='outputs/reports/training/',\n" - " period='2024-W12',\n" - " output='outputs/dashboards/kpi/weekly_summary.pdf'\n" - ")\n" - "EOF" - ) - - pdf.subsection_title("Step 6: Commit & Push Your Work") - pdf.code_block( - "# Switch to your git identity\n" - "source team_docs/switch_user.sh godswill\n" - "\n" - "git checkout develop && git pull origin develop\n" - "git checkout -b feature/training-mlflow-setup\n" - "\n" - "git add scripts/run_training.py\n" - "git add scripts/evaluate.py\n" - "git add notebooks/06_training_analysis.ipynb\n" - "git commit -m \"feat(training): add MLflow experiment tracking and Optuna hyperparameter search\"\n" - "\n" - "git push godswill feature/training-mlflow-setup" - ) - - pdf.output(os.path.join(OUTPUT_DIR, "Godswill_Chukwu_Role.pdf")) - print("Created: Godswill_Chukwu_Role.pdf") - - -def create_paul_doc(): - pdf = RoleDoc("Paul (cutewizzy11)") - pdf.add_page() - - pdf.set_font("Helvetica", "B", 18) - pdf.cell(0, 10, "Paul", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_font("Helvetica", "", 11) - pdf.set_text_color(100, 100, 100) - pdf.cell(0, 7, "Frontend Developer - React Dashboard & UI Lead", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_text_color(0, 0, 0) - pdf.ln(5) - - pdf.key_value("GitHub", "@cutewizzy11") - pdf.key_value("Access Level", "Maintainer") - pdf.key_value("Reports To", "@Goldokpa (Project Owner)") - pdf.key_value("Project Duration", "3 Months") - pdf.ln(3) - - # How It Fits - pdf.section_title("How This Role Fits You") - pdf.body_text( - "Your GitHub portfolio shows a developer who is comfortable across the full stack but has a clear " - "strength in TypeScript and JavaScript-driven interfaces. nova-agent, Data-management-Koinonia, " - "and anyebe-web-craft are all TypeScript projects - the same language ClimateVision's frontend is " - "built in. Your react-projects and ecommerce-app repositories show hands-on React experience, and " - "your Heart-Attack-Risk-Predictor on Streamlit shows you can bridge data science outputs and " - "interactive user interfaces - exactly the challenge you face here." - ) - pdf.body_text( - "ClimateVision's dashboard already has a working foundation: React 18, TypeScript strict mode, " - "Vite, TailwindCSS, React Router, Recharts, and a fully-typed API client. Your job is not to " - "start from scratch - it is to take this functional base and build the components, pages, and " - "interactions that turn it into a polished, production-ready environmental monitoring dashboard " - "that NGOs and researchers can actually use." - ) - pdf.body_text( - "Your experience with data management interfaces (Koinonia church app) and e-commerce UIs means " - "you understand how to build interfaces where users interact with structured data - filtering, " - "searching, viewing records, managing subscriptions. That skill maps directly onto ClimateVision's " - "run history browser, NGO subscription manager, and alert tracking panel. You have shipped this " - "category of UI before." - ) - pdf.ln(2) - - # Role Description - pdf.section_title("Your Role on ClimateVision") - pdf.body_text( - "You own the React dashboard - every pixel the end user sees. The backend API is built, the " - "data models are defined, and the component library has a strong foundation. Your mission is " - "to complete the user-facing layer: build missing pages, wire components to live API data, " - "implement real-time updates, and ensure the interface is responsive, accessible, and fast. " - "You are the engineer who makes ClimateVision feel like a real product." - ) - pdf.subsection_title("Core Responsibilities") - pdf.bullet("Build and complete all dashboard pages: Dashboard home, NGO Management, Alerts, and deep-dive Analysis views") - pdf.bullet("Wire all components to live API data using the existing api.ts client - replace mock/static data throughout") - pdf.bullet("Implement real-time run status updates using polling (useRunPolling hook) and WebSocket for live job tracking") - pdf.bullet("Build the NGO management page - organisation registration, subscription setup, alert acknowledgment") - pdf.bullet("Implement the Alerts page - filterable, paginated alert feed with severity badges and map drill-down") - pdf.bullet("Extend the Map components - overlay segmentation masks on the map after prediction completes") - pdf.bullet("Add component-level tests using Vitest and React Testing Library") - pdf.bullet("Ensure full responsive design for tablet and desktop breakpoints using TailwindCSS") - pdf.bullet("Implement accessibility: keyboard navigation, screen reader labels, focus management") - pdf.bullet("Performance: code splitting, lazy loading pages, skeleton loading states already in the UI library") - pdf.ln(2) - - # Codebase Ownership - pdf.section_title("Your Codebase Ownership") - pdf.body_text("You are the primary owner of the entire frontend directory:") - pdf.code_block( - "frontend/src/ # PRIMARY OWNER - Full frontend\n" - "\n" - " pages/ # PRIMARY OWNER - All page components\n" - " NewAnalysis.tsx # Exists - extend with live map result overlay\n" - " Upload.tsx # Exists - connect to /predict/upload endpoint\n" - " RunHistory.tsx # Exists - add filters, pagination, search\n" - " Analytics.tsx # Exists - connect live data, add date picker\n" - " Settings.tsx # Exists - wire to API key and config endpoints\n" - " Dashboard.tsx # BUILD - Home page KPI summary\n" - " NGOManagement.tsx # BUILD - Org registration + subscriptions\n" - " Alerts.tsx # BUILD - Alert feed with severity filters\n" - "\n" - " components/ # PRIMARY OWNER - All UI components\n" - " charts/ # Extend existing Recharts components\n" - " Map/ # Extend - add mask overlay on results\n" - " ngo/ # Complete - wire AlertsPanel, SubscriptionManager\n" - " results/ # Complete - wire ResultsPanel to live predictions\n" - " runs/ # Extend RunCard with status polling\n" - " ui/ # Extend UI library as needed\n" - "\n" - " api.ts # CO-OWNER - Add any missing endpoint calls\n" - " types.ts # CO-OWNER - Add frontend-specific types\n" - " contexts/ # CO-OWNER - AppContext, ToastContext\n" - " hooks/ # PRIMARY OWNER - useGeocoding, useRunPolling\n" - "\n" - " tests/ # PRIMARY OWNER - Component tests (to be created)\n" - " components/\n" - " pages/" - ) - pdf.ln(2) - - # 3-Month Timeline - pdf.section_title("Your 3-Month Delivery Timeline") - pdf.month_block("MONTH 1: Foundation & Live Data (Weeks 1-4)", [ - ("Week 1-2: Setup & API Wiring", [ - "Clone repo, install deps, run dev server - verify all pages render", - "Run the FastAPI backend locally and confirm api.ts endpoints connect", - "Wire RunHistory page to live /runs API data - replace any static data", - "Wire Analytics page to live run metrics - confirm charts render with real data", - "Add loading skeletons (SkeletonCard already exists) to all data-fetching pages", - ]), - ("Week 3-4: Dashboard Home & Settings", [ - "Build Dashboard.tsx - KPI summary cards: total runs, alerts, analysis breakdown", - "Add Dashboard as the new root route (/) and move NewAnalysis to /new-analysis", - "Wire Settings.tsx to API config endpoints - API base URL, analysis preferences", - "Implement Toast notifications for success/error states across all forms", - ]), - ]) - pdf.month_block("MONTH 2: NGO Features & Real-Time (Weeks 5-8)", [ - ("Week 5-6: NGO Management Page", [ - "Build NGOManagement.tsx - list registered organisations from /organizations endpoint", - "Implement organisation registration form with validation", - "Build SubscriptionManager UI - region bbox picker + analysis type + threshold", - "Wire to POST /organizations and POST /organizations/{id}/subscriptions endpoints", - ]), - ("Week 7-8: Alerts & Real-Time Updates", [ - "Build Alerts.tsx - paginated alert feed filtered by severity and analysis type", - "Implement alert acknowledgment button wired to PATCH /organizations/{id}/alerts/{id}", - "Extend useRunPolling hook to poll job status and update UI when predictions complete", - "Add live segmentation mask overlay on RegionMap after a prediction run finishes", - ]), - ]) - pdf.month_block("MONTH 3: Polish & Production (Weeks 9-12)", [ - ("Week 9-10: Testing & Accessibility", [ - "Set up Vitest and React Testing Library - write tests for all page components", - "Test all API integration points with mocked responses", - "Accessibility audit: add aria-labels, keyboard nav, focus rings across all pages", - "Responsive design audit - tablet (768px) and large desktop (1440px) breakpoints", - ]), - ("Week 11-12: Performance & Final Integration", [ - "Implement React.lazy() and Suspense for all page-level code splitting", - "Bundle analysis with vite-bundle-visualizer - eliminate unused dependencies", - "Full end-to-end test: bbox input -> prediction job -> live status -> result on map", - "Final UI polish pass: spacing, typography, colour consistency across all pages", - ]), - ]) - - # Code Pipeline - pdf.section_title("Your Code Pipeline") - pdf.body_text("Your daily pipeline as frontend developer - from clone to a live feature pushed to GitHub.") - - pdf.subsection_title("Step 1: Setup") - pdf.code_block( - "git clone https://github.com/Climate-Vision/ClimateVision.git\n" - "cd ClimateVision/frontend\n" - "npm install\n" - "\n" - "# Start the backend API (needed for live data)\n" - "cd .. && uvicorn climatevision.api.main:app --reload --port 8000 &\n" - "\n" - "# Start the frontend dev server\n" - "cd frontend && npm run dev\n" - "# App running at: http://localhost:5173" - ) - - pdf.subsection_title("Step 2: Build a New Page or Component") - pdf.code_block( - "# Example: building the Dashboard home page\n" - "touch src/pages/Dashboard.tsx\n" - "\n" - "# Import existing UI primitives - don't rebuild what exists\n" - "# Available: Card, Badge, StatusBadge, SkeletonCard, ProgressBar,\n" - "# Tooltip, EmptyState, ErrorBoundary, AnalysisTypeSelector\n" - "\n" - "# Import charts - already built with Recharts\n" - "# Available: TimeSeriesChart, BarChart, GaugeChart\n" - "\n" - "# Import API functions from api.ts\n" - "# import { listRuns, listOrganizations, listAlerts } from '../api'" - ) - - pdf.subsection_title("Step 3: Connect to Live API Data") - pdf.code_block( - "# Example: fetching live runs in a component\n" - "import { useEffect, useState } from 'react'\n" - "import { listRuns } from '../api'\n" - "import type { Run } from '../api'\n" - "\n" - "const [runs, setRuns] = useState([])\n" - "const [loading, setLoading] = useState(true)\n" - "\n" - "useEffect(() => {\n" - " listRuns().then(data => {\n" - " setRuns(data)\n" - " setLoading(false)\n" - " })\n" - "}, [])\n" - "\n" - "# Use SkeletonCard while loading\n" - "if (loading) return " - ) - - pdf.subsection_title("Step 4: Run Quality Checks") - pdf.code_block( - "# From the frontend/ directory:\n" - "\n" - "# TypeScript type check - zero errors before pushing\n" - "npm run type-check\n" - "\n" - "# Lint check\n" - "npm run lint\n" - "\n" - "# Run component tests\n" - "npm run test\n" - "\n" - "# Production build - must succeed before any PR\n" - "npm run build" - ) - - pdf.subsection_title("Step 5: Commit & Push Your Work") - pdf.code_block( - "# Switch to your git identity\n" - "source team_docs/switch_user.sh paul\n" - "\n" - "git checkout develop && git pull origin develop\n" - "git checkout -b feature/frontend-dashboard-home\n" - "\n" - "# Stage only frontend files\n" - "git add frontend/src/pages/Dashboard.tsx\n" - "git add frontend/src/main.tsx\n" - "\n" - "git commit -m \"feat(frontend): add Dashboard home page with KPI summary cards\"\n" - "\n" - "# Push from your GitHub account\n" - "git push paul feature/frontend-dashboard-home\n" - "\n" - "# Branch naming convention:\n" - "# feature/frontend-* new UI features\n" - "# fix/frontend-* bug fixes\n" - "# refactor/frontend-* component refactoring" - ) - - pdf.section_title("Your Key Collaborators") - pdf.bullet("Olufemi Taiwo (femi23) - He owns the FastAPI backend your api.ts calls. Any new endpoint you need, request it from him. Coordinate on response shapes, pagination, and error formats.") - pdf.bullet("@Goldokpa (Project Owner) - He built the original api.ts and App shell. He is your first point of contact for architecture questions and has context on every frontend design decision.") - pdf.bullet("@franchaise (Analytics Lead) - His carbon metrics and KPI data feed your Analytics and Dashboard pages. Agree on the JSON structure for chart data with him.") - pdf.bullet("Victor Mbachu (@cutewizzy11 in other refs) - If Docker or CI/CD issues block your local dev, coordinate with the infrastructure owner.") - pdf.bullet("@edoh-Onuh (ML Lead) - Model prediction outputs appear as map overlays in your UI. Coordinate on the GeoJSON mask format and confidence score schema so your map component renders them correctly.") - - pdf.output(os.path.join(OUTPUT_DIR, "Paul_cutewizzy11_Role.pdf")) - print("Created: Paul_cutewizzy11_Role.pdf") - - -def create_gold_doc(): - pdf = RoleDoc("Gold Okpa") - pdf.add_page() - - pdf.set_font("Helvetica", "B", 18) - pdf.cell(0, 10, "Gold Okpa", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_font("Helvetica", "", 11) - pdf.set_text_color(100, 100, 100) - pdf.cell(0, 7, "Project Owner & Lead Architect - ClimateVision", align="C", new_x="LMARGIN", new_y="NEXT") - pdf.set_text_color(0, 0, 0) - pdf.ln(5) - - pdf.key_value("GitHub", "@Goldokpa") - pdf.key_value("Access Level", "Owner (Admin)") - pdf.key_value("Email", "okpagold@gmail.com") - pdf.key_value("Project Duration", "Ongoing") - pdf.ln(3) - - # Role Overview - pdf.section_title("Your Role on ClimateVision") - pdf.body_text( - "You built ClimateVision from the ground up. Every foundational layer of this system - the React " - "frontend and API client, the Google Earth Engine integration with service account auth and synthetic " - "NDVI fallback, the data pipeline scripts, the training and evaluation infrastructure, the Colab " - "training notebook, and the overall architecture - was shipped by you. You are not just the project " - "owner in title. You are the technical architect, the integration lead, and the person who knows " - "every module of this codebase at a deep level." - ) - pdf.body_text( - "As the team scales, your role shifts from building everything yourself to orchestrating six " - "specialist engineers - setting the architectural direction, reviewing and merging their code, " - "maintaining the integrity of the overall system, and ensuring every module fits together cleanly. " - "You are the final authority on what goes into the main branch and what ships to users." - ) - pdf.ln(2) - - pdf.subsection_title("Core Responsibilities") - pdf.bullet("Own the overall system architecture and make final decisions on design patterns, module boundaries, and API contracts") - pdf.bullet("Review and merge all pull requests into the develop and main branches") - pdf.bullet("Maintain config.yaml - the single source of truth for all model, data, and API configuration") - pdf.bullet("Own the Google Earth Engine integration and satellite data orchestration at the system level") - pdf.bullet("Manage GitHub repository: branch protection rules, secrets, environment variables, and access permissions") - pdf.bullet("Coordinate sprint planning, milestone tracking, and cross-team dependency resolution") - pdf.bullet("Own the release process: version tagging, changelog, and production deployment sign-off") - pdf.bullet("Onboard new team members and ensure every engineer has the access and context they need") - pdf.bullet("Make final calls on model selection, analysis type prioritisation, and stakeholder deliverables") - pdf.ln(2) - - # Codebase Ownership - pdf.section_title("Your Codebase Ownership") - pdf.body_text("As project owner you have authority over the full codebase. Your primary ownership areas are:") - pdf.code_block( - "config.yaml # PRIMARY OWNER - All system configuration\n" - ".env / .env.example # PRIMARY OWNER - Environment secrets template\n" - "setup.py / requirements.txt # PRIMARY OWNER - Package definition\n" - "\n" - "src/climatevision/ # ARCHITECT - Full codebase authority\n" - " api/main.py # Co-owner with Olufemi - original author\n" - " analysis/ # Original author - analysis framework\n" - " config.py # PRIMARY OWNER - Config management\n" - " db.py # PRIMARY OWNER - Database schema\n" - "\n" - "scripts/ # ORIGINAL AUTHOR - All pipeline scripts\n" - " prepare_data.py # GEE data pipeline (you built this)\n" - " setup_gee.py # GEE service account auth\n" - " train.py | evaluate.py | infer.py # Training & inference scripts\n" - " export_model.py # ONNX export\n" - "\n" - "frontend/ # ORIGINAL AUTHOR - App shell & API client\n" - " src/App.tsx # Main application\n" - " src/api.ts # API client (you wrote this)\n" - "\n" - "notebooks/ # ORIGINAL AUTHOR\n" - " train_on_colab.ipynb # Colab training notebook\n" - "\n" - ".github/ # PRIMARY OWNER - CI/CD and repo rules\n" - "README.md / CONTRIBUTING.md # PRIMARY OWNER - Public documentation" - ) - pdf.ln(2) - - # 3-Month Plan - pdf.section_title("Your 3-Month Orchestration Plan") - pdf.month_block("MONTH 1: Team Integration (Weeks 1-4)", [ - ("Week 1-2: Onboarding & Access", [ - "Grant all 6 engineers Maintainer access on GitHub", - "Set up branch protection: require passing CI + 1 review on develop", - "Create GitHub project board with milestones mapped to each engineer's 3-month timeline", - "Distribute and walk through each team member's role document", - "Verify all engineers can clone the repo, install dependencies, and run the API locally", - ]), - ("Week 3-4: Architecture Alignment", [ - "Hold kickoff session: walkthrough of config.yaml, module boundaries, and API contracts", - "Define and document tensor shapes, data formats, and model output schemas", - "Review and merge first PRs from each team member - establish code review rhythm", - "Set up MLflow server on shared infrastructure for experiment tracking", - ]), - ]) - pdf.month_block("MONTH 2: Integration & Quality (Weeks 5-8)", [ - ("Week 5-6: Cross-Module Integration", [ - "Integration test: Adeolu's DataLoader -> Edoh's model -> Olufemi's inference API", - "Integration test: Olufemi's API output -> Francis' carbon estimation -> Victor's dashboard", - "Resolve any data contract mismatches between modules", - "Set up automated integration test suite in GitHub Actions", - ]), - ("Week 7-8: Architecture Reviews", [ - "Review all module implementations against original architecture design", - "Identify and resolve any technical debt or design drift before it compounds", - "Run end-to-end test: satellite bbox input -> dashboard output for all 3 analysis types", - "Performance profiling: measure API latency and model inference time", - ]), - ]) - pdf.month_block("MONTH 3: Production & Release (Weeks 9-12)", [ - ("Week 9-10: Production Hardening", [ - "Review all security configurations: API keys, CORS, input validation, secrets management", - "Final review of Docker and CI/CD pipeline with Victor", - "Load test the API endpoints - verify stability under concurrent requests", - "Complete documentation audit: README, API docs, and module docstrings", - ]), - ("Week 11-12: v1.0 Release", [ - "Final code review sweep across all modules", - "Tag v1.0 release with full changelog", - "Deploy to production environment and verify all services healthy", - "Publish project to open-source community and notify NGO partners", - ]), - ]) - - # Code Pipeline - pdf.section_title("Your Code Pipeline") - pdf.body_text("As project owner your pipeline covers architecture, integration testing, PR reviews, and release management - as well as direct development when extending core systems.") - - pdf.subsection_title("Step 1: Daily Project Management") - pdf.code_block( - "# Check open PRs and review queue\n" - "gh pr list --repo Climate-Vision/ClimateVision\n" - "\n" - "# Check CI status across all branches\n" - "gh run list --repo Climate-Vision/ClimateVision --limit 10\n" - "\n" - "# View open issues\n" - "gh issue list --repo Climate-Vision/ClimateVision --label bug" - ) - - pdf.subsection_title("Step 2: Review & Merge a Team Member's PR") - pdf.code_block( - "# Fetch and checkout their branch for local testing\n" - "git fetch origin\n" - "git checkout feature/data-sentinel2-preprocessing\n" - "\n" - "# Test their code runs correctly\n" - "pip install -r requirements.txt\n" - "python -c \"from climatevision.data.preprocessing import preprocess_tiles; print('OK')\"\n" - "\n" - "# Review on GitHub and approve\n" - "gh pr review --approve --body \"Tested locally - preprocessing pipeline works correctly\"\n" - "\n" - "# Merge into develop\n" - "gh pr merge --squash --delete-branch" - ) - - pdf.subsection_title("Step 3: Run End-to-End Integration Test") - pdf.code_block( - "# Start all services\n" - "docker-compose up --build -d\n" - "\n" - "# Test the full pipeline: bbox -> prediction -> response\n" - "curl -X POST http://localhost:8000/predict/json \\\n" - " -H \"Content-Type: application/json\" \\\n" - " -d '{\"bbox\": [-60,-15,-45,5], \"start_date\": \"2023-01-01\",\n" - " \"end_date\": \"2023-12-31\", \"analysis_type\": \"deforestation\"}'\n" - "\n" - "# Run automated integration tests\n" - "pytest tests/integration/ -v\n" - "\n" - "# Verify frontend builds and loads dashboard data\n" - "cd frontend && npm run build && npm run preview" - ) - - pdf.subsection_title("Step 4: Update System Configuration") - pdf.code_block( - "# Edit the master config (all analysis types, thresholds, model params)\n" - "# File: config.yaml\n" - "\n" - "# Example: update deforestation alert threshold\n" - "# deforestation:\n" - "# alert_threshold: 0.15 -> 0.10 (more sensitive)\n" - "\n" - "# Validate config loads correctly after changes\n" - "python - <<'EOF'\n" - "from climatevision.config import load_config\n" - "cfg = load_config('config.yaml')\n" - "print(f\"Analysis types: {list(cfg.keys())}\")\n" - "EOF" - ) - - pdf.subsection_title("Step 5: Tag a Release") - pdf.code_block( - "# Ensure you are on the owner identity\n" - "source team_docs/switch_user.sh gold\n" - "\n" - "# Merge develop into main for release\n" - "git checkout main\n" - "git merge develop --no-ff -m \"release: v1.0.0\"\n" - "\n" - "# Tag the release\n" - "git tag -a v1.0.0 -m \"ClimateVision v1.0.0 - Deforestation, Ice Melt, Flood Detection\"\n" - "\n" - "# Push main and tag to GitHub\n" - "git push origin main\n" - "git push origin v1.0.0\n" - "\n" - "# Create GitHub release with changelog\n" - "gh release create v1.0.0 \\\n" - " --title \"ClimateVision v1.0.0\" \\\n" - " --notes \"First production release. Supports deforestation, arctic ice, and flood detection.\"" - ) - - pdf.subsection_title("Step 6: Direct Development (Core Systems)") - pdf.code_block( - "# When extending core architecture directly\n" - "source team_docs/switch_user.sh gold\n" - "\n" - "git checkout develop && git pull origin develop\n" - "git checkout -b feature/core-new-analysis-type\n" - "\n" - "# Make changes to core modules (analysis/, config.py, db.py, api/main.py)\n" - "\n" - "git add src/climatevision/analysis/\n" - "git add config.yaml\n" - "git commit -m \"feat(core): add drought detection analysis type to registry\"\n" - "\n" - "# Push as project owner\n" - "git push origin feature/core-new-analysis-type" - ) - - pdf.section_title("Your Key Collaborators") - pdf.bullet("Victor Mbachu (@cutewizzy11) - Co-owner for infrastructure decisions. Coordinate on Dockerfile, CI/CD pipelines, and production deployment architecture.") - pdf.bullet("Edoh-Onuh (@edoh-Onuh) - ML Lead. Final authority on model architecture decisions sits with you, but Edoh drives the implementation. Review all model PRs carefully.") - pdf.bullet("Olufemi Taiwo (femi23) - API Lead. You are the original author of main.py. Any structural changes to the API must go through your review.") - pdf.bullet("Adeolu Mary Oshadare (@Oshgig) - Data Pipeline Lead. You built the GEE scripts she extends. Maintain alignment on data contracts between ingestion and training.") - pdf.bullet("Francis Umo (@franchaise) - Analytics Lead. Carbon estimates and impact reports are the primary stakeholder-facing output. Review these deliverables closely.") - pdf.bullet("Godswill Chukwu - ML Insights Lead. His experiment results and KPI reports inform your architectural and model selection decisions.") - - pdf.output(os.path.join(OUTPUT_DIR, "Gold_Okpa_Role.pdf")) - print("Created: Gold_Okpa_Role.pdf") - - -if __name__ == "__main__": - create_adeolu_doc() - create_francis_doc() - create_olufemi_doc() - create_edoh_doc() - create_victor_doc() - create_godswill_doc() - create_paul_doc() - create_gold_doc() - print(f"\nAll 8 role documents generated in: {OUTPUT_DIR}")