mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Support ensemble cross plot curves
* Remove use of RifEnsembleStatisticsReader * Add RimSummaryAddressSelector and RimEnsembleCrossPlotStatisticsCase * Remove RifEnsembleStatisticsReader * Add support for cross plot x-axis selection * Support source stepping on ensemble cross plot curves * Add isXAxisSummaryVector
This commit is contained in:
@@ -41,11 +41,11 @@ RiaSummaryCurveDefinition::RiaSummaryCurveDefinition()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaSummaryCurveDefinition::RiaSummaryCurveDefinition( RimSummaryCase* summaryCase,
|
||||
const RifEclipseSummaryAddress& summaryAddress,
|
||||
RiaSummaryCurveDefinition::RiaSummaryCurveDefinition( RimSummaryCase* summaryCaseY,
|
||||
const RifEclipseSummaryAddress& summaryAddressY,
|
||||
bool isEnsembleCurve )
|
||||
: m_summaryCaseY( summaryCase )
|
||||
, m_summaryAddressY( summaryAddress )
|
||||
: m_summaryCaseY( summaryCaseY )
|
||||
, m_summaryAddressY( summaryAddressY )
|
||||
, m_summaryCaseX( nullptr )
|
||||
, m_summaryAddressX( RifEclipseSummaryAddress::timeAddress() )
|
||||
, m_ensemble( nullptr )
|
||||
@@ -56,9 +56,9 @@ RiaSummaryCurveDefinition::RiaSummaryCurveDefinition( RimSummaryCase*
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaSummaryCurveDefinition::RiaSummaryCurveDefinition( RimSummaryCaseCollection* ensemble, const RifEclipseSummaryAddress& summaryAddress )
|
||||
RiaSummaryCurveDefinition::RiaSummaryCurveDefinition( RimSummaryCaseCollection* ensemble, const RifEclipseSummaryAddress& summaryAddressY )
|
||||
: m_summaryCaseY( nullptr )
|
||||
, m_summaryAddressY( summaryAddress )
|
||||
, m_summaryAddressY( summaryAddressY )
|
||||
, m_summaryCaseX( nullptr )
|
||||
, m_summaryAddressX( RifEclipseSummaryAddress::timeAddress() )
|
||||
, m_ensemble( ensemble )
|
||||
|
||||
@@ -38,8 +38,8 @@ class RiaSummaryCurveDefinition
|
||||
{
|
||||
public:
|
||||
RiaSummaryCurveDefinition();
|
||||
explicit RiaSummaryCurveDefinition( RimSummaryCase* summaryCase, const RifEclipseSummaryAddress& summaryAddress, bool isEnsembleCurve );
|
||||
explicit RiaSummaryCurveDefinition( RimSummaryCaseCollection* ensemble, const RifEclipseSummaryAddress& summaryAddress );
|
||||
explicit RiaSummaryCurveDefinition( RimSummaryCase* summaryCaseY, const RifEclipseSummaryAddress& summaryAddressY, bool isEnsembleCurve );
|
||||
explicit RiaSummaryCurveDefinition( RimSummaryCaseCollection* ensemble, const RifEclipseSummaryAddress& summaryAddressY );
|
||||
|
||||
// Y Axis
|
||||
RimSummaryCase* summaryCaseY() const;
|
||||
|
||||
@@ -45,7 +45,6 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCaseRestartSelector.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifReaderEnsembleStatisticsRft.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader.h
|
||||
@@ -136,7 +135,6 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifSummaryCaseRestartSelector.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter.cpp
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017- Statoil ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RifEnsembleStatisticsReader.h"
|
||||
|
||||
#include "RimEnsembleCurveSet.h"
|
||||
#include "RimEnsembleStatisticsCase.h"
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifEnsembleStatisticsReader::RifEnsembleStatisticsReader( RimEnsembleStatisticsCase* ensStatCase )
|
||||
{
|
||||
CVF_ASSERT( ensStatCase );
|
||||
|
||||
m_ensembleStatCase = ensStatCase;
|
||||
|
||||
m_allResultAddresses =
|
||||
std::set<RifEclipseSummaryAddress>( { RifEclipseSummaryAddress::ensembleStatisticsAddress( ENSEMBLE_STAT_P10_QUANTITY_NAME, "" ),
|
||||
RifEclipseSummaryAddress::ensembleStatisticsAddress( ENSEMBLE_STAT_P50_QUANTITY_NAME, "" ),
|
||||
RifEclipseSummaryAddress::ensembleStatisticsAddress( ENSEMBLE_STAT_P90_QUANTITY_NAME, "" ),
|
||||
RifEclipseSummaryAddress::ensembleStatisticsAddress( ENSEMBLE_STAT_MEAN_QUANTITY_NAME, "" ) } );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<time_t> RifEnsembleStatisticsReader::timeSteps( const RifEclipseSummaryAddress& resultAddress ) const
|
||||
{
|
||||
if ( !validateAddress( resultAddress ) ) return {};
|
||||
return m_ensembleStatCase->timeSteps();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifEnsembleStatisticsReader::values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const
|
||||
{
|
||||
if ( !validateAddress( resultAddress ) ) return false;
|
||||
|
||||
const std::vector<double>* sourceData = nullptr;
|
||||
auto quantityName = resultAddress.ensembleStatisticsVectorName();
|
||||
|
||||
if ( quantityName == ENSEMBLE_STAT_P10_QUANTITY_NAME )
|
||||
sourceData = &m_ensembleStatCase->p10();
|
||||
else if ( quantityName == ENSEMBLE_STAT_P50_QUANTITY_NAME )
|
||||
sourceData = &m_ensembleStatCase->p50();
|
||||
else if ( quantityName == ENSEMBLE_STAT_P90_QUANTITY_NAME )
|
||||
sourceData = &m_ensembleStatCase->p90();
|
||||
else if ( quantityName == ENSEMBLE_STAT_MEAN_QUANTITY_NAME )
|
||||
sourceData = &m_ensembleStatCase->mean();
|
||||
|
||||
if ( !sourceData ) return false;
|
||||
|
||||
values->clear();
|
||||
values->reserve( sourceData->size() );
|
||||
for ( auto val : *sourceData )
|
||||
values->push_back( val );
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RifEnsembleStatisticsReader::unitName( const RifEclipseSummaryAddress& resultAddress ) const
|
||||
{
|
||||
std::string retval;
|
||||
|
||||
// The stat case does not have a unit set, so pick up the unit from one of the input cases, if possible
|
||||
auto cases = m_ensembleStatCase->curveSet()->summaryCaseCollection()->allSummaryCases();
|
||||
if ( cases.size() > 0 )
|
||||
{
|
||||
QString qName = QString::fromStdString( resultAddress.vectorName() );
|
||||
std::string orgQName = qName.split( ":" )[1].toStdString();
|
||||
|
||||
RifEclipseSummaryAddress address = RifEclipseSummaryAddress( resultAddress );
|
||||
address.setVectorName( orgQName );
|
||||
|
||||
retval = cases[0]->summaryReader()->unitName( address );
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::EclipseUnitSystem RifEnsembleStatisticsReader::unitSystem() const
|
||||
{
|
||||
return m_ensembleStatCase->unitSystem();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifEnsembleStatisticsReader::validateAddress( const RifEclipseSummaryAddress& address ) const
|
||||
{
|
||||
return address.category() == RifEclipseSummaryAddressDefines::SummaryCategory::SUMMARY_ENSEMBLE_STATISTICS &&
|
||||
!address.vectorName().empty();
|
||||
}
|
||||
@@ -77,18 +77,16 @@ void RimDataSourceSteppingTools::modifyCurrentIndex( caf::PdmValueField*
|
||||
bool RimDataSourceSteppingTools::updateAddressIfMatching( const QVariant& oldValue,
|
||||
const QVariant& newValue,
|
||||
RifEclipseSummaryAddressDefines::SummaryCategory category,
|
||||
RifEclipseSummaryAddress* adr )
|
||||
RifEclipseSummaryAddress& adr )
|
||||
{
|
||||
if ( !adr ) return false;
|
||||
|
||||
if ( category == RifEclipseSummaryAddressDefines::SummaryCategory::SUMMARY_REGION )
|
||||
{
|
||||
int oldInt = oldValue.toInt();
|
||||
int newInt = newValue.toInt();
|
||||
|
||||
if ( adr->regionNumber() == oldInt )
|
||||
if ( adr.regionNumber() == oldInt )
|
||||
{
|
||||
adr->setRegion( newInt );
|
||||
adr.setRegion( newInt );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -98,9 +96,9 @@ bool RimDataSourceSteppingTools::updateAddressIfMatching( const QVariant&
|
||||
int oldInt = oldValue.toInt();
|
||||
int newInt = newValue.toInt();
|
||||
|
||||
if ( adr->aquiferNumber() == oldInt )
|
||||
if ( adr.aquiferNumber() == oldInt )
|
||||
{
|
||||
adr->setAquiferNumber( newInt );
|
||||
adr.setAquiferNumber( newInt );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -110,9 +108,9 @@ bool RimDataSourceSteppingTools::updateAddressIfMatching( const QVariant&
|
||||
std::string oldString = oldValue.toString().toStdString();
|
||||
std::string newString = newValue.toString().toStdString();
|
||||
|
||||
if ( adr->groupName() == oldString )
|
||||
if ( adr.groupName() == oldString )
|
||||
{
|
||||
adr->setGroupName( newString );
|
||||
adr.setGroupName( newString );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -122,9 +120,9 @@ bool RimDataSourceSteppingTools::updateAddressIfMatching( const QVariant&
|
||||
std::string oldString = oldValue.toString().toStdString();
|
||||
std::string newString = newValue.toString().toStdString();
|
||||
|
||||
if ( adr->networkName() == oldString )
|
||||
if ( adr.networkName() == oldString )
|
||||
{
|
||||
adr->setNetworkName( newString );
|
||||
adr.setNetworkName( newString );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -134,9 +132,9 @@ bool RimDataSourceSteppingTools::updateAddressIfMatching( const QVariant&
|
||||
std::string oldString = oldValue.toString().toStdString();
|
||||
std::string newString = newValue.toString().toStdString();
|
||||
|
||||
if ( adr->wellName() == oldString )
|
||||
if ( adr.wellName() == oldString )
|
||||
{
|
||||
adr->setWellName( newString );
|
||||
adr.setWellName( newString );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -146,9 +144,9 @@ bool RimDataSourceSteppingTools::updateAddressIfMatching( const QVariant&
|
||||
{
|
||||
std::string oldString = oldValue.toString().toStdString();
|
||||
std::string newString = newValue.toString().toStdString();
|
||||
if ( adr->blockAsString() == oldString )
|
||||
if ( adr.blockAsString() == oldString )
|
||||
{
|
||||
adr->setCellIjk( newString );
|
||||
adr.setCellIjk( newString );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -157,11 +155,11 @@ bool RimDataSourceSteppingTools::updateAddressIfMatching( const QVariant&
|
||||
{
|
||||
std::string oldString = oldValue.toString().toStdString();
|
||||
std::string newString = newValue.toString().toStdString();
|
||||
if ( adr->formatUiTextRegionToRegion() == oldString )
|
||||
if ( adr.formatUiTextRegionToRegion() == oldString )
|
||||
{
|
||||
auto [region1, region2] = RifEclipseSummaryAddress::regionToRegionPairFromUiText( newString );
|
||||
adr->setRegion( region1 );
|
||||
adr->setRegion2( region2 );
|
||||
adr.setRegion( region1 );
|
||||
adr.setRegion2( region2 );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -170,9 +168,9 @@ bool RimDataSourceSteppingTools::updateAddressIfMatching( const QVariant&
|
||||
{
|
||||
int oldInt = oldValue.toInt();
|
||||
int newInt = newValue.toInt();
|
||||
if ( adr->wellSegmentNumber() == oldInt )
|
||||
if ( adr.wellSegmentNumber() == oldInt )
|
||||
{
|
||||
adr->setWellSegmentNumber( newInt );
|
||||
adr.setWellSegmentNumber( newInt );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -184,48 +182,14 @@ bool RimDataSourceSteppingTools::updateAddressIfMatching( const QVariant&
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDataSourceSteppingTools::updateHistoryAndSummaryQuantityIfMatching( const QVariant& oldValue,
|
||||
const QVariant& newValue,
|
||||
RifEclipseSummaryAddress* adr )
|
||||
bool RimDataSourceSteppingTools::updateQuantityIfMatching( const QVariant& oldValue, const QVariant& newValue, RifEclipseSummaryAddress& adr )
|
||||
{
|
||||
if ( !adr ) return false;
|
||||
|
||||
std::string oldString = oldValue.toString().toStdString();
|
||||
std::string newString = newValue.toString().toStdString();
|
||||
|
||||
if ( adr->vectorName() == oldString )
|
||||
if ( adr.vectorName() == oldString )
|
||||
{
|
||||
adr->setVectorName( newString );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string correspondingOldString = RiaSummaryAddressAnalyzer::correspondingHistorySummaryCurveName( oldString );
|
||||
std::string correspondingNewString = RiaSummaryAddressAnalyzer::correspondingHistorySummaryCurveName( newString );
|
||||
|
||||
if ( adr->vectorName() == correspondingOldString )
|
||||
{
|
||||
adr->setVectorName( correspondingNewString );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDataSourceSteppingTools::updateQuantityIfMatching( const QVariant& oldValue, const QVariant& newValue, RifEclipseSummaryAddress* adr )
|
||||
{
|
||||
if ( !adr ) return false;
|
||||
|
||||
std::string oldString = oldValue.toString().toStdString();
|
||||
std::string newString = newValue.toString().toStdString();
|
||||
|
||||
if ( adr->vectorName() == oldString )
|
||||
{
|
||||
adr->setVectorName( newString );
|
||||
adr.setVectorName( newString );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -39,9 +39,7 @@ public:
|
||||
static bool updateAddressIfMatching( const QVariant& oldValue,
|
||||
const QVariant& newValue,
|
||||
RifEclipseSummaryAddressDefines::SummaryCategory category,
|
||||
RifEclipseSummaryAddress* adr );
|
||||
RifEclipseSummaryAddress& adr );
|
||||
|
||||
static bool updateHistoryAndSummaryQuantityIfMatching( const QVariant& oldValue, const QVariant& newValue, RifEclipseSummaryAddress* adr );
|
||||
|
||||
static bool updateQuantityIfMatching( const QVariant& oldValue, const QVariant& newValue, RifEclipseSummaryAddress* adr );
|
||||
static bool updateQuantityIfMatching( const QVariant& oldValue, const QVariant& newValue, RifEclipseSummaryAddress& adr );
|
||||
};
|
||||
|
||||
@@ -292,7 +292,7 @@ void RimSummaryCalculation::substituteVariables( std::vector<SummaryCalculationV
|
||||
{
|
||||
if ( v.summaryAddress.category() == address.category() )
|
||||
{
|
||||
RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, address.category(), &v.summaryAddress );
|
||||
RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, address.category(), v.summaryAddress );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimSummaryTableTools.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimSummaryDeclineCurve.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimSummaryRegressionAnalysisCurve.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimSummaryAddressSelector.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCrossPlotStatisticsCase.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -108,6 +110,8 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimSummaryTableTools.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimSummaryDeclineCurve.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimSummaryRegressionAnalysisCurve.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimSummaryAddressSelector.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCrossPlotStatisticsCase.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2023- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimEnsembleCrossPlotStatisticsCase.h"
|
||||
|
||||
#include "RiaSummaryTools.h"
|
||||
#include "RiaTimeHistoryCurveResampler.h"
|
||||
|
||||
#include "RigStatisticsMath.h"
|
||||
|
||||
#include "RimEnsembleCurveSet.h"
|
||||
#include "RimEnsembleStatisticsCase.h"
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
|
||||
#include <limits>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEnsembleCrossPlotStatisticsCase::RimEnsembleCrossPlotStatisticsCase()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleCrossPlotStatisticsCase::values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const
|
||||
{
|
||||
if ( m_adrX.isValid() )
|
||||
{
|
||||
auto stringToTest = resultAddress.vectorName();
|
||||
auto it = stringToTest.find( m_adrX.vectorName() );
|
||||
if ( it != std::string::npos )
|
||||
{
|
||||
*values = m_binnedXValues;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
auto quantityName = resultAddress.ensembleStatisticsVectorName();
|
||||
|
||||
if ( quantityName == ENSEMBLE_STAT_P10_QUANTITY_NAME )
|
||||
*values = m_p10Data;
|
||||
else if ( quantityName == ENSEMBLE_STAT_P50_QUANTITY_NAME )
|
||||
*values = m_p50Data;
|
||||
else if ( quantityName == ENSEMBLE_STAT_P90_QUANTITY_NAME )
|
||||
*values = m_p90Data;
|
||||
else if ( quantityName == ENSEMBLE_STAT_MEAN_QUANTITY_NAME )
|
||||
*values = m_meanData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimEnsembleCrossPlotStatisticsCase::unitName( const RifEclipseSummaryAddress& resultAddress ) const
|
||||
{
|
||||
if ( m_firstSummaryCase && m_firstSummaryCase->summaryReader() )
|
||||
{
|
||||
return m_firstSummaryCase->summaryReader()->unitName( resultAddress );
|
||||
}
|
||||
|
||||
return "Ensemble Cross Plot - Undefined Unit";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimEnsembleCrossPlotStatisticsCase::caseName() const
|
||||
{
|
||||
return "Ensemble Statistics";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleCrossPlotStatisticsCase::createSummaryReaderInterface()
|
||||
{
|
||||
// Nothing to do, as RimEnsembleCrossPlotStatisticsCase inherits RifSummaryReaderInterface
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifSummaryReaderInterface* RimEnsembleCrossPlotStatisticsCase::summaryReader()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleCrossPlotStatisticsCase::calculate( const std::vector<RimSummaryCase*>& sumCases,
|
||||
const RifEclipseSummaryAddress& inputAddressX,
|
||||
const RifEclipseSummaryAddress& inputAddressY,
|
||||
bool includeIncompleteCurves,
|
||||
int binCount,
|
||||
int sampleCountThreshold )
|
||||
{
|
||||
if ( !inputAddressX.isValid() || !inputAddressY.isValid() ) return;
|
||||
if ( sumCases.empty() ) return;
|
||||
|
||||
clearData();
|
||||
|
||||
// Use first summary case to get unit system and other meta data
|
||||
m_firstSummaryCase = sumCases.front();
|
||||
|
||||
m_adrX = inputAddressX;
|
||||
m_adrY = inputAddressY;
|
||||
|
||||
std::vector<std::pair<double, double>> pairs;
|
||||
|
||||
auto [minTimeStep, maxTimeStep] = RimEnsembleStatisticsCase::findMinMaxTimeStep( sumCases, inputAddressX );
|
||||
RiaDefines::DateTimePeriod period = RimEnsembleStatisticsCase::findBestResamplingPeriod( minTimeStep, maxTimeStep );
|
||||
|
||||
for ( const auto& sumCase : sumCases )
|
||||
{
|
||||
const auto& reader = sumCase->summaryReader();
|
||||
if ( reader )
|
||||
{
|
||||
const std::vector<time_t>& timeSteps = reader->timeSteps( inputAddressX );
|
||||
|
||||
std::vector<double> valuesX;
|
||||
reader->values( inputAddressX, &valuesX );
|
||||
if ( valuesX.empty() ) continue;
|
||||
|
||||
std::vector<double> valuesY;
|
||||
reader->values( inputAddressY, &valuesY );
|
||||
if ( valuesY.empty() ) continue;
|
||||
|
||||
if ( !includeIncompleteCurves && timeSteps.size() != valuesX.size() ) continue;
|
||||
if ( !includeIncompleteCurves && timeSteps.size() != valuesY.size() ) continue;
|
||||
|
||||
auto [resampledTimeStepsX, resampledValuesX] =
|
||||
RiaSummaryTools::resampledValuesForPeriod( inputAddressX, timeSteps, valuesX, period );
|
||||
|
||||
auto [resampledTimeStepsY, resampledValuesY] =
|
||||
RiaSummaryTools::resampledValuesForPeriod( inputAddressY, timeSteps, valuesY, period );
|
||||
|
||||
size_t minimumCount = std::min( resampledValuesX.size(), resampledValuesY.size() );
|
||||
|
||||
for ( size_t i = 0; i < minimumCount; i++ )
|
||||
{
|
||||
pairs.emplace_back( std::make_pair( resampledValuesX[i], resampledValuesY[i] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort on X values
|
||||
std::sort( pairs.begin(), pairs.end(), []( const auto& lhs, const auto& rhs ) { return lhs.first < rhs.first; } );
|
||||
|
||||
const auto p = std::minmax_element( pairs.begin(), pairs.end() );
|
||||
auto minX = p.first->first;
|
||||
auto maxX = p.second->first;
|
||||
auto rangeX = maxX - minX;
|
||||
auto deltaRangeX = rangeX / binCount;
|
||||
|
||||
double currentX = minX;
|
||||
|
||||
std::vector<double> binnedYValues;
|
||||
for ( auto v : pairs )
|
||||
{
|
||||
if ( v.first < currentX + deltaRangeX )
|
||||
{
|
||||
binnedYValues.emplace_back( v.second );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add statistics for current bin if sample count is above threshold
|
||||
// TODO: Add option to skip bin if unique realization count is below threshold
|
||||
|
||||
if ( static_cast<int>( binnedYValues.size() ) > sampleCountThreshold )
|
||||
{
|
||||
double p10, p50, p90, mean;
|
||||
RigStatisticsMath::calculateStatisticsCurves( binnedYValues, &p10, &p50, &p90, &mean, RigStatisticsMath::PercentileStyle::SWITCHED );
|
||||
m_p10Data.push_back( p10 );
|
||||
m_p50Data.push_back( p50 );
|
||||
m_p90Data.push_back( p90 );
|
||||
m_meanData.push_back( mean );
|
||||
|
||||
m_binnedXValues.emplace_back( currentX );
|
||||
}
|
||||
|
||||
currentX += deltaRangeX;
|
||||
binnedYValues.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleCrossPlotStatisticsCase::hasP10Data() const
|
||||
{
|
||||
return !m_p10Data.empty();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleCrossPlotStatisticsCase::hasP50Data() const
|
||||
{
|
||||
return !m_p50Data.empty();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleCrossPlotStatisticsCase::hasP90Data() const
|
||||
{
|
||||
return !m_p90Data.empty();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleCrossPlotStatisticsCase::hasMeanData() const
|
||||
{
|
||||
return !m_meanData.empty();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::EclipseUnitSystem RimEnsembleCrossPlotStatisticsCase::unitSystem() const
|
||||
{
|
||||
if ( m_firstSummaryCase && m_firstSummaryCase->summaryReader() )
|
||||
{
|
||||
return m_firstSummaryCase->summaryReader()->unitSystem();
|
||||
}
|
||||
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<time_t> RimEnsembleCrossPlotStatisticsCase::timeSteps( const RifEclipseSummaryAddress& resultAddress ) const
|
||||
{
|
||||
if ( m_firstSummaryCase && m_firstSummaryCase->summaryReader() )
|
||||
{
|
||||
return m_firstSummaryCase->summaryReader()->timeSteps( resultAddress );
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleCrossPlotStatisticsCase::clearData()
|
||||
{
|
||||
m_binnedXValues.clear();
|
||||
m_p10Data.clear();
|
||||
m_p50Data.clear();
|
||||
m_p90Data.clear();
|
||||
m_meanData.clear();
|
||||
m_firstSummaryCase = nullptr;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017- Statoil ASA
|
||||
// Copyright (C) 2023- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@@ -18,28 +18,57 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RiaDateTimeDefines.h"
|
||||
#include "RiaDefines.h"
|
||||
|
||||
#include "RifSummaryReaderInterface.h"
|
||||
|
||||
class RimEnsembleStatisticsCase;
|
||||
#include "RimSummaryCase.h"
|
||||
|
||||
class RifEclipseSummaryAddress;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RifEnsembleStatisticsReader : public RifSummaryReaderInterface
|
||||
class RimEnsembleCrossPlotStatisticsCase : public RimSummaryCase, public RifSummaryReaderInterface
|
||||
{
|
||||
public:
|
||||
RifEnsembleStatisticsReader( RimEnsembleStatisticsCase* ensStatCase );
|
||||
RimEnsembleCrossPlotStatisticsCase();
|
||||
|
||||
void calculate( const std::vector<RimSummaryCase*>& sumCases,
|
||||
const RifEclipseSummaryAddress& inputAddressX,
|
||||
const RifEclipseSummaryAddress& inputAddressY,
|
||||
bool includeIncompleteCurves,
|
||||
int binCount,
|
||||
int sampleCountThreshold );
|
||||
|
||||
bool hasP10Data() const;
|
||||
bool hasP50Data() const;
|
||||
bool hasP90Data() const;
|
||||
bool hasMeanData() const;
|
||||
|
||||
QString caseName() const override;
|
||||
void createSummaryReaderInterface() override;
|
||||
RifSummaryReaderInterface* summaryReader() override;
|
||||
RiaDefines::EclipseUnitSystem unitSystem() const override;
|
||||
|
||||
std::vector<time_t> timeSteps( const RifEclipseSummaryAddress& resultAddress ) const override;
|
||||
bool values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const override;
|
||||
std::string unitName( const RifEclipseSummaryAddress& resultAddress ) const override;
|
||||
|
||||
RiaDefines::EclipseUnitSystem unitSystem() const override;
|
||||
private:
|
||||
void clearData();
|
||||
|
||||
private:
|
||||
bool validateAddress( const RifEclipseSummaryAddress& address ) const;
|
||||
std::vector<double> m_p10Data;
|
||||
std::vector<double> m_p50Data;
|
||||
std::vector<double> m_p90Data;
|
||||
std::vector<double> m_meanData;
|
||||
|
||||
private:
|
||||
RimEnsembleStatisticsCase* m_ensembleStatCase;
|
||||
RifEclipseSummaryAddress m_adrX;
|
||||
RifEclipseSummaryAddress m_adrY;
|
||||
|
||||
std::vector<double> m_binnedXValues;
|
||||
|
||||
caf::PdmPointer<RimSummaryCase> m_firstSummaryCase;
|
||||
};
|
||||
@@ -30,8 +30,6 @@
|
||||
#include "RimSummaryCalculationCollection.h"
|
||||
#include "SummaryPlotCommands/RicSummaryPlotEditorUi.h"
|
||||
|
||||
#include "RifEnsembleStatisticsReader.h"
|
||||
|
||||
#include "RimCustomObjectiveFunction.h"
|
||||
#include "RimCustomObjectiveFunctionCollection.h"
|
||||
#include "RimDerivedEnsembleCaseCollection.h"
|
||||
@@ -43,10 +41,12 @@
|
||||
#include "RimEnsembleStatisticsCase.h"
|
||||
#include "RimObjectiveFunction.h"
|
||||
#include "RimObjectiveFunctionTools.h"
|
||||
#include "RimPlotAxisProperties.h"
|
||||
#include "RimPlotAxisPropertiesInterface.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimRegularLegendConfig.h"
|
||||
#include "RimSummaryAddress.h"
|
||||
#include "RimSummaryAddressSelector.h"
|
||||
#include "RimSummaryCalculationCollection.h"
|
||||
#include "RimSummaryCase.h"
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
@@ -139,6 +139,19 @@ RimEnsembleCurveSet::RimEnsembleCurveSet()
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_resampling, "Resampling", "Resampling" );
|
||||
|
||||
// X Axis
|
||||
CAF_PDM_InitField( &m_xAxisType,
|
||||
"HorizontalAxisType",
|
||||
caf::AppEnum<RiaDefines::HorizontalAxisType>( RiaDefines::HorizontalAxisType::TIME ),
|
||||
"Axis Type" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_xAddressSelector, "XAddressSelector", "" );
|
||||
m_xAddressSelector = new RimSummaryAddressSelector;
|
||||
m_xAddressSelector.uiCapability()->setUiTreeHidden( true );
|
||||
m_xAddressSelector.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
|
||||
m_xAddressSelector->addressChanged.connect( this, &RimEnsembleCurveSet::onXAxisAddressChanged );
|
||||
|
||||
CAF_PDM_InitField( &m_colorMode, "ColorMode", caf::AppEnum<ColorMode>( ColorMode::SINGLE_COLOR_WITH_ALPHA ), "Coloring Mode" );
|
||||
|
||||
CAF_PDM_InitField( &m_colorForRealizations, "Color", RiaColorTools::textColor3f(), "Color" );
|
||||
@@ -228,9 +241,8 @@ RimEnsembleCurveSet::RimEnsembleCurveSet()
|
||||
|
||||
m_summaryAddressNameTools = new RimSummaryCurveAutoName;
|
||||
|
||||
m_ensembleStatCase.reset( new RimEnsembleStatisticsCase( this ) );
|
||||
m_ensembleStatCase->createSummaryReaderInterface();
|
||||
m_ensembleStatCase->createRftReaderInterface();
|
||||
m_ensembleStatCaseY.reset( new RimEnsembleStatisticsCase() );
|
||||
m_ensembleStatCaseXY.reset( new RimEnsembleCrossPlotStatisticsCase() );
|
||||
|
||||
m_disableStatisticCurves = false;
|
||||
m_isCurveSetFiltered = false;
|
||||
@@ -406,6 +418,31 @@ void RimEnsembleCurveSet::setSummaryAddress( RifEclipseSummaryAddress address )
|
||||
m_objectiveValuesSummaryAddresses.push_back( summaryAddress );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleCurveSet::setCurveAddress( RiaSummaryCurveAddress address )
|
||||
{
|
||||
setSummaryAddress( address.summaryAddressY() );
|
||||
setSummaryAddressX( address.summaryAddressX() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleCurveSet::setSummaryAddressX( RifEclipseSummaryAddress address )
|
||||
{
|
||||
m_xAddressSelector->setAddress( address );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleCurveSet::isXAxisSummaryVector() const
|
||||
{
|
||||
return m_xAxisType() == RiaDefines::HorizontalAxisType::SUMMARY_VECTOR;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -429,7 +466,12 @@ RifEclipseSummaryAddress RimEnsembleCurveSet::summaryAddress() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaSummaryCurveAddress RimEnsembleCurveSet::curveAddress() const
|
||||
{
|
||||
return RiaSummaryCurveAddress( summaryAddress(), RifEclipseSummaryAddress::timeAddress() );
|
||||
if ( m_xAxisType() == RiaDefines::HorizontalAxisType::TIME )
|
||||
{
|
||||
return RiaSummaryCurveAddress( RifEclipseSummaryAddress::timeAddress(), summaryAddress() );
|
||||
}
|
||||
|
||||
return RiaSummaryCurveAddress( m_xAddressSelector->summaryAddress(), summaryAddress() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -678,6 +720,42 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi
|
||||
|
||||
updateTextInPlot = true;
|
||||
}
|
||||
else if ( &m_xAxisType == changedField )
|
||||
{
|
||||
if ( m_xAxisType() == RiaDefines::HorizontalAxisType::TIME )
|
||||
{
|
||||
// TODO: How to handle this?
|
||||
// m_xPlotAxisProperties = plot->timeAxisProperties();
|
||||
}
|
||||
else if ( isXAxisSummaryVector() )
|
||||
{
|
||||
if ( !m_xAddressSelector->ensemble() )
|
||||
{
|
||||
m_xAddressSelector->setEnsemble( summaryCaseCollection() );
|
||||
m_xAddressSelector->setAddress( summaryAddress() );
|
||||
}
|
||||
|
||||
if ( !m_xAddressSelector->plotAxisProperties() )
|
||||
{
|
||||
RiuPlotAxis plotAxis = RiuPlotAxis::defaultBottomForSummaryVectors();
|
||||
if ( auto axis = plot->axisPropertiesForPlotAxis( plotAxis ) )
|
||||
{
|
||||
m_xAddressSelector->setPlotAxisProperties( axis );
|
||||
}
|
||||
else
|
||||
{
|
||||
RimPlotAxisProperties* newPlotAxisProperties =
|
||||
plot->addNewAxisProperties( RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM, "Bottom Axis" );
|
||||
plot->updateConnectedEditors();
|
||||
|
||||
m_xAddressSelector->setPlotAxisProperties( newPlotAxisProperties );
|
||||
}
|
||||
}
|
||||
}
|
||||
plot->updateAxes();
|
||||
plot->updatePlotTitle();
|
||||
updateAllCurves();
|
||||
}
|
||||
else if ( changedField == &m_resampling )
|
||||
{
|
||||
updateAllCurves();
|
||||
@@ -914,8 +992,10 @@ void RimEnsembleCurveSet::defineObjectEditorAttribute( QString uiConfigName, caf
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleCurveSet::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
m_yValuesSummaryAddressUiField = m_yValuesSummaryAddress->address();
|
||||
|
||||
{
|
||||
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Summary Vector Y" );
|
||||
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Summary Vector" );
|
||||
curveDataGroup->add( &m_yValuesSummaryCaseCollection );
|
||||
curveDataGroup->add( &m_yValuesSummaryAddressUiField );
|
||||
curveDataGroup->add( &m_yPushButtonSelectSummaryAddress, { false, 1, 0 } );
|
||||
@@ -923,6 +1003,16 @@ void RimEnsembleCurveSet::defineUiOrdering( QString uiConfigName, caf::PdmUiOrde
|
||||
curveDataGroup->add( &m_plotAxisProperties );
|
||||
}
|
||||
|
||||
{
|
||||
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Summary Vector X Axis" );
|
||||
curveDataGroup->add( &m_xAxisType );
|
||||
|
||||
if ( isXAxisSummaryVector() )
|
||||
{
|
||||
m_xAddressSelector->uiOrdering( uiConfigName, *curveDataGroup );
|
||||
}
|
||||
}
|
||||
|
||||
appendColorGroup( uiOrdering );
|
||||
|
||||
{
|
||||
@@ -986,6 +1076,14 @@ void RimEnsembleCurveSet::onCustomObjectiveFunctionChanged( const caf::SignalEmi
|
||||
updateObjectiveFunctionLegend();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleCurveSet::onXAxisAddressChanged( const caf::SignalEmitter* emitter )
|
||||
{
|
||||
updateAllCurves();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -1790,8 +1888,6 @@ void RimEnsembleCurveSet::updateEnsembleCurves( const std::vector<RimSummaryCase
|
||||
|
||||
if ( m_statistics->hideEnsembleCurves() ) return;
|
||||
|
||||
setLeftOrRightAxisY( axisY() );
|
||||
|
||||
RimSummaryAddress* addr = m_yValuesSummaryAddress();
|
||||
if ( plot && addr->address().category() != RifEclipseSummaryAddressDefines::SummaryCategory::SUMMARY_INVALID )
|
||||
{
|
||||
@@ -1817,6 +1913,14 @@ void RimEnsembleCurveSet::updateEnsembleCurves( const std::vector<RimSummaryCase
|
||||
addCurve( curve );
|
||||
|
||||
curve->setLeftOrRightAxisY( axisY() );
|
||||
if ( isXAxisSummaryVector() )
|
||||
{
|
||||
curve->setAxisTypeX( RiaDefines::HorizontalAxisType::SUMMARY_VECTOR );
|
||||
curve->setSummaryCaseX( sumCase );
|
||||
curve->setSummaryAddressX( m_xAddressSelector->summaryAddress() );
|
||||
if ( m_xAddressSelector->plotAxisProperties() )
|
||||
curve->setTopOrBottomAxisX( m_xAddressSelector->plotAxisProperties()->plotAxis() );
|
||||
}
|
||||
|
||||
newSummaryCurves.push_back( curve );
|
||||
}
|
||||
@@ -1877,22 +1981,70 @@ void RimEnsembleCurveSet::updateStatisticsCurves( const std::vector<RimSummaryCa
|
||||
else
|
||||
statCases = group->allSummaryCases();
|
||||
}
|
||||
m_ensembleStatCase->calculate( statCases, m_statistics->includeIncompleteCurves() );
|
||||
|
||||
if ( isXAxisSummaryVector() )
|
||||
{
|
||||
m_ensembleStatCaseXY->calculate( statCases,
|
||||
m_xAddressSelector->summaryAddress(),
|
||||
summaryAddress(),
|
||||
m_statistics->includeIncompleteCurves(),
|
||||
m_statistics->crossPlotCurvesBinCount(),
|
||||
m_statistics->crossPlotCurvesSampleCountThresholdPerBin() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ensembleStatCaseY->calculate( statCases, summaryAddress(), m_statistics->includeIncompleteCurves() );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<RifEclipseSummaryAddress> addresses;
|
||||
std::vector<RiaSummaryCurveAddress> addresses;
|
||||
if ( m_statistics->isActive() )
|
||||
{
|
||||
RifEclipseSummaryAddress dataAddress = m_yValuesSummaryAddress->address();
|
||||
if ( isXAxisSummaryVector() )
|
||||
{
|
||||
RifEclipseSummaryAddress dataAddressY = m_yValuesSummaryAddress->address();
|
||||
RifEclipseSummaryAddress dataAddressX = m_xAddressSelector->summaryAddress();
|
||||
|
||||
if ( m_statistics->showP10Curve() && m_ensembleStatCase->hasP10Data() )
|
||||
addresses.push_back( SAddr::ensembleStatisticsAddress( ENSEMBLE_STAT_P10_QUANTITY_NAME, dataAddress.vectorName() ) );
|
||||
if ( m_statistics->showP50Curve() && m_ensembleStatCase->hasP50Data() )
|
||||
addresses.push_back( SAddr::ensembleStatisticsAddress( ENSEMBLE_STAT_P50_QUANTITY_NAME, dataAddress.vectorName() ) );
|
||||
if ( m_statistics->showP90Curve() && m_ensembleStatCase->hasP90Data() )
|
||||
addresses.push_back( SAddr::ensembleStatisticsAddress( ENSEMBLE_STAT_P90_QUANTITY_NAME, dataAddress.vectorName() ) );
|
||||
if ( m_statistics->showMeanCurve() && m_ensembleStatCase->hasMeanData() )
|
||||
addresses.push_back( SAddr::ensembleStatisticsAddress( ENSEMBLE_STAT_MEAN_QUANTITY_NAME, dataAddress.vectorName() ) );
|
||||
auto getStatisticsAddress = []( const std::string& statisticsVectorName,
|
||||
const RifEclipseSummaryAddress& addrX,
|
||||
const RifEclipseSummaryAddress& addrY ) -> RiaSummaryCurveAddress
|
||||
{
|
||||
auto xStatAddress = SAddr::ensembleStatisticsAddress( statisticsVectorName, addrX.vectorName() );
|
||||
auto yStatAddress = SAddr::ensembleStatisticsAddress( statisticsVectorName, addrY.vectorName() );
|
||||
|
||||
return RiaSummaryCurveAddress( xStatAddress, yStatAddress );
|
||||
};
|
||||
|
||||
if ( m_statistics->showP10Curve() && m_ensembleStatCaseXY->hasP10Data() )
|
||||
addresses.push_back( getStatisticsAddress( ENSEMBLE_STAT_P10_QUANTITY_NAME, dataAddressX, dataAddressY ) );
|
||||
if ( m_statistics->showP50Curve() && m_ensembleStatCaseXY->hasP50Data() )
|
||||
addresses.push_back( getStatisticsAddress( ENSEMBLE_STAT_P50_QUANTITY_NAME, dataAddressX, dataAddressY ) );
|
||||
if ( m_statistics->showP90Curve() && m_ensembleStatCaseXY->hasP90Data() )
|
||||
addresses.push_back( getStatisticsAddress( ENSEMBLE_STAT_P90_QUANTITY_NAME, dataAddressX, dataAddressY ) );
|
||||
if ( m_statistics->showMeanCurve() && m_ensembleStatCaseXY->hasMeanData() )
|
||||
addresses.push_back( getStatisticsAddress( ENSEMBLE_STAT_MEAN_QUANTITY_NAME, dataAddressX, dataAddressY ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
RifEclipseSummaryAddress dataAddressY = m_yValuesSummaryAddress->address();
|
||||
|
||||
auto getStatisticsAddress = []( const std::string& statisticsVectorName, const RifEclipseSummaryAddress& addrY ) -> RiaSummaryCurveAddress
|
||||
{
|
||||
auto xStatAddress = RifEclipseSummaryAddress::timeAddress();
|
||||
auto yStatAddress = SAddr::ensembleStatisticsAddress( statisticsVectorName, addrY.vectorName() );
|
||||
|
||||
return RiaSummaryCurveAddress( xStatAddress, yStatAddress );
|
||||
};
|
||||
|
||||
if ( m_statistics->showP10Curve() && m_ensembleStatCaseY->hasP10Data() )
|
||||
addresses.push_back( getStatisticsAddress( ENSEMBLE_STAT_P10_QUANTITY_NAME, dataAddressY ) );
|
||||
if ( m_statistics->showP50Curve() && m_ensembleStatCaseY->hasP50Data() )
|
||||
addresses.push_back( getStatisticsAddress( ENSEMBLE_STAT_P50_QUANTITY_NAME, dataAddressY ) );
|
||||
if ( m_statistics->showP90Curve() && m_ensembleStatCaseY->hasP90Data() )
|
||||
addresses.push_back( getStatisticsAddress( ENSEMBLE_STAT_P90_QUANTITY_NAME, dataAddressY ) );
|
||||
if ( m_statistics->showMeanCurve() && m_ensembleStatCaseY->hasMeanData() )
|
||||
addresses.push_back( getStatisticsAddress( ENSEMBLE_STAT_MEAN_QUANTITY_NAME, dataAddressY ) );
|
||||
}
|
||||
}
|
||||
|
||||
deleteStatisticsCurves();
|
||||
@@ -1900,6 +2052,13 @@ void RimEnsembleCurveSet::updateStatisticsCurves( const std::vector<RimSummaryCa
|
||||
auto plot = firstAncestorOrThisOfType<RimSummaryPlot>();
|
||||
if ( plot && plot->plotWidget() )
|
||||
{
|
||||
RimSummaryCase* summaryCase = nullptr;
|
||||
|
||||
if ( isXAxisSummaryVector() )
|
||||
summaryCase = m_ensembleStatCaseXY.get();
|
||||
else
|
||||
summaryCase = m_ensembleStatCaseY.get();
|
||||
|
||||
for ( auto address : addresses )
|
||||
{
|
||||
auto curve = new RimSummaryCurve();
|
||||
@@ -1908,19 +2067,28 @@ void RimEnsembleCurveSet::updateStatisticsCurves( const std::vector<RimSummaryCa
|
||||
curve->setColor( m_statistics->color() );
|
||||
curve->setResampling( m_resampling() );
|
||||
|
||||
auto symbol = statisticsCurveSymbolFromAddress( address );
|
||||
auto symbol = statisticsCurveSymbolFromAddress( address.summaryAddressY() );
|
||||
curve->setSymbol( symbol );
|
||||
curve->setSymbolSize( statisticsCurveSymbolSize( symbol ) );
|
||||
curve->setSymbolSkipDistance( 150 );
|
||||
if ( m_statistics->showCurveLabels() )
|
||||
{
|
||||
curve->setSymbolLabel( QString::fromStdString( address.ensembleStatisticsVectorName() ) );
|
||||
curve->setSymbolLabel( QString::fromStdString( address.summaryAddressY().ensembleStatisticsVectorName() ) );
|
||||
}
|
||||
curve->setLineStyle( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_SOLID );
|
||||
curve->setSummaryCaseY( m_ensembleStatCase.get() );
|
||||
curve->setSummaryAddressYAndApplyInterpolation( address );
|
||||
curve->setSummaryCaseY( summaryCase );
|
||||
curve->setSummaryAddressYAndApplyInterpolation( address.summaryAddressY() );
|
||||
curve->setLeftOrRightAxisY( axisY() );
|
||||
|
||||
if ( isXAxisSummaryVector() )
|
||||
{
|
||||
curve->setAxisTypeX( RiaDefines::HorizontalAxisType::SUMMARY_VECTOR );
|
||||
curve->setSummaryCaseX( summaryCase );
|
||||
curve->setSummaryAddressX( address.summaryAddressX() );
|
||||
if ( m_xAddressSelector->plotAxisProperties() )
|
||||
curve->setTopOrBottomAxisX( m_xAddressSelector->plotAxisProperties()->plotAxis() );
|
||||
}
|
||||
|
||||
curve->setShowInLegend( m_statistics->showStatisticsCurveLegends() );
|
||||
|
||||
curve->updateCurveVisibility();
|
||||
@@ -2058,7 +2226,9 @@ bool RimEnsembleCurveSet::isFiltered() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleCurveSet::hasP10Data() const
|
||||
{
|
||||
return m_ensembleStatCase->hasP10Data();
|
||||
if ( isXAxisSummaryVector() ) return m_ensembleStatCaseXY->hasP10Data();
|
||||
|
||||
return m_ensembleStatCaseY->hasP10Data();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -2066,7 +2236,9 @@ bool RimEnsembleCurveSet::hasP10Data() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleCurveSet::hasP50Data() const
|
||||
{
|
||||
return m_ensembleStatCase->hasP50Data();
|
||||
if ( isXAxisSummaryVector() ) return m_ensembleStatCaseXY->hasP50Data();
|
||||
|
||||
return m_ensembleStatCaseY->hasP50Data();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -2074,7 +2246,9 @@ bool RimEnsembleCurveSet::hasP50Data() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleCurveSet::hasP90Data() const
|
||||
{
|
||||
return m_ensembleStatCase->hasP90Data();
|
||||
if ( isXAxisSummaryVector() ) return m_ensembleStatCaseXY->hasP90Data();
|
||||
|
||||
return m_ensembleStatCaseY->hasP90Data();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -2082,7 +2256,9 @@ bool RimEnsembleCurveSet::hasP90Data() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleCurveSet::hasMeanData() const
|
||||
{
|
||||
return m_ensembleStatCase->hasMeanData();
|
||||
if ( isXAxisSummaryVector() ) return m_ensembleStatCaseXY->hasMeanData();
|
||||
|
||||
return m_ensembleStatCaseY->hasMeanData();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
#include "RiaDateTimeDefines.h"
|
||||
#include "RiaPlotDefines.h"
|
||||
#include "RiaSummaryCurveAddress.h"
|
||||
#include "RiaSummaryDefines.h"
|
||||
|
||||
#include "RimEnsembleCrossPlotStatisticsCase.h"
|
||||
#include "RimEnsembleCurveSetColorManager.h"
|
||||
#include "RimEnsembleCurveSetInterface.h"
|
||||
#include "RimTimeStepFilter.h"
|
||||
@@ -64,6 +66,7 @@ class RiuSummaryVectorSelectionDialog;
|
||||
class RiuPlotWidget;
|
||||
class RiuPlotCurve;
|
||||
class RimPlotAxisPropertiesInterface;
|
||||
class RimSummaryAddressSelector;
|
||||
|
||||
class QwtPlot;
|
||||
class QwtPlotCurve;
|
||||
@@ -111,6 +114,7 @@ public:
|
||||
void deleteCurve( RimSummaryCurve* curve );
|
||||
|
||||
void setSummaryAddress( RifEclipseSummaryAddress address );
|
||||
void setCurveAddress( RiaSummaryCurveAddress address );
|
||||
void setSummaryAddressAndStatisticsFlag( RifEclipseSummaryAddress address );
|
||||
RifEclipseSummaryAddress summaryAddress() const;
|
||||
RiaSummaryCurveAddress curveAddress() const;
|
||||
@@ -215,10 +219,14 @@ private:
|
||||
|
||||
void onObjectiveFunctionChanged( const caf::SignalEmitter* emitter );
|
||||
void onCustomObjectiveFunctionChanged( const caf::SignalEmitter* emitter );
|
||||
void onXAxisAddressChanged( const caf::SignalEmitter* emitter );
|
||||
|
||||
void setTransparentCurveColor();
|
||||
void onColorTagClicked( const SignalEmitter* emitter, size_t index );
|
||||
|
||||
void setSummaryAddressX( RifEclipseSummaryAddress address );
|
||||
bool isXAxisSummaryVector() const;
|
||||
|
||||
private:
|
||||
caf::PdmField<bool> m_showCurves;
|
||||
caf::PdmChildArrayField<RimSummaryCurve*> m_curves;
|
||||
@@ -231,6 +239,9 @@ private:
|
||||
caf::PdmField<bool> m_yPushButtonSelectSummaryAddress;
|
||||
caf::PdmField<RiaDefines::DateTimePeriodEnum> m_resampling;
|
||||
|
||||
caf::PdmField<caf::AppEnum<RiaDefines::HorizontalAxisType>> m_xAxisType;
|
||||
caf::PdmChildField<RimSummaryAddressSelector*> m_xAddressSelector;
|
||||
|
||||
caf::PdmField<ColorModeEnum> m_colorMode;
|
||||
caf::PdmField<cvf::Color3f> m_mainEnsembleColor;
|
||||
caf::PdmField<cvf::Color3f> m_colorForRealizations;
|
||||
@@ -270,7 +281,8 @@ private:
|
||||
QPointer<RiuDraggableOverlayFrame> m_filterOverlayFrame;
|
||||
QPointer<RiuDraggableOverlayFrame> m_objectiveFunctionOverlayFrame;
|
||||
|
||||
std::unique_ptr<RimEnsembleStatisticsCase> m_ensembleStatCase;
|
||||
std::unique_ptr<RimEnsembleStatisticsCase> m_ensembleStatCaseY;
|
||||
std::unique_ptr<RimEnsembleCrossPlotStatisticsCase> m_ensembleStatCaseXY;
|
||||
|
||||
std::unique_ptr<RiaSummaryCurveDefinitionAnalyser> m_analyserOfSelectedCurveDefs;
|
||||
|
||||
|
||||
@@ -46,6 +46,12 @@ RimEnsembleStatistics::RimEnsembleStatistics( RimEnsembleCurveSetInterface* pare
|
||||
CAF_PDM_InitField( &m_showCurveLabels, "ShowCurveLabels", true, "Show Curve Labels" );
|
||||
CAF_PDM_InitField( &m_includeIncompleteCurves, "IncludeIncompleteCurves", false, "Include Incomplete Curves" );
|
||||
|
||||
CAF_PDM_InitField( &m_crossPlotCurvesBinCount, "CrossPlotCurvesBinCount", 100, "Bin Count" );
|
||||
CAF_PDM_InitField( &m_crossPlotCurvesStatisticsSampleCountThresholdPerBin,
|
||||
"CrossPlotCurvesStatisticsSampleCountThresholdPerBin",
|
||||
100,
|
||||
"Sample Threshold per Bin" );
|
||||
|
||||
CAF_PDM_InitField( &m_warningLabel, "WarningLabel", QString( "Warning: Ensemble time range mismatch" ), "" );
|
||||
|
||||
CAF_PDM_InitField( &m_color, "Color", RiaColorTools::textColor3f(), "Color" );
|
||||
@@ -79,6 +85,22 @@ void RimEnsembleStatistics::setShowStatisticsCurves( bool show )
|
||||
m_active = show;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RimEnsembleStatistics::crossPlotCurvesBinCount() const
|
||||
{
|
||||
return m_crossPlotCurvesBinCount;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RimEnsembleStatistics::crossPlotCurvesSampleCountThresholdPerBin() const
|
||||
{
|
||||
return m_crossPlotCurvesStatisticsSampleCountThresholdPerBin;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -124,27 +146,23 @@ void RimEnsembleStatistics::showColorField( bool show )
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleStatistics::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
||||
{
|
||||
if ( changedField == &m_active || changedField == &m_basedOnFilteredCases || changedField == &m_showP10Curve ||
|
||||
changedField == &m_showP50Curve || changedField == &m_showP90Curve || changedField == &m_showMeanCurve ||
|
||||
changedField == &m_showCurveLabels || changedField == &m_color || changedField == &m_includeIncompleteCurves ||
|
||||
changedField == &m_showStatisticsCurveLegends )
|
||||
{
|
||||
auto curveSet = m_parentCurveSet;
|
||||
if ( !curveSet ) return;
|
||||
|
||||
curveSet->updateStatisticsCurves();
|
||||
|
||||
// Trigger update of tree view editor for ensemble curve set as they depend on these fields
|
||||
if ( changedField == &m_active || changedField == &m_basedOnFilteredCases || changedField == &m_color ) curveSet->updateEditors();
|
||||
}
|
||||
|
||||
if ( changedField == &m_hideEnsembleCurves )
|
||||
{
|
||||
auto curveSet = m_parentCurveSet;
|
||||
if ( !curveSet ) return;
|
||||
|
||||
curveSet->updateAllCurves();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto curveSet = m_parentCurveSet;
|
||||
if ( !curveSet ) return;
|
||||
|
||||
curveSet->updateStatisticsCurves();
|
||||
|
||||
// Trigger update of tree view editor for ensemble curve set as they depend on these fields
|
||||
if ( changedField == &m_active || changedField == &m_basedOnFilteredCases || changedField == &m_color ) curveSet->updateEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -162,6 +180,10 @@ void RimEnsembleStatistics::defineUiOrdering( QString uiConfigName, caf::PdmUiOr
|
||||
uiOrdering.add( &m_includeIncompleteCurves );
|
||||
uiOrdering.add( &m_showCurveLabels );
|
||||
|
||||
auto crossPlotGroup = uiOrdering.addNewGroup( "Cross Plot" );
|
||||
crossPlotGroup->add( &m_crossPlotCurvesBinCount );
|
||||
crossPlotGroup->add( &m_crossPlotCurvesStatisticsSampleCountThresholdPerBin );
|
||||
|
||||
if ( m_showColorField ) uiOrdering.add( &m_color );
|
||||
|
||||
auto group = uiOrdering.addNewGroup( "Curves" );
|
||||
|
||||
@@ -52,6 +52,9 @@ public:
|
||||
|
||||
bool includeIncompleteCurves() const { return m_includeIncompleteCurves; }
|
||||
|
||||
int crossPlotCurvesBinCount() const;
|
||||
int crossPlotCurvesSampleCountThresholdPerBin() const;
|
||||
|
||||
void disableP10Curve( bool disable );
|
||||
void disableP50Curve( bool disable );
|
||||
void disableP90Curve( bool disable );
|
||||
@@ -76,6 +79,10 @@ private:
|
||||
caf::PdmField<bool> m_showCurveLabels;
|
||||
caf::PdmField<bool> m_includeIncompleteCurves;
|
||||
|
||||
// Ensemble cross plot settings
|
||||
caf::PdmField<int> m_crossPlotCurvesBinCount;
|
||||
caf::PdmField<int> m_crossPlotCurvesStatisticsSampleCountThresholdPerBin;
|
||||
|
||||
caf::PdmField<QString> m_warningLabel;
|
||||
|
||||
bool m_showColorField;
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
#include "RimEnsembleStatisticsCase.h"
|
||||
|
||||
#include "RifEnsembleStatisticsReader.h"
|
||||
|
||||
#include "RiaSummaryTools.h"
|
||||
#include "RiaTimeHistoryCurveResampler.h"
|
||||
|
||||
@@ -40,9 +38,8 @@
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEnsembleStatisticsCase::RimEnsembleStatisticsCase( RimEnsembleCurveSet* curveSet )
|
||||
RimEnsembleStatisticsCase::RimEnsembleStatisticsCase()
|
||||
{
|
||||
m_curveSet = curveSet;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -56,33 +53,73 @@ const std::vector<time_t>& RimEnsembleStatisticsCase::timeSteps() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<double>& RimEnsembleStatisticsCase::p10() const
|
||||
std::vector<time_t> RimEnsembleStatisticsCase::timeSteps( const RifEclipseSummaryAddress& resultAddress ) const
|
||||
{
|
||||
return m_p10Data;
|
||||
return m_timeSteps;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<double>& RimEnsembleStatisticsCase::p50() const
|
||||
bool RimEnsembleStatisticsCase::hasP10Data() const
|
||||
{
|
||||
return m_p50Data;
|
||||
return !m_p10Data.empty();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<double>& RimEnsembleStatisticsCase::p90() const
|
||||
bool RimEnsembleStatisticsCase::hasP50Data() const
|
||||
{
|
||||
return m_p90Data;
|
||||
return !m_p50Data.empty();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<double>& RimEnsembleStatisticsCase::mean() const
|
||||
bool RimEnsembleStatisticsCase::hasP90Data() const
|
||||
{
|
||||
return m_meanData;
|
||||
return !m_p90Data.empty();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleStatisticsCase::hasMeanData() const
|
||||
{
|
||||
return !m_meanData.empty();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleStatisticsCase::values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const
|
||||
{
|
||||
auto quantityName = resultAddress.ensembleStatisticsVectorName();
|
||||
|
||||
if ( quantityName == ENSEMBLE_STAT_P10_QUANTITY_NAME )
|
||||
*values = m_p10Data;
|
||||
else if ( quantityName == ENSEMBLE_STAT_P50_QUANTITY_NAME )
|
||||
*values = m_p50Data;
|
||||
else if ( quantityName == ENSEMBLE_STAT_P90_QUANTITY_NAME )
|
||||
*values = m_p90Data;
|
||||
else if ( quantityName == ENSEMBLE_STAT_MEAN_QUANTITY_NAME )
|
||||
*values = m_meanData;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimEnsembleStatisticsCase::unitName( const RifEclipseSummaryAddress& resultAddress ) const
|
||||
{
|
||||
if ( m_firstSummaryCase && m_firstSummaryCase->summaryReader() )
|
||||
{
|
||||
return m_firstSummaryCase->summaryReader()->unitName( resultAddress );
|
||||
}
|
||||
|
||||
return "Ensemble Statistics Case - Undefined Unit";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -98,7 +135,7 @@ QString RimEnsembleStatisticsCase::caseName() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleStatisticsCase::createSummaryReaderInterface()
|
||||
{
|
||||
m_statisticsReader.reset( new RifEnsembleStatisticsReader( this ) );
|
||||
// Nothing to do here as RimEnsembleStatisticsCase inherits from RifSummaryReaderInterface
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -106,33 +143,7 @@ void RimEnsembleStatisticsCase::createSummaryReaderInterface()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifSummaryReaderInterface* RimEnsembleStatisticsCase::summaryReader()
|
||||
{
|
||||
if ( !m_statisticsReader )
|
||||
{
|
||||
createSummaryReaderInterface();
|
||||
}
|
||||
return m_statisticsReader.get();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const RimEnsembleCurveSet* RimEnsembleStatisticsCase::curveSet() const
|
||||
{
|
||||
return m_curveSet;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*>& sumCases, bool includeIncompleteCurves )
|
||||
{
|
||||
auto inputAddress = m_curveSet->summaryAddress();
|
||||
if ( m_statisticsReader && inputAddress.isValid() )
|
||||
{
|
||||
const std::vector<RimSummaryCase*>& validCases = validSummaryCases( sumCases, inputAddress, includeIncompleteCurves );
|
||||
|
||||
calculate( validCases, inputAddress, includeIncompleteCurves );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -142,15 +153,18 @@ void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*>& s
|
||||
const RifEclipseSummaryAddress& inputAddress,
|
||||
bool includeIncompleteCurves )
|
||||
{
|
||||
std::vector<time_t> allTimeSteps;
|
||||
std::vector<std::vector<double>> caseAndTimeStepValues;
|
||||
|
||||
clearData();
|
||||
if ( !inputAddress.isValid() ) return;
|
||||
if ( sumCases.empty() ) return;
|
||||
|
||||
auto [minTimeStep, maxTimeStep] = findMinMaxTimeStep( sumCases, inputAddress );
|
||||
// Use first summary case to get unit system and other meta data
|
||||
m_firstSummaryCase = sumCases.front();
|
||||
|
||||
auto [minTimeStep, maxTimeStep] = findMinMaxTimeStep( sumCases, inputAddress );
|
||||
RiaDefines::DateTimePeriod period = findBestResamplingPeriod( minTimeStep, maxTimeStep );
|
||||
|
||||
std::vector<time_t> allTimeSteps;
|
||||
std::vector<std::vector<double>> caseAndTimeStepValues;
|
||||
caseAndTimeStepValues.reserve( sumCases.size() );
|
||||
for ( const auto& sumCase : sumCases )
|
||||
{
|
||||
@@ -172,7 +186,6 @@ void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*>& s
|
||||
}
|
||||
}
|
||||
|
||||
clearData();
|
||||
m_timeSteps = allTimeSteps;
|
||||
|
||||
for ( size_t timeStepIndex = 0; timeStepIndex < allTimeSteps.size(); timeStepIndex++ )
|
||||
@@ -202,10 +215,11 @@ void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*>& s
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::EclipseUnitSystem RimEnsembleStatisticsCase::unitSystem() const
|
||||
{
|
||||
if ( m_curveSet )
|
||||
if ( m_firstSummaryCase && m_firstSummaryCase->summaryReader() )
|
||||
{
|
||||
return m_curveSet->summaryCaseCollection()->unitSystem();
|
||||
return m_firstSummaryCase->summaryReader()->unitSystem();
|
||||
}
|
||||
|
||||
return RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -219,6 +233,7 @@ void RimEnsembleStatisticsCase::clearData()
|
||||
m_p50Data.clear();
|
||||
m_p90Data.clear();
|
||||
m_meanData.clear();
|
||||
m_firstSummaryCase = nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -21,43 +21,38 @@
|
||||
#include "RiaDateTimeDefines.h"
|
||||
#include "RiaDefines.h"
|
||||
|
||||
#include "RifSummaryReaderInterface.h"
|
||||
|
||||
#include "RimSummaryCase.h"
|
||||
|
||||
class RifEnsembleStatisticsReader;
|
||||
class RimEnsembleCurveSet;
|
||||
class RifEclipseSummaryAddress;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimEnsembleStatisticsCase : public RimSummaryCase
|
||||
class RimEnsembleStatisticsCase : public RimSummaryCase, public RifSummaryReaderInterface
|
||||
{
|
||||
public:
|
||||
RimEnsembleStatisticsCase( RimEnsembleCurveSet* curveSet );
|
||||
RimEnsembleStatisticsCase();
|
||||
|
||||
const std::vector<time_t>& timeSteps() const;
|
||||
const std::vector<double>& p10() const;
|
||||
const std::vector<double>& p50() const;
|
||||
const std::vector<double>& p90() const;
|
||||
const std::vector<double>& mean() const;
|
||||
|
||||
bool hasP10Data() const { return !m_p10Data.empty(); }
|
||||
bool hasP50Data() const { return !m_p50Data.empty(); }
|
||||
bool hasP90Data() const { return !m_p90Data.empty(); }
|
||||
bool hasMeanData() const { return !m_meanData.empty(); }
|
||||
bool hasP10Data() const;
|
||||
bool hasP50Data() const;
|
||||
bool hasP90Data() const;
|
||||
bool hasMeanData() const;
|
||||
|
||||
QString caseName() const override;
|
||||
void createSummaryReaderInterface() override;
|
||||
RifSummaryReaderInterface* summaryReader() override;
|
||||
QString caseName() const override;
|
||||
void createSummaryReaderInterface() override;
|
||||
RifSummaryReaderInterface* summaryReader() override;
|
||||
RiaDefines::EclipseUnitSystem unitSystem() const override;
|
||||
|
||||
const RimEnsembleCurveSet* curveSet() const;
|
||||
|
||||
void calculate( const std::vector<RimSummaryCase*>& sumCases, bool includeIncompleteCurves );
|
||||
RiaDefines::EclipseUnitSystem unitSystem() const;
|
||||
|
||||
private:
|
||||
void calculate( const std::vector<RimSummaryCase*>& sumCases, const RifEclipseSummaryAddress& inputAddress, bool includeIncompleteCurves );
|
||||
void clearData();
|
||||
|
||||
std::vector<time_t> timeSteps( const RifEclipseSummaryAddress& resultAddress ) const override;
|
||||
bool values( const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values ) const override;
|
||||
std::string unitName( const RifEclipseSummaryAddress& resultAddress ) const override;
|
||||
|
||||
static std::vector<RimSummaryCase*> validSummaryCases( const std::vector<RimSummaryCase*>& allSumCases,
|
||||
const RifEclipseSummaryAddress& inputAddress,
|
||||
bool includeIncompleteCurves );
|
||||
@@ -66,12 +61,14 @@ private:
|
||||
static RiaDefines::DateTimePeriod findBestResamplingPeriod( time_t minTimeStep, time_t maxTimeStep );
|
||||
|
||||
private:
|
||||
std::unique_ptr<RifEnsembleStatisticsReader> m_statisticsReader;
|
||||
RimEnsembleCurveSet* m_curveSet;
|
||||
void clearData();
|
||||
|
||||
private:
|
||||
std::vector<time_t> m_timeSteps;
|
||||
std::vector<double> m_p10Data;
|
||||
std::vector<double> m_p50Data;
|
||||
std::vector<double> m_p90Data;
|
||||
std::vector<double> m_meanData;
|
||||
|
||||
caf::PdmPointer<RimSummaryCase> m_firstSummaryCase;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2023 Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimSummaryAddressSelector.h"
|
||||
|
||||
#include "RiaResultNames.h"
|
||||
#include "RiaSummaryCurveDefinition.h"
|
||||
#include "RiaSummaryTools.h"
|
||||
|
||||
#include "RifSummaryReaderInterface.h"
|
||||
|
||||
#include "RimPlotAxisPropertiesInterface.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimSummaryAddress.h"
|
||||
#include "RimSummaryCase.h"
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
#include "RimSummaryPlot.h"
|
||||
|
||||
#include "RiuSummaryVectorSelectionDialog.h"
|
||||
|
||||
#include "cafPdmUiLineEditor.h"
|
||||
#include "cafPdmUiPushButtonEditor.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimSummaryAddressSelector, "RimSummaryAddressSelector" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimSummaryAddressSelector::RimSummaryAddressSelector()
|
||||
: addressChanged( this )
|
||||
|
||||
{
|
||||
CAF_PDM_InitFieldNoDefault( &m_summaryCase, "SummaryCase", "Case" );
|
||||
m_summaryCase.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
m_summaryCase.uiCapability()->setAutoAddingOptionFromValue( false );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_summaryCaseCollection, "SummaryCaseCollection", "Ensemble" );
|
||||
m_summaryCaseCollection.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
m_summaryCaseCollection.uiCapability()->setAutoAddingOptionFromValue( false );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_summaryAddressUiField, "summaryAddressUiField", "Vector" );
|
||||
m_summaryAddressUiField.xmlCapability()->disableIO();
|
||||
m_summaryAddressUiField.uiCapability()->setUiEditorTypeName( caf::PdmUiLineEditor::uiEditorTypeName() );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_summaryAddress, "SummaryAddress", "Summary Address" );
|
||||
m_summaryAddress.uiCapability()->setUiTreeHidden( true );
|
||||
m_summaryAddress.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_pushButtonSelectSummaryAddress, "SelectAddress", "" );
|
||||
caf::PdmUiPushButtonEditor::configureEditorForField( &m_pushButtonSelectSummaryAddress );
|
||||
m_pushButtonSelectSummaryAddress.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
|
||||
m_pushButtonSelectSummaryAddress = false;
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_plotAxisProperties, "PlotAxisProperties", "Axis" );
|
||||
|
||||
m_summaryAddress = new RimSummaryAddress;
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_resamplingPeriod, "Resampling", "Resampling" );
|
||||
|
||||
m_dataSource = SummaryDataSource::SINGLE_CASE;
|
||||
m_showDataSource = true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryAddressSelector::setSummaryCase( RimSummaryCase* summaryCase )
|
||||
{
|
||||
m_summaryCase = summaryCase;
|
||||
m_dataSource = SummaryDataSource::SINGLE_CASE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryAddressSelector::setEnsemble( RimSummaryCaseCollection* ensemble )
|
||||
{
|
||||
m_summaryCaseCollection = ensemble;
|
||||
m_dataSource = SummaryDataSource::ENSEMBLE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryAddressSelector::setAddress( const RifEclipseSummaryAddress& address )
|
||||
{
|
||||
m_summaryAddress->setAddress( address );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryAddressSelector::setResamplingPeriod( RiaDefines::DateTimePeriodEnum resampling )
|
||||
{
|
||||
m_resamplingPeriod = resampling;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryAddressSelector::setPlotAxisProperties( RimPlotAxisPropertiesInterface* plotAxisProperties )
|
||||
{
|
||||
m_plotAxisProperties = plotAxisProperties;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryAddressSelector::setShowDataSource( bool enable )
|
||||
{
|
||||
m_showDataSource = enable;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimSummaryCase* RimSummaryAddressSelector::summaryCase() const
|
||||
{
|
||||
return m_summaryCase();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimSummaryCaseCollection* RimSummaryAddressSelector::ensemble() const
|
||||
{
|
||||
return m_summaryCaseCollection();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifEclipseSummaryAddress RimSummaryAddressSelector::summaryAddress() const
|
||||
{
|
||||
return m_summaryAddress()->address();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaDefines::DateTimePeriodEnum RimSummaryAddressSelector::resamplingPeriod() const
|
||||
{
|
||||
return m_resamplingPeriod();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimPlotAxisPropertiesInterface* RimSummaryAddressSelector::plotAxisProperties() const
|
||||
{
|
||||
return m_plotAxisProperties();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryAddressSelector::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
||||
{
|
||||
if ( changedField == &m_pushButtonSelectSummaryAddress )
|
||||
{
|
||||
RiuSummaryVectorSelectionDialog dlg( nullptr );
|
||||
|
||||
if ( m_dataSource == SummaryDataSource::SINGLE_CASE )
|
||||
{
|
||||
dlg.hideEnsembles();
|
||||
dlg.setCaseAndAddress( m_summaryCase(), m_summaryAddress->address() );
|
||||
}
|
||||
else if ( m_dataSource == SummaryDataSource::ENSEMBLE )
|
||||
{
|
||||
dlg.hideSummaryCases();
|
||||
dlg.setEnsembleAndAddress( m_summaryCaseCollection(), m_summaryAddress->address() );
|
||||
}
|
||||
|
||||
if ( dlg.exec() == QDialog::Accepted )
|
||||
{
|
||||
auto curveSelection = dlg.curveSelection();
|
||||
if ( !curveSelection.empty() )
|
||||
{
|
||||
m_summaryCase = curveSelection[0].summaryCaseY();
|
||||
m_summaryCaseCollection = curveSelection[0].ensemble();
|
||||
auto addr = curveSelection[0].summaryAddressY();
|
||||
m_summaryAddress->setAddress( addr );
|
||||
m_summaryAddressUiField = addr;
|
||||
}
|
||||
}
|
||||
|
||||
m_pushButtonSelectSummaryAddress = false;
|
||||
}
|
||||
else if ( changedField == &m_summaryAddressUiField )
|
||||
{
|
||||
m_summaryAddress->setAddress( m_summaryAddressUiField() );
|
||||
}
|
||||
|
||||
addressChanged.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
auto createOptionsForSummaryCase = []() -> QList<caf::PdmOptionItemInfo>
|
||||
{
|
||||
RimProject* proj = RimProject::current();
|
||||
std::vector<RimSummaryCase*> cases = proj->allSummaryCases();
|
||||
|
||||
auto options = RiaSummaryTools::optionsForSummaryCases( cases );
|
||||
if ( !options.empty() )
|
||||
{
|
||||
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
|
||||
}
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
auto createOptionsForEnsemble = []() -> QList<caf::PdmOptionItemInfo>
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
|
||||
RimProject* proj = RimProject::current();
|
||||
std::vector<RimSummaryCaseCollection*> groups = proj->summaryGroups();
|
||||
|
||||
for ( RimSummaryCaseCollection* group : groups )
|
||||
{
|
||||
if ( group->isEnsemble() ) options.push_back( caf::PdmOptionItemInfo( group->name(), group ) );
|
||||
}
|
||||
|
||||
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
|
||||
return options;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
auto createOptionsForAddresses = []( const std::set<RifEclipseSummaryAddress>& allAddresses ) -> QList<caf::PdmOptionItemInfo>
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
|
||||
for ( auto& address : allAddresses )
|
||||
{
|
||||
if ( address.isErrorResult() ) continue;
|
||||
|
||||
std::string name = address.uiText();
|
||||
QString s = QString::fromStdString( name );
|
||||
options.push_back( caf::PdmOptionItemInfo( s, QVariant::fromValue( address ) ) );
|
||||
}
|
||||
|
||||
options.push_front( caf::PdmOptionItemInfo( RiaResultNames::undefinedResultName(), QVariant::fromValue( RifEclipseSummaryAddress() ) ) );
|
||||
return options;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo> RimSummaryAddressSelector::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
|
||||
{
|
||||
if ( fieldNeedingOptions == &m_summaryCase )
|
||||
{
|
||||
return createOptionsForSummaryCase();
|
||||
}
|
||||
|
||||
if ( fieldNeedingOptions == &m_summaryCaseCollection )
|
||||
{
|
||||
return createOptionsForEnsemble();
|
||||
}
|
||||
|
||||
if ( fieldNeedingOptions == &m_summaryAddressUiField )
|
||||
{
|
||||
std::set<RifEclipseSummaryAddress> addresses;
|
||||
if ( m_dataSource == SummaryDataSource::SINGLE_CASE && m_summaryCase() )
|
||||
{
|
||||
RifSummaryReaderInterface* reader = m_summaryCase()->summaryReader();
|
||||
if ( reader )
|
||||
{
|
||||
addresses = reader->allResultAddresses();
|
||||
}
|
||||
}
|
||||
else if ( m_dataSource == SummaryDataSource::ENSEMBLE && m_summaryCaseCollection() )
|
||||
{
|
||||
addresses = m_summaryCaseCollection()->ensembleSummaryAddresses();
|
||||
}
|
||||
|
||||
return createOptionsForAddresses( addresses );
|
||||
}
|
||||
|
||||
if ( fieldNeedingOptions == &m_plotAxisProperties )
|
||||
{
|
||||
if ( auto plot = firstAncestorOrThisOfTypeAsserted<RimSummaryPlot>() )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
for ( auto axis : plot->plotAxes() )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( axis->objectName(), axis ) );
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryAddressSelector::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
if ( m_showDataSource )
|
||||
{
|
||||
if ( m_dataSource == SummaryDataSource::SINGLE_CASE )
|
||||
{
|
||||
uiOrdering.add( &m_summaryCase );
|
||||
}
|
||||
else
|
||||
{
|
||||
uiOrdering.add( &m_summaryCaseCollection );
|
||||
}
|
||||
}
|
||||
|
||||
// Update the UI field, as this is not serialized to file
|
||||
m_summaryAddressUiField = m_summaryAddress->address();
|
||||
|
||||
uiOrdering.add( &m_summaryAddressUiField, { true, 2, 1 } );
|
||||
uiOrdering.add( &m_pushButtonSelectSummaryAddress, { false, 1, 0 } );
|
||||
uiOrdering.add( &m_resamplingPeriod, { true, 3, 1 } );
|
||||
uiOrdering.add( &m_plotAxisProperties, { true, 3, 1 } );
|
||||
|
||||
uiOrdering.skipRemainingFields( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryAddressSelector::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
|
||||
{
|
||||
if ( &m_pushButtonSelectSummaryAddress == field )
|
||||
{
|
||||
auto attrib = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>( attribute );
|
||||
if ( attrib )
|
||||
{
|
||||
attrib->m_buttonText = "...";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2023 Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RiaDateTimeDefines.h"
|
||||
|
||||
#include "RifEclipseSummaryAddress.h"
|
||||
#include "RifEclipseSummaryAddressQMetaType.h"
|
||||
|
||||
#include "cafPdmChildField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
class RimSummaryCase;
|
||||
class RimSummaryCaseCollection;
|
||||
class RimSummaryAddress;
|
||||
class RimPlotAxisPropertiesInterface;
|
||||
|
||||
class RimSummaryAddressSelector : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
enum class SummaryDataSource
|
||||
{
|
||||
SINGLE_CASE,
|
||||
ENSEMBLE
|
||||
};
|
||||
|
||||
caf::Signal<> addressChanged;
|
||||
|
||||
public:
|
||||
RimSummaryAddressSelector();
|
||||
|
||||
void setSummaryCase( RimSummaryCase* summaryCase );
|
||||
void setEnsemble( RimSummaryCaseCollection* ensemble );
|
||||
void setAddress( const RifEclipseSummaryAddress& address );
|
||||
void setResamplingPeriod( RiaDefines::DateTimePeriodEnum resampling );
|
||||
void setPlotAxisProperties( RimPlotAxisPropertiesInterface* plotAxisProperties );
|
||||
void setShowDataSource( bool enable );
|
||||
|
||||
RimSummaryCase* summaryCase() const;
|
||||
RimSummaryCaseCollection* ensemble() const;
|
||||
RifEclipseSummaryAddress summaryAddress() const;
|
||||
RiaDefines::DateTimePeriodEnum resamplingPeriod() const;
|
||||
RimPlotAxisPropertiesInterface* plotAxisProperties() const;
|
||||
|
||||
private:
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimSummaryCase*> m_summaryCase;
|
||||
caf::PdmPtrField<RimSummaryCaseCollection*> m_summaryCaseCollection;
|
||||
caf::PdmChildField<RimSummaryAddress*> m_summaryAddress;
|
||||
caf::PdmField<RifEclipseSummaryAddress> m_summaryAddressUiField;
|
||||
caf::PdmField<bool> m_pushButtonSelectSummaryAddress;
|
||||
caf::PdmPtrField<RimPlotAxisPropertiesInterface*> m_plotAxisProperties;
|
||||
caf::PdmField<RiaDefines::DateTimePeriodEnum> m_resamplingPeriod;
|
||||
|
||||
SummaryDataSource m_dataSource;
|
||||
bool m_showDataSource;
|
||||
};
|
||||
@@ -525,7 +525,7 @@ QList<caf::PdmOptionItemInfo> RimSummaryCurve::calculateValueOptions( const caf:
|
||||
|
||||
options = RiaSummaryTools::optionsForSummaryCases( cases );
|
||||
|
||||
if ( options.size() > 0 )
|
||||
if ( !options.empty() )
|
||||
{
|
||||
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
|
||||
}
|
||||
@@ -643,38 +643,53 @@ void RimSummaryCurve::onLoadDataAndUpdate( bool updateParentPlot )
|
||||
|
||||
if ( m_xAxisType == RiaDefines::HorizontalAxisType::SUMMARY_VECTOR )
|
||||
{
|
||||
auto curveValuesX = valuesX();
|
||||
auto curveTimeStepsX = timeStepsX();
|
||||
|
||||
auto curveTimeStepsY = timeStepsY();
|
||||
|
||||
if ( curveValuesY.empty() || curveValuesX.empty() )
|
||||
if ( m_xValuesSummaryAddress()->address().category() == SummaryCategory::SUMMARY_ENSEMBLE_STATISTICS )
|
||||
{
|
||||
shouldPopulateViewWithEmptyData = true;
|
||||
std::vector<double> curveValuesX;
|
||||
std::vector<double> curveValuesY;
|
||||
|
||||
// Read x and y values from ensemble statistics (not time steps are read)
|
||||
RifSummaryReaderInterface* reader = m_xValuesSummaryCase()->summaryReader();
|
||||
|
||||
reader->values( m_xValuesSummaryAddress->address(), &curveValuesX );
|
||||
reader->values( m_yValuesSummaryAddress->address(), &curveValuesY );
|
||||
|
||||
setSamplesFromXYValues( curveValuesX, curveValuesY, useLogarithmicScale );
|
||||
}
|
||||
else
|
||||
{
|
||||
RiaTimeHistoryCurveMerger curveMerger;
|
||||
curveMerger.addCurveData( curveTimeStepsX, curveValuesX );
|
||||
curveMerger.addCurveData( curveTimeStepsY, curveValuesY );
|
||||
curveMerger.computeInterpolatedValues();
|
||||
auto curveValuesX = valuesX();
|
||||
auto curveTimeStepsX = timeStepsX();
|
||||
auto curveTimeStepsY = timeStepsY();
|
||||
|
||||
if ( curveMerger.allXValues().size() > 0 )
|
||||
if ( curveValuesY.empty() || curveValuesX.empty() )
|
||||
{
|
||||
setSamplesFromXYValues( curveMerger.interpolatedYValuesForAllXValues( 0 ),
|
||||
curveMerger.interpolatedYValuesForAllXValues( 1 ),
|
||||
useLogarithmicScale );
|
||||
shouldPopulateViewWithEmptyData = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldPopulateViewWithEmptyData = true;
|
||||
RiaTimeHistoryCurveMerger curveMerger;
|
||||
curveMerger.addCurveData( curveTimeStepsX, curveValuesX );
|
||||
curveMerger.addCurveData( curveTimeStepsY, curveValuesY );
|
||||
curveMerger.computeInterpolatedValues();
|
||||
|
||||
if ( !curveMerger.allXValues().empty() )
|
||||
{
|
||||
setSamplesFromXYValues( curveMerger.interpolatedYValuesForAllXValues( 0 ),
|
||||
curveMerger.interpolatedYValuesForAllXValues( 1 ),
|
||||
useLogarithmicScale );
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldPopulateViewWithEmptyData = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<time_t> curveTimeStepsY = timeStepsY();
|
||||
if ( plot->timeAxisProperties() && curveTimeStepsY.size() > 0 && curveTimeStepsY.size() == curveValuesY.size() )
|
||||
if ( plot->timeAxisProperties() && !curveTimeStepsY.empty() && curveTimeStepsY.size() == curveValuesY.size() )
|
||||
{
|
||||
if ( plot->timeAxisProperties()->timeMode() == RimSummaryTimeAxisProperties::DATE )
|
||||
{
|
||||
@@ -732,7 +747,7 @@ void RimSummaryCurve::onLoadDataAndUpdate( bool updateParentPlot )
|
||||
double timeScale = plot->timeAxisProperties()->fromTimeTToDisplayUnitScale();
|
||||
|
||||
std::vector<double> timeFromSimulationStart;
|
||||
if ( curveTimeStepsY.size() )
|
||||
if ( !curveTimeStepsY.empty() )
|
||||
{
|
||||
time_t startDate = curveTimeStepsY[0];
|
||||
for ( const auto& date : curveTimeStepsY )
|
||||
@@ -1193,7 +1208,7 @@ void RimSummaryCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
if ( dlg.exec() == QDialog::Accepted )
|
||||
{
|
||||
auto curveSelection = dlg.curveSelection();
|
||||
if ( curveSelection.size() > 0 )
|
||||
if ( !curveSelection.empty() )
|
||||
{
|
||||
m_yValuesSummaryCase = curveSelection[0].summaryCaseY();
|
||||
m_yValuesSummaryAddress->setAddress( curveSelection[0].summaryAddressY() );
|
||||
@@ -1227,7 +1242,7 @@ void RimSummaryCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
if ( dlg.exec() == QDialog::Accepted )
|
||||
{
|
||||
auto curveSelection = dlg.curveSelection();
|
||||
if ( curveSelection.size() > 0 )
|
||||
if ( !curveSelection.empty() )
|
||||
{
|
||||
m_xValuesSummaryCase = curveSelection[0].summaryCaseY();
|
||||
m_xValuesSummaryAddress->setAddress( curveSelection[0].summaryAddressY() );
|
||||
@@ -1255,7 +1270,7 @@ void RimSummaryCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
curveMerger.addCurveData( curveTimeStepsY, curveValuesY );
|
||||
curveMerger.computeInterpolatedValues();
|
||||
|
||||
if ( curveMerger.validIntervalsForAllXValues().size() == 0 )
|
||||
if ( curveMerger.validIntervalsForAllXValues().empty() )
|
||||
{
|
||||
QString description;
|
||||
|
||||
|
||||
@@ -270,8 +270,17 @@ QString RimSummaryPlotAxisFormatter::autoAxisTitle() const
|
||||
|
||||
for ( const RiaSummaryCurveDefinition& curveDef : m_curveDefinitions )
|
||||
{
|
||||
std::string unitText;
|
||||
RifEclipseSummaryAddress sumAddress = curveDef.summaryAddressY();
|
||||
RifEclipseSummaryAddress sumAddress;
|
||||
if ( m_axisProperties->plotAxis().isHorizontal() )
|
||||
{
|
||||
sumAddress = curveDef.summaryAddressX();
|
||||
}
|
||||
else
|
||||
{
|
||||
sumAddress = curveDef.summaryAddressY();
|
||||
}
|
||||
|
||||
std::string unitText;
|
||||
if ( curveDef.ensemble() )
|
||||
{
|
||||
std::vector<RimSummaryCase*> sumCases = curveDef.ensemble()->allSummaryCases();
|
||||
@@ -285,8 +294,7 @@ QString RimSummaryPlotAxisFormatter::autoAxisTitle() const
|
||||
RimSummaryCase* sumCase = curveDef.summaryCaseY();
|
||||
if ( m_axisProperties->plotAxis().isHorizontal() )
|
||||
{
|
||||
sumCase = curveDef.summaryCaseX();
|
||||
sumAddress = curveDef.summaryAddressX();
|
||||
sumCase = curveDef.summaryCaseX();
|
||||
}
|
||||
|
||||
if ( sumCase && sumCase->summaryReader() )
|
||||
|
||||
@@ -329,6 +329,7 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi( const caf::PdmFieldHandle*
|
||||
if ( dataSourceSteppingObject() ) curves = dataSourceSteppingObject()->allCurves( m_sourceSteppingType );
|
||||
|
||||
bool isAutoZoomAllowed = false;
|
||||
bool doZoomAll = false;
|
||||
|
||||
if ( changedField == &m_stepDimension )
|
||||
{
|
||||
@@ -361,6 +362,25 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi( const caf::PdmFieldHandle*
|
||||
|
||||
bool triggerLoadDataAndUpdate = false;
|
||||
|
||||
auto updateEnsembleAddresses = [&doZoomAll, &oldValue, &newValue]( const std::vector<RimEnsembleCurveSet*>& curveSets )
|
||||
{
|
||||
for ( auto curveSet : curveSets )
|
||||
{
|
||||
auto curveAdr = curveSet->curveAddress();
|
||||
|
||||
auto yAddressToModify = curveAdr.summaryAddressY();
|
||||
RimDataSourceSteppingTools::updateQuantityIfMatching( oldValue, newValue, yAddressToModify );
|
||||
|
||||
auto xAddressToModify = curveAdr.summaryAddressX();
|
||||
RimDataSourceSteppingTools::updateQuantityIfMatching( oldValue, newValue, xAddressToModify );
|
||||
|
||||
curveSet->setCurveAddress( RiaSummaryCurveAddress( xAddressToModify, yAddressToModify ) );
|
||||
curveSet->updateConnectedEditors();
|
||||
|
||||
doZoomAll = true;
|
||||
}
|
||||
};
|
||||
|
||||
if ( changedField == &m_summaryCase )
|
||||
{
|
||||
if ( m_summaryCase() )
|
||||
@@ -431,11 +451,7 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi( const caf::PdmFieldHandle*
|
||||
|
||||
if ( dataSourceSteppingObject() )
|
||||
{
|
||||
for ( auto curveSet : dataSourceSteppingObject()->curveSets() )
|
||||
{
|
||||
auto adr = curveSet->summaryAddress();
|
||||
if ( RimDataSourceSteppingTools::updateQuantityIfMatching( oldValue, newValue, &adr ) ) curveSet->setSummaryAddress( adr );
|
||||
}
|
||||
updateEnsembleAddresses( dataSourceSteppingObject()->curveSets() );
|
||||
}
|
||||
|
||||
m_vectorName.uiCapability()->updateConnectedEditors();
|
||||
@@ -486,26 +502,21 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi( const caf::PdmFieldHandle*
|
||||
if ( isYAxisStepping() )
|
||||
{
|
||||
RifEclipseSummaryAddress adr = curve->summaryAddressY();
|
||||
RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, summaryCategoryToModify, &adr );
|
||||
RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, summaryCategoryToModify, adr );
|
||||
curve->setSummaryAddressY( adr );
|
||||
}
|
||||
|
||||
if ( isXAxisStepping() )
|
||||
{
|
||||
RifEclipseSummaryAddress adr = curve->summaryAddressX();
|
||||
RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, summaryCategoryToModify, &adr );
|
||||
RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, summaryCategoryToModify, adr );
|
||||
curve->setSummaryAddressX( adr );
|
||||
}
|
||||
}
|
||||
|
||||
if ( dataSourceSteppingObject() )
|
||||
{
|
||||
for ( auto curveSet : dataSourceSteppingObject()->curveSets() )
|
||||
{
|
||||
auto adr = curveSet->summaryAddress();
|
||||
RimDataSourceSteppingTools::updateAddressIfMatching( oldValue, newValue, summaryCategoryToModify, &adr );
|
||||
curveSet->setSummaryAddress( adr );
|
||||
}
|
||||
updateEnsembleAddresses( dataSourceSteppingObject()->curveSets() );
|
||||
}
|
||||
|
||||
triggerLoadDataAndUpdate = true;
|
||||
@@ -522,7 +533,15 @@ void RimSummaryPlotSourceStepping::fieldChangedByUi( const caf::PdmFieldHandle*
|
||||
summaryMultiPlot->updatePlots();
|
||||
summaryMultiPlot->updatePlotTitles();
|
||||
|
||||
if ( isAutoZoomAllowed ) summaryMultiPlot->zoomAllYAxes();
|
||||
if ( doZoomAll )
|
||||
{
|
||||
summaryMultiPlot->zoomAll();
|
||||
}
|
||||
else if ( isAutoZoomAllowed )
|
||||
{
|
||||
// The time axis can be zoomed and will be used for all plots. Do not zoom time axis in this case.
|
||||
summaryMultiPlot->zoomAllYAxes();
|
||||
}
|
||||
|
||||
RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow();
|
||||
mainPlotWindow->updateMultiPlotToolBar();
|
||||
@@ -1261,13 +1280,13 @@ void RimSummaryPlotSourceStepping::updateVectorNameInCurves( std::vector<RimSumm
|
||||
if ( isYAxisStepping() )
|
||||
{
|
||||
auto adr = curve->summaryAddressY();
|
||||
if ( RimDataSourceSteppingTools::updateQuantityIfMatching( oldValue, newValue, &adr ) ) curve->setSummaryAddressY( adr );
|
||||
if ( RimDataSourceSteppingTools::updateQuantityIfMatching( oldValue, newValue, adr ) ) curve->setSummaryAddressY( adr );
|
||||
}
|
||||
|
||||
if ( isXAxisStepping() )
|
||||
{
|
||||
auto adr = curve->summaryAddressX();
|
||||
if ( RimDataSourceSteppingTools::updateQuantityIfMatching( oldValue, newValue, &adr ) ) curve->setSummaryAddressX( adr );
|
||||
if ( RimDataSourceSteppingTools::updateQuantityIfMatching( oldValue, newValue, adr ) ) curve->setSummaryAddressX( adr );
|
||||
}
|
||||
|
||||
if ( m_autoUpdateAppearance )
|
||||
|
||||
Reference in New Issue
Block a user