#2778 Observed error bars. Display error bars in the same color as data points

This commit is contained in:
Bjørn Erik Jensen
2018-05-25 11:10:03 +02:00
parent 14a5fd4009
commit 403e1759f9
10 changed files with 166 additions and 23 deletions

View File

@@ -159,6 +159,7 @@ void RifCsvUserData::buildTimeStepsAndMappings()
RifEclipseSummaryAddress sumAddress = ci.summaryAddress;
m_allResultAddresses.push_back(sumAddress);
if (sumAddress.isErrorResult()) m_allErrorAddresses.insert(sumAddress);
m_mapFromAddressToTimeStepIndex[sumAddress] = m_timeSteps.size() - 1;
m_mapFromAddressToResultIndex[sumAddress] = columnIndex;

View File

@@ -143,6 +143,9 @@ RifEclipseSummaryAddress RifEclipseSummaryAddress::importedAddress(const std::st
std::string RifEclipseSummaryAddress::uiText() const
{
std::string text;
if (m_isErrorResult) text += "ERR:";
text += m_quantityName;
switch(this->category())
{
@@ -227,7 +230,7 @@ std::string RifEclipseSummaryAddress::uiText(RifEclipseSummaryAddress::SummaryId
case RifEclipseSummaryAddress::INPUT_LGR_NAME: return lgrName();
case RifEclipseSummaryAddress::INPUT_SEGMENT_NUMBER: return std::to_string(wellSegmentNumber());
case RifEclipseSummaryAddress::INPUT_AQUIFER_NUMBER: return std::to_string(aquiferNumber());
case RifEclipseSummaryAddress::INPUT_VECTOR_NAME: return quantityName() + (m_isErrorResult ? " (err)" : "");
case RifEclipseSummaryAddress::INPUT_VECTOR_NAME: return quantityName();
}
return "";
}

View File

@@ -31,6 +31,17 @@ const std::vector<RifEclipseSummaryAddress>& RifSummaryReaderInterface::allResul
return m_allResultAddresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifEclipseSummaryAddress RifSummaryReaderInterface::errorAddress(const RifEclipseSummaryAddress& resultAddress) const
{
RifEclipseSummaryAddress errAddr = resultAddress;
errAddr.setAsErrorResult();
return m_allErrorAddresses.find(errAddr) != m_allErrorAddresses.end() ? errAddr : RifEclipseSummaryAddress();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -38,6 +38,7 @@ class RifSummaryReaderInterface : public cvf::Object
public:
bool hasAddress(const RifEclipseSummaryAddress& resultAddress) const;
const std::vector<RifEclipseSummaryAddress>& allResultAddresses() const;
RifEclipseSummaryAddress errorAddress(const RifEclipseSummaryAddress& resultAddress) const;
virtual const std::vector<time_t>& timeSteps(const RifEclipseSummaryAddress& resultAddress) const = 0;
@@ -50,5 +51,6 @@ public:
static std::vector<QDateTime> fromTimeT(const std::vector<time_t>& timeSteps);
protected:
std::vector<RifEclipseSummaryAddress> m_allResultAddresses;
std::vector<RifEclipseSummaryAddress> m_allResultAddresses; // Result and error addresses
std::set<RifEclipseSummaryAddress> m_allErrorAddresses; // Error addresses
};

View File

@@ -20,6 +20,7 @@
#include "RimEnsembleCurveSet.h"
#include "RimEnsembleCurveSetCollection.h"
#include "RimSummaryCrossPlot.h"
#include "RimSummaryCurve.h"
#include "RimSummaryCurveCollection.h"
#include "RimSummaryCurveFilter.h"
@@ -110,6 +111,8 @@ RimPlotCurve::RimPlotCurve()
CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Contribute To Legend", "", "", "");
CAF_PDM_InitField(&m_showErrorBars, "ShowErrorBars", true, "Show Error Bars", "", "", "");
m_qwtPlotCurve = new RiuRimQwtPlotCurve(this);
m_parentQwtPlot = nullptr;
@@ -170,7 +173,11 @@ void RimPlotCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField, con
{
updateLegendEntryVisibilityAndPlotLegend();
}
else if (changedField == &m_showErrorBars)
{
m_qwtPlotCurve->showErrorBars(m_showErrorBars);
updateCurveAppearance();
}
if (m_parentQwtPlot) m_parentQwtPlot->replot();
}
@@ -362,6 +369,9 @@ void RimPlotCurve::appearanceUiOrdering(caf::PdmUiOrdering& uiOrdering)
uiOrdering.add(&m_curveThickness);
uiOrdering.add(&m_lineStyle);
uiOrdering.add(&m_curveInterpolation);
if(isCrossPlotCurve()) m_showErrorBars = false;
else uiOrdering.add(&m_showErrorBars);
}
//--------------------------------------------------------------------------------------------------
@@ -464,6 +474,20 @@ void RimPlotCurve::updateCurveAppearance()
m_qwtPlotCurve->setStyle(curveStyle);
m_qwtPlotCurve->setSymbol(symbol);
m_qwtPlotCurve->setSymbolSkipPixelDistance(m_symbolSkipPixelDistance());
m_qwtPlotCurve->setErrorBarsColor(curveColor);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimPlotCurve::isCrossPlotCurve() const
{
RimSummaryCrossPlot* crossPlot = nullptr;
this->firstAncestorOrThisOfType(crossPlot);
if (crossPlot) return true;
return false;
}
//--------------------------------------------------------------------------------------------------

View File

@@ -101,6 +101,7 @@ public:
void setZOrder(double z);
virtual void updateCurveAppearance();
bool isCrossPlotCurve() const;
protected:
@@ -135,7 +136,7 @@ protected:
caf::PdmField<cvf::Color3f> m_curveColor;
caf::PdmField<int> m_curveThickness;
caf::PdmField<float> m_symbolSkipPixelDistance;
caf::PdmField<bool> m_showErrorBars;
caf::PdmField< caf::AppEnum< PointSymbolEnum > > m_pointSymbol;
caf::PdmField< caf::AppEnum< LineStyleEnum > > m_lineStyle;

View File

@@ -457,7 +457,18 @@ void RimSummaryCurve::onLoadDataAndUpdate(bool updateParentPlot)
{
if (plot->timeAxisProperties()->timeMode() == RimSummaryTimeAxisProperties::DATE)
{
m_qwtPlotCurve->setSamplesFromTimeTAndYValues(curveTimeStepsY, curveValuesY, isLogCurve);
auto reader = summaryCaseY()->summaryReader();
auto errAddress = reader->errorAddress(summaryAddressY());
if (errAddress.isValid())
{
std::vector<double> errValues;
reader->values(errAddress, &errValues);
m_qwtPlotCurve->setSamplesFromTimeTAndYValues(curveTimeStepsY, curveValuesY, errValues, isLogCurve);
}
else
{
m_qwtPlotCurve->setSamplesFromTimeTAndYValues(curveTimeStepsY, curveValuesY, isLogCurve);
}
}
else
{
@@ -492,6 +503,8 @@ void RimSummaryCurve::onLoadDataAndUpdate(bool updateParentPlot)
updateZoomInParentPlot();
m_parentQwtPlot->replot();
}
m_qwtPlotCurve->showErrorBars(m_showErrorBars);
}
if (updateParentPlot) updateQwtPlotAxis();
@@ -594,18 +607,6 @@ void RimSummaryCurve::appendOptionItemsForSummaryAddresses(QList<caf::PdmOptionI
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimSummaryCurve::isCrossPlotCurve() const
{
RimSummaryCrossPlot* crossPlot = nullptr;
this->firstAncestorOrThisOfType(crossPlot);
if (crossPlot) return true;
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -97,8 +97,6 @@ private:
RimSummaryCase* summaryCase,
RimSummaryFilter* summaryFilter);
bool isCrossPlotCurve() const;
private:
// Y values
caf::PdmPtrField<RimSummaryCase*> m_yValuesSummaryCase;

View File

@@ -24,7 +24,9 @@
#include "qwt_date.h"
#include "qwt_point_mapper.h"
#include "qwt_painter.h"
#include "qwt_plot_intervalcurve.h"
#include "qwt_scale_map.h"
#include "qwt_interval_symbol.h"
//--------------------------------------------------------------------------------------------------
///
@@ -39,6 +41,13 @@ RiuLineSegmentQwtPlotCurve::RiuLineSegmentQwtPlotCurve(const QString &title)
this->setRenderHint(QwtPlotItem::RenderAntialiased, true);
m_symbolSkipPixelDistance = 10.0f;
m_errorBars = new QwtPlotIntervalCurve();
m_errorBars->setStyle(QwtPlotIntervalCurve::CurveStyle::NoCurve);
m_errorBars->setSymbol(new QwtIntervalSymbol(QwtIntervalSymbol::Bar));
m_showErrorBars = true;
m_attachedToPlot = nullptr;
}
//--------------------------------------------------------------------------------------------------
@@ -46,20 +55,25 @@ RiuLineSegmentQwtPlotCurve::RiuLineSegmentQwtPlotCurve(const QString &title)
//--------------------------------------------------------------------------------------------------
RiuLineSegmentQwtPlotCurve::~RiuLineSegmentQwtPlotCurve()
{
delete m_errorBars;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve::setSamplesFromXValuesAndYValues(const std::vector<double>& xValues, const std::vector<double>& yValues, bool keepOnlyPositiveValues)
void RiuLineSegmentQwtPlotCurve::setSamplesFromXValuesAndYValues(const std::vector<double>& xValues, const std::vector<double>& yValues, const std::vector<double>& yErrorValues, bool keepOnlyPositiveValues)
{
CVF_ASSERT(xValues.size() == yValues.size());
CVF_ASSERT(yErrorValues.empty() || yErrorValues.size() == xValues.size());
bool showErrorBars = m_showErrorBars && !yErrorValues.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;
{
auto intervalsOfValidValues = RigCurveDataTools::calculateIntervalsOfValidValues(yValues, keepOnlyPositiveValues);
@@ -67,18 +81,36 @@ void RiuLineSegmentQwtPlotCurve::setSamplesFromXValuesAndYValues(const std::vect
RigCurveDataTools::getValuesByIntervals(yValues, intervalsOfValidValues, &filteredYValues);
RigCurveDataTools::getValuesByIntervals(xValues, intervalsOfValidValues, &filteredXValues);
if(showErrorBars) RigCurveDataTools::getValuesByIntervals(yErrorValues, intervalsOfValidValues, &filteredYErrorValues);
filteredIntervals = RigCurveDataTools::computePolyLineStartStopIndices(intervalsOfValidValues);
}
points.reserve(static_cast<int>(filteredXValues.size()));
errorIntervals.reserve(static_cast<int>(filteredXValues.size()));
for ( size_t i = 0; i < filteredXValues.size(); i++ )
{
points << QPointF(filteredXValues[i], filteredYValues[i]);
if (showErrorBars)
{
errorIntervals << QwtIntervalSample(filteredXValues[i], filteredYValues[i] - filteredYErrorValues[i], filteredYValues[i] + filteredYErrorValues[i]);
}
}
}
this->setSamples(points);
this->setLineSegmentStartStopIndices(filteredIntervals);
if(showErrorBars) m_errorBars->setSamples(errorIntervals);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve::setSamplesFromXValuesAndYValues(const std::vector<double>& xValues, const std::vector<double>& yValues, bool keepOnlyPositiveValues)
{
setSamplesFromXValuesAndYValues(xValues, yValues, std::vector<double>(), keepOnlyPositiveValues);
}
//--------------------------------------------------------------------------------------------------
@@ -86,7 +118,7 @@ void RiuLineSegmentQwtPlotCurve::setSamplesFromXValuesAndYValues(const std::vect
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve::setSamplesFromDatesAndYValues(const std::vector<QDateTime>& dateTimes, const std::vector<double>& yValues, bool keepOnlyPositiveValues)
{
setSamplesFromXValuesAndYValues(RiuLineSegmentQwtPlotCurve::fromQDateTime(dateTimes), yValues, keepOnlyPositiveValues);
setSamplesFromXValuesAndYValues(RiuLineSegmentQwtPlotCurve::fromQDateTime(dateTimes), yValues, std::vector<double>(), keepOnlyPositiveValues);
}
//--------------------------------------------------------------------------------------------------
@@ -94,7 +126,15 @@ void RiuLineSegmentQwtPlotCurve::setSamplesFromDatesAndYValues(const std::vector
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve::setSamplesFromTimeTAndYValues(const std::vector<time_t>& dateTimes, const std::vector<double>& yValues, bool keepOnlyPositiveValues)
{
setSamplesFromXValuesAndYValues(RiuLineSegmentQwtPlotCurve::fromTime_t(dateTimes), yValues, keepOnlyPositiveValues);
setSamplesFromXValuesAndYValues(RiuLineSegmentQwtPlotCurve::fromTime_t(dateTimes), yValues, std::vector<double>(), keepOnlyPositiveValues);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve::setSamplesFromTimeTAndYValues(const std::vector<time_t>& dateTimes, const std::vector<double>& yValues, const std::vector<double>& yErrorValues, bool keepOnlyPositiveValues)
{
setSamplesFromXValuesAndYValues(RiuLineSegmentQwtPlotCurve::fromTime_t(dateTimes), yValues, yErrorValues, keepOnlyPositiveValues);
}
//--------------------------------------------------------------------------------------------------
@@ -201,6 +241,46 @@ void RiuLineSegmentQwtPlotCurve::setSymbolSkipPixelDistance(float distance)
m_symbolSkipPixelDistance = distance >= 0.0f ? distance: 0.0f;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve::attach(QwtPlot *plot)
{
QwtPlotItem::attach(plot);
if(m_showErrorBars) m_errorBars->attach(plot);
m_attachedToPlot = plot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve::detach()
{
QwtPlotItem::detach();
m_errorBars->detach();
m_attachedToPlot = nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve::showErrorBars(bool show)
{
m_showErrorBars = show;
if (m_showErrorBars && m_attachedToPlot) m_errorBars->attach(m_attachedToPlot);
else m_errorBars->detach();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuLineSegmentQwtPlotCurve::setErrorBarsColor(QColor color)
{
QwtIntervalSymbol* newSymbol = new QwtIntervalSymbol(QwtIntervalSymbol::Bar);
newSymbol->setPen(QPen(color));
m_errorBars->setSymbol(newSymbol);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -20,6 +20,9 @@
#pragma once
#include "qwt_plot_curve.h"
#include "qwt_plot_intervalcurve.h"
class RiuErrorBarsQwtPlotCurve;
//==================================================================================================
//
@@ -51,6 +54,11 @@ public:
const std::vector<double>& yValues,
bool keepOnlyPositiveValues);
void setSamplesFromXValuesAndYValues(const std::vector<double>& xValues,
const std::vector<double>& yValues,
const std::vector<double>& yErrorValues,
bool keepOnlyPositiveValues);
void setSamplesFromDatesAndYValues(const std::vector<QDateTime>& dateTimes,
const std::vector<double>& yValues,
bool keepOnlyPositiveValues);
@@ -59,10 +67,20 @@ public:
const std::vector<double>& yValues,
bool keepOnlyPositiveValues);
void setSamplesFromTimeTAndYValues(const std::vector<time_t>& dateTimes,
const std::vector<double>& yValues,
const std::vector<double>& yErrorValues,
bool keepOnlyPositiveValues);
void setLineSegmentStartStopIndices(const std::vector< std::pair<size_t, size_t> >& lineSegmentStartStopIndices);
void setSymbolSkipPixelDistance(float distance);
void attach(QwtPlot *plot);
void detach();
void showErrorBars(bool show);
void setErrorBarsColor(QColor color);
protected:
virtual void drawCurve(QPainter* p, int style,
const QwtScaleMap& xMap, const QwtScaleMap& yMap,
@@ -83,4 +101,8 @@ private:
private:
std::vector< std::pair<size_t, size_t> > m_polyLineStartStopIndices;
float m_symbolSkipPixelDistance;
bool m_showErrorBars;
QwtPlotIntervalCurve* m_errorBars;
QwtPlot* m_attachedToPlot;
};