diff --git a/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.cpp b/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.cpp index 13d334314c..ede8e17170 100644 --- a/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.cpp +++ b/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.cpp @@ -182,7 +182,7 @@ std::set RiaSummaryAddressAnalyzer::aquifers() const //-------------------------------------------------------------------------------------------------- std::set RiaSummaryAddressAnalyzer::categories() const { - return m_categories; + return keysInMap( m_categories ); } //-------------------------------------------------------------------------------------------------- @@ -312,6 +312,18 @@ std::string RiaSummaryAddressAnalyzer::correspondingHistorySummaryCurveName( con return curveName + historyIdentifier; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set + RiaSummaryAddressAnalyzer::vectorNamesForCategory( RifEclipseSummaryAddress::SummaryVarCategory category ) +{ + auto it = m_categories.find( category ); + if ( it != m_categories.end() ) return it->second; + + return {}; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -433,7 +445,12 @@ void RiaSummaryAddressAnalyzer::analyzeSingleAddress( const RifEclipseSummaryAdd if ( address.category() != RifEclipseSummaryAddress::SUMMARY_INVALID ) { - m_categories.insert( address.category() ); + if ( m_categories.count( address.category() ) == 0 ) + { + m_categories[address.category()] = { address.vectorName() }; + } + else + m_categories[address.category()].insert( address.vectorName() ); } } @@ -463,6 +480,20 @@ std::set RiaSummaryAddressAnalyzer::keysInMap( const std::multimap RiaSummaryAddressAnalyzer::keysInMap( + const std::map>& map ) +{ + std::set keys; + for ( const auto& [key, value] : map ) + { + keys.insert( key ); + } + return keys; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.h b/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.h index 6a73167784..685470a417 100644 --- a/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.h +++ b/ApplicationLibCode/Application/Tools/RiaSummaryAddressAnalyzer.h @@ -69,6 +69,8 @@ public: static std::string correspondingHistorySummaryCurveName( const std::string& curveName ); + std::set vectorNamesForCategory( RifEclipseSummaryAddress::SummaryVarCategory category ); + private: void assignCategoryToQuantities() const; void computeQuantityNamesWithHistory() const; @@ -77,6 +79,8 @@ private: static std::set keysInMap( const std::multimap& map ); static std::set keysInMap( const std::multimap& map ); + static std::set + keysInMap( const std::map>& map ); static std::vector> valuesInMap( const std::multimap& map ); @@ -98,5 +102,5 @@ private: std::multimap m_blocks; std::multimap m_aquifers; - std::set m_categories; + std::map> m_categories; }; diff --git a/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.cpp b/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.cpp index bb522a0584..697c33bdab 100644 --- a/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.cpp +++ b/ApplicationLibCode/FileInterface/RifEclipseSummaryAddress.cpp @@ -727,6 +727,10 @@ RifEclipseSummaryAddress RifEclipseSummaryAddress::fromTokens( const std::vector std::string token1; std::string token2; + int intValue0 = 0; + int intValue1 = 0; + int intValue2 = 0; + vectorName = tokens[0]; if ( tokens.size() > 1 ) token1 = tokens[1]; @@ -740,7 +744,11 @@ RifEclipseSummaryAddress RifEclipseSummaryAddress::fromTokens( const std::vector return fieldAddress( vectorName ); case SUMMARY_AQUIFER: - if ( !token1.empty() ) return aquiferAddress( vectorName, RiaStdStringTools::toInt( token1 ) ); + if ( !token1.empty() ) + { + RiaStdStringTools::toInt( token1, intValue0 ); + return aquiferAddress( vectorName, intValue0 ); + } break; case SUMMARY_NETWORK: @@ -752,7 +760,11 @@ RifEclipseSummaryAddress RifEclipseSummaryAddress::fromTokens( const std::vector break; case SUMMARY_REGION: - if ( !token1.empty() ) return regionAddress( vectorName, RiaStdStringTools::toInt( token1 ) ); + if ( !token1.empty() ) + { + RiaStdStringTools::toInt( token1, intValue0 ); + return regionAddress( vectorName, intValue0 ); + } break; case SUMMARY_REGION_2_REGION: @@ -761,9 +773,10 @@ RifEclipseSummaryAddress RifEclipseSummaryAddress::fromTokens( const std::vector auto regions = RiaStdStringTools::splitString( token1, '-' ); if ( regions.size() == 2 ) { - return regionToRegionAddress( vectorName, - RiaStdStringTools::toInt( regions[0] ), - RiaStdStringTools::toInt( regions[1] ) ); + RiaStdStringTools::toInt( regions[0], intValue0 ); + RiaStdStringTools::toInt( regions[1], intValue1 ); + + return regionToRegionAddress( vectorName, intValue0, intValue1 ); } } break; @@ -782,11 +795,11 @@ RifEclipseSummaryAddress RifEclipseSummaryAddress::fromTokens( const std::vector auto ijk = RiaStdStringTools::splitString( token2, ',' ); if ( ijk.size() == 3 ) { - return wellCompletionAddress( vectorName, - token1, - RiaStdStringTools::toInt( ijk[0] ), - RiaStdStringTools::toInt( ijk[1] ), - RiaStdStringTools::toInt( ijk[2] ) ); + RiaStdStringTools::toInt( ijk[0], intValue0 ); + RiaStdStringTools::toInt( ijk[1], intValue1 ); + RiaStdStringTools::toInt( ijk[2], intValue2 ); + + return wellCompletionAddress( vectorName, token1, intValue0, intValue1, intValue2 ); } } break; @@ -802,18 +815,23 @@ RifEclipseSummaryAddress RifEclipseSummaryAddress::fromTokens( const std::vector auto ijk = RiaStdStringTools::splitString( token3, ',' ); if ( ijk.size() == 3 ) { - return wellCompletionLgrAddress( vectorName, - token1, - token2, - RiaStdStringTools::toInt( ijk[0] ), - RiaStdStringTools::toInt( ijk[1] ), - RiaStdStringTools::toInt( ijk[2] ) ); + RiaStdStringTools::toInt( ijk[0], intValue0 ); + RiaStdStringTools::toInt( ijk[1], intValue1 ); + RiaStdStringTools::toInt( ijk[2], intValue2 ); + + return wellCompletionLgrAddress( vectorName, token1, token2, intValue0, intValue1, intValue2 ); } } break; case SUMMARY_WELL_SEGMENT: - if ( !token2.empty() ) return wellSegmentAddress( vectorName, token1, RiaStdStringTools::toInt( token2 ) ); + + if ( !token2.empty() ) + { + RiaStdStringTools::toInt( token2, intValue0 ); + + return wellSegmentAddress( vectorName, token1, intValue0 ); + } break; case SUMMARY_BLOCK: @@ -822,10 +840,11 @@ RifEclipseSummaryAddress RifEclipseSummaryAddress::fromTokens( const std::vector auto ijk = RiaStdStringTools::splitString( token1, ',' ); if ( ijk.size() == 3 ) { - return blockAddress( vectorName, - RiaStdStringTools::toInt( ijk[0] ), - RiaStdStringTools::toInt( ijk[1] ), - RiaStdStringTools::toInt( ijk[2] ) ); + RiaStdStringTools::toInt( ijk[0], intValue0 ); + RiaStdStringTools::toInt( ijk[1], intValue1 ); + RiaStdStringTools::toInt( ijk[2], intValue2 ); + + return blockAddress( vectorName, intValue0, intValue1, intValue2 ); } } break; @@ -836,11 +855,11 @@ RifEclipseSummaryAddress RifEclipseSummaryAddress::fromTokens( const std::vector auto ijk = RiaStdStringTools::splitString( token2, ',' ); if ( ijk.size() == 3 ) { - return blockLgrAddress( vectorName, - token1, - RiaStdStringTools::toInt( ijk[0] ), - RiaStdStringTools::toInt( ijk[1] ), - RiaStdStringTools::toInt( ijk[2] ) ); + RiaStdStringTools::toInt( ijk[0], intValue0 ); + RiaStdStringTools::toInt( ijk[1], intValue1 ); + RiaStdStringTools::toInt( ijk[2], intValue2 ); + + return blockLgrAddress( vectorName, token1, intValue0, intValue1, intValue2 ); } } break; diff --git a/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp b/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp index 6ac6923eee..f4548c79e0 100644 --- a/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp +++ b/ApplicationLibCode/FileInterface/RifOpmCommonSummary.cpp @@ -395,32 +395,49 @@ std::pair, std::map invalidKeywords; - for ( const auto& keyword : keywords ) +#pragma omp parallel { - auto eclAdr = RifEclipseSummaryAddress::fromEclipseTextAddress( keyword ); - if ( !eclAdr.isValid() ) - { - invalidKeywords.push_back( keyword ); + std::set threadAddresses; + std::map threadAddressToNodeIndexMap; + std::vector threadInvalidKeywords; - // If a category is not found, use the MISC category - eclAdr = RifEclipseSummaryAddress::miscAddress( keyword ); +#pragma omp for + for ( int index = 0; index < (int)keywords.size(); index++ ) + { + auto keyword = keywords[index]; + + auto eclAdr = RifEclipseSummaryAddress::fromEclipseTextAddress( keyword ); + if ( !eclAdr.isValid() ) + { + threadInvalidKeywords.push_back( keyword ); + + // If a category is not found, use the MISC category + eclAdr = RifEclipseSummaryAddress::miscAddress( keyword ); + } + + if ( eclAdr.isValid() ) + { + threadAddresses.insert( eclAdr ); + threadAddressToNodeIndexMap[eclAdr] = keyword; + } } - if ( eclAdr.isValid() ) +#pragma omp critical { - addresses.insert( eclAdr ); - addressToNodeIndexMap[eclAdr] = keyword; + addresses.insert( threadAddresses.begin(), threadAddresses.end() ); + addressToNodeIndexMap.insert( threadAddressToNodeIndexMap.begin(), threadAddressToNodeIndexMap.end() ); + invalidKeywords.insert( invalidKeywords.end(), threadInvalidKeywords.begin(), threadInvalidKeywords.end() ); } + + // DEBUG code + // Used to print keywords not being categorized correctly + /* + for ( const auto& kw : invalidKeywords ) + { + RiaLogging::warning( QString::fromStdString( kw ) ); + } + */ } - // DEBUG code - // Used to print keywords not being categorized correctly - /* - for ( const auto& kw : invalidKeywords ) - { - RiaLogging::warning( QString::fromStdString( kw ) ); - } - */ - return { addresses, addressToNodeIndexMap }; } diff --git a/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.cpp b/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.cpp index 326fbd0917..599ab33b0e 100644 --- a/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.cpp +++ b/ApplicationLibCode/FileInterface/RifSummaryReaderInterface.cpp @@ -57,13 +57,5 @@ bool RifSummaryReaderInterface::hasAddress( const RifEclipseSummaryAddress& resu static const RifEclipseSummaryAddress defaultAdr = RifEclipseSummaryAddress(); if ( resultAddress == defaultAdr ) return true; - for ( const RifEclipseSummaryAddress& summaryAddress : m_allResultAddresses ) - { - if ( summaryAddress == resultAddress ) - { - return true; - } - } - - return false; + return ( m_allResultAddresses.count( resultAddress ) > 0 ); } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp index eef1eb2a7d..a39c0ed4ba 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp @@ -1967,6 +1967,14 @@ bool RimEnsembleCurveSet::hasMeanData() const return m_ensembleStatCase->hasMeanData(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RimEnsembleCurveSet::minimumAndMaximumValues() const +{ + return m_ensembleStatCase->minimumAndMaximumValues(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h index 2aa535d10f..10f31b6e88 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h @@ -155,6 +155,8 @@ public: bool hasP90Data() const override; bool hasMeanData() const override; + std::pair minimumAndMaximumValues() const; + void appendColorGroup( caf::PdmUiOrdering& uiOrdering ); static void appendOptionItemsForSummaryAddresses( QList* options, diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp index 9b1614291b..8692e2b6d0 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.cpp @@ -39,6 +39,8 @@ /// //-------------------------------------------------------------------------------------------------- RimEnsembleStatisticsCase::RimEnsembleStatisticsCase( RimEnsembleCurveSet* curveSet ) + : m_minimumValue( DOUBLE_INF ) + , m_maximumValue( -DOUBLE_INF ) { m_curveSet = curveSet; } @@ -83,6 +85,14 @@ const std::vector& RimEnsembleStatisticsCase::mean() const return m_meanData; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const std::pair RimEnsembleStatisticsCase::minimumAndMaximumValues() const +{ + return { m_minimumValue, m_maximumValue }; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -195,6 +205,11 @@ void RimEnsembleStatisticsCase::calculate( const std::vector su m_p50Data.push_back( p50 ); m_p90Data.push_back( p90 ); m_meanData.push_back( mean ); + + const auto [min, max] = std::minmax_element( begin( valuesAtTimeStep ), end( valuesAtTimeStep ) ); + + m_maximumValue = std::max( m_maximumValue, *max ); + m_minimumValue = std::min( m_minimumValue, *min ); } } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.h index 20b53581ac..5e734b6222 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleStatisticsCase.h @@ -40,6 +40,8 @@ public: const std::vector& p90() const; const std::vector& mean() const; + const std::pair minimumAndMaximumValues() const; + bool hasP10Data() const { return !m_p10Data.empty(); } bool hasP50Data() const { return !m_p50Data.empty(); } bool hasP90Data() const { return !m_p90Data.empty(); } @@ -72,4 +74,7 @@ private: std::vector m_p50Data; std::vector m_p90Data; std::vector m_meanData; + + double m_maximumValue; + double m_minimumValue; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp index ff0bbfcebb..33599139e6 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.cpp @@ -22,6 +22,7 @@ #include "RiaLogging.h" #include "RiaStatisticsTools.h" #include "RiaStdStringTools.h" +#include "RiaSummaryAddressAnalyzer.h" #include "RiaWeightedMeanCalculator.h" #include "RicfCommandObject.h" @@ -158,6 +159,7 @@ void RimSummaryCaseCollection::removeCase( RimSummaryCase* summaryCase, bool not m_cases.removeChild( summaryCase ); m_cachedSortedEnsembleParameters.clear(); + m_analyzer.reset(); caseRemoved.send( summaryCase ); @@ -184,6 +186,7 @@ void RimSummaryCaseCollection::addCase( RimSummaryCase* summaryCase ) m_cases.push_back( summaryCase ); m_cachedSortedEnsembleParameters.clear(); + m_analyzer.reset(); // Update derived ensemble cases (if any) std::vector referringObjects; @@ -344,6 +347,7 @@ std::set RimSummaryCaseCollection::ensembleTimeSteps() const } return allTimeSteps; } + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -929,6 +933,21 @@ void RimSummaryCaseCollection::updateReferringCurveSets() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RiaSummaryAddressAnalyzer* RimSummaryCaseCollection::addressAnalyzer() +{ + if ( !m_analyzer ) + { + m_analyzer = std::make_unique(); + + m_analyzer->appendAddresses( ensembleSummaryAddresses() ); + } + + return m_analyzer.get(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h index 394fc7b6a0..be50d153fa 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCaseCollection.h @@ -35,6 +35,7 @@ #include +#include #include #include @@ -42,6 +43,7 @@ class RifReaderRftInterface; class RifReaderEnsembleStatisticsRft; class RimSummaryCase; class RimSummaryAddressCollection; +class RiaSummaryAddressAnalyzer; //================================================================================================== /// @@ -110,6 +112,8 @@ public: void updateReferringCurveSets(); + RiaSummaryAddressAnalyzer* addressAnalyzer(); + private: RigEnsembleParameter createEnsembleParameter( const QString& paramName ) const; static void sortByBinnedVariation( std::vector& parameterVector ); @@ -146,5 +150,6 @@ private: size_t m_commonAddressCount; // if different address count among cases, set to 0 - mutable std::vector m_cachedSortedEnsembleParameters; + mutable std::vector m_cachedSortedEnsembleParameters; + std::unique_ptr m_analyzer; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp index 48df237ee2..3ae1635ac1 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryMultiPlot.cpp @@ -981,7 +981,7 @@ void RimSummaryMultiPlot::computeAggregatedAxisRange() for ( auto axis : plot->plotAxes() ) { - for ( auto curve : plot->summaryAndEnsembleCurves() ) + for ( auto curve : plot->summaryCurves() ) { if ( curve->axisY() == axis->plotAxisType() ) { @@ -1002,6 +1002,25 @@ void RimSummaryMultiPlot::computeAggregatedAxisRange() } } } + + for ( auto curveSet : plot->curveSets() ) + { + if ( curveSet->axisY() == axis->plotAxisType() ) + { + auto [minimum, maximum] = curveSet->minimumAndMaximumValues(); + + if ( axisRanges.count( axis->plotAxisType() ) == 0 ) + { + axisRanges[axis->plotAxisType()] = std::make_pair( minimum, maximum ); + } + else + { + auto& [currentMin, currentMax] = axisRanges[axis->plotAxisType()]; + axisRanges[axis->plotAxisType()] = + std::make_pair( std::min( currentMin, minimum ), std::max( currentMax, maximum ) ); + } + } + } } // set all plots to use the global min/max values for each category diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp index c3e6cd9eac..70de196336 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.cpp @@ -211,12 +211,29 @@ QList return options; } - auto addresses = adressesForSourceStepping(); - if ( !addresses.empty() ) + RiaSummaryAddressAnalyzer fallbackAnalyzer; + RiaSummaryAddressAnalyzer* analyzer = nullptr; + if ( !dataSourceSteppingObject()->curveSets().empty() ) + { + auto first = dataSourceSteppingObject()->curveSets().front(); + analyzer = first->summaryCaseCollection()->addressAnalyzer(); + } + + if ( !analyzer ) + { + // No cached analyzer found. Fallback to population of a local analyzer. Try to avoid this, as the analysis + // operation is quite expensive. + + auto addresses = adressesForSourceStepping(); + fallbackAnalyzer.appendAddresses( addresses ); + analyzer = &fallbackAnalyzer; + } + + if ( analyzer ) { if ( fieldNeedingOptions == &m_vectorName ) { - std::map displayAndValueStrings = optionsForQuantity( addresses ); + auto displayAndValueStrings = optionsForQuantity( analyzer ); for ( const auto& displayAndValue : displayAndValueStrings ) { @@ -268,10 +285,7 @@ QList if ( category != RifEclipseSummaryAddress::SUMMARY_INVALID ) { - RiaSummaryAddressAnalyzer analyzer; - analyzer.appendAddresses( addresses ); - - identifierTexts = analyzer.identifierTexts( category, secondaryIdentifier ); + identifierTexts = analyzer->identifierTexts( category, secondaryIdentifier ); } if ( !identifierTexts.empty() ) @@ -1175,9 +1189,6 @@ std::map RimSummaryPlotSourceStepping::optionsForQuantity( std auto subset = RiaSummaryAddressAnalyzer::addressesForCategory( addresses, category ); quantityAnalyzer.appendAddresses( subset ); - RiaSummaryAddressAnalyzer analyzerForVisibleCurves; - analyzerForVisibleCurves.appendAddresses( visibleCurveAddresses ); - auto quantities = quantityAnalyzer.quantities(); for ( const auto& s : quantities ) { @@ -1190,6 +1201,36 @@ std::map RimSummaryPlotSourceStepping::optionsForQuantity( std return displayAndValueStrings; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::map RimSummaryPlotSourceStepping::optionsForQuantity( RiaSummaryAddressAnalyzer* analyzser ) +{ + RifEclipseSummaryAddress::SummaryVarCategory category = RifEclipseSummaryAddress::SUMMARY_FIELD; + + auto visibleCurveAddresses = addressesForCurvesInPlot(); + if ( !visibleCurveAddresses.empty() ) + { + category = visibleCurveAddresses.begin()->category(); + } + + std::map displayAndValueStrings; + + if ( analyzser ) + { + auto vectorNames = analyzser->vectorNamesForCategory( category ); + + for ( const auto& s : vectorNames ) + { + QString valueString = QString::fromStdString( s ); + + displayAndValueStrings[valueString] = valueString; + } + } + + return displayAndValueStrings; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h index 35512dc6d6..dd1dacda0e 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlotSourceStepping.h @@ -35,6 +35,7 @@ class RimSummaryCurve; class RifSummaryReaderInterface; class RimSummaryCaseCollection; class RifEclipseSummaryAddress; +class RiaSummaryAddressAnalyzer; //================================================================================================== /// @@ -98,6 +99,7 @@ private: RimSummaryDataSourceStepping* dataSourceSteppingObject() const; std::map optionsForQuantity( std::set addresses ); + std::map optionsForQuantity( RiaSummaryAddressAnalyzer* analyzser ); private: caf::PdmPointer m_objectForSourceStepping; diff --git a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsMath.cpp b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsMath.cpp index 0ae38b380b..b8c75c9281 100644 --- a/ApplicationLibCode/ResultStatisticsCache/RigStatisticsMath.cpp +++ b/ApplicationLibCode/ResultStatisticsCache/RigStatisticsMath.cpp @@ -105,20 +105,16 @@ void RigStatisticsMath::calculateStatisticsCurves( const std::vector& va P90 }; - std::vector sortedValues; - double valueSum = 0; + std::vector sortedValues = values; - { - std::multiset vSet( values.begin(), values.end() ); - for ( double v : vSet ) - { - if ( RiaStatisticsTools::isValidNumber( v ) ) - { - sortedValues.push_back( v ); - valueSum += v; - } - } - } + sortedValues.erase( std::remove_if( sortedValues.begin(), + sortedValues.end(), + []( double x ) { return !RiaStatisticsTools::isValidNumber( x ); } ), + sortedValues.end() ); + + std::sort( sortedValues.begin(), sortedValues.end() ); + + double valueSum = std::accumulate( sortedValues.begin(), sortedValues.end(), 0.0 ); int valueCount = (int)sortedValues.size(); double percentiles[] = { 0.1, 0.5, 0.9 }; diff --git a/ApplicationLibCode/UnitTests/RiaSummaryAddressAnalyzer-Test.cpp b/ApplicationLibCode/UnitTests/RiaSummaryAddressAnalyzer-Test.cpp index bd9c76de9a..9dc48e58e9 100644 --- a/ApplicationLibCode/UnitTests/RiaSummaryAddressAnalyzer-Test.cpp +++ b/ApplicationLibCode/UnitTests/RiaSummaryAddressAnalyzer-Test.cpp @@ -138,3 +138,42 @@ TEST( RiaSummaryAddressAnalyzer, CellBlocks ) auto blocks = analyzer.blocks(); EXPECT_EQ( 3u, blocks.size() ); } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RiaSummaryAddressAnalyzer, QuantitiesPerCategory ) +{ + std::vector addresses; + + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::fieldAddress( "FOPT" ); + addresses.push_back( adr ); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::fieldAddress( "FOPR" ); + addresses.push_back( adr ); + } + + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellAddress( "WOPT", "WellA" ); + addresses.push_back( adr ); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellAddress( "WOPR", "WellB" ); + addresses.push_back( adr ); + } + { + RifEclipseSummaryAddress adr = RifEclipseSummaryAddress::wellAddress( "WWPR", "WellA" ); + addresses.push_back( adr ); + } + + RiaSummaryAddressAnalyzer analyzer; + analyzer.appendAddresses( addresses ); + + auto categories = analyzer.categories(); + EXPECT_EQ( 2u, categories.size() ); + + auto vectorNamesForWells = analyzer.vectorNamesForCategory( RifEclipseSummaryAddress::SUMMARY_WELL ); + EXPECT_EQ( 3u, vectorNamesForWells.size() ); +} diff --git a/ApplicationLibCode/UnitTests/RigStatisticsMath-Test.cpp b/ApplicationLibCode/UnitTests/RigStatisticsMath-Test.cpp index 17e42e4c6a..de0a3820c8 100644 --- a/ApplicationLibCode/UnitTests/RigStatisticsMath-Test.cpp +++ b/ApplicationLibCode/UnitTests/RigStatisticsMath-Test.cpp @@ -20,6 +20,7 @@ #include "gtest/gtest.h" +#include "QElapsedTimer" #include "RigStatisticsMath.h" //-------------------------------------------------------------------------------------------------- @@ -295,3 +296,37 @@ TEST( RigStatisticsMath, calculateStatisticsCurves ) EXPECT_DOUBLE_EQ( 1.0, mean ); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RigStatisticsMath, DISABLED_performanceTesting ) +{ + RigStatisticsMath::PercentileStyle percentileStyle = RigStatisticsMath::PercentileStyle::REGULAR; + { + size_t timerCount = 10; + for ( size_t t = 0; t < timerCount; t++ ) + { + QElapsedTimer timer; + timer.start(); + + size_t iterationCount = 10000; + for ( size_t i = 0; i < iterationCount; i++ ) + { + size_t numberOfValues = 200; + std::vector values( numberOfValues ); + std::iota( values.begin(), values.end(), numberOfValues ); + + double mean = HUGE_VAL; + double p10 = HUGE_VAL; + double p50 = HUGE_VAL; + double p90 = HUGE_VAL; + + RigStatisticsMath::calculateStatisticsCurves( values, &p10, &p50, &p90, &mean, percentileStyle ); + } + + auto testDuration = timer.elapsed(); + std::cout << testDuration << "\n"; + } + } +}