26 QString QgsCellStatisticsAlgorithmBase::group()
const
28 return QObject::tr(
"Raster analysis" );
31 QString QgsCellStatisticsAlgorithmBase::groupId()
const
33 return QStringLiteral(
"rasteranalysis" );
36 void QgsCellStatisticsAlgorithmBase::initAlgorithm(
const QVariantMap & )
41 addSpecificAlgorithmParams();
47 std::unique_ptr< QgsProcessingParameterNumber > output_nodata_parameter = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral(
"OUTPUT_NODATA_VALUE" ), QObject::tr(
"Output NoData value" ),
QgsProcessingParameterNumber::Double, -9999,
false );
49 addParameter( output_nodata_parameter.release() );
52 QObject::tr(
"Output layer" ) ) );
63 QgsRasterLayer *referenceLayer = parameterAsRasterLayer( parameters, QStringLiteral(
"REFERENCE_LAYER" ), context );
64 if ( !referenceLayer )
67 mIgnoreNoData = parameterAsBool( parameters, QStringLiteral(
"IGNORE_NODATA" ), context );
68 mNoDataValue = parameterAsDouble( parameters, QStringLiteral(
"OUTPUT_NODATA_VALUE" ), context );
69 mCrs = referenceLayer->
crs();
72 mLayerWidth = referenceLayer->
width();
73 mLayerHeight = referenceLayer->
height();
74 mExtent = referenceLayer->
extent();
76 const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral(
"INPUT" ), context );
77 QList< QgsRasterLayer * > rasterLayers;
78 rasterLayers.reserve( layers.count() );
87 QgsRasterAnalysisUtils::RasterLogicInput input;
91 input.interface = input.sourceDataProvider.get();
93 if ( layer->
crs() != mCrs )
95 input.projector = std::make_unique< QgsRasterProjector >();
96 input.projector->setInput( input.sourceDataProvider.get() );
98 input.interface = input.projector.get();
100 mInputs.emplace_back( std::move( input ) );
107 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
109 for (
int band : i.bands )
112 if (
static_cast<int>( mDataType ) <
static_cast<int>( inputDataType ) )
113 mDataType = inputDataType;
117 prepareSpecificAlgorithmParameters( parameters, context, feedback );
125 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
126 QFileInfo fi( outputFile );
129 std::unique_ptr< QgsRasterFileWriter > writer = std::make_unique< QgsRasterFileWriter >( outputFile );
130 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
131 writer->setOutputFormat( outputFormat );
132 mOutputRasterDataProvider = writer->createOneBandRaster( mDataType, mLayerWidth, mLayerHeight, mExtent, mCrs );
133 if ( !mOutputRasterDataProvider )
135 if ( !mOutputRasterDataProvider->isValid() )
138 mOutputRasterDataProvider->setNoDataValue( 1, mNoDataValue );
142 processRasterStack( feedback );
145 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
146 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
147 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
148 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
149 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
150 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
159 QString QgsCellStatisticsAlgorithm::displayName()
const
161 return QObject::tr(
"Cell statistics" );
164 QString QgsCellStatisticsAlgorithm::name()
const
166 return QStringLiteral(
"cellstatistics" );
169 QStringList QgsCellStatisticsAlgorithm::tags()
const
171 return QObject::tr(
"cell,pixel,statistic,count,mean,sum,majority,minority,variance,variety,range,median,minimum,maximum" ).split(
',' );
174 QString QgsCellStatisticsAlgorithm::shortHelpString()
const
176 return QObject::tr(
"The Cell statistics algorithm computes a value for each cell of the "
177 "output raster. At each cell location, "
178 "the output value is defined as a function of all overlaid cell values of the "
180 "The output raster's extent and resolution is defined by a reference "
181 "raster. The following functions can be applied on the input "
182 "raster cells per output raster cell location:\n"
188 " <li>Standard deviation</li>"
192 " <li>Minority (least frequent value)</li>"
193 " <li>Majority (most frequent value)</li>"
194 " <li>Range (max-min)</li>"
195 " <li>Variety (count of unique values)</li>"
197 "Input raster layers that do not match the cell size of the reference raster layer will be "
198 "resampled using nearest neighbor resampling. The output raster data type will be set to "
199 "the most complex data type present in the input datasets except when using the functions "
200 "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"
201 "<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"
202 "<i>Calculation details - Count:</i> Count will always result in the number of cells without NoData values at the current cell location.\n"
203 "<i>Calculation details - Median:</i> If the number of input layers is even, the median will be calculated as the "
204 "arithmetic mean of the two middle values of the ordered cell input values. In this case the output data type is Float32.\n"
205 "<i>Calculation details - Minority/Majority:</i> If no unique minority or majority could be found, the result is NoData, except all "
206 "input cell values are equal." );
209 QgsCellStatisticsAlgorithm *QgsCellStatisticsAlgorithm::createInstance()
const
211 return new QgsCellStatisticsAlgorithm();
214 void QgsCellStatisticsAlgorithm::addSpecificAlgorithmParams()
216 QStringList statistics = QStringList();
217 statistics << QObject::tr(
"Sum" )
218 << QObject::tr(
"Count" )
219 << QObject::tr(
"Mean" )
220 << QObject::tr(
"Median" )
221 << QObject::tr(
"Standard deviation" )
222 << QObject::tr(
"Variance" )
223 << QObject::tr(
"Minimum" )
224 << QObject::tr(
"Maximum" )
225 << QObject::tr(
"Minority" )
226 << QObject::tr(
"Majority" )
227 << QObject::tr(
"Range" )
228 << QObject::tr(
"Variety" );
230 addParameter(
new QgsProcessingParameterEnum( QStringLiteral(
"STATISTIC" ), QObject::tr(
"Statistic" ), statistics,
false, 0,
false ) );
237 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValueStatisticMethods
>( parameterAsEnum( parameters, QStringLiteral(
"STATISTIC" ), context ) );
241 mMethod == QgsRasterAnalysisUtils::Mean ||
242 mMethod == QgsRasterAnalysisUtils::StandardDeviation ||
243 mMethod == QgsRasterAnalysisUtils::Variance ||
244 ( mMethod == QgsRasterAnalysisUtils::Median && ( mInputs.size() % 2 == 0 ) )
247 if (
static_cast<int>( mDataType ) < 6 )
250 else if ( mMethod == QgsRasterAnalysisUtils::Count || mMethod == QgsRasterAnalysisUtils::Variety )
252 if (
static_cast<int>( mDataType ) > 5 )
262 int nbBlocksWidth =
static_cast< int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
263 int nbBlocksHeight =
static_cast< int >( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
264 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
265 mOutputRasterDataProvider->setEditable(
true );
267 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
274 std::unique_ptr< QgsRasterBlock > outputBlock;
275 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
277 std::vector< std::unique_ptr< QgsRasterBlock > > inputBlocks;
278 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
282 for (
int band : i.bands )
286 std::unique_ptr< QgsRasterBlock > b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
287 inputBlocks.emplace_back( std::move( b ) );
291 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
292 for (
int row = 0; row < iterRows; row++ )
297 for (
int col = 0; col < iterCols; col++ )
300 bool noDataInStack =
false;
301 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
302 int cellValueStackSize = cellValues.size();
304 if ( noDataInStack && !mIgnoreNoData )
308 if ( mMethod == QgsRasterAnalysisUtils::Count )
309 outputBlock->setValue( row, col, cellValueStackSize );
312 outputBlock->setValue( row, col, mNoDataValue );
315 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
319 case QgsRasterAnalysisUtils::Sum:
320 result = std::accumulate( cellValues.begin(), cellValues.end(), 0.0 );
322 case QgsRasterAnalysisUtils::Count:
323 result = cellValueStackSize;
325 case QgsRasterAnalysisUtils::Mean:
326 result = QgsRasterAnalysisUtils::meanFromCellValues( cellValues, cellValueStackSize );
328 case QgsRasterAnalysisUtils::Median:
329 result = QgsRasterAnalysisUtils::medianFromCellValues( cellValues, cellValueStackSize );
331 case QgsRasterAnalysisUtils::StandardDeviation:
332 result = QgsRasterAnalysisUtils::stddevFromCellValues( cellValues, cellValueStackSize );
334 case QgsRasterAnalysisUtils::Variance:
335 result = QgsRasterAnalysisUtils::varianceFromCellValues( cellValues, cellValueStackSize );
337 case QgsRasterAnalysisUtils::Minimum:
338 result = QgsRasterAnalysisUtils::minimumFromCellValues( cellValues );
340 case QgsRasterAnalysisUtils::Maximum:
341 result = QgsRasterAnalysisUtils::maximumFromCellValues( cellValues );
343 case QgsRasterAnalysisUtils::Minority:
344 result = QgsRasterAnalysisUtils::minorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
346 case QgsRasterAnalysisUtils::Majority:
347 result = QgsRasterAnalysisUtils::majorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
349 case QgsRasterAnalysisUtils::Range:
350 result = QgsRasterAnalysisUtils::rangeFromCellValues( cellValues );
352 case QgsRasterAnalysisUtils::Variety:
353 result = QgsRasterAnalysisUtils::varietyFromCellValues( cellValues );
356 outputBlock->setValue( row, col, result );
361 outputBlock->setValue( row, col, mNoDataValue );
365 mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop );
367 mOutputRasterDataProvider->setEditable(
false );
373 QString QgsCellStatisticsPercentileAlgorithm::displayName()
const
375 return QObject::tr(
"Cell stack percentile" );
378 QString QgsCellStatisticsPercentileAlgorithm::name()
const
380 return QStringLiteral(
"cellstackpercentile" );
383 QStringList QgsCellStatisticsPercentileAlgorithm::tags()
const
385 return QObject::tr(
"cell,pixel,statistic,percentile,quantile,quartile" ).split(
',' );
388 QString QgsCellStatisticsPercentileAlgorithm::shortHelpString()
const
390 return QObject::tr(
"The Cell stack percentile algorithm returns the cell-wise percentile value of a stack of rasters "
391 "and writes the results to an output raster. The percentile to return is determined by the percentile input value (ranges between 0 and 1). "
392 "At each cell location, the specified percentile is obtained using the respective value from "
393 "the stack of all overlaid and sorted cell values of the input rasters.\n\n"
394 "There are three methods for percentile calculation:"
396 " <li>Nearest rank</li>"
397 " <li>Inclusive linear interpolation (PERCENTILE.INC)</li>"
398 " <li>Exclusive linear interpolation (PERCENTILE.EXC)</li>"
400 "While the output value can stay the same for the nearest rank method (obtains the value that is nearest to the "
401 "specified percentile), the linear interpolation method return unique values for different percentiles. Both interpolation "
402 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
403 "The output raster's extent and resolution is defined by a reference "
404 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
405 "resampled using nearest neighbor resampling. NoData values in any of the input layers will result in a NoData cell output if the Ignore NoData parameter is not set. "
406 "The output raster data type will be set to the most complex data type present in the input datasets. " );
409 QgsCellStatisticsPercentileAlgorithm *QgsCellStatisticsPercentileAlgorithm::createInstance()
const
411 return new QgsCellStatisticsPercentileAlgorithm();
414 void QgsCellStatisticsPercentileAlgorithm::addSpecificAlgorithmParams()
416 addParameter(
new QgsProcessingParameterEnum( QStringLiteral(
"METHOD" ), QObject::tr(
"Method" ), QStringList() << QObject::tr(
"Nearest rank" ) << QObject::tr(
"Inclusive linear interpolation (PERCENTILE.INC)" ) << QObject::tr(
"Exclusive linear interpolation (PERCENTILE.EXC)" ),
false, 0,
false ) );
423 mMethod =
static_cast< QgsRasterAnalysisUtils::CellValuePercentileMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
424 mPercentile = parameterAsDouble( parameters, QStringLiteral(
"PERCENTILE" ), context );
428 if ( mMethod != QgsRasterAnalysisUtils::CellValuePercentileMethods::NearestRankPercentile &&
static_cast< int >( mDataType ) < 6 )
439 int nbBlocksWidth =
static_cast< int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
440 int nbBlocksHeight =
static_cast< int >( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
441 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
442 mOutputRasterDataProvider->setEditable(
true );
444 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
451 std::unique_ptr< QgsRasterBlock > outputBlock;
452 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
454 std::vector< std::unique_ptr< QgsRasterBlock > > inputBlocks;
455 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
459 for (
int band : i.bands )
463 std::unique_ptr< QgsRasterBlock > b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
464 inputBlocks.emplace_back( std::move( b ) );
468 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
469 for (
int row = 0; row < iterRows; row++ )
474 for (
int col = 0; col < iterCols; col++ )
477 bool noDataInStack =
false;
478 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
479 int cellValueStackSize = cellValues.size();
481 if ( noDataInStack && !mIgnoreNoData )
483 outputBlock->setValue( row, col, mNoDataValue );
485 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
489 case QgsRasterAnalysisUtils::NearestRankPercentile:
490 result = QgsRasterAnalysisUtils::nearestRankPercentile( cellValues, cellValueStackSize, mPercentile );
492 case QgsRasterAnalysisUtils::InterpolatedPercentileInc:
493 result = QgsRasterAnalysisUtils::interpolatedPercentileInc( cellValues, cellValueStackSize, mPercentile );
495 case QgsRasterAnalysisUtils::InterpolatedPercentileExc:
496 result = QgsRasterAnalysisUtils::interpolatedPercentileExc( cellValues, cellValueStackSize, mPercentile, mNoDataValue );
499 outputBlock->setValue( row, col, result );
504 outputBlock->setValue( row, col, mNoDataValue );
508 mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop );
510 mOutputRasterDataProvider->setEditable(
false );
516 QString QgsCellStatisticsPercentRankFromValueAlgorithm::displayName()
const
518 return QObject::tr(
"Cell stack percent rank from value" );
521 QString QgsCellStatisticsPercentRankFromValueAlgorithm::name()
const
523 return QStringLiteral(
"cellstackpercentrankfromvalue" );
526 QStringList QgsCellStatisticsPercentRankFromValueAlgorithm::tags()
const
528 return QObject::tr(
"cell,pixel,statistic,percentrank,rank,percent,value" ).split(
',' );
531 QString QgsCellStatisticsPercentRankFromValueAlgorithm::shortHelpString()
const
533 return QObject::tr(
"The Cell stack percentrank from value algorithm calculates the cell-wise percentrank value of a stack of rasters based on a single input value "
534 "and writes them to an output raster.\n\n"
535 "At each cell location, the specified value is ranked among the respective values in the stack of all overlaid and sorted cell values from the input rasters. "
536 "For values outside of the stack value distribution, the algorithm returns NoData because the value cannot be ranked among the cell values.\n\n"
537 "There are two methods for percentile calculation:"
539 " <li>Inclusive linearly interpolated percent rank (PERCENTRANK.INC)</li>"
540 " <li>Exclusive linearly interpolated percent rank (PERCENTRANK.EXC)</li>"
542 "The linear interpolation method return the unique percent rank for different values. Both interpolation "
543 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
544 "The output raster's extent and resolution is defined by a reference "
545 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
546 "resampled using nearest neighbor resampling. NoData values in any of the input layers will result in a NoData cell output if the Ignore NoData parameter is not set. "
547 "The output raster data type will always be Float32." );
550 QgsCellStatisticsPercentRankFromValueAlgorithm *QgsCellStatisticsPercentRankFromValueAlgorithm::createInstance()
const
552 return new QgsCellStatisticsPercentRankFromValueAlgorithm();
555 void QgsCellStatisticsPercentRankFromValueAlgorithm::addSpecificAlgorithmParams()
557 addParameter(
new QgsProcessingParameterEnum( QStringLiteral(
"METHOD" ), QObject::tr(
"Method" ), QStringList() << QObject::tr(
"Inclusive linear interpolation (PERCENTRANK.INC)" ) << QObject::tr(
"Exclusive linear interpolation (PERCENTRANK.EXC)" ),
false, 0,
false ) );
564 mMethod =
static_cast< QgsRasterAnalysisUtils::CellValuePercentRankMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
565 mValue = parameterAsDouble( parameters, QStringLiteral(
"VALUE" ), context );
572 void QgsCellStatisticsPercentRankFromValueAlgorithm::processRasterStack(
QgsProcessingFeedback *feedback )
577 int nbBlocksWidth =
static_cast< int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
578 int nbBlocksHeight =
static_cast< int >( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
579 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
580 mOutputRasterDataProvider->setEditable(
true );
582 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
589 std::unique_ptr< QgsRasterBlock > outputBlock;
590 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
592 std::vector< std::unique_ptr< QgsRasterBlock > > inputBlocks;
593 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
597 for (
int band : i.bands )
601 std::unique_ptr< QgsRasterBlock > b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
602 inputBlocks.emplace_back( std::move( b ) );
606 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
607 for (
int row = 0; row < iterRows; row++ )
612 for (
int col = 0; col < iterCols; col++ )
615 bool noDataInStack =
false;
616 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
617 int cellValueStackSize = cellValues.size();
619 if ( noDataInStack && !mIgnoreNoData )
621 outputBlock->setValue( row, col, mNoDataValue );
623 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
627 case QgsRasterAnalysisUtils::InterpolatedPercentRankInc:
628 result = QgsRasterAnalysisUtils::interpolatedPercentRankInc( cellValues, cellValueStackSize, mValue, mNoDataValue );
630 case QgsRasterAnalysisUtils::InterpolatedPercentRankExc:
631 result = QgsRasterAnalysisUtils::interpolatedPercentRankExc( cellValues, cellValueStackSize, mValue, mNoDataValue );
634 outputBlock->setValue( row, col, result );
639 outputBlock->setValue( row, col, mNoDataValue );
643 mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop );
645 mOutputRasterDataProvider->setEditable(
false );
652 QString QgsCellStatisticsPercentRankFromRasterAlgorithm::displayName()
const
654 return QObject::tr(
"Cell stack percentrank from raster layer" );
657 QString QgsCellStatisticsPercentRankFromRasterAlgorithm::name()
const
659 return QStringLiteral(
"cellstackpercentrankfromrasterlayer" );
662 QStringList QgsCellStatisticsPercentRankFromRasterAlgorithm::tags()
const
664 return QObject::tr(
"cell,pixel,statistic,percentrank,rank,percent,value,raster" ).split(
',' );
667 QString QgsCellStatisticsPercentRankFromRasterAlgorithm::shortHelpString()
const
669 return QObject::tr(
"The Cell stack percentrank from raster layer algorithm calculates the cell-wise percentrank value of a stack of rasters based on an input value raster "
670 "and writes them to an output raster.\n\n"
671 "At each cell location, the current value of the value raster is used ranked among the respective values in the stack of all overlaid and sorted cell values of the input rasters. "
672 "For values outside of the the stack value distribution, the algorithm returns NoData because the value cannot be ranked among the cell values.\n\n"
673 "There are two methods for percentile calculation:"
675 " <li>Inclusive linearly interpolated percent rank (PERCENTRANK.INC)</li>"
676 " <li>Exclusive linearly interpolated percent rank (PERCENTRANK.EXC)</li>"
678 "The linear interpolation method return the unique percent rank for different values. Both interpolation "
679 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
680 "The output raster's extent and resolution is defined by a reference "
681 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
682 "resampled using nearest neighbor resampling. NoData values in any of the input layers will result in a NoData cell output if the Ignore NoData parameter is not set. "
683 "The output raster data type will always be Float32." );
686 QgsCellStatisticsPercentRankFromRasterAlgorithm *QgsCellStatisticsPercentRankFromRasterAlgorithm::createInstance()
const
688 return new QgsCellStatisticsPercentRankFromRasterAlgorithm();
691 void QgsCellStatisticsPercentRankFromRasterAlgorithm::addSpecificAlgorithmParams()
694 addParameter(
new QgsProcessingParameterBand( QStringLiteral(
"VALUE_RASTER_BAND" ), QObject::tr(
"Value raster band" ), 1, QStringLiteral(
"VALUE_LAYER" ) ) );
695 addParameter(
new QgsProcessingParameterEnum( QStringLiteral(
"METHOD" ), QObject::tr(
"Method" ), QStringList() << QObject::tr(
"Inclusive linear interpolation (PERCENTRANK.INC)" ) << QObject::tr(
"Exclusive linear interpolation (PERCENTRANK.EXC)" ),
false, 0,
false ) );
701 mMethod =
static_cast< QgsRasterAnalysisUtils::CellValuePercentRankMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
703 QgsRasterLayer *inputValueRaster = parameterAsRasterLayer( parameters, QStringLiteral(
"INPUT_VALUE_RASTER" ), context );
704 if ( !inputValueRaster )
709 mValueRasterBand = parameterAsInt( parameters, QStringLiteral(
"VALUE_RASTER_BAND" ), context );
716 void QgsCellStatisticsPercentRankFromRasterAlgorithm::processRasterStack(
QgsProcessingFeedback *feedback )
720 int nbBlocksWidth =
static_cast< int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
721 int nbBlocksHeight =
static_cast< int >( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
722 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
723 mOutputRasterDataProvider->setEditable(
true );
725 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
732 std::unique_ptr< QgsRasterBlock > outputBlock;
733 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
735 std::unique_ptr< QgsRasterBlock > valueBlock( mValueRasterInterface->block( mValueRasterBand, blockExtent, iterCols, iterRows ) );
737 std::vector< std::unique_ptr< QgsRasterBlock > > inputBlocks;
738 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
742 for (
int band : i.bands )
746 std::unique_ptr< QgsRasterBlock > b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
747 inputBlocks.emplace_back( std::move( b ) );
751 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
752 for (
int row = 0; row < iterRows; row++ )
757 for (
int col = 0; col < iterCols; col++ )
759 bool percentRankValueIsNoData =
false;
760 double percentRankValue = valueBlock->valueAndNoData( row, col, percentRankValueIsNoData );
763 bool noDataInStack =
false;
764 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
765 int cellValueStackSize = cellValues.size();
767 if ( noDataInStack && !mIgnoreNoData && !percentRankValueIsNoData )
769 outputBlock->setValue( row, col, mNoDataValue );
771 else if ( !noDataInStack || ( !percentRankValueIsNoData && mIgnoreNoData && cellValueStackSize > 0 ) )
775 case QgsRasterAnalysisUtils::InterpolatedPercentRankInc:
776 result = QgsRasterAnalysisUtils::interpolatedPercentRankInc( cellValues, cellValueStackSize, percentRankValue, mNoDataValue );
778 case QgsRasterAnalysisUtils::InterpolatedPercentRankExc:
779 result = QgsRasterAnalysisUtils::interpolatedPercentRankExc( cellValues, cellValueStackSize, percentRankValue, mNoDataValue );
782 outputBlock->setValue( row, col, result );
787 outputBlock->setValue( row, col, mNoDataValue );
791 mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop );
793 mOutputRasterDataProvider->setEditable(
false );