26QString QgsCellStatisticsAlgorithmBase::group()
const
28 return QObject::tr(
"Raster analysis" );
31QString QgsCellStatisticsAlgorithmBase::groupId()
const
33 return QStringLiteral(
"rasteranalysis" );
36void QgsCellStatisticsAlgorithmBase::initAlgorithm(
const QVariantMap & )
40 addSpecificAlgorithmParams();
46 auto output_nodata_parameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral(
"OUTPUT_NODATA_VALUE" ), QObject::tr(
"Output NoData value" ),
Qgis::ProcessingNumberParameterType::Double, -9999,
false );
48 addParameter( output_nodata_parameter.release() );
52 auto createOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATE_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
53 createOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
55 addParameter( createOptsParam.release() );
57 auto creationOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATION_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
58 creationOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
60 addParameter( creationOptsParam.release() );
73 QgsRasterLayer *referenceLayer = parameterAsRasterLayer( parameters, QStringLiteral(
"REFERENCE_LAYER" ), context );
74 if ( !referenceLayer )
77 mIgnoreNoData = parameterAsBool( parameters, QStringLiteral(
"IGNORE_NODATA" ), context );
78 mNoDataValue = parameterAsDouble( parameters, QStringLiteral(
"OUTPUT_NODATA_VALUE" ), context );
79 mCrs = referenceLayer->
crs();
82 mLayerWidth = referenceLayer->
width();
83 mLayerHeight = referenceLayer->
height();
84 mExtent = referenceLayer->
extent();
86 const QList<QgsMapLayer *> layers = parameterAsLayerList( parameters, QStringLiteral(
"INPUT" ), context );
87 QList<QgsRasterLayer *> rasterLayers;
88 rasterLayers.reserve( layers.count() );
97 QgsRasterAnalysisUtils::RasterLogicInput input;
101 input.interface = input.sourceDataProvider.get();
103 if ( layer->
crs() != mCrs )
105 input.projector = std::make_unique<QgsRasterProjector>();
106 input.projector->setInput( input.sourceDataProvider.get() );
108 input.interface = input.projector.get();
110 mInputs.emplace_back( std::move( input ) );
117 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
119 for (
int band : i.bands )
122 if (
static_cast<int>( mDataType ) <
static_cast<int>( inputDataType ) )
123 mDataType = inputDataType;
127 prepareSpecificAlgorithmParameters( parameters, context, feedback );
135 QString creationOptions = parameterAsString( parameters, QStringLiteral(
"CREATION_OPTIONS" ), context ).trimmed();
137 const QString optionsString = parameterAsString( parameters, QStringLiteral(
"CREATE_OPTIONS" ), context );
138 if ( !optionsString.isEmpty() )
139 creationOptions = optionsString;
141 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
142 QFileInfo fi( outputFile );
145 auto writer = std::make_unique<QgsRasterFileWriter>( outputFile );
146 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
147 if ( !creationOptions.isEmpty() )
149 writer->setCreationOptions( creationOptions.split(
'|' ) );
151 writer->setOutputFormat( outputFormat );
152 mOutputRasterDataProvider.reset( writer->createOneBandRaster( mDataType, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
153 if ( !mOutputRasterDataProvider )
155 if ( !mOutputRasterDataProvider->isValid() )
158 mOutputRasterDataProvider->setNoDataValue( 1, mNoDataValue );
162 processRasterStack( feedback );
164 mOutputRasterDataProvider.reset();
167 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
168 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
169 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
170 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
171 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
172 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
181QString QgsCellStatisticsAlgorithm::displayName()
const
183 return QObject::tr(
"Cell statistics" );
186QString QgsCellStatisticsAlgorithm::name()
const
188 return QStringLiteral(
"cellstatistics" );
191QStringList QgsCellStatisticsAlgorithm::tags()
const
193 return QObject::tr(
"cell,pixel,statistic,count,mean,sum,majority,minority,variance,variety,range,median,minimum,maximum" ).split(
',' );
196QString QgsCellStatisticsAlgorithm::shortHelpString()
const
198 return QObject::tr(
"The Cell statistics algorithm computes a value for each cell of the "
199 "output raster. At each cell location, "
200 "the output value is defined as a function of all overlaid cell values of the "
202 "The output raster's extent and resolution is defined by a reference "
203 "raster. The following functions can be applied on the input "
204 "raster cells per output raster cell location:\n"
210 " <li>Standard deviation</li>"
214 " <li>Minority (least frequent value)</li>"
215 " <li>Majority (most frequent value)</li>"
216 " <li>Range (max-min)</li>"
217 " <li>Variety (count of unique values)</li>"
219 "Input raster layers that do not match the cell size of the reference raster layer will be "
220 "resampled using nearest neighbor resampling. The output raster data type will be set to "
221 "the most complex data type present in the input datasets except when using the functions "
222 "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"
223 "<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"
224 "<i>Calculation details - Count:</i> Count will always result in the number of cells without NoData values at the current cell location.\n"
225 "<i>Calculation details - Median:</i> If the number of input layers is even, the median will be calculated as the "
226 "arithmetic mean of the two middle values of the ordered cell input values. In this case the output data type is Float32.\n"
227 "<i>Calculation details - Minority/Majority:</i> If no unique minority or majority could be found, the result is NoData, except all "
228 "input cell values are equal." );
231QString QgsCellStatisticsAlgorithm::shortDescription()
const
233 return QObject::tr(
"Generates a raster whose cell values are computed from overlaid cell values of the input rasters." );
236QgsCellStatisticsAlgorithm *QgsCellStatisticsAlgorithm::createInstance()
const
238 return new QgsCellStatisticsAlgorithm();
241void QgsCellStatisticsAlgorithm::addSpecificAlgorithmParams()
243 QStringList statistics = QStringList();
244 statistics << QObject::tr(
"Sum" )
245 << QObject::tr(
"Count" )
246 << QObject::tr(
"Mean" )
247 << QObject::tr(
"Median" )
248 << QObject::tr(
"Standard deviation" )
249 << QObject::tr(
"Variance" )
250 << QObject::tr(
"Minimum" )
251 << QObject::tr(
"Maximum" )
252 << QObject::tr(
"Minority" )
253 << QObject::tr(
"Majority" )
254 << QObject::tr(
"Range" )
255 << QObject::tr(
"Variety" );
257 addParameter(
new QgsProcessingParameterEnum( QStringLiteral(
"STATISTIC" ), QObject::tr(
"Statistic" ), statistics,
false, 0,
false ) );
264 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValueStatisticMethods
>( parameterAsEnum( parameters, QStringLiteral(
"STATISTIC" ), context ) );
268 mMethod == QgsRasterAnalysisUtils::Mean || mMethod == QgsRasterAnalysisUtils::StandardDeviation || mMethod == QgsRasterAnalysisUtils::Variance || ( mMethod == QgsRasterAnalysisUtils::Median && ( mInputs.size() % 2 == 0 ) )
271 if (
static_cast<int>( mDataType ) < 6 )
274 else if ( mMethod == QgsRasterAnalysisUtils::Count || mMethod == QgsRasterAnalysisUtils::Variety )
276 if (
static_cast<int>( mDataType ) > 5 )
286 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
287 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
288 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
289 mOutputRasterDataProvider->setEditable(
true );
291 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
298 std::unique_ptr<QgsRasterBlock> outputBlock;
299 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
301 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
302 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
306 for (
int band : i.bands )
310 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
311 inputBlocks.emplace_back( std::move( b ) );
315 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
316 for (
int row = 0; row < iterRows; row++ )
321 for (
int col = 0; col < iterCols; col++ )
324 bool noDataInStack =
false;
325 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
326 int cellValueStackSize = cellValues.size();
328 if ( noDataInStack && !mIgnoreNoData )
332 if ( mMethod == QgsRasterAnalysisUtils::Count )
333 outputBlock->setValue( row, col, cellValueStackSize );
336 outputBlock->setValue( row, col, mNoDataValue );
339 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
343 case QgsRasterAnalysisUtils::Sum:
344 result = std::accumulate( cellValues.begin(), cellValues.end(), 0.0 );
346 case QgsRasterAnalysisUtils::Count:
347 result = cellValueStackSize;
349 case QgsRasterAnalysisUtils::Mean:
350 result = QgsRasterAnalysisUtils::meanFromCellValues( cellValues, cellValueStackSize );
352 case QgsRasterAnalysisUtils::Median:
353 result = QgsRasterAnalysisUtils::medianFromCellValues( cellValues, cellValueStackSize );
355 case QgsRasterAnalysisUtils::StandardDeviation:
356 result = QgsRasterAnalysisUtils::stddevFromCellValues( cellValues, cellValueStackSize );
358 case QgsRasterAnalysisUtils::Variance:
359 result = QgsRasterAnalysisUtils::varianceFromCellValues( cellValues, cellValueStackSize );
361 case QgsRasterAnalysisUtils::Minimum:
362 result = QgsRasterAnalysisUtils::minimumFromCellValues( cellValues );
364 case QgsRasterAnalysisUtils::Maximum:
365 result = QgsRasterAnalysisUtils::maximumFromCellValues( cellValues );
367 case QgsRasterAnalysisUtils::Minority:
368 result = QgsRasterAnalysisUtils::minorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
370 case QgsRasterAnalysisUtils::Majority:
371 result = QgsRasterAnalysisUtils::majorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
373 case QgsRasterAnalysisUtils::Range:
374 result = QgsRasterAnalysisUtils::rangeFromCellValues( cellValues );
376 case QgsRasterAnalysisUtils::Variety:
377 result = QgsRasterAnalysisUtils::varietyFromCellValues( cellValues );
380 outputBlock->setValue( row, col, result );
385 outputBlock->setValue( row, col, mNoDataValue );
389 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
391 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
394 mOutputRasterDataProvider->setEditable(
false );
400QString QgsCellStatisticsPercentileAlgorithm::displayName()
const
402 return QObject::tr(
"Cell stack percentile" );
405QString QgsCellStatisticsPercentileAlgorithm::name()
const
407 return QStringLiteral(
"cellstackpercentile" );
410QStringList QgsCellStatisticsPercentileAlgorithm::tags()
const
412 return QObject::tr(
"cell,pixel,statistic,percentile,quantile,quartile" ).split(
',' );
415QString QgsCellStatisticsPercentileAlgorithm::shortHelpString()
const
417 return QObject::tr(
"This algorithm generates a raster containing the cell-wise percentile value of a stack of input rasters. "
418 "The percentile to return is determined by the percentile input value (ranges between 0 and 1). "
419 "At each cell location, the specified percentile is obtained using the respective value from "
420 "the stack of all overlaid and sorted cell values of the input rasters.\n\n"
421 "There are three methods for percentile calculation:"
423 " <li>Nearest rank</li>"
424 " <li>Inclusive linear interpolation (PERCENTILE.INC)</li>"
425 " <li>Exclusive linear interpolation (PERCENTILE.EXC)</li>"
427 "While the output value can stay the same for the nearest rank method (obtains the value that is nearest to the "
428 "specified percentile), the linear interpolation method return unique values for different percentiles. Both interpolation "
429 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
430 "The output raster's extent and resolution is defined by a reference "
431 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
432 "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. "
433 "The output raster data type will be set to the most complex data type present in the input datasets. " );
436QString QgsCellStatisticsPercentileAlgorithm::shortDescription()
const
438 return QObject::tr(
"Generates a raster containing the cell-wise percentile value of a stack of input rasters." );
441QgsCellStatisticsPercentileAlgorithm *QgsCellStatisticsPercentileAlgorithm::createInstance()
const
443 return new QgsCellStatisticsPercentileAlgorithm();
446void QgsCellStatisticsPercentileAlgorithm::addSpecificAlgorithmParams()
448 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 ) );
455 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentileMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
456 mPercentile = parameterAsDouble( parameters, QStringLiteral(
"PERCENTILE" ), context );
460 if ( mMethod != QgsRasterAnalysisUtils::CellValuePercentileMethods::NearestRankPercentile &&
static_cast<int>( mDataType ) < 6 )
470 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
471 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
472 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
473 mOutputRasterDataProvider->setEditable(
true );
475 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
482 std::unique_ptr<QgsRasterBlock> outputBlock;
483 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
485 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
486 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
490 for (
int band : i.bands )
494 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
495 inputBlocks.emplace_back( std::move( b ) );
499 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
500 for (
int row = 0; row < iterRows; row++ )
505 for (
int col = 0; col < iterCols; col++ )
508 bool noDataInStack =
false;
509 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
510 int cellValueStackSize = cellValues.size();
512 if ( noDataInStack && !mIgnoreNoData )
514 outputBlock->setValue( row, col, mNoDataValue );
516 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
520 case QgsRasterAnalysisUtils::NearestRankPercentile:
521 result = QgsRasterAnalysisUtils::nearestRankPercentile( cellValues, cellValueStackSize, mPercentile );
523 case QgsRasterAnalysisUtils::InterpolatedPercentileInc:
524 result = QgsRasterAnalysisUtils::interpolatedPercentileInc( cellValues, cellValueStackSize, mPercentile );
526 case QgsRasterAnalysisUtils::InterpolatedPercentileExc:
527 result = QgsRasterAnalysisUtils::interpolatedPercentileExc( cellValues, cellValueStackSize, mPercentile, mNoDataValue );
530 outputBlock->setValue( row, col, result );
535 outputBlock->setValue( row, col, mNoDataValue );
539 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
541 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
544 mOutputRasterDataProvider->setEditable(
false );
550QString QgsCellStatisticsPercentRankFromValueAlgorithm::displayName()
const
552 return QObject::tr(
"Cell stack percent rank from value" );
555QString QgsCellStatisticsPercentRankFromValueAlgorithm::name()
const
557 return QStringLiteral(
"cellstackpercentrankfromvalue" );
560QStringList QgsCellStatisticsPercentRankFromValueAlgorithm::tags()
const
562 return QObject::tr(
"cell,pixel,statistic,percentrank,rank,percent,value" ).split(
',' );
565QString QgsCellStatisticsPercentRankFromValueAlgorithm::shortHelpString()
const
567 return QObject::tr(
"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"
568 "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. "
569 "For values outside of the stack value distribution, the algorithm returns NoData because the value cannot be ranked among the cell values.\n\n"
570 "There are two methods for percentile calculation:"
572 " <li>Inclusive linearly interpolated percent rank (PERCENTRANK.INC)</li>"
573 " <li>Exclusive linearly interpolated percent rank (PERCENTRANK.EXC)</li>"
575 "The linear interpolation method return the unique percent rank for different values. Both interpolation "
576 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
577 "The output raster's extent and resolution is defined by a reference "
578 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
579 "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. "
580 "The output raster data type will always be Float32." );
583QString QgsCellStatisticsPercentRankFromValueAlgorithm::shortDescription()
const
585 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." );
588QgsCellStatisticsPercentRankFromValueAlgorithm *QgsCellStatisticsPercentRankFromValueAlgorithm::createInstance()
const
590 return new QgsCellStatisticsPercentRankFromValueAlgorithm();
593void QgsCellStatisticsPercentRankFromValueAlgorithm::addSpecificAlgorithmParams()
595 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 ) );
602 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentRankMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
603 mValue = parameterAsDouble( parameters, QStringLiteral(
"VALUE" ), context );
610void QgsCellStatisticsPercentRankFromValueAlgorithm::processRasterStack(
QgsProcessingFeedback *feedback )
614 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
615 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
616 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
617 mOutputRasterDataProvider->setEditable(
true );
619 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
626 std::unique_ptr<QgsRasterBlock> outputBlock;
627 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
629 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
630 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
634 for (
int band : i.bands )
638 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
639 inputBlocks.emplace_back( std::move( b ) );
643 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
644 for (
int row = 0; row < iterRows; row++ )
649 for (
int col = 0; col < iterCols; col++ )
652 bool noDataInStack =
false;
653 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
654 int cellValueStackSize = cellValues.size();
656 if ( noDataInStack && !mIgnoreNoData )
658 outputBlock->setValue( row, col, mNoDataValue );
660 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
664 case QgsRasterAnalysisUtils::InterpolatedPercentRankInc:
665 result = QgsRasterAnalysisUtils::interpolatedPercentRankInc( cellValues, cellValueStackSize, mValue, mNoDataValue );
667 case QgsRasterAnalysisUtils::InterpolatedPercentRankExc:
668 result = QgsRasterAnalysisUtils::interpolatedPercentRankExc( cellValues, cellValueStackSize, mValue, mNoDataValue );
671 outputBlock->setValue( row, col, result );
676 outputBlock->setValue( row, col, mNoDataValue );
680 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
682 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
685 mOutputRasterDataProvider->setEditable(
false );
692QString QgsCellStatisticsPercentRankFromRasterAlgorithm::displayName()
const
694 return QObject::tr(
"Cell stack percentrank from raster layer" );
697QString QgsCellStatisticsPercentRankFromRasterAlgorithm::name()
const
699 return QStringLiteral(
"cellstackpercentrankfromrasterlayer" );
702QStringList QgsCellStatisticsPercentRankFromRasterAlgorithm::tags()
const
704 return QObject::tr(
"cell,pixel,statistic,percentrank,rank,percent,value,raster" ).split(
',' );
707QString QgsCellStatisticsPercentRankFromRasterAlgorithm::shortHelpString()
const
709 return QObject::tr(
"This algorithm generates a raster containing the cell-wise percent rank value of a stack of input rasters "
710 "based on an input value raster.\n\n"
711 "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. "
712 "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"
713 "There are two methods for percentile calculation:"
715 " <li>Inclusive linearly interpolated percent rank (PERCENTRANK.INC)</li>"
716 " <li>Exclusive linearly interpolated percent rank (PERCENTRANK.EXC)</li>"
718 "The linear interpolation method return the unique percent rank for different values. Both interpolation "
719 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
720 "The output raster's extent and resolution is defined by a reference "
721 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
722 "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. "
723 "The output raster data type will always be Float32." );
726QString QgsCellStatisticsPercentRankFromRasterAlgorithm::shortDescription()
const
728 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." );
731QgsCellStatisticsPercentRankFromRasterAlgorithm *QgsCellStatisticsPercentRankFromRasterAlgorithm::createInstance()
const
733 return new QgsCellStatisticsPercentRankFromRasterAlgorithm();
736void QgsCellStatisticsPercentRankFromRasterAlgorithm::addSpecificAlgorithmParams()
739 addParameter(
new QgsProcessingParameterBand( QStringLiteral(
"VALUE_RASTER_BAND" ), QObject::tr(
"Value raster band" ), 1, QStringLiteral(
"VALUE_LAYER" ) ) );
740 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 ) );
746 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentRankMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
748 QgsRasterLayer *inputValueRaster = parameterAsRasterLayer( parameters, QStringLiteral(
"INPUT_VALUE_RASTER" ), context );
749 if ( !inputValueRaster )
754 mValueRasterBand = parameterAsInt( parameters, QStringLiteral(
"VALUE_RASTER_BAND" ), context );
761void QgsCellStatisticsPercentRankFromRasterAlgorithm::processRasterStack(
QgsProcessingFeedback *feedback )
765 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
766 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
767 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
768 mOutputRasterDataProvider->setEditable(
true );
770 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
777 std::unique_ptr<QgsRasterBlock> outputBlock;
778 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
780 std::unique_ptr<QgsRasterBlock> valueBlock( mValueRasterInterface->block( mValueRasterBand, blockExtent, iterCols, iterRows ) );
782 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
783 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
787 for (
int band : i.bands )
791 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
792 inputBlocks.emplace_back( std::move( b ) );
796 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
797 for (
int row = 0; row < iterRows; row++ )
802 for (
int col = 0; col < iterCols; col++ )
804 bool percentRankValueIsNoData =
false;
805 double percentRankValue = valueBlock->valueAndNoData( row, col, percentRankValueIsNoData );
808 bool noDataInStack =
false;
809 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
810 int cellValueStackSize = cellValues.size();
812 if ( noDataInStack && !mIgnoreNoData && !percentRankValueIsNoData )
814 outputBlock->setValue( row, col, mNoDataValue );
816 else if ( !noDataInStack || ( !percentRankValueIsNoData && mIgnoreNoData && cellValueStackSize > 0 ) )
820 case QgsRasterAnalysisUtils::InterpolatedPercentRankInc:
821 result = QgsRasterAnalysisUtils::interpolatedPercentRankInc( cellValues, cellValueStackSize, percentRankValue, mNoDataValue );
823 case QgsRasterAnalysisUtils::InterpolatedPercentRankExc:
824 result = QgsRasterAnalysisUtils::interpolatedPercentRankExc( cellValues, cellValueStackSize, percentRankValue, mNoDataValue );
827 outputBlock->setValue( row, col, result );
832 outputBlock->setValue( row, col, mNoDataValue );
836 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
838 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
841 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.
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.
static QString driverForExtension(const QString &extension)
Returns the GDAL driver name for a specified file extension.
Iterator for sequentially processing raster cells.
static const int DEFAULT_MAXIMUM_TILE_WIDTH
Default maximum tile width.
static const int DEFAULT_MAXIMUM_TILE_HEIGHT
Default maximum tile height.
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...