26using namespace Qt::StringLiterals;
31QString QgsCellStatisticsAlgorithmBase::group()
const
33 return QObject::tr(
"Raster analysis" );
36QString QgsCellStatisticsAlgorithmBase::groupId()
const
38 return u
"rasteranalysis"_s;
41void QgsCellStatisticsAlgorithmBase::initAlgorithm(
const QVariantMap & )
45 addSpecificAlgorithmParams();
53 addParameter( output_nodata_parameter.release() );
57 auto createOptsParam = std::make_unique<QgsProcessingParameterString>( u
"CREATE_OPTIONS"_s, QObject::tr(
"Creation options" ), QVariant(),
false,
true );
58 createOptsParam->setMetadata( QVariantMap( { { u
"widget_wrapper"_s, QVariantMap( { { u
"widget_type"_s, u
"rasteroptions"_s } } ) } } ) );
60 addParameter( createOptsParam.release() );
62 auto creationOptsParam = std::make_unique<QgsProcessingParameterString>( u
"CREATION_OPTIONS"_s, QObject::tr(
"Creation options" ), QVariant(),
false,
true );
63 creationOptsParam->setMetadata( QVariantMap( { { u
"widget_wrapper"_s, QVariantMap( { { u
"widget_type"_s, u
"rasteroptions"_s } } ) } } ) );
65 addParameter( creationOptsParam.release() );
78 QgsRasterLayer *referenceLayer = parameterAsRasterLayer( parameters, u
"REFERENCE_LAYER"_s, context );
79 if ( !referenceLayer )
82 mIgnoreNoData = parameterAsBool( parameters, u
"IGNORE_NODATA"_s, context );
83 mNoDataValue = parameterAsDouble( parameters, u
"OUTPUT_NODATA_VALUE"_s, context );
84 mCrs = referenceLayer->
crs();
87 mLayerWidth = referenceLayer->
width();
88 mLayerHeight = referenceLayer->
height();
89 mExtent = referenceLayer->
extent();
91 const QList<QgsMapLayer *> layers = parameterAsLayerList( parameters, u
"INPUT"_s, context );
92 QList<QgsRasterLayer *> rasterLayers;
93 rasterLayers.reserve( layers.count() );
102 QgsRasterAnalysisUtils::RasterLogicInput input;
106 input.interface = input.sourceDataProvider.get();
108 if ( layer->
crs() != mCrs )
110 input.projector = std::make_unique<QgsRasterProjector>();
111 input.projector->setInput( input.sourceDataProvider.get() );
113 input.interface = input.projector.get();
115 mInputs.emplace_back( std::move( input ) );
122 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
124 for (
int band : i.bands )
127 if (
static_cast<int>( mDataType ) <
static_cast<int>( inputDataType ) )
128 mDataType = inputDataType;
132 prepareSpecificAlgorithmParameters( parameters, context, feedback );
140 QString creationOptions = parameterAsString( parameters, u
"CREATION_OPTIONS"_s, context ).trimmed();
142 const QString optionsString = parameterAsString( parameters, u
"CREATE_OPTIONS"_s, context );
143 if ( !optionsString.isEmpty() )
144 creationOptions = optionsString;
146 const QString outputFile = parameterAsOutputLayer( parameters, u
"OUTPUT"_s, context );
147 const QString outputFormat = parameterAsOutputRasterFormat( parameters, u
"OUTPUT"_s, context );
149 auto writer = std::make_unique<QgsRasterFileWriter>( outputFile );
150 writer->setOutputProviderKey( u
"gdal"_s );
151 if ( !creationOptions.isEmpty() )
153 writer->setCreationOptions( creationOptions.split(
'|' ) );
155 writer->setOutputFormat( outputFormat );
156 mOutputRasterDataProvider.reset( writer->createOneBandRaster( mDataType, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
157 if ( !mOutputRasterDataProvider )
159 if ( !mOutputRasterDataProvider->isValid() )
162 mOutputRasterDataProvider->setNoDataValue( 1, mNoDataValue );
165 const bool hasReportsDuringClose = mOutputRasterDataProvider->hasReportsDuringClose();
166 mMaxProgressDuringBlockWriting = hasReportsDuringClose ? 50.0 : 100.0;
169 processRasterStack( feedback );
171 if ( feedback && hasReportsDuringClose )
174 if ( !mOutputRasterDataProvider->closeWithProgress( scaledFeedback.get() ) )
182 mOutputRasterDataProvider.reset();
185 outputs.insert( u
"EXTENT"_s, mExtent.toString() );
186 outputs.insert( u
"CRS_AUTHID"_s, mCrs.authid() );
187 outputs.insert( u
"WIDTH_IN_PIXELS"_s, mLayerWidth );
188 outputs.insert( u
"HEIGHT_IN_PIXELS"_s, mLayerHeight );
189 outputs.insert( u
"TOTAL_PIXEL_COUNT"_s, layerSize );
190 outputs.insert( u
"OUTPUT"_s, outputFile );
199QString QgsCellStatisticsAlgorithm::displayName()
const
201 return QObject::tr(
"Cell statistics" );
204QString QgsCellStatisticsAlgorithm::name()
const
206 return u
"cellstatistics"_s;
209QStringList QgsCellStatisticsAlgorithm::tags()
const
211 return QObject::tr(
"cell,pixel,statistic,count,mean,sum,majority,minority,variance,variety,range,median,minimum,maximum" ).split(
',' );
214QString QgsCellStatisticsAlgorithm::shortHelpString()
const
217 "The Cell statistics algorithm computes a value for each cell of the "
218 "output raster. At each cell location, "
219 "the output value is defined as a function of all overlaid cell values of the "
221 "The output raster's extent and resolution is defined by a reference "
222 "raster. The following functions can be applied on the input "
223 "raster cells per output raster cell location:\n"
229 " <li>Standard deviation</li>"
233 " <li>Minority (least frequent value)</li>"
234 " <li>Majority (most frequent value)</li>"
235 " <li>Range (max-min)</li>"
236 " <li>Variety (count of unique values)</li>"
238 "Input raster layers that do not match the cell size of the reference raster layer will be "
239 "resampled using nearest neighbor resampling. The output raster data type will be set to "
240 "the most complex data type present in the input datasets except when using the functions "
241 "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"
242 "<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"
243 "<i>Calculation details - Count:</i> Count will always result in the number of cells without NoData values at the current cell location.\n"
244 "<i>Calculation details - Median:</i> If the number of input layers is even, the median will be calculated as the "
245 "arithmetic mean of the two middle values of the ordered cell input values. In this case the output data type is Float32.\n"
246 "<i>Calculation details - Minority/Majority:</i> If no unique minority or majority could be found, the result is NoData, except all "
247 "input cell values are equal."
251QString QgsCellStatisticsAlgorithm::shortDescription()
const
253 return QObject::tr(
"Generates a raster whose cell values are computed from overlaid cell values of the input rasters." );
256QgsCellStatisticsAlgorithm *QgsCellStatisticsAlgorithm::createInstance()
const
258 return new QgsCellStatisticsAlgorithm();
261void QgsCellStatisticsAlgorithm::addSpecificAlgorithmParams()
263 QStringList statistics = QStringList();
265 << QObject::tr(
"Sum" )
266 << QObject::tr(
"Count" )
267 << QObject::tr(
"Mean" )
268 << QObject::tr(
"Median" )
269 << QObject::tr(
"Standard deviation" )
270 << QObject::tr(
"Variance" )
271 << QObject::tr(
"Minimum" )
272 << QObject::tr(
"Maximum" )
273 << QObject::tr(
"Minority" )
274 << QObject::tr(
"Majority" )
275 << QObject::tr(
"Range" )
276 << QObject::tr(
"Variety" );
285 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValueStatisticMethods
>( parameterAsEnum( parameters, u
"STATISTIC"_s, context ) );
288 if ( mMethod == QgsRasterAnalysisUtils::Mean
289 || mMethod == QgsRasterAnalysisUtils::StandardDeviation
290 || mMethod == QgsRasterAnalysisUtils::Variance
291 || ( mMethod == QgsRasterAnalysisUtils::Median && ( mInputs.size() % 2 == 0 ) ) )
293 if (
static_cast<int>( mDataType ) < 6 )
296 else if ( mMethod == QgsRasterAnalysisUtils::Count || mMethod == QgsRasterAnalysisUtils::Variety )
298 if (
static_cast<int>( mDataType ) > 5 )
306 mOutputRasterDataProvider->setEditable(
true );
308 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
315 std::unique_ptr<QgsRasterBlock> outputBlock;
316 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
318 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
319 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
323 for (
int band : i.bands )
327 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
328 inputBlocks.emplace_back( std::move( b ) );
332 feedback->
setProgress( mMaxProgressDuringBlockWriting * outputIter.progress( 1 ) );
333 for (
int row = 0; row < iterRows; row++ )
338 for (
int col = 0; col < iterCols; col++ )
341 bool noDataInStack =
false;
342 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
343 int cellValueStackSize = cellValues.size();
345 if ( noDataInStack && !mIgnoreNoData )
349 if ( mMethod == QgsRasterAnalysisUtils::Count )
350 outputBlock->setValue( row, col, cellValueStackSize );
353 outputBlock->setValue( row, col, mNoDataValue );
356 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
360 case QgsRasterAnalysisUtils::Sum:
361 result = std::accumulate( cellValues.begin(), cellValues.end(), 0.0 );
363 case QgsRasterAnalysisUtils::Count:
364 result = cellValueStackSize;
366 case QgsRasterAnalysisUtils::Mean:
367 result = QgsRasterAnalysisUtils::meanFromCellValues( cellValues, cellValueStackSize );
369 case QgsRasterAnalysisUtils::Median:
370 result = QgsRasterAnalysisUtils::medianFromCellValues( cellValues, cellValueStackSize );
372 case QgsRasterAnalysisUtils::StandardDeviation:
373 result = QgsRasterAnalysisUtils::stddevFromCellValues( cellValues, cellValueStackSize );
375 case QgsRasterAnalysisUtils::Variance:
376 result = QgsRasterAnalysisUtils::varianceFromCellValues( cellValues, cellValueStackSize );
378 case QgsRasterAnalysisUtils::Minimum:
379 result = QgsRasterAnalysisUtils::minimumFromCellValues( cellValues );
381 case QgsRasterAnalysisUtils::Maximum:
382 result = QgsRasterAnalysisUtils::maximumFromCellValues( cellValues );
384 case QgsRasterAnalysisUtils::Minority:
385 result = QgsRasterAnalysisUtils::minorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
387 case QgsRasterAnalysisUtils::Majority:
388 result = QgsRasterAnalysisUtils::majorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
390 case QgsRasterAnalysisUtils::Range:
391 result = QgsRasterAnalysisUtils::rangeFromCellValues( cellValues );
393 case QgsRasterAnalysisUtils::Variety:
394 result = QgsRasterAnalysisUtils::varietyFromCellValues( cellValues );
397 outputBlock->setValue( row, col, result );
402 outputBlock->setValue( row, col, mNoDataValue );
406 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
408 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
411 mOutputRasterDataProvider->setEditable(
false );
417QString QgsCellStatisticsPercentileAlgorithm::displayName()
const
419 return QObject::tr(
"Cell stack percentile" );
422QString QgsCellStatisticsPercentileAlgorithm::name()
const
424 return u
"cellstackpercentile"_s;
427QStringList QgsCellStatisticsPercentileAlgorithm::tags()
const
429 return QObject::tr(
"cell,pixel,statistic,percentile,quantile,quartile" ).split(
',' );
432QString QgsCellStatisticsPercentileAlgorithm::shortHelpString()
const
435 "This algorithm generates a raster containing the cell-wise percentile value of a stack of input rasters. "
436 "The percentile to return is determined by the percentile input value (ranges between 0 and 1). "
437 "At each cell location, the specified percentile is obtained using the respective value from "
438 "the stack of all overlaid and sorted cell values of the input rasters.\n\n"
439 "There are three methods for percentile calculation:"
441 " <li>Nearest rank</li>"
442 " <li>Inclusive linear interpolation (PERCENTILE.INC)</li>"
443 " <li>Exclusive linear interpolation (PERCENTILE.EXC)</li>"
445 "While the output value can stay the same for the nearest rank method (obtains the value that is nearest to the "
446 "specified percentile), the linear interpolation method return unique values for different percentiles. Both interpolation "
447 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
448 "The output raster's extent and resolution is defined by a reference "
449 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
450 "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. "
451 "The output raster data type will be set to the most complex data type present in the input datasets. "
455QString QgsCellStatisticsPercentileAlgorithm::shortDescription()
const
457 return QObject::tr(
"Generates a raster containing the cell-wise percentile value of a stack of input rasters." );
460QgsCellStatisticsPercentileAlgorithm *QgsCellStatisticsPercentileAlgorithm::createInstance()
const
462 return new QgsCellStatisticsPercentileAlgorithm();
465void QgsCellStatisticsPercentileAlgorithm::addSpecificAlgorithmParams()
469 QObject::tr(
"Method" ),
470 QStringList() << QObject::tr(
"Nearest rank" ) << QObject::tr(
"Inclusive linear interpolation (PERCENTILE.INC)" ) << QObject::tr(
"Exclusive linear interpolation (PERCENTILE.EXC)" ),
481 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentileMethods
>( parameterAsEnum( parameters, u
"METHOD"_s, context ) );
482 mPercentile = parameterAsDouble( parameters, u
"PERCENTILE"_s, context );
486 if ( mMethod != QgsRasterAnalysisUtils::CellValuePercentileMethods::NearestRankPercentile &&
static_cast<int>( mDataType ) < 6 )
494 mOutputRasterDataProvider->setEditable(
true );
496 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
503 std::unique_ptr<QgsRasterBlock> outputBlock;
504 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
506 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
507 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
511 for (
int band : i.bands )
515 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
516 inputBlocks.emplace_back( std::move( b ) );
520 feedback->
setProgress( mMaxProgressDuringBlockWriting * outputIter.progress( 1 ) );
521 for (
int row = 0; row < iterRows; row++ )
526 for (
int col = 0; col < iterCols; col++ )
529 bool noDataInStack =
false;
530 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
531 int cellValueStackSize = cellValues.size();
533 if ( noDataInStack && !mIgnoreNoData )
535 outputBlock->setValue( row, col, mNoDataValue );
537 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
541 case QgsRasterAnalysisUtils::NearestRankPercentile:
542 result = QgsRasterAnalysisUtils::nearestRankPercentile( cellValues, cellValueStackSize, mPercentile );
544 case QgsRasterAnalysisUtils::InterpolatedPercentileInc:
545 result = QgsRasterAnalysisUtils::interpolatedPercentileInc( cellValues, cellValueStackSize, mPercentile );
547 case QgsRasterAnalysisUtils::InterpolatedPercentileExc:
548 result = QgsRasterAnalysisUtils::interpolatedPercentileExc( cellValues, cellValueStackSize, mPercentile, mNoDataValue );
551 outputBlock->setValue( row, col, result );
556 outputBlock->setValue( row, col, mNoDataValue );
560 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
562 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
565 mOutputRasterDataProvider->setEditable(
false );
571QString QgsCellStatisticsPercentRankFromValueAlgorithm::displayName()
const
573 return QObject::tr(
"Cell stack percent rank from value" );
576QString QgsCellStatisticsPercentRankFromValueAlgorithm::name()
const
578 return u
"cellstackpercentrankfromvalue"_s;
581QStringList QgsCellStatisticsPercentRankFromValueAlgorithm::tags()
const
583 return QObject::tr(
"cell,pixel,statistic,percentrank,rank,percent,value" ).split(
',' );
586QString QgsCellStatisticsPercentRankFromValueAlgorithm::shortHelpString()
const
589 "This algorithm generates a raster containing the cell-wise percent rank value of a stack of input rasters based on a single input value.\n\n"
590 "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. "
591 "For values outside of the stack value distribution, the algorithm returns NoData because the value cannot be ranked among the cell values.\n\n"
592 "There are two methods for percentile calculation:"
594 " <li>Inclusive linearly interpolated percent rank (PERCENTRANK.INC)</li>"
595 " <li>Exclusive linearly interpolated percent rank (PERCENTRANK.EXC)</li>"
597 "The linear interpolation method return the unique percent rank for different values. Both interpolation "
598 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
599 "The output raster's extent and resolution is defined by a reference "
600 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
601 "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. "
602 "The output raster data type will always be Float32."
606QString QgsCellStatisticsPercentRankFromValueAlgorithm::shortDescription()
const
608 return QObject::tr(
"Generates a raster containing the cell-wise percent rank value of a stack of input rasters based on a single input value." );
611QgsCellStatisticsPercentRankFromValueAlgorithm *QgsCellStatisticsPercentRankFromValueAlgorithm::createInstance()
const
613 return new QgsCellStatisticsPercentRankFromValueAlgorithm();
616void QgsCellStatisticsPercentRankFromValueAlgorithm::addSpecificAlgorithmParams()
619 new QgsProcessingParameterEnum( u
"METHOD"_s, QObject::tr(
"Method" ), QStringList() << QObject::tr(
"Inclusive linear interpolation (PERCENTRANK.INC)" ) << QObject::tr(
"Exclusive linear interpolation (PERCENTRANK.EXC)" ),
false, 0,
false )
627 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentRankMethods
>( parameterAsEnum( parameters, u
"METHOD"_s, context ) );
628 mValue = parameterAsDouble( parameters, u
"VALUE"_s, context );
635void QgsCellStatisticsPercentRankFromValueAlgorithm::processRasterStack(
QgsProcessingFeedback *feedback )
637 mOutputRasterDataProvider->setEditable(
true );
639 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
646 std::unique_ptr<QgsRasterBlock> outputBlock;
647 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
649 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
650 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
654 for (
int band : i.bands )
658 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
659 inputBlocks.emplace_back( std::move( b ) );
663 feedback->
setProgress( mMaxProgressDuringBlockWriting * outputIter.progress( 1 ) );
664 for (
int row = 0; row < iterRows; row++ )
669 for (
int col = 0; col < iterCols; col++ )
672 bool noDataInStack =
false;
673 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
674 int cellValueStackSize = cellValues.size();
676 if ( noDataInStack && !mIgnoreNoData )
678 outputBlock->setValue( row, col, mNoDataValue );
680 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
684 case QgsRasterAnalysisUtils::InterpolatedPercentRankInc:
685 result = QgsRasterAnalysisUtils::interpolatedPercentRankInc( cellValues, cellValueStackSize, mValue, mNoDataValue );
687 case QgsRasterAnalysisUtils::InterpolatedPercentRankExc:
688 result = QgsRasterAnalysisUtils::interpolatedPercentRankExc( cellValues, cellValueStackSize, mValue, mNoDataValue );
691 outputBlock->setValue( row, col, result );
696 outputBlock->setValue( row, col, mNoDataValue );
700 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
702 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
705 mOutputRasterDataProvider->setEditable(
false );
712QString QgsCellStatisticsPercentRankFromRasterAlgorithm::displayName()
const
714 return QObject::tr(
"Cell stack percentrank from raster layer" );
717QString QgsCellStatisticsPercentRankFromRasterAlgorithm::name()
const
719 return u
"cellstackpercentrankfromrasterlayer"_s;
722QStringList QgsCellStatisticsPercentRankFromRasterAlgorithm::tags()
const
724 return QObject::tr(
"cell,pixel,statistic,percentrank,rank,percent,value,raster" ).split(
',' );
727QString QgsCellStatisticsPercentRankFromRasterAlgorithm::shortHelpString()
const
730 "This algorithm generates a raster containing the cell-wise percent rank value of a stack of input rasters "
731 "based on an input value raster.\n\n"
732 "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. "
733 "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"
734 "There are two methods for percentile calculation:"
736 " <li>Inclusive linearly interpolated percent rank (PERCENTRANK.INC)</li>"
737 " <li>Exclusive linearly interpolated percent rank (PERCENTRANK.EXC)</li>"
739 "The linear interpolation method return the unique percent rank for different values. Both interpolation "
740 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
741 "The output raster's extent and resolution is defined by a reference "
742 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
743 "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. "
744 "The output raster data type will always be Float32."
748QString QgsCellStatisticsPercentRankFromRasterAlgorithm::shortDescription()
const
750 return QObject::tr(
"Generates a raster containing the cell-wise percent rank value of a stack of input rasters based on an input value raster." );
753QgsCellStatisticsPercentRankFromRasterAlgorithm *QgsCellStatisticsPercentRankFromRasterAlgorithm::createInstance()
const
755 return new QgsCellStatisticsPercentRankFromRasterAlgorithm();
758void QgsCellStatisticsPercentRankFromRasterAlgorithm::addSpecificAlgorithmParams()
761 addParameter(
new QgsProcessingParameterBand( u
"VALUE_RASTER_BAND"_s, QObject::tr(
"Value raster band" ), 1, u
"VALUE_LAYER"_s ) );
763 new QgsProcessingParameterEnum( u
"METHOD"_s, QObject::tr(
"Method" ), QStringList() << QObject::tr(
"Inclusive linear interpolation (PERCENTRANK.INC)" ) << QObject::tr(
"Exclusive linear interpolation (PERCENTRANK.EXC)" ),
false, 0,
false )
770 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentRankMethods
>( parameterAsEnum( parameters, u
"METHOD"_s, context ) );
772 QgsRasterLayer *inputValueRaster = parameterAsRasterLayer( parameters, u
"INPUT_VALUE_RASTER"_s, context );
773 if ( !inputValueRaster )
778 mValueRasterBand = parameterAsInt( parameters, u
"VALUE_RASTER_BAND"_s, context );
785void QgsCellStatisticsPercentRankFromRasterAlgorithm::processRasterStack(
QgsProcessingFeedback *feedback )
787 mOutputRasterDataProvider->setEditable(
true );
789 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
796 std::unique_ptr<QgsRasterBlock> outputBlock;
797 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
799 std::unique_ptr<QgsRasterBlock> valueBlock( mValueRasterInterface->block( mValueRasterBand, blockExtent, iterCols, iterRows ) );
801 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
802 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
806 for (
int band : i.bands )
810 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
811 inputBlocks.emplace_back( std::move( b ) );
815 feedback->
setProgress( mMaxProgressDuringBlockWriting * outputIter.progress( 1 ) );
816 for (
int row = 0; row < iterRows; row++ )
821 for (
int col = 0; col < iterCols; col++ )
823 bool percentRankValueIsNoData =
false;
824 double percentRankValue = valueBlock->valueAndNoData( row, col, percentRankValueIsNoData );
827 bool noDataInStack =
false;
828 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
829 int cellValueStackSize = cellValues.size();
831 if ( noDataInStack && !mIgnoreNoData && !percentRankValueIsNoData )
833 outputBlock->setValue( row, col, mNoDataValue );
835 else if ( !noDataInStack || ( !percentRankValueIsNoData && mIgnoreNoData && cellValueStackSize > 0 ) )
839 case QgsRasterAnalysisUtils::InterpolatedPercentRankInc:
840 result = QgsRasterAnalysisUtils::interpolatedPercentRankInc( cellValues, cellValueStackSize, percentRankValue, mNoDataValue );
842 case QgsRasterAnalysisUtils::InterpolatedPercentRankExc:
843 result = QgsRasterAnalysisUtils::interpolatedPercentRankExc( cellValues, cellValueStackSize, percentRankValue, mNoDataValue );
846 outputBlock->setValue( row, col, result );
851 outputBlock->setValue( row, col, mNoDataValue );
855 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
857 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
860 mOutputRasterDataProvider->setEditable(
false );
DataType
Raster data types.
@ Float32
Thirty two bit floating point (float).
@ Byte
Eight bit unsigned integer (quint8).
@ Int32
Thirty two bit signed integer (qint32).
@ Hidden
Parameter is hidden and should not be shown to users.
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
@ Double
Double/float values.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
static std::unique_ptr< QgsFeedback > createScaledFeedback(QgsFeedback *parentFeedback, double startPercentage, double endPercentage)
Returns a feedback object whose [0, 100] progression range will be mapped to parentFeedback [startPer...
Base class for all map layer types.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
Contains information about the context in which a processing algorithm is executed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
A numeric output for processing algorithms.
A string output for processing algorithms.
A raster band parameter for Processing algorithms.
A boolean parameter for processing algorithms.
An enum based parameter for processing algorithms, allowing for selection from predefined values.
A parameter for processing algorithms which accepts multiple map layers.
A numeric parameter for processing algorithms.
A raster layer destination parameter, for specifying the destination path for a raster layer created ...
A raster layer parameter for processing algorithms.
QgsRasterDataProvider * clone() const override=0
Clone itself, create deep copy.
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
Iterator for sequentially processing raster cells.
Represents a raster layer.
int height() const
Returns the height of the (unclipped) raster.
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
double rasterUnitsPerPixelY() const
Returns the number of raster units per each raster pixel in Y axis.
int width() const
Returns the width of the (unclipped) raster.
A rectangle specified with double values.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...