Stats/histogram removed from raster layer

This commit is contained in:
Radim Blazek 2012-07-27 11:48:09 +02:00
parent 35e53702dd
commit de20264c31
15 changed files with 110 additions and 100 deletions

View File

@ -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;
@ -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
@ -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
@ -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/ );
@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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,

View File

@ -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.
@ -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
{

View File

@ -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 ) );
@ -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 )
@ -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 )
@ -934,6 +936,7 @@ bool QgsRasterLayer::hasStatistics( int theBandNo )
return false;
}
}
*/
/**
* @param thePoint the QgsPoint for which to obtain pixel values
@ -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" );
@ -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" );
@ -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() )

View File

@ -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
@ -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 );
@ -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 */

View File

@ -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;

View File

@ -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 );

View File

@ -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;
}
@ -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 );

View File

@ -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;

View File

@ -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;

View File

@ -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 )
@ -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 ) );

View File

@ -238,12 +238,10 @@ class QgsGdalProvider : public QgsRasterDataProvider
QStringList subLayers() const;
static QStringList subLayers( GDALDatasetH dataset );
/** \brief If the provider supports it, return band stats for the
given band.
@note added in QGIS 1.7
@note overloads virtual method from QgsRasterProvider::bandStatistics
bool hasStatistics( int theBandNo,
const QgsRectangle & theExtent = QgsRectangle(),
int theSampleSize = 0 );
*/
QgsRasterBandStats bandStatistics( int theBandNo,
const QgsRectangle & theExtent = QgsRectangle(),
int theSampleSize = 0 );

View File

@ -187,19 +187,20 @@ void TestQgsRasterLayer::checkDimensions()
QVERIFY( mpRasterLayer->height() == 10 );
// regression check for ticket #832
// note bandStatistics call is base 1
QVERIFY( mpRasterLayer->bandStatistics( 1 ).elementCount == 100 );
QVERIFY( mpRasterLayer->dataProvider()->bandStatistics( 1 ).elementCount == 100 );
mReport += "<h2>Check Dimensions</h2>\n";
mReport += "<p>Passed</p>";
}
void TestQgsRasterLayer::checkStats()
{
QgsRasterBandStats myStatistics = mpRasterLayer->dataProvider()->bandStatistics( 1 );
QVERIFY( mpRasterLayer->width() == 10 );
QVERIFY( mpRasterLayer->height() == 10 );
QVERIFY( mpRasterLayer->bandStatistics( 1 ).elementCount == 100 );
QVERIFY( mpRasterLayer->bandStatistics( 1 ).minimumValue == 0 );
QVERIFY( mpRasterLayer->bandStatistics( 1 ).maximumValue == 9 );
QVERIFY( mpRasterLayer->bandStatistics( 1 ).mean == 4.5 );
QVERIFY( fabs( mpRasterLayer->bandStatistics( 1 ).stdDev - 2.87228132326901431 )
QVERIFY( myStatistics.elementCount == 100 );
QVERIFY( myStatistics.minimumValue == 0 );
QVERIFY( myStatistics.maximumValue == 9 );
QVERIFY( myStatistics.mean == 4.5 );
QVERIFY( fabs( myStatistics.stdDev - 2.87228132326901431 )
< 0.0000000000000001 );
mReport += "<h2>Check Stats</h2>\n";
mReport += "<p>Passed</p>";