mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-09 23:16:00 -06:00
Fix log axis crash in Grid Cross Plot and refactor log axis range code
This commit is contained in:
parent
0ce69d41dd
commit
52d2eed98b
@ -464,6 +464,14 @@ double RiaDefines::minimumDefaultValuePlot()
|
||||
return -10.0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
double RiaDefines::minimumDefaultLogValuePlot()
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -135,6 +135,7 @@ namespace RiaDefines
|
||||
};
|
||||
|
||||
double minimumDefaultValuePlot();
|
||||
double minimumDefaultLogValuePlot();
|
||||
double maximumDefaultValuePlot();
|
||||
|
||||
enum PhaseType {
|
||||
|
@ -269,7 +269,7 @@ void RimGridCrossPlot::detachAllCurves()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridCrossPlot::updateAxisScaling()
|
||||
{
|
||||
updateAxisDisplay();
|
||||
loadDataAndUpdate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -379,13 +379,11 @@ void RimGridCrossPlot::onLoadDataAndUpdate()
|
||||
for (auto curveSet : m_crossPlotCurveSets)
|
||||
{
|
||||
curveSet->loadDataAndUpdate(false);
|
||||
curveSet->updateConnectedEditors();
|
||||
}
|
||||
|
||||
updateCurveNamesAndPlotTitle();
|
||||
updateAllRequiredEditors();
|
||||
|
||||
updatePlot();
|
||||
|
||||
updatePlot();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -542,7 +540,7 @@ void RimGridCrossPlot::swapAxes()
|
||||
}
|
||||
|
||||
loadDataAndUpdate();
|
||||
|
||||
|
||||
updateAxisDisplay();
|
||||
}
|
||||
|
||||
@ -574,7 +572,6 @@ QString RimGridCrossPlot::asciiDataForPlotExport(int curveSetIndex) const
|
||||
formatter.setTableRowLineAppendText("");
|
||||
formatter.setColumnSpacing(3);
|
||||
|
||||
|
||||
m_crossPlotCurveSets[curveSetIndex]->exportFormattedData(formatter);
|
||||
formatter.tableCompleted();
|
||||
return asciiData;
|
||||
@ -593,6 +590,22 @@ RiuGridCrossQwtPlot* RimGridCrossPlot::qwtPlot() const
|
||||
return m_qwtPlot;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimGridCrossPlot::isXAxisLogarithmic() const
|
||||
{
|
||||
return m_xAxisProperties->isLogarithmicScaleEnabled();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimGridCrossPlot::isYAxisLogarithmic() const
|
||||
{
|
||||
return m_yAxisProperties->isLogarithmicScaleEnabled();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -691,7 +704,17 @@ void RimGridCrossPlot::updateAxisInQwt(RiaDefines::PlotAxis axisType)
|
||||
|
||||
if (axisProperties->isAutoZoom())
|
||||
{
|
||||
m_qwtPlot->setAxisAutoScale(qwtAxisId);
|
||||
std::vector<const QwtPlotCurve*> plotCurves = visibleQwtCurves();
|
||||
|
||||
double min, max;
|
||||
RimPlotAxisLogRangeCalculator logRangeCalculator(qwtAxisId, plotCurves);
|
||||
logRangeCalculator.computeAxisRange(&min, &max);
|
||||
if (axisProperties->isAxisInverted())
|
||||
{
|
||||
std::swap(min, max);
|
||||
}
|
||||
|
||||
m_qwtPlot->setAxisScale(qwtAxisId, min, max);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -750,6 +773,28 @@ void RimGridCrossPlot::updateAxisFromQwt(RiaDefines::PlotAxis axisType)
|
||||
axisProperties->updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<const QwtPlotCurve*> RimGridCrossPlot::visibleQwtCurves() const
|
||||
{
|
||||
std::vector<const QwtPlotCurve*> plotCurves;
|
||||
for (auto curveSet : m_crossPlotCurveSets)
|
||||
{
|
||||
if (curveSet->isChecked())
|
||||
{
|
||||
for (auto curve : curveSet->curves())
|
||||
{
|
||||
if (curve->isCurveVisible())
|
||||
{
|
||||
plotCurves.push_back(curve->qwtPlotCurve());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return plotCurves;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Name Configuration
|
||||
///
|
||||
|
@ -74,6 +74,8 @@ public:
|
||||
QString asciiTitleForPlotExport(int curveSetIndex) const;
|
||||
QString asciiDataForPlotExport(int curveSetIndex) const;
|
||||
RiuGridCrossQwtPlot* qwtPlot() const;
|
||||
bool isXAxisLogarithmic() const;
|
||||
bool isYAxisLogarithmic() const;
|
||||
|
||||
public:
|
||||
// Rim2dPlotInterface overrides
|
||||
@ -96,13 +98,13 @@ protected:
|
||||
bool* useOptionsOnly) override;
|
||||
|
||||
void updatePlot();
|
||||
void updateCurveNames();
|
||||
|
||||
QString xAxisParameterString() const;
|
||||
QString yAxisParameterString() const;
|
||||
|
||||
void updateAxisInQwt(RiaDefines::PlotAxis axisType);
|
||||
void updateAxisFromQwt(RiaDefines::PlotAxis axisType);
|
||||
std::vector<const QwtPlotCurve*> visibleQwtCurves() const;
|
||||
|
||||
private:
|
||||
caf::PdmField<bool> m_showLegend;
|
||||
@ -115,7 +117,7 @@ private:
|
||||
caf::PdmChildArrayField<RimGridCrossPlotCurveSet*> m_crossPlotCurveSets;
|
||||
|
||||
QPointer<RiuGridCrossQwtPlot> m_qwtPlot;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -406,6 +406,10 @@ void RimGridCrossPlotCurveSet::onLoadDataAndUpdate(bool updateParentPlot)
|
||||
RigEclipseCrossPlotResult result = RigEclipseCrossPlotDataExtractor::extract(
|
||||
eclipseCase->eclipseCaseData(), m_timeStep(), xAddress, yAddress, m_grouping(), groupAddress, timeStepCellVisibilityMap);
|
||||
|
||||
if (isXAxisLogarithmic() || isYAxisLogarithmic())
|
||||
{
|
||||
filterInvalidCurveValues(&result);
|
||||
}
|
||||
createCurves(result);
|
||||
|
||||
if (updateParentPlot)
|
||||
@ -877,6 +881,26 @@ void RimGridCrossPlotCurveSet::exportFormattedData(RifEclipseDataTableFormatter&
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimGridCrossPlotCurveSet::isXAxisLogarithmic() const
|
||||
{
|
||||
RimGridCrossPlot* parent = nullptr;
|
||||
firstAncestorOrThisOfTypeAsserted(parent);
|
||||
return parent->isXAxisLogarithmic();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimGridCrossPlotCurveSet::isYAxisLogarithmic() const
|
||||
{
|
||||
RimGridCrossPlot* parent = nullptr;
|
||||
firstAncestorOrThisOfTypeAsserted(parent);
|
||||
return parent->isYAxisLogarithmic();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -1001,6 +1025,42 @@ bool RimGridCrossPlotCurveSet::hasMultipleTimeSteps() const
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridCrossPlotCurveSet::filterInvalidCurveValues(RigEclipseCrossPlotResult* result)
|
||||
{
|
||||
bool xLog = isXAxisLogarithmic();
|
||||
bool yLog = isYAxisLogarithmic();
|
||||
|
||||
if (xLog || yLog)
|
||||
{
|
||||
|
||||
RigEclipseCrossPlotResult validResult;
|
||||
for (size_t i = 0; i < result->xValues.size(); ++i)
|
||||
{
|
||||
double xValue = result->xValues[i];
|
||||
double yValue = result->yValues[i];
|
||||
bool invalid = (xLog && xValue <= 0.0) || (yLog && yValue <= 0.0);
|
||||
if (!invalid)
|
||||
{
|
||||
validResult.xValues.push_back(xValue);
|
||||
validResult.yValues.push_back(yValue);
|
||||
if (i < result->groupValuesContinuous.size())
|
||||
{
|
||||
validResult.groupValuesContinuous.push_back(result->groupValuesContinuous[i]);
|
||||
}
|
||||
if (i < result->groupValuesDiscrete.size())
|
||||
{
|
||||
validResult.groupValuesDiscrete.push_back(result->groupValuesDiscrete[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*result = validResult;
|
||||
}
|
||||
}
|
||||
|
||||
CAF_PDM_SOURCE_INIT(RimGridCrossPlotCurveSetNameConfig, "RimGridCrossPlotCurveSetNameConfig");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -117,6 +117,9 @@ public:
|
||||
void swapAxisProperties(bool updatePlot);
|
||||
void exportFormattedData(RifEclipseDataTableFormatter& formatter) const;
|
||||
|
||||
bool isXAxisLogarithmic() const;
|
||||
bool isYAxisLogarithmic() const;
|
||||
|
||||
protected:
|
||||
void initAfterRead() override;
|
||||
void onLoadDataAndUpdate(bool updateParentPlot);
|
||||
@ -139,6 +142,7 @@ protected:
|
||||
void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override;
|
||||
|
||||
bool hasMultipleTimeSteps() const;
|
||||
void filterInvalidCurveValues(RigEclipseCrossPlotResult* result);
|
||||
private:
|
||||
|
||||
caf::PdmPtrField<RimCase*> m_case;
|
||||
@ -154,4 +158,5 @@ private:
|
||||
caf::PdmChildArrayField<RimGridCrossPlotCurve*> m_crossPlotCurves;
|
||||
|
||||
std::map<int, RigEclipseCrossPlotResult> m_groupedResults;
|
||||
|
||||
};
|
||||
|
@ -239,12 +239,11 @@ void RimEclipseCellColors::uiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEclipseCellColors::setReservoirView(RimEclipseView* ownerReservoirView)
|
||||
{
|
||||
m_reservoirView = ownerReservoirView;
|
||||
if (ownerReservoirView)
|
||||
{
|
||||
this->setEclipseCase(ownerReservoirView->eclipseCase());
|
||||
}
|
||||
|
||||
m_reservoirView = ownerReservoirView;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
#include "cafPdmUiSliderEditor.h"
|
||||
|
||||
#include "cvfVector2.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <qwt_plot_curve.h>
|
||||
@ -373,32 +375,32 @@ caf::PdmFieldHandle* RimPlotAxisProperties::objectToggleField()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimPlotAxisRangeCalculator::RimPlotAxisRangeCalculator(QwtPlot::Axis axis,
|
||||
const std::vector<QwtPlotCurve*>& qwtCurves,
|
||||
const std::vector<double>& axisValuesForAllCurves)
|
||||
: m_singleCurves(qwtCurves)
|
||||
, m_axisValuesForAllCurves(axisValuesForAllCurves)
|
||||
RimPlotAxisLogRangeCalculator::RimPlotAxisLogRangeCalculator(QwtPlot::Axis axis,
|
||||
const std::vector<const QwtPlotCurve*>& qwtCurves)
|
||||
: m_axis(axis)
|
||||
, m_curves(qwtCurves)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimPlotAxisRangeCalculator::computeAxisRange(double* min, double* max) const
|
||||
void RimPlotAxisLogRangeCalculator::computeAxisRange(double* minPositive, double* max) const
|
||||
{
|
||||
double minValue = HUGE_VAL;
|
||||
double maxValue = -HUGE_VAL;
|
||||
double minPosValue = HUGE_VAL;
|
||||
double maxValue = -HUGE_VAL;
|
||||
|
||||
for (QwtPlotCurve* curve : m_singleCurves)
|
||||
for (const QwtPlotCurve* curve : m_curves)
|
||||
{
|
||||
double minCurveValue = HUGE_VAL;
|
||||
double maxCurveValue = -HUGE_VAL;
|
||||
double minPosCurveValue = HUGE_VAL;
|
||||
double maxCurveValue = -HUGE_VAL;
|
||||
|
||||
if (curveValueRange(curve, &minCurveValue, &maxCurveValue))
|
||||
if (curveValueRange(curve, &minPosCurveValue, &maxCurveValue))
|
||||
{
|
||||
if (minCurveValue < minValue)
|
||||
if (minPosCurveValue < minPosValue)
|
||||
{
|
||||
minValue = minCurveValue;
|
||||
CVF_ASSERT(minPosCurveValue > 0.0);
|
||||
minPosValue = minPosCurveValue;
|
||||
}
|
||||
|
||||
if (maxCurveValue > maxValue)
|
||||
@ -408,33 +410,20 @@ void RimPlotAxisRangeCalculator::computeAxisRange(double* min, double* max) cons
|
||||
}
|
||||
}
|
||||
|
||||
if (minValue == HUGE_VAL)
|
||||
if (minPosValue == HUGE_VAL)
|
||||
{
|
||||
minValue = RiaDefines::minimumDefaultValuePlot();
|
||||
maxValue = RiaDefines::maximumDefaultValuePlot();
|
||||
minPosValue = RiaDefines::minimumDefaultLogValuePlot();
|
||||
maxValue = RiaDefines::maximumDefaultValuePlot();
|
||||
}
|
||||
|
||||
// For logarithmic auto scaling, compute positive curve value closest to zero and use
|
||||
// this value as the plot visible minimum
|
||||
|
||||
double pos = HUGE_VAL;
|
||||
double neg = -HUGE_VAL;
|
||||
|
||||
RigStatisticsCalculator::posNegClosestToZero(m_axisValuesForAllCurves, pos, neg);
|
||||
|
||||
if (pos != HUGE_VAL)
|
||||
{
|
||||
minValue = pos;
|
||||
}
|
||||
|
||||
*min = minValue;
|
||||
*max = maxValue;
|
||||
|
||||
*minPositive = minPosValue;
|
||||
*max = maxValue;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimPlotAxisRangeCalculator::curveValueRange(const QwtPlotCurve* qwtCurve, double* min, double* max) const
|
||||
bool RimPlotAxisLogRangeCalculator::curveValueRange(const QwtPlotCurve* qwtCurve, double* minPositive, double* max) const
|
||||
{
|
||||
if (!qwtCurve) return false;
|
||||
|
||||
@ -443,15 +432,31 @@ bool RimPlotAxisRangeCalculator::curveValueRange(const QwtPlotCurve* qwtCurve, d
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_axis == QwtPlot::xBottom || m_axis == QwtPlot::xTop)
|
||||
float minPosF = std::numeric_limits<float>::infinity();
|
||||
float maxF = -std::numeric_limits<float>::infinity();
|
||||
|
||||
int axisValueIndex = 0;
|
||||
if (m_axis == QwtPlot::yLeft || m_axis == QwtPlot::yRight)
|
||||
{
|
||||
*min = qwtCurve->minXValue();
|
||||
*max = qwtCurve->maxXValue();
|
||||
axisValueIndex = 1;
|
||||
}
|
||||
else
|
||||
|
||||
for (size_t i = 0; i < qwtCurve->dataSize(); ++i)
|
||||
{
|
||||
*min = qwtCurve->minYValue();
|
||||
*max = qwtCurve->maxYValue();
|
||||
QPointF sample = qwtCurve->sample((int) i);
|
||||
cvf::Vec2f vec(sample.x(), sample.y());
|
||||
float value = vec[axisValueIndex];
|
||||
if (value == HUGE_VALF) continue;
|
||||
|
||||
maxF = std::max(maxF, value);
|
||||
if (value > 0.0f && value < minPosF)
|
||||
{
|
||||
minPosF = value;
|
||||
}
|
||||
}
|
||||
|
||||
*minPositive = minPosF;
|
||||
*max = maxF;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -120,20 +120,18 @@ class QwtPlotCurve;
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimPlotAxisRangeCalculator
|
||||
class RimPlotAxisLogRangeCalculator
|
||||
{
|
||||
public:
|
||||
RimPlotAxisRangeCalculator(QwtPlot::Axis axis,
|
||||
const std::vector<QwtPlotCurve*>& qwtCurves,
|
||||
const std::vector<double>& axisValuesForAllCurves);
|
||||
RimPlotAxisLogRangeCalculator(QwtPlot::Axis axis,
|
||||
const std::vector<const QwtPlotCurve*>& qwtCurves);
|
||||
|
||||
void computeAxisRange(double* min, double* max) const;
|
||||
void computeAxisRange(double* minPositive, double* max) const;
|
||||
|
||||
private:
|
||||
bool curveValueRange(const QwtPlotCurve* qwtCurve, double* min, double* max) const;
|
||||
bool curveValueRange(const QwtPlotCurve* qwtCurve, double* minPositive, double* max) const;
|
||||
|
||||
private:
|
||||
QwtPlot::Axis m_axis;
|
||||
const std::vector<QwtPlotCurve*> m_singleCurves;
|
||||
const std::vector<double> m_axisValuesForAllCurves;
|
||||
QwtPlot::Axis m_axis;
|
||||
const std::vector<const QwtPlotCurve*> m_curves;
|
||||
};
|
||||
|
@ -635,32 +635,25 @@ void RimSummaryPlot::updateZoomForAxis(RiaDefines::PlotAxis plotAxis)
|
||||
{
|
||||
if (yAxisProps->isLogarithmicScaleEnabled)
|
||||
{
|
||||
std::vector<double> yValues;
|
||||
std::vector<QwtPlotCurve*> plotCurves;
|
||||
std::vector<const QwtPlotCurve*> plotCurves;
|
||||
|
||||
for (RimSummaryCurve* c : visibleSummaryCurvesForAxis(plotAxis))
|
||||
{
|
||||
std::vector<double> curveValues = c->valuesY();
|
||||
yValues.insert(yValues.end(), curveValues.begin(), curveValues.end());
|
||||
plotCurves.push_back(c->qwtPlotCurve());
|
||||
}
|
||||
|
||||
for (RimGridTimeHistoryCurve* c : visibleTimeHistoryCurvesForAxis(plotAxis))
|
||||
{
|
||||
std::vector<double> curveValues = c->yValues();
|
||||
yValues.insert(yValues.end(), curveValues.begin(), curveValues.end());
|
||||
plotCurves.push_back(c->qwtPlotCurve());
|
||||
}
|
||||
|
||||
for (RimAsciiDataCurve* c : visibleAsciiDataCurvesForAxis(plotAxis))
|
||||
{
|
||||
std::vector<double> curveValues = c->yValues();
|
||||
yValues.insert(yValues.end(), curveValues.begin(), curveValues.end());
|
||||
plotCurves.push_back(c->qwtPlotCurve());
|
||||
}
|
||||
|
||||
double min, max;
|
||||
RimPlotAxisRangeCalculator calc(QwtPlot::yLeft, plotCurves, yValues);
|
||||
RimPlotAxisLogRangeCalculator calc(QwtPlot::yLeft, plotCurves);
|
||||
calc.computeAxisRange(&min, &max);
|
||||
|
||||
if (yAxisProps->isAxisInverted())
|
||||
|
Loading…
Reference in New Issue
Block a user