diff --git a/ApplicationLibCode/Application/Tools/RiaCurveMerger.h b/ApplicationLibCode/Application/Tools/RiaCurveMerger.h index f8bf950288..75676db362 100644 --- a/ApplicationLibCode/Application/Tools/RiaCurveMerger.h +++ b/ApplicationLibCode/Application/Tools/RiaCurveMerger.h @@ -22,6 +22,16 @@ #include +namespace RiaCurveDefines +{ +enum class InterpolationMethod +{ + STEP_LEFT, + STEP_RIGHT, + LINEAR +}; +} + template class XValueComparator { @@ -39,7 +49,8 @@ class RiaCurveMerger { public: using XComparator = XValueComparator; - RiaCurveMerger(); + + RiaCurveMerger( RiaCurveDefines::InterpolationMethod method ); void addCurveData( const std::vector& xValues, const std::vector& yValues ); size_t curveCount() const; @@ -63,8 +74,10 @@ public: public: // Helper methods, available as public to be able to access from unit tests - static double - interpolatedYValue( const XValueType& xValue, const std::vector& curveXValues, const std::vector& curveYValues ); + static double interpolatedYValue( const XValueType& xValue, + const std::vector& curveXValues, + const std::vector& curveYValues, + RiaCurveDefines::InterpolationMethod interpolationMethod ); private: void computeUnionOfXValues( bool includeValuesFromPartialCurves ); @@ -78,8 +91,9 @@ private: std::vector m_allXValues; std::vector> m_interpolatedValuesForAllCurves; - bool m_isXValuesSharedBetweenCurves; - bool m_isXValuesMonotonicallyIncreasing; + bool m_isXValuesSharedBetweenCurves; + bool m_isXValuesMonotonicallyIncreasing; + RiaCurveDefines::InterpolationMethod m_interpolationMethod; }; using RiaTimeHistoryCurveMerger = RiaCurveMerger; diff --git a/ApplicationLibCode/Application/Tools/RiaCurveMerger.inl b/ApplicationLibCode/Application/Tools/RiaCurveMerger.inl index fe0c96b0e0..954b869888 100644 --- a/ApplicationLibCode/Application/Tools/RiaCurveMerger.inl +++ b/ApplicationLibCode/Application/Tools/RiaCurveMerger.inl @@ -54,9 +54,10 @@ bool XValueComparator::equals( const XValueType& lhs, const XValueTy /// //-------------------------------------------------------------------------------------------------- template -RiaCurveMerger::RiaCurveMerger() +RiaCurveMerger::RiaCurveMerger( RiaCurveDefines::InterpolationMethod method ) : m_isXValuesSharedBetweenCurves( false ) , m_isXValuesMonotonicallyIncreasing( true ) + , m_interpolationMethod( method ) { } @@ -178,8 +179,10 @@ void RiaCurveMerger::computeInterpolatedValues( bool includeValuesFr } else { - interpolValue = - interpolatedYValue( m_allXValues[valueIndex], m_originalValues[curveIdx].first, m_originalValues[curveIdx].second ); + interpolValue = interpolatedYValue( m_allXValues[valueIndex], + m_originalValues[curveIdx].first, + m_originalValues[curveIdx].second, + m_interpolationMethod ); } if ( !RiaCurveDataTools::isValidValue( interpolValue, false ) ) @@ -263,9 +266,10 @@ void RiaCurveMerger::removeValuesForPartialCurves( std::set -double RiaCurveMerger::interpolatedYValue( const XValueType& interpolationXValue, - const std::vector& xValues, - const std::vector& yValues ) +double RiaCurveMerger::interpolatedYValue( const XValueType& interpolationXValue, + const std::vector& xValues, + const std::vector& yValues, + RiaCurveDefines::InterpolationMethod interpolationMethod ) { if ( xValues.empty() ) return HUGE_VAL; if ( yValues.size() != xValues.size() ) return HUGE_VAL; @@ -330,6 +334,16 @@ double RiaCurveMerger::interpolatedYValue( const XValueType& bool isSecondValid = RiaCurveDataTools::isValidValue( secondValue, removeInterpolatedValues ); if ( !isSecondValid ) return HUGE_VAL; + if ( interpolationMethod == RiaCurveDefines::InterpolationMethod::STEP_RIGHT ) + { + return secondValue; + } + + if ( interpolationMethod == RiaCurveDefines::InterpolationMethod::STEP_LEFT ) + { + return firstValue; + } + double firstDiff = fabs( XComparator::diff( interpolationXValue, xValues.at( firstI ) ) ); double secondDiff = fabs( XComparator::diff( xValues.at( secondI ), interpolationXValue ) ); diff --git a/ApplicationLibCode/FileInterface/RifReaderEnsembleStatisticsRft.cpp b/ApplicationLibCode/FileInterface/RifReaderEnsembleStatisticsRft.cpp index ca469ae43b..ad39df65f3 100644 --- a/ApplicationLibCode/FileInterface/RifReaderEnsembleStatisticsRft.cpp +++ b/ApplicationLibCode/FileInterface/RifReaderEnsembleStatisticsRft.cpp @@ -220,7 +220,7 @@ void RifReaderEnsembleStatisticsRft::calculateStatistics( const QString& wellNam // The TVD values is extracted from the first summary case RifEclipseRftAddress mdAddress = RifEclipseRftAddress::createAddress( wellName, timeStep, ChannelType::MD ); - RiaCurveMerger curveMerger; + RiaCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); RiaWeightedMeanCalculator dataSetSizeCalc; for ( RimSummaryCase* summaryCase : m_summaryCaseCollection->allSummaryCases() ) @@ -247,7 +247,7 @@ void RifReaderEnsembleStatisticsRft::calculateStatistics( const QString& wellNam // Compute statistics based on TVD depths. No measured depth can be estimated. // This concept works well for vertical wells, but does not work for horizontal wells. - RiaCurveMerger curveMerger; + RiaCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); RiaWeightedMeanCalculator dataSetSizeCalc; RifEclipseRftAddress tvdAddress = RifEclipseRftAddress::createAddress( wellName, timeStep, ChannelType::TVD ); diff --git a/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp b/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp index 0d516baca5..ceb9d87966 100644 --- a/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp @@ -326,7 +326,7 @@ std::optional, std::vector>> { QString leftHandSideVariableName = RimSummaryCalculation::findLeftHandSide( expression ); - RiaTimeHistoryCurveMerger timeHistoryCurveMerger; + RiaTimeHistoryCurveMerger timeHistoryCurveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); for ( size_t i = 0; i < variables.size(); i++ ) { diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.cpp index 1c1d4584e6..982c04b7a1 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.cpp @@ -316,7 +316,9 @@ std::pair, std::vector> RimDeltaSummaryCase::calcula return ResultPair(); } - RiaTimeHistoryCurveMerger merger; + auto interpolationMethod = address.hasAccumulatedData() ? RiaCurveDefines::InterpolationMethod::LINEAR + : RiaCurveDefines::InterpolationMethod::STEP_RIGHT; + RiaTimeHistoryCurveMerger merger( interpolationMethod ); merger.addCurveData( reader1->timeSteps( address ), values1 ); merger.addCurveData( reader2->timeSteps( address ), values2 ); merger.computeInterpolatedValues( includeIncompleteCurves ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp index 147e20cde4..88a5b370f2 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp @@ -157,7 +157,9 @@ void RimEnsembleStatisticsCase::calculate( const std::vector& s // The last time step for the individual realizations in an ensemble is usually identical. Add a small threshold to improve robustness. const auto timeThreshold = RiaSummaryTools::calculateTimeThreshold( minTime, maxTime ); - RiaTimeHistoryCurveMerger curveMerger; + auto interpolationMethod = inputAddress.hasAccumulatedData() ? RiaCurveDefines::InterpolationMethod::LINEAR + : RiaCurveDefines::InterpolationMethod::STEP_RIGHT; + RiaTimeHistoryCurveMerger curveMerger( interpolationMethod ); for ( const auto& sumCase : summaryCases ) { const auto& reader = sumCase->summaryReader(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index ccedea1026..12f9d926e5 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -631,7 +631,7 @@ void RimSummaryCurve::onLoadDataAndUpdate( bool updateParentPlot ) } else { - RiaTimeHistoryCurveMerger curveMerger; + RiaTimeHistoryCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); curveMerger.addCurveData( curveTimeStepsX, curveValuesX ); curveMerger.addCurveData( curveTimeStepsY, curveValuesY ); @@ -1258,7 +1258,7 @@ void RimSummaryCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField, if ( !curveValuesX.empty() && !curveValuesY.empty() ) { - RiaTimeHistoryCurveMerger curveMerger; + RiaTimeHistoryCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); curveMerger.addCurveData( curveTimeStepsX, curveValuesX ); curveMerger.addCurveData( curveTimeStepsY, curveValuesY ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurvesData.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurvesData.cpp index 4467d1299c..d72b4782dc 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurvesData.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurvesData.cpp @@ -156,8 +156,8 @@ QString RimSummaryCurvesData::createTextForExport( const std::vector exportData( 2 ); - RimSummaryCurvesData::prepareCaseCurvesForExport( resamplingPeriod, ResampleAlgorithm::DATA_DECIDES, summaryCurvesData, &exportData[0] ); - RimSummaryCurvesData::prepareCaseCurvesForExport( resamplingPeriod, ResampleAlgorithm::PERIOD_END, gridCurvesData, &exportData[1] ); + RimSummaryCurvesData::prepareCaseCurvesForExport( resamplingPeriod, summaryCurvesData, &exportData[0] ); + RimSummaryCurvesData::prepareCaseCurvesForExport( resamplingPeriod, gridCurvesData, &exportData[1] ); RimSummaryCurvesData::appendToExportData( out, exportData, showTimeAsLongString ); @@ -279,7 +279,6 @@ void RimSummaryCurvesData::populateSummaryCurvesData( std::vector curves, RimSummaryCurvesData* curvesData ); static void prepareCaseCurvesForExport( RiaDefines::DateTimePeriod period, - ResampleAlgorithm algorithm, const RimSummaryCurvesData& inputCurvesData, RimSummaryCurvesData* resultCurvesData ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index 05c320cf99..0d144997ce 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -1730,7 +1730,7 @@ bool RimSummaryPlot::updateStackedCurveDataForAxis( RiuPlotAxis plotAxis ) if ( stackingItems.empty() ) return true; - RiaCurveMerger curveMerger; + RiaCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); std::map curvePhaseCount; for ( auto stackingItem : stackingItems ) diff --git a/ApplicationLibCode/ProjectDataModel/WellLog/RimEnsembleWellLogStatistics.cpp b/ApplicationLibCode/ProjectDataModel/WellLog/RimEnsembleWellLogStatistics.cpp index b73bf44925..f63f75aa20 100644 --- a/ApplicationLibCode/ProjectDataModel/WellLog/RimEnsembleWellLogStatistics.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellLog/RimEnsembleWellLogStatistics.cpp @@ -85,8 +85,8 @@ void RimEnsembleWellLogStatistics::calculate( const std::vector& wellLogFiles, const QString& wellLogChannelName ) { - RiaCurveMerger curveMerger; - RiaCurveMerger tvdCurveMerger; + RiaCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); + RiaCurveMerger tvdCurveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); RiaWeightedMeanCalculator dataSetSizeCalc; diff --git a/ApplicationLibCode/UnitTests/RigTimeCurveHistoryMerger-Test.cpp b/ApplicationLibCode/UnitTests/RigTimeCurveHistoryMerger-Test.cpp index b4d485a3c8..bc845fe409 100644 --- a/ApplicationLibCode/UnitTests/RigTimeCurveHistoryMerger-Test.cpp +++ b/ApplicationLibCode/UnitTests/RigTimeCurveHistoryMerger-Test.cpp @@ -12,26 +12,28 @@ TEST( RiaTimeHistoryCurveMergerTest, TestDateInterpolation ) std::vector values{ 2.0, 3.5, 5.0, 6.0 }; std::vector timeSteps{ 1, 5, 10, 15 }; + auto interpolationMethod = RiaCurveDefines::InterpolationMethod::LINEAR; + { - double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 1, timeSteps, values ); + double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 1, timeSteps, values, interpolationMethod ); EXPECT_EQ( 2.0, val ); } { - double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 0, timeSteps, values ); + double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 0, timeSteps, values, interpolationMethod ); EXPECT_EQ( HUGE_VAL, val ); } { - double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 20, timeSteps, values ); + double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 20, timeSteps, values, interpolationMethod ); EXPECT_EQ( HUGE_VAL, val ); } { - double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 3, timeSteps, values ); + double val = RiaTimeHistoryCurveMerger::interpolatedYValue( 3, timeSteps, values, interpolationMethod ); EXPECT_EQ( 2.75, val ); } @@ -53,7 +55,7 @@ TEST( RiaTimeHistoryCurveMergerTest, ExtractIntervalsWithSameTimeSteps ) timeSteps.push_back( i ); } - RiaTimeHistoryCurveMerger interpolate; + RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR ); interpolate.addCurveData( timeSteps, valuesA ); interpolate.addCurveData( timeSteps, valuesB ); interpolate.computeInterpolatedValues( true ); @@ -81,7 +83,7 @@ TEST( RiaTimeHistoryCurveMergerTest, ExtractIntervalsWithSameTimeStepsOneComplet timeSteps.push_back( i ); } - RiaTimeHistoryCurveMerger interpolate; + RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR ); interpolate.addCurveData( timeSteps, valuesA ); interpolate.addCurveData( timeSteps, valuesB ); interpolate.computeInterpolatedValues( true ); @@ -109,7 +111,7 @@ TEST( RiaTimeHistoryCurveMergerTest, ExtractIntervalsWithSameTimeStepsBothComple timeSteps.push_back( i ); } - RiaTimeHistoryCurveMerger interpolate; + RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR ); interpolate.addCurveData( timeSteps, valuesA ); interpolate.addCurveData( timeSteps, valuesB ); interpolate.computeInterpolatedValues( true ); @@ -134,7 +136,7 @@ TEST( RiaTimeHistoryCurveMergerTest, OverlappintTimes ) std::vector timeStepsA{ 0, 10, 11, 15, 20 }; std::vector timeStepsB{ 1, 2, 3, 5, 7 }; - RiaTimeHistoryCurveMerger interpolate; + RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR ); interpolate.addCurveData( timeStepsA, valuesA ); interpolate.addCurveData( timeStepsB, valuesB ); interpolate.computeInterpolatedValues( true ); @@ -153,7 +155,7 @@ TEST( RiaTimeHistoryCurveMergerTest, OverlappintTimes ) TEST( RiaTimeHistoryCurveMergerTest, RobustUse ) { { - RiaTimeHistoryCurveMerger curveMerger; + RiaTimeHistoryCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); curveMerger.computeInterpolatedValues( true ); EXPECT_EQ( 0, static_cast( curveMerger.allXValues().size() ) ); } @@ -165,7 +167,7 @@ TEST( RiaTimeHistoryCurveMergerTest, RobustUse ) std::vector timeStepsB{ 1, 2, 3 }; { - RiaTimeHistoryCurveMerger curveMerger; + RiaTimeHistoryCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); curveMerger.addCurveData( timeStepsA, valuesA ); curveMerger.computeInterpolatedValues( true ); EXPECT_EQ( timeStepsA.size(), curveMerger.allXValues().size() ); @@ -173,7 +175,7 @@ TEST( RiaTimeHistoryCurveMergerTest, RobustUse ) } { - RiaTimeHistoryCurveMerger curveMerger; + RiaTimeHistoryCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); curveMerger.addCurveData( timeStepsA, valuesA ); curveMerger.addCurveData( timeStepsB, valuesB ); @@ -198,7 +200,7 @@ TEST( RiaTimeHistoryCurveMergerTest, NoTimeStepOverlap ) std::vector timeStepsB{ 100, 200, 300 }; { - RiaTimeHistoryCurveMerger curveMerger; + RiaTimeHistoryCurveMerger curveMerger( RiaCurveDefines::InterpolationMethod::LINEAR ); curveMerger.addCurveData( timeStepsA, valuesA ); curveMerger.addCurveData( timeStepsB, valuesB ); @@ -218,7 +220,7 @@ TEST( RiaTimeHistoryCurveMergerTest, SharedXValues ) std::vector valuesB{ 10, 20, 30, 40, 50, 60, 70 }; std::vector timeSteps{ 1, 2, 3, 4, 5, 6, 7 }; - RiaTimeHistoryCurveMerger interpolate; + RiaTimeHistoryCurveMerger interpolate( RiaCurveDefines::InterpolationMethod::LINEAR ); interpolate.addCurveData( timeSteps, valuesA ); interpolate.addCurveData( timeSteps, valuesB ); interpolate.computeInterpolatedValues( true );