ResInsight/ApplicationLibCode/UserInterface/RiuSummaryVectorSelectionUi.cpp
Magne Sjaastad 4d21f90bf9
Add summary multi plot
Improve robustness related to update of Summary Plot Manager

Add RimSummaryMultiPlot
Move shared code into RiaSummaryStringTools
Added "Create Summary Multi Plot" to menu of MultiPlot in project tree
2021-12-23 09:30:36 +01:00

1710 lines
74 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiuSummaryVectorSelectionUi.h"
#include "RiaCurveSetDefinition.h"
#include "RiaOptionItemFactory.h"
#include "RiaStdStringTools.h"
#include "RiaSummaryCurveDefinition.h"
#include "RifEclipseSummaryAddress.h"
#include "RifReaderEclipseSummary.h"
#include "RifSummaryReaderInterface.h"
#include "RimCalculatedSummaryCase.h"
#include "RimObservedDataCollection.h"
#include "RimObservedSummaryData.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSummaryCalculation.h"
#include "RimSummaryCalculationCollection.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryCaseMainCollection.h"
#include "RiuSummaryCurveDefinitionKeywords.h"
#include "RiuSummaryQuantityNameInfoProvider.h"
#include "cafPdmPointer.h"
#include "cafPdmUiFieldHandle.h"
#include "cafPdmUiTreeSelectionEditor.h"
#include <QDebug>
#include <algorithm>
CAF_PDM_SOURCE_INIT( RiuSummaryVectorSelectionUi, "RicSummaryAddressSelection" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
class SummaryIdentifierAndField
{
public:
SummaryIdentifierAndField()
: m_summaryIdentifier( (RifEclipseSummaryAddress::SummaryIdentifierType)0 )
, m_pdmField( nullptr )
{
}
SummaryIdentifierAndField( const SummaryIdentifierAndField& ) = delete;
SummaryIdentifierAndField( RifEclipseSummaryAddress::SummaryIdentifierType summaryIdentifier )
: m_summaryIdentifier( summaryIdentifier )
, m_pdmField( new caf::PdmField<std::vector<QString>>() )
{
}
virtual ~SummaryIdentifierAndField() { delete m_pdmField; }
RifEclipseSummaryAddress::SummaryIdentifierType summaryIdentifier() const { return m_summaryIdentifier; }
caf::PdmField<std::vector<QString>>* pdmField() { return m_pdmField; }
private:
RifEclipseSummaryAddress::SummaryIdentifierType m_summaryIdentifier;
caf::PdmField<std::vector<QString>>* m_pdmField;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuSummaryVectorSelectionUi::RiuSummaryVectorSelectionUi()
: m_identifierFieldsMap( {
{ RifEclipseSummaryAddress::SUMMARY_FIELD,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_AQUIFER,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_AQUIFER_NUMBER ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_NETWORK,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_MISC,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_REGION,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_REGION_NUMBER ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_REGION_2_REGION ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_WELL_GROUP,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_WELL_GROUP_NAME ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_WELL,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_WELL_NAME ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_WELL_NAME ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_CELL_IJK ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_LGR_NAME ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_WELL_NAME ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_CELL_IJK ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_WELL_LGR,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_LGR_NAME ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_WELL_NAME ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_WELL_NAME ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_SEGMENT_NUMBER ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_BLOCK,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_CELL_IJK ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_LGR_NAME ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_CELL_IJK ) },
{ new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_CALCULATED,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
{ RifEclipseSummaryAddress::SUMMARY_IMPORTED,
{ { new SummaryIdentifierAndField( RifEclipseSummaryAddress::INPUT_VECTOR_NAME ) } } },
} )
, m_showIndividualEnsembleCases( false )
{
CAF_PDM_InitFieldNoDefault( &m_selectedSources, "SummaryCases", "Cases" );
m_selectedSources.uiCapability()->setAutoAddingOptionFromValue( false );
CAF_PDM_InitFieldNoDefault( &m_currentSummaryCategory, "CurrentSummaryCategory", "Current Summary Category" );
CAF_PDM_InitFieldNoDefault( &m_selectedSummaryCategories, "SelectedSummaryCategories", "Summary Categories" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_FIELD][0]->pdmField(),
"FieldVectors",
"Field vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_AQUIFER][0]->pdmField(),
"Aquifers",
"Aquifers" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_AQUIFER][1]->pdmField(),
"AquiferVectors",
"Aquifer Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_NETWORK][0]->pdmField(),
"NetworkVectors",
"Network Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_MISC][0]->pdmField(),
"MiscVectors",
"Misc Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION][0]->pdmField(),
"Regions",
"Regions" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION][1]->pdmField(),
"RegionsVectors",
"Regions Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION][0]->pdmField(),
"Region2RegionRegions",
"Regions" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION][1]->pdmField(),
"Region2RegionVectors",
"Region2s Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_GROUP][0]->pdmField(),
"WellGroupWellGroupNames",
"Well groups" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_GROUP][1]->pdmField(),
"WellGroupVectors",
"Well Group Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL][0]->pdmField(),
"WellWellName",
"Wells" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL][1]->pdmField(),
"WellVectors",
"Well Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][0]->pdmField(),
"WellCompletionWellName",
"Wells" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][1]->pdmField(),
"WellCompletionIjk",
"Cell IJK" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][2]->pdmField(),
"WellCompletionVectors",
"Well Completion Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][0]->pdmField(),
"WellCompletionLgrLgrName",
"LGR Names" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][1]->pdmField(),
"WellCompletionLgrWellName",
"Wells" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][2]->pdmField(),
"WellCompletionLgrIjk",
"Cell IJK" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][3]->pdmField(),
"WellCompletionLgrVectors",
"Well Completion Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][0]->pdmField(),
"WellLgrLgrName",
"LGR Names" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][1]->pdmField(),
"WellLgrWellName",
"Wells" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][2]->pdmField(),
"WellLgrVectors",
"Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][0]->pdmField(),
"WellSegmentWellName",
"Wells" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][1]->pdmField(),
"WellSegmentNumber",
"Segments" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][2]->pdmField(),
"WellSegmentVectors",
"Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK][0]->pdmField(),
"BlockIjk",
"Cell IJK" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK][1]->pdmField(),
"BlockVectors",
"Block Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][0]->pdmField(),
"BlockLgrLgrName",
"LGR Names" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][1]->pdmField(),
"BlockLgrIjk",
"Cell IJK" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][2]->pdmField(),
"BlockLgrVectors",
"Block Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_CALCULATED][0]->pdmField(),
"CalculatedVectors",
"Calculated Vectors" );
CAF_PDM_InitFieldNoDefault( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_IMPORTED][0]->pdmField(),
"ImportedVectors",
"Imported vectors" );
for ( const auto& itemTypes : m_identifierFieldsMap )
{
for ( const auto& itemInputType : itemTypes.second )
{
itemInputType->pdmField()->uiCapability()->setUiEditorTypeName(
caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
itemInputType->pdmField()->uiCapability()->setUiLabelPosition(
itemTypes.second.size() > 2 ? caf::PdmUiItemInfo::TOP : caf::PdmUiItemInfo::HIDDEN );
itemInputType->pdmField()->uiCapability()->setAutoAddingOptionFromValue( false );
}
itemTypes.second.back()->pdmField()->uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
}
m_selectedSources.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
m_selectedSources.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
m_selectedSources.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
m_selectedSummaryCategories.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
m_selectedSummaryCategories.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
m_currentSummaryCategory.uiCapability()->setUiHidden( true );
m_multiSelectionMode = false;
m_hideEnsembles = false;
m_hideSummaryCases = false;
m_hideDifferenceVectors = false;
m_hideHistoryVectors = false;
m_hideVectorsWithoutHistory = false;
m_prevCurveCount = 0;
m_prevCurveSetCount = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuSummaryVectorSelectionUi::~RiuSummaryVectorSelectionUi()
{
for ( const auto& identifierAndFieldList : m_identifierFieldsMap )
{
for ( const auto& identifierAndField : identifierAndFieldList.second )
{
delete identifierAndField->pdmField();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RiaSummaryCurveDefinition> RiuSummaryVectorSelectionUi::allCurveDefinitionsFromSelection() const
{
std::vector<RiaSummaryCurveDefinition> curveDefVector;
{
std::set<RiaSummaryCurveDefinition> curveDefinitions;
std::set<RifEclipseSummaryAddress> selectedAddressesFromUi = buildAddressListFromSelections();
for ( SummarySource* currSource : selectedSummarySources() )
{
RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>( currSource );
RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>( currSource );
std::set<RifEclipseSummaryAddress> addressesFromSource;
std::vector<RimSummaryCase*> casesFromSource;
// Build case list
if ( ensemble )
{
auto addresses = ensemble->ensembleSummaryAddresses();
addressesFromSource.insert( addresses.begin(), addresses.end() );
auto ensembleCases = ensemble->allSummaryCases();
casesFromSource.insert( casesFromSource.end(), ensembleCases.begin(), ensembleCases.end() );
}
else
{
RifSummaryReaderInterface* reader = sumCase ? sumCase->summaryReader() : nullptr;
if ( reader )
{
addressesFromSource.insert( reader->allResultAddresses().begin(), reader->allResultAddresses().end() );
casesFromSource.push_back( sumCase );
}
}
for ( auto caseFromSource : casesFromSource )
{
for ( const auto& addressFromSource : addressesFromSource )
{
if ( selectedAddressesFromUi.count( addressFromSource ) > 0 )
{
curveDefinitions.insert(
RiaSummaryCurveDefinition( caseFromSource, addressFromSource, ensemble != nullptr ) );
}
}
}
}
std::copy( curveDefinitions.begin(), curveDefinitions.end(), std::back_inserter( curveDefVector ) );
}
return curveDefVector;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RiaCurveSetDefinition> RiuSummaryVectorSelectionUi::allCurveSetDefinitionsFromSelections() const
{
std::vector<RiaCurveSetDefinition> curveSetDefVector;
std::set<RiaCurveSetDefinition> curveSetDefinitions;
std::set<RifEclipseSummaryAddress> selectedAddressesFromUi = buildAddressListFromSelections();
for ( SummarySource* currSource : selectedSummarySources() )
{
RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>( currSource );
if ( !ensemble ) continue;
std::set<RifEclipseSummaryAddress> addressesFromSource;
// Build case list
auto addresses = ensemble->ensembleSummaryAddresses();
addressesFromSource.insert( addresses.begin(), addresses.end() );
for ( const auto& addressFromSource : addressesFromSource )
{
if ( selectedAddressesFromUi.count( addressFromSource ) > 0 )
{
curveSetDefinitions.insert( RiaCurveSetDefinition( ensemble, addressFromSource ) );
}
}
}
std::copy( curveSetDefinitions.begin(), curveSetDefinitions.end(), std::back_inserter( curveSetDefVector ) );
return curveSetDefVector;
}
//--------------------------------------------------------------------------------------------------
/// One CurveDefinition pr ensemble curve set,
/// but if enableIndividualEnsembleCaseSelection has been enabled,
/// the ensembles are never available for direct selection, and this method will always return the
/// "expanded" set of curvedefinitions
//--------------------------------------------------------------------------------------------------
std::vector<RiaSummaryCurveDefinition> RiuSummaryVectorSelectionUi::selection() const
{
std::vector<RiaSummaryCurveDefinition> curveDefSelection;
std::set<RifEclipseSummaryAddress> selectedAddressesFromUi = buildAddressListFromSelections();
for ( SummarySource* currSource : selectedSummarySources() )
{
RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>( currSource );
RimSummaryCase* sourceCase = dynamic_cast<RimSummaryCase*>( currSource );
if ( ensemble )
{
std::set<RifEclipseSummaryAddress> addressUnion = ensemble->ensembleSummaryAddresses();
for ( const auto& addr : selectedAddressesFromUi )
{
if ( addressUnion.count( addr ) )
{
curveDefSelection.push_back( RiaSummaryCurveDefinition( ensemble, addr ) );
}
}
}
else
{
if ( !( sourceCase && sourceCase->summaryReader() ) ) continue;
const std::set<RifEclipseSummaryAddress>& readerAddresses = sourceCase->summaryReader()->allResultAddresses();
for ( const auto& addr : selectedAddressesFromUi )
{
if ( readerAddresses.count( addr ) )
{
curveDefSelection.push_back( RiaSummaryCurveDefinition( sourceCase, addr, false ) );
}
}
}
}
return curveDefSelection;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::setMultiSelectionMode( bool multiSelectionMode )
{
m_multiSelectionMode = multiSelectionMode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::hideEnsembles( bool hide )
{
m_hideEnsembles = hide;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::hideSummaryCases( bool hide )
{
m_hideSummaryCases = hide;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::enableIndividualEnsembleCaseSelection( bool enable )
{
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;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::setFieldChangedHandler( const std::function<void()>& handlerFunc )
{
m_toggleChangedHandler = handlerFunc;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::setDefaultSelection( const std::vector<SummarySource*>& defaultSources )
{
RimProject* proj = RimProject::current();
auto allSumCases = proj->allSummaryCases();
if ( allSumCases.size() > 0 )
{
RifEclipseSummaryAddress defaultAddress;
std::vector<SummarySource*> selectTheseSources = defaultSources;
if ( selectTheseSources.empty() ) selectTheseSources.push_back( allSumCases[0] );
std::vector<RiaSummaryCurveDefinition> curveDefs;
for ( SummarySource* s : selectTheseSources )
{
RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>( s );
RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>( s );
if ( ensemble )
{
curveDefs.push_back( RiaSummaryCurveDefinition( ensemble, defaultAddress ) );
}
else
{
curveDefs.push_back( RiaSummaryCurveDefinition( sumCase, defaultAddress, false ) );
}
}
setSelectedCurveDefinitions( curveDefs );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RiuSummaryVectorSelectionUi::optionsForSummaryDataSource( bool hideSummaryCases,
bool hideEnsembles,
bool showIndividualEnsembleCases )
{
QList<caf::PdmOptionItemInfo> options;
RimProject* proj = RimProject::current();
std::vector<RimOilField*> oilFields;
proj->allOilFields( oilFields );
for ( RimOilField* oilField : oilFields )
{
RimSummaryCaseMainCollection* sumCaseMainColl = oilField->summaryCaseMainCollection();
if ( sumCaseMainColl )
{
if ( !hideSummaryCases )
{
// Top level cases
for ( const auto& sumCase : sumCaseMainColl->topLevelSummaryCases() )
{
options.push_back( caf::PdmOptionItemInfo( sumCase->displayCaseName(), sumCase ) );
}
}
// Ensembles
if ( !hideEnsembles )
{
bool ensembleHeaderCreated = false;
for ( const auto& sumCaseColl : sumCaseMainColl->summaryCaseCollections() )
{
if ( !sumCaseColl->isEnsemble() ) continue;
if ( !ensembleHeaderCreated )
{
options.push_back( caf::PdmOptionItemInfo::createHeader( "Ensembles", true ) );
ensembleHeaderCreated = true;
}
// Ensemble level
{
auto optionItem = caf::PdmOptionItemInfo( sumCaseColl->name(), sumCaseColl );
optionItem.setLevel( 1 );
options.push_back( optionItem );
}
if ( showIndividualEnsembleCases )
{
for ( const auto& sumCase : sumCaseColl->allSummaryCases() )
{
auto optionItem = caf::PdmOptionItemInfo( sumCase->displayCaseName(), sumCase );
optionItem.setLevel( 2 );
options.push_back( optionItem );
}
}
}
}
if ( !hideSummaryCases )
{
// Grouped cases
for ( const auto& sumCaseColl : sumCaseMainColl->summaryCaseCollections() )
{
if ( sumCaseColl->isEnsemble() ) continue;
options.push_back( caf::PdmOptionItemInfo::createHeader( sumCaseColl->name(), true ) );
for ( const auto& sumCase : sumCaseColl->allSummaryCases() )
{
auto optionItem = caf::PdmOptionItemInfo( sumCase->displayCaseName(), sumCase );
optionItem.setLevel( 1 );
options.push_back( optionItem );
}
}
// Observed data
auto observedDataColl = oilField->observedDataCollection();
if ( observedDataColl->allObservedSummaryData().size() > 0 )
{
options.push_back( caf::PdmOptionItemInfo::createHeader( "Observed Data", true ) );
for ( const auto& obsData : observedDataColl->allObservedSummaryData() )
{
auto optionItem = caf::PdmOptionItemInfo( obsData->caseName(), obsData );
optionItem.setLevel( 1 );
options.push_back( optionItem );
}
}
}
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::setSelectedCurveDefinitions( const std::vector<RiaSummaryCurveDefinition>& curveDefinitions )
{
resetAllFields();
std::set<RifEclipseSummaryAddress::SummaryVarCategory> categories;
for ( const auto& curveDef : curveDefinitions )
{
if ( !( curveDef.summaryCase() || curveDef.isEnsembleCurve() ) ) continue;
RimSummaryCase* summaryCase = curveDef.summaryCase();
RifEclipseSummaryAddress summaryAddress = curveDef.summaryAddress();
// Ignore ensemble statistics curves
if ( summaryAddress.category() == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS ) continue;
// Select summary category if not already selected
auto& selectedCategories = m_selectedSummaryCategories();
if ( std::find( selectedCategories.begin(), selectedCategories.end(), summaryAddress.category() ) ==
selectedCategories.end() )
{
if ( summaryAddress.category() != RifEclipseSummaryAddress::SUMMARY_INVALID )
{
m_selectedSummaryCategories.v().push_back( summaryAddress.category() );
}
else
{
// Use field category as fall back category to avoid an empty list of vectors
summaryAddress = RifEclipseSummaryAddress::fieldAddress( "" );
}
}
// Select case if not already selected
if ( curveDef.isEnsembleCurve() )
{
if ( curveDef.ensemble() && !m_hideEnsembles )
{
if ( std::find( m_selectedSources.begin(), m_selectedSources.end(), curveDef.ensemble() ) ==
m_selectedSources.end() )
{
m_selectedSources.push_back( curveDef.ensemble() );
handleAddedSource( curveDef.ensemble() );
}
}
}
else
{
if ( curveDef.summaryCase() && ( !curveDef.ensemble() || m_showIndividualEnsembleCases ) )
{
if ( std::find( m_selectedSources.begin(), m_selectedSources.end(), curveDef.summaryCase() ) ==
m_selectedSources.end() )
{
m_selectedSources.push_back( curveDef.summaryCase() );
handleAddedSource( curveDef.summaryCase() );
}
}
}
bool isObservedDataCase = isObservedData( summaryCase );
auto identifierAndFieldList = m_identifierFieldsMap[summaryAddress.category()];
for ( const auto& identifierAndField : identifierAndFieldList )
{
bool isVectorField = identifierAndField->summaryIdentifier() == RifEclipseSummaryAddress::INPUT_VECTOR_NAME;
QString avalue =
QString::fromStdString( summaryAddress.addressComponentUiText( identifierAndField->summaryIdentifier() ) );
if ( isVectorField && isObservedDataCase )
{
avalue = avalue + QString( OBSERVED_DATA_AVALUE_POSTFIX );
}
if ( isVectorField && summaryAddress.category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
{
// Append calculation id to input vector name calculated data.
avalue = avalue + QString( ":%1" ).arg( summaryAddress.id() );
}
const auto& currentSelectionVector = identifierAndField->pdmField()->v();
if ( std::find( currentSelectionVector.begin(), currentSelectionVector.end(), avalue ) ==
currentSelectionVector.end() )
{
std::vector<QString> newSelectionVector( currentSelectionVector.begin(), currentSelectionVector.end() );
newSelectionVector.push_back( avalue );
( *identifierAndField->pdmField() ) = newSelectionVector;
}
}
categories.insert( curveDef.summaryAddress().category() );
}
if ( !categories.empty() )
{
RifEclipseSummaryAddress::SummaryVarCategory cat = *( categories.begin() );
m_currentSummaryCategory.setValue( cat );
}
m_previouslySelectedSources = m_selectedSources.ptrReferencedObjects();
m_prevCurveCount = allCurveDefinitionsFromSelection().size();
m_prevCurveSetCount = allCurveSetDefinitionsFromSelections().size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RiuSummaryVectorSelectionUi::findPossibleSummaryAddressesFromCalculated() const
{
std::set<RifEclipseSummaryAddress> addressSet;
if ( m_currentSummaryCategory == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
{
RimSummaryCase* calcSumCase = calculatedSummaryCase();
const std::set<RifEclipseSummaryAddress> allAddresses = calcSumCase->summaryReader()->allResultAddresses();
for ( const auto& adr : allAddresses )
{
addressSet.insert( adr );
}
}
return addressSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
if ( changedField == &m_selectedSources )
{
caf::PdmObject* objectAdded = nullptr;
for ( caf::PdmObject* selectedObject : m_selectedSources() )
{
auto it = std::find( m_previouslySelectedSources.begin(), m_previouslySelectedSources.end(), selectedObject );
if ( it == m_previouslySelectedSources.end() )
{
objectAdded = selectedObject;
handleAddedSource( objectAdded );
break;
}
}
if ( !objectAdded )
{
caf::PdmObject* objectRemoved = nullptr;
for ( caf::PdmObject* previouslySelectedObject : m_previouslySelectedSources )
{
auto it = std::find( m_selectedSources.begin(), m_selectedSources.end(), previouslySelectedObject );
if ( it == m_selectedSources.end() )
{
objectRemoved = previouslySelectedObject;
handleRemovedSource( objectRemoved );
break;
}
}
}
m_previouslySelectedSources = m_selectedSources.ptrReferencedObjects();
}
if ( changedField != &m_selectedSources && changedField != &m_selectedSummaryCategories &&
changedField != &m_currentSummaryCategory )
{
RifEclipseSummaryAddress::SummaryVarCategory currentCategory = m_currentSummaryCategory();
if ( currentCategory != RifEclipseSummaryAddress::SUMMARY_INVALID )
{
// When a summary vector is selected, make sure the summary category for the summary vector is in the
// selection Note that we use the size of the variant to avoid this operation when an item in unchecked
if ( newValue.toList().size() > oldValue.toList().size() )
{
if ( std::find( m_selectedSummaryCategories.v().begin(),
m_selectedSummaryCategories.v().end(),
currentCategory ) == m_selectedSummaryCategories.v().end() )
{
m_selectedSummaryCategories.v().push_back( currentCategory );
}
}
if ( !newValue.toList().empty() )
{
auto identifierAndFieldList = m_identifierFieldsMap[currentCategory];
for ( const auto identifierAndField : identifierAndFieldList )
{
if ( identifierAndField->summaryIdentifier() == RifEclipseSummaryAddress::INPUT_VECTOR_NAME )
continue;
auto v = identifierAndField->pdmField()->value();
if ( v.empty() )
{
auto field = identifierAndField->pdmField();
QList<caf::PdmOptionItemInfo> options;
appendOptionItemsForSubCategoriesAndVectors( options, identifierAndField );
if ( !options.isEmpty() )
{
std::vector<QString> values;
auto firstOption = options.front();
auto firstValue = firstOption.value();
QString valueText = firstValue.toString();
values.push_back( valueText );
field->setValue( values );
}
}
}
}
}
}
size_t curveCount = allCurveDefinitionsFromSelection().size();
size_t curveSetCount = allCurveSetDefinitionsFromSelections().size();
if ( m_toggleChangedHandler != nullptr )
{
// Do nothing if the curve count and curve set count is identical
if ( !m_multiSelectionMode || ( curveCount != m_prevCurveCount || curveSetCount != m_prevCurveSetCount ) )
{
m_toggleChangedHandler();
m_prevCurveCount = curveCount;
m_prevCurveSetCount = curveSetCount;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo>
RiuSummaryVectorSelectionUi::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly )
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_selectedSources )
{
appendOptionItemsForSources( options );
}
else if ( fieldNeedingOptions == &m_selectedSummaryCategories )
{
appendOptionItemsForCategories( options );
}
else
{
// Lookup item type input field
auto identifierAndField = lookupIdentifierAndFieldFromFieldHandle( fieldNeedingOptions );
appendOptionItemsForSubCategoriesAndVectors( options, identifierAndField );
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
caf::PdmUiGroup* sourcesGroup =
uiOrdering.addNewGroupWithKeyword( "Sources", RiuSummaryCurveDefinitionKeywords::sources() );
sourcesGroup->add( &m_selectedSources );
caf::PdmUiGroup* itemTypesGroup =
uiOrdering.addNewGroupWithKeyword( "Summary Types", RiuSummaryCurveDefinitionKeywords::summaryTypes() );
itemTypesGroup->add( &m_selectedSummaryCategories );
caf::PdmField<std::vector<QString>>* summaryiesField = nullptr;
RifEclipseSummaryAddress::SummaryVarCategory sumCategory = m_currentSummaryCategory();
if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_INVALID )
{
sumCategory = RifEclipseSummaryAddress::SUMMARY_FIELD;
}
if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_FIELD )
{
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_FIELD][0]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_AQUIFER )
{
{
caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "Aquifers" );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_AQUIFER][0]->pdmField() );
}
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_AQUIFER][1]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_NETWORK )
{
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_NETWORK][0]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_MISC )
{
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_MISC][0]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_REGION )
{
{
caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "Regions" );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION][0]->pdmField() );
}
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION][1]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION )
{
{
caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "Regions" );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION][0]->pdmField() );
}
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_REGION_2_REGION][1]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_WELL_GROUP )
{
{
caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "Well Groups" );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_GROUP][0]->pdmField() );
}
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_GROUP][1]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_WELL )
{
{
caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "Wells" );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL][0]->pdmField() );
}
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL][1]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION )
{
{
caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "Completions" );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][0]->pdmField() );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][1]->pdmField() );
}
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION][2]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR )
{
{
caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "LGR Completions" );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][0]->pdmField() );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][1]->pdmField() );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][2]->pdmField() );
}
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_COMPLETION_LGR][3]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_WELL_LGR )
{
{
caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "LGR Wells" );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][0]->pdmField() );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][1]->pdmField() );
}
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_LGR][2]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT )
{
{
caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "Well Segments" );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][0]->pdmField() );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][1]->pdmField() );
}
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_WELL_SEGMENT][2]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_BLOCK )
{
{
caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "Blocks" );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK][0]->pdmField() );
}
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK][1]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR )
{
{
caf::PdmUiGroup* myGroup = uiOrdering.addNewGroup( "LGR Blocks" );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][0]->pdmField() );
myGroup->add( m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][1]->pdmField() );
}
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR][2]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
{
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_CALCULATED][0]->pdmField();
}
else if ( sumCategory == RifEclipseSummaryAddress::SUMMARY_IMPORTED )
{
summaryiesField = m_identifierFieldsMap[RifEclipseSummaryAddress::SUMMARY_IMPORTED][0]->pdmField();
}
caf::PdmUiGroup* summariesGroup =
uiOrdering.addNewGroupWithKeyword( "Summaries", RiuSummaryCurveDefinitionKeywords::summaries() );
if ( summaryiesField )
{
summariesGroup->add( summaryiesField );
}
uiOrdering.skipRemainingFields( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RiuSummaryVectorSelectionUi::findPossibleSummaryAddressesFromSelectedCases(
const SummaryIdentifierAndField* identifierAndField ) const
{
std::vector<SummarySource*> sources;
for ( const auto& source : m_selectedSources.value() )
{
RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>( source.p() );
RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>( source.p() );
if ( sumCase )
{
auto calculated = dynamic_cast<RimCalculatedSummaryCase*>( sumCase );
if ( !isObservedData( sumCase ) && !calculated )
{
sources.push_back( sumCase );
}
}
else if ( ensemble )
{
sources.push_back( ensemble );
}
}
return findPossibleSummaryAddresses( sources, identifierAndField );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RiuSummaryVectorSelectionUi::findPossibleSummaryAddressesFromSelectedObservedData(
const SummaryIdentifierAndField* identifierAndField ) const
{
std::vector<SummarySource*> obsData;
for ( const auto& source : m_selectedSources.value() )
{
RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>( source.p() );
if ( sumCase && isObservedData( sumCase ) )
{
obsData.push_back( sumCase );
}
}
return findPossibleSummaryAddresses( obsData, identifierAndField );
}
//--------------------------------------------------------------------------------------------------
/// Returns the summary addresses that match the selected item type and input selections made in GUI
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress>
RiuSummaryVectorSelectionUi::findPossibleSummaryAddresses( const std::vector<SummarySource*>& selectedSources,
const SummaryIdentifierAndField* identifierAndField ) const
{
std::set<RifEclipseSummaryAddress> addrUnion;
auto isVectorField = identifierAndField != nullptr &&
identifierAndField->summaryIdentifier() == RifEclipseSummaryAddress::INPUT_VECTOR_NAME;
auto controllingIdentifierAndField = identifierAndField != nullptr ? lookupControllingField( identifierAndField )
: nullptr;
if ( !isVectorField && controllingIdentifierAndField != nullptr &&
controllingIdentifierAndField->pdmField()->v().size() == 0 )
{
return addrUnion;
}
for ( SummarySource* currSource : selectedSources )
{
std::set<RifEclipseSummaryAddress> allAddresses;
RimSummaryCase* currCase = dynamic_cast<RimSummaryCase*>( currSource );
RimSummaryCaseCollection* currEnsemble = dynamic_cast<RimSummaryCaseCollection*>( currSource );
if ( currCase )
{
RifSummaryReaderInterface* reader = currCase->summaryReader();
if ( reader ) allAddresses = reader->allResultAddresses();
}
else if ( currEnsemble )
{
allAddresses = currEnsemble->ensembleSummaryAddresses();
}
bool applySelections = identifierAndField == nullptr ||
( !isVectorField && controllingIdentifierAndField != nullptr );
std::vector<SummaryIdentifierAndField*> controllingFields;
if ( applySelections )
{
// Build selections vector
controllingFields = buildControllingFieldList( identifierAndField );
}
for ( auto& address : allAddresses )
{
if ( address.category() == m_currentSummaryCategory() )
{
bool addressSelected = applySelections
? isAddressCompatibleWithControllingFieldSelection( address, controllingFields )
: true;
if ( addressSelected )
{
addrUnion.insert( address );
}
}
}
}
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;
}
//--------------------------------------------------------------------------------------------------
/// Build a list of relevant selections
//--------------------------------------------------------------------------------------------------
std::vector<SummaryIdentifierAndField*>
RiuSummaryVectorSelectionUi::buildControllingFieldList( const SummaryIdentifierAndField* identifierAndField ) const
{
std::vector<SummaryIdentifierAndField*> controllingFields;
const auto& identifierAndFieldList = m_identifierFieldsMap.at( m_currentSummaryCategory() );
for ( const auto& identifierAndFieldItem : identifierAndFieldList )
{
if ( identifierAndFieldItem == identifierAndField )
{
break;
}
controllingFields.push_back( identifierAndFieldItem );
}
return controllingFields;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
SummaryIdentifierAndField*
RiuSummaryVectorSelectionUi::lookupIdentifierAndFieldFromFieldHandle( const caf::PdmFieldHandle* pdmFieldHandle ) const
{
for ( const auto& itemTypes : m_identifierFieldsMap )
{
for ( const auto& itemTypeInput : itemTypes.second )
{
if ( pdmFieldHandle == itemTypeInput->pdmField() )
{
return itemTypeInput;
}
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
/// Returns the Controlling pdm field info for the specified pdm field info.
/// Controlling means the field controlling the dependent field
/// If the specified pdm field info is the topmost (i.e. index is 0), nullptr is returned
//--------------------------------------------------------------------------------------------------
SummaryIdentifierAndField*
RiuSummaryVectorSelectionUi::lookupControllingField( const SummaryIdentifierAndField* dependentField ) const
{
for ( const auto& identifierAndFieldList : m_identifierFieldsMap )
{
int index = 0;
for ( const auto& iaf : identifierAndFieldList.second )
{
if ( iaf == dependentField )
{
return index > 0 ? identifierAndFieldList.second[index - 1] : nullptr;
}
index++;
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuSummaryVectorSelectionUi::isAddressCompatibleWithControllingFieldSelection(
const RifEclipseSummaryAddress& address,
const std::vector<SummaryIdentifierAndField*>& identifierAndFieldList ) const
{
for ( const auto& identifierAndField : identifierAndFieldList )
{
bool match = false;
for ( const auto& selectedText : identifierAndField->pdmField()->v() )
{
if ( QString::compare( QString::fromStdString(
address.addressComponentUiText( identifierAndField->summaryIdentifier() ) ),
selectedText ) == 0 )
{
match = true;
break;
}
}
if ( !match )
{
return false;
}
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RiuSummaryVectorSelectionUi::buildAddressListFromSelections() const
{
std::set<RifEclipseSummaryAddress> addressSet;
for ( const auto& category : m_selectedSummaryCategories() )
{
if ( m_identifierFieldsMap.at( category ).size() == 0 ||
category == RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_INVALID )
continue;
const auto& identifierAndFieldList = m_identifierFieldsMap.at( category );
std::vector<std::pair<RifEclipseSummaryAddress::SummaryIdentifierType, QString>> selectionStack;
buildAddressListForCategoryRecursively( category, identifierAndFieldList.begin(), selectionStack, addressSet );
}
return addressSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::buildAddressListForCategoryRecursively(
RifEclipseSummaryAddress::SummaryVarCategory category,
std::vector<SummaryIdentifierAndField*>::const_iterator identifierAndFieldItr,
std::vector<std::pair<RifEclipseSummaryAddress::SummaryIdentifierType, QString>>& identifierPath,
std::set<RifEclipseSummaryAddress>& addressSet ) const
{
for ( const auto& identifierText : ( *identifierAndFieldItr )->pdmField()->v() )
{
auto idText = identifierText;
// Calculated results have a id appended. E.g. "Calculation_3 ( NORNE_ATW2013, WOPR:B-4H ):3"
if ( category == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
{
// Extract the calculation id
QStringList tokens = idText.split( ":" );
QString calculationId = tokens.last();
// Put the input vector name back together
tokens.pop_back();
idText = tokens.join( ":" );
identifierPath.push_back( std::make_pair( RifEclipseSummaryAddress::INPUT_ID, calculationId ) );
}
idText.remove( OBSERVED_DATA_AVALUE_POSTFIX );
identifierPath.push_back( std::make_pair( ( *identifierAndFieldItr )->summaryIdentifier(), idText ) );
if ( ( *identifierAndFieldItr )->summaryIdentifier() != RifEclipseSummaryAddress::INPUT_VECTOR_NAME )
{
buildAddressListForCategoryRecursively( category, std::next( identifierAndFieldItr, 1 ), identifierPath, addressSet );
}
else
{
std::map<RifEclipseSummaryAddress::SummaryIdentifierType, std::string> selectedIdentifiers;
for ( const auto& identifier : identifierPath )
{
selectedIdentifiers.insert( std::make_pair( identifier.first, identifier.second.toStdString() ) );
}
auto address = RifEclipseSummaryAddress( category, selectedIdentifiers );
addressSet.insert( address );
}
if ( !identifierPath.empty() )
{
identifierPath.pop_back();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute )
{
caf::PdmUiTreeSelectionEditorAttribute* attrib = dynamic_cast<caf::PdmUiTreeSelectionEditorAttribute*>( attribute );
if ( attrib )
{
if ( &m_selectedSummaryCategories == field )
{
attrib->currentIndexFieldHandle = &m_currentSummaryCategory;
attrib->showTextFilter = false;
attrib->showToggleAllCheckbox = false;
attrib->setCurrentIndexWhenItemIsChecked = true;
}
// All tree selection editors are set in specified selection mode
attrib->singleSelectionMode = !m_multiSelectionMode;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::resetAllFields()
{
m_selectedSources.clear();
m_previouslySelectedSources.clear();
m_selectedSummaryCategories = std::vector<caf::AppEnum<RifEclipseSummaryAddress::SummaryVarCategory>>();
// clear all state in fields
for ( auto& identifierAndFieldList : m_identifierFieldsMap )
{
for ( auto a : identifierAndFieldList.second )
{
a->pdmField()->v().clear();
}
}
m_prevCurveCount = 0;
m_prevCurveSetCount = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiuSummaryVectorSelectionUi::isObservedData( const RimSummaryCase* sumCase ) const
{
return dynamic_cast<const RimObservedSummaryData*>( sumCase ) != nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<SummarySource*> RiuSummaryVectorSelectionUi::selectedSummarySources() const
{
std::vector<SummarySource*> sources;
for ( const auto& source : m_selectedSources )
{
sources.push_back( source );
}
// Always add the summary case for calculated curves as this case is not displayed in UI
sources.push_back( RiuSummaryVectorSelectionUi::calculatedSummaryCase() );
return sources;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RiuSummaryVectorSelectionUi::calculatedSummaryCase()
{
RimSummaryCalculationCollection* calcColl = RimProject::current()->calculationCollection();
return calcColl->calculationSummaryCase();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::appendOptionItemsForSources( QList<caf::PdmOptionItemInfo>& options ) const
{
auto dataSourceOptions =
optionsForSummaryDataSource( m_hideSummaryCases, m_hideEnsembles, m_showIndividualEnsembleCases );
for ( auto& o : dataSourceOptions )
{
options.push_back( o );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::appendOptionItemsForCategories( QList<caf::PdmOptionItemInfo>& options ) const
{
std::vector<RifEclipseSummaryAddress::SummaryVarCategory> sortedCategoriesForUi;
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_FIELD );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_AQUIFER );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_NETWORK );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_MISC );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_REGION );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_REGION_2_REGION );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_GROUP );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_COMPLETION );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_SEGMENT );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_BLOCK );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_LGR );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL_COMPLETION_LGR );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_BLOCK_LGR );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_CALCULATED );
sortedCategoriesForUi.push_back( RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_IMPORTED );
// NB SUMMARY_ENSEMBLE_STATISTICS is intentionally excluded
// categoriesForUiDisplay.push_back(RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_ENSEMBLE_STATISTICS);
for ( auto category : sortedCategoriesForUi )
{
auto option = RiaOptionItemFactory::optionItemFromSummaryType( category );
options.push_back( option );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::appendOptionItemsForSubCategoriesAndVectors( QList<caf::PdmOptionItemInfo>& options,
SummaryIdentifierAndField* identifierAndField ) const
{
if ( identifierAndField == nullptr ) return;
enum
{
SUM_CASES,
OBS_DATA,
CALCULATED_CURVES
};
const int itemCount = CALCULATED_CURVES + 1;
std::set<RifEclipseSummaryAddress> addrUnion[itemCount];
addrUnion[SUM_CASES] = findPossibleSummaryAddressesFromSelectedCases( identifierAndField );
addrUnion[OBS_DATA] = findPossibleSummaryAddressesFromSelectedObservedData( identifierAndField );
addrUnion[CALCULATED_CURVES] = findPossibleSummaryAddressesFromCalculated();
std::set<std::string> itemNames[itemCount];
for ( int i = 0; i < itemCount; i++ )
{
for ( const auto& address : addrUnion[i] )
{
if ( address.isErrorResult() ) continue;
auto name = address.addressComponentUiText( identifierAndField->summaryIdentifier() );
if ( name.size() > 0 )
{
if ( i == CALCULATED_CURVES )
{
name += QString( ":%1" ).arg( address.id() ).toStdString();
}
itemNames[i].insert( name );
}
}
}
bool isVectorField = identifierAndField->summaryIdentifier() == RifEclipseSummaryAddress::INPUT_VECTOR_NAME;
// Merge sets for all other fields than vector fields
if ( !isVectorField )
{
itemNames[SUM_CASES].insert( itemNames[OBS_DATA].begin(), itemNames[OBS_DATA].end() );
itemNames[OBS_DATA].clear();
}
for ( int i = 0; i < itemCount; i++ )
{
// Create headers only for vector fields when observed data is selected
bool hasObservedData = itemNames[OBS_DATA].size() > 0;
bool groupItems = isVectorField && hasObservedData;
if ( groupItems )
{
QString headerText;
if ( i == SUM_CASES )
{
headerText = QString( "Simulated Data" );
}
else if ( i == OBS_DATA )
{
headerText = QString( "Observed Data" );
}
else if ( i == CALCULATED_CURVES )
{
headerText = QString( "Calculated" );
}
if ( !headerText.isEmpty() )
{
options.push_back( caf::PdmOptionItemInfo::createHeader( headerText, true ) );
}
}
auto itemPostfix = ( isVectorField && i == OBS_DATA ) ? QString( OBSERVED_DATA_AVALUE_POSTFIX ) : QString( "" );
// Sort numeric identifiers by numeric val
std::vector<std::string> itemNamesVector;
{
switch ( identifierAndField->summaryIdentifier() )
{
case RifEclipseSummaryAddress::INPUT_REGION_NUMBER:
case RifEclipseSummaryAddress::INPUT_SEGMENT_NUMBER:
case RifEclipseSummaryAddress::INPUT_AQUIFER_NUMBER:
{
std::set<int> values;
for ( const std::string& itemName : itemNames[i] )
{
values.insert( RiaStdStringTools::toInt( itemName ) );
}
for ( int v : values )
{
itemNamesVector.push_back( std::to_string( v ) );
}
break;
}
default:
itemNamesVector.insert( itemNamesVector.end(), itemNames[i].begin(), itemNames[i].end() );
break;
}
}
for ( const auto& itemName : itemNamesVector )
{
QString displayName;
if ( isVectorField )
{
std::string longVectorName =
RiuSummaryQuantityNameInfoProvider::instance()->longNameFromQuantityName( itemName );
if ( longVectorName.empty() )
{
displayName = QString::fromStdString( itemName );
}
else
{
displayName = QString::fromStdString( longVectorName );
displayName += QString( " (%1)" ).arg( QString::fromStdString( itemName ) );
}
}
else
{
displayName = QString::fromStdString( itemName );
}
auto optionItem = caf::PdmOptionItemInfo( displayName, QString::fromStdString( itemName ) + itemPostfix );
if ( groupItems ) optionItem.setLevel( 1 );
options.push_back( optionItem );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::handleAddedSource( SummarySource* sourceAdded )
{
CAF_ASSERT( sourceAdded );
auto caseCollection = dynamic_cast<RimSummaryCaseCollection*>( sourceAdded );
if ( caseCollection && m_showIndividualEnsembleCases )
{
// Select all children
for ( auto summaryCase : caseCollection->allSummaryCases() )
{
auto it = std::find( m_selectedSources.begin(), m_selectedSources.end(), summaryCase );
if ( it == m_selectedSources.end() )
{
m_selectedSources.push_back( summaryCase );
}
}
}
else
{
auto summaryCase = dynamic_cast<RimSummaryCase*>( sourceAdded );
if ( summaryCase )
{
auto caseCollection = summaryCase->ensemble();
if ( caseCollection )
{
auto it = std::find( m_selectedSources.begin(), m_selectedSources.end(), caseCollection );
if ( it == m_selectedSources.end() )
{
// Check if all children have been selected.
bool allChildrenSelected = true;
for ( auto summaryChild : caseCollection->allSummaryCases() )
{
auto it = std::find( m_selectedSources.begin(), m_selectedSources.end(), summaryChild );
if ( it == m_selectedSources.end() )
{
allChildrenSelected = false;
break;
}
}
if ( allChildrenSelected ) // Add collection if all children have been selected
{
m_selectedSources.push_back( caseCollection );
}
}
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuSummaryVectorSelectionUi::handleRemovedSource( SummarySource* sourceRemoved )
{
CAF_ASSERT( sourceRemoved );
auto caseCollection = dynamic_cast<RimSummaryCaseCollection*>( sourceRemoved );
if ( caseCollection )
{
// Select all children
for ( auto summaryCase : caseCollection->allSummaryCases() )
{
auto it = std::find( m_selectedSources.begin(), m_selectedSources.end(), summaryCase );
if ( it != m_selectedSources.end() )
{
m_selectedSources.removePtr( *it );
}
}
}
else
{
auto summaryCase = dynamic_cast<RimSummaryCase*>( sourceRemoved );
if ( summaryCase )
{
auto caseCollection = summaryCase->ensemble();
if ( caseCollection )
{
auto it = std::find( m_selectedSources.begin(), m_selectedSources.end(), caseCollection );
if ( it != m_selectedSources.end() )
{
m_selectedSources.removePtr( *it );
}
}
}
}
}