[zonal statistics] add variance statistic

This commit is contained in:
nirvn 2017-06-29 09:47:08 +07:00 committed by Mathieu Pellerin
parent 8379f9bb98
commit 58f6f93cb6
4 changed files with 29 additions and 5 deletions

View File

@ -36,6 +36,7 @@ class QgsZonalStatistics
Minority,
Majority,
Variety,
Variance,
All
};
typedef QFlags<QgsZonalStatistics::Statistic> Statistics;

View File

@ -158,6 +158,13 @@ int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
QgsField varietyField( varietyFieldName, QVariant::Int, QStringLiteral( "int" ) );
newFieldList.push_back( varietyField );
}
QString varianceFieldName;
if ( mStatistics & QgsZonalStatistics::Variance )
{
varianceFieldName = getUniqueFieldName( mAttributePrefix + "variance", newFieldList );
QgsField varianceField( varianceFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
newFieldList.push_back( varianceField );
}
vectorProvider->addAttributes( newFieldList );
//index of the new fields
@ -172,6 +179,7 @@ int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
int minorityIndex = mStatistics & QgsZonalStatistics::Minority ? vectorProvider->fieldNameIndex( minorityFieldName ) : -1;
int majorityIndex = mStatistics & QgsZonalStatistics::Majority ? vectorProvider->fieldNameIndex( majorityFieldName ) : -1;
int varietyIndex = mStatistics & QgsZonalStatistics::Variety ? vectorProvider->fieldNameIndex( varietyFieldName ) : -1;
int varianceIndex = mStatistics & QgsZonalStatistics::Variance ? vectorProvider->fieldNameIndex( varianceFieldName ) : -1;
if ( ( mStatistics & QgsZonalStatistics::Count && countIndex == -1 )
|| ( mStatistics & QgsZonalStatistics::Sum && sumIndex == -1 )
@ -184,6 +192,7 @@ int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
|| ( mStatistics & QgsZonalStatistics::Minority && minorityIndex == -1 )
|| ( mStatistics & QgsZonalStatistics::Majority && majorityIndex == -1 )
|| ( mStatistics & QgsZonalStatistics::Variety && varietyIndex == -1 )
|| ( mStatistics & QgsZonalStatistics::Variance && varianceIndex == -1 )
)
{
//failed to create a required field
@ -200,7 +209,8 @@ int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
QgsFeature f;
bool statsStoreValues = ( mStatistics & QgsZonalStatistics::Median ) ||
( mStatistics & QgsZonalStatistics::StDev );
( mStatistics & QgsZonalStatistics::StDev ) ||
( mStatistics & QgsZonalStatistics::Variance );
bool statsStoreValueCount = ( mStatistics & QgsZonalStatistics::Minority ) ||
( mStatistics & QgsZonalStatistics::Majority );
@ -288,7 +298,7 @@ int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
}
changeAttributeMap.insert( medianIndex, QVariant( medianValue ) );
}
if ( mStatistics & QgsZonalStatistics::StDev )
if ( mStatistics & QgsZonalStatistics::StDev || mStatistics & QgsZonalStatistics::Variance )
{
double sumSquared = 0;
for ( int i = 0; i < featureStats.values.count(); ++i )
@ -296,8 +306,14 @@ int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
double diff = featureStats.values.at( i ) - mean;
sumSquared += diff * diff;
}
double stdev = qPow( sumSquared / featureStats.values.count(), 0.5 );
changeAttributeMap.insert( stdevIndex, QVariant( stdev ) );
double variance = sumSquared / featureStats.values.count();
if ( mStatistics & QgsZonalStatistics::StDev )
{
double stdev = qPow( variance, 0.5 );
changeAttributeMap.insert( stdevIndex, QVariant( stdev ) );
}
if ( mStatistics & QgsZonalStatistics::Variance )
changeAttributeMap.insert( varianceIndex, QVariant( variance ) );
}
if ( mStatistics & QgsZonalStatistics::Min )
changeAttributeMap.insert( minIndex, QVariant( featureStats.min ) );

View File

@ -55,7 +55,8 @@ class ANALYSIS_EXPORT QgsZonalStatistics
Minority = 256, //!< Minority of pixel values
Majority = 512, //!< Majority of pixel values
Variety = 1024, //!< Variety (count of distinct) pixel values
All = Count | Sum | Mean | Median | StDev | Max | Min | Range | Minority | Majority | Variety
Variance = 2048, //!< Variance of pixel values
All = Count | Sum | Mean | Median | StDev | Max | Min | Range | Minority | Majority | Variety | Variance
};
Q_DECLARE_FLAGS( Statistics, Statistic )

View File

@ -94,6 +94,7 @@ void TestQgsZonalStatistics::testStatistics()
QCOMPARE( f.attribute( "minority" ).toDouble(), 0.0 );
QCOMPARE( f.attribute( "majority" ).toDouble(), 1.0 );
QCOMPARE( f.attribute( "variety" ).toDouble(), 2.0 );
QCOMPARE( f.attribute( "variance" ).toDouble(), 0.222222222222222 );
request.setFilterFid( 1 );
fetched = mVectorLayer->getFeatures( request ).nextFeature( f );
@ -109,6 +110,7 @@ void TestQgsZonalStatistics::testStatistics()
QCOMPARE( f.attribute( "minority" ).toDouble(), 0.0 );
QCOMPARE( f.attribute( "majority" ).toDouble(), 1.0 );
QCOMPARE( f.attribute( "variety" ).toDouble(), 2.0 );
QCOMPARE( f.attribute( "variance" ).toDouble(), 0.24691358024691 );
request.setFilterFid( 2 );
fetched = mVectorLayer->getFeatures( request ).nextFeature( f );
@ -124,6 +126,7 @@ void TestQgsZonalStatistics::testStatistics()
QCOMPARE( f.attribute( "minority" ).toDouble(), 0.0 );
QCOMPARE( f.attribute( "majority" ).toDouble(), 1.0 );
QCOMPARE( f.attribute( "variety" ).toDouble(), 2.0 );
QCOMPARE( f.attribute( "variance" ).toDouble(), 0.13888888888889 );
// same with long prefix to ensure that field name truncation handled correctly
QgsZonalStatistics zsl( mVectorLayer, mRasterLayer, QStringLiteral( "myqgis2_" ), 1, QgsZonalStatistics::All );
@ -143,6 +146,7 @@ void TestQgsZonalStatistics::testStatistics()
QCOMPARE( f.attribute( "myqgis2__2" ).toDouble(), 0.0 );
QCOMPARE( f.attribute( "myqgis2__3" ).toDouble(), 1.0 );
QCOMPARE( f.attribute( "myqgis2_va" ).toDouble(), 2.0 );
QCOMPARE( f.attribute( "myqgis2__4" ).toDouble(), 0.222222222222222 );
request.setFilterFid( 1 );
fetched = mVectorLayer->getFeatures( request ).nextFeature( f );
@ -158,6 +162,7 @@ void TestQgsZonalStatistics::testStatistics()
QCOMPARE( f.attribute( "myqgis2__2" ).toDouble(), 0.0 );
QCOMPARE( f.attribute( "myqgis2__3" ).toDouble(), 1.0 );
QCOMPARE( f.attribute( "myqgis2_va" ).toDouble(), 2.0 );
QCOMPARE( f.attribute( "myqgis2__4" ).toDouble(), 0.24691358024691 );
request.setFilterFid( 2 );
fetched = mVectorLayer->getFeatures( request ).nextFeature( f );
@ -173,6 +178,7 @@ void TestQgsZonalStatistics::testStatistics()
QCOMPARE( f.attribute( "myqgis2__2" ).toDouble(), 0.0 );
QCOMPARE( f.attribute( "myqgis2__3" ).toDouble(), 1.0 );
QCOMPARE( f.attribute( "myqgis2_va" ).toDouble(), 2.0 );
QCOMPARE( f.attribute( "myqgis2__4" ).toDouble(), 0.13888888888889 );
}
QGSTEST_MAIN( TestQgsZonalStatistics )