27QString QgsCellStatisticsAlgorithmBase::group()
const
29 return QObject::tr(
"Raster analysis" );
32QString QgsCellStatisticsAlgorithmBase::groupId()
const
34 return QStringLiteral(
"rasteranalysis" );
37void QgsCellStatisticsAlgorithmBase::initAlgorithm(
const QVariantMap & )
41 addSpecificAlgorithmParams();
47 auto output_nodata_parameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral(
"OUTPUT_NODATA_VALUE" ), QObject::tr(
"Output NoData value" ),
Qgis::ProcessingNumberParameterType::Double, -9999,
false );
49 addParameter( output_nodata_parameter.release() );
53 auto createOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATE_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
54 createOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
56 addParameter( createOptsParam.release() );
58 auto creationOptsParam = std::make_unique<QgsProcessingParameterString>( QStringLiteral(
"CREATION_OPTIONS" ), QObject::tr(
"Creation options" ), QVariant(),
false,
true );
59 creationOptsParam->setMetadata( QVariantMap( { { QStringLiteral(
"widget_wrapper" ), QVariantMap( { { QStringLiteral(
"widget_type" ), QStringLiteral(
"rasteroptions" ) } } ) } } ) );
61 addParameter( creationOptsParam.release() );
74 QgsRasterLayer *referenceLayer = parameterAsRasterLayer( parameters, QStringLiteral(
"REFERENCE_LAYER" ), context );
75 if ( !referenceLayer )
78 mIgnoreNoData = parameterAsBool( parameters, QStringLiteral(
"IGNORE_NODATA" ), context );
79 mNoDataValue = parameterAsDouble( parameters, QStringLiteral(
"OUTPUT_NODATA_VALUE" ), context );
80 mCrs = referenceLayer->
crs();
83 mLayerWidth = referenceLayer->
width();
84 mLayerHeight = referenceLayer->
height();
85 mExtent = referenceLayer->
extent();
87 const QList<QgsMapLayer *> layers = parameterAsLayerList( parameters, QStringLiteral(
"INPUT" ), context );
88 QList<QgsRasterLayer *> rasterLayers;
89 rasterLayers.reserve( layers.count() );
98 QgsRasterAnalysisUtils::RasterLogicInput input;
102 input.interface = input.sourceDataProvider.get();
104 if ( layer->
crs() != mCrs )
106 input.projector = std::make_unique<QgsRasterProjector>();
107 input.projector->setInput( input.sourceDataProvider.get() );
109 input.interface = input.projector.get();
111 mInputs.emplace_back( std::move( input ) );
118 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
120 for (
int band : i.bands )
123 if (
static_cast<int>( mDataType ) <
static_cast<int>( inputDataType ) )
124 mDataType = inputDataType;
128 prepareSpecificAlgorithmParameters( parameters, context, feedback );
136 QString creationOptions = parameterAsString( parameters, QStringLiteral(
"CREATION_OPTIONS" ), context ).trimmed();
138 const QString optionsString = parameterAsString( parameters, QStringLiteral(
"CREATE_OPTIONS" ), context );
139 if ( !optionsString.isEmpty() )
140 creationOptions = optionsString;
142 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
143 QFileInfo fi( outputFile );
146 auto writer = std::make_unique<QgsRasterFileWriter>( outputFile );
147 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
148 if ( !creationOptions.isEmpty() )
150 writer->setCreationOptions( creationOptions.split(
'|' ) );
152 writer->setOutputFormat( outputFormat );
153 mOutputRasterDataProvider.reset( writer->createOneBandRaster( mDataType, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
154 if ( !mOutputRasterDataProvider )
156 if ( !mOutputRasterDataProvider->isValid() )
159 mOutputRasterDataProvider->setNoDataValue( 1, mNoDataValue );
163 processRasterStack( feedback );
165 mOutputRasterDataProvider.reset();
168 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
169 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
170 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
171 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
172 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
173 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
182QString QgsCellStatisticsAlgorithm::displayName()
const
184 return QObject::tr(
"Cell statistics" );
187QString QgsCellStatisticsAlgorithm::name()
const
189 return QStringLiteral(
"cellstatistics" );
192QStringList QgsCellStatisticsAlgorithm::tags()
const
194 return QObject::tr(
"cell,pixel,statistic,count,mean,sum,majority,minority,variance,variety,range,median,minimum,maximum" ).split(
',' );
197QString QgsCellStatisticsAlgorithm::shortHelpString()
const
199 return QObject::tr(
"The Cell statistics algorithm computes a value for each cell of the "
200 "output raster. At each cell location, "
201 "the output value is defined as a function of all overlaid cell values of the "
203 "The output raster's extent and resolution is defined by a reference "
204 "raster. The following functions can be applied on the input "
205 "raster cells per output raster cell location:\n"
211 " <li>Standard deviation</li>"
215 " <li>Minority (least frequent value)</li>"
216 " <li>Majority (most frequent value)</li>"
217 " <li>Range (max-min)</li>"
218 " <li>Variety (count of unique values)</li>"
220 "Input raster layers that do not match the cell size of the reference raster layer will be "
221 "resampled using nearest neighbor resampling. The output raster data type will be set to "
222 "the most complex data type present in the input datasets except when using the functions "
223 "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"
224 "<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"
225 "<i>Calculation details - Count:</i> Count will always result in the number of cells without NoData values at the current cell location.\n"
226 "<i>Calculation details - Median:</i> If the number of input layers is even, the median will be calculated as the "
227 "arithmetic mean of the two middle values of the ordered cell input values. In this case the output data type is Float32.\n"
228 "<i>Calculation details - Minority/Majority:</i> If no unique minority or majority could be found, the result is NoData, except all "
229 "input cell values are equal." );
232QString QgsCellStatisticsAlgorithm::shortDescription()
const
234 return QObject::tr(
"Generates a raster whose cell values are computed from overlaid cell values of the input rasters." );
237QgsCellStatisticsAlgorithm *QgsCellStatisticsAlgorithm::createInstance()
const
239 return new QgsCellStatisticsAlgorithm();
242void QgsCellStatisticsAlgorithm::addSpecificAlgorithmParams()
244 QStringList statistics = QStringList();
245 statistics << QObject::tr(
"Sum" )
246 << QObject::tr(
"Count" )
247 << QObject::tr(
"Mean" )
248 << QObject::tr(
"Median" )
249 << QObject::tr(
"Standard deviation" )
250 << QObject::tr(
"Variance" )
251 << QObject::tr(
"Minimum" )
252 << QObject::tr(
"Maximum" )
253 << QObject::tr(
"Minority" )
254 << QObject::tr(
"Majority" )
255 << QObject::tr(
"Range" )
256 << QObject::tr(
"Variety" );
258 addParameter(
new QgsProcessingParameterEnum( QStringLiteral(
"STATISTIC" ), QObject::tr(
"Statistic" ), statistics,
false, 0,
false ) );
265 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValueStatisticMethods
>( parameterAsEnum( parameters, QStringLiteral(
"STATISTIC" ), context ) );
269 mMethod == QgsRasterAnalysisUtils::Mean || mMethod == QgsRasterAnalysisUtils::StandardDeviation || mMethod == QgsRasterAnalysisUtils::Variance || ( mMethod == QgsRasterAnalysisUtils::Median && ( mInputs.size() % 2 == 0 ) )
272 if (
static_cast<int>( mDataType ) < 6 )
275 else if ( mMethod == QgsRasterAnalysisUtils::Count || mMethod == QgsRasterAnalysisUtils::Variety )
277 if (
static_cast<int>( mDataType ) > 5 )
287 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
288 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
289 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
290 mOutputRasterDataProvider->setEditable(
true );
292 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
299 std::unique_ptr<QgsRasterBlock> outputBlock;
300 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
302 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
303 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
307 for (
int band : i.bands )
311 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
312 inputBlocks.emplace_back( std::move( b ) );
316 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
317 for (
int row = 0; row < iterRows; row++ )
322 for (
int col = 0; col < iterCols; col++ )
325 bool noDataInStack =
false;
326 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
327 int cellValueStackSize = cellValues.size();
329 if ( noDataInStack && !mIgnoreNoData )
333 if ( mMethod == QgsRasterAnalysisUtils::Count )
334 outputBlock->setValue( row, col, cellValueStackSize );
337 outputBlock->setValue( row, col, mNoDataValue );
340 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
344 case QgsRasterAnalysisUtils::Sum:
345 result = std::accumulate( cellValues.begin(), cellValues.end(), 0.0 );
347 case QgsRasterAnalysisUtils::Count:
348 result = cellValueStackSize;
350 case QgsRasterAnalysisUtils::Mean:
351 result = QgsRasterAnalysisUtils::meanFromCellValues( cellValues, cellValueStackSize );
353 case QgsRasterAnalysisUtils::Median:
354 result = QgsRasterAnalysisUtils::medianFromCellValues( cellValues, cellValueStackSize );
356 case QgsRasterAnalysisUtils::StandardDeviation:
357 result = QgsRasterAnalysisUtils::stddevFromCellValues( cellValues, cellValueStackSize );
359 case QgsRasterAnalysisUtils::Variance:
360 result = QgsRasterAnalysisUtils::varianceFromCellValues( cellValues, cellValueStackSize );
362 case QgsRasterAnalysisUtils::Minimum:
363 result = QgsRasterAnalysisUtils::minimumFromCellValues( cellValues );
365 case QgsRasterAnalysisUtils::Maximum:
366 result = QgsRasterAnalysisUtils::maximumFromCellValues( cellValues );
368 case QgsRasterAnalysisUtils::Minority:
369 result = QgsRasterAnalysisUtils::minorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
371 case QgsRasterAnalysisUtils::Majority:
372 result = QgsRasterAnalysisUtils::majorityFromCellValues( cellValues, mNoDataValue, cellValueStackSize );
374 case QgsRasterAnalysisUtils::Range:
375 result = QgsRasterAnalysisUtils::rangeFromCellValues( cellValues );
377 case QgsRasterAnalysisUtils::Variety:
378 result = QgsRasterAnalysisUtils::varietyFromCellValues( cellValues );
381 outputBlock->setValue( row, col, result );
386 outputBlock->setValue( row, col, mNoDataValue );
390 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
392 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
395 mOutputRasterDataProvider->setEditable(
false );
401QString QgsCellStatisticsPercentileAlgorithm::displayName()
const
403 return QObject::tr(
"Cell stack percentile" );
406QString QgsCellStatisticsPercentileAlgorithm::name()
const
408 return QStringLiteral(
"cellstackpercentile" );
411QStringList QgsCellStatisticsPercentileAlgorithm::tags()
const
413 return QObject::tr(
"cell,pixel,statistic,percentile,quantile,quartile" ).split(
',' );
416QString QgsCellStatisticsPercentileAlgorithm::shortHelpString()
const
418 return QObject::tr(
"This algorithm generates a raster containing the cell-wise percentile value of a stack of input rasters. "
419 "The percentile to return is determined by the percentile input value (ranges between 0 and 1). "
420 "At each cell location, the specified percentile is obtained using the respective value from "
421 "the stack of all overlaid and sorted cell values of the input rasters.\n\n"
422 "There are three methods for percentile calculation:"
424 " <li>Nearest rank</li>"
425 " <li>Inclusive linear interpolation (PERCENTILE.INC)</li>"
426 " <li>Exclusive linear interpolation (PERCENTILE.EXC)</li>"
428 "While the output value can stay the same for the nearest rank method (obtains the value that is nearest to the "
429 "specified percentile), the linear interpolation method return unique values for different percentiles. Both interpolation "
430 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
431 "The output raster's extent and resolution is defined by a reference "
432 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
433 "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. "
434 "The output raster data type will be set to the most complex data type present in the input datasets. " );
437QString QgsCellStatisticsPercentileAlgorithm::shortDescription()
const
439 return QObject::tr(
"Generates a raster containing the cell-wise percentile value of a stack of input rasters." );
442QgsCellStatisticsPercentileAlgorithm *QgsCellStatisticsPercentileAlgorithm::createInstance()
const
444 return new QgsCellStatisticsPercentileAlgorithm();
447void QgsCellStatisticsPercentileAlgorithm::addSpecificAlgorithmParams()
449 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 ) );
456 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentileMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
457 mPercentile = parameterAsDouble( parameters, QStringLiteral(
"PERCENTILE" ), context );
461 if ( mMethod != QgsRasterAnalysisUtils::CellValuePercentileMethods::NearestRankPercentile &&
static_cast<int>( mDataType ) < 6 )
471 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
472 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
473 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
474 mOutputRasterDataProvider->setEditable(
true );
476 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
483 std::unique_ptr<QgsRasterBlock> outputBlock;
484 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
486 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
487 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
491 for (
int band : i.bands )
495 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
496 inputBlocks.emplace_back( std::move( b ) );
500 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
501 for (
int row = 0; row < iterRows; row++ )
506 for (
int col = 0; col < iterCols; col++ )
509 bool noDataInStack =
false;
510 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
511 int cellValueStackSize = cellValues.size();
513 if ( noDataInStack && !mIgnoreNoData )
515 outputBlock->setValue( row, col, mNoDataValue );
517 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
521 case QgsRasterAnalysisUtils::NearestRankPercentile:
522 result = QgsRasterAnalysisUtils::nearestRankPercentile( cellValues, cellValueStackSize, mPercentile );
524 case QgsRasterAnalysisUtils::InterpolatedPercentileInc:
525 result = QgsRasterAnalysisUtils::interpolatedPercentileInc( cellValues, cellValueStackSize, mPercentile );
527 case QgsRasterAnalysisUtils::InterpolatedPercentileExc:
528 result = QgsRasterAnalysisUtils::interpolatedPercentileExc( cellValues, cellValueStackSize, mPercentile, mNoDataValue );
531 outputBlock->setValue( row, col, result );
536 outputBlock->setValue( row, col, mNoDataValue );
540 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
542 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
545 mOutputRasterDataProvider->setEditable(
false );
551QString QgsCellStatisticsPercentRankFromValueAlgorithm::displayName()
const
553 return QObject::tr(
"Cell stack percent rank from value" );
556QString QgsCellStatisticsPercentRankFromValueAlgorithm::name()
const
558 return QStringLiteral(
"cellstackpercentrankfromvalue" );
561QStringList QgsCellStatisticsPercentRankFromValueAlgorithm::tags()
const
563 return QObject::tr(
"cell,pixel,statistic,percentrank,rank,percent,value" ).split(
',' );
566QString QgsCellStatisticsPercentRankFromValueAlgorithm::shortHelpString()
const
568 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"
569 "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. "
570 "For values outside of the stack value distribution, the algorithm returns NoData because the value cannot be ranked among the cell values.\n\n"
571 "There are two methods for percentile calculation:"
573 " <li>Inclusive linearly interpolated percent rank (PERCENTRANK.INC)</li>"
574 " <li>Exclusive linearly interpolated percent rank (PERCENTRANK.EXC)</li>"
576 "The linear interpolation method return the unique percent rank for different values. Both interpolation "
577 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
578 "The output raster's extent and resolution is defined by a reference "
579 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
580 "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. "
581 "The output raster data type will always be Float32." );
584QString QgsCellStatisticsPercentRankFromValueAlgorithm::shortDescription()
const
586 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." );
589QgsCellStatisticsPercentRankFromValueAlgorithm *QgsCellStatisticsPercentRankFromValueAlgorithm::createInstance()
const
591 return new QgsCellStatisticsPercentRankFromValueAlgorithm();
594void QgsCellStatisticsPercentRankFromValueAlgorithm::addSpecificAlgorithmParams()
596 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 ) );
603 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentRankMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
604 mValue = parameterAsDouble( parameters, QStringLiteral(
"VALUE" ), context );
611void QgsCellStatisticsPercentRankFromValueAlgorithm::processRasterStack(
QgsProcessingFeedback *feedback )
615 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
616 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
617 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
618 mOutputRasterDataProvider->setEditable(
true );
620 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
627 std::unique_ptr<QgsRasterBlock> outputBlock;
628 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
630 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
631 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
635 for (
int band : i.bands )
639 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
640 inputBlocks.emplace_back( std::move( b ) );
644 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
645 for (
int row = 0; row < iterRows; row++ )
650 for (
int col = 0; col < iterCols; col++ )
653 bool noDataInStack =
false;
654 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
655 int cellValueStackSize = cellValues.size();
657 if ( noDataInStack && !mIgnoreNoData )
659 outputBlock->setValue( row, col, mNoDataValue );
661 else if ( !noDataInStack || ( mIgnoreNoData && cellValueStackSize > 0 ) )
665 case QgsRasterAnalysisUtils::InterpolatedPercentRankInc:
666 result = QgsRasterAnalysisUtils::interpolatedPercentRankInc( cellValues, cellValueStackSize, mValue, mNoDataValue );
668 case QgsRasterAnalysisUtils::InterpolatedPercentRankExc:
669 result = QgsRasterAnalysisUtils::interpolatedPercentRankExc( cellValues, cellValueStackSize, mValue, mNoDataValue );
672 outputBlock->setValue( row, col, result );
677 outputBlock->setValue( row, col, mNoDataValue );
681 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
683 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
686 mOutputRasterDataProvider->setEditable(
false );
693QString QgsCellStatisticsPercentRankFromRasterAlgorithm::displayName()
const
695 return QObject::tr(
"Cell stack percentrank from raster layer" );
698QString QgsCellStatisticsPercentRankFromRasterAlgorithm::name()
const
700 return QStringLiteral(
"cellstackpercentrankfromrasterlayer" );
703QStringList QgsCellStatisticsPercentRankFromRasterAlgorithm::tags()
const
705 return QObject::tr(
"cell,pixel,statistic,percentrank,rank,percent,value,raster" ).split(
',' );
708QString QgsCellStatisticsPercentRankFromRasterAlgorithm::shortHelpString()
const
710 return QObject::tr(
"This algorithm generates a raster containing the cell-wise percent rank value of a stack of input rasters "
711 "based on an input value raster.\n\n"
712 "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. "
713 "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"
714 "There are two methods for percentile calculation:"
716 " <li>Inclusive linearly interpolated percent rank (PERCENTRANK.INC)</li>"
717 " <li>Exclusive linearly interpolated percent rank (PERCENTRANK.EXC)</li>"
719 "The linear interpolation method return the unique percent rank for different values. Both interpolation "
720 "methods follow their counterpart methods implemented by LibreOffice or Microsoft Excel. \n\n"
721 "The output raster's extent and resolution is defined by a reference "
722 "raster. If the input raster layers that do not match the cell size of the reference raster layer will be "
723 "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. "
724 "The output raster data type will always be Float32." );
727QString QgsCellStatisticsPercentRankFromRasterAlgorithm::shortDescription()
const
729 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." );
732QgsCellStatisticsPercentRankFromRasterAlgorithm *QgsCellStatisticsPercentRankFromRasterAlgorithm::createInstance()
const
734 return new QgsCellStatisticsPercentRankFromRasterAlgorithm();
737void QgsCellStatisticsPercentRankFromRasterAlgorithm::addSpecificAlgorithmParams()
740 addParameter(
new QgsProcessingParameterBand( QStringLiteral(
"VALUE_RASTER_BAND" ), QObject::tr(
"Value raster band" ), 1, QStringLiteral(
"VALUE_LAYER" ) ) );
741 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 ) );
747 mMethod =
static_cast<QgsRasterAnalysisUtils::CellValuePercentRankMethods
>( parameterAsEnum( parameters, QStringLiteral(
"METHOD" ), context ) );
749 QgsRasterLayer *inputValueRaster = parameterAsRasterLayer( parameters, QStringLiteral(
"INPUT_VALUE_RASTER" ), context );
750 if ( !inputValueRaster )
755 mValueRasterBand = parameterAsInt( parameters, QStringLiteral(
"VALUE_RASTER_BAND" ), context );
762void QgsCellStatisticsPercentRankFromRasterAlgorithm::processRasterStack(
QgsProcessingFeedback *feedback )
766 int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
767 int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
768 int nbBlocks = nbBlocksWidth * nbBlocksHeight;
769 mOutputRasterDataProvider->setEditable(
true );
771 outputIter.startRasterRead( 1, mLayerWidth, mLayerHeight, mExtent );
778 std::unique_ptr<QgsRasterBlock> outputBlock;
779 while ( outputIter.readNextRasterPart( 1, iterCols, iterRows, outputBlock, iterLeft, iterTop, &blockExtent ) )
781 std::unique_ptr<QgsRasterBlock> valueBlock( mValueRasterInterface->block( mValueRasterBand, blockExtent, iterCols, iterRows ) );
783 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
784 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : std::as_const( mInputs ) )
788 for (
int band : i.bands )
792 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
793 inputBlocks.emplace_back( std::move( b ) );
797 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
798 for (
int row = 0; row < iterRows; row++ )
803 for (
int col = 0; col < iterCols; col++ )
805 bool percentRankValueIsNoData =
false;
806 double percentRankValue = valueBlock->valueAndNoData( row, col, percentRankValueIsNoData );
809 bool noDataInStack =
false;
810 std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
811 int cellValueStackSize = cellValues.size();
813 if ( noDataInStack && !mIgnoreNoData && !percentRankValueIsNoData )
815 outputBlock->setValue( row, col, mNoDataValue );
817 else if ( !noDataInStack || ( !percentRankValueIsNoData && mIgnoreNoData && cellValueStackSize > 0 ) )
821 case QgsRasterAnalysisUtils::InterpolatedPercentRankInc:
822 result = QgsRasterAnalysisUtils::interpolatedPercentRankInc( cellValues, cellValueStackSize, percentRankValue, mNoDataValue );
824 case QgsRasterAnalysisUtils::InterpolatedPercentRankExc:
825 result = QgsRasterAnalysisUtils::interpolatedPercentRankExc( cellValues, cellValueStackSize, percentRankValue, mNoDataValue );
828 outputBlock->setValue( row, col, result );
833 outputBlock->setValue( row, col, mNoDataValue );
837 if ( !mOutputRasterDataProvider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
839 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( mOutputRasterDataProvider->error().summary() ) );
842 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...