Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix SIP issue with return results from calculateStatistics
Fixes #43245

SIP failed to convert the QMap<QgsZonalStatistics::Statistic, QVariant>
so we give it an QMap<int, QVariant>.
  • Loading branch information
elpaso authored and nyalldawson committed Jun 21, 2021
1 parent 772321f commit f4a793a
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 5 deletions.
Expand Up @@ -130,7 +130,9 @@ Returns a short, friendly display name for a ``statistic``, suitable for use in
.. versionadded:: 3.12
%End

static QMap<QgsZonalStatistics::Statistic, QVariant> calculateStatistics( QgsRasterInterface *rasterInterface, const QgsGeometry &geometry, double cellSizeX, double cellSizeY, int rasterBand, QgsZonalStatistics::Statistics statistics );


static QMap<int, QVariant> calculateStatisticsInt( QgsRasterInterface *rasterInterface, const QgsGeometry &geometry, double cellSizeX, double cellSizeY, int rasterBand, QgsZonalStatistics::Statistics statistics ) /PyName=calculateStatistics/;
%Docstring
Calculates the specified ``statistics`` for the pixels of ``rasterBand``
in ``rasterInterface`` (a raster layer :py:func:`~QgsZonalStatistics.dataProvider` ) within polygon ``geometry``.
Expand Down
15 changes: 14 additions & 1 deletion src/analysis/vector/qgszonalstatistics.cpp
Expand Up @@ -287,6 +287,19 @@ QString QgsZonalStatistics::shortName( QgsZonalStatistics::Statistic statistic )
return QString();
}

///@cond PRIVATE
QMap<int, QVariant> QgsZonalStatistics::calculateStatisticsInt( QgsRasterInterface *rasterInterface, const QgsGeometry &geometry, double cellSizeX, double cellSizeY, int rasterBand, QgsZonalStatistics::Statistics statistics )
{
const auto result { QgsZonalStatistics::calculateStatistics( rasterInterface, geometry, cellSizeX, cellSizeY, rasterBand, statistics ) };
QMap<int, QVariant> pyResult;
for ( auto it = result.constBegin(); it != result.constEnd(); ++it )
{
pyResult.insert( it.key(), it.value() );
}
return pyResult;
}
/// @endcond

QMap<QgsZonalStatistics::Statistic, QVariant> QgsZonalStatistics::calculateStatistics( QgsRasterInterface *rasterInterface, const QgsGeometry &geometry, double cellSizeX, double cellSizeY, int rasterBand, QgsZonalStatistics::Statistics statistics )
{
QMap<QgsZonalStatistics::Statistic, QVariant> results;
Expand Down Expand Up @@ -327,7 +340,7 @@ QMap<QgsZonalStatistics::Statistic, QVariant> QgsZonalStatistics::calculateStati
}

// calculate the statistics
QgsAttributeMap changeAttributeMap;

if ( statistics & QgsZonalStatistics::Count )
results.insert( QgsZonalStatistics::Count, QVariant( featureStats.count ) );
if ( statistics & QgsZonalStatistics::Sum )
Expand Down
16 changes: 16 additions & 0 deletions src/analysis/vector/qgszonalstatistics.h
Expand Up @@ -155,7 +155,23 @@ class ANALYSIS_EXPORT QgsZonalStatistics
*
* \since QGIS 3.16
*/
#ifndef SIP_RUN
static QMap<QgsZonalStatistics::Statistic, QVariant> calculateStatistics( QgsRasterInterface *rasterInterface, const QgsGeometry &geometry, double cellSizeX, double cellSizeY, int rasterBand, QgsZonalStatistics::Statistics statistics );
#endif

///@cond PRIVATE
// Required to fix https://github.com/qgis/QGIS/issues/43245 (SIP is failing to convert the enum to values)

/**
* Calculates the specified \a statistics for the pixels of \a rasterBand
* in \a rasterInterface (a raster layer dataProvider() ) within polygon \a geometry.
*
* Returns a map of statistic to result value.
*
* \since QGIS 3.16
*/
static QMap<int, QVariant> calculateStatisticsInt( QgsRasterInterface *rasterInterface, const QgsGeometry &geometry, double cellSizeX, double cellSizeY, int rasterBand, QgsZonalStatistics::Statistics statistics ) SIP_PYNAME( calculateStatistics );
/// @endcond

private:
QgsZonalStatistics() = default;
Expand Down
32 changes: 29 additions & 3 deletions tests/src/python/test_qgszonalstatistics.py
Expand Up @@ -11,16 +11,19 @@
__copyright__ = 'Copyright 2013, The QGIS Project'

import qgis # NOQA

from qgis.PyQt.QtCore import QDir, QFile
from qgis.core import QgsVectorLayer, QgsRasterLayer, QgsFeature, QgsFeatureRequest
import os
import shutil
from qgis.PyQt.QtCore import QDir, QFile, QTemporaryDir
from qgis.core import QgsVectorLayer, QgsRasterLayer, QgsFeature, QgsFeatureRequest, QgsGeometry
from qgis.analysis import QgsZonalStatistics

from qgis.testing import start_app, unittest
from utilities import unitTestDataPath

start_app()

TEST_DATA_DIR = unitTestDataPath()


class TestQgsZonalStatistics(unittest.TestCase):

Expand Down Expand Up @@ -117,6 +120,29 @@ def testStatistics(self):
myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11]))
assert feat[11] == 2.0, myMessage

def test_enum_conversion(self):
"""Test regression GH #43245"""

tmp = QTemporaryDir()
origin = os.path.join(TEST_DATA_DIR, 'raster', 'band1_byte_ct_epsg4326.tif')
dest = os.path.join(tmp.path(), 'band1_byte_ct_epsg4326.tif')
shutil.copyfile(origin, dest)

layer = QgsRasterLayer(dest, 'rast', 'gdal')

stats = QgsZonalStatistics.calculateStatistics(
layer.dataProvider(),
QgsGeometry.fromWkt(layer.extent().asWktPolygon()),
layer.rasterUnitsPerPixelX(),
layer.rasterUnitsPerPixelY(),
1,
QgsZonalStatistics.Statistic.Max | QgsZonalStatistics.Statistic.Median
)

self.assertEqual(sorted(list(stats.keys())), [QgsZonalStatistics.Statistic.Median, QgsZonalStatistics.Statistic.Max])
self.assertEqual(stats[QgsZonalStatistics.Statistic.Median], 142.0)
self.assertEqual(stats[QgsZonalStatistics.Statistic.Max], 254.0)


if __name__ == '__main__':
unittest.main()

0 comments on commit f4a793a

Please sign in to comment.