Skip to content

Conversation

jayneel-shah18
Copy link
Contributor

This PR introduces a comprehensive test suite for the i.smap GRASS GIS module, validating its functionality. The suite ensures the robustness of classification algorithms.

Key Updates in this PR

  • Synthetic Data Generation: Procedurally generates test data using mathematical expressions.
  • Basic Classification Test: Validates correct classification into distinct classes.
  • Goodness Map Test: Checks the accuracy of the goodness-of-fit map.
  • Maximum Likelihood Estimation Test: Ensures correct application of the -m flag.
  • Block Size Consistency Test: Evaluates the stability of results across different block sizes.

Test Case Descriptions

  1. Basic Classification Test
    • Verifies that the classification using i.smap produces the expected number of distinct classes.
  2. Goodness Map Generation
    • Assesses the correctness of the goodness map by comparing statistical properties against reference values.
  3. Maximum Likelihood Estimation Validation
    • Ensures proper application of the -m flag and evaluates the classification accuracy using r.kappa.
  4. Block Size Impact
    • Compares outputs across different block sizes to validate result consistency.

Performance

  • Windows: 2.862s
  • macOS: 1.486s
  • Ubuntu: 2.393s

This test suite significantly enhances the reliability of the i.smap module by covering both core functionalities and edge cases. Looking forward to feedback and potential refinements!

@github-actions github-actions bot added Python Related code is in Python module imagery tests Related to Test Suite labels Mar 18, 2025
@petrasovaa petrasovaa merged commit 689b1dd into OSGeo:main Mar 30, 2025
28 checks passed
@github-actions github-actions bot added this to the 8.5.0 milestone Mar 30, 2025
@jayneel-shah18 jayneel-shah18 deleted the i_smap_tests branch March 30, 2025 18:15
@wenzeslaus
Copy link
Member

The test sometimes fails on my PR (#5527). Anyone else noticed anything strange with this new i.smap test?

For example in https://github.com/OSGeo/grass/actions/runs/14423101622/job/40448155461?pr=5527:

Running ./imagery/i.smap/testsuite/test_i_smap.py...
========================================================================
0..3..6..9..12..15..18..21..24..27..30..33..36..39..42..45..48..51..54..57..60..63..66..69..72..75..78..81..84..87..90..93..96..99..100
..0..3..6..9..12..15..18..21..24..27..30..33..36..39..42..45..48..51..54..57..60..63..66..69..72..75..78..81..84..87..90..93..96..99..100
.F
======================================================================
FAIL: test_with_goodness_map (__main__.TestISmap)
Validate goodness of fit map generation and
----------------------------------------------------------------------
Traceback (most recent call last):
  File "imagery/i.smap/testsuite/test_i_smap.py", line 113, in test_with_goodness_map
    self.assertRasterFitsUnivar(self.goodness_map, reference_stats, precision=1e-6)
  File "etc/python/grass/gunittest/case.py", line 295, in assertRasterFitsUnivar
    self.assertModuleKeyValue(
  File "etc/python/grass/gunittest/case.py", line 277, in assertModuleKeyValue
    self.fail(self._formatMessage(msg, stdMsg))
AssertionError: r.univar map=smap_goodness percentile=90.0 nprocs=1 separator== format=plain -g difference:
mismatch values (key, reference, actual): [('max', 4.495414, 3.60080480575562)]
command: r.univar map=smap_goodness percentile=90.0 nprocs=1 separator== format=plain -g {'map': 'smap_goodness', 'separator': '=', 'flags': 'g'}

----------------------------------------------------------------------
Ran 4 tests in 2.364s
FAILED (failures=1)
========================================================================
FAILED ./imagery/i.smap/testsuite/test_i_smap.py (1 test failed)

@echoix
Copy link
Member

echoix commented Apr 14, 2025

Yes, I remember having to do some reruns on some PRs with a test from imagery being flaky

@echoix
Copy link
Member

echoix commented Apr 14, 2025

@jayneel-shah18
Copy link
Contributor Author

Thanks for flagging this! I dug into it and traced the flakiness to an ambiguity in the arithmetic expression used for generating the third synthetic raster input (synth_map3) in the test setup.

In the following line:

20 * exp(-((row() - 50)^2 + (col() - 50)^2) / 500)

the division by 500 is evaluated after the exponential due to operator precedence, which leads to significantly smaller values than intended. This affects the input fed to i.gensigset, and ultimately results in variations in the i.smap classification and the computed goodness map. These variations are enough to make the assertRasterFitsUnivar() test for the goodness map occasionally fail, especially since the test uses a tight precision (1e-6).

Adding parentheses to correctly group the division inside the exponent resolves the issue and makes the test deterministic:

20 * exp(-(((row() - 50)^2 + (col() - 50)^2) / 500))

I will push this fix shortly.

@jayneel-shah18
Copy link
Contributor Author

Raised the PR to resolve this behavior - #5552

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
imagery module Python Related code is in Python tests Related to Test Suite
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants