25 QString QgsCellStatisticsAlgorithm::displayName()
const
27 return QObject::tr(
"Cell statistics" );
30 QString QgsCellStatisticsAlgorithm::name()
const
32 return QObject::tr(
"cellstatistics" );
35 QStringList QgsCellStatisticsAlgorithm::tags()
const
37 return QObject::tr(
"cell,pixel,statistic,count,mean,sum,majority,minority,variance,variety,range,median,minimum,maximum" ).split(
',' );
40 QString QgsCellStatisticsAlgorithm::group()
const
42 return QObject::tr(
"Raster analysis" );
45 QString QgsCellStatisticsAlgorithm::groupId()
const
47 return QStringLiteral(
"rasteranalysis" );
50 QString QgsCellStatisticsAlgorithm::shortHelpString()
const
52 return QObject::tr(
"The Cell statistics algorithm computes a value for each cell of the "
53 "output raster. At each cell location, "
54 "the output value is defined as a function of all overlaid cell values of the "
56 "The output raster's extent and resolution is defined by a reference "
57 "raster. The following functions can be applied on the input "
58 "raster cells per output raster cell location:\n"
64 " <li>Standard deviation</li>"
68 " <li>Minority (least frequent value)</li>"
69 " <li>Majority (most frequent value)</li>"
70 " <li>Range (max-min)</li>"
71 " <li>Variety (count of unique values)</li>"
73 "Input raster layers that do not match the cell size of the reference raster layer will be "
74 "resampled using nearest neighbor resampling. The output raster data type will be set to "
75 "the most complex data type present in the input datasets except when using the functions "
76 "Mean, Standard deviation and Variance (data type is always Float32/Float64 depending on input float type) or Count and Variety (data type is always Int32).\n"
77 "<i>Calculation details - general:</i> NoData values in any of the input layers will result in a NoData cell output if the Ignore NoData parameter is not set.\n"
78 "<i>Calculation details - Count:</i> Count will always result in the number of cells without NoData values at the current cell location.\n"
79 "<i>Calculation details - Median:</i> If the number of input layers is even, the median will be calculated as the "
80 "arithmetic mean of the two middle values of the ordered cell input values.\n"
81 "<i>Calculation details - Minority/Majority:</i> If no unique minority or majority could be found, the result is NoData, except all "
82 "input cell values are equal." );
85 QgsCellStatisticsAlgorithm *QgsCellStatisticsAlgorithm::createInstance()
const
87 return new QgsCellStatisticsAlgorithm();
90 void QgsCellStatisticsAlgorithm::initAlgorithm(
const QVariantMap & )
95 QStringList statistics = QStringList();
96 statistics << QObject::tr(
"Sum" )
97 << QObject::tr(
"Count" )
98 << QObject::tr(
"Mean" )
99 << QObject::tr(
"Median" )
100 << QObject::tr(
"Standard deviation" )
101 << QObject::tr(
"Variance" )
102 << QObject::tr(
"Minimum" )
103 << QObject::tr(
"Maximum" )
104 << QObject::tr(
"Minority" )
105 << QObject::tr(
"Majority" )
106 << QObject::tr(
"Range" )
107 << QObject::tr(
"Variety" );
109 addParameter(
new QgsProcessingParameterEnum( QStringLiteral(
"STATISTIC" ), QObject::tr(
"Statistic" ), statistics,
false, 0,
false ) );
114 std::unique_ptr< QgsProcessingParameterNumber > output_nodata_parameter = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral(
"OUTPUT_NODATA_VALUE" ), QObject::tr(
"Output NoData value" ),
QgsProcessingParameterNumber::Double, -9999,
true );
116 addParameter( output_nodata_parameter.release() );
119 QObject::tr(
"Output layer" ) ) );
130 QgsRasterLayer *referenceLayer = parameterAsRasterLayer( parameters, QStringLiteral(
"REFERENCE_LAYER" ), context );
131 if ( !referenceLayer )
134 mIgnoreNoData = parameterAsBool( parameters, QStringLiteral(
"IGNORE_NODATA" ), context );
135 mNoDataValue = parameterAsDouble( parameters, QStringLiteral(
"OUTPUT_NODATA_VALUE" ), context );
136 mCrs = referenceLayer->
crs();
139 mLayerWidth = referenceLayer->
width();
140 mLayerHeight = referenceLayer->
height();
141 mExtent = referenceLayer->
extent();
143 const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral(
"INPUT" ), context );
144 QList< QgsRasterLayer * > rasterLayers;
145 rasterLayers.reserve( layers.count() );
154 QgsRasterAnalysisUtils::RasterLogicInput input;
158 input.interface = input.sourceDataProvider.get();
160 if ( layer->
crs() != mCrs )
162 input.projector = qgis::make_unique< QgsRasterProjector >();
163 input.projector->setInput( input.sourceDataProvider.get() );
165 input.interface = input.projector.get();
167 mInputs.emplace_back( std::move( input ) );
177 QgsRasterAnalysisUtils::CellValueStatisticMethods method =
static_cast<QgsRasterAnalysisUtils::CellValueStatisticMethods
>( parameterAsEnum( parameters, QStringLiteral(
"STATISTIC" ), context ) );
182 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : mInputs )
184 for (
int band : i.bands )
187 if (
static_cast<int>( mDataType ) <
static_cast<int>( inputDataType ) )
188 mDataType = inputDataType;
193 if ( method == QgsRasterAnalysisUtils::Mean || method == QgsRasterAnalysisUtils::StandardDeviation || method == QgsRasterAnalysisUtils::Variance )
195 if (
static_cast<int>( mDataType ) < 6 )
198 else if ( method == QgsRasterAnalysisUtils::Count || method == QgsRasterAnalysisUtils::Variety )
200 if (
static_cast<int>( mDataType ) > 5 )
204 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
205 QFileInfo fi( outputFile );
208 std::unique_ptr< QgsRasterFileWriter > writer = qgis::make_unique< QgsRasterFileWriter >( outputFile );
209 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
210 writer->setOutputFormat( outputFormat );
211 std::unique_ptr<QgsRasterDataProvider > provider( writer->createOneBandRaster( mDataType, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
214 if ( !provider->isValid() )
217 provider->setNoDataValue( 1, mNoDataValue );
222 int nbBlocksWidth =
static_cast< int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
223 int nbBlocksHeight =
static_cast< int >( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
224 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
225 provider->setEditable(
true );
227 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
234 std::unique_ptr< QgsRasterBlock > outputBlock;
235 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
237 std::vector< std::unique_ptr< QgsRasterBlock > > inputBlocks;
238 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : mInputs )
242 for (
int band : i.bands )
246 std::unique_ptr< QgsRasterBlock > b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
247 inputBlocks.emplace_back( std::move( b ) );
251 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
252 for (
int row = 0; row < iterRows; row++ )
257 for (
int col = 0; col < iterCols; col++ )
260 bool noDataInStack =
false;
261 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
262 int cellValueStackSize = cellValues.size();
264 if ( noDataInStack && !mIgnoreNoData )
268 if ( method == QgsRasterAnalysisUtils::Count )
269 outputBlock->setValue( row, col, cellValueStackSize );
272 outputBlock->setValue( row, col, mNoDataValue );
275 else if ( !noDataInStack || mIgnoreNoData )
279 case QgsRasterAnalysisUtils::Sum:
280 result = std::accumulate( cellValues.begin(), cellValues.end(), 0.0 );
282 case QgsRasterAnalysisUtils::Count:
283 result = cellValueStackSize;
285 case QgsRasterAnalysisUtils::Mean:
286 result = QgsRasterAnalysisUtils::meanFromCellValues( cellValues, cellValueStackSize );
288 case QgsRasterAnalysisUtils::Median:
289 result = QgsRasterAnalysisUtils::medianFromCellValues( cellValues, cellValueStackSize );
291 case QgsRasterAnalysisUtils::StandardDeviation:
292 result = QgsRasterAnalysisUtils::stddevFromCellValues( cellValues, cellValueStackSize );
294 case QgsRasterAnalysisUtils::Variance:
295 result = QgsRasterAnalysisUtils::varianceFromCellValues( cellValues, cellValueStackSize );
297 case QgsRasterAnalysisUtils::Minimum:
298 result = QgsRasterAnalysisUtils::minimumFromCellValues( cellValues );
300 case QgsRasterAnalysisUtils::Maximum:
301 result = QgsRasterAnalysisUtils::maximumFromCellValues( cellValues );
303 case QgsRasterAnalysisUtils::Minority:
304 result = QgsRasterAnalysisUtils::minorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
306 case QgsRasterAnalysisUtils::Majority:
307 result = QgsRasterAnalysisUtils::majorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
309 case QgsRasterAnalysisUtils::Range:
310 result = QgsRasterAnalysisUtils::rangeFromCellValues( cellValues );
312 case QgsRasterAnalysisUtils::Variety:
313 result = QgsRasterAnalysisUtils::varietyFromCellValues( cellValues );
316 outputBlock->setValue( row, col, result );
320 provider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop );
322 provider->setEditable(
false );
325 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
326 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
327 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
328 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
329 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
330 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );