29 QString QgsRasterFrequencyByComparisonOperatorBase::group()
const
31 return QObject::tr(
"Raster analysis" );
34 QString QgsRasterFrequencyByComparisonOperatorBase::groupId()
const
36 return QStringLiteral(
"rasteranalysis" );
39 void QgsRasterFrequencyByComparisonOperatorBase::initAlgorithm(
const QVariantMap & )
42 addParameter(
new QgsProcessingParameterBand( QStringLiteral(
"INPUT_VALUE_RASTER_BAND" ), QObject::tr(
"Value raster band" ), 1, QStringLiteral(
"INPUT_VALUE_RASTER" ) ) );
50 std::unique_ptr< QgsProcessingParameterNumber > output_nodata_parameter = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral(
"OUTPUT_NODATA_VALUE" ), QObject::tr(
"Output NoData value" ),
QgsProcessingParameterNumber::Double, -9999,
true );
52 addParameter( output_nodata_parameter.release() );
55 QObject::tr(
"Output layer" ) ) );
56 addOutput(
new QgsProcessingOutputNumber( QStringLiteral(
"OCCURRENCE_COUNT" ), QObject::tr(
"Count of value occurrences" ) ) );
57 addOutput(
new QgsProcessingOutputNumber( QStringLiteral(
"FOUND_LOCATIONS_COUNT" ), QObject::tr(
"Count of cells with equal value occurrences" ) ) );
58 addOutput(
new QgsProcessingOutputNumber( QStringLiteral(
"MEAN_FREQUENCY_PER_LOCATION" ), QObject::tr(
"Mean frequency at valid cell locations" ) ) );
68 QgsRasterLayer *inputValueRaster = parameterAsRasterLayer( parameters, QStringLiteral(
"INPUT_VALUE_RASTER" ), context );
69 if ( !inputValueRaster )
72 mInputValueRasterBand = parameterAsInt( parameters, QStringLiteral(
"INPUT_VALUE_RASTER_BAND" ), context );
73 mIgnoreNoData = parameterAsBool( parameters, QStringLiteral(
"IGNORE_NODATA" ), context );
76 mNoDataValue = parameterAsDouble( parameters, QStringLiteral(
"OUTPUT_NODATA_VALUE" ), context );
77 mCrs = inputValueRaster->
crs();
80 mLayerWidth = inputValueRaster->
width();
81 mLayerHeight = inputValueRaster->
height();
82 mExtent = inputValueRaster->
extent();
84 const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral(
"INPUT_RASTERS" ), context );
85 QList< QgsRasterLayer * > rasterLayers;
86 rasterLayers.reserve( layers.count() );
95 QgsRasterAnalysisUtils::RasterLogicInput input;
99 input.interface = input.sourceDataProvider.get();
101 if ( layer->
crs() != mCrs )
103 input.projector = std::make_unique< QgsRasterProjector >();
104 input.projector->setInput( input.sourceDataProvider.get() );
106 input.interface = input.projector.get();
108 mInputs.emplace_back( std::move( input ) );
117 const QString outputFile = parameterAsOutputLayer( parameters, QStringLiteral(
"OUTPUT" ), context );
118 const QFileInfo fi( outputFile );
121 std::unique_ptr< QgsRasterFileWriter > writer = std::make_unique< QgsRasterFileWriter >( outputFile );
122 writer->setOutputProviderKey( QStringLiteral(
"gdal" ) );
123 writer->setOutputFormat( outputFormat );
124 std::unique_ptr<QgsRasterDataProvider > provider( writer->createOneBandRaster(
Qgis::DataType::Int32, mLayerWidth, mLayerHeight, mExtent, mCrs ) );
127 if ( !provider->isValid() )
130 provider->setNoDataValue( 1, mNoDataValue );
131 const qgssize layerSize =
static_cast< qgssize >( mLayerWidth ) *
static_cast< qgssize >( mLayerHeight );
135 const int nbBlocksWidth =
static_cast< int>( std::ceil( 1.0 * mLayerWidth / maxWidth ) );
136 const int nbBlocksHeight =
static_cast< int >( std::ceil( 1.0 * mLayerHeight / maxHeight ) );
137 const int nbBlocks = nbBlocksWidth * nbBlocksHeight;
138 provider->setEditable(
true );
141 iter.startRasterRead( mInputValueRasterBand, mLayerWidth, mLayerHeight, mExtent );
148 unsigned long long occurrenceCount = 0;
149 unsigned long long noDataLocationsCount = 0;
150 std::unique_ptr< QgsRasterBlock > inputBlock;
151 while ( iter.readNextRasterPart( 1, iterCols, iterRows, inputBlock, iterLeft, iterTop, &blockExtent ) )
153 std::vector< std::unique_ptr< QgsRasterBlock > > inputBlocks;
154 for (
const QgsRasterAnalysisUtils::RasterLogicInput &i : mInputs )
158 for (
const int band : i.bands )
162 std::unique_ptr< QgsRasterBlock > b( i.interface->block( band, blockExtent, iterCols, iterRows ) );
163 inputBlocks.emplace_back( std::move( b ) );
167 std::unique_ptr< QgsRasterBlock > outputBlock = std::make_unique<QgsRasterBlock>(
Qgis::DataType::Int32, iterCols, iterRows );
168 feedback->
setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
169 for (
int row = 0; row < iterRows; row++ )
174 for (
int col = 0; col < iterCols; col++ )
176 bool valueRasterCellIsNoData =
false;
177 const double value = inputBlock->valueAndNoData( row, col, valueRasterCellIsNoData );
179 if ( valueRasterCellIsNoData && !mIgnoreNoData )
183 outputBlock->setValue( row, col, mNoDataValue );
184 noDataLocationsCount++;
188 bool noDataInStack =
false;
189 const std::vector<double> cellValues = QgsRasterAnalysisUtils::getCellValuesFromBlockStack( inputBlocks, row, col, noDataInStack );
191 if ( noDataInStack && !mIgnoreNoData )
193 outputBlock->setValue( row, col, mNoDataValue );
194 noDataLocationsCount++;
198 const int frequency = applyComparisonOperator( value, cellValues );
199 outputBlock->setValue( row, col, frequency );
200 occurrenceCount += frequency;
205 provider->writeBlock( outputBlock.get(), 1, iterLeft, iterTop );
207 provider->setEditable(
false );
209 const unsigned long long foundLocationsCount = layerSize - noDataLocationsCount;
210 const double meanEqualCountPerValidLocation =
static_cast<double>( occurrenceCount ) /
static_cast<double>( foundLocationsCount * mInputs.size() );
213 outputs.insert( QStringLiteral(
"OCCURRENCE_COUNT" ), occurrenceCount );
214 outputs.insert( QStringLiteral(
"FOUND_LOCATIONS_COUNT" ), foundLocationsCount );
215 outputs.insert( QStringLiteral(
"MEAN_FREQUENCY_PER_LOCATION" ), meanEqualCountPerValidLocation );
216 outputs.insert( QStringLiteral(
"EXTENT" ), mExtent.toString() );
217 outputs.insert( QStringLiteral(
"CRS_AUTHID" ), mCrs.authid() );
218 outputs.insert( QStringLiteral(
"WIDTH_IN_PIXELS" ), mLayerWidth );
219 outputs.insert( QStringLiteral(
"HEIGHT_IN_PIXELS" ), mLayerHeight );
220 outputs.insert( QStringLiteral(
"TOTAL_PIXEL_COUNT" ), layerSize );
221 outputs.insert( QStringLiteral(
"OUTPUT" ), outputFile );
230 QString QgsRasterFrequencyByEqualOperatorAlgorithm::displayName()
const
232 return QObject::tr(
"Equal to frequency" );
235 QString QgsRasterFrequencyByEqualOperatorAlgorithm::name()
const
237 return QStringLiteral(
"equaltofrequency" );
240 QStringList QgsRasterFrequencyByEqualOperatorAlgorithm::tags()
const
242 return QObject::tr(
"cell,equal,frequency,pixel,stack" ).split(
',' );
245 QString QgsRasterFrequencyByEqualOperatorAlgorithm::shortHelpString()
const
247 return QObject::tr(
"The Equal to frequency algorithm evaluates on a cell-by-cell basis the frequency "
248 "(number of times) the values of an input stack of rasters are equal "
249 "to the value of a value raster. \n "
250 "If multiband rasters are used in the data raster stack, the algorithm will always "
251 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
252 "The input value layer serves as reference layer for the sample layers. "
253 "Any NoData cells in the value raster or the data layer stack will result in a NoData cell "
254 "in the output raster if the ignore NoData parameter is not checked. "
255 "The output NoData value can be set manually. The output rasters extent and resolution "
256 "is defined by the input raster layer and is always of int32 type." );
259 QgsRasterFrequencyByEqualOperatorAlgorithm *QgsRasterFrequencyByEqualOperatorAlgorithm::createInstance()
const
261 return new QgsRasterFrequencyByEqualOperatorAlgorithm();
264 int QgsRasterFrequencyByEqualOperatorAlgorithm::applyComparisonOperator(
double searchValue, std::vector<double> cellValueStack )
266 return static_cast<int>( std::count( cellValueStack.begin(), cellValueStack.end(), searchValue ) );
273 QString QgsRasterFrequencyByGreaterThanOperatorAlgorithm::displayName()
const
275 return QObject::tr(
"Greater than frequency" );
278 QString QgsRasterFrequencyByGreaterThanOperatorAlgorithm::name()
const
280 return QStringLiteral(
"greaterthanfrequency" );
283 QStringList QgsRasterFrequencyByGreaterThanOperatorAlgorithm::tags()
const
285 return QObject::tr(
"cell,greater,frequency,pixel,stack" ).split(
',' );
288 QString QgsRasterFrequencyByGreaterThanOperatorAlgorithm::shortHelpString()
const
290 return QObject::tr(
"The Greater than frequency algorithm evaluates on a cell-by-cell basis the frequency "
291 "(number of times) the values of an input stack of rasters are greater than "
292 "the value of a value raster. \n "
293 "If multiband rasters are used in the data raster stack, the algorithm will always "
294 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
295 "The input value layer serves as reference layer for the sample layers. "
296 "Any NoData cells in the value raster or the data layer stack will result in a NoData cell "
297 "in the output raster if the ignore NoData parameter is not checked. "
298 "The output NoData value can be set manually. The output rasters extent and resolution "
299 "is defined by the input raster layer and is always of int32 type." );
302 QgsRasterFrequencyByGreaterThanOperatorAlgorithm *QgsRasterFrequencyByGreaterThanOperatorAlgorithm::createInstance()
const
304 return new QgsRasterFrequencyByGreaterThanOperatorAlgorithm();
307 int QgsRasterFrequencyByGreaterThanOperatorAlgorithm::applyComparisonOperator(
double searchValue, std::vector<double> cellValueStack )
309 return static_cast<int>( std::count_if( cellValueStack.begin(), cellValueStack.end(), [&](
double const & stackValue ) { return stackValue > searchValue; } ) );
316 QString QgsRasterFrequencyByLessThanOperatorAlgorithm::displayName()
const
318 return QObject::tr(
"Less than frequency" );
321 QString QgsRasterFrequencyByLessThanOperatorAlgorithm::name()
const
323 return QStringLiteral(
"lessthanfrequency" );
326 QStringList QgsRasterFrequencyByLessThanOperatorAlgorithm::tags()
const
328 return QObject::tr(
"cell,less,lower,frequency,pixel,stack" ).split(
',' );
331 QString QgsRasterFrequencyByLessThanOperatorAlgorithm::shortHelpString()
const
333 return QObject::tr(
"The Less than frequency algorithm evaluates on a cell-by-cell basis the frequency "
334 "(number of times) the values of an input stack of rasters are less than "
335 "the value of a value raster. \n "
336 "If multiband rasters are used in the data raster stack, the algorithm will always "
337 "perform the analysis on the first band of the rasters - use GDAL to use other bands in the analysis. "
338 "The input value layer serves as reference layer for the sample layers. "
339 "Any NoData cells in the value raster or the data layer stack will result in a NoData cell "
340 "in the output raster if the ignore NoData parameter is not checked. "
341 "The output NoData value can be set manually. The output rasters extent and resolution "
342 "is defined by the input raster layer and is always of int32 type." );
345 QgsRasterFrequencyByLessThanOperatorAlgorithm *QgsRasterFrequencyByLessThanOperatorAlgorithm::createInstance()
const
347 return new QgsRasterFrequencyByLessThanOperatorAlgorithm();
350 int QgsRasterFrequencyByLessThanOperatorAlgorithm::applyComparisonOperator(
double searchValue, std::vector<double> cellValueStack )
352 return static_cast<int>( std::count_if( cellValueStack.begin(), cellValueStack.end(), [&](
double const & stackValue ) { return stackValue < searchValue; } ) );