25 #include <QCryptographicHash> 32 mTabStyle = QStringLiteral(
"border-spacing: 0px; border-width: 1px 1px 0 0; border-style: solid;" );
33 mCellStyle = QStringLiteral(
"border-width: 0 0 1px 1px; border-style: solid; font-size: smaller; text-align: center;" );
34 mOkStyle = QStringLiteral(
"background: #00ff00;" );
35 mErrStyle = QStringLiteral(
"background: #ff0000;" );
36 mErrMsgStyle = QStringLiteral(
"color: #ff0000;" );
40 const QString &expectedKey, QString expectedUri )
43 mReport += QLatin1String(
"\n\n" );
48 if ( !verifiedProvider || !verifiedProvider->
isValid() )
50 error( QStringLiteral(
"Cannot load provider %1 with URI: %2" ).arg( verifiedKey, verifiedUri ), mReport );
56 if ( !expectedProvider || !expectedProvider->
isValid() )
58 error( QStringLiteral(
"Cannot load provider %1 with URI: %2" ).arg( expectedKey, expectedUri ), mReport );
62 if ( !ok )
return false;
64 mReport += QStringLiteral(
"Verified URI: %1<br>" ).arg( verifiedUri.replace(
'&', QLatin1String(
"&" ) ) );
65 mReport += QStringLiteral(
"Expected URI: %1<br>" ).arg( expectedUri.replace(
'&', QLatin1String(
"&" ) ) );
67 mReport += QLatin1String(
"<br>" );
68 mReport += QStringLiteral(
"<table style='%1'>\n" ).arg( mTabStyle );
69 mReport += compareHead();
71 compare( QStringLiteral(
"Band count" ), verifiedProvider->
bandCount(), expectedProvider->
bandCount(), mReport, ok );
73 compare( QStringLiteral(
"Width" ), verifiedProvider->
xSize(), expectedProvider->
xSize(), mReport, ok );
74 compare( QStringLiteral(
"Height" ), verifiedProvider->
ySize(), expectedProvider->
ySize(), mReport, ok );
78 if ( verifiedProvider->
extent() != expectedProvider->
extent() ) ok =
false;
81 mReport += QLatin1String(
"</table>\n" );
83 if ( !ok )
return false;
86 for (
int band = 1; band <= expectedProvider->
bandCount(); band++ )
88 mReport += QStringLiteral(
"<h3>Band %1</h3>\n" ).arg( band );
89 mReport += QStringLiteral(
"<table style='%1'>\n" ).arg( mTabStyle );
90 mReport += compareHead();
94 compare( QStringLiteral(
"Source data type" ), verifiedProvider->
sourceDataType( band ), expectedProvider->
sourceDataType( band ), mReport, typesOk );
95 compare( QStringLiteral(
"Data type" ), verifiedProvider->
dataType( band ), expectedProvider->
dataType( band ), mReport, typesOk );
112 compare( QStringLiteral(
"Minimum value" ), verifiedStats.
minimumValue, expectedStats.
minimumValue, mReport, statsOk, tol );
114 compare( QStringLiteral(
"Maximum value" ), verifiedStats.
maximumValue, expectedStats.
maximumValue, mReport, statsOk, tol );
119 tol = tolerance( expectedStats.
mean );
120 compare( QStringLiteral(
"Mean" ), verifiedStats.
mean, expectedStats.
mean, mReport, statsOk, tol );
123 tol = tolerance( expectedStats.
stdDev, 1 );
124 compare( QStringLiteral(
"Standard deviation" ), verifiedStats.
stdDev, expectedStats.
stdDev, mReport, statsOk, tol );
126 mReport += QLatin1String(
"</table>" );
127 mReport += QLatin1String(
"<br>" );
129 if ( !statsOk || !typesOk || !noDataOk )
135 mReport += QLatin1String(
"<table><tr>" );
136 mReport += QLatin1String(
"<td>Data comparison</td>" );
137 mReport += QStringLiteral(
"<td style='%1 %2 border: 1px solid'>correct value</td>" ).arg( mCellStyle, mOkStyle );
138 mReport += QLatin1String(
"<td></td>" );
139 mReport += QStringLiteral(
"<td style='%1 %2 border: 1px solid'>wrong value<br>expected value</td></tr>" ).arg( mCellStyle, mErrStyle );
140 mReport += QLatin1String(
"</tr></table>" );
141 mReport += QLatin1String(
"<br>" );
143 int width = expectedProvider->
xSize();
144 int height = expectedProvider->
ySize();
145 std::unique_ptr< QgsRasterBlock > expectedBlock( expectedProvider->
block( band, expectedProvider->
extent(), width, height ) );
146 std::unique_ptr< QgsRasterBlock > verifiedBlock( verifiedProvider->
block( band, expectedProvider->
extent(), width, height ) );
148 if ( !expectedBlock || !expectedBlock->isValid() ||
149 !verifiedBlock || !verifiedBlock->isValid() )
152 mReport += QLatin1String(
"cannot read raster block" );
157 QString htmlTable = QStringLiteral(
"<table style='%1'>" ).arg( mTabStyle );
158 for (
int row = 0; row < height; row ++ )
160 htmlTable += QLatin1String(
"<tr>" );
161 for (
int col = 0; col < width; col ++ )
164 double verifiedVal = verifiedBlock->value( row, col );
165 double expectedVal = expectedBlock->value( row, col );
168 if ( compare( verifiedVal, expectedVal, 0 ) )
170 valStr = QStringLiteral(
"%1" ).arg( verifiedVal );
176 valStr = QStringLiteral(
"%1<br>%2" ).arg( verifiedVal ).arg( expectedVal );
178 htmlTable += QStringLiteral(
"<td style='%1 %2'>%3</td>" ).arg( mCellStyle, cellOk ? mOkStyle : mErrStyle, valStr );
180 htmlTable += QLatin1String(
"</tr>" );
182 htmlTable += QLatin1String(
"</table>" );
184 mReport += htmlTable;
186 delete verifiedProvider;
187 delete expectedProvider;
191 void QgsRasterChecker::error(
const QString &message, QString &
report )
193 report += QStringLiteral(
"<font style='%1'>Error: " ).arg( mErrMsgStyle );
195 report += QLatin1String(
"</font>" );
198 double QgsRasterChecker::tolerance(
double val,
int places )
202 return 1. * std::pow( 10, std::round( std::log10( std::fabs( val ) ) - places ) );
205 QString QgsRasterChecker::compareHead()
208 html += QStringLiteral(
"<tr><th style='%1'>Param name</th><th style='%1'>Verified value</th><th style='%1'>Expected value</th><th style='%1'>Difference</th><th style='%1'>Tolerance</th></tr>" ).arg( mCellStyle );
212 void QgsRasterChecker::compare(
const QString ¶mName,
int verifiedVal,
int expectedVal, QString &
report,
bool &ok )
214 bool isEqual = verifiedVal == expectedVal;
215 compareRow( paramName, QString::number( verifiedVal ), QString::number( expectedVal ),
report, isEqual, QString::number( verifiedVal - expectedVal ) );
220 bool QgsRasterChecker::compare(
double verifiedVal,
double expectedVal,
double tolerance )
223 return ( std::isnan( verifiedVal ) && std::isnan( expectedVal ) ) || ( std::fabs( verifiedVal - expectedVal ) <= tolerance );
226 void QgsRasterChecker::compare(
const QString ¶mName,
double verifiedVal,
double expectedVal, QString &
report,
bool &ok,
double tolerance )
228 bool isNearEqual = compare( verifiedVal, expectedVal, tolerance );
229 compareRow( paramName, QString::number( verifiedVal ), QString::number( expectedVal ),
report, isNearEqual, QString::number( verifiedVal - expectedVal ), QString::number( tolerance ) );
234 void QgsRasterChecker::compareRow(
const QString ¶mName,
const QString &verifiedVal,
const QString &expectedVal, QString &
report,
bool ok,
const QString &difference,
const QString &tolerance )
236 report += QLatin1String(
"<tr>\n" );
237 report += QStringLiteral(
"<td style='%1'>%2</td><td style='%1 %3'>%4</td><td style='%1'>%5</td>\n" ).arg( mCellStyle, paramName, ok ? mOkStyle : mErrStyle, verifiedVal, expectedVal );
238 report += QStringLiteral(
"<td style='%1'>%2</td>\n" ).arg( mCellStyle, difference );
239 report += QStringLiteral(
"<td style='%1'>%2</td>\n" ).arg( mCellStyle, tolerance );
240 report += QLatin1String(
"</tr>" );
virtual int bandCount() const =0
Gets number of bands.
double maximumValue
The maximum cell value in the raster band.
virtual int ySize() const
Qgis::DataType sourceDataType(int bandNo) const override=0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
QgsDataProvider * createProvider(const QString &providerKey, const QString &dataSource, const QgsDataProvider::ProviderOptions &options=QgsDataProvider::ProviderOptions())
Creates a new instance of a provider.
double stdDev
The standard deviation of the cell values.
The RasterBandStats struct is a container for statistics about a single raster band.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
double mean
The mean cell value for the band. NO_DATA values are excluded.
QgsRectangle extent() const override=0
Returns the extent of the layer.
virtual bool isValid() const =0
Returns true if this is a valid layer.
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
bool runTest(const QString &verifiedKey, QString verifiedUri, const QString &expectedKey, QString expectedUri)
Test using renderer to generate the image to be compared.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
QgsRasterBlock * block(int bandNo, const QgsRectangle &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
Setting options for creating vector data providers.
double minimumValue
The minimum cell value in the raster band.
virtual int xSize() const
Gets raster size.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
Base class for raster data providers.