#7761 Objective Function : Change formula and add several options

This commit is contained in:
Magne Sjaastad 2021-06-09 16:25:19 +02:00
parent c89e00b966
commit 4de91e885b
24 changed files with 883 additions and 537 deletions

View File

@ -20,8 +20,7 @@
#include "RimCustomObjectiveFunction.h"
#include "RimCustomObjectiveFunctionCollection.h"
#include "RimCustomObjectiveFunctionWeight.h"
#include "RimEnsembleCurveSet.h"
#include "RimObjectiveFunctionTools.h"
#include "RiuPlotMainWindowTools.h"
@ -53,8 +52,7 @@ void RicNewCustomObjectiveFunctionFeature::onActionTriggered( bool isChecked )
if ( coll.size() == 1 )
{
RimCustomObjectiveFunction* newFunc = coll[0]->addObjectiveFunction();
RimCustomObjectiveFunctionWeight* newWeight = newFunc->addWeight();
newWeight->setSummaryAddress( newWeight->parentCurveSet()->summaryAddress() );
RimCustomObjectiveFunctionWeight* newWeight = RimObjectiveFunctionTools::addWeight( newFunc );
coll[0]->updateConnectedEditors();
RiuPlotMainWindowTools::selectAsCurrentItem( newFunc );
RiuPlotMainWindowTools::setExpanded( coll.front() );

View File

@ -20,7 +20,7 @@
#include "RimCustomObjectiveFunction.h"
#include "RimCustomObjectiveFunctionWeight.h"
#include "RimEnsembleCurveSet.h"
#include "RimObjectiveFunctionTools.h"
#include "RiuPlotMainWindowTools.h"
@ -51,16 +51,11 @@ void RicNewCustomObjectiveFunctionWeightFeature::onActionTriggered( bool isCheck
if ( func.size() == 1 )
{
RimCustomObjectiveFunctionWeight* newWeight = func[0]->addWeight();
if ( func[0]->weights().size() > 1 )
{
newWeight->setSummaryAddress( func[0]->weights()[0]->summaryAddresses().front() );
}
else
{
newWeight->setSummaryAddress( newWeight->parentCurveSet()->summaryAddress() );
}
func[0]->updateConnectedEditors();
auto firstObjectiveFunction = func.front();
auto newWeight = RimObjectiveFunctionTools::addWeight( firstObjectiveFunction );
firstObjectiveFunction->updateConnectedEditors();
RiuPlotMainWindowTools::selectAsCurrentItem( newWeight );
RiuPlotMainWindowTools::setExpanded( func.front() );
}

View File

@ -28,8 +28,7 @@ class RicNewCustomObjectiveFunctionWeightFeature : public caf::CmdFeature
CAF_CMD_HEADER_INIT;
protected:
// Overrides
bool isCommandEnabled() override;
void onActionTriggered(bool isChecked) override;
void setupActionLook(QAction* actionToSetup) override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
};

View File

@ -21,6 +21,7 @@
#include "RimEnsembleCurveFilter.h"
#include "RimEnsembleCurveFilterCollection.h"
#include "RimEnsembleCurveSet.h"
#include "RimObjectiveFunctionTools.h"
#include "RiuPlotMainWindowTools.h"
@ -67,7 +68,11 @@ void RicNewEnsembleCurveFilterFeature::onActionTriggered( bool isChecked )
else
{
std::vector<RifEclipseSummaryAddress> addresses;
addresses.push_back( newFilter->parentCurveSet()->summaryAddress() );
auto candidateAdr = newFilter->parentCurveSet()->summaryAddress();
auto nativeQuantityName = RimObjectiveFunctionTools::nativeQuantityName( candidateAdr.quantityName() );
candidateAdr.setQuantityName( nativeQuantityName );
addresses.push_back( candidateAdr );
newFilter->setSummaryAddresses( addresses );
}
newFilter->loadDataAndUpdate();

View File

@ -45,6 +45,21 @@ RimCustomObjectiveFunction::RimCustomObjectiveFunction()
CAF_PDM_InitFieldNoDefault( &m_weights, "Weights", "", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_objectiveFunctions, "ObjectiveFunctions", "Objective Functions", "", "", "" );
{
auto objFunc1 = new RimObjectiveFunction();
objFunc1->setFunctionType( RimObjectiveFunction::FunctionType::F1 );
m_objectiveFunctions.push_back( objFunc1 );
objFunc1->changed.connect( this, &RimCustomObjectiveFunction::onObjectiveFunctionChanged );
}
{
auto objFunc1 = new RimObjectiveFunction();
objFunc1->setFunctionType( RimObjectiveFunction::FunctionType::F2 );
m_objectiveFunctions.push_back( objFunc1 );
objFunc1->changed.connect( this, &RimCustomObjectiveFunction::onObjectiveFunctionChanged );
}
m_isValid = true;
setDeletable( true );
@ -71,32 +86,21 @@ std::vector<RimCustomObjectiveFunctionWeight*> RimCustomObjectiveFunction::weigh
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimCustomObjectiveFunction::values() const
std::vector<double> RimCustomObjectiveFunction::functionValueForAllCases() const
{
std::vector<double> values;
if ( m_weights.empty() ) return {};
RimSummaryCaseCollection* caseCollection = parentCurveSet()->summaryCaseCollection();
for ( auto weight : m_weights )
if ( !caseCollection || caseCollection->allSummaryCases().empty() ) return {};
std::vector<double> values;
for ( auto sumCase : caseCollection->allSummaryCases() )
{
std::vector<double> functionValues =
caseCollection->objectiveFunction( weight->objectiveFunction() )->values( weight->summaryAddresses() );
if ( values.size() == 0 )
{
for ( size_t i = 0; i < functionValues.size(); i++ )
{
values.push_back( weight->weightValue() * functionValues[i] );
}
}
else
{
for ( size_t i = 0; i < functionValues.size(); i++ )
{
if ( values.size() > i + 1 )
{
values[i] += weight->weightValue() * functionValues[i];
}
}
}
auto functionValue = value( sumCase );
values.push_back( functionValue );
}
return values;
}
@ -105,15 +109,23 @@ std::vector<double> RimCustomObjectiveFunction::values() const
//--------------------------------------------------------------------------------------------------
double RimCustomObjectiveFunction::value( RimSummaryCase* summaryCase ) const
{
double value = 0.0;
RimSummaryCaseCollection* caseCollection = parentCurveSet()->summaryCaseCollection();
if ( m_functionValueForAllCases.count( summaryCase ) > 0 )
{
return m_functionValueForAllCases[summaryCase];
}
double value = 0.0;
for ( auto weight : m_weights )
{
double functionValue =
caseCollection->objectiveFunction( weight->objectiveFunction() )->value( summaryCase, weight->summaryAddresses() );
objectiveFunction( weight->objectiveFunction() )
->value( summaryCase, weight->summaryAddresses(), parentCurveSet()->objectiveFunctionTimeConfig() );
value += weight->weightValue() * functionValue;
}
m_functionValueForAllCases[summaryCase] = value;
return value;
}
@ -125,7 +137,7 @@ std::pair<double, double> RimCustomObjectiveFunction::minMaxValues() const
double minValue = std::numeric_limits<double>::infinity();
double maxValue = -std::numeric_limits<double>::infinity();
for ( auto value : values() )
for ( auto value : functionValueForAllCases() )
{
if ( value != std::numeric_limits<double>::infinity() )
{
@ -196,6 +208,7 @@ bool RimCustomObjectiveFunction::isValid() const
//--------------------------------------------------------------------------------------------------
void RimCustomObjectiveFunction::onWeightChanged()
{
m_functionValueForAllCases.clear();
parentCollection()->onObjectiveFunctionChanged( this );
}
@ -220,17 +233,23 @@ QString RimCustomObjectiveFunction::formulaString( std::vector<RifEclipseSummary
QStringList weightFormulae;
for ( auto weight : weights() )
{
weightFormulae << QString( "%0 * %1" )
.arg( weight->weightValue() )
.arg( parentCurveSet()
->summaryCaseCollection()
->objectiveFunction( weight->objectiveFunction() )
->formulaString( vectorSummaryAddresses ) );
weightFormulae
<< QString( "%0 * %1" )
.arg( weight->weightValue() )
.arg( objectiveFunction( weight->objectiveFunction() )->formulaString( vectorSummaryAddresses ) );
}
formula += weightFormulae.join( " + " );
return formula;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCustomObjectiveFunction::clearCache()
{
m_functionValueForAllCases.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -239,6 +258,14 @@ caf::PdmFieldHandle* RimCustomObjectiveFunction::userDescriptionField()
return &m_functionTitle;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCustomObjectiveFunction::onObjectiveFunctionChanged( const caf::SignalEmitter* emitter )
{
onWeightChanged();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -269,6 +296,35 @@ void RimCustomObjectiveFunction::defineEditorAttribute( const caf::PdmFieldHandl
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCustomObjectiveFunction::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &m_customFunctionTitle );
{
auto objFunc1 = objectiveFunction( RimObjectiveFunction::FunctionType::F1 );
if ( objFunc1 )
{
auto equationGroup = uiOrdering.addNewGroup( "Equation for Time Range" );
objFunc1->hideFunctionSelection();
objFunc1->uiOrdering( "", *equationGroup );
}
}
{
auto objFunc2 = objectiveFunction( RimObjectiveFunction::FunctionType::F2 );
{
auto equationGroup = uiOrdering.addNewGroup( "Equation for Selected Time Range" );
objFunc2->hideFunctionSelection();
objFunc2->uiOrdering( "", *equationGroup );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -288,3 +344,18 @@ RimCustomObjectiveFunctionCollection* RimCustomObjectiveFunction::parentCollecti
firstAncestorOrThisOfType( collection );
return collection;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimObjectiveFunction* RimCustomObjectiveFunction::objectiveFunction( RimObjectiveFunction::FunctionType functionType ) const
{
for ( auto objectiveFunc : m_objectiveFunctions.childObjects() )
{
if ( objectiveFunc->functionType() == functionType )
{
return objectiveFunc;
}
}
return nullptr;
}

View File

@ -22,6 +22,7 @@
#include "RimObjectiveFunction.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmProxyValueField.h"
@ -44,7 +45,7 @@ public:
RimCustomObjectiveFunctionWeight* addWeight();
std::vector<RimCustomObjectiveFunctionWeight*> weights() const;
std::vector<double> values() const;
std::vector<double> functionValueForAllCases() const;
double value( RimSummaryCase* summaryCase ) const;
std::pair<double, double> minMaxValues() const;
bool weightContainsFunctionType( RimObjectiveFunction::FunctionType functionType ) const;
@ -55,20 +56,31 @@ public:
void invalidate();
QString formulaString( std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses ) const;
void clearCache();
private:
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /* = "" */ ) override;
void defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute ) override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
RimEnsembleCurveSet* parentCurveSet() const;
RimCustomObjectiveFunctionCollection* parentCollection() const;
RimObjectiveFunction* objectiveFunction( RimObjectiveFunction::FunctionType functionType ) const;
caf::PdmFieldHandle* userDescriptionField() override;
void onObjectiveFunctionChanged( const caf::SignalEmitter* emitter );
private:
caf::PdmProxyValueField<QString> m_functionTitle;
caf::PdmField<QString> m_customFunctionTitle;
caf::PdmChildArrayField<RimCustomObjectiveFunctionWeight*> m_weights;
bool m_isValid;
caf::PdmChildArrayField<RimObjectiveFunction*> m_objectiveFunctions;
mutable std::map<RimSummaryCase*, double> m_functionValueForAllCases;
bool m_isValid;
};

View File

@ -23,6 +23,7 @@
#include "RimCustomObjectiveFunction.h"
#include "RimEnsembleCurveSet.h"
#include "RimObjectiveFunctionTools.h"
#include "RimSummaryAddress.h"
#include "RiuSummaryVectorSelectionDialog.h"
@ -83,7 +84,7 @@ QString RimCustomObjectiveFunctionWeight::title() const
}
return QString( "%0 * %1::%2%3%4" )
.arg( m_weightValue, 0, 'f', 2 )
.arg( caf::AppEnum<RimObjectiveFunction::FunctionType>( m_objectiveFunction() ).uiText() )
.arg( caf::AppEnum<RimObjectiveFunction::FunctionType>( m_objectiveFunction() ).text() )
.arg( addressVector.size() > 1 ? "(" : "" )
.arg( QString::fromStdString( RifEclipseSummaryAddress::generateStringFromAddresses( addressVector, " + " ) ) )
.arg( addressVector.size() > 1 ? ")" : "" );
@ -156,7 +157,7 @@ void RimCustomObjectiveFunctionWeight::fieldChangedByUi( const caf::PdmFieldHand
else if ( changedField == &m_objectiveValuesSelectSummaryAddressPushButton )
{
RiuSummaryVectorSelectionDialog dlg( nullptr );
dlg.enableMultiSelect( true );
RimObjectiveFunctionTools::configureDialogForObjectiveFunctions( &dlg );
RimSummaryCaseCollection* candidateEnsemble = parentCurveSet()->summaryCaseCollection();
std::vector<RifEclipseSummaryAddress> candidateAddresses;
@ -165,7 +166,6 @@ void RimCustomObjectiveFunctionWeight::fieldChangedByUi( const caf::PdmFieldHand
candidateAddresses.push_back( address->address() );
}
dlg.hideSummaryCases();
dlg.setEnsembleAndAddresses( candidateEnsemble, candidateAddresses );
if ( dlg.exec() == QDialog::Accepted )

View File

@ -38,6 +38,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimDerivedSummaryCase.h
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCaseCollection.h
${CMAKE_CURRENT_LIST_DIR}/RimSummaryPlotFilterTextCurveSetEditor.h
${CMAKE_CURRENT_LIST_DIR}/RimObjectiveFunction.h
${CMAKE_CURRENT_LIST_DIR}/RimObjectiveFunctionTools.h
)
set (SOURCE_GROUP_SOURCE_FILES
@ -79,6 +80,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimDerivedSummaryCase.cpp
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCaseCollection.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSummaryPlotFilterTextCurveSetEditor.cpp
${CMAKE_CURRENT_LIST_DIR}/RimObjectiveFunction.cpp
${CMAKE_CURRENT_LIST_DIR}/RimObjectiveFunctionTools.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@ -25,6 +25,7 @@
#include "RimCustomObjectiveFunctionCollection.h"
#include "RimEnsembleCurveFilterCollection.h"
#include "RimEnsembleCurveSet.h"
#include "RimObjectiveFunctionTools.h"
#include "RimSummaryAddress.h"
#include "RimSummaryCase.h"
@ -98,7 +99,11 @@ RimEnsembleCurveFilter::RimEnsembleCurveFilter()
m_objectiveValuesSelectSummaryAddressPushButton = false;
CAF_PDM_InitFieldNoDefault( &m_objectiveFunction, "ObjectiveFunction", "Objective Function", "", "", "" );
m_objectiveFunction.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
m_objectiveFunction = new RimObjectiveFunction();
m_objectiveFunction.uiCapability()->setUiHidden( true );
m_objectiveFunction.uiCapability()->setUiTreeHidden( true );
m_objectiveFunction.uiCapability()->setUiTreeChildrenHidden( true );
m_objectiveFunction->changed.connect( this, &RimEnsembleCurveFilter::onObjectionFunctionChanged );
CAF_PDM_InitFieldNoDefault( &m_customObjectiveFunction, "CustomObjectiveFunction", "Custom Objective Function", "", "", "" );
m_customObjectiveFunction.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
@ -202,7 +207,7 @@ QString RimEnsembleCurveFilter::description() const
}
descriptor =
QString( "%1::%2%3%4" )
.arg( caf::AppEnum<RimObjectiveFunction::FunctionType>( m_objectiveFunction() ).uiText() )
.arg( m_objectiveFunction()->shortName() )
.arg( addressVector.size() > 1 ? "(" : "" )
.arg( QString::fromStdString( RifEclipseSummaryAddress::generateStringFromAddresses( addressVector, "+" ) ) )
.arg( addressVector.size() > 1 ? ")" : "" );
@ -359,7 +364,12 @@ void RimEnsembleCurveFilter::fieldChangedByUi( const caf::PdmFieldHandle* change
if ( m_objectiveValuesSummaryAddresses.size() == 0 )
{
RimSummaryAddress* summaryAddress = new RimSummaryAddress();
summaryAddress->setAddress( parentCurveSet()->summaryAddress() );
RifEclipseSummaryAddress candidateAdr = parentCurveSet()->summaryAddress();
auto nativeQuantityName = RimObjectiveFunctionTools::nativeQuantityName( candidateAdr.quantityName() );
candidateAdr.setQuantityName( nativeQuantityName );
summaryAddress->setAddress( candidateAdr );
m_objectiveValuesSummaryAddresses.push_back( summaryAddress );
updateAddressesUiField();
}
@ -377,7 +387,7 @@ void RimEnsembleCurveFilter::fieldChangedByUi( const caf::PdmFieldHandle* change
else if ( changedField == &m_objectiveValuesSelectSummaryAddressPushButton )
{
RiuSummaryVectorSelectionDialog dlg( nullptr );
dlg.enableMultiSelect( true );
RimObjectiveFunctionTools::configureDialogForObjectiveFunctions( &dlg );
RimSummaryCaseCollection* candidateEnsemble = parentCurveSet()->summaryCaseCollection();
std::vector<RifEclipseSummaryAddress> candidateAddresses;
@ -386,7 +396,6 @@ void RimEnsembleCurveFilter::fieldChangedByUi( const caf::PdmFieldHandle* change
candidateAddresses.push_back( address->address() );
}
dlg.hideSummaryCases();
dlg.setEnsembleAndAddresses( candidateEnsemble, candidateAddresses );
if ( dlg.exec() == QDialog::Accepted )
@ -394,10 +403,11 @@ void RimEnsembleCurveFilter::fieldChangedByUi( const caf::PdmFieldHandle* change
auto curveSelection = dlg.curveSelection();
if ( !curveSelection.empty() )
{
m_objectiveValuesSummaryAddresses.clear();
for ( auto address : curveSelection )
{
RimSummaryAddress* summaryAddress = new RimSummaryAddress();
summaryAddress->setAddress( parentCurveSet()->summaryAddress() );
summaryAddress->setAddress( address.summaryAddress() );
m_objectiveValuesSummaryAddresses.push_back( summaryAddress );
}
this->loadDataAndUpdate();
@ -455,6 +465,11 @@ void RimEnsembleCurveFilter::defineUiOrdering( QString uiConfigName, caf::PdmUiO
{
uiOrdering.add( &m_objectiveValuesSummaryAddressesUiField );
uiOrdering.add( &m_objectiveValuesSelectSummaryAddressPushButton, { false, 1, 0 } );
{
auto equationGroup = uiOrdering.addNewGroup( "Equation" );
m_objectiveFunction->uiOrdering( "", *equationGroup );
}
uiOrdering.add( &m_objectiveFunction );
}
else if ( m_filterMode() == FilterMode::BY_CUSTOM_OBJECTIVE_FUNCTION )
@ -543,8 +558,7 @@ std::vector<RimSummaryCase*> RimEnsembleCurveFilter::applyFilter( const std::vec
}
else if ( m_filterMode() == FilterMode::BY_OBJECTIVE_FUNCTION )
{
auto objectiveFunction = ensemble->objectiveFunction( m_objectiveFunction() );
bool hasWarning = false;
bool hasWarning = false;
std::vector<RifEclipseSummaryAddress> addresses;
for ( auto address : m_objectiveValuesSummaryAddresses() )
@ -552,7 +566,8 @@ std::vector<RimSummaryCase*> RimEnsembleCurveFilter::applyFilter( const std::vec
addresses.push_back( address->address() );
}
double value = objectiveFunction->value( sumCase, addresses, &hasWarning );
double value =
m_objectiveFunction->value( sumCase, addresses, curveSet->objectiveFunctionTimeConfig(), &hasWarning );
if ( hasWarning ) continue;
if ( value < m_minValue() || value > m_maxValue )
@ -610,6 +625,25 @@ RimEnsembleCurveSet* RimEnsembleCurveFilter::parentCurveSet() const
return curveSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleCurveFilter::onObjectionFunctionChanged( const caf::SignalEmitter* emitter )
{
updateMaxMinAndDefaultValues( true );
parentCurveSet()->updateAllCurves();
parentCurveSet()->updateFilterLegend();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleCurveFilter::updateMaxMinAndDefaultValuesFromParent()
{
updateMaxMinAndDefaultValues( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -653,18 +687,20 @@ void RimEnsembleCurveFilter::updateMaxMinAndDefaultValues( bool forceDefault )
}
else if ( m_filterMode() == FilterMode::BY_OBJECTIVE_FUNCTION )
{
auto objectiveFunction = parentCurveSet()->summaryCaseCollection()->objectiveFunction( m_objectiveFunction() );
auto objectiveFunction = m_objectiveFunction();
std::vector<RifEclipseSummaryAddress> addresses;
for ( auto address : m_objectiveValuesSummaryAddresses() )
{
addresses.push_back( address->address() );
}
if ( objectiveFunction->isValid( addresses ) )
{
std::pair<double, double> minMaxValues = objectiveFunction->minMaxValues( addresses );
auto summaryCases = parentCurveSet()->summaryCaseCollection()->allSummaryCases();
m_lowerLimit = minMaxValues.first;
m_upperLimit = minMaxValues.second;
auto [minObjValue, maxObjValue] =
objectiveFunction->minMaxValues( summaryCases, addresses, parentCurveSet()->objectiveFunctionTimeConfig() );
m_lowerLimit = minObjValue;
m_upperLimit = maxObjValue;
if ( forceDefault || !( m_minValue >= m_lowerLimit && m_minValue <= m_upperLimit ) )
m_minValue = m_lowerLimit;

View File

@ -24,6 +24,7 @@
#include "RimObjectiveFunction.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmProxyValueField.h"
@ -84,6 +85,9 @@ public:
RimEnsembleCurveSet* parentCurveSet() const;
void onObjectionFunctionChanged( const caf::SignalEmitter* emitter );
void updateMaxMinAndDefaultValuesFromParent();
protected:
caf::PdmFieldHandle* objectToggleField() override;
@ -92,18 +96,20 @@ private:
void updateMaxMinAndDefaultValues( bool forceDefault );
private:
caf::PdmProxyValueField<QString> m_filterTitle;
caf::PdmField<bool> m_active;
caf::PdmField<caf::AppEnum<FilterMode>> m_filterMode;
caf::PdmField<QString> m_ensembleParameterName;
caf::PdmChildArrayField<RimSummaryAddress*> m_objectiveValuesSummaryAddresses;
caf::PdmField<QString> m_objectiveValuesSummaryAddressesUiField;
caf::PdmField<bool> m_objectiveValuesSelectSummaryAddressPushButton;
caf::PdmField<caf::AppEnum<RimObjectiveFunction::FunctionType>> m_objectiveFunction;
caf::PdmPtrField<RimCustomObjectiveFunction*> m_customObjectiveFunction;
caf::PdmField<double> m_minValue;
caf::PdmField<double> m_maxValue;
caf::PdmField<std::vector<QString>> m_categories;
caf::PdmProxyValueField<QString> m_filterTitle;
caf::PdmField<bool> m_active;
caf::PdmField<caf::AppEnum<FilterMode>> m_filterMode;
caf::PdmField<QString> m_ensembleParameterName;
caf::PdmChildArrayField<RimSummaryAddress*> m_objectiveValuesSummaryAddresses;
caf::PdmField<QString> m_objectiveValuesSummaryAddressesUiField;
caf::PdmField<bool> m_objectiveValuesSelectSummaryAddressPushButton;
caf::PdmChildField<RimObjectiveFunction*> m_objectiveFunction;
caf::PdmPtrField<RimCustomObjectiveFunction*> m_customObjectiveFunction;
caf::PdmField<double> m_minValue;
caf::PdmField<double> m_maxValue;
caf::PdmField<std::vector<QString>> m_categories;
double m_lowerLimit;
double m_upperLimit;

View File

@ -43,6 +43,7 @@
#include "RimEnsembleStatistics.h"
#include "RimEnsembleStatisticsCase.h"
#include "RimObjectiveFunction.h"
#include "RimObjectiveFunctionTools.h"
#include "RimProject.h"
#include "RimRegularLegendConfig.h"
#include "RimSummaryAddress.h"
@ -155,13 +156,10 @@ RimEnsembleCurveSet::RimEnsembleCurveSet()
m_objectiveValuesSelectSummaryAddressPushButton.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
m_objectiveValuesSelectSummaryAddressPushButton = false;
CAF_PDM_InitFieldNoDefault( &m_objectiveFunction, "ObjectiveFunction", "Objective Function", "", "", "" );
m_objectiveFunction.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_customObjectiveFunction, "CustomObjectiveFunction", "Objective Function", "", "", "" );
m_customObjectiveFunction.uiCapability()->setUiEditorTypeName( caf::PdmUiListEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_showObjectiveFunctionFormula, "ShowObjectiveFunctionFormula", true, "Show Formula in Plot", "", "", "" );
CAF_PDM_InitField( &m_showObjectiveFunctionFormula, "ShowObjectiveFunctionFormula", true, "Show Text Box in Plot", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_minDateRange, "MinDateRange", "From", "", "", "" );
m_minDateRange.uiCapability()->setUiEditorTypeName( caf::PdmUiDateEditor::uiEditorTypeName() );
@ -200,7 +198,13 @@ RimEnsembleCurveSet::RimEnsembleCurveSet()
"",
"" );
m_customObjectiveFunctions = new RimCustomObjectiveFunctionCollection();
m_customObjectiveFunctions->objectiveFunctionChanged.connect( this, &RimEnsembleCurveSet::onObjectiveFunctionChanged );
m_customObjectiveFunctions->objectiveFunctionChanged.connect( this,
&RimEnsembleCurveSet::onCustomObjectiveFunctionChanged );
CAF_PDM_InitFieldNoDefault( &m_objectiveFunction, "ObjectiveFunction", "Objective Function", "", "", "" );
m_objectiveFunction = new RimObjectiveFunction();
m_objectiveFunction.uiCapability()->setUiHidden( true );
m_objectiveFunction->changed.connect( this, &RimEnsembleCurveSet::onObjectiveFunctionChanged );
CAF_PDM_InitFieldNoDefault( &m_statistics, "Statistics", "Statistics", "", "", "" );
m_statistics = new RimEnsembleStatistics();
@ -309,6 +313,7 @@ void RimEnsembleCurveSet::loadDataAndUpdate( bool updateParentPlot )
updateAllCurves();
updateFilterLegend();
updateObjectiveFunctionLegend();
updateTimeAnnotations();
if ( updateParentPlot )
{
@ -602,7 +607,7 @@ void RimEnsembleCurveSet::setTimeSteps( const std::vector<size_t>& timeStepIndic
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<time_t> RimEnsembleCurveSet::selectedTimeSteps()
std::vector<time_t> RimEnsembleCurveSet::selectedTimeSteps() const
{
std::vector<time_t> selectedTimeTTimeSteps;
for ( const QDateTime& dateTime : m_selectedTimeSteps.v() )
@ -648,8 +653,6 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi
}
else if ( changedField == &m_yValuesSummaryCaseCollection )
{
// Empty address cache
// m_allAddressesCache.clear();
updateAllCurves();
updateTextInPlot = true;
@ -669,19 +672,12 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi
updateLegendMappingMode();
updateCurveColors();
}
else if ( changedField == &m_objectiveFunction )
{
updateLegendMappingMode();
updateCurveColors();
updateTimeAnnotations();
updateObjectiveFunctionLegend();
}
else if ( changedField == &m_objectiveValuesSummaryAddressesUiField )
{
updateAddressesUiField();
std::vector<size_t> indices;
indices.push_back( summaryCaseCollection()->objectiveFunction( m_objectiveFunction() )->range().first );
indices.push_back( 0 );
setTimeSteps( indices );
updateMaxMinAndDefaultValues();
@ -697,7 +693,6 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi
else if ( changedField == &m_colorMode )
{
m_ensembleParameter.uiCapability()->setUiHidden( m_colorMode() != ColorMode::BY_ENSEMBLE_PARAM );
m_objectiveFunction.uiCapability()->setUiHidden( m_colorMode() != ColorMode::BY_OBJECTIVE_FUNCTION );
if ( m_colorMode() == ColorMode::BY_ENSEMBLE_PARAM )
{
@ -736,10 +731,10 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi
}
else if ( changedField == &m_selectedTimeSteps )
{
summaryCaseCollection()->objectiveFunction( m_objectiveFunction() )->setTimeStepList( selectedTimeSteps() );
updateCurveColors();
updateTimeAnnotations();
updateObjectiveFunctionLegend();
updateMaxMinAndDefaultValues();
}
else if ( changedField == &m_minTimeStep || changedField == &m_maxTimeStep )
{
@ -812,7 +807,7 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi
else if ( changedField == &m_objectiveValuesSelectSummaryAddressPushButton )
{
RiuSummaryVectorSelectionDialog dlg( nullptr );
dlg.enableMultiSelect( true );
RimObjectiveFunctionTools::configureDialogForObjectiveFunctions( &dlg );
RimSummaryCaseCollection* candidateEnsemble = m_yValuesSummaryCaseCollection();
std::vector<RifEclipseSummaryAddress> candidateAddresses;
@ -821,7 +816,6 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi
candidateAddresses.push_back( address->address() );
}
dlg.hideSummaryCases();
dlg.setEnsembleAndAddresses( candidateEnsemble, candidateAddresses );
if ( dlg.exec() == QDialog::Accepted )
@ -846,11 +840,10 @@ void RimEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedFi
{
if ( m_customObjectiveFunction() )
{
if ( m_customObjectiveFunction()->weightContainsFunctionType( RimObjectiveFunction::FunctionType::M2 ) )
if ( m_customObjectiveFunction()->weightContainsFunctionType( RimObjectiveFunction::FunctionType::F2 ) )
{
std::vector<size_t> indices;
indices.push_back(
summaryCaseCollection()->objectiveFunction( RimObjectiveFunction::FunctionType::M2 )->range().first );
indices.push_back( 0 );
setTimeSteps( indices );
}
@ -915,7 +908,25 @@ void RimEnsembleCurveSet::updateMaxMinAndDefaultValues()
m_minDateRange = QDateTime::fromSecsSinceEpoch( m_minTimeStep ).date();
m_maxDateRange = QDateTime::fromSecsSinceEpoch( m_maxTimeStep ).date();
summaryCaseCollection()->objectiveFunction( m_objectiveFunction() )->setTimeStepRange( m_minTimeStep(), m_maxTimeStep() );
for ( auto filter : m_curveFilters->filters() )
{
filter->updateMaxMinAndDefaultValuesFromParent();
}
for ( auto objFunc : m_customObjectiveFunctions->objectiveFunctions() )
{
objFunc->clearCache();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleCurveSet::onCustomObjectiveFunctionChanged( const caf::SignalEmitter* emitter )
{
updateCurveColors();
updateFilterLegend();
updateObjectiveFunctionLegend();
}
//--------------------------------------------------------------------------------------------------
@ -926,6 +937,7 @@ void RimEnsembleCurveSet::onObjectiveFunctionChanged( const caf::SignalEmitter*
updateCurveColors();
updateFilterLegend();
updateObjectiveFunctionLegend();
updateTimeAnnotations();
}
//--------------------------------------------------------------------------------------------------
@ -950,32 +962,41 @@ void RimEnsembleCurveSet::appendColorGroup( caf::PdmUiOrdering& uiOrdering )
{
if ( m_colorMode == ColorMode::BY_OBJECTIVE_FUNCTION )
{
m_objectiveFunction.uiCapability()->setUiReadOnly( !m_yValuesSummaryCaseCollection() );
colorsGroup->add( &m_objectiveValuesSummaryAddressesUiField );
colorsGroup->add( &m_objectiveValuesSelectSummaryAddressPushButton, { false, 1, 0 } );
colorsGroup->add( &m_objectiveFunction );
{
auto equationGroup = colorsGroup->addNewGroup( "Equation" );
m_objectiveFunction->uiOrdering( "", *equationGroup );
equationGroup->add( &m_showObjectiveFunctionFormula );
}
}
else
{
colorsGroup->add( &m_customObjectiveFunction );
colorsGroup->add( &m_showObjectiveFunctionFormula );
}
colorsGroup->add( &m_showObjectiveFunctionFormula );
if ( ( m_colorMode == ColorMode::BY_OBJECTIVE_FUNCTION &&
m_objectiveFunction() == RimObjectiveFunction::FunctionType::M1 ) ||
( m_colorMode == ColorMode::BY_CUSTOM_OBJECTIVE_FUNCTION && m_customObjectiveFunction() &&
m_customObjectiveFunction()->weightContainsFunctionType( RimObjectiveFunction::FunctionType::M1 ) ) )
{
colorsGroup->add( &m_minDateRange );
colorsGroup->add( &m_minTimeStep );
colorsGroup->add( &m_maxDateRange );
colorsGroup->add( &m_maxTimeStep );
}
if ( m_objectiveFunction() == RimObjectiveFunction::FunctionType::M2 ||
( m_customObjectiveFunction() &&
m_customObjectiveFunction()->weightContainsFunctionType( RimObjectiveFunction::FunctionType::M2 ) ) )
{
colorsGroup->add( &m_timeStepFilter );
colorsGroup->add( &m_selectedTimeSteps );
auto timeSelectionGroup = colorsGroup->addNewGroup( "Time Selection" );
if ( ( m_colorMode == ColorMode::BY_OBJECTIVE_FUNCTION &&
m_objectiveFunction()->functionType() == RimObjectiveFunction::FunctionType::F1 ) ||
( m_colorMode == ColorMode::BY_CUSTOM_OBJECTIVE_FUNCTION && m_customObjectiveFunction() &&
m_customObjectiveFunction()->weightContainsFunctionType( RimObjectiveFunction::FunctionType::F1 ) ) )
{
timeSelectionGroup->add( &m_minDateRange );
timeSelectionGroup->add( &m_minTimeStep );
timeSelectionGroup->add( &m_maxDateRange );
timeSelectionGroup->add( &m_maxTimeStep );
}
if ( m_objectiveFunction()->functionType() == RimObjectiveFunction::FunctionType::F2 ||
( m_customObjectiveFunction() &&
m_customObjectiveFunction()->weightContainsFunctionType( RimObjectiveFunction::FunctionType::F2 ) ) )
{
timeSelectionGroup->add( &m_timeStepFilter );
timeSelectionGroup->add( &m_selectedTimeSteps );
}
}
}
}
@ -1354,13 +1375,10 @@ void RimEnsembleCurveSet::updateObjectiveFunctionLegend()
addresses.push_back( address->address() );
}
title = "Objective Function";
description =
QString( "%0 = %1" )
.arg( m_yValuesSummaryCaseCollection()->objectiveFunction( m_objectiveFunction() )->uiName() )
.arg( m_yValuesSummaryCaseCollection()
->objectiveFunction( m_objectiveFunction() )
->formulaString( addresses ) );
title = "Objective Function";
description = QString( "%0::%1" )
.arg( m_objectiveFunction()->shortName() )
.arg( m_objectiveFunction()->formulaString( addresses ) );
}
else if ( m_colorMode() == ColorMode::BY_CUSTOM_OBJECTIVE_FUNCTION && m_customObjectiveFunction() )
{
@ -1391,6 +1409,14 @@ void RimEnsembleCurveSet::updateObjectiveFunctionLegend()
plot->viewer()->scheduleReplot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
ObjectiveFunctionTimeConfig RimEnsembleCurveSet::objectiveFunctionTimeConfig() const
{
return { m_minTimeStep(), m_maxTimeStep(), selectedTimeSteps() };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -1403,16 +1429,7 @@ void RimEnsembleCurveSet::updateCurveColors()
QString parameterName = m_ensembleParameter();
{
QString legendTitle;
if ( m_isUsingAutoName )
{
legendTitle = m_autoGeneratedName();
}
else
{
legendTitle += m_userDefinedName();
}
QString legendTitle = "Ensemble Parameter";
legendTitle += "\n";
legendTitle += parameterName;
@ -1454,33 +1471,29 @@ void RimEnsembleCurveSet::updateCurveColors()
RimSummaryCaseCollection* group = m_yValuesSummaryCaseCollection();
{
QString legendTitle;
if ( m_isUsingAutoName )
{
legendTitle = m_autoGeneratedName();
}
else
{
legendTitle += m_userDefinedName();
}
QString legendTitle = "Objective Function";
legendTitle += "\n";
legendTitle += caf::AppEnum<RimObjectiveFunction::FunctionType>( m_objectiveFunction() ).uiText();
legendTitle +=
caf::AppEnum<RimObjectiveFunction::FunctionType>( m_objectiveFunction()->functionType() ).uiText();
m_legendConfig->setTitle( legendTitle );
}
if ( group && !group->allSummaryCases().empty() )
{
auto objectiveFunction = group->objectiveFunction( m_objectiveFunction() );
auto objectiveFunction = m_objectiveFunction();
std::vector<RifEclipseSummaryAddress> summaryAddresses;
for ( auto address : m_objectiveValuesSummaryAddresses() )
{
summaryAddresses.push_back( address->address() );
}
if ( objectiveFunction->isValid( summaryAddresses ) )
{
RimEnsembleCurveSetColorManager::initializeLegendConfig( m_legendConfig, objectiveFunction, summaryAddresses );
RimEnsembleCurveSetColorManager::initializeLegendConfig( m_legendConfig,
objectiveFunction,
group->allSummaryCases(),
summaryAddresses,
objectiveFunctionTimeConfig() );
for ( auto& curve : m_curves )
{
if ( curve->summaryAddressY().category() == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS )
@ -1489,15 +1502,12 @@ void RimEnsembleCurveSet::updateCurveColors()
cvf::Color3f curveColor = RimEnsembleCurveSetColorManager::caseColor( m_legendConfig,
rimCase,
objectiveFunction,
summaryAddresses );
summaryAddresses,
objectiveFunctionTimeConfig() );
curve->setColor( curveColor );
curve->updateCurveAppearance();
}
}
else if ( m_legendOverlayFrame )
{
m_legendOverlayFrame->hide();
}
}
}
else if ( m_colorMode == ColorMode::BY_CUSTOM_OBJECTIVE_FUNCTION )
@ -1505,16 +1515,7 @@ void RimEnsembleCurveSet::updateCurveColors()
RimSummaryCaseCollection* group = m_yValuesSummaryCaseCollection();
{
QString legendTitle;
if ( m_isUsingAutoName )
{
legendTitle = m_autoGeneratedName();
}
else
{
legendTitle += m_userDefinedName();
}
QString legendTitle = "Custom\nObjective Function";
legendTitle += "\n";
if ( m_customObjectiveFunction() && m_customObjectiveFunction()->isValid() )
{
@ -1589,17 +1590,17 @@ void RimEnsembleCurveSet::updateTimeAnnotations()
plot->removeAllTimeAnnotations();
if ( ( m_colorMode() == ColorMode::BY_OBJECTIVE_FUNCTION &&
m_objectiveFunction() == RimObjectiveFunction::FunctionType::M1 ) ||
m_objectiveFunction()->functionType() == RimObjectiveFunction::FunctionType::F1 ) ||
( m_colorMode() == ColorMode::BY_CUSTOM_OBJECTIVE_FUNCTION && m_customObjectiveFunction() &&
m_customObjectiveFunction()->weightContainsFunctionType( RimObjectiveFunction::FunctionType::M1 ) ) )
m_customObjectiveFunction()->weightContainsFunctionType( RimObjectiveFunction::FunctionType::F1 ) ) )
{
plot->addTimeRangeAnnotation( m_minTimeStep, m_maxTimeStep );
}
if ( ( m_colorMode() == ColorMode::BY_OBJECTIVE_FUNCTION &&
m_objectiveFunction() == RimObjectiveFunction::FunctionType::M2 ) ||
m_objectiveFunction()->functionType() == RimObjectiveFunction::FunctionType::F2 ) ||
( m_colorMode() == ColorMode::BY_CUSTOM_OBJECTIVE_FUNCTION && m_customObjectiveFunction() &&
m_customObjectiveFunction()->weightContainsFunctionType( RimObjectiveFunction::FunctionType::M2 ) ) )
m_customObjectiveFunction()->weightContainsFunctionType( RimObjectiveFunction::FunctionType::F2 ) ) )
{
for ( QDateTime timeStep : m_selectedTimeSteps() )
{
@ -1801,7 +1802,7 @@ RimEnsembleCurveSet* RimEnsembleCurveSet::clone() const
{
RimEnsembleCurveSet* copy = dynamic_cast<RimEnsembleCurveSet*>(
this->xmlCapability()->copyByXmlSerialization( caf::PdmDefaultObjectFactory::instance() ) );
copy->m_yValuesSummaryCaseCollection = m_yValuesSummaryCaseCollection();
copy->setSummaryCaseCollection( m_yValuesSummaryCaseCollection() );
// Update summary case references
for ( size_t i = 0; i < m_curves.size(); i++ )

View File

@ -59,6 +59,7 @@ class RimObjectiveFunction;
class RiuDraggableOverlayFrame;
class RiaSummaryCurveDefinitionAnalyser;
class RiaSummaryCurveDefinition;
class RiuSummaryVectorSelectionDialog;
class QwtPlot;
class QwtPlotCurve;
@ -125,7 +126,7 @@ public:
void updateAllCurves();
void setTimeSteps( const std::vector<size_t>& timeStepIndices );
std::vector<time_t> selectedTimeSteps();
std::vector<time_t> selectedTimeSteps() const;
void updateStatisticsCurves();
RimEnsembleCurveSet* clone() const;
@ -153,6 +154,8 @@ public:
void updateFilterLegend();
void updateObjectiveFunctionLegend();
ObjectiveFunctionTimeConfig objectiveFunctionTimeConfig() const;
private:
void updateEnsembleCurves( const std::vector<RimSummaryCase*>& sumCases );
void updateStatisticsCurves( const std::vector<RimSummaryCase*>& sumCases );
@ -186,6 +189,7 @@ private:
void updateAddressesUiField();
void onObjectiveFunctionChanged( const caf::SignalEmitter* emitter );
void onCustomObjectiveFunctionChanged( const caf::SignalEmitter* emitter );
private:
caf::PdmField<bool> m_showCurves;
@ -203,25 +207,26 @@ private:
caf::PdmField<cvf::Color3f> m_color;
caf::PdmField<QString> m_ensembleParameter;
caf::PdmChildArrayField<RimSummaryAddress*> m_objectiveValuesSummaryAddresses;
caf::PdmField<QString> m_objectiveValuesSummaryAddressesUiField;
caf::PdmField<bool> m_objectiveValuesSelectSummaryAddressPushButton;
caf::PdmField<caf::AppEnum<RimObjectiveFunction::FunctionType>> m_objectiveFunction;
caf::PdmPtrField<RimCustomObjectiveFunction*> m_customObjectiveFunction;
caf::PdmField<time_t> m_minTimeStep;
caf::PdmField<time_t> m_maxTimeStep;
caf::PdmField<QDate> m_minDateRange;
caf::PdmField<QDate> m_maxDateRange;
caf::PdmField<TimeStepFilterEnum> m_timeStepFilter;
caf::PdmField<std::vector<QDateTime>> m_selectedTimeSteps;
caf::PdmChildArrayField<RimSummaryAddress*> m_objectiveValuesSummaryAddresses;
caf::PdmField<QString> m_objectiveValuesSummaryAddressesUiField;
caf::PdmField<bool> m_objectiveValuesSelectSummaryAddressPushButton;
caf::PdmPtrField<RimCustomObjectiveFunction*> m_customObjectiveFunction;
caf::PdmField<time_t> m_minTimeStep;
caf::PdmField<time_t> m_maxTimeStep;
caf::PdmField<QDate> m_minDateRange;
caf::PdmField<QDate> m_maxDateRange;
caf::PdmField<TimeStepFilterEnum> m_timeStepFilter;
caf::PdmField<std::vector<QDateTime>> m_selectedTimeSteps;
caf::PdmField<caf::AppEnum<RiaDefines::PlotAxis>> m_plotAxis;
caf::PdmChildField<RimRegularLegendConfig*> m_legendConfig;
caf::PdmChildField<RimEnsembleCurveFilterCollection*> m_curveFilters;
caf::PdmChildField<RimEnsembleStatistics*> m_statistics;
caf::PdmChildField<RimRegularLegendConfig*> m_legendConfig;
caf::PdmChildField<RimEnsembleCurveFilterCollection*> m_curveFilters;
caf::PdmChildField<RimEnsembleStatistics*> m_statistics;
caf::PdmChildField<RimCustomObjectiveFunctionCollection*> m_customObjectiveFunctions;
caf::PdmField<bool> m_showObjectiveFunctionFormula;
caf::PdmChildField<RimObjectiveFunction*> m_objectiveFunction;
caf::PdmField<bool> m_isUsingAutoName;
caf::PdmField<QString> m_userDefinedName;

View File

@ -133,21 +133,13 @@ void RimEnsembleCurveSetColorManager::initializeLegendConfig( RimRegularLegendCo
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleCurveSetColorManager::initializeLegendConfig( RimRegularLegendConfig* legendConfig,
std::shared_ptr<RimObjectiveFunction> objectiveFunction,
std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses )
void RimEnsembleCurveSetColorManager::initializeLegendConfig( RimRegularLegendConfig* legendConfig,
RimObjectiveFunction* objectiveFunction,
const std::vector<RimSummaryCase*>& summaryCases,
const std::vector<RifEclipseSummaryAddress>& vectorSummaryAddresses,
const ObjectiveFunctionTimeConfig& timeConfig )
{
double minValue = std::numeric_limits<double>::infinity();
double maxValue = -std::numeric_limits<double>::infinity();
for ( auto value : objectiveFunction->values( vectorSummaryAddresses ) )
{
if ( value != std::numeric_limits<double>::infinity() )
{
if ( value < minValue ) minValue = value;
if ( value > maxValue ) maxValue = value;
}
}
auto [minValue, maxValue] = objectiveFunction->minMaxValues( summaryCases, vectorSummaryAddresses, timeConfig );
legendConfig->setAutomaticRanges( minValue, maxValue, minValue, maxValue );
}
@ -161,7 +153,7 @@ void RimEnsembleCurveSetColorManager::initializeLegendConfig( RimRegularLegendCo
double minValue = std::numeric_limits<double>::infinity();
double maxValue = -std::numeric_limits<double>::infinity();
for ( auto value : customObjectiveFunction->values() )
for ( auto value : customObjectiveFunction->functionValueForAllCases() )
{
if ( value != std::numeric_limits<double>::infinity() )
{
@ -210,10 +202,11 @@ cvf::Color3f RimEnsembleCurveSetColorManager::caseColor( const RimRegularLegendC
//--------------------------------------------------------------------------------------------------
cvf::Color3f RimEnsembleCurveSetColorManager::caseColor( const RimRegularLegendConfig* legendConfig,
RimSummaryCase* summaryCase,
std::shared_ptr<RimObjectiveFunction> objectiveFunction,
std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses )
RimObjectiveFunction* objectiveFunction,
std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses,
const ObjectiveFunctionTimeConfig& timeConfig )
{
double value = objectiveFunction->value( summaryCase, vectorSummaryAddresses );
double value = objectiveFunction->value( summaryCase, vectorSummaryAddresses, timeConfig );
if ( value != std::numeric_limits<double>::infinity() )
{
return cvf::Color3f( legendConfig->scalarMapper()->mapToColor( value ) );

View File

@ -59,9 +59,11 @@ public:
}
static void initializeLegendConfig( RimRegularLegendConfig* legendConfig, const EnsembleParameter& parameter );
static void initializeLegendConfig( RimRegularLegendConfig* legendConfig,
std::shared_ptr<RimObjectiveFunction> objectiveFunction,
std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses );
static void initializeLegendConfig( RimRegularLegendConfig* legendConfig,
RimObjectiveFunction* objectiveFunction,
const std::vector<RimSummaryCase*>& summaryCases,
const std::vector<RifEclipseSummaryAddress>& vectorSummaryAddresses,
const ObjectiveFunctionTimeConfig& timeConfig );
static void initializeLegendConfig( RimRegularLegendConfig* legendConfig,
caf::PdmPointer<RimCustomObjectiveFunction> customObjectiveFunction );
@ -72,8 +74,9 @@ public:
static cvf::Color3f caseColor( const RimRegularLegendConfig* legendConfig,
RimSummaryCase* summaryCase,
std::shared_ptr<RimObjectiveFunction> objectiveFunction,
std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses );
RimObjectiveFunction* objectiveFunction,
std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses,
const ObjectiveFunctionTimeConfig& timeConfig );
static cvf::Color3f caseColor( const RimRegularLegendConfig* legendConfig,
RimSummaryCase* summaryCase,

View File

@ -37,244 +37,145 @@ namespace caf
template <>
void caf::AppEnum<RimObjectiveFunction::FunctionType>::setUp()
{
addItem( RimObjectiveFunction::FunctionType::M1, "M1", "M1" );
addItem( RimObjectiveFunction::FunctionType::M2, "M2", "M2" );
setDefault( RimObjectiveFunction::FunctionType::M1 );
addItem( RimObjectiveFunction::FunctionType::F1, "F1", "Time Range (F1)" );
addItem( RimObjectiveFunction::FunctionType::F2, "F2", "Selected Time Steps (F2)" );
setDefault( RimObjectiveFunction::FunctionType::F1 );
}
} // namespace caf
CAF_PDM_SOURCE_INIT( RimObjectiveFunction, "RimObjectiveFunction" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimObjectiveFunction::uiName() const
RimObjectiveFunction::RimObjectiveFunction()
: changed( this )
{
if ( m_functionType == FunctionType::M1 )
{
return QString( "M1" );
}
else if ( m_functionType == FunctionType::M2 )
{
return QString( "M2" );
}
return QString();
CAF_PDM_InitObject( "Objective Function", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_functionType, "FunctionType", "Function Type", "", "", "" );
CAF_PDM_InitField( &m_normalizeByNumberOfObservations,
"NormalizeByNumberOfObservations",
true,
"Normalize by Number of Observations",
"",
"",
"" );
CAF_PDM_InitField( &m_normalizeByNumberOfVectors,
"NormalizeByNumberOfVectors",
true,
"Normalize by Number of Vectors",
"",
"",
"" );
CAF_PDM_InitField( &m_errorEstimatePercentage, "ErrorEstimatePercentage", 100.0, "Error Estimate [0..100 %]", "", "", "" );
CAF_PDM_InitField( &m_useSquaredError, "UseSquaredError", true, "Use Squared Error Term", "", "", "" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimObjectiveFunction::FunctionType RimObjectiveFunction::functionType()
void RimObjectiveFunction::setFunctionType( FunctionType functionType )
{
return m_functionType;
m_functionType = functionType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimObjectiveFunction::setTimeStepRange( time_t startTimeStep, time_t endTimeStep )
QString RimObjectiveFunction::shortName() const
{
m_startTimeStep = startTimeStep;
m_endTimeStep = endTimeStep;
return caf::AppEnum<FunctionType>::text( m_functionType() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimObjectiveFunction::setTimeStepList( std::vector<time_t> timeSteps )
RimObjectiveFunction::FunctionType RimObjectiveFunction::functionType() const
{
m_timeSteps = timeSteps;
return m_functionType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimObjectiveFunction::RimObjectiveFunction( const RimSummaryCaseCollection* summaryCaseCollection, FunctionType type )
{
m_summaryCaseCollection = summaryCaseCollection;
m_functionType = type;
m_startTimeStep = 0;
m_endTimeStep = INT_MAX;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimObjectiveFunction::value( size_t caseIndex,
std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses,
bool* hasWarning ) const
{
auto summaryCases = m_summaryCaseCollection->allSummaryCases();
if ( caseIndex < summaryCases.size() )
{
return value( summaryCases[caseIndex], vectorSummaryAddresses, hasWarning );
}
return 0.0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimObjectiveFunction::value( RimSummaryCase* summaryCase,
std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses,
bool* hasWarning ) const
double RimObjectiveFunction::value( RimSummaryCase* summaryCase,
const std::vector<RifEclipseSummaryAddress>& vectorSummaryAddresses,
const ObjectiveFunctionTimeConfig& timeConfig,
bool* hasWarning ) const
{
RifSummaryReaderInterface* readerInterface = summaryCase->summaryReader();
if ( readerInterface )
{
if ( m_functionType == FunctionType::M1 )
double aggregatedObjectiveFunctionValue = 0.0;
for ( auto vectorSummaryAddress : vectorSummaryAddresses )
{
double sumValues = 0.0;
double sumValuesSquared = 0.0;
double N = 0.0;
for ( auto vectorSummaryAddress : vectorSummaryAddresses )
std::string s = vectorSummaryAddress.quantityName() + RifReaderEclipseSummary::differenceIdentifier();
if ( !vectorSummaryAddress.quantityName().empty() )
{
std::string s = vectorSummaryAddress.quantityName() + RifReaderEclipseSummary::differenceIdentifier();
if ( !vectorSummaryAddress.quantityName().empty() )
if ( vectorSummaryAddress.quantityName().find( RifReaderEclipseSummary::differenceIdentifier() ) !=
std::string::npos )
{
if ( vectorSummaryAddress.quantityName().find( RifReaderEclipseSummary::differenceIdentifier() ) !=
std::string::npos )
{
s = vectorSummaryAddress.quantityName();
}
RifEclipseSummaryAddress vectorSummaryAddressDiff = vectorSummaryAddress;
vectorSummaryAddressDiff.setQuantityName( s );
s = vectorSummaryAddress.quantityName();
}
RifEclipseSummaryAddress vectorSummaryAddressDiff = vectorSummaryAddress;
vectorSummaryAddressDiff.setQuantityName( s );
if ( readerInterface->allResultAddresses().count( vectorSummaryAddressDiff ) )
RifEclipseSummaryAddress vectorSummaryAddressHistory = vectorSummaryAddress;
vectorSummaryAddressDiff.setQuantityName( vectorSummaryAddress.quantityName() +
RifReaderEclipseSummary::differenceIdentifier() );
if ( readerInterface->allResultAddresses().count( vectorSummaryAddressDiff ) )
{
const std::vector<time_t>& allTimeSteps = readerInterface->timeSteps( vectorSummaryAddressDiff );
std::vector<size_t> timeStepsForEvaluation = timeStepIndicesForEvaluation( allTimeSteps, timeConfig );
std::vector<double> summaryDiffValues;
std::vector<double> summaryHistoryValues;
if ( readerInterface->values( vectorSummaryAddressDiff, &summaryDiffValues ) &&
readerInterface->values( vectorSummaryAddressHistory, &summaryHistoryValues ) )
{
std::vector<double> values;
if ( readerInterface->values( vectorSummaryAddressDiff, &values ) )
const double functionValue =
computeFunctionValue( summaryDiffValues, summaryHistoryValues, timeStepsForEvaluation );
if ( functionValue != std::numeric_limits<double>::infinity() )
{
const std::vector<time_t>& timeSteps = readerInterface->timeSteps( vectorSummaryAddressDiff );
size_t index = 0;
N += static_cast<double>( values.size() );
if ( values.size() > 1 )
{
for ( time_t t : timeSteps )
{
if ( t >= m_startTimeStep && t <= m_endTimeStep )
{
const double& value = values[index];
sumValues += std::abs( value );
sumValuesSquared += value * value;
}
index++;
}
}
}
}
else
{
RiaLogging::info( "The selected summary address does not have a related difference address." );
if ( hasWarning )
{
*hasWarning = true;
aggregatedObjectiveFunctionValue += functionValue;
}
}
}
else
{
RiaLogging::info( "Invalid summary address." );
if ( hasWarning )
{
*hasWarning = true;
}
}
if ( sumValues != 0 )
{
return sumValues / std::sqrt( ( N * sumValuesSquared - sumValues * sumValues ) / ( N * ( N - 1.0 ) ) );
}
}
}
else if ( m_functionType == FunctionType::M2 )
{
double value = 0;
for ( auto vectorSummaryAddress : vectorSummaryAddresses )
{
std::string s = vectorSummaryAddress.quantityName() + RifReaderEclipseSummary::differenceIdentifier();
if ( !vectorSummaryAddress.quantityName().empty() )
{
if ( vectorSummaryAddress.quantityName().find( RifReaderEclipseSummary::differenceIdentifier() ) !=
std::string::npos )
{
s = vectorSummaryAddress.quantityName();
}
RifEclipseSummaryAddress vectorSummaryAddressDiff = vectorSummaryAddress;
vectorSummaryAddressDiff.setQuantityName( s );
if ( readerInterface->allResultAddresses().count( vectorSummaryAddressDiff ) )
{
std::vector<double> values;
if ( readerInterface->values( vectorSummaryAddressDiff, &values ) )
{
const std::vector<time_t>& timeSteps = readerInterface->timeSteps( vectorSummaryAddressDiff );
size_t index = 0;
std::vector<time_t> xValues( 2, 0 );
std::vector<double> yValues( 2, 0.0 );
for ( time_t t : timeSteps )
{
if ( t >= m_startTimeStep && t <= m_endTimeStep )
{
if ( xValues.front() == 0 )
{
xValues[0] = t;
yValues[0] = values[index];
}
else if ( xValues.back() == 0 )
{
xValues[1] = t;
yValues[1] = values[index];
}
else
{
xValues[0] = xValues[1];
xValues[1] = t;
yValues[0] = yValues[1];
yValues[1] = values[index];
}
if ( xValues.back() != 0 )
{
for ( time_t timeStep : m_timeSteps )
{
if ( xValues[0] <= timeStep && xValues[1] >= timeStep )
{
double interpValue = std::abs(
RiaCurveMerger<time_t>::interpolatedYValue( timeStep, xValues, yValues ) );
if ( interpValue != HUGE_VAL )
{
value += interpValue;
}
}
}
}
index++;
}
}
}
}
else
{
RiaLogging::info( "The selected summary address does not have a related difference address." );
if ( hasWarning )
{
*hasWarning = true;
}
}
}
else
{
RiaLogging::info( "Invalid summary address." );
RiaLogging::info( "The selected summary address does not have a related difference address." );
if ( hasWarning )
{
*hasWarning = true;
}
}
}
return value;
else
{
RiaLogging::info( "Invalid summary address." );
if ( hasWarning )
{
*hasWarning = true;
}
}
if ( m_normalizeByNumberOfVectors && vectorSummaryAddresses.size() > 0 )
{
aggregatedObjectiveFunctionValue /= vectorSummaryAddresses.size();
}
return aggregatedObjectiveFunctionValue;
}
}
return 0.0;
@ -284,102 +185,40 @@ double RimObjectiveFunction::value( RimSummaryCase* summar
///
//--------------------------------------------------------------------------------------------------
std::pair<double, double>
RimObjectiveFunction::minMaxValues( std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses ) const
RimObjectiveFunction::minMaxValues( const std::vector<RimSummaryCase*>& summaryCases,
const std::vector<RifEclipseSummaryAddress>& vectorSummaryAddresses,
const ObjectiveFunctionTimeConfig& timeConfig ) const
{
double minValue = std::numeric_limits<double>::infinity();
double maxValue = -std::numeric_limits<double>::infinity();
for ( auto value : values( vectorSummaryAddresses ) )
for ( auto sumCase : summaryCases )
{
if ( value != std::numeric_limits<double>::infinity() )
auto objValue = value( sumCase, vectorSummaryAddresses, timeConfig );
{
if ( value < minValue ) minValue = value;
if ( value > maxValue ) maxValue = value;
if ( objValue != std::numeric_limits<double>::infinity() )
{
if ( objValue < minValue ) minValue = objValue;
if ( objValue > maxValue ) maxValue = objValue;
}
}
}
return std::make_pair( minValue, maxValue );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<time_t, time_t> RimObjectiveFunction::range() const
{
return std::make_pair( m_startTimeStep, m_endTimeStep );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimObjectiveFunction::values( std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses ) const
{
std::vector<double> values;
auto summaryCases = m_summaryCaseCollection->allSummaryCases();
bool hasWarning = false;
for ( size_t index = 0; index < summaryCases.size(); index++ )
{
values.push_back( value( index, vectorSummaryAddresses, &hasWarning ) );
if ( hasWarning )
{
return std::vector<double>();
}
}
return values;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimObjectiveFunction::isValid( std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses ) const
{
bool hasWarning = false;
if ( m_summaryCaseCollection && m_summaryCaseCollection->allSummaryCases().size() > 0 &&
m_summaryCaseCollection->allSummaryCases().front() )
{
value( m_summaryCaseCollection->allSummaryCases().front(), vectorSummaryAddresses, &hasWarning );
if ( hasWarning )
{
return false;
}
}
else
{
return false;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimObjectiveFunction::formulaString( std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses )
{
QString formula;
if ( m_functionType == FunctionType::M1 )
for ( RifEclipseSummaryAddress address : vectorSummaryAddresses )
{
formula += "(" + QString::fromWCharArray( L"\u03A3" ) + "(|";
QStringList addresses;
for ( RifEclipseSummaryAddress address : vectorSummaryAddresses )
{
addresses << QString::fromStdString( address.uiText() );
}
formula += addresses.join( "| + |" );
formula += "|))/(stdv)";
}
else if ( m_functionType == FunctionType::M2 )
{
formula += QString::fromWCharArray( L"\u03A3" ) + "(|";
QStringList addresses;
for ( RifEclipseSummaryAddress address : vectorSummaryAddresses )
{
addresses << QString::fromStdString( address.uiText() );
}
formula += addresses.join( "| + |" );
formula += "|)";
QString text = QString::fromStdString( address.uiText() );
formula += text + "\n";
}
return formula;
}
@ -388,5 +227,164 @@ QString RimObjectiveFunction::formulaString( std::vector<RifEclipseSummaryAddres
//--------------------------------------------------------------------------------------------------
bool RimObjectiveFunction::operator<( const RimObjectiveFunction& other ) const
{
return this->uiName() < other.uiName();
return this->shortName() < other.shortName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimObjectiveFunction::hideFunctionSelection()
{
m_functionType.uiCapability()->setUiHidden( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimObjectiveFunction::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &m_functionType );
uiOrdering.add( &m_normalizeByNumberOfObservations );
uiOrdering.add( &m_normalizeByNumberOfVectors );
uiOrdering.add( &m_errorEstimatePercentage );
uiOrdering.add( &m_useSquaredError );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimObjectiveFunction::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
double estimate = m_errorEstimatePercentage;
m_errorEstimatePercentage = std::clamp( estimate, 0.0, 100.0 );
changed.send();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimObjectiveFunction::errorEstimate() const
{
return std::clamp( ( m_errorEstimatePercentage / 100.0 ), 0.0, 1.0 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<size_t> RimObjectiveFunction::timeStepIndicesForEvaluation( const std::vector<time_t>& allTimeSteps,
const ObjectiveFunctionTimeConfig& timeConfig ) const
{
std::vector<size_t> timeStepIndices;
if ( functionType() == FunctionType::F1 )
{
for ( size_t i = 0; i < allTimeSteps.size(); i++ )
{
const auto& t = allTimeSteps[i];
if ( t >= timeConfig.m_startTimeStep && t <= timeConfig.m_endTimeStep )
{
timeStepIndices.push_back( i );
}
}
}
else if ( functionType() == FunctionType::F2 )
{
for ( const auto& t : timeConfig.m_timeSteps )
{
for ( size_t i = 0; i < allTimeSteps.size(); i++ )
{
const auto& candidateTime = allTimeSteps[i];
if ( t == candidateTime )
{
timeStepIndices.push_back( i );
}
}
}
}
return timeStepIndices;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimObjectiveFunction::computeFunctionValue( const std::vector<double>& summaryDiffValues,
const std::vector<double>& summaryHistoryValues,
const std::vector<size_t>& evaluationIndices ) const
{
if ( summaryHistoryValues.size() != summaryDiffValues.size() ) return std::numeric_limits<double>::infinity();
const double epsilonErrorEstimate = errorEstimate();
double sumValues = 0.0;
double sumValuesSquared = 0.0;
size_t valueCount = evaluationIndices.size();
double averageHistoryValue = 0.0;
if ( !summaryHistoryValues.empty() )
{
for ( auto val : summaryHistoryValues )
{
averageHistoryValue += val;
}
averageHistoryValue /= summaryHistoryValues.size();
}
//
// 1 ( |ti - tHi| ) n
// value = - * SUM ( ---------- )
// N ( eps * tHi )
//
// N : observation count
// ti : simulated value at time step i
// Hti : observed (history) value at time step i
// eps : error estimate (0..1)
// n : 2 - squared error term
//
// https://github.com/OPM/ResInsight/issues/7761
//
//
//
const double epsilon = 1e-67;
for ( size_t timeStepIndex : evaluationIndices )
{
const double diffValue = std::abs( summaryDiffValues[timeStepIndex] );
double historyValue = summaryHistoryValues[timeStepIndex];
double nominator = std::abs( epsilonErrorEstimate * historyValue );
if ( nominator < epsilon )
{
if ( averageHistoryValue > epsilon )
nominator = averageHistoryValue;
else if ( diffValue > epsilon )
nominator = diffValue;
else
nominator = 1.0;
}
const double normalizedDiff = diffValue / nominator;
sumValues += std::abs( normalizedDiff );
sumValuesSquared += normalizedDiff * normalizedDiff;
}
if ( valueCount > 0 )
{
double functionValue = 0.0;
if ( m_useSquaredError )
functionValue = sumValuesSquared;
else
functionValue = sumValues;
if ( m_normalizeByNumberOfObservations ) functionValue /= valueCount;
return functionValue;
}
return std::numeric_limits<double>::infinity();
}

View File

@ -18,6 +18,10 @@
#pragma once
#include "cafAppEnum.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include <QString>
#include <QVariant>
@ -27,51 +31,71 @@ class RimSummaryCase;
class RimSummaryCaseCollection;
class RifEclipseSummaryAddress;
class ObjectiveFunctionTimeConfig
{
public:
time_t m_startTimeStep;
time_t m_endTimeStep;
std::vector<time_t> m_timeSteps;
};
//==================================================================================================
///
//==================================================================================================
class RimObjectiveFunction
class RimObjectiveFunction : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
caf::Signal<> changed;
public:
enum class FunctionType
{
M1 = 0,
M2
F1 = 0,
F2
};
QString uiName() const;
RimObjectiveFunction::FunctionType functionType();
QString shortName() const;
RimObjectiveFunction::FunctionType functionType() const;
void setTimeStepRange( time_t startTime, time_t endTime );
void setTimeStepList( std::vector<time_t> timeSteps );
RimObjectiveFunction();
void setFunctionType( RimObjectiveFunction::FunctionType functionType );
RimObjectiveFunction( const RimSummaryCaseCollection* summaryCaseCollection, FunctionType type );
double value( RimSummaryCase* summaryCase,
const std::vector<RifEclipseSummaryAddress>& vectorSummaryAddresses,
const ObjectiveFunctionTimeConfig& timeConfig,
bool* hasWarning = nullptr ) const;
double value( size_t caseIndex,
std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses,
bool* hasWarning = nullptr ) const;
double value( RimSummaryCase* summaryCase,
std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses,
bool* hasWarning = nullptr ) const;
std::pair<double, double> minMaxValues( std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses ) const;
std::pair<time_t, time_t> range() const;
std::vector<double> values( std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses ) const;
bool isValid( std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses ) const;
std::pair<double, double> minMaxValues( const std::vector<RimSummaryCase*>& summaryCases,
const std::vector<RifEclipseSummaryAddress>& vectorSummaryAddresses,
const ObjectiveFunctionTimeConfig& timeConfig ) const;
QString formulaString( std::vector<RifEclipseSummaryAddress> vectorSummaryAddresses );
bool operator<( const RimObjectiveFunction& other ) const;
private:
const RimSummaryCaseCollection* m_summaryCaseCollection;
void hideFunctionSelection();
time_t m_startTimeStep;
time_t m_endTimeStep;
std::vector<time_t> m_timeSteps;
FunctionType m_functionType;
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
private:
double errorEstimate() const;
std::vector<size_t> timeStepIndicesForEvaluation( const std::vector<time_t>& allTimeSteps,
const ObjectiveFunctionTimeConfig& timeConfig ) const;
double computeFunctionValue( const std::vector<double>& summaryDiffValues,
const std::vector<double>& summaryHistoryValues,
const std::vector<size_t>& evaluationIndices ) const;
private:
caf::PdmField<caf::AppEnum<RimObjectiveFunction::FunctionType>> m_functionType;
caf::PdmField<bool> m_normalizeByNumberOfObservations;
caf::PdmField<double> m_errorEstimatePercentage;
caf::PdmField<bool> m_useSquaredError;
caf::PdmField<bool> m_normalizeByNumberOfVectors;
};

View File

@ -0,0 +1,95 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021 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 "RimObjectiveFunctionTools.h"
#include "RifEclipseSummaryAddress.h"
#include "RiaStdStringTools.h"
#include "RifReaderEclipseSummary.h"
#include "RimCustomObjectiveFunction.h"
#include "RimCustomObjectiveFunctionWeight.h"
#include "RimEnsembleCurveSet.h"
#include "RiuSummaryVectorSelectionDialog.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCustomObjectiveFunctionWeight* RimObjectiveFunctionTools::addWeight( RimCustomObjectiveFunction* customObjectiveFunction )
{
if ( !customObjectiveFunction ) return nullptr;
RimCustomObjectiveFunctionWeight* newWeight = customObjectiveFunction->addWeight();
RifEclipseSummaryAddress candidateAdr;
if ( customObjectiveFunction->weights().size() > 1 )
{
candidateAdr = customObjectiveFunction->weights().front()->summaryAddresses().front();
}
else
{
candidateAdr = newWeight->parentCurveSet()->summaryAddress();
}
auto nativeQuantityName = RimObjectiveFunctionTools::nativeQuantityName( candidateAdr.quantityName() );
candidateAdr.setQuantityName( nativeQuantityName );
newWeight->setSummaryAddress( candidateAdr );
return newWeight;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::string RimObjectiveFunctionTools::nativeQuantityName( const std::string& quantityName )
{
std::string nativeName = quantityName;
{
auto stringToRemove = RifReaderEclipseSummary::differenceIdentifier();
if ( RiaStdStringTools::endsWith( nativeName, stringToRemove ) )
{
nativeName = nativeName.substr( 0, nativeName.size() - stringToRemove.size() );
}
}
{
auto stringToRemove = RifReaderEclipseSummary::historyIdentifier();
if ( RiaStdStringTools::endsWith( nativeName, stringToRemove ) )
{
nativeName = nativeName.substr( 0, nativeName.size() - stringToRemove.size() );
}
}
return nativeName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimObjectiveFunctionTools::configureDialogForObjectiveFunctions( RiuSummaryVectorSelectionDialog* dialog )
{
if ( !dialog ) return;
dialog->enableMultiSelect( true );
dialog->hideDifferenceVectors();
dialog->hideHistoryVectors();
dialog->hideVectorsWithNoHistory();
dialog->hideSummaryCases();
}

View File

@ -0,0 +1,36 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021 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 <string>
class RimCustomObjectiveFunctionWeight;
class RimCustomObjectiveFunction;
class RiuSummaryVectorSelectionDialog;
namespace RimObjectiveFunctionTools
{
RimCustomObjectiveFunctionWeight* addWeight( RimCustomObjectiveFunction* customObjectiveFunction );
// Returns a string without string endings 'H' and '_DIFF'
std::string nativeQuantityName( const std::string& quantityName );
void configureDialogForObjectiveFunctions( RiuSummaryVectorSelectionDialog* dialog );
}; // namespace RimObjectiveFunctionTools

View File

@ -213,9 +213,6 @@ RimSummaryCaseCollection::RimSummaryCaseCollection()
m_statisticsEclipseRftReader = new RifReaderEnsembleStatisticsRft( this );
m_commonAddressCount = 0;
m_objectiveFunctions.push_back( std::make_shared<RimObjectiveFunction>( this, RimObjectiveFunction::FunctionType::M1 ) );
m_objectiveFunctions.push_back( std::make_shared<RimObjectiveFunction>( this, RimObjectiveFunction::FunctionType::M2 ) );
}
//--------------------------------------------------------------------------------------------------
@ -865,30 +862,6 @@ void RimSummaryCaseCollection::clearEnsembleParametersHashes()
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::shared_ptr<RimObjectiveFunction>> RimSummaryCaseCollection::objectiveFunctions() const
{
return m_objectiveFunctions;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::shared_ptr<RimObjectiveFunction>
RimSummaryCaseCollection::objectiveFunction( RimObjectiveFunction::FunctionType functionType )
{
for ( auto objectiveFunc : m_objectiveFunctions )
{
if ( objectiveFunc->functionType() == functionType )
{
return objectiveFunc;
}
}
return m_objectiveFunctions.front();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -138,9 +138,6 @@ public:
void calculateEnsembleParametersIntersectionHash();
void clearEnsembleParametersHashes();
std::vector<std::shared_ptr<RimObjectiveFunction>> objectiveFunctions() const;
std::shared_ptr<RimObjectiveFunction> objectiveFunction( RimObjectiveFunction::FunctionType functionType );
void loadDataAndUpdate();
static bool validateEnsembleCases( const std::vector<RimSummaryCase*> cases );
@ -181,6 +178,4 @@ private:
size_t m_commonAddressCount; // if different address count among cases, set to 0
mutable std::vector<EnsembleParameter> m_cachedSortedEnsembleParameters;
std::vector<std::shared_ptr<RimObjectiveFunction>> m_objectiveFunctions;
};

View File

@ -186,6 +186,30 @@ void RiuSummaryVectorSelectionDialog::enableIndividualEnsembleCaseSelection( boo
summaryAddressSelection()->enableIndividualEnsembleCaseSelection( enable );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionDialog::hideHistoryVectors()
{
summaryAddressSelection()->hideHistoryVectors( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionDialog::hideDifferenceVectors()
{
summaryAddressSelection()->hideDifferenceVectors( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionDialog::hideVectorsWithNoHistory()
{
summaryAddressSelection()->hideVectorsWithoutHistory( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -52,6 +52,10 @@ public:
void enableMultiSelect( bool enable );
void enableIndividualEnsembleCaseSelection( bool enable );
void hideHistoryVectors();
void hideDifferenceVectors();
void hideVectorsWithNoHistory();
private:
RiuSummaryVectorSelectionUi* summaryAddressSelection() const;
void updateLabel();

View File

@ -23,6 +23,7 @@
#include "RiaSummaryCurveDefinition.h"
#include "RifEclipseSummaryAddress.h"
#include "RifReaderEclipseSummary.h"
#include "RifSummaryReaderInterface.h"
#include "RimCalculatedSummaryCase.h"
@ -383,6 +384,10 @@ RiuSummaryVectorSelectionUi::RiuSummaryVectorSelectionUi()
m_hideEnsembles = false;
m_hideSummaryCases = false;
m_hideDifferenceVectors = false;
m_hideHistoryVectors = false;
m_hideVectorsWithoutHistory = false;
m_prevCurveCount = 0;
m_prevCurveSetCount = 0;
}
@ -566,6 +571,30 @@ void RiuSummaryVectorSelectionUi::enableIndividualEnsembleCaseSelection( bool en
m_showIndividualEnsembleCases = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::hideDifferenceVectors( bool hide )
{
m_hideDifferenceVectors = hide;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::hideHistoryVectors( bool hide )
{
m_hideHistoryVectors = hide;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::hideVectorsWithoutHistory( bool hide )
{
m_hideVectorsWithoutHistory = hide;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -1128,6 +1157,40 @@ std::set<RifEclipseSummaryAddress>
}
}
}
if ( m_hideHistoryVectors || m_hideDifferenceVectors )
{
std::set<RifEclipseSummaryAddress> filteredAddresses;
for ( const auto& adr : addrUnion )
{
if ( m_hideHistoryVectors && adr.isHistoryQuantity() ) continue;
if ( m_hideDifferenceVectors )
{
const auto diffText = RifReaderEclipseSummary::differenceIdentifier();
if ( RiaStdStringTools::endsWith( adr.quantityName(), diffText ) ) continue;
}
if ( m_hideVectorsWithoutHistory )
{
auto candidateName = adr.quantityName() + RifReaderEclipseSummary::historyIdentifier();
bool found = false;
for ( const auto& ad : addrUnion )
{
if ( ad.quantityName() == candidateName ) found = true;
}
if ( !found ) continue;
}
filteredAddresses.insert( adr );
}
addrUnion.swap( filteredAddresses );
}
return addrUnion;
}

View File

@ -63,6 +63,10 @@ public:
void hideSummaryCases( bool hide );
void enableIndividualEnsembleCaseSelection( bool enable );
void hideDifferenceVectors( bool hide );
void hideHistoryVectors( bool hide );
void hideVectorsWithoutHistory( bool hide );
void setFieldChangedHandler( const std::function<void()>& handlerFunc );
void setDefaultSelection( const std::vector<SummarySource*>& defaultCases );
@ -129,6 +133,10 @@ private:
bool m_hideSummaryCases;
bool m_showIndividualEnsembleCases;
bool m_hideHistoryVectors;
bool m_hideVectorsWithoutHistory;
bool m_hideDifferenceVectors;
std::function<void()> m_toggleChangedHandler;
size_t m_prevCurveCount;