Skip to content

Commit 58f6f93

Browse files
committedJun 29, 2017
[zonal statistics] add variance statistic
1 parent 8379f9b commit 58f6f93

File tree

4 files changed

+29
-5
lines changed

4 files changed

+29
-5
lines changed
 

‎python/analysis/vector/qgszonalstatistics.sip‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class QgsZonalStatistics
3636
Minority,
3737
Majority,
3838
Variety,
39+
Variance,
3940
All
4041
};
4142
typedef QFlags<QgsZonalStatistics::Statistic> Statistics;

‎src/analysis/vector/qgszonalstatistics.cpp‎

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,13 @@ int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
158158
QgsField varietyField( varietyFieldName, QVariant::Int, QStringLiteral( "int" ) );
159159
newFieldList.push_back( varietyField );
160160
}
161+
QString varianceFieldName;
162+
if ( mStatistics & QgsZonalStatistics::Variance )
163+
{
164+
varianceFieldName = getUniqueFieldName( mAttributePrefix + "variance", newFieldList );
165+
QgsField varianceField( varianceFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
166+
newFieldList.push_back( varianceField );
167+
}
161168
vectorProvider->addAttributes( newFieldList );
162169

163170
//index of the new fields
@@ -172,6 +179,7 @@ int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
172179
int minorityIndex = mStatistics & QgsZonalStatistics::Minority ? vectorProvider->fieldNameIndex( minorityFieldName ) : -1;
173180
int majorityIndex = mStatistics & QgsZonalStatistics::Majority ? vectorProvider->fieldNameIndex( majorityFieldName ) : -1;
174181
int varietyIndex = mStatistics & QgsZonalStatistics::Variety ? vectorProvider->fieldNameIndex( varietyFieldName ) : -1;
182+
int varianceIndex = mStatistics & QgsZonalStatistics::Variance ? vectorProvider->fieldNameIndex( varianceFieldName ) : -1;
175183

176184
if ( ( mStatistics & QgsZonalStatistics::Count && countIndex == -1 )
177185
|| ( mStatistics & QgsZonalStatistics::Sum && sumIndex == -1 )
@@ -184,6 +192,7 @@ int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
184192
|| ( mStatistics & QgsZonalStatistics::Minority && minorityIndex == -1 )
185193
|| ( mStatistics & QgsZonalStatistics::Majority && majorityIndex == -1 )
186194
|| ( mStatistics & QgsZonalStatistics::Variety && varietyIndex == -1 )
195+
|| ( mStatistics & QgsZonalStatistics::Variance && varianceIndex == -1 )
187196
)
188197
{
189198
//failed to create a required field
@@ -200,7 +209,8 @@ int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
200209
QgsFeature f;
201210

202211
bool statsStoreValues = ( mStatistics & QgsZonalStatistics::Median ) ||
203-
( mStatistics & QgsZonalStatistics::StDev );
212+
( mStatistics & QgsZonalStatistics::StDev ) ||
213+
( mStatistics & QgsZonalStatistics::Variance );
204214
bool statsStoreValueCount = ( mStatistics & QgsZonalStatistics::Minority ) ||
205215
( mStatistics & QgsZonalStatistics::Majority );
206216

@@ -288,16 +298,22 @@ int QgsZonalStatistics::calculateStatistics( QgsFeedback *feedback )
288298
}
289299
changeAttributeMap.insert( medianIndex, QVariant( medianValue ) );
290300
}
291-
if ( mStatistics & QgsZonalStatistics::StDev )
301+
if ( mStatistics & QgsZonalStatistics::StDev || mStatistics & QgsZonalStatistics::Variance )
292302
{
293303
double sumSquared = 0;
294304
for ( int i = 0; i < featureStats.values.count(); ++i )
295305
{
296306
double diff = featureStats.values.at( i ) - mean;
297307
sumSquared += diff * diff;
298308
}
299-
double stdev = qPow( sumSquared / featureStats.values.count(), 0.5 );
300-
changeAttributeMap.insert( stdevIndex, QVariant( stdev ) );
309+
double variance = sumSquared / featureStats.values.count();
310+
if ( mStatistics & QgsZonalStatistics::StDev )
311+
{
312+
double stdev = qPow( variance, 0.5 );
313+
changeAttributeMap.insert( stdevIndex, QVariant( stdev ) );
314+
}
315+
if ( mStatistics & QgsZonalStatistics::Variance )
316+
changeAttributeMap.insert( varianceIndex, QVariant( variance ) );
301317
}
302318
if ( mStatistics & QgsZonalStatistics::Min )
303319
changeAttributeMap.insert( minIndex, QVariant( featureStats.min ) );

‎src/analysis/vector/qgszonalstatistics.h‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ class ANALYSIS_EXPORT QgsZonalStatistics
5555
Minority = 256, //!< Minority of pixel values
5656
Majority = 512, //!< Majority of pixel values
5757
Variety = 1024, //!< Variety (count of distinct) pixel values
58-
All = Count | Sum | Mean | Median | StDev | Max | Min | Range | Minority | Majority | Variety
58+
Variance = 2048, //!< Variance of pixel values
59+
All = Count | Sum | Mean | Median | StDev | Max | Min | Range | Minority | Majority | Variety | Variance
5960
};
6061
Q_DECLARE_FLAGS( Statistics, Statistic )
6162

‎tests/src/analysis/testqgszonalstatistics.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ void TestQgsZonalStatistics::testStatistics()
9494
QCOMPARE( f.attribute( "minority" ).toDouble(), 0.0 );
9595
QCOMPARE( f.attribute( "majority" ).toDouble(), 1.0 );
9696
QCOMPARE( f.attribute( "variety" ).toDouble(), 2.0 );
97+
QCOMPARE( f.attribute( "variance" ).toDouble(), 0.222222222222222 );
9798

9899
request.setFilterFid( 1 );
99100
fetched = mVectorLayer->getFeatures( request ).nextFeature( f );
@@ -109,6 +110,7 @@ void TestQgsZonalStatistics::testStatistics()
109110
QCOMPARE( f.attribute( "minority" ).toDouble(), 0.0 );
110111
QCOMPARE( f.attribute( "majority" ).toDouble(), 1.0 );
111112
QCOMPARE( f.attribute( "variety" ).toDouble(), 2.0 );
113+
QCOMPARE( f.attribute( "variance" ).toDouble(), 0.24691358024691 );
112114

113115
request.setFilterFid( 2 );
114116
fetched = mVectorLayer->getFeatures( request ).nextFeature( f );
@@ -124,6 +126,7 @@ void TestQgsZonalStatistics::testStatistics()
124126
QCOMPARE( f.attribute( "minority" ).toDouble(), 0.0 );
125127
QCOMPARE( f.attribute( "majority" ).toDouble(), 1.0 );
126128
QCOMPARE( f.attribute( "variety" ).toDouble(), 2.0 );
129+
QCOMPARE( f.attribute( "variance" ).toDouble(), 0.13888888888889 );
127130

128131
// same with long prefix to ensure that field name truncation handled correctly
129132
QgsZonalStatistics zsl( mVectorLayer, mRasterLayer, QStringLiteral( "myqgis2_" ), 1, QgsZonalStatistics::All );
@@ -143,6 +146,7 @@ void TestQgsZonalStatistics::testStatistics()
143146
QCOMPARE( f.attribute( "myqgis2__2" ).toDouble(), 0.0 );
144147
QCOMPARE( f.attribute( "myqgis2__3" ).toDouble(), 1.0 );
145148
QCOMPARE( f.attribute( "myqgis2_va" ).toDouble(), 2.0 );
149+
QCOMPARE( f.attribute( "myqgis2__4" ).toDouble(), 0.222222222222222 );
146150

147151
request.setFilterFid( 1 );
148152
fetched = mVectorLayer->getFeatures( request ).nextFeature( f );
@@ -158,6 +162,7 @@ void TestQgsZonalStatistics::testStatistics()
158162
QCOMPARE( f.attribute( "myqgis2__2" ).toDouble(), 0.0 );
159163
QCOMPARE( f.attribute( "myqgis2__3" ).toDouble(), 1.0 );
160164
QCOMPARE( f.attribute( "myqgis2_va" ).toDouble(), 2.0 );
165+
QCOMPARE( f.attribute( "myqgis2__4" ).toDouble(), 0.24691358024691 );
161166

162167
request.setFilterFid( 2 );
163168
fetched = mVectorLayer->getFeatures( request ).nextFeature( f );
@@ -173,6 +178,7 @@ void TestQgsZonalStatistics::testStatistics()
173178
QCOMPARE( f.attribute( "myqgis2__2" ).toDouble(), 0.0 );
174179
QCOMPARE( f.attribute( "myqgis2__3" ).toDouble(), 1.0 );
175180
QCOMPARE( f.attribute( "myqgis2_va" ).toDouble(), 2.0 );
181+
QCOMPARE( f.attribute( "myqgis2__4" ).toDouble(), 0.13888888888889 );
176182
}
177183

178184
QGSTEST_MAIN( TestQgsZonalStatistics )

0 commit comments

Comments
 (0)
Please sign in to comment.