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 mReport += QStringLiteral(
"Verified URI: %1<br>" ).arg( verifiedUri.replace(
'&', QLatin1String(
"&" ) ) );
63 mReport += QStringLiteral(
"Expected URI: %1<br>" ).arg( expectedUri.replace(
'&', QLatin1String(
"&" ) ) );
65 mReport += QLatin1String(
"<br>" );
66 mReport += QStringLiteral(
"<table style='%1'>\n" ).arg( mTabStyle );
67 mReport += compareHead();
69 compare( QStringLiteral(
"Band count" ), verifiedProvider->
bandCount(), expectedProvider->
bandCount(), mReport, ok );
71 compare( QStringLiteral(
"Width" ), verifiedProvider->
xSize(), expectedProvider->
xSize(), mReport, ok );
72 compare( QStringLiteral(
"Height" ), verifiedProvider->
ySize(), expectedProvider->
ySize(), mReport, ok );
76 if ( verifiedProvider->
extent() != expectedProvider->
extent() ) ok =
false;
79 mReport += QLatin1String(
"</table>\n" );
81 if ( !ok )
return false;
84 for (
int band = 1; band <= expectedProvider->
bandCount(); band++ )
86 mReport += QStringLiteral(
"<h3>Band %1</h3>\n" ).arg( band );
87 mReport += QStringLiteral(
"<table style='%1'>\n" ).arg( mTabStyle );
88 mReport += compareHead();
92 compare( QStringLiteral(
"Source data type" ), verifiedProvider->
sourceDataType( band ), expectedProvider->
sourceDataType( band ), mReport, typesOk );
93 compare( QStringLiteral(
"Data type" ), verifiedProvider->
dataType( band ), expectedProvider->
dataType( band ), mReport, typesOk );
110 compare( QStringLiteral(
"Minimum value" ), verifiedStats.
minimumValue, expectedStats.
minimumValue, mReport, statsOk, tol );
112 compare( QStringLiteral(
"Maximum value" ), verifiedStats.
maximumValue, expectedStats.
maximumValue, mReport, statsOk, tol );
117 tol = tolerance( expectedStats.
mean );
118 compare( QStringLiteral(
"Mean" ), verifiedStats.
mean, expectedStats.
mean, mReport, statsOk, tol );
121 tol = tolerance( expectedStats.
stdDev, 1 );
122 compare( QStringLiteral(
"Standard deviation" ), verifiedStats.
stdDev, expectedStats.
stdDev, mReport, statsOk, tol );
124 mReport += QLatin1String(
"</table>" );
125 mReport += QLatin1String(
"<br>" );
127 if ( !statsOk || !typesOk || !noDataOk )
133 mReport += QLatin1String(
"<table><tr>" );
134 mReport += QLatin1String(
"<td>Data comparison</td>" );
135 mReport += QStringLiteral(
"<td style='%1 %2 border: 1px solid'>correct value</td>" ).arg( mCellStyle, mOkStyle );
136 mReport += QLatin1String(
"<td></td>" );
137 mReport += QStringLiteral(
"<td style='%1 %2 border: 1px solid'>wrong value<br>expected value</td></tr>" ).arg( mCellStyle, mErrStyle );
138 mReport += QLatin1String(
"</tr></table>" );
139 mReport += QLatin1String(
"<br>" );
141 int width = expectedProvider->
xSize();
142 int height = expectedProvider->
ySize();
143 std::unique_ptr< QgsRasterBlock > expectedBlock( expectedProvider->
block( band, expectedProvider->
extent(), width, height ) );
144 std::unique_ptr< QgsRasterBlock > verifiedBlock( verifiedProvider->
block( band, expectedProvider->
extent(), width, height ) );
146 if ( !expectedBlock || !expectedBlock->isValid() ||
147 !verifiedBlock || !verifiedBlock->isValid() )
150 mReport += QLatin1String(
"cannot read raster block" );
155 QString htmlTable = QStringLiteral(
"<table style='%1'>" ).arg( mTabStyle );
156 for (
int row = 0; row < height; row ++ )
158 htmlTable += QLatin1String(
"<tr>" );
159 for (
int col = 0; col < width; col ++ )
162 double verifiedVal = verifiedBlock->value( row, col );
163 double expectedVal = expectedBlock->value( row, col );
166 if ( compare( verifiedVal, expectedVal, 0 ) )
168 valStr = QString::number( verifiedVal );
174 valStr = QStringLiteral(
"%1<br>%2" ).arg( verifiedVal ).arg( expectedVal );
176 htmlTable += QStringLiteral(
"<td style='%1 %2'>%3</td>" ).arg( mCellStyle, cellOk ? mOkStyle : mErrStyle, valStr );
178 htmlTable += QLatin1String(
"</tr>" );
180 htmlTable += QLatin1String(
"</table>" );
182 mReport += htmlTable;
184 delete verifiedProvider;
185 delete expectedProvider;
189 void QgsRasterChecker::error(
const QString &message, QString &report )
191 report += QStringLiteral(
"<font style='%1'>Error: " ).arg( mErrMsgStyle );
193 report += QLatin1String(
"</font>" );
196 double QgsRasterChecker::tolerance(
double val,
int places )
200 return 1. * std::pow( 10, std::round( std::log10( std::fabs( val ) ) - places ) );
203 QString QgsRasterChecker::compareHead()
206 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 );
210 void QgsRasterChecker::compare(
const QString ¶mName,
int verifiedVal,
int expectedVal, QString &report,
bool &ok )
212 bool isEqual = verifiedVal == expectedVal;
213 compareRow( paramName, QString::number( verifiedVal ), QString::number( expectedVal ),
report, isEqual, QString::number( verifiedVal - expectedVal ) );
218 bool QgsRasterChecker::compare(
double verifiedVal,
double expectedVal,
double tolerance )
221 return ( std::isnan( verifiedVal ) && std::isnan( expectedVal ) ) || ( std::fabs( verifiedVal - expectedVal ) <= tolerance );
224 void QgsRasterChecker::compare(
const QString ¶mName,
double verifiedVal,
double expectedVal, QString &report,
bool &ok,
double tolerance )
226 bool isNearEqual = compare( verifiedVal, expectedVal, tolerance );
227 compareRow( paramName, QString::number( verifiedVal ), QString::number( expectedVal ),
report, isNearEqual, QString::number( verifiedVal - expectedVal ), QString::number( tolerance ) );
232 void QgsRasterChecker::compareRow(
const QString ¶mName,
const QString &verifiedVal,
const QString &expectedVal, QString &report,
bool ok,
const QString &difference,
const QString &tolerance )
234 report += QLatin1String(
"<tr>\n" );
235 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 );
236 report += QStringLiteral(
"<td style='%1'>%2</td>\n" ).arg( mCellStyle, difference );
237 report += QStringLiteral(
"<td style='%1'>%2</td>\n" ).arg( mCellStyle, tolerance );
238 report += QLatin1String(
"</tr>" );
virtual bool isValid() const =0
Returns true if this is a valid layer.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
The RasterBandStats struct is a container for statistics about a single raster band.
double mean
The mean cell value for the band. NO_DATA values are excluded.
double stdDev
The standard deviation of the cell values.
double minimumValue
The minimum cell value in the raster band.
double maximumValue
The maximum cell value in the raster band.
bool runTest(const QString &verifiedKey, QString verifiedUri, const QString &expectedKey, QString expectedUri)
Test using renderer to generate the image to be compared.
Base class for raster data providers.
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
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.
QgsRectangle extent() const override=0
Returns the extent of the layer.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
QgsRasterBlock * block(int bandNo, const QgsRectangle &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
virtual int xSize() const
Gets raster size.
virtual int bandCount() const =0
Gets number of bands.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
virtual int ySize() const
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
Setting options for creating vector data providers.