From 15ce1f75aa3928a1deee12c92f291f18a624974c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Thu, 24 Jul 2025 09:18:28 +0200 Subject: [PATCH] #12604 Add appearance settings for ensemble curve sets Introduces customizable appearance settings for curve sets in RFT plots, including color, line style, and symbols. --- ApplicationLibCode/CMakeLists.txt | 1 + .../Appearance/CMakeLists_files.cmake | 12 + .../Appearance/RimCurveAppearanceDefines.cpp | 38 ++ .../Appearance/RimCurveAppearanceDefines.h | 33 ++ .../Appearance/RimCurveSetAppearance.cpp | 340 ++++++++++++++++++ .../Appearance/RimCurveSetAppearance.h | 97 +++++ .../Flow/RimWellRftEnsembleCurveSet.cpp | 158 +++----- .../Flow/RimWellRftEnsembleCurveSet.h | 49 +-- .../ProjectDataModel/Flow/RimWellRftPlot.cpp | 160 ++++++--- .../ProjectDataModel/Flow/RimWellRftPlot.h | 16 +- .../Summary/RimEnsembleCurveFilter.cpp | 4 +- .../Summary/RimEnsembleCurveSet.cpp | 32 +- .../Summary/RimEnsembleCurveSet.h | 43 +-- .../RimEnsembleCurveSetColorManager.cpp | 5 + .../WellLog/RimWellLogRftCurve.cpp | 1 + 15 files changed, 733 insertions(+), 256 deletions(-) create mode 100644 ApplicationLibCode/ProjectDataModel/Appearance/CMakeLists_files.cmake create mode 100644 ApplicationLibCode/ProjectDataModel/Appearance/RimCurveAppearanceDefines.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/Appearance/RimCurveAppearanceDefines.h create mode 100644 ApplicationLibCode/ProjectDataModel/Appearance/RimCurveSetAppearance.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/Appearance/RimCurveSetAppearance.h diff --git a/ApplicationLibCode/CMakeLists.txt b/ApplicationLibCode/CMakeLists.txt index 5a733bc6e9..d06af48c33 100644 --- a/ApplicationLibCode/CMakeLists.txt +++ b/ApplicationLibCode/CMakeLists.txt @@ -99,6 +99,7 @@ list( FileInterface/CMakeLists_files.cmake ProjectDataModel/CMakeLists_files.cmake ProjectDataModel/AnalysisPlots/CMakeLists_files.cmake + ProjectDataModel/Appearance/CMakeLists_files.cmake ProjectDataModel/CorrelationPlots/CMakeLists_files.cmake ProjectDataModel/ContourMap/CMakeLists_files.cmake ProjectDataModel/Cloud/CMakeLists_files.cmake diff --git a/ApplicationLibCode/ProjectDataModel/Appearance/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/Appearance/CMakeLists_files.cmake new file mode 100644 index 0000000000..1c6d7d3e32 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Appearance/CMakeLists_files.cmake @@ -0,0 +1,12 @@ +set(SOURCE_GROUP_HEADER_FILES + ${CMAKE_CURRENT_LIST_DIR}/RimCurveSetAppearance.h + ${CMAKE_CURRENT_LIST_DIR}/RimCurveAppearanceDefines.h +) + +set(SOURCE_GROUP_SOURCE_FILES + ${CMAKE_CURRENT_LIST_DIR}/RimCurveSetAppearance.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimCurveAppearanceDefines.cpp +) + +list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) +list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES}) diff --git a/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveAppearanceDefines.cpp b/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveAppearanceDefines.cpp new file mode 100644 index 0000000000..ef4290b6eb --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveAppearanceDefines.cpp @@ -0,0 +1,38 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2025- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimCurveAppearanceDefines.h" +#include "cafAppEnum.h" + +namespace caf +{ +template <> +void AppEnum::setUp() +{ + addItem( RimCurveAppearanceDefines::ParameterSorting::ABSOLUTE_VALUE, "ABSOLUTE_VALUE", "Absolute Correlation" ); + addItem( RimCurveAppearanceDefines::ParameterSorting::ALPHABETICALLY, "ALPHABETICALLY", "Alphabetically" ); + setDefault( RimCurveAppearanceDefines::ParameterSorting::ABSOLUTE_VALUE ); +} +template <> +void AppEnum::setUp() +{ + addItem( RimCurveAppearanceDefines::AppearanceMode::DEFAULT, "DEFAULT", "Default" ); + addItem( RimCurveAppearanceDefines::AppearanceMode::CUSTOM, "CUSTOM", "Custom" ); + setDefault( RimCurveAppearanceDefines::AppearanceMode::DEFAULT ); +} +} // namespace caf diff --git a/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveAppearanceDefines.h b/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveAppearanceDefines.h new file mode 100644 index 0000000000..b597fbb598 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveAppearanceDefines.h @@ -0,0 +1,33 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2025- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// +#pragma once + +namespace RimCurveAppearanceDefines +{ +enum class ParameterSorting +{ + ABSOLUTE_VALUE, + ALPHABETICALLY +}; + +enum class AppearanceMode +{ + DEFAULT, + CUSTOM +}; +} // namespace RimCurveAppearanceDefines diff --git a/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveSetAppearance.cpp b/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveSetAppearance.cpp new file mode 100644 index 0000000000..c4e34f7874 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveSetAppearance.cpp @@ -0,0 +1,340 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2025- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimCurveSetAppearance.h" + +#include "RiaColorTools.h" + +#include "RimSummaryEnsemble.h" + +#include "RiuGuiTheme.h" + +#include "cafPdmFieldCvfColor.h" +#include "cafPdmUiDoubleSliderEditor.h" +#include "cafPdmUiTreeOrdering.h" +#include "cafPdmUiTreeSelectionEditor.h" + +CAF_PDM_SOURCE_INIT( RimCurveSetAppearance, "RimCurveSetAppearance" ); + +namespace internal +{ +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector parametersWithVariation( RimSummaryEnsemble* ensemble ) +{ + if ( !ensemble ) return {}; + + auto parameters = ensemble->variationSortedEnsembleParameters( true ); + + std::vector names; + for ( const auto& param : parameters ) + { + names.emplace_back( param.name ); + } + return names; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector sortedParameters( RimSummaryEnsemble* ensemble, RimCurveAppearanceDefines::ParameterSorting sorting ) +{ + auto params = internal::parametersWithVariation( ensemble ); + + if ( sorting == RimCurveAppearanceDefines::ParameterSorting::ALPHABETICALLY ) + { + std::sort( params.begin(), params.end() ); + } + + return params; +} + +} // namespace internal + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimCurveSetAppearance::RimCurveSetAppearance() + : appearanceChanged( this ) +{ + CAF_PDM_InitObject( "Curve Set Appearance" ); + + CAF_PDM_InitField( &m_colorMode, "ColorMode", caf::AppEnum( ColorMode::SINGLE_COLOR_WITH_ALPHA ), "Coloring Mode" ); + + CAF_PDM_InitField( &m_colorForRealizations, "Color", RiaColorTools::textColor3f(), "Color" ); + CAF_PDM_InitField( &m_mainEnsembleColor, "MainEnsembleColor", RiaColorTools::textColor3f(), "Color" ); + CAF_PDM_InitField( &m_colorTransparency, "ColorTransparency", 0.3, "Transparency" ); + m_colorTransparency.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() ); + + CAF_PDM_InitField( &m_ensembleParameter, "EnsembleParameter", QString( "" ), "Parameter" ); + m_ensembleParameter.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); + + CAF_PDM_InitFieldNoDefault( &m_ensembleParameterSorting, "EnsembleParameterSorting", "Parameter Sorting" ); + + auto defaultLineStyle = LineStyle( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_NONE ); + auto defaultPointSymbol = PointSymbol( RiuPlotCurveSymbol::PointSymbolEnum::SYMBOL_CROSS ); + + CAF_PDM_InitFieldNoDefault( &m_useCustomAppearance, "UseCustomAppearance", "Appearance" ); + CAF_PDM_InitField( &m_lineStyle, "LineStyle", defaultLineStyle, "Line Style" ); + CAF_PDM_InitField( &m_pointSymbol, "PointSymbol", defaultPointSymbol, "Symbol" ); + CAF_PDM_InitField( &m_symbolSize, "SymbolSize", 6, "Symbol Size" ); + + auto defaultStatisticsPointSymbol = PointSymbol( RiuPlotCurveSymbol::PointSymbolEnum::SYMBOL_ELLIPSE ); + CAF_PDM_InitFieldNoDefault( &m_statisticsUseCustomAppearance, "StatisticsUseCustomAppearance", "Appearance" ); + CAF_PDM_InitField( &m_statisticsLineStyle, "StatisticsLineStyle", defaultLineStyle, "Line Style" ); + CAF_PDM_InitField( &m_statisticsPointSymbol, "StatisticsPointSymbol", defaultStatisticsPointSymbol, "Symbol" ); + CAF_PDM_InitField( &m_statisticsSymbolSize, "StatisticsSymbolSize", 6, "Symbol Size" ); + + CAF_PDM_InitFieldNoDefault( &m_ensemble, "SummaryEnsemble", "Ensemble" ); + + CAF_PDM_InitFieldNoDefault( &m_ensembleLegendConfig, "LegendConfig", "" ); + m_ensembleLegendConfig = new RimRegularLegendConfig(); + m_ensembleLegendConfig->setColorLegend( + RimRegularLegendConfig::mapToColorLegend( RimEnsembleCurveSetColorManager::DEFAULT_ENSEMBLE_COLOR_RANGE ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Color3f RimCurveSetAppearance::curveColor( const RimSummaryEnsemble* ensemble, const RimSummaryCase* summaryCase ) const +{ + if ( m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::BY_ENSEMBLE_PARAM ) + { + if ( !ensemble || !summaryCase ) return cvf::Color3f( 0.0, 0.0, 0.0 ); + auto ensembleParam = ensemble->ensembleParameter( m_ensembleParameter() ); + return RimEnsembleCurveSetColorManager::caseColor( m_ensembleLegendConfig, summaryCase, ensembleParam ); + } + + return m_colorForRealizations(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Color3f RimCurveSetAppearance::statisticsCurveColor() const +{ + return m_mainEnsembleColor(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCurveSetAppearance::setColorMode( ColorModeEnum colorMode ) +{ + m_colorMode = colorMode; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCurveSetAppearance::setEnsembleParameter( const QString& ensembleParameter ) +{ + m_ensembleParameter = ensembleParameter; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimRegularLegendConfig* RimCurveSetAppearance::legendConfig() const +{ + if ( m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR || + m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR_WITH_ALPHA ) + { + return nullptr; + } + + if ( !m_ensembleLegendConfig->showLegend() ) return nullptr; + + updateEnsembleParameterLegend( m_ensembleLegendConfig ); + + return m_ensembleLegendConfig(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCurveSetAppearance::setMainEnsembleColor( const cvf::Color3f& color ) +{ + m_mainEnsembleColor = color; + + updateRealizationColor(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCurveSetAppearance::setEnsemble( RimSummaryEnsemble* ensemble ) +{ + m_ensemble = ensemble; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCurveSetAppearance::setShowLineStyleAndSymbols( bool showLineStyleAndSymbols ) +{ + m_showLineStyleAndSymbols = showLineStyleAndSymbols; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCurveSetAppearance::updateEnsembleParameterLegend( RimRegularLegendConfig* legendConfig ) const +{ + if ( !m_ensemble || !legendConfig ) return; + + auto ensembleParam = m_ensemble->ensembleParameter( m_ensembleParameter ); + legendConfig->setTitle( m_ensemble->name() + "\n" + m_ensembleParameter ); + RimEnsembleCurveSetColorManager::initializeLegendConfig( legendConfig, ensembleParam ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCurveSetAppearance::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) +{ + if ( changedField == &m_colorMode || changedField == &m_colorTransparency || changedField == &m_mainEnsembleColor ) + { + updateRealizationColor(); + } + + if ( ( changedField == &m_colorMode ) && ( m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::BY_ENSEMBLE_PARAM ) && + m_ensembleParameter().isEmpty() ) + { + auto params = internal::sortedParameters( m_ensemble, m_ensembleParameterSorting() ); + if ( !params.empty() ) + { + m_ensembleParameter = params.front(); + } + } + + if ( changedField == &m_colorMode || changedField == &m_ensembleParameter || changedField == &m_ensembleParameterSorting ) + { + updateEnsembleParameterLegend( m_ensembleLegendConfig ); + } + + appearanceChanged.send(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCurveSetAppearance::updateRealizationColor() +{ + if ( m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR_WITH_ALPHA ) + { + auto backgroundColor = RiuGuiTheme::getColorByVariableName( "backgroundColor1" ); + + auto sourceColor = RiaColorTools::toQColor( m_mainEnsembleColor ); + auto sourceWeight = 100; + int backgroundWeight = std::max( 1, static_cast( sourceWeight * 10 * m_colorTransparency ) ); + auto blendedColor = RiaColorTools::blendQColors( backgroundColor, sourceColor, backgroundWeight, sourceWeight ); + + m_colorForRealizations = RiaColorTools::fromQColorTo3f( blendedColor ); + } + else + { + m_colorForRealizations = m_mainEnsembleColor(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCurveSetAppearance::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + uiOrdering.add( &m_colorMode ); + + if ( m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR ) + { + uiOrdering.add( &m_mainEnsembleColor ); + } + else if ( m_colorMode() == RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR_WITH_ALPHA ) + { + uiOrdering.add( &m_mainEnsembleColor ); + uiOrdering.add( &m_colorTransparency ); + } + else if ( m_colorMode == ColorMode::BY_ENSEMBLE_PARAM ) + { + uiOrdering.add( &m_ensembleParameterSorting ); + uiOrdering.add( &m_ensembleParameter ); + } + + if ( m_showLineStyleAndSymbols ) + { + uiOrdering.add( &m_useCustomAppearance ); + if ( m_useCustomAppearance() == RimCurveAppearanceDefines::AppearanceMode::CUSTOM ) + { + uiOrdering.add( &m_lineStyle ); + uiOrdering.add( &m_pointSymbol ); + uiOrdering.add( &m_symbolSize ); + } + + uiOrdering.add( &m_statisticsUseCustomAppearance ); + if ( m_statisticsUseCustomAppearance() == RimCurveAppearanceDefines::AppearanceMode::CUSTOM ) + { + uiOrdering.add( &m_statisticsLineStyle ); + uiOrdering.add( &m_statisticsPointSymbol ); + uiOrdering.add( &m_statisticsSymbolSize ); + } + } + + uiOrdering.skipRemainingFields(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimCurveSetAppearance::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= "" */ ) +{ + if ( m_colorMode == ColorMode::BY_ENSEMBLE_PARAM ) + { + uiTreeOrdering.add( m_ensembleLegendConfig() ); + } + uiTreeOrdering.skipRemainingChildren(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QList RimCurveSetAppearance::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) +{ + QList options; + + if ( fieldNeedingOptions == &m_ensembleParameter ) + { + auto params = internal::sortedParameters( m_ensemble, m_ensembleParameterSorting() ); + for ( const auto& param : params ) + { + options.push_back( caf::PdmOptionItemInfo( param, param ) ); + } + } + else if ( fieldNeedingOptions == &m_colorMode ) + { + auto singleColorOption = ColorModeEnum( ColorMode::SINGLE_COLOR ); + auto singleColorWithAlphaOption = ColorModeEnum( ColorMode::SINGLE_COLOR_WITH_ALPHA ); + auto byEnsParamOption = ColorModeEnum( ColorMode::BY_ENSEMBLE_PARAM ); + + options.push_back( caf::PdmOptionItemInfo( singleColorOption.uiText(), ColorMode::SINGLE_COLOR ) ); + options.push_back( caf::PdmOptionItemInfo( singleColorWithAlphaOption.uiText(), ColorMode::SINGLE_COLOR_WITH_ALPHA ) ); + options.push_back( caf::PdmOptionItemInfo( byEnsParamOption.uiText(), ColorMode::BY_ENSEMBLE_PARAM ) ); + } + + return options; +} diff --git a/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveSetAppearance.h b/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveSetAppearance.h new file mode 100644 index 0000000000..f54270cf4b --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/Appearance/RimCurveSetAppearance.h @@ -0,0 +1,97 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2025- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimCurveAppearanceDefines.h" +#include "RimEnsembleCurveSetColorManager.h" + +#include "RiuPlotCurveSymbol.h" +#include "RiuQwtPlotCurveDefines.h" + +#include "cafPdmObject.h" + +#include "cvfColor3.h" + +class RimRegularLegendConfig; +class RimSummaryEnsemble; +class RimSummaryCase; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimCurveSetAppearance : public caf::PdmObject +{ + CAF_PDM_HEADER_INIT; + +public: + using ColorMode = RimEnsembleCurveSetColorManager::ColorMode; + using ColorModeEnum = RimEnsembleCurveSetColorManager::ColorModeEnum; + using LineStyle = caf::AppEnum; + using PointSymbol = caf::AppEnum; + + caf::Signal<> appearanceChanged; + +public: + RimCurveSetAppearance(); + + void setMainEnsembleColor( const cvf::Color3f& color ); + void setEnsemble( RimSummaryEnsemble* ensemble ); + + void setShowLineStyleAndSymbols( bool showCustomAppearance ); + + cvf::Color3f curveColor( const RimSummaryEnsemble* ensemble, const RimSummaryCase* summaryCase ) const; + cvf::Color3f statisticsCurveColor() const; + + void setColorMode( ColorModeEnum colorMode ); + void setEnsembleParameter( const QString& ensembleParameter ); + RimRegularLegendConfig* legendConfig() const; + +private: + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override; + void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; + QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; + + void updateRealizationColor(); + void updateEnsembleParameterLegend( RimRegularLegendConfig* legendConfig ) const; + +private: + caf::PdmField m_colorMode; + caf::PdmField m_mainEnsembleColor; + caf::PdmField m_colorForRealizations; + caf::PdmField m_colorTransparency; + caf::PdmField m_ensembleParameter; + caf::PdmField> m_ensembleParameterSorting; + + caf::PdmField> m_useCustomAppearance; + caf::PdmField m_lineStyle; + caf::PdmField m_pointSymbol; + caf::PdmField m_symbolSize; + + caf::PdmField> m_statisticsUseCustomAppearance; + caf::PdmField m_statisticsLineStyle; + caf::PdmField m_statisticsPointSymbol; + caf::PdmField m_statisticsSymbolSize; + + caf::PdmPtrField m_ensemble; + caf::PdmChildField m_ensembleLegendConfig; + + bool m_showLineStyleAndSymbols = false; +}; diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftEnsembleCurveSet.cpp b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftEnsembleCurveSet.cpp index 9aecd5ebaa..be5e35b696 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftEnsembleCurveSet.cpp +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftEnsembleCurveSet.cpp @@ -20,21 +20,17 @@ #include "RifReaderEnsembleStatisticsRft.h" +#include "Appearance/RimCurveSetAppearance.h" #include "RimEclipseCase.h" -#include "RimEnsembleCurveSetColorManager.h" +#include "RimProject.h" #include "RimRegularLegendConfig.h" #include "RimSummaryCase.h" #include "RimSummaryEnsemble.h" #include "RimTools.h" #include "RimWellRftPlot.h" -#include "RiuQwtPlotWidget.h" - #include "cafPdmUiObjectHandle.h" #include "cafPdmUiTreeOrdering.h" -#include "cafPdmUiTreeSelectionEditor.h" - -#include CAF_PDM_SOURCE_INIT( RimWellRftEnsembleCurveSet, "WellRftEnsembleCurveSet" ); @@ -53,18 +49,24 @@ RimWellRftEnsembleCurveSet::RimWellRftEnsembleCurveSet() m_ensembleName.uiCapability()->setUiHidden( true ); m_ensembleName.xmlCapability()->disableIO(); - CAF_PDM_InitField( &m_ensembleColorMode, "ColorMode", ColorModeEnum( ColorMode::SINGLE_COLOR ), "Coloring Mode" ); - - CAF_PDM_InitField( &m_ensembleParameter, "EnsembleParameter", QString( "" ), "Ensemble Parameter" ); - m_ensembleParameter.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() ); - - CAF_PDM_InitFieldNoDefault( &m_ensembleLegendConfig, "LegendConfig", "" ); - m_ensembleLegendConfig = new RimRegularLegendConfig(); - m_ensembleLegendConfig->setColorLegend( - RimRegularLegendConfig::mapToColorLegend( RimEnsembleCurveSetColorManager::DEFAULT_ENSEMBLE_COLOR_RANGE ) ); - CAF_PDM_InitFieldNoDefault( &m_eclipseCase, "EclipseResultCase", "Eclipse Result Case" ); m_eclipseCase.uiCapability()->setUiHidden( true ); + + CAF_PDM_InitFieldNoDefault( &m_appearance, "Appearance", "Appearance" ); + m_appearance = new RimCurveSetAppearance(); + m_appearance.uiCapability()->setUiTreeHidden( true ); + m_appearance->appearanceChanged.connect( this, &RimWellRftEnsembleCurveSet::updatePlot ); + + CAF_PDM_InitField( &m_ensembleColorMode_OBSOLETE, + "ColorMode", + RimEnsembleCurveSetColorManager::ColorModeEnum( RimEnsembleCurveSetColorManager::ColorMode::SINGLE_COLOR ), + "Coloring Mode" ); + m_ensembleColorMode_OBSOLETE.uiCapability()->setUiHidden( true ); + m_ensembleColorMode_OBSOLETE.xmlCapability()->setIOWritable( false ); + + CAF_PDM_InitField( &m_ensembleParameter_OBSOLETE, "EnsembleParameter", QString( "" ), "Ensemble Parameter" ); + m_ensembleParameter_OBSOLETE.uiCapability()->setUiHidden( true ); + m_ensembleParameter_OBSOLETE.xmlCapability()->setIOWritable( false ); } //-------------------------------------------------------------------------------------------------- @@ -89,76 +91,41 @@ void RimWellRftEnsembleCurveSet::setEnsemble( RimSummaryEnsemble* ensemble ) { m_ensemble = ensemble; + m_appearance->setEnsemble( ensemble ); + clearEnsembleStatistics(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimEnsembleCurveSetColorManager::ColorMode RimWellRftEnsembleCurveSet::colorMode() const +void RimWellRftEnsembleCurveSet::setCurveColor( const cvf::Color3f& color ) { - return m_ensembleColorMode(); + m_appearance->setMainEnsembleColor( color ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellRftEnsembleCurveSet::setColorMode( ColorMode mode ) +cvf::Color3f RimWellRftEnsembleCurveSet::curveColor( RimSummaryEnsemble* ensemble, const RimSummaryCase* summaryCase ) const { - m_ensembleColorMode = mode; + if ( !summaryCase ) return m_appearance->statisticsCurveColor(); + + return m_appearance->curveColor( ensemble, summaryCase ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimWellRftEnsembleCurveSet::initializeLegend() +void RimWellRftEnsembleCurveSet::updatePlot( const SignalEmitter* emitter ) { - auto ensembleParam = m_ensemble->ensembleParameter( m_ensembleParameter ); - m_ensembleLegendConfig->setTitle( m_ensemble->name() + "\n" + m_ensembleParameter ); - RimEnsembleCurveSetColorManager::initializeLegendConfig( m_ensembleLegendConfig, ensembleParam ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -cvf::Color3f RimWellRftEnsembleCurveSet::caseColor( const RimSummaryCase* summaryCase ) const -{ - auto ensembleParam = m_ensemble->ensembleParameter( m_ensembleParameter ); - return RimEnsembleCurveSetColorManager::caseColor( m_ensembleLegendConfig, summaryCase, ensembleParam ); -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QString RimWellRftEnsembleCurveSet::currentEnsembleParameter() const -{ - return m_ensembleParameter; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void RimWellRftEnsembleCurveSet::setEnsembleParameter( const QString& parameterName ) -{ - m_ensembleParameter = parameterName; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -std::vector RimWellRftEnsembleCurveSet::parametersWithVariation() const -{ - std::set paramSet; - RimSummaryEnsemble* group = m_ensemble; - if ( group ) + if ( RimWellRftPlot* rftPlot = firstAncestorOrThisOfType() ) { - auto parameters = group->variationSortedEnsembleParameters( true ); - for ( const auto& param : parameters ) - { - paramSet.insert( param.name ); - } + rftPlot->rebuildCurves(); } - return std::vector( paramSet.begin(), paramSet.end() ); + + // Required to update the color legend object, as this object is only present in the Project Tree when ensemble parameter is used + updateConnectedEditors(); } //-------------------------------------------------------------------------------------------------- @@ -174,6 +141,12 @@ void RimWellRftEnsembleCurveSet::clearEnsembleStatistics() //-------------------------------------------------------------------------------------------------- void RimWellRftEnsembleCurveSet::initAfterRead() { + if ( RimProject::current()->isProjectFileVersionEqualOrOlderThan( "2025.04" ) ) + { + m_appearance->setColorMode( m_ensembleColorMode_OBSOLETE() ); + m_appearance->setEnsembleParameter( m_ensembleParameter_OBSOLETE() ); + } + clearEnsembleStatistics(); } @@ -182,26 +155,7 @@ void RimWellRftEnsembleCurveSet::initAfterRead() //-------------------------------------------------------------------------------------------------- RimRegularLegendConfig* RimWellRftEnsembleCurveSet::legendConfig() { - return m_ensembleLegendConfig; -} - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RigEnsembleParameter::Type RimWellRftEnsembleCurveSet::currentEnsembleParameterType() const -{ - if ( m_ensembleColorMode() == ColorMode::BY_ENSEMBLE_PARAM ) - { - RimSummaryEnsemble* group = m_ensemble(); - QString parameterName = m_ensembleParameter(); - - if ( group && !parameterName.isEmpty() ) - { - auto eParam = group->ensembleParameter( parameterName ); - return eParam.type; - } - } - return RigEnsembleParameter::TYPE_NONE; + return m_appearance->legendConfig(); } //-------------------------------------------------------------------------------------------------- @@ -234,13 +188,7 @@ RifReaderRftInterface* RimWellRftEnsembleCurveSet::statisticsEclipseRftReader() //-------------------------------------------------------------------------------------------------- void RimWellRftEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) { - if ( changedField == &m_ensembleColorMode || changedField == &m_ensembleParameter ) - { - RimWellRftPlot* rftPlot = firstAncestorOrThisOfTypeAsserted(); - rftPlot->syncCurvesFromUiSelection(); - rftPlot->updateConnectedEditors(); - } - else if ( changedField == &m_eclipseCase ) + if ( changedField == &m_eclipseCase ) { clearEnsembleStatistics(); } @@ -252,14 +200,7 @@ void RimWellRftEnsembleCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* ch QList RimWellRftEnsembleCurveSet::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) { QList options; - if ( fieldNeedingOptions == &m_ensembleParameter ) - { - for ( const QString& param : parametersWithVariation() ) - { - options.push_back( caf::PdmOptionItemInfo( param, param ) ); - } - } - else if ( fieldNeedingOptions == &m_eclipseCase ) + if ( fieldNeedingOptions == &m_eclipseCase ) { RimTools::caseOptionItems( &options ); @@ -273,16 +214,11 @@ QList RimWellRftEnsembleCurveSet::calculateValueOptions( //-------------------------------------------------------------------------------------------------- void RimWellRftEnsembleCurveSet::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { - caf::PdmUiGroup* colorsGroup = uiOrdering.addNewGroup( "Ensemble Curve Colors" ); - colorsGroup->add( &m_ensembleColorMode ); - - if ( m_ensembleColorMode == ColorMode::BY_ENSEMBLE_PARAM ) - { - colorsGroup->add( &m_ensembleParameter ); - } - uiOrdering.add( &m_eclipseCase ); + auto group = uiOrdering.addNewGroup( "Appearance" ); + m_appearance->uiOrdering( uiConfigName, *group ); + uiOrdering.skipRemainingFields( true ); } @@ -291,11 +227,11 @@ void RimWellRftEnsembleCurveSet::defineUiOrdering( QString uiConfigName, caf::Pd //-------------------------------------------------------------------------------------------------- void RimWellRftEnsembleCurveSet::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= "" */ ) { - if ( m_ensembleColorMode == ColorMode::BY_ENSEMBLE_PARAM && !m_ensembleParameter().isEmpty() ) + if ( auto legendConfig = m_appearance->legendConfig() ) { - uiTreeOrdering.add( m_ensembleLegendConfig() ); + uiTreeOrdering.add( legendConfig ); } - uiTreeOrdering.skipRemainingChildren( true ); + uiTreeOrdering.skipRemainingChildren(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftEnsembleCurveSet.h b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftEnsembleCurveSet.h index d45720d320..c1c049c0b6 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftEnsembleCurveSet.h +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftEnsembleCurveSet.h @@ -20,45 +20,37 @@ #include "RimEnsembleCurveSetColorManager.h" -#include "RigEnsembleParameter.h" - #include "cafPdmChildField.h" #include "cafPdmObject.h" #include "cafPdmProxyValueField.h" #include "cafPdmPtrField.h" #include "cvfColor3.h" -#include - class RiuCvfOverlayItemWidget; class RimSummaryEnsemble; class RimEclipseCase; class RifReaderEnsembleStatisticsRft; class RifReaderRftInterface; +class RimCurveSetAppearance; +class RimSummaryCase; +class RimRegularLegendConfig; class RimWellRftEnsembleCurveSet : public caf::PdmObject { CAF_PDM_HEADER_INIT; -public: - using ColorMode = RimEnsembleCurveSetColorManager::ColorMode; - using ColorModeEnum = RimEnsembleCurveSetColorManager::ColorModeEnum; - public: RimWellRftEnsembleCurveSet(); ~RimWellRftEnsembleCurveSet() override; - RimSummaryEnsemble* ensemble() const; void setEnsemble( RimSummaryEnsemble* ensemble ); - ColorMode colorMode() const; - void setColorMode( ColorMode mode ); - void initializeLegend(); - cvf::Color3f caseColor( const RimSummaryCase* summaryCase ) const; - QString currentEnsembleParameter() const; + RimSummaryEnsemble* ensemble() const; + QString ensembleName() const; - void setEnsembleParameter( const QString& parameterName ); - RimRegularLegendConfig* legendConfig(); - RigEnsembleParameter::Type currentEnsembleParameterType() const; + void setCurveColor( const cvf::Color3f& color ); + cvf::Color3f curveColor( RimSummaryEnsemble* ensemble, const RimSummaryCase* summaryCase ) const; + + RimRegularLegendConfig* legendConfig(); void setEclipseCase( RimEclipseCase* eclipseCase ); RimEclipseCase* eclipseCase() const; @@ -66,7 +58,7 @@ public: RifReaderRftInterface* statisticsEclipseRftReader(); void clearEnsembleStatistics(); -protected: +private: void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; @@ -74,21 +66,18 @@ protected: void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override; caf::PdmFieldHandle* userDescriptionField() override; + void initAfterRead() override; + + void updatePlot( const SignalEmitter* emitter ); private: - QString ensembleName() const; - std::vector parametersWithVariation() const; - -private: - caf::PdmPtrField m_eclipseCase; - caf::PdmPtrField m_ensemble; - caf::PdmProxyValueField m_ensembleName; - caf::PdmField m_ensembleColorMode; - caf::PdmField m_ensembleParameter; - caf::PdmChildField m_ensembleLegendConfig; + caf::PdmPtrField m_eclipseCase; + caf::PdmPtrField m_ensemble; + caf::PdmProxyValueField m_ensembleName; + caf::PdmChildField m_appearance; std::unique_ptr m_statisticsEclipseRftReader; -protected: - void initAfterRead() override; + caf::PdmField m_ensembleColorMode_OBSOLETE; + caf::PdmField m_ensembleParameter_OBSOLETE; }; diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp index 3f23be0736..5460b340b9 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.cpp @@ -21,6 +21,7 @@ #include "RiaColorTables.h" #include "RiaColorTools.h" #include "RiaPlotDefines.h" +#include "RiaQDateTimeTools.h" #include "RiaSimWellBranchTools.h" #include "Summary/RiaSummaryTools.h" @@ -57,6 +58,7 @@ #include "RiuAbstractLegendFrame.h" #include "RiuDraggableOverlayFrame.h" +#include "RiuPlotCurve.h" #include "RiuQwtPlotCurveDefines.h" #include "RiuQwtPlotWidget.h" @@ -520,12 +522,17 @@ void RimWellRftPlot::updateCurvesInPlot( const std::set( plotByIndex( 0 ) ); if ( !plotTrack ) return; + if ( plotTrack->plotWidget() ) + { + detachAndDeleteLegendCurves(); + } + // Delete curves plotTrack->deleteAllCurves(); defineCurveColorsAndSymbols( allCurveDefs ); - std::set ensemblesWithSummaryCurves; + std::set> curveSetsForLegend; // Add new curves for ( const RiaRftPltCurveDefinition& curveDefToAdd : allCurveDefs ) @@ -589,7 +596,12 @@ void RimWellRftPlot::updateCurvesInPlot( const std::seteclipseCase(); + if ( curveSet ) + { + eclipeCase = curveSet->eclipseCase(); + + curveSetsForLegend.insert( { curveSet, curveDefToAdd.timeStep() } ); + } } curve->setEclipseCase( eclipeCase ); @@ -604,9 +616,7 @@ void RimWellRftPlot::updateCurvesInPlot( const std::setsetShowInLegend( isFirstSummaryCurveInEnsemble ); - ensemblesWithSummaryCurves.insert( curveDefToAdd.address().ensemble() ); + curve->setShowInLegend( false ); } } else if ( m_showStatisticsCurves && curveDefToAdd.address().sourceType() == RifDataSourceForRftPlt::SourceType::ENSEMBLE_RFT ) @@ -638,18 +648,16 @@ void RimWellRftPlot::updateCurvesInPlot( const std::setsetObservedFmuRftData( findObservedFmuData( m_wellPathNameOrSimWellName, curveDefToAdd.timeStep() ) ); curve->setZOrder( RiuQwtPlotCurveDefines::zDepthForIndex( RiuQwtPlotCurveDefines::ZIndex::Z_ENSEMBLE_STAT_CURVE ) ); applyCurveAppearance( curve ); - auto symbol = statisticsCurveSymbolFromAddress( rftAddress ); - RiuPlotCurveSymbol::LabelPosition labelPos = statisticsLabelPosFromAddress( rftAddress ); + + auto symbol = m_timeStepSymbols[curveDefToAdd.timeStep()]; curve->setSymbol( symbol ); - curve->setSymbolLabelPosition( labelPos ); - curve->setSymbolSize( curve->symbolSize() + 3 ); - curve->setSymbolSkipDistance( 150 ); + auto size = curve->symbolSize(); + curve->setSymbolSize( size + 2 ); curve->setLineStyle( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_SOLID ); - QString uiText = caf::AppEnum::uiText( rftAddress.wellLogChannel() ); - QString label = uiText.replace( ": Pressure", "" ); - curve->setSymbolLabel( label ); curve->setLineThickness( 3 ); - curve->setShowInLegend( !m_showEnsembleCurves ); + curve->setShowInLegend( false ); + + curveSetsForLegend.insert( { curveSet, curveDefToAdd.timeStep() } ); } } } @@ -712,6 +720,43 @@ void RimWellRftPlot::updateCurvesInPlot( const std::setplotWidget() ) + { + // Create curves with no content to display in the curve legend section. Ensures a consistent legend for both ensemble and + // statistics curves. + + auto formatString = RiaQDateTimeTools::createTimeFormatStringFromDates( m_selectedTimeSteps() ); + for ( const auto& [curveSet, dateTime] : curveSetsForLegend ) + { + auto riuCurve = widget->createPlotCurve( nullptr, "" ); + riuCurve->attachToPlot( plotTrack->plotWidget() ); + riuCurve->setVisibleInLegend( true ); + + QStringList titleItems; + titleItems.push_back( curveSet->ensembleName() ); + titleItems.push_back( dateTime.toString( formatString ) ); + titleItems.push_back( m_wellPathNameOrSimWellName ); + QString title = titleItems.join( ", " ); + riuCurve->setTitle( title ); + + auto color = RiaColorTools::toQColor( curveSet->curveColor( nullptr, nullptr ) ); + int curveThickness = 3; + riuCurve->setAppearance( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_SOLID, + RiuQwtPlotCurveDefines::CurveInterpolationEnum::INTERPOLATION_POINT_TO_POINT, + curveThickness, + color ); + + auto symbolType = m_timeStepSymbols[dateTime]; + auto symbol = riuCurve->createSymbol( symbolType ); + symbol->setSize( 8, 8 ); + symbol->setColor( color ); + + riuCurve->setSymbol( symbol ); + + m_legendPlotCurves.push_back( riuCurve ); + } + } + if ( depthType() == RiaDefines::DepthTypeEnum::MEASURED_DEPTH ) { assignWellPathToExtractionCurves(); @@ -1284,6 +1329,18 @@ void RimWellRftPlot::initAfterRead() m_wellLogPlot_OBSOLETE = nullptr; } + if ( RimProject::current()->isProjectFileVersionEqualOrOlderThan( "2025.04.3" ) ) + { + std::vector colorTable; + RiaColorTables::summaryCurveDefaultPaletteColors().color3fArray().toStdVector( &colorTable ); + + size_t colorIndex = 0; + for ( auto e : m_ensembleCurveSets ) + { + e->setCurveColor( colorTable[colorIndex % colorTable.size()] ); + } + } + RimWellLogPlot::initAfterRead(); } @@ -1314,6 +1371,17 @@ bool RimWellRftPlot::useUndoRedoForFieldChanged() return false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellRftPlot::deleteViewWidget() +{ + // Required to detach curves before view widget is deleted. The Qwt plot curves are implicitly deleted when the view widget is deleted. + detachAndDeleteLegendCurves(); + + RimDepthTrackPlot::deleteViewWidget(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -1398,45 +1466,12 @@ cvf::Color3f RimWellRftPlot::findCurveColor( RimWellLogCurve* curve ) { RiaRftPltCurveDefinition curveDef = RimWellPlotTools::curveDefFromCurve( curve ); - cvf::Color3f curveColor; - if ( curveDef.address().sourceType() == RifDataSourceForRftPlt::SourceType::SUMMARY_RFT ) + if ( RimWellRftEnsembleCurveSet* ensembleCurveSet = findEnsembleCurveSet( curveDef.address().ensemble() ) ) { - RimWellRftEnsembleCurveSet* ensembleCurveSet = findEnsembleCurveSet( curveDef.address().ensemble() ); - if ( ensembleCurveSet && ensembleCurveSet->colorMode() == ColorMode::BY_ENSEMBLE_PARAM ) - { - curveColor = ensembleCurveSet->caseColor( curveDef.address().summaryCase() ); - } - else - { - if ( curveDef.address().ensemble() ) - { - // If we have an ensemble, we need to use the ensemble address to find one single color for all curves in the ensemble. If - // we also include the summary case, each curve will be assigned a separate color. - - RifDataSourceForRftPlt dataSource( curveDef.address().ensemble() ); - curveColor = m_dataSourceColors[dataSource]; - } - else - { - curveColor = m_dataSourceColors[curveDef.address()]; - } - } - - if ( m_showStatisticsCurves ) - { - if ( plotByIndex( 0 ) && plotByIndex( 0 )->plotWidget() ) - { - cvf::Color3f backgroundColor = RiaColorTools::fromQColorTo3f( plotByIndex( 0 )->plotWidget()->backgroundColor() ); - curveColor = RiaColorTools::blendCvfColors( backgroundColor, curveColor, 1, 2 ); - } - } - } - else - { - curveColor = m_dataSourceColors[curveDef.address()]; + return ensembleCurveSet->curveColor( curveDef.address().ensemble(), curveDef.address().summaryCase() ); } - return curveColor; + return m_dataSourceColors[curveDef.address()]; } //-------------------------------------------------------------------------------------------------- @@ -1467,10 +1502,7 @@ void RimWellRftPlot::defineCurveColorsAndSymbols( const std::setensemble() == ensemble; } ); if ( ensemble_it != ensembles.end() ) { - curveSet->initializeLegend(); - - if ( viewer && curveSet->legendConfig()->showLegend() && curveSet->colorMode() == ColorMode::BY_ENSEMBLE_PARAM && - !curveSet->currentEnsembleParameter().isEmpty() ) + if ( viewer && curveSet->legendConfig() ) { if ( !m_ensembleLegendFrames[curveSet] ) { @@ -1563,6 +1595,9 @@ void RimWellRftPlot::createEnsembleCurveSets() delete curveSet; } + std::vector colorTable; + RiaColorTables::summaryCurveDefaultPaletteColors().color3fArray().toStdVector( &colorTable ); + // Then add curve set for any ensembles we haven't already added for ( RimSummaryEnsemble* ensemble : rftEnsembles ) { @@ -1573,11 +1608,28 @@ void RimWellRftPlot::createEnsembleCurveSets() { RimWellRftEnsembleCurveSet* curveSet = new RimWellRftEnsembleCurveSet; curveSet->setEnsemble( ensemble ); + auto index = m_ensembleCurveSets.size(); + auto color = colorTable.at( index % colorTable.size() ); + curveSet->setCurveColor( color ); m_ensembleCurveSets.push_back( curveSet ); } } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimWellRftPlot::detachAndDeleteLegendCurves() +{ + for ( auto c : m_legendPlotCurves ) + { + c->detach(); + delete c; + } + + m_legendPlotCurves.clear(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.h b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.h index e8737e73d9..490c6ab06c 100644 --- a/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.h +++ b/ApplicationLibCode/ProjectDataModel/Flow/RimWellRftPlot.h @@ -18,10 +18,7 @@ #pragma once -#include "RimEnsembleCurveSetColorManager.h" -#include "RimViewWindow.h" #include "RimWellLogPlot.h" -#include "RimWellRftEnsembleCurveSet.h" #include "RifDataSourceForRftPltQMetaType.h" @@ -30,10 +27,7 @@ #include "cafPdmField.h" #include "cafPdmObject.h" #include "cafPdmPtrField.h" -#include "cvfCollection.h" -#include -#include #include #include @@ -55,6 +49,8 @@ class RifDataSourceForRftPlt; class RifEclipseRftAddress; class RiuDraggableOverlayFrame; class RimDataSourceForRftPlt; +class RiuPlotCurve; +class RimWellRftEnsembleCurveSet; namespace cvf { @@ -100,7 +96,7 @@ public: void rebuildCurves(); -protected: +private: void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName ) override; @@ -112,8 +108,8 @@ protected: void setupBeforeSave() override; void initAfterRead() override; bool useUndoRedoForFieldChanged() override; + void deleteViewWidget() override; -private: std::map findWellSources(); void updateEditorsFromPreviousSelection(); void setSelectedSourcesFromCurves(); @@ -149,6 +145,8 @@ private: std::vector selectedEnsembles() const; void createEnsembleCurveSets(); + void detachAndDeleteLegendCurves(); + private: friend class RimWellRftEnsembleCurveSet; @@ -172,6 +170,8 @@ private: std::map m_timeStepSymbols; bool m_isOnLoad; + std::vector m_legendPlotCurves; + caf::PdmChildField m_wellLogPlot_OBSOLETE; bool m_isInitialized = false; }; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveFilter.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveFilter.cpp index 116a9f3be3..a4e0ace74b 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveFilter.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveFilter.cpp @@ -303,7 +303,7 @@ QList RimEnsembleCurveFilter::calculateValueOptions( con auto curveSet = parentCurveSet(); if ( curveSet ) { - auto params = curveSet->ensembleParameters( RimEnsembleCurveSet::ParameterSorting::ABSOLUTE_VALUE ); + auto params = curveSet->ensembleParameters( RimCurveAppearanceDefines::ParameterSorting::ABSOLUTE_VALUE ); for ( const auto& [param, corr] : params ) { options.push_back( caf::PdmOptionItemInfo( QString( "%1 (Avg. correlation: %2)" ).arg( param.name ).arg( corr ), param.name ) ); @@ -789,7 +789,7 @@ void RimEnsembleCurveFilter::updateMaxMinAndDefaultValues( bool forceDefault ) { if ( !selectedEnsembleParameter().isValid() ) { - auto ensParams = parentCurveSet()->ensembleParameters( RimEnsembleCurveSet::ParameterSorting::ABSOLUTE_VALUE ); + auto ensParams = parentCurveSet()->ensembleParameters( RimCurveAppearanceDefines::ParameterSorting::ABSOLUTE_VALUE ); if ( !ensParams.empty() ) { m_ensembleParameterName = ensParams.front().first.name; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp index 8ed13de82c..e843412f6d 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp @@ -85,23 +85,6 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -namespace caf -{ -template <> -void AppEnum::setUp() -{ - addItem( RimEnsembleCurveSet::ParameterSorting::ABSOLUTE_VALUE, "ABSOLUTE_VALUE", "Absolute Correlation" ); - addItem( RimEnsembleCurveSet::ParameterSorting::ALPHABETICALLY, "ALPHABETICALLY", "Alphabetically" ); - setDefault( RimEnsembleCurveSet::ParameterSorting::ABSOLUTE_VALUE ); -} -template <> -void AppEnum::setUp() -{ - addItem( RimEnsembleCurveSet::AppearanceMode::DEFAULT, "DEFAULT", "Default" ); - addItem( RimEnsembleCurveSet::AppearanceMode::CUSTOM, "CUSTOM", "Custom" ); - setDefault( RimEnsembleCurveSet::AppearanceMode::DEFAULT ); -} -} // namespace caf //-------------------------------------------------------------------------------------------------- /// Internal functions @@ -1330,7 +1313,7 @@ void RimEnsembleCurveSet::defineUiOrdering( QString uiConfigName, caf::PdmUiOrde caf::PdmUiGroup* statAppearance = statGroup->addNewGroupWithKeyword( "Appearance", "StatisticsAppearance" ); statAppearance->add( &m_statisticsUseCustomAppearance ); - if ( m_statisticsUseCustomAppearance() == AppearanceMode::CUSTOM ) + if ( m_statisticsUseCustomAppearance() == RimCurveAppearanceDefines::AppearanceMode::CUSTOM ) { statAppearance->add( &m_statisticsLineStyle ); statAppearance->add( &m_statisticsPointSymbol ); @@ -1495,7 +1478,7 @@ void RimEnsembleCurveSet::appendColorGroup( caf::PdmUiOrdering& uiOrdering ) } colorsGroup->add( &m_useCustomAppearance ); - if ( m_useCustomAppearance() == AppearanceMode::CUSTOM ) + if ( m_useCustomAppearance() == RimCurveAppearanceDefines::AppearanceMode::CUSTOM ) { colorsGroup->add( &m_lineStyle ); colorsGroup->add( &m_pointSymbol ); @@ -2213,7 +2196,7 @@ void RimEnsembleCurveSet::updateEnsembleCurves( const std::vectorsetLineThickness( lineThickness ); - if ( m_useCustomAppearance() == AppearanceMode::CUSTOM ) + if ( m_useCustomAppearance() == RimCurveAppearanceDefines::AppearanceMode::CUSTOM ) { curve->setLineStyle( m_lineStyle() ); curve->setSymbol( m_pointSymbol() ); @@ -2365,7 +2348,7 @@ void RimEnsembleCurveSet::updateStatisticsCurves( const std::vectorsetCheckState( isCurvesVisible() ); - if ( m_statisticsUseCustomAppearance() == AppearanceMode::DEFAULT ) + if ( m_statisticsUseCustomAppearance() == RimCurveAppearanceDefines::AppearanceMode::DEFAULT ) { auto symbol = statisticsCurveSymbolFromAddress( address.summaryAddressY() ); curve->setSymbol( symbol ); @@ -2469,17 +2452,18 @@ std::vector RimEnsembleCurveSet::variationSortedEnsemblePa //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -std::vector> RimEnsembleCurveSet::ensembleParameters( ParameterSorting sortingMode ) const +std::vector> + RimEnsembleCurveSet::ensembleParameters( RimCurveAppearanceDefines::ParameterSorting sortingMode ) const { RimSummaryEnsemble* ensemble = m_yValuesSummaryEnsemble; if ( ensemble ) { - if ( sortingMode == ParameterSorting::ABSOLUTE_VALUE ) + if ( sortingMode == RimCurveAppearanceDefines::ParameterSorting::ABSOLUTE_VALUE ) { return ensemble->correlationSortedEnsembleParameters( summaryAddressY() ); } - if ( sortingMode == ParameterSorting::ALPHABETICALLY ) + if ( sortingMode == RimCurveAppearanceDefines::ParameterSorting::ALPHABETICALLY ) { auto parameters = ensemble->parameterCorrelationsAllTimeSteps( summaryAddressY() ); std::sort( parameters.begin(), diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h index 02a910073c..b9b4107e5a 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h @@ -25,6 +25,7 @@ #include "Summary/RiaSummaryCurveAddress.h" #include "Summary/RiaSummaryDefines.h" +#include "Appearance/RimCurveAppearanceDefines.h" #include "RimEnsembleCrossPlotStatisticsCase.h" #include "RimEnsembleCurveSetColorManager.h" #include "RimEnsembleCurveSetInterface.h" @@ -86,18 +87,6 @@ public: using LineStyle = caf::AppEnum; using PointSymbol = caf::AppEnum; - enum class ParameterSorting - { - ABSOLUTE_VALUE, - ALPHABETICALLY - }; - - enum class AppearanceMode - { - DEFAULT, - CUSTOM - }; - public: RimEnsembleCurveSet(); ~RimEnsembleCurveSet() override; @@ -160,7 +149,7 @@ public: void updateAllTextInPlot(); std::vector variationSortedEnsembleParameters() const; - std::vector> ensembleParameters( ParameterSorting sortingMode ) const; + std::vector> ensembleParameters( RimCurveAppearanceDefines::ParameterSorting sortingMode ) const; std::vector filterEnsembleCases( const std::vector& sumCases ); void disableStatisticCurves(); @@ -264,22 +253,22 @@ private: caf::PdmField> m_xAxisType; caf::PdmChildField m_xAddressSelector; - caf::PdmField m_colorMode; - caf::PdmField m_mainEnsembleColor; - caf::PdmField m_colorForRealizations; - caf::PdmField m_colorTransparency; - caf::PdmField m_ensembleParameter; - caf::PdmField> m_ensembleParameterSorting; + caf::PdmField m_colorMode; + caf::PdmField m_mainEnsembleColor; + caf::PdmField m_colorForRealizations; + caf::PdmField m_colorTransparency; + caf::PdmField m_ensembleParameter; + caf::PdmField> m_ensembleParameterSorting; - caf::PdmField> m_useCustomAppearance; - caf::PdmField m_lineStyle; - caf::PdmField m_pointSymbol; - caf::PdmField m_symbolSize; + caf::PdmField> m_useCustomAppearance; + caf::PdmField m_lineStyle; + caf::PdmField m_pointSymbol; + caf::PdmField m_symbolSize; - caf::PdmField> m_statisticsUseCustomAppearance; - caf::PdmField m_statisticsLineStyle; - caf::PdmField m_statisticsPointSymbol; - caf::PdmField m_statisticsSymbolSize; + caf::PdmField> m_statisticsUseCustomAppearance; + caf::PdmField m_statisticsLineStyle; + caf::PdmField m_statisticsPointSymbol; + caf::PdmField m_statisticsSymbolSize; caf::PdmChildArrayField m_objectiveValuesSummaryAddresses; caf::PdmField m_objectiveValuesSummaryAddressesUiField; diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.cpp index 08eea67be9..2e0b2eeb8a 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimEnsembleCurveSetColorManager.cpp @@ -171,6 +171,11 @@ cvf::Color3f RimEnsembleCurveSetColorManager::caseColor( const RimRegularLegendC const RimSummaryCase* summaryCase, const RigEnsembleParameter& ensembleParam ) { + if ( !summaryCase || !legendConfig ) + { + return RiaColorTables::undefinedCellColor(); + } + if ( ensembleParam.isText() ) { QString tValue = summaryCase->hasCaseRealizationParameters() diff --git a/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.cpp b/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.cpp index a9f699b15a..78e959dfdf 100644 --- a/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.cpp +++ b/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogRftCurve.cpp @@ -57,6 +57,7 @@ #include "RimWellLogTrack.h" #include "RimWellPath.h" #include "RimWellPlotTools.h" +#include "RimWellRftEnsembleCurveSet.h" #include "RimWellRftPlot.h" #include "RiuQwtPlotCurve.h"