30QString QgsRasterFrequencyByComparisonOperatorBase::group()
const
32 return QObject::tr(
"Raster analysis" );
35QString QgsRasterFrequencyByComparisonOperatorBase::groupId()
const
37 return QStringLiteral(
"rasteranalysis" );
40void QgsRasterFrequencyByComparisonOperatorBase::initAlgorithm(
const QVariantMap & )
43 addParameter(
new QgsProcessingParameterBand( QStringLiteral(
"INPUT_VALUE_RASTER_BAND" ), QObject::tr(
"Value raster band" ), 1, QStringLiteral(
"INPUT_VALUE_RASTER" ) ) );
47 auto output_nodata_parameter = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral(
"OUTPUT_NODATA_VALUE" ), QObject::tr(
"Output NoData value" ),
Qgis::ProcessingNumberParameterType::Double, -9999,
true );
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() );
64 addOutput(
new QgsProcessingOutputNumber( QStringLiteral(
"OCCURRENCE_COUNT" ), QObject::tr(
"Count of value occurrences" ) ) );
65 addOutput(
new QgsProcessingOutputNumber( QStringLiteral(
"FOUND_LOCATIONS_COUNT" ), QObject::tr(
"Count of cells with equal value occurrences" ) ) );
66 addOutput(
new QgsProcessingOutputNumber( QStringLiteral(
"MEAN_FREQUENCY_PER_LOCATION" ), QObject::tr(
"Mean frequency at valid cell locations" ) ) );
76 QgsRasterLayer *inputValueRaster = parameterAsRasterLayer( parameters, QStringLiteral(
"INPUT_VALUE_RASTER" ), context );
77 if ( !inputValueRaster )
80 mInputValueRasterBand = parameterAsInt( parameters, QStringLiteral(
"INPUT_VALUE_RASTER_BAND" ), context );
81 mIgnoreNoData = parameterAsBool( parameters, QStringLiteral(
"IGNORE_NODATA" ), context );
84 mNoDataValue = parameterAsDouble( parameters, QStringLiteral(
"OUTPUT_NODATA_VALUE" ), context );
85 mCrs = inputValueRaster->
crs();
88 mLayerWidth = inputValueRaster->
width();
89 mLayerHeight = inputValueRaster->
height();
90 mExtent = inputValueRaster->
extent();
92 const QList<QgsMapLayer *> layers = parameterAsLayerList( parameters, QStringLiteral(
"INPUT_RASTERS" ), context );
93 QList<QgsRasterLayer *> rasterLayers;
94 rasterLayers.reserve( layers.count() );
103 QgsRasterAnalysisUtils::RasterLogicInput input;
107 input.interface = input.sourceDataProvider.get();
109 if ( layer->
crs() != mCrs )
111 input.projector = std::make_unique<QgsRasterProjector>();
112 input.projector->setInput( input.sourceDataProvider.get() );
114 input.interface = input.projector.get();
116 mInputs.emplace_back( std::move( input ) );
125 QString creationOptions = parameterAsString( parameters, QStringLiteral(
"CREATION_OPTIONS" ), context ).trimmed();
127 const QString optionsString = parameterAsString( parameters, QStringLiteral(
"CREATE_OPTIONS" ), context );
128 if ( !optionsString.isEmpty() )
129 creationOptions = optionsString;
131 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
132 const QFileInfo fi( outputFile );
135 auto writer = std::make_unique<QgsRasterFileWriter>( outputFile );
136 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
137 if ( !creationOptions.isEmpty() )
139 writer->setCreationOptions( creationOptions.split(
'|' ) );
141 writer->setOutputFormat( outputFormat );
142 std::unique_ptr<QgsRasterDataProvider> provider( writer->createOneBandRaster(
Qgis::DataType::Int32, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
145 if ( !provider->isValid() )
148 provider->setNoDataValue( 1, mNoDataValue );
149 const qgssize layerSize =
static_cast<qgssize>( mLayerWidth ) *
static_cast<qgssize>( mLayerHeight );
153 const int nbBlocksWidth =
static_cast<int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
154 const int nbBlocksHeight =
static_cast<int>( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
155 const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
156 provider->setEditable(
true );
159 iter.startRasterRead( mInputValueRasterBand, mLayerWidth, mLayerHeight, mExtent );
166 unsigned long long occurrenceCount = 0;
167 unsigned long long noDataLocationsCount = 0;
168 std::unique_ptr<QgsRasterBlock> inputBlock;
169 while ( iter.readNextRasterPart( 1, iterCols, iterRows, inputBlock, iterLeft, iterTop, &blockExtent ) )
171 std::vector<std::unique_ptr<QgsRasterBlock>> inputBlocks;
172 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : mInputs )
176 for (
const int band : i.bands )
180 std::unique_ptr<QgsRasterBlock> b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
181 inputBlocks.emplace_back( std::move( b ) );
186 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
187 for (
int row = 0; row < iterRows; row++ )
192 for (
int col = 0; col < iterCols; col++ )
194 bool valueRasterCellIsNoData =
false;
195 const double value = inputBlock->valueAndNoData( row, col, valueRasterCellIsNoData );
197 if ( valueRasterCellIsNoData && !mIgnoreNoData )
201 outputBlock->setValue( row, col, mNoDataValue );
202 noDataLocationsCount++;
206 bool noDataInStack =
false;
207 const std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
209 if ( noDataInStack && !mIgnoreNoData )
211 outputBlock->setValue( row, col, mNoDataValue );
212 noDataLocationsCount++;
216 const int frequency = applyComparisonOperator( value, cellValues );
217 outputBlock->setValue( row, col, frequency );
218 occurrenceCount += frequency;
223 if ( !provider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop ) )
225 throw QgsProcessingException( QObject::tr(
"Could not write raster block: %1" ).arg( provider->error().summary() ) );
228 provider->setEditable(
false );
230 const unsigned long long foundLocationsCount = layerSize - noDataLocationsCount;
231 const double meanEqualCountPerValidLocation =
static_cast<double>( occurrenceCount ) /
static_cast<double>( foundLocationsCount * mInputs.size() );
234 outputs.insert( QStringLiteral(
"OCCURRENCE_COUNT" ), occurrenceCount );
235 outputs.insert( QStringLiteral(
"FOUND_LOCATIONS_COUNT" ), foundLocationsCount );
236 outputs.insert( QStringLiteral(
"MEAN_FREQUENCY_PER_LOCATION" ), meanEqualCountPerValidLocation );
237 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
238 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
239 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
240 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
241 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
242 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
251QString QgsRasterFrequencyByEqualOperatorAlgorithm::displayName()
const
253 return QObject::tr(
"Equal to frequency" );
256QString QgsRasterFrequencyByEqualOperatorAlgorithm::name()
const
258 return QStringLiteral(
"equaltofrequency" );
261QStringList QgsRasterFrequencyByEqualOperatorAlgorithm::tags()
const
263 return QObject::tr(
"cell,equal,frequency,pixel,stack" ).split(
',' );
266QString QgsRasterFrequencyByEqualOperatorAlgorithm::shortHelpString()
const
268 return QObject::tr(
"This algorithm evaluates on a cell-by-cell basis the frequency "
269 "(number of times) the values of an input stack of rasters are equal "
270 "to the value of a value raster. \n "
271 "If multiband rasters are used in the data raster stack, the algorithm will always "
272 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
273 "The input value layer serves as reference layer for the sample layers. "
274 "Any NoData cells in the value raster or the data layer stack will result in a NoData cell "
275 "in the output raster if the ignore NoData parameter is not checked. "
276 "The output NoData value can be set manually. The output rasters extent and resolution "
277 "is defined by the input raster layer and is always of int32 type." );
280QString QgsRasterFrequencyByEqualOperatorAlgorithm::shortDescription()
const
282 return QObject::tr(
"Evaluates on a cell-by-cell basis the frequency (number of times) "
283 "the values of an input stack of rasters are equal to the value of a value raster." );
286QgsRasterFrequencyByEqualOperatorAlgorithm *QgsRasterFrequencyByEqualOperatorAlgorithm::createInstance()
const
288 return new QgsRasterFrequencyByEqualOperatorAlgorithm();
291int QgsRasterFrequencyByEqualOperatorAlgorithm::applyComparisonOperator(
double searchValue, std::vector<double> cellValueStack )
293 return static_cast<int>( std::count( cellValueStack.begin(), cellValueStack.end(), searchValue ) );
300QString QgsRasterFrequencyByGreaterThanOperatorAlgorithm::displayName()
const
302 return QObject::tr(
"Greater than frequency" );
305QString QgsRasterFrequencyByGreaterThanOperatorAlgorithm::name()
const
307 return QStringLiteral(
"greaterthanfrequency" );
310QStringList QgsRasterFrequencyByGreaterThanOperatorAlgorithm::tags()
const
312 return QObject::tr(
"cell,greater,frequency,pixel,stack" ).split(
',' );
315QString QgsRasterFrequencyByGreaterThanOperatorAlgorithm::shortHelpString()
const
317 return QObject::tr(
"This algorithm evaluates on a cell-by-cell basis the frequency "
318 "(number of times) the values of an input stack of rasters are greater than "
319 "the value of a value raster. \n "
320 "If multiband rasters are used in the data raster stack, the algorithm will always "
321 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
322 "The input value layer serves as reference layer for the sample layers. "
323 "Any NoData cells in the value raster or the data layer stack will result in a NoData cell "
324 "in the output raster if the ignore NoData parameter is not checked. "
325 "The output NoData value can be set manually. The output rasters extent and resolution "
326 "is defined by the input raster layer and is always of int32 type." );
329QString QgsRasterFrequencyByGreaterThanOperatorAlgorithm::shortDescription()
const
331 return QObject::tr(
"Evaluates on a cell-by-cell basis the frequency (number of times) "
332 "the values of an input stack of rasters are greater than the value of a value raster." );
335QgsRasterFrequencyByGreaterThanOperatorAlgorithm *QgsRasterFrequencyByGreaterThanOperatorAlgorithm::createInstance()
const
337 return new QgsRasterFrequencyByGreaterThanOperatorAlgorithm();
340int QgsRasterFrequencyByGreaterThanOperatorAlgorithm::applyComparisonOperator(
double searchValue, std::vector<double> cellValueStack )
342 return static_cast<int>( std::count_if( cellValueStack.begin(), cellValueStack.end(), [&](
double const &stackValue ) { return stackValue > searchValue; } ) );
349QString QgsRasterFrequencyByLessThanOperatorAlgorithm::displayName()
const
351 return QObject::tr(
"Less than frequency" );
354QString QgsRasterFrequencyByLessThanOperatorAlgorithm::name()
const
356 return QStringLiteral(
"lessthanfrequency" );
359QStringList QgsRasterFrequencyByLessThanOperatorAlgorithm::tags()
const
361 return QObject::tr(
"cell,less,lower,frequency,pixel,stack" ).split(
',' );
364QString QgsRasterFrequencyByLessThanOperatorAlgorithm::shortHelpString()
const
366 return QObject::tr(
"This algorithm evaluates on a cell-by-cell basis the frequency "
367 "(number of times) the values of an input stack of rasters are less than "
368 "the value of a value raster. \n "
369 "If multiband rasters are used in the data raster stack, the algorithm will always "
370 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
371 "The input value layer serves as reference layer for the sample layers. "
372 "Any NoData cells in the value raster or the data layer stack will result in a NoData cell "
373 "in the output raster if the ignore NoData parameter is not checked. "
374 "The output NoData value can be set manually. The output rasters extent and resolution "
375 "is defined by the input raster layer and is always of int32 type." );
378QString QgsRasterFrequencyByLessThanOperatorAlgorithm::shortDescription()
const
380 return QObject::tr(
"Evaluates on a cell-by-cell basis the frequency (number of times) "
381 "the values of an input stack of rasters are less than the value of a value raster." );
384QgsRasterFrequencyByLessThanOperatorAlgorithm *QgsRasterFrequencyByLessThanOperatorAlgorithm::createInstance()
const
386 return new QgsRasterFrequencyByLessThanOperatorAlgorithm();
389int QgsRasterFrequencyByLessThanOperatorAlgorithm::applyComparisonOperator(
double searchValue, std::vector<double> cellValueStack )
391 return static_cast<int>( std::count_if( cellValueStack.begin(), cellValueStack.end(), [&](
double const &stackValue ) { return stackValue < searchValue; } ) );
@ 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.
A parameter for processing algorithms which accepts multiple map layers.
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...