#4732 Support error bars for observed RFT data (#4760)

* #4732 Fix missing refresh for ensemble RFT

* WIP

* #4732 Fix missing refresh for ensemble RFT

* WIP

* Make sure Observed RFT data is loaded on startup

* Make error bars work for RFT plots

* #4761 Add labels with formation and value/error to observed data points

* Changes after review
This commit is contained in:
Gaute Lindkvist
2019-09-25 17:48:19 +02:00
committed by GitHub
parent 931e7dc42d
commit 2a20f84f1f
16 changed files with 240 additions and 58 deletions

View File

@@ -73,20 +73,21 @@ RiuQwtPlotCurve::~RiuQwtPlotCurve() {}
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::setSamplesFromXValuesAndYValues( const std::vector<double>& xValues,
const std::vector<double>& yValues,
const std::vector<double>& yErrorValues,
bool keepOnlyPositiveValues )
const std::vector<double>& errorValues,
bool keepOnlyPositiveValues,
ErrorAxis errorAxis )
{
CVF_ASSERT( xValues.size() == yValues.size() );
CVF_ASSERT( yErrorValues.empty() || yErrorValues.size() == xValues.size() );
bool showErrorBars = m_showErrorBars && !yErrorValues.empty();
bool showErrorBars = m_showErrorBars && !errorValues.empty();
QPolygonF points;
QVector<QwtIntervalSample> errorIntervals;
std::vector<std::pair<size_t, size_t>> filteredIntervals;
{
std::vector<double> filteredYValues;
std::vector<double> filteredXValues;
std::vector<double> filteredYErrorValues;
std::vector<double> filteredErrorValues;
{
auto intervalsOfValidValues = RiaCurveDataTools::calculateIntervalsOfValidValues( yValues,
@@ -96,7 +97,7 @@ void RiuQwtPlotCurve::setSamplesFromXValuesAndYValues( const std::vector<double>
RiaCurveDataTools::getValuesByIntervals( xValues, intervalsOfValidValues, &filteredXValues );
if ( showErrorBars )
RiaCurveDataTools::getValuesByIntervals( yErrorValues, intervalsOfValidValues, &filteredYErrorValues );
RiaCurveDataTools::getValuesByIntervals( errorValues, intervalsOfValidValues, &filteredErrorValues );
filteredIntervals = RiaCurveDataTools::computePolyLineStartStopIndices( intervalsOfValidValues );
}
@@ -107,11 +108,20 @@ void RiuQwtPlotCurve::setSamplesFromXValuesAndYValues( const std::vector<double>
{
points << QPointF( filteredXValues[i], filteredYValues[i] );
if ( showErrorBars && filteredYValues[i] != DOUBLE_INF && filteredYErrorValues[i] != DOUBLE_INF )
if ( showErrorBars && filteredYValues[i] != DOUBLE_INF && filteredErrorValues[i] != DOUBLE_INF )
{
errorIntervals << QwtIntervalSample( filteredXValues[i],
filteredYValues[i] - filteredYErrorValues[i],
filteredYValues[i] + filteredYErrorValues[i] );
if ( errorAxis == ERROR_ALONG_Y_AXIS )
{
errorIntervals << QwtIntervalSample( filteredXValues[i],
filteredYValues[i] - filteredErrorValues[i],
filteredYValues[i] + filteredErrorValues[i] );
}
else
{
errorIntervals << QwtIntervalSample( filteredYValues[i],
filteredXValues[i] - filteredErrorValues[i],
filteredXValues[i] + filteredErrorValues[i] );
}
}
}
}
@@ -119,7 +129,18 @@ void RiuQwtPlotCurve::setSamplesFromXValuesAndYValues( const std::vector<double>
this->setSamples( points );
this->setLineSegmentStartStopIndices( filteredIntervals );
if ( showErrorBars ) m_errorBars->setSamples( errorIntervals );
if ( showErrorBars )
{
m_errorBars->setSamples( errorIntervals );
if ( errorAxis == ERROR_ALONG_Y_AXIS )
{
m_errorBars->setOrientation( Qt::Vertical );
}
else
{
m_errorBars->setOrientation( Qt::Horizontal );
}
}
}
//--------------------------------------------------------------------------------------------------
@@ -285,11 +306,21 @@ void RiuQwtPlotCurve::drawSymbols( QPainter* painter,
const RiuQwtSymbol* sym = dynamic_cast<const RiuQwtSymbol*>( &symbol );
if ( sym && !sym->label().isEmpty() )
if ( sym )
{
for ( auto& pt : pointsToDisplay )
if ( m_perPointLabels.size() == pointsToDisplay.size() )
{
sym->renderSymbolLabel( painter, pt );
for ( int i = 0; i < (int)pointsToDisplay.size(); ++i )
{
sym->renderSymbolLabel( painter, pointsToDisplay[i], m_perPointLabels[i] );
}
}
else if ( !sym->globalLabel().isEmpty() )
{
for ( auto& pt : pointsToDisplay )
{
sym->renderSymbolLabel( painter, pt, sym->globalLabel() );
}
}
}
}
@@ -318,7 +349,10 @@ void RiuQwtPlotCurve::setSymbolSkipPixelDistance( float distance )
void RiuQwtPlotCurve::attach( QwtPlot* plot )
{
QwtPlotItem::attach( plot );
if ( m_showErrorBars ) m_errorBars->attach( plot );
if ( m_showErrorBars )
{
m_errorBars->attach( plot );
}
m_attachedToPlot = plot;
}
@@ -362,6 +396,24 @@ void RiuQwtPlotCurve::setErrorBarsColor( QColor color )
m_errorBars->setSymbol( newSymbol );
}
//--------------------------------------------------------------------------------------------------
/// Set the Qwt X-Axis (QwtPlot::xBottom or QwtPlot::xTop).
/// This is important to make sure the x-axis interval is set correctly.
/// WellLogPlots use top-axis and Summary uses bottom axis.
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::setErrorBarsXAxis( int axis )
{
m_errorBars->setXAxis( axis );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotCurve::setPerPointLabels( const std::vector<QString>& labels )
{
m_perPointLabels = labels;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -48,6 +48,12 @@ class RiuErrorBarsQwtPlotCurve;
class RiuQwtPlotCurve : public QwtPlotCurve
{
public:
enum ErrorAxis
{
ERROR_ALONG_X_AXIS,
ERROR_ALONG_Y_AXIS
};
enum CurveInterpolationEnum
{
INTERPOLATION_POINT_TO_POINT,
@@ -83,8 +89,9 @@ public:
void setSamplesFromXValuesAndYValues( const std::vector<double>& xValues,
const std::vector<double>& yValues,
const std::vector<double>& yErrorValues,
bool keepOnlyPositiveValues );
const std::vector<double>& errorValues,
bool keepOnlyPositiveValues,
ErrorAxis errorAxis = ERROR_ALONG_Y_AXIS );
void setSamplesFromDatesAndYValues( const std::vector<QDateTime>& dateTimes,
const std::vector<double>& yValues,
@@ -108,6 +115,8 @@ public:
void clearErrorBars();
void showErrorBars( bool show );
void setErrorBarsColor( QColor color );
void setErrorBarsXAxis( int axis );
void setPerPointLabels( const std::vector<QString>& labels );
void setAppearance( LineStyleEnum lineStyle,
CurveInterpolationEnum interpolationType,
@@ -145,4 +154,6 @@ private:
QwtPlotIntervalCurve* m_errorBars;
QwtPlot* m_attachedToPlot;
bool m_blackAndWhiteLegendIcon;
std::vector<QString> m_perPointLabels;
};

View File

@@ -28,7 +28,7 @@
//--------------------------------------------------------------------------------------------------
RiuQwtSymbol::RiuQwtSymbol( PointSymbolEnum riuStyle, const QString& label, LabelPosition labelPosition )
: QwtSymbol( QwtSymbol::NoSymbol )
, m_label( label )
, m_globalLabel( label )
, m_labelPosition( labelPosition )
{
QwtSymbol::Style style = QwtSymbol::NoSymbol;
@@ -133,34 +133,33 @@ RiuQwtSymbol::RiuQwtSymbol( PointSymbolEnum riuStyle, const QString& label, Labe
void RiuQwtSymbol::renderSymbols( QPainter* painter, const QPointF* points, int numPoints ) const
{
QwtSymbol::renderSymbols( painter, points, numPoints );
if ( !m_label.isEmpty() )
{
for ( int i = 0; i < numPoints; i++ )
{
auto position = points[i];
// renderSymbolLabel(painter, position);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtSymbol::renderSymbolLabel( QPainter* painter, const QPointF& position ) const
void RiuQwtSymbol::renderSymbolLabel( QPainter* painter, const QPointF& position, const QString& label ) const
{
QSize symbolSize = QwtSymbol::size();
QRect symbolRect( position.x(), position.y(), symbolSize.width(), symbolSize.height() );
QRect labelRect = labelBoundingRect( painter, symbolRect );
painter->drawText( labelRect.topLeft(), m_label );
QRect labelRect = labelBoundingRect( painter, symbolRect, label );
painter->drawText( labelRect.topLeft(), label );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtSymbol::setLabel( const QString& label )
QString RiuQwtSymbol::globalLabel() const
{
m_label = label;
return m_globalLabel;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtSymbol::setGlobalLabel( const QString& label )
{
m_globalLabel = label;
}
//--------------------------------------------------------------------------------------------------
@@ -212,7 +211,7 @@ RiuQwtSymbol::PointSymbolEnum RiuQwtSymbol::cycledSymbolStyle( int indexLevel )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QRect RiuQwtSymbol::labelBoundingRect( const QPainter* painter, const QRect& symbolRect ) const
QRect RiuQwtSymbol::labelBoundingRect( const QPainter* painter, const QRect& symbolRect, const QString& label ) const
{
CVF_ASSERT( painter );
@@ -221,7 +220,7 @@ QRect RiuQwtSymbol::labelBoundingRect( const QPainter* painter, const QRect& sym
int symbolWidth = symbolRect.width();
int symbolHeight = symbolRect.height();
int labelWidth = painter->fontMetrics().width( m_label );
int labelWidth = painter->fontMetrics().width( label );
int labelHeight = painter->fontMetrics().height();
QPoint labelPosition;

View File

@@ -61,14 +61,11 @@ public:
};
RiuQwtSymbol( PointSymbolEnum riuStyle, const QString& label, LabelPosition labelPosition = LabelAboveSymbol );
void renderSymbols( QPainter* painter, const QPointF* points, int numPoints ) const override;
void renderSymbolLabel( QPainter* painter, const QPointF& position ) const;
QString label() const
{
return m_label;
}
void setLabel( const QString& label );
void renderSymbolLabel( QPainter* painter, const QPointF& position, const QString& label ) const;
QString globalLabel() const;
void setGlobalLabel( const QString& label );
void setLabelPosition( LabelPosition labelPosition );
@@ -76,9 +73,9 @@ public:
static PointSymbolEnum cycledSymbolStyle( int indexLevel );
private:
QRect labelBoundingRect( const QPainter* painter, const QRect& symbolRect ) const;
QRect labelBoundingRect( const QPainter* painter, const QRect& symbolRect, const QString& label ) const;
private:
QString m_label;
QString m_globalLabel;
LabelPosition m_labelPosition;
};