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." );
231QgsCellStatisticsAlgorithm *QgsCellStatisticsAlgorithm::createInstance()
const
233 return new QgsCellStatisticsAlgorithm();
236void QgsCellStatisticsAlgorithm::addSpecificAlgorithmParams()
238 QStringList statistics = QStringList();
239 statistics << QObject::tr(
"Sum" )
240 << QObject::tr(
"Count" )
241 << QObject::tr(
"Mean" )
242 << QObject::tr(
"Median" )
243 << QObject::tr(
"Standard deviation" )
244 << QObject::tr(
"Variance" )
245 << QObject::tr(
"Minimum" )
246 << QObject::tr(
"Maximum" )
247 << QObject::tr(
"Minority" )
248 << QObject::tr(
"Majority" )
249 << QObject::tr(
"Range" )
250 << QObject::tr(
"Variety" );
252 addParameter(
new QgsProcessingParameterEnum( QStringLiteral(
"STATISTIC" ), QObject::tr(
"Statistic" ), statistics,
false, 0,
false ) );
259 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValueStatisticMethods
>( parameterAsEnum( parameters, QStringLiteral(
"STATISTIC" ), context ) );
263 mMethod == QgsRasterAnalysisUtils::Mean || mMethod == QgsRasterAnalysisUtils::StandardDeviation || mMethod == QgsRasterAnalysisUtils::Variance || ( mMethod == QgsRasterAnalysisUtils::Median && ( mInputs.size() % 2 == 0 ) )
266 if (
static_cast<int>( mDataType ) < 6 )
269 else if ( mMethod == QgsRasterAnalysisUtils::Count || mMethod == QgsRasterAnalysisUtils::Variety )
271 if (
static_cast<int>( mDataType ) > 5 )
281 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
282 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
283 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
284 mOutputRasterDataProvider->setEditable(
true );
286 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
293 std::unique_ptr<QgsRasterBlock> outputBlock;
294 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
296 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
297 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
301 for (
int band : i.bands )
305 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
306 inputBlocks.emplace_back( std::move( b ) );
310 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
311 for (
int row = 0; row < iterRows; row++ )
316 for (
int col = 0; col < iterCols; col++ )
319 bool noDataInStack =
false;
320 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
321 int cellValueStackSize = cellValues.size();
323 if ( noDataInStack && !mIgnoreNoData )
327 if ( mMethod == QgsRasterAnalysisUtils::Count )
328 outputBlock->setValue( row, col, cellValueStackSize );
331 outputBlock->setValue( row, col, mNoDataValue );
334 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
338 case QgsRasterAnalysisUtils::Sum:
339 result = std::accumulate( cellValues.begin(), cellValues.end(), 0.0 );
341 case QgsRasterAnalysisUtils::Count:
342 result = cellValueStackSize;
344 case QgsRasterAnalysisUtils::Mean:
345 result = QgsRasterAnalysisUtils::meanFromCellValues( cellValues, cellValueStackSize );
347 case QgsRasterAnalysisUtils::Median:
348 result = QgsRasterAnalysisUtils::medianFromCellValues( cellValues, cellValueStackSize );
350 case QgsRasterAnalysisUtils::StandardDeviation:
351 result = QgsRasterAnalysisUtils::stddevFromCellValues( cellValues, cellValueStackSize );
353 case QgsRasterAnalysisUtils::Variance:
354 result = QgsRasterAnalysisUtils::varianceFromCellValues( cellValues, cellValueStackSize );
356 case QgsRasterAnalysisUtils::Minimum:
357 result = QgsRasterAnalysisUtils::minimumFromCellValues( cellValues );
359 case QgsRasterAnalysisUtils::Maximum:
360 result = QgsRasterAnalysisUtils::maximumFromCellValues( cellValues );
362 case QgsRasterAnalysisUtils::Minority:
363 result = QgsRasterAnalysisUtils::minorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
365 case QgsRasterAnalysisUtils::Majority:
366 result = QgsRasterAnalysisUtils::majorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
368 case QgsRasterAnalysisUtils::Range:
369 result = QgsRasterAnalysisUtils::rangeFromCellValues( cellValues );
371 case QgsRasterAnalysisUtils::Variety:
372 result = QgsRasterAnalysisUtils::varietyFromCellValues( cellValues );
375 outputBlock->setValue( row, col, result );
380 outputBlock->setValue( row, col, mNoDataValue );
384 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
386 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
389 mOutputRasterDataProvider->setEditable(
false );
395QString QgsCellStatisticsPercentileAlgorithm::displayName()
const
397 return QObject::tr(
"Cell stack percentile" );
400QString QgsCellStatisticsPercentileAlgorithm::name()
const
402 return QStringLiteral(
"cellstackpercentile" );
405QStringList QgsCellStatisticsPercentileAlgorithm::tags()
const
407 return QObject::tr(
"cell,pixel,statistic,percentile,quantile,quartile" ).split(
',' );
410QString QgsCellStatisticsPercentileAlgorithm::shortHelpString()
const
412 return QObject::tr(
"The Cell stack percentile algorithm returns the cell-wise percentile value of a stack of rasters "
413 "and writes the results to an output raster. The percentile to return is determined by the percentile input value (ranges between 0 and 1). "
414 "At each cell location, the specified percentile is obtained using the respective value from "
415 "the stack of all overlaid and sorted cell values of the input rasters.\n\n"
416 "There are three methods for percentile calculation:"
418 " <li>Nearest rank</li>"
419 " <li>Inclusive linear interpolation (PERCENTILE.INC)</li>"
420 " <li>Exclusive linear interpolation (PERCENTILE.EXC)</li>"
422 "While the output value can stay the same for the nearest rank method (obtains the value that is nearest to the "
423 "specified percentile), the linear interpolation method return unique values for different percentiles. Both interpolation "
424 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
425 "The output raster's extent and resolution is defined by a reference "
426 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
427 "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. "
428 "The output raster data type will be set to the most complex data type present in the input datasets. " );
431QgsCellStatisticsPercentileAlgorithm *QgsCellStatisticsPercentileAlgorithm::createInstance()
const
433 return new QgsCellStatisticsPercentileAlgorithm();
436void QgsCellStatisticsPercentileAlgorithm::addSpecificAlgorithmParams()
438 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 ) );
445 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentileMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
446 mPercentile = parameterAsDouble( parameters, QStringLiteral(
"PERCENTILE" ), context );
450 if ( mMethod != QgsRasterAnalysisUtils::CellValuePercentileMethods::NearestRankPercentile &&
static_cast<int>( mDataType ) < 6 )
460 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
461 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
462 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
463 mOutputRasterDataProvider->setEditable(
true );
465 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
472 std::unique_ptr<QgsRasterBlock> outputBlock;
473 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
475 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
476 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
480 for (
int band : i.bands )
484 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
485 inputBlocks.emplace_back( std::move( b ) );
489 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
490 for (
int row = 0; row < iterRows; row++ )
495 for (
int col = 0; col < iterCols; col++ )
498 bool noDataInStack =
false;
499 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
500 int cellValueStackSize = cellValues.size();
502 if ( noDataInStack && !mIgnoreNoData )
504 outputBlock->setValue( row, col, mNoDataValue );
506 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
510 case QgsRasterAnalysisUtils::NearestRankPercentile:
511 result = QgsRasterAnalysisUtils::nearestRankPercentile( cellValues, cellValueStackSize, mPercentile );
513 case QgsRasterAnalysisUtils::InterpolatedPercentileInc:
514 result = QgsRasterAnalysisUtils::interpolatedPercentileInc( cellValues, cellValueStackSize, mPercentile );
516 case QgsRasterAnalysisUtils::InterpolatedPercentileExc:
517 result = QgsRasterAnalysisUtils::interpolatedPercentileExc( cellValues, cellValueStackSize, mPercentile, mNoDataValue );
520 outputBlock->setValue( row, col, result );
525 outputBlock->setValue( row, col, mNoDataValue );
529 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
531 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
534 mOutputRasterDataProvider->setEditable(
false );
540QString QgsCellStatisticsPercentRankFromValueAlgorithm::displayName()
const
542 return QObject::tr(
"Cell stack percent rank from value" );
545QString QgsCellStatisticsPercentRankFromValueAlgorithm::name()
const
547 return QStringLiteral(
"cellstackpercentrankfromvalue" );
550QStringList QgsCellStatisticsPercentRankFromValueAlgorithm::tags()
const
552 return QObject::tr(
"cell,pixel,statistic,percentrank,rank,percent,value" ).split(
',' );
555QString QgsCellStatisticsPercentRankFromValueAlgorithm::shortHelpString()
const
557 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 "
558 "and writes them to an output raster.\n\n"
559 "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. "
560 "For values outside of the stack value distribution, the algorithm returns NoData because the value cannot be ranked among the cell values.\n\n"
561 "There are two methods for percentile calculation:"
563 " <li>Inclusive linearly interpolated percent rank (PERCENTRANK.INC)</li>"
564 " <li>Exclusive linearly interpolated percent rank (PERCENTRANK.EXC)</li>"
566 "The linear interpolation method return the unique percent rank for different values. Both interpolation "
567 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
568 "The output raster's extent and resolution is defined by a reference "
569 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
570 "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. "
571 "The output raster data type will always be Float32." );
574QgsCellStatisticsPercentRankFromValueAlgorithm *QgsCellStatisticsPercentRankFromValueAlgorithm::createInstance()
const
576 return new QgsCellStatisticsPercentRankFromValueAlgorithm();
579void QgsCellStatisticsPercentRankFromValueAlgorithm::addSpecificAlgorithmParams()
581 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 ) );
588 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentRankMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
589 mValue = parameterAsDouble( parameters, QStringLiteral(
"VALUE" ), context );
596void QgsCellStatisticsPercentRankFromValueAlgorithm::processRasterStack(
QgsProcessingFeedback *feedback )
600 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
601 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
602 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
603 mOutputRasterDataProvider->setEditable(
true );
605 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
612 std::unique_ptr<QgsRasterBlock> outputBlock;
613 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
615 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
616 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
620 for (
int band : i.bands )
624 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
625 inputBlocks.emplace_back( std::move( b ) );
629 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
630 for (
int row = 0; row < iterRows; row++ )
635 for (
int col = 0; col < iterCols; col++ )
638 bool noDataInStack =
false;
639 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
640 int cellValueStackSize = cellValues.size();
642 if ( noDataInStack && !mIgnoreNoData )
644 outputBlock->setValue( row, col, mNoDataValue );
646 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
650 case QgsRasterAnalysisUtils::InterpolatedPercentRankInc:
651 result = QgsRasterAnalysisUtils::interpolatedPercentRankInc( cellValues, cellValueStackSize, mValue, mNoDataValue );
653 case QgsRasterAnalysisUtils::InterpolatedPercentRankExc:
654 result = QgsRasterAnalysisUtils::interpolatedPercentRankExc( cellValues, cellValueStackSize, mValue, mNoDataValue );
657 outputBlock->setValue( row, col, result );
662 outputBlock->setValue( row, col, mNoDataValue );
666 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
668 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
671 mOutputRasterDataProvider->setEditable(
false );
678QString QgsCellStatisticsPercentRankFromRasterAlgorithm::displayName()
const
680 return QObject::tr(
"Cell stack percentrank from raster layer" );
683QString QgsCellStatisticsPercentRankFromRasterAlgorithm::name()
const
685 return QStringLiteral(
"cellstackpercentrankfromrasterlayer" );
688QStringList QgsCellStatisticsPercentRankFromRasterAlgorithm::tags()
const
690 return QObject::tr(
"cell,pixel,statistic,percentrank,rank,percent,value,raster" ).split(
',' );
693QString QgsCellStatisticsPercentRankFromRasterAlgorithm::shortHelpString()
const
695 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 "
696 "and writes them to an output raster.\n\n"
697 "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. "
698 "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"
699 "There are two methods for percentile calculation:"
701 " <li>Inclusive linearly interpolated percent rank (PERCENTRANK.INC)</li>"
702 " <li>Exclusive linearly interpolated percent rank (PERCENTRANK.EXC)</li>"
704 "The linear interpolation method return the unique percent rank for different values. Both interpolation "
705 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
706 "The output raster's extent and resolution is defined by a reference "
707 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
708 "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. "
709 "The output raster data type will always be Float32." );
712QgsCellStatisticsPercentRankFromRasterAlgorithm *QgsCellStatisticsPercentRankFromRasterAlgorithm::createInstance()
const
714 return new QgsCellStatisticsPercentRankFromRasterAlgorithm();
717void QgsCellStatisticsPercentRankFromRasterAlgorithm::addSpecificAlgorithmParams()
720 addParameter(
new QgsProcessingParameterBand( QStringLiteral(
"VALUE_RASTER_BAND" ), QObject::tr(
"Value raster band" ), 1, QStringLiteral(
"VALUE_LAYER" ) ) );
721 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 ) );
727 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentRankMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
729 QgsRasterLayer *inputValueRaster = parameterAsRasterLayer( parameters, QStringLiteral(
"INPUT_VALUE_RASTER" ), context );
730 if ( !inputValueRaster )
735 mValueRasterBand = parameterAsInt( parameters, QStringLiteral(
"VALUE_RASTER_BAND" ), context );
742void QgsCellStatisticsPercentRankFromRasterAlgorithm::processRasterStack(
QgsProcessingFeedback *feedback )
746 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
747 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
748 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
749 mOutputRasterDataProvider->setEditable(
true );
751 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
758 std::unique_ptr<QgsRasterBlock> outputBlock;
759 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
761 std::unique_ptr<QgsRasterBlock> valueBlock( mValueRasterInterface->block( mValueRasterBand, blockExtent, iterCols, iterRows ) );
763 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
764 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
768 for (
int band : i.bands )
772 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
773 inputBlocks.emplace_back( std::move( b ) );
777 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
778 for (
int row = 0; row < iterRows; row++ )
783 for (
int col = 0; col < iterCols; col++ )
785 bool percentRankValueIsNoData =
false;
786 double percentRankValue = valueBlock->valueAndNoData( row, col, percentRankValueIsNoData );
789 bool noDataInStack =
false;
790 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
791 int cellValueStackSize = cellValues.size();
793 if ( noDataInStack && !mIgnoreNoData && !percentRankValueIsNoData )
795 outputBlock->setValue( row, col, mNoDataValue );
797 else if ( !noDataInStack || ( !percentRankValueIsNoData && mIgnoreNoData && cellValueStackSize > 0 ) )
801 case QgsRasterAnalysisUtils::InterpolatedPercentRankInc:
802 result = QgsRasterAnalysisUtils::interpolatedPercentRankInc( cellValues, cellValueStackSize, percentRankValue, mNoDataValue );
804 case QgsRasterAnalysisUtils::InterpolatedPercentRankExc:
805 result = QgsRasterAnalysisUtils::interpolatedPercentRankExc( cellValues, cellValueStackSize, percentRankValue, mNoDataValue );
808 outputBlock->setValue( row, col, result );
813 outputBlock->setValue( row, col, mNoDataValue );
817 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
819 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
822 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...