Skip to content

Dev#58

Open
AdenAthar wants to merge 50 commits intomainfrom
dev
Open

Dev#58
AdenAthar wants to merge 50 commits intomainfrom
dev

Conversation

@AdenAthar
Copy link
Copy Markdown
Collaborator

This PR brings dev into main, incorporating 10 months of development work across six areas: CI/CD automation, starch scale overhaul, QR/barcode variety tracking, segmentation improvements, test expansion, and developer documentation fixes.

Changes

Starch Scale Overhaul

  • Moved hardcoded starch scale data out of StarchArea.py into Granny/assets/starch_scales.yml, reducing the file by ~100 lines and making varieties editable without touching code
  • Changed threshold from absolute pixel value (172) to percentage of each image's actual brightness range (low + (high - low) × 0.55), improving monotonicity across different lighting
    conditions
  • Expanded from 8 to 20+ calibrated varieties including CORNELL, PURDUE, DANJOU, WA38_1, WA38_2, ENZA, EMPIRE, FUJI, IDARED, JONATHAN
  • Removed MINNEISKA, ROYAL_GALA (non-monotonic reference data), HONEY_CRISP duplicate, and old ALLAN_BROS entry
  • Deleted redundant Granny/config/starch_scales.yml leftover from initial YAML refactor

QR Code & Barcode Integration

  • Added Granny/Utils/QRCodeDetector.py — OpenCV QR detection with pyzbar 1D barcode fallback (Code128, Code39, EAN, UPC), rotation-invariant, gracefully degrades if pyzbar not installed
  • Segmentation now detects QR codes on tray images and names output fruit files PROJECT_LOT_DATE_VARIETY_fruit_##.png automatically
  • Added _parse_qr_from_filename() and _add_qr_metadata() to base Analysis class for reuse across all analyses

Segmentation Improvements

  • Raised default YOLO confidence threshold from 0.25 to 0.7 to reduce false positives
  • Added configurable label text color via text_color_r, text_color_g, text_color_b CLI parameters (default black)

CI/CD Pipeline

  • Added .github/workflows/pytest-coverage.yml — runs full test suite on Python 3.9–3.12 on every PR, uploads coverage report to QLTY Cloud

Test Expansion

  • Grew test suite from 30 to 92 tests (+16% coverage, 43%→59%)
  • Added test_StarchArea.py (23 new tests), test_QRCodeDetector.py, test_Analysis.py

Developer's Guide

  • Fixed incorrect method names and class descriptions throughout (performAnalysis → _preRun/_processImage/_postRun)
  • Rewrote adding_analysis.rst, api_reference.rst, example_analysis.rst to match actual codebase

Test plan

  • python -m pytest tests/ -v passes all 92 tests locally
  • CI passes on Python 3.9–3.12
  • Segmentation runs on a tray image with and without a QR code
  • Starch analysis produces monotonic index output on calibrated varieties
  • granny --help shows all new parameters

AdenAthar and others added 30 commits September 11, 2025 14:11
- Add input validation before assigning to self.value
- Validate that input is a string and not empty
- Only set self.value after successful directory creation and validation
- Addresses requirement to validate all values before they get set
- Created .github/workflows/pytest-coverage.yml for automated testing
- Tests run on Python 3.9, 3.10, 3.11, 3.12 for every PR
- Added pytest-cov to setup.py dependencies
- Coverage reports uploaded to QLTY Cloud (free for open source)
- Uses OIDC authentication following QLTY best practices
- Current coverage: 43% (48/48 tests passing)
- Created QRCodeDetector utility for extracting variety info from QR codes
- Integrated QR detection into Segmentation analysis
- QR detection is optional - continues normally if no QR code found
- Saves variety info (variety_code, timing, full_variety) to variety_info.txt
- Expected QR format: 'BB-Late', 'CC-Early', etc.
- Tested: Works with and without QR codes in images
- Interactive script to generate QR codes with experimental metadata
- Fields: project code, lot code, date, variety
- Format: PROJECT|LOT|DATE|VARIETY (pipe-delimited)
- Outputs to qr_codes/ directory with descriptive filenames
- Moved hardcoded starch scale data from StarchScales class to external YAML file
- Added load_starch_scales() function to read Granny/config/starch_scales.yml
- Dynamically populate StarchScales class attributes from YAML at module load time
- Reduced StarchArea.py by 102 lines by externalizing data
- Improves maintainability: starch scales can now be updated without code changes
Refactor starch scales to load from YAML configuration
- Moved hardcoded starch scale data from StarchScales class to external YAML file
- Added load_starch_scales() function to read Granny/assets/starch_scales.yml
- Dynamically populate StarchScales class attributes from YAML at module load time
- Reduced StarchArea.py by 102 lines by externalizing data
- Improves maintainability: starch scales can now be updated without code changes
Refactor starch scales to load from YAML asset file
Integrate QR code detection throughout the analysis pipeline to automatically
capture and propagate experimental metadata (project, lot, date, variety) from
tray labels to analysis outputs.

Changes:
- Update QRCodeDetector to parse pipe-delimited QR format (PROJECT|LOT|DATE|VARIETY)
- Modify Segmentation to include QR data in segmented image filenames when detected
- Add helper method to Analysis base class for extracting QR data from filenames
- Update all downstream analyses (Starch, Blush, PeelColor, SuperficialScald) to
  extract and include QR metadata in CSV outputs
- Fix MetaDataValue to use numeric_only=True when calculating tray averages to
  handle string metadata columns
- Update QR code generator to output to QR_Output directory

When QR code is detected, segmented images are named:
PROJECT_LOT_DATE_VARIETY_fruit_##.png

When no QR code is detected, default naming is used:
original_tray_name_fruit_##.png

CSV outputs now include project, lot, date, and variety columns populated from
QR data when available, otherwise left empty for backward compatibility.
The QR code generator is a utility tool for creating tray labels and does not
need to be part of the core Granny analysis package. Users can create QR codes
using standard QR generation tools or libraries as needed for their workflows.
- Added new starch scale calibrations: PURDUE, DANJOU, AMBROSIA,
  MINNEISKA, PINKLADY, REDDELICIOUS1980, REDDELICIOUS1990, ROYAL_GALA
- Implemented configurable RGB text color parameters for segmentation
  visualization (text_color_r, text_color_g, text_color_b)
- All new varieties processed with default threshold 172
- Total starch scales now: 17 varieties
- Changed PURDUE calibration to use default threshold 172
- Added threshold 150 data as commented alternative for comparison
- All varieties now consistently use threshold 172
Convert threshold from absolute value to percentage of actual pixel range.
User inputs 0-255 (e.g., 172 = 67.45%), applied as: low + (high - low) * percentage.
Provides consistent detection across varying lighting conditions.
Re-processed reference images using AI background removal (rembg) to fix
pixel range detection issues caused by white/gray backgrounds.
Moved duplicated QR/barcode metadata block into shared
_add_qr_metadata() method in Analysis.py. Replaces 12 repeated
lines in each of 4 analyses with a single method call.
All 4 varieties have monotonically decreasing ratings and were calibrated
from MSU reference images using threshold 172.
Testing on 15 MSU starch reference varieties showed that 55% threshold
achieves perfect monotonicity (15/15 varieties) compared to 67.45%
which had 8/15 monotonic with 9 violations.

The percentage-based threshold adapts to each image's actual pixel
range, providing more consistent results across varying lighting
conditions.
AdenAthar and others added 20 commits February 12, 2026 14:21
- Updated 12 MSU varieties with new 55% threshold data achieving
  15/15 monotonicity with 0 violations
- Added 5 new varieties: HONEYCRISP, BRAEBURN, EVERCRISP, GALA, ROME
- All MSU varieties now use consistent integer index scales (1-8)
- Kept non-MSU varieties unchanged (HONEY_CRISP, WA38, ALLAN_BROS,
  CORNELL, PURDUE, DANJOU, MINNEISKA, ROYAL_GALA)
Add functional tests for QR detector, metadata parsing, and tray summary
Fix FileDirValue to validate input before setting value
Major corrections:
- Analysis: Document _preRun(), _processImage(), _postRun() pattern
  instead of outdated performAnalysis() override pattern
- Image class: Fix method names (getImageName not getFileName,
  addValue not addMetadata)
- ImageIO: Clarify it's abstract with loadImage/saveImage for single
  images; ImageListValue handles lists via readValue/writeValue
- GrannyUI: Clarify addProgramArgs() is not abstract (only run() is)
- Scheduler: Fix schedule() return type (returns IDs, run() executes)
- Update all code examples to use correct patterns
…EY_CRISP

StarchArea.py:
- extractImage() -> getPixelRange()
- adjustImage() -> remapToRange()
- gray -> grayscale
- Removed unused grayscale_normalized variable

starch_scales.yml:
- Removed duplicate HONEY_CRISP entry (HONEYCRISP with 55% calibration is kept)
…tarch

- Remove getPixelRange nested function and inline its histogram logic
- Remove remapToRange function (dead code - was only used for visualization)
- Remove unused grayscale_normalized variable
- Clean up comments
…hold

- CORNELL: Updated ratings from new calibration
- PURDUE: Updated ratings from new calibration
- DANJOU: Updated ratings, interpolated 1.5 and 3.5 for monotonicity, added 6.0
- WA38: Added new entry with averaged A/B sample ratings
- WA38_1: New floral pattern scale (55% threshold), interpolated for monotonicity
- WA38_2: New radial pattern scale (55% threshold), interpolated for monotonicity
- ENZA: New scale (replaces incorrectly labeled ALLAN_BROS)
- Removed: old WA38_1, WA38_2, WA38, ALLAN_BROS, MINNEISKA, ROYAL_GALA
Update starch scales: add ENZA, new WA38_1/WA38_2, remove old entries
Tests cover: YAML scale loading, StarchScales class attributes,
parameter defaults and validation, _calculateStarch threshold math
with synthetic images, _calculateIndex closest-match logic, and
_drawMask pixel overlay behaviour. Grows test count from 54 to 76.
Add comprehensive unit tests for StarchArea
Raises the default YOLO confidence threshold from 0.25 to 0.7 to
reduce false positive detections during segmentation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Increase default segmentation confidence threshold to 0.7
The canonical file is Granny/assets/starch_scales.yml which has the
current 55% threshold calibration data. The config/ copy was an old
leftover from the initial YAML refactor.
@AdenAthar AdenAthar requested a review from spficklin April 1, 2026 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant