mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#2778 Observed error bars. Display error bars in the same color as data points
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 "";
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -97,8 +97,6 @@ private:
|
||||
RimSummaryCase* summaryCase,
|
||||
RimSummaryFilter* summaryFilter);
|
||||
|
||||
bool isCrossPlotCurve() const;
|
||||
|
||||
private:
|
||||
// Y values
|
||||
caf::PdmPtrField<RimSummaryCase*> m_yValuesSummaryCase;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user