Skip to content

Commit

Permalink
Stats/histogram removed from raster layer
Browse files Browse the repository at this point in the history
  • Loading branch information
blazek committed Jul 27, 2012
1 parent 35e5370 commit de20264
Show file tree
Hide file tree
Showing 15 changed files with 110 additions and 100 deletions.
21 changes: 0 additions & 21 deletions python/core/qgsrasterlayer.sip
Expand Up @@ -162,9 +162,6 @@ public:
/** \brief Accessor that returns the height of the (unclipped) raster */
int height();

/** \brief Accessor to find out whether the histogram should be inverted */
//bool invertHistogram() const; //removed with raster redesign

/** \brief Is the NoDataValue Valid */
bool isNoDataValueValid() const;

Expand Down Expand Up @@ -198,9 +195,6 @@ public:
/** \brief Mutator for mGrayMinimumMaximumEstimated */
//void setGrayMinimumMaximumEstimated( bool theBool ); //removed with raster redesign

/** \brief Mutator to alter the state of the invert histogram flag */
//void setInvertHistogram( bool theFlag ); //removed with raster redesign

/** \brief Mutator for mRGBMinimumMaximumEstimated */
//void setRGBMinimumMaximumEstimated( bool theBool ); //removed with raster redesign

Expand Down Expand Up @@ -249,12 +243,6 @@ public:
* If no matching band is found zero will be returned! */
int bandNumber( const QString & theBandName );

/** \brief Get RasterBandStats for a band given its number (read only) */
const QgsRasterBandStats bandStatistics( int );

/** \brief Get RasterBandStats for a band given its name (read only) */
const QgsRasterBandStats bandStatistics( const QString & );

/** \brief Accessor for ths raster layers pyramid list. A pyramid list defines the
* POTENTIAL pyramids that can be in a raster. To know which of the pyramid layers
* ACTUALLY exists you need to look at the existsFlag member in each struct stored in the
Expand Down Expand Up @@ -322,9 +310,6 @@ public:
/** \brief Checks if symbology is the same as another layers */
bool hasCompatibleSymbology( const QgsMapLayer& theOther ) const;

/** \brief Check whether a given band number has stats associated with it */
bool hasStatistics( int theBandNoInt );

/** \brief Identify raster value(s) found on the point position */
bool identify( const QgsPoint & point, QMap<QString, QString>& results /Out/ );

Expand Down Expand Up @@ -489,12 +474,6 @@ public:
const QString & theResamplingMethod = "NEAREST",
bool theTryInternalFlag = false );

/** \brief Populate the histogram vector for a given band */
void populateHistogram( int theBandNoInt,
int theBinCountInt = 256,
bool theIgnoreOutOfRangeFlag = true,
bool theThoroughBandScanFlag = false );

void showStatusMessage( const QString & theMessage );

/** \brief Propagate progress updates from GDAL up to the parent app */
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgisapp.cpp
Expand Up @@ -5581,7 +5581,7 @@ QgsContrastEnhancement* QgisApp::rasterContrastEnhancement( QgsRasterLayer* rlay
}
else
{
QgsRasterBandStats rasterBandStats = rlayer->bandStatistics( band );
QgsRasterBandStats rasterBandStats = rlayer->dataProvider()->bandStatistics( band );
minValue = rasterBandStats.minimumValue;
maxValue = rasterBandStats.maximumValue;
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsprojectfiletransform.cpp
Expand Up @@ -590,7 +590,7 @@ void QgsProjectFileTransform::convertRasterProperties( QDomDocument& doc, QDomNo
newColorRampShaderElem.setAttribute( "colorRampType", "INTERPOLATED" );

//get minmax from rasterlayer
QgsRasterBandStats rasterBandStats = rlayer->bandStatistics( grayBand );
QgsRasterBandStats rasterBandStats = rlayer->dataProvider()->bandStatistics( grayBand );
double minValue = rasterBandStats.minimumValue;
double maxValue = rasterBandStats.maximumValue;
double breakSize = ( maxValue - minValue ) / 3;
Expand Down
20 changes: 20 additions & 0 deletions src/core/qgsrasterdataprovider.cpp
Expand Up @@ -473,6 +473,26 @@ QgsRasterBandStats QgsRasterDataProvider::statisticsDefaults( int theBandNo,
return myRasterBandStats;
}

bool QgsRasterDataProvider::hasStatistics( int theBandNo,
const QgsRectangle & theExtent,
int theSampleSize )
{
QgsDebugMsg( QString( "theBandNo = %1 theSampleSize = %2" ).arg( theBandNo ).arg( theSampleSize ) );
if ( mStatistics.size() == 0 ) return false;

QgsRasterBandStats myRasterBandStats = statisticsDefaults( theBandNo, theExtent, theSampleSize );

foreach( QgsRasterBandStats stats, mStatistics )
{
if ( stats == myRasterBandStats )
{
QgsDebugMsg( "Has cached statistics." );
return true;
}
}
return false;
}

// Find cached
QgsRasterBandStats QgsRasterDataProvider::bandStatistics( int theBandNo,
const QgsRectangle & theExtent,
Expand Down
25 changes: 5 additions & 20 deletions src/core/qgsrasterdataprovider.h
Expand Up @@ -295,26 +295,6 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
return QStringList();
}

/** \brief test if the requested histogram is already available */

virtual bool hasCachedHistogram( int theBandNoInt, int theBinCountInt = RASTER_HISTOGRAM_BINS )
{
Q_UNUSED( theBandNoInt ); Q_UNUSED( theBinCountInt ); return false;
}

/** \brief Populate the histogram vector for a given band */

virtual void populateHistogram( int theBandNoInt,
QgsRasterBandStats & theBandStats,
int theBinCountInt = RASTER_HISTOGRAM_BINS,
bool theIgnoreOutOfRangeFlag = true,
bool theThoroughBandScanFlag = false
)
{
Q_UNUSED( theBandNoInt ); Q_UNUSED( theBandStats ); Q_UNUSED( theBinCountInt );
Q_UNUSED( theIgnoreOutOfRangeFlag ); Q_UNUSED( theThoroughBandScanFlag );
}

/** \brief Get histogram. Histograms are cached in providers.
* @param theBandNo The band (number).
* @param theBinCount Number of bins (intervals,buckets). If 0, the number of bins is decided automaticaly according to data type, raster size etc.
Expand Down Expand Up @@ -371,6 +351,11 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
const QgsRectangle & theExtent = QgsRectangle(),
int theSampleSize = 0 );

/** \brief Returns true if histogram is available (cached, already calculated), the parameters are the same as in histogram() */
virtual bool hasStatistics( int theBandNo,
const QgsRectangle & theExtent = QgsRectangle(),
int theSampleSize = 0 );

/** \brief helper function to create zero padded band names */
QString generateBandName( int theBandNumber ) const
{
Expand Down
30 changes: 6 additions & 24 deletions src/core/raster/qgsrasterlayer.cpp
Expand Up @@ -339,6 +339,7 @@ int QgsRasterLayer::bandNumber( QString const & theBandName ) const
* @sa RasterBandStats
* @note This is a cpu intensive and slow task!
*/
/*
const QgsRasterBandStats QgsRasterLayer::bandStatistics( int theBandNo )
{
QgsDebugMsg( "theBandNo = " + QString::number( theBandNo ) );
Expand Down Expand Up @@ -411,7 +412,7 @@ const QgsRasterBandStats QgsRasterLayer::bandStatistics( QString const & theBand
return QgsRasterBandStats(); // return a null one
}

*/

QString QgsRasterLayer::buildPyramids( RasterPyramidList const & theRasterPyramidList,
QString const & theResamplingMethod, bool theTryInternalFlag )
Expand Down Expand Up @@ -922,6 +923,7 @@ bool QgsRasterLayer::hasCompatibleSymbology( const QgsMapLayer& theOther ) const
* @param theBandNo The number of the band to check
* @return true if statistics have already been build for this band otherwise false
*/
/*
bool QgsRasterLayer::hasStatistics( int theBandNo )
{
if ( theBandNo <= mRasterStatsList.size() && theBandNo > 0 )
Expand All @@ -934,6 +936,7 @@ bool QgsRasterLayer::hasStatistics( int theBandNo )
return false;
}
}
*/

/**
* @param thePoint the QgsPoint for which to obtain pixel values
Expand Down Expand Up @@ -1289,7 +1292,7 @@ QString QgsRasterLayer::metadata()
myMetadata += "</p>\n";

//check if full stats for this layer have already been collected
if ( !hasStatistics( myIteratorInt ) ) //not collected
if ( !dataProvider()->hasStatistics( myIteratorInt ) ) //not collected
{
QgsDebugMsg( ".....no" );

Expand All @@ -1304,7 +1307,7 @@ QString QgsRasterLayer::metadata()
{
QgsDebugMsg( ".....yes" );

QgsRasterBandStats myRasterBandStats = bandStatistics( myIteratorInt );
QgsRasterBandStats myRasterBandStats = dataProvider()->bandStatistics( myIteratorInt );
//Min Val
myMetadata += "<p>";
myMetadata += tr( "Min Val" );
Expand Down Expand Up @@ -1460,27 +1463,6 @@ QPixmap QgsRasterLayer::paletteAsPixmap( int theBandNumber )
}
}

/*
* @param theBandNoInt - which band to find out if has a cached histogram
* @param theBinCountInt - how many 'bins' to categorise the data into
*/
bool QgsRasterLayer::hasCachedHistogram( int theBandNo, int theBinCount )
{
return mDataProvider->hasCachedHistogram( theBandNo, theBinCount );
}

/*
* @param theBandNoInt - which band to compute the histogram for
* @param theBinCountInt - how many 'bins' to categorise the data into
* @param theIgnoreOutOfRangeFlag - whether to ignore values that are out of range (default=true)
* @param theThoroughBandScanFlag - whether to visit each cell when computing the histogram (default=false)
*/
void QgsRasterLayer::populateHistogram( int theBandNo, int theBinCount, bool theIgnoreOutOfRangeFlag, bool theHistogramEstimatedFlag )
{
QgsRasterBandStats myRasterBandStats = bandStatistics( theBandNo );
mDataProvider->populateHistogram( theBandNo, myRasterBandStats, theBinCount, theIgnoreOutOfRangeFlag, theHistogramEstimatedFlag );
}

QString QgsRasterLayer::providerType() const
{
if ( mProviderKey.isEmpty() )
Expand Down
18 changes: 3 additions & 15 deletions src/core/raster/qgsrasterlayer.h
Expand Up @@ -386,10 +386,10 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
int bandNumber( const QString & theBandName ) const;

/** \brief Get RasterBandStats for a band given its number (read only) */
const QgsRasterBandStats bandStatistics( int );
//const QgsRasterBandStats bandStatistics( int );

/** \brief Get RasterBandStats for a band given its name (read only) */
const QgsRasterBandStats bandStatistics( const QString & );
//const QgsRasterBandStats bandStatistics( const QString & );

/** \brief Accessor for ths raster layers pyramid list. A pyramid list defines the
* POTENTIAL pyramids that can be in a raster. To know which of the pyramid layers
Expand Down Expand Up @@ -461,7 +461,7 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
bool hasCompatibleSymbology( const QgsMapLayer& theOther ) const;

/** \brief Check whether a given band number has stats associated with it */
bool hasStatistics( int theBandNoInt );
//bool hasStatistics( int theBandNoInt );

/** \brief Identify raster value(s) found on the point position */
bool identify( const QgsPoint & point, QMap<QString, QString>& results );
Expand Down Expand Up @@ -642,18 +642,6 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
const QString & theResamplingMethod = "NEAREST",
bool theTryInternalFlag = false );

/** \brief test if the requested histogram is already available */

bool hasCachedHistogram( int theBandNoInt,
int theBinCountInt = RASTER_HISTOGRAM_BINS );

/** \brief Populate the histogram vector for a given band */

void populateHistogram( int theBandNoInt,
int theBinCountInt = RASTER_HISTOGRAM_BINS,
bool theIgnoreOutOfRangeFlag = true,
bool theThoroughBandScanFlag = false );

void showStatusMessage( const QString & theMessage );

/** \brief Propagate progress updates from GDAL up to the parent app */
Expand Down
2 changes: 1 addition & 1 deletion src/gui/raster/qgsmultibandcolorrendererwidget.cpp
Expand Up @@ -221,7 +221,7 @@ void QgsMultiBandColorRendererWidget::loadMinMaxValueForBand( int band, QLineEdi
}
else if ( mUseStdDevRadioButton->isChecked() )
{
QgsRasterBandStats rasterBandStats = mRasterLayer->bandStatistics( band );
QgsRasterBandStats rasterBandStats = mRasterLayer->dataProvider()->bandStatistics( band );
double diff = mStdDevSpinBox->value() * rasterBandStats.stdDev;
minMaxValues[0] = rasterBandStats.mean - diff;
minMaxValues[1] = rasterBandStats.mean + diff;
Expand Down
2 changes: 1 addition & 1 deletion src/gui/raster/qgsrasterhistogramwidget.cpp
Expand Up @@ -403,7 +403,7 @@ void QgsRasterHistogramWidget::refreshHistogram()
if ( ! mySelectedBands.contains( myIteratorInt ) )
continue;
}
QgsRasterBandStats myRasterBandStats = mRasterLayer->bandStatistics( myIteratorInt );
QgsRasterBandStats myRasterBandStats = mRasterLayer->dataProvider()->bandStatistics( myIteratorInt );
// mRasterLayer->populateHistogram( myIteratorInt, BINCOUNT, myIgnoreOutOfRangeFlag, myThoroughBandScanFlag );
int sampleSize = 250000; // number of sample cells
QgsRasterHistogram myHistogram = mRasterLayer->dataProvider()->histogram( myIteratorInt, BINCOUNT, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), QgsRectangle(), sampleSize );
Expand Down
4 changes: 2 additions & 2 deletions src/gui/raster/qgsrasterrendererwidget.cpp
Expand Up @@ -67,7 +67,7 @@ bool QgsRasterRendererWidget::bandMinMax( LoadMinMaxAlgo loadAlgo, int band, dou
}
else if ( loadAlgo == Actual )
{
QgsRasterBandStats rasterBandStats = mRasterLayer->bandStatistics( band );
QgsRasterBandStats rasterBandStats = mRasterLayer->dataProvider()->bandStatistics( band );
minMaxValues[0] = rasterBandStats.minimumValue;
minMaxValues[1] = rasterBandStats.maximumValue;
}
Expand Down Expand Up @@ -129,7 +129,7 @@ bool QgsRasterRendererWidget::bandMinMaxFromStdDev( double stdDev, int band, dou
return false;
}

QgsRasterBandStats myRasterBandStats = mRasterLayer->bandStatistics( band );
QgsRasterBandStats myRasterBandStats = mRasterLayer->dataProvider()->bandStatistics( band );
minMaxValues[0] = myRasterBandStats.mean - ( stdDev * myRasterBandStats.stdDev );
minMaxValues[1] = myRasterBandStats.mean + ( stdDev * myRasterBandStats.stdDev );

Expand Down
2 changes: 1 addition & 1 deletion src/gui/raster/qgssinglebandgrayrendererwidget.cpp
Expand Up @@ -104,7 +104,7 @@ void QgsSingleBandGrayRendererWidget::on_mLoadPushButton_clicked()
}
else if ( mUseStdDevRadioButton->isChecked() )
{
QgsRasterBandStats rasterBandStats = mRasterLayer->bandStatistics( band );
QgsRasterBandStats rasterBandStats = mRasterLayer->dataProvider()->bandStatistics( band );
double diff = mStdDevSpinBox->value() * rasterBandStats.stdDev;
minMaxValues[0] = rasterBandStats.mean - diff;
minMaxValues[1] = rasterBandStats.mean + diff;
Expand Down
2 changes: 1 addition & 1 deletion src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp
Expand Up @@ -184,7 +184,7 @@ void QgsSingleBandPseudoColorRendererWidget::on_mClassifyButton_clicked()
}

int bandNr = mBandComboBox->itemData( bandComboIndex ).toInt();
QgsRasterBandStats myRasterBandStats = mRasterLayer->bandStatistics( bandNr );
QgsRasterBandStats myRasterBandStats = mRasterLayer->dataProvider()->bandStatistics( bandNr );
int numberOfEntries = mNumberOfEntriesSpinBox->value();

QList<double> entryValues;
Expand Down
59 changes: 58 additions & 1 deletion src/providers/gdal/qgsgdalprovider.cpp
Expand Up @@ -1267,7 +1267,7 @@ bool QgsGdalProvider::hasHistogram( int theBandNo,
return false;
}

QgsDebugMsg( "Looking for GDAL histogram xxxx" );
QgsDebugMsg( "Looking for GDAL histogram" );

GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
if ( ! myGdalBand )
Expand Down Expand Up @@ -2001,6 +2001,63 @@ QGISEXTERN bool isValidRasterFileName( QString const & theFileNameQString, QStri
}
}

bool QgsGdalProvider::hasStatistics( int theBandNo,
const QgsRectangle & theExtent,
int theSampleSize )
{
QgsDebugMsg( QString( "theBandNo = %1 theSampleSize = %2" ).arg( theBandNo ).arg( theSampleSize ) );

// First check if cached in mStatistics
if ( QgsRasterDataProvider::hasStatistics( theBandNo, theExtent, theSampleSize ) )
{
return true;
}

QgsRasterBandStats myRasterBandStats = statisticsDefaults( theBandNo, theExtent, theSampleSize );

// If not cached, check if supported by GDAL
if ( myRasterBandStats.extent != extent() )
{
QgsDebugMsg( "Not supported by GDAL." );
return false;
}

QgsDebugMsg( "Looking for GDAL statistics" );

GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
if ( ! myGdalBand )
{
return false;
}

int bApproxOK = false;
if ( theSampleSize > 0 )
{
if (( xSize() * ySize() / theSampleSize ) > 2 ) // not perfect
{
bApproxOK = true;
}
}

// Params in GDALGetRasterStatistics must not be NULL otherwise GDAL returns
// without error even if stats are not cached
double pdfMin;
double pdfMax;
double pdfMean;
double pdfStdDev;

// try to fetch the cached stats (bForce=FALSE)
CPLErr myerval = GDALGetRasterStatistics( myGdalBand, bApproxOK, FALSE, &pdfMin, &pdfMax, &pdfMean, &pdfStdDev );

if ( CE_None == myerval ) // CE_Warning if cached not found
{
QgsDebugMsg( "GDAL has cached statistics" );
return true;
}

return false;
}

QgsRasterBandStats QgsGdalProvider::bandStatistics( int theBandNo, const QgsRectangle & theExtent, int theSampleSize )
{
QgsDebugMsg( QString( "theBandNo = %1 theSampleSize = %2" ).arg( theBandNo ).arg( theSampleSize ) );
Expand Down

0 comments on commit de20264

Please sign in to comment.