diff --git a/ApplicationLibCode/Application/Tools/RiaCurveMerger.h b/ApplicationLibCode/Application/Tools/RiaCurveMerger.h index b8a98458c7..b6a4965f17 100644 --- a/ApplicationLibCode/Application/Tools/RiaCurveMerger.h +++ b/ApplicationLibCode/Application/Tools/RiaCurveMerger.h @@ -44,7 +44,7 @@ public: void addCurveData( const std::vector& xValues, const std::vector& yValues ); size_t curveCount() const; - void computeInterpolatedValues( bool includeValuesFromPartialCurves = true ); + void computeInterpolatedValues( bool includeValuesFromPartialCurves ); RiaCurveDataTools::CurveIntervals validIntervalsForAllXValues() const; const std::vector& allXValues() const; diff --git a/ApplicationLibCode/Application/Tools/Summary/RiaSummaryTools.cpp b/ApplicationLibCode/Application/Tools/Summary/RiaSummaryTools.cpp index c37ef5914d..9c40bab613 100644 --- a/ApplicationLibCode/Application/Tools/Summary/RiaSummaryTools.cpp +++ b/ApplicationLibCode/Application/Tools/Summary/RiaSummaryTools.cpp @@ -430,3 +430,15 @@ void RiaSummaryTools::reloadSummaryEnsemble( RimSummaryEnsemble* ensemble ) multiPlot->updatePlotTitles(); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +time_t RiaSummaryTools::calculateTimeThreshold( const time_t& minimum, const time_t& maximum ) +{ + // The cutoff time is the time where the time step is less than 1% of the total time range + const auto epsilon = 0.01; + const auto timeThreshold = maximum - ( maximum - minimum ) * epsilon; + + return timeThreshold; +} diff --git a/ApplicationLibCode/Application/Tools/Summary/RiaSummaryTools.h b/ApplicationLibCode/Application/Tools/Summary/RiaSummaryTools.h index b97b8a52c0..e3f3e4a06b 100644 --- a/ApplicationLibCode/Application/Tools/Summary/RiaSummaryTools.h +++ b/ApplicationLibCode/Application/Tools/Summary/RiaSummaryTools.h @@ -97,6 +97,8 @@ public: static void reloadSummaryCase( RimSummaryCase* summaryCase ); static void reloadSummaryEnsemble( RimSummaryEnsemble* ensemble ); + static time_t calculateTimeThreshold( const time_t& minimum, const time_t& maximum ); + private: static void updateRequiredCalculatedCurves( RimSummaryCase* sourceSummaryCase ); static bool isCalculationRequired( const RimUserDefinedCalculation* summaryCalculation, const RimSummaryCase* summaryCase ); diff --git a/ApplicationLibCode/FileInterface/RifReaderEnsembleStatisticsRft.cpp b/ApplicationLibCode/FileInterface/RifReaderEnsembleStatisticsRft.cpp index 379c3671c6..ca469ae43b 100644 --- a/ApplicationLibCode/FileInterface/RifReaderEnsembleStatisticsRft.cpp +++ b/ApplicationLibCode/FileInterface/RifReaderEnsembleStatisticsRft.cpp @@ -294,7 +294,8 @@ void RifReaderEnsembleStatisticsRft::extractStatisticsFromCurveMerger( const QSt clearCache( wellName, timeStep ); - curveMerger.computeInterpolatedValues( false ); + bool includeValuesFromPartialCurves = false; + curveMerger.computeInterpolatedValues( includeValuesFromPartialCurves ); const std::vector& allDepths = curveMerger.allXValues(); if ( !allDepths.empty() ) diff --git a/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimAnalysisPlot.cpp b/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimAnalysisPlot.cpp index d7ae8c1ed4..2362ac131d 100644 --- a/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimAnalysisPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/AnalysisPlots/RimAnalysisPlot.cpp @@ -1447,7 +1447,8 @@ void RimAnalysisPlot::addDataToChartBuilder( RiuGroupedBarChartBuilder& chartBui referenceCaseReader, -1, DerivedSummaryOperator::DERIVED_OPERATOR_SUB, - curveDef.summaryAddressY() ); + curveDef.summaryAddressY(), + true ); timeSteps.swap( timeAndValues.first ); values.swap( timeAndValues.second ); } diff --git a/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp b/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp index ae35be37e4..4f8d485420 100644 --- a/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimSummaryCalculation.cpp @@ -345,7 +345,8 @@ std::optional, std::vector>> } } - timeHistoryCurveMerger.computeInterpolatedValues(); + bool includeValuesFromPartialCurves = true; + timeHistoryCurveMerger.computeInterpolatedValues( includeValuesFromPartialCurves ); ExpressionParser parser; for ( size_t i = 0; i < variables.size(); i++ ) diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.cpp index c12178cb21..1c1d4584e6 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.cpp @@ -21,6 +21,7 @@ #include "RiaCurveMerger.h" #include "RiaLogging.h" #include "RiaQDateTimeTools.h" +#include "Summary/RiaSummaryTools.h" #include "RimDeltaSummaryEnsemble.h" #include "RimProject.h" @@ -96,7 +97,7 @@ std::pair> RimDeltaSummaryCase::values( const RifEclip if ( auto deltaEnsemble = firstAncestorOfType() ) { - if ( deltaEnsemble->discardSummaryAddressOnlyPresentInOneCase() ) + if ( deltaEnsemble->discardMissingOrIncompleteRealizations() ) { RifSummaryReaderInterface* reader1 = m_summaryCase1 ? m_summaryCase1->summaryReader() : nullptr; RifSummaryReaderInterface* reader2 = m_summaryCase2 ? m_summaryCase2->summaryReader() : nullptr; @@ -125,6 +126,36 @@ std::pair> RimDeltaSummaryCase::values( const RifEclip return { false, {} }; } + if ( auto deltaEnsemble = firstAncestorOfType() ) + { + if ( deltaEnsemble->discardMissingOrIncompleteRealizations() ) + { + auto ensembleTimeSteps = deltaEnsemble->ensembleTimeSteps(); + + auto caseTimeSteps = m_dataCache.at( resultAddress ).first; + + if ( !ensembleTimeSteps.empty() && !caseTimeSteps.empty() ) + { + const auto minTime = *std::min_element( ensembleTimeSteps.begin(), ensembleTimeSteps.end() ); + const auto maxTime = *std::max_element( ensembleTimeSteps.begin(), ensembleTimeSteps.end() ); + + // 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 ); + + if ( *caseTimeSteps.rbegin() < timeThreshold ) + { + QString txt = "Summary vector " + QString::fromStdString( resultAddress.toEclipseTextAddress() ) + + " has different time steps in the source ensembles, no values are calculated for this vector."; + + RiaLogging::warning( txt ); + + return { false, {} }; + } + } + } + } + return { true, m_dataCache.at( resultAddress ).second }; } @@ -187,6 +218,8 @@ void RimDeltaSummaryCase::setSummaryCases( RimSummaryCase* sumCase1, RimSummaryC { m_summaryCase1 = sumCase1; m_summaryCase2 = sumCase2; + + clearCache(); } //-------------------------------------------------------------------------------------------------- @@ -218,8 +251,15 @@ void RimDeltaSummaryCase::calculate( const RifEclipseSummaryAddress& address ) c fixedTimeStepCase2 = m_fixedTimeStepIndex; } + bool includeIncompleteCurves = true; + if ( auto deltaEnsemble = firstAncestorOfType() ) + { + includeIncompleteCurves = !deltaEnsemble->discardMissingOrIncompleteRealizations(); + } + auto itAndIsInsertedPair = m_dataCache.insert( - std::make_pair( address, calculateDerivedValues( reader1, fixedTimeStepCase1, reader2, fixedTimeStepCase2, m_operator(), address ) ) ); + std::make_pair( address, + calculateDerivedValues( reader1, fixedTimeStepCase1, reader2, fixedTimeStepCase2, m_operator(), address, includeIncompleteCurves ) ) ); // Check if we got any data. If not, erase the map entry to comply with previous behavior @@ -237,7 +277,8 @@ std::pair, std::vector> RimDeltaSummaryCase::calcula RifSummaryReaderInterface* reader2, int fixedTimeStepCase2, DerivedSummaryOperator summaryOperator, - const RifEclipseSummaryAddress& address ) + const RifEclipseSummaryAddress& address, + bool includeIncompleteCurves ) { using ResultPair = std::pair, std::vector>; @@ -278,7 +319,7 @@ std::pair, std::vector> RimDeltaSummaryCase::calcula RiaTimeHistoryCurveMerger merger; merger.addCurveData( reader1->timeSteps( address ), values1 ); merger.addCurveData( reader2->timeSteps( address ), values2 ); - merger.computeInterpolatedValues(); + merger.computeInterpolatedValues( includeIncompleteCurves ); const std::vector& allValues1 = merger.interpolatedYValuesForAllXValues( 0 ); const std::vector& allValues2 = merger.interpolatedYValuesForAllXValues( 1 ); @@ -321,12 +362,20 @@ QString RimDeltaSummaryCase::caseName() const //-------------------------------------------------------------------------------------------------- void RimDeltaSummaryCase::createSummaryReaderInterface() { + m_allResultAddresses.clear(); + if ( m_summaryCase1 ) { if ( !m_summaryCase1->summaryReader() ) { m_summaryCase1->createSummaryReaderInterface(); } + + if ( m_summaryCase1->summaryReader() ) + { + auto adr = m_summaryCase1->summaryReader()->allResultAddresses(); + m_allResultAddresses.insert( adr.begin(), adr.end() ); + } } if ( m_summaryCase2 ) { @@ -334,6 +383,12 @@ void RimDeltaSummaryCase::createSummaryReaderInterface() { m_summaryCase2->createSummaryReaderInterface(); } + + if ( m_summaryCase2->summaryReader() ) + { + auto adr = m_summaryCase2->summaryReader()->allResultAddresses(); + m_allResultAddresses.insert( adr.begin(), adr.end() ); + } } } @@ -351,6 +406,8 @@ RifSummaryReaderInterface* RimDeltaSummaryCase::summaryReader() void RimDeltaSummaryCase::setOperator( DerivedSummaryOperator oper ) { m_operator = oper; + + clearCache(); } //-------------------------------------------------------------------------------------------------- @@ -380,6 +437,14 @@ void RimDeltaSummaryCase::clearData( const RifEclipseSummaryAddress& address ) c m_dataCache.erase( address ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimDeltaSummaryCase::clearCache() +{ + m_dataCache.clear(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.h b/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.h index 39b9152fe9..0709cafbce 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryCase.h @@ -75,7 +75,8 @@ public: RifSummaryReaderInterface* reader2, int fixedTimeStepCase2, DerivedSummaryOperator m_operator, - const RifEclipseSummaryAddress& address ); + const RifEclipseSummaryAddress& address, + bool includeIncompleteCurves ); void createSummaryReaderInterface() override; RifSummaryReaderInterface* summaryReader() override; @@ -98,6 +99,8 @@ private: void calculate( const RifEclipseSummaryAddress& address ) const; void clearData( const RifEclipseSummaryAddress& address ) const; + void clearCache(); + private: caf::PdmPtrField m_summaryCase1; caf::PdmPtrField m_summaryCase2; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryEnsemble.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryEnsemble.cpp index dfb83d6108..3137395d92 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryEnsemble.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryEnsemble.cpp @@ -76,11 +76,11 @@ RimDeltaSummaryEnsemble::RimDeltaSummaryEnsemble() CAF_PDM_InitField( &m_matchOnParameters, "MatchOnParameters", false, "Match On Parameters" ); caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_matchOnParameters ); - CAF_PDM_InitField( &m_discardAddressPresentInOneSourceCase, - "DiscardAddressPresentInOneSourceCase", - false, - "Discard Vectors if Missing in One of the Source Ensembles" ); - caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_discardAddressPresentInOneSourceCase ); + CAF_PDM_InitField( &m_discardMissingOrIncompleteRealizations, + "DiscardMissingOrIncompleteRealizations", + true, + "Discard Missing or Incomplete Realizations" ); + caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_discardMissingOrIncompleteRealizations ); CAF_PDM_InitFieldNoDefault( &m_useFixedTimeStep, "UseFixedTimeStep", "Use Fixed Time Step" ); CAF_PDM_InitField( &m_fixedTimeStepIndex, "FixedTimeStepIndex", 0, "Time Step" ); @@ -206,9 +206,9 @@ void RimDeltaSummaryEnsemble::createDerivedEnsembleCases() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool RimDeltaSummaryEnsemble::discardSummaryAddressOnlyPresentInOneCase() const +bool RimDeltaSummaryEnsemble::discardMissingOrIncompleteRealizations() const { - return m_discardAddressPresentInOneSourceCase(); + return m_discardMissingOrIncompleteRealizations(); } //-------------------------------------------------------------------------------------------------- @@ -314,7 +314,7 @@ void RimDeltaSummaryEnsemble::defineUiOrdering( QString uiConfigName, caf::PdmUi } uiOrdering.add( &m_matchOnParameters ); - uiOrdering.add( &m_discardAddressPresentInOneSourceCase ); + uiOrdering.add( &m_discardMissingOrIncompleteRealizations ); uiOrdering.skipRemainingFields( true ); @@ -337,7 +337,8 @@ void RimDeltaSummaryEnsemble::fieldChangedByUi( const caf::PdmFieldHandle* chang doUpdateCases = true; doShowDialog = true; } - else if ( changedField == &m_operator || changedField == &m_useFixedTimeStep || changedField == &m_fixedTimeStepIndex ) + else if ( changedField == &m_operator || changedField == &m_useFixedTimeStep || changedField == &m_fixedTimeStepIndex || + changedField == &m_discardMissingOrIncompleteRealizations ) { doUpdate = true; doUpdateCases = true; @@ -370,12 +371,12 @@ void RimDeltaSummaryEnsemble::fieldChangedByUi( const caf::PdmFieldHandle* chang } } - updateReferringCurveSets(); + updateReferringCurveSetsZoomAll(); // If other derived ensembles are referring to this ensemble, update their cases as well for ( auto refering : findReferringEnsembles() ) { - refering->updateReferringCurveSets(); + refering->updateReferringCurveSetsZoomAll(); } } } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryEnsemble.h b/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryEnsemble.h index 20c1e92547..ca56819b75 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryEnsemble.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimDeltaSummaryEnsemble.h @@ -62,7 +62,7 @@ public: void createDerivedEnsembleCases(); - bool discardSummaryAddressOnlyPresentInOneCase() const; + bool discardMissingOrIncompleteRealizations() const; private: QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; @@ -93,7 +93,7 @@ private: caf::PdmField m_swapEnsemblesButton; caf::PdmField m_caseCount; caf::PdmField m_matchOnParameters; - caf::PdmField m_discardAddressPresentInOneSourceCase; + caf::PdmField m_discardMissingOrIncompleteRealizations; caf::PdmField> m_useFixedTimeStep; caf::PdmField m_fixedTimeStepIndex; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp index ae9c5c659d..880da03297 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp @@ -341,6 +341,9 @@ void RimEnsembleCurveSet::loadDataAndUpdate( bool updateParentPlot ) { m_yValuesSummaryAddressUiField = m_yValuesSummaryAddress->address(); + // Recreate the statistics case, as the statistics data is cached internally + m_ensembleStatCaseY = std::make_unique(); + m_curveFilters->loadDataAndUpdate(); updateAddressesUiField(); @@ -1168,6 +1171,13 @@ void RimEnsembleCurveSet::defineUiOrdering( QString uiConfigName, caf::PdmUiOrde m_statistics->defaultUiOrdering( isXAxisSummaryVector(), *statGroup ); + bool enableIncomplete = true; + if ( dynamic_cast( m_yValuesSummaryEnsemble() ) ) + { + enableIncomplete = false; + } + m_statistics->enableIncludeIncompleteCurves( enableIncomplete ); + caf::PdmUiGroup* statAppearance = statGroup->addNewGroupWithKeyword( "Appearance", "StatisticsAppearance" ); statAppearance->add( &m_statisticsUseCustomAppearance ); if ( m_statisticsUseCustomAppearance() == AppearanceMode::CUSTOM ) diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.cpp index 82d3dd19c1..7269078402 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.cpp @@ -164,6 +164,14 @@ void RimEnsembleStatistics::enableCurveLabels( bool enable ) m_showCurveLabels = enable; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleStatistics::enableIncludeIncompleteCurves( bool enable ) +{ + m_includeIncompleteCurves.uiCapability()->setUiReadOnly( !enable ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.h index f51b797a2b..cb7d1c3a11 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatistics.h @@ -48,6 +48,8 @@ public: bool showCurveLabels() const; void enableCurveLabels( bool enable ); + void enableIncludeIncompleteCurves( bool enable ); + cvf::Color3f color() const { return m_color; } void setColor( const cvf::Color3f& color ); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp index ed7e53a7ad..241b9bc5e4 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp @@ -143,14 +143,14 @@ void RimEnsembleStatisticsCase::calculate( const std::vector& s // Use first summary case to get unit system and other meta data m_firstSummaryCase = summaryCases.front(); - const auto [minTime, maxTime] = findMinMaxTime( summaryCases, inputAddress ); - RiaDefines::DateTimePeriod period = findBestResamplingPeriod( minTime, maxTime ); + const auto [minTime, maxTime] = findMinMaxTime( summaryCases, inputAddress ); // The last time step for the individual realizations in an ensemble is usually identical. Add a small threshold to improve robustness. - const auto timeThreshold = maxTime - ( maxTime - minTime ) * 0.01; + const auto timeThreshold = RiaSummaryTools::calculateTimeThreshold( minTime, maxTime ); + + RiaDefines::DateTimePeriod period = findBestResamplingPeriod( minTime, maxTime ); RiaTimeHistoryCurveMerger curveMerger; - for ( const auto& sumCase : summaryCases ) { const auto& reader = sumCase->summaryReader(); @@ -169,7 +169,7 @@ void RimEnsembleStatisticsCase::calculate( const std::vector& s } } - curveMerger.computeInterpolatedValues(); + curveMerger.computeInterpolatedValues( includeIncompleteCurves ); std::vector> curveValues; for ( size_t i = 0; i < curveMerger.curveCount(); i++ ) diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp index c4bc937460..983c31468d 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseMainCollection.cpp @@ -201,7 +201,7 @@ void RimSummaryCaseMainCollection::removeCases( std::vector& ca for ( RimSummaryEnsemble* summaryCaseCollection : m_caseCollections ) { - summaryCaseCollection->updateReferringCurveSets(); + summaryCaseCollection->updateReferringCurveSetsZoomAll(); } dataSourceHasChanged.send(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp index 4804a14052..aa26c11c4b 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurve.cpp @@ -655,7 +655,9 @@ void RimSummaryCurve::onLoadDataAndUpdate( bool updateParentPlot ) RiaTimeHistoryCurveMerger curveMerger; curveMerger.addCurveData( curveTimeStepsX, curveValuesX ); curveMerger.addCurveData( curveTimeStepsY, curveValuesY ); - curveMerger.computeInterpolatedValues(); + + bool includeValuesFromPartialCurves = true; + curveMerger.computeInterpolatedValues( includeValuesFromPartialCurves ); if ( !curveMerger.allXValues().empty() ) { @@ -1285,7 +1287,9 @@ void RimSummaryCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField, RiaTimeHistoryCurveMerger curveMerger; curveMerger.addCurveData( curveTimeStepsX, curveValuesX ); curveMerger.addCurveData( curveTimeStepsY, curveValuesY ); - curveMerger.computeInterpolatedValues(); + + bool includeValuesFromPartialCurves = true; + curveMerger.computeInterpolatedValues( includeValuesFromPartialCurves ); if ( curveMerger.validIntervalsForAllXValues().empty() ) { diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.cpp index 75132976a1..3d503c04df 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.cpp @@ -32,6 +32,7 @@ #include "RimSummaryAddressCollection.h" #include "RimSummaryCase.h" #include "RimSummaryEnsembleTools.h" +#include "RimSummaryPlot.h" #include "cafPdmFieldScriptingCapability.h" #include "cafPdmObjectScriptingCapability.h" @@ -103,7 +104,7 @@ void RimSummaryEnsemble::removeCase( RimSummaryCase* summaryCase, bool notifyCha if ( notifyChange ) { - updateReferringCurveSets(); + updateReferringCurveSetsZoomAll(); } if ( m_isEnsemble && m_cases.size() != caseCountBeforeRemove ) @@ -134,7 +135,7 @@ void RimSummaryEnsemble::addCase( RimSummaryCase* summaryCase ) if ( !derivedEnsemble ) continue; derivedEnsemble->createDerivedEnsembleCases(); - derivedEnsemble->updateReferringCurveSets(); + derivedEnsemble->updateReferringCurveSetsZoomAll(); } if ( m_isEnsemble ) @@ -143,7 +144,7 @@ void RimSummaryEnsemble::addCase( RimSummaryCase* summaryCase ) calculateEnsembleParametersIntersectionHash(); } - updateReferringCurveSets(); + updateReferringCurveSetsZoomAll(); clearChildNodes(); } @@ -616,7 +617,7 @@ void RimSummaryEnsemble::onLoadDataAndUpdate() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSummaryEnsemble::updateReferringCurveSets() +void RimSummaryEnsemble::updateReferringCurveSets( bool doZoomAll ) { // Update curve set referring to this group std::vector referringObjects = objectsWithReferringPtrFieldsOfType(); @@ -629,10 +630,34 @@ void RimSummaryEnsemble::updateReferringCurveSets() if ( curveSet ) { curveSet->loadDataAndUpdate( updateParentPlot ); + + if ( doZoomAll ) + { + if ( auto parentPlot = curveSet->firstAncestorOrThisOfType() ) + { + parentPlot->zoomAll(); + } + } } } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryEnsemble::updateReferringCurveSets() +{ + updateReferringCurveSets( false ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimSummaryEnsemble::updateReferringCurveSetsZoomAll() +{ + updateReferringCurveSets( true ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.h index d2dbb334ea..8e87fe4869 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.h @@ -98,6 +98,7 @@ public: void onCalculationUpdated(); void updateReferringCurveSets(); + void updateReferringCurveSetsZoomAll(); RiaSummaryAddressAnalyzer* addressAnalyzer(); @@ -110,6 +111,8 @@ private: QString nameAndItemCount() const; void updateIcon(); + void updateReferringCurveSets( bool doZoomAll ); + void initAfterRead() override; void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; diff --git a/ApplicationLibCode/ProjectDataModel/WellLog/RimEnsembleWellLogStatistics.cpp b/ApplicationLibCode/ProjectDataModel/WellLog/RimEnsembleWellLogStatistics.cpp index cbb9cd6367..b73bf44925 100644 --- a/ApplicationLibCode/ProjectDataModel/WellLog/RimEnsembleWellLogStatistics.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellLog/RimEnsembleWellLogStatistics.cpp @@ -125,8 +125,9 @@ void RimEnsembleWellLogStatistics::calculate( const std::vector( interpolate.curveCount() ) ); auto interpolatedTimeSteps = interpolate.allXValues(); @@ -154,7 +154,7 @@ TEST( RiaTimeHistoryCurveMergerTest, RobustUse ) { { RiaTimeHistoryCurveMerger curveMerger; - curveMerger.computeInterpolatedValues(); + curveMerger.computeInterpolatedValues( true ); EXPECT_EQ( 0, static_cast( curveMerger.allXValues().size() ) ); } @@ -167,7 +167,7 @@ TEST( RiaTimeHistoryCurveMergerTest, RobustUse ) { RiaTimeHistoryCurveMerger curveMerger; curveMerger.addCurveData( timeStepsA, valuesA ); - curveMerger.computeInterpolatedValues(); + curveMerger.computeInterpolatedValues( true ); EXPECT_EQ( timeStepsA.size(), curveMerger.allXValues().size() ); EXPECT_EQ( timeStepsA.size(), curveMerger.interpolatedYValuesForAllXValues( 0 ).size() ); } @@ -178,8 +178,8 @@ TEST( RiaTimeHistoryCurveMergerTest, RobustUse ) curveMerger.addCurveData( timeStepsB, valuesB ); // Execute interpolation twice is allowed - curveMerger.computeInterpolatedValues(); - curveMerger.computeInterpolatedValues(); + curveMerger.computeInterpolatedValues( true ); + curveMerger.computeInterpolatedValues( true ); EXPECT_EQ( 8, static_cast( curveMerger.allXValues().size() ) ); EXPECT_EQ( 8, static_cast( curveMerger.interpolatedYValuesForAllXValues( 0 ).size() ) ); EXPECT_EQ( 8, static_cast( curveMerger.interpolatedYValuesForAllXValues( 1 ).size() ) ); @@ -203,7 +203,7 @@ TEST( RiaTimeHistoryCurveMergerTest, NoTimeStepOverlap ) curveMerger.addCurveData( timeStepsB, valuesB ); // Execute interpolation twice is allowed - curveMerger.computeInterpolatedValues(); + curveMerger.computeInterpolatedValues( true ); EXPECT_EQ( 8, static_cast( curveMerger.allXValues().size() ) ); EXPECT_EQ( 0, static_cast( curveMerger.validIntervalsForAllXValues().size() ) ); }