mirror of
https://github.com/OPM/ResInsight.git
synced 2026-08-27 05:37:21 -05:00
#13903 Harmonize correlation and tornado bar-chart behavior
Extract shared helpers into a new RimCorrelationBarChartTools namespace so RimCorrelationPlot and RimRftTornadoPlot share a single source of truth for: - highlightSelectedParameterBar and the click-to-parameter-name lookup - the axis-label format, abs/sort-value math, and the addBarEntry call (with the "legendText must equal parameter name" convention) via addCorrelationBar Also enable click-to-select on RimCorrelationPlot: use the parameter name as the bar chart title so click-to-select works, and recolor the selected bar via a new HighlightBarColor field, mirroring the pattern used in RimRftTornadoPlot.
This commit is contained in:
@@ -8,6 +8,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimCorrelationReportPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimRftCorrelationReportPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimRftTornadoPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimCorrelationBarChartTools.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -20,6 +21,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimCorrelationReportPlot.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimRftCorrelationReportPlot.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimRftTornadoPlot.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimCorrelationBarChartTools.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2026 Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimCorrelationBarChartTools.h"
|
||||
|
||||
#include "RiuGroupedBarChartBuilder.h"
|
||||
#include "RiuPlotItem.h"
|
||||
#include "RiuQwtPlotItem.h"
|
||||
#include "RiuQwtPlotWidget.h"
|
||||
|
||||
#include "qwt_column_symbol.h"
|
||||
#include "qwt_plot.h"
|
||||
#include "qwt_plot_barchart.h"
|
||||
#include "qwt_text.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimCorrelationBarChartTools::highlightSelectedParameterBar( RiuQwtPlotWidget* plotWidget,
|
||||
const QString& selectedParamName,
|
||||
const QColor& barColor,
|
||||
const QColor& highlightColor )
|
||||
{
|
||||
if ( !plotWidget ) return;
|
||||
|
||||
for ( QwtPlotItem* item : plotWidget->qwtPlot()->itemList( QwtPlotItem::Rtti_PlotBarChart ) )
|
||||
{
|
||||
auto* barChart = static_cast<QwtPlotBarChart*>( item );
|
||||
auto* symbol = const_cast<QwtColumnSymbol*>( barChart->symbol() );
|
||||
if ( !symbol ) continue;
|
||||
|
||||
const QColor color = ( barChart->title().text() == selectedParamName ) ? highlightColor : barColor;
|
||||
|
||||
QPalette palette = symbol->palette();
|
||||
palette.setColor( QPalette::Window, color );
|
||||
palette.setColor( QPalette::Dark, color );
|
||||
symbol->setPalette( palette );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimCorrelationBarChartTools::parameterNameFromPlotItem( std::shared_ptr<RiuPlotItem> plotItem )
|
||||
{
|
||||
auto* qwtPlotItem = dynamic_cast<RiuQwtPlotItem*>( plotItem.get() );
|
||||
if ( !qwtPlotItem ) return {};
|
||||
|
||||
auto* barChart = dynamic_cast<QwtPlotBarChart*>( qwtPlotItem->qwtPlotItem() );
|
||||
if ( !barChart ) return {};
|
||||
|
||||
return barChart->title().text();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimCorrelationBarChartTools::addCorrelationBar( RiuGroupedBarChartBuilder& chartBuilder,
|
||||
const QString& parameterName,
|
||||
double correlation,
|
||||
bool showAbsoluteValues,
|
||||
bool sortByAbsoluteValues )
|
||||
{
|
||||
const double value = showAbsoluteValues ? std::abs( correlation ) : correlation;
|
||||
const double sortValue = sortByAbsoluteValues ? std::abs( value ) : value;
|
||||
const QString axisLabel = QString( "%1 (%2)" ).arg( parameterName ).arg( correlation, 5, 'f', 2 );
|
||||
|
||||
// legendText (5th arg) becomes barChart->title() and is used for click-to-select and
|
||||
// selection highlight; it must equal parameterName.
|
||||
// barText (6th arg) is shown on the axis label and can include the correlation value.
|
||||
chartBuilder.addBarEntry( "", "", "", sortValue, parameterName, axisLabel, value );
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2026 Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include <QColor>
|
||||
#include <QString>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class RiuGroupedBarChartBuilder;
|
||||
class RiuPlotItem;
|
||||
class RiuQwtPlotWidget;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// Presentation helpers shared by the correlation bar/tornado plots (RimCorrelationPlot,
|
||||
/// RimRftTornadoPlot). The plots rely on the convention that the legendText passed to
|
||||
/// RiuGroupedBarChartBuilder::addBarEntry equals the parameter name, so the bar chart's
|
||||
/// title can be used to identify which parameter was clicked or should be highlighted.
|
||||
///
|
||||
//==================================================================================================
|
||||
namespace RimCorrelationBarChartTools
|
||||
{
|
||||
void highlightSelectedParameterBar( RiuQwtPlotWidget* plotWidget,
|
||||
const QString& selectedParamName,
|
||||
const QColor& barColor,
|
||||
const QColor& highlightColor );
|
||||
|
||||
QString parameterNameFromPlotItem( std::shared_ptr<RiuPlotItem> plotItem );
|
||||
|
||||
void addCorrelationBar( RiuGroupedBarChartBuilder& chartBuilder,
|
||||
const QString& parameterName,
|
||||
double correlation,
|
||||
bool showAbsoluteValues,
|
||||
bool sortByAbsoluteValues );
|
||||
} // namespace RimCorrelationBarChartTools
|
||||
@@ -24,11 +24,11 @@
|
||||
|
||||
#include "RiuGroupedBarChartBuilder.h"
|
||||
#include "RiuPlotMainWindowTools.h"
|
||||
#include "RiuQwtPlotItem.h"
|
||||
#include "RiuQwtPlotWidget.h"
|
||||
|
||||
#include "RifSummaryReaderInterface.h"
|
||||
|
||||
#include "RimCorrelationBarChartTools.h"
|
||||
#include "RimDeltaSummaryCase.h"
|
||||
#include "RimEnsembleCurveSet.h"
|
||||
#include "RimPlotAxisProperties.h"
|
||||
@@ -44,7 +44,6 @@
|
||||
#include "cafPdmUiTreeSelectionEditor.h"
|
||||
|
||||
#include "qwt_plot.h"
|
||||
#include "qwt_plot_barchart.h"
|
||||
#include "qwt_text.h"
|
||||
|
||||
#include <limits>
|
||||
@@ -75,6 +74,8 @@ RimCorrelationPlot::RimCorrelationPlot()
|
||||
// Color taken from https://webviz-subsurface-example.azurewebsites.net/parameters-vs-rft
|
||||
QColor qColor = QColor( "#3173b2" );
|
||||
CAF_PDM_InitField( &m_barColor, "BarColor", RiaColorTools::fromQColorTo3f( qColor ), "Bar Color" );
|
||||
QColor highlightColor = QColor( "#f5a623" );
|
||||
CAF_PDM_InitField( &m_highlightBarColor, "HighlightBarColor", RiaColorTools::fromQColorTo3f( highlightColor ), "Bar Color (Selected)" );
|
||||
|
||||
setLegendsVisible( false );
|
||||
setDeletable( true );
|
||||
@@ -99,7 +100,8 @@ void RimCorrelationPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedFie
|
||||
|
||||
if ( changedField == &m_showAbsoluteValues || changedField == &m_sortByAbsoluteValues ||
|
||||
changedField == &m_excludeParametersWithoutVariation || changedField == &m_selectedParametersList ||
|
||||
changedField == &m_showOnlyTopNCorrelations || changedField == &m_topNFilterCount || changedField == &m_barColor )
|
||||
changedField == &m_showOnlyTopNCorrelations || changedField == &m_topNFilterCount || changedField == &m_barColor ||
|
||||
changedField == &m_highlightBarColor )
|
||||
{
|
||||
if ( changedField == &m_excludeParametersWithoutVariation )
|
||||
{
|
||||
@@ -142,6 +144,7 @@ void RimCorrelationPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder
|
||||
plotGroup->add( &m_axisTitleFontSize );
|
||||
plotGroup->add( &m_axisValueFontSize );
|
||||
plotGroup->add( &m_barColor );
|
||||
plotGroup->add( &m_highlightBarColor );
|
||||
|
||||
m_description.uiCapability()->setUiReadOnly( m_useAutoPlotTitle() );
|
||||
uiOrdering.skipRemainingFields( true );
|
||||
@@ -191,6 +194,10 @@ void RimCorrelationPlot::onLoadDataAndUpdate()
|
||||
|
||||
chartBuilder.addBarChartToPlot( m_plotWidget->qwtPlot(), Qt::Horizontal, m_showOnlyTopNCorrelations() ? m_topNFilterCount() : -1 );
|
||||
chartBuilder.setLabelFontSize( labelFontSize() );
|
||||
RimCorrelationBarChartTools::highlightSelectedParameterBar( m_plotWidget,
|
||||
m_selectedParameter,
|
||||
RiaColorTools::toQColor( m_barColor() ),
|
||||
RiaColorTools::toQColor( m_highlightBarColor() ) );
|
||||
|
||||
m_plotWidget->qwtPlot()->insertLegend( nullptr );
|
||||
m_plotWidget->updateLegend();
|
||||
@@ -247,11 +254,11 @@ void RimCorrelationPlot::addDataToChartBuilder( RiuGroupedBarChartBuilder& chart
|
||||
|
||||
for ( auto parameterCorrPair : correlations )
|
||||
{
|
||||
double value = m_showAbsoluteValues() ? std::abs( parameterCorrPair.second ) : parameterCorrPair.second;
|
||||
double sortValue = m_sortByAbsoluteValues() ? std::abs( value ) : value;
|
||||
QString barText = QString( "%1 (%2)" ).arg( parameterCorrPair.first.name ).arg( parameterCorrPair.second, 5, 'f', 2 );
|
||||
QString majorText = "", medText = "", minText = "", legendText = barText;
|
||||
chartBuilder.addBarEntry( majorText, medText, minText, sortValue, legendText, barText, value );
|
||||
RimCorrelationBarChartTools::addCorrelationBar( chartBuilder,
|
||||
parameterCorrPair.first.name,
|
||||
parameterCorrPair.second,
|
||||
m_showAbsoluteValues(),
|
||||
m_sortByAbsoluteValues() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,24 +282,12 @@ void RimCorrelationPlot::updatePlotTitle()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimCorrelationPlot::onPlotItemSelected( std::shared_ptr<RiuPlotItem> plotItem, bool toggle, int sampleIndex )
|
||||
void RimCorrelationPlot::onPlotItemSelected( std::shared_ptr<RiuPlotItem> plotItem, bool /*toggle*/, int /*sampleIndex*/ )
|
||||
{
|
||||
RiuQwtPlotItem* qwtPlotItem = dynamic_cast<RiuQwtPlotItem*>( plotItem.get() );
|
||||
if ( !qwtPlotItem ) return;
|
||||
const QString paramName = RimCorrelationBarChartTools::parameterNameFromPlotItem( plotItem );
|
||||
if ( paramName.isEmpty() || curveDefinitions().empty() ) return;
|
||||
|
||||
QwtPlotBarChart* barChart = dynamic_cast<QwtPlotBarChart*>( qwtPlotItem->qwtPlotItem() );
|
||||
if ( barChart && !curveDefinitions().empty() )
|
||||
{
|
||||
auto curveDef = curveDefinitions().front();
|
||||
auto barTitle = barChart->title();
|
||||
for ( auto param : ensembleParameters() )
|
||||
{
|
||||
if ( barTitle.text() == param.name )
|
||||
{
|
||||
tornadoItemSelected.send( std::make_pair( param.name, curveDef ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
tornadoItemSelected.send( std::make_pair( paramName, curveDefinitions().front() ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -369,3 +364,11 @@ void RimCorrelationPlot::setTopNFilterCount( int filterCount )
|
||||
{
|
||||
m_topNFilterCount = filterCount;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimCorrelationPlot::setSelectedParameter( const QString& paramName )
|
||||
{
|
||||
m_selectedParameter = paramName;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ public:
|
||||
void setShowOnlyTopNCorrelations( bool showOnlyTopNCorrelations );
|
||||
void setTopNFilterCount( int filterCount );
|
||||
|
||||
void setSelectedParameter( const QString& paramName );
|
||||
|
||||
private:
|
||||
// Overridden PDM methods
|
||||
|
||||
@@ -79,4 +81,7 @@ private:
|
||||
caf::PdmField<int> m_topNFilterCount;
|
||||
caf::PdmField<std::vector<QString>> m_selectedParametersList;
|
||||
caf::PdmField<cvf::Color3f> m_barColor;
|
||||
caf::PdmField<cvf::Color3f> m_highlightBarColor;
|
||||
|
||||
QString m_selectedParameter;
|
||||
};
|
||||
|
||||
@@ -714,6 +714,7 @@ void RimCorrelationReportPlot::onDataSelection( const caf::SignalEmitter*
|
||||
auto curveDef = parameterAndCurveDef.second;
|
||||
|
||||
m_correlationPlot->setCurveDefinitions( { curveDef } );
|
||||
m_correlationPlot->setSelectedParameter( paramName );
|
||||
m_correlationPlot->loadDataAndUpdate();
|
||||
m_parameterResultCrossPlot->setCurveDefinitions( { curveDef } );
|
||||
m_parameterResultCrossPlot->setEnsembleParameter( paramName );
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "RigEnsembleParameter.h"
|
||||
#include "RigStatisticsTools.h"
|
||||
|
||||
#include "RimCorrelationBarChartTools.h"
|
||||
#include "RimEclipseResultCase.h"
|
||||
#include "RimParameterRftCrossPlot.h"
|
||||
#include "RimSummaryEnsemble.h"
|
||||
@@ -32,14 +33,11 @@
|
||||
#include "RiuContextMenuLauncher.h"
|
||||
#include "RiuGroupedBarChartBuilder.h"
|
||||
#include "RiuPlotItem.h"
|
||||
#include "RiuQwtPlotItem.h"
|
||||
#include "RiuQwtPlotWidget.h"
|
||||
|
||||
#include "cafPdmUiCheckBoxEditor.h"
|
||||
|
||||
#include "qwt_column_symbol.h"
|
||||
#include "qwt_plot.h"
|
||||
#include "qwt_plot_barchart.h"
|
||||
#include "qwt_text.h"
|
||||
|
||||
#include <QPaintDevice>
|
||||
@@ -293,7 +291,10 @@ void RimRftTornadoPlot::onLoadDataAndUpdate()
|
||||
const int labelSize = caf::FontTools::absolutePointSize( RiaPreferences::current()->defaultPlotFontSize(), m_labelFontSize() );
|
||||
chartBuilder.setLabelFontSize( labelSize );
|
||||
chartBuilder.addBarChartToPlot( m_plotWidget->qwtPlot(), Qt::Horizontal, m_showOnlyTopNCorrelations() ? m_topNFilterCount() : -1 );
|
||||
highlightSelectedParameterBar();
|
||||
RimCorrelationBarChartTools::highlightSelectedParameterBar( m_plotWidget,
|
||||
m_selectedParameter,
|
||||
RiaColorTools::toQColor( m_barColor() ),
|
||||
RiaColorTools::toQColor( m_highlightBarColor() ) );
|
||||
|
||||
m_plotWidget->qwtPlot()->insertLegend( nullptr );
|
||||
|
||||
@@ -345,11 +346,8 @@ void RimRftTornadoPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedFiel
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimRftTornadoPlot::onPlotItemSelected( std::shared_ptr<RiuPlotItem> plotItem, bool /*toggle*/, int /*sampleIndex*/ )
|
||||
{
|
||||
auto* qwtPlotItem = dynamic_cast<RiuQwtPlotItem*>( plotItem.get() );
|
||||
if ( !qwtPlotItem ) return;
|
||||
|
||||
auto* barChart = dynamic_cast<QwtPlotBarChart*>( qwtPlotItem->qwtPlotItem() );
|
||||
if ( barChart && m_parameterSelectedCallback ) m_parameterSelectedCallback( barChart->title().text() );
|
||||
const QString paramName = RimCorrelationBarChartTools::parameterNameFromPlotItem( plotItem );
|
||||
if ( !paramName.isEmpty() && m_parameterSelectedCallback ) m_parameterSelectedCallback( paramName );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -397,52 +395,12 @@ std::map<QString, double> RimRftTornadoPlot::addDataToChartBuilder( RiuGroupedBa
|
||||
|
||||
correlations[param.name] = pearson;
|
||||
|
||||
double value = m_showAbsoluteValues() ? std::abs( pearson ) : pearson;
|
||||
double sortValue = m_sortByAbsoluteValues() ? std::abs( value ) : value;
|
||||
// legendText becomes barChart->title() and is used for click-to-select; must equal param.name.
|
||||
// barText is shown on the axis label and can include the correlation value.
|
||||
QString axisLabel = QString( "%1 (%2)" ).arg( param.name ).arg( pearson, 5, 'f', 2 );
|
||||
chartBuilder.addBarEntry( "", "", "", sortValue, param.name, axisLabel, value );
|
||||
RimCorrelationBarChartTools::addCorrelationBar( chartBuilder, param.name, pearson, m_showAbsoluteValues(), m_sortByAbsoluteValues() );
|
||||
}
|
||||
|
||||
return correlations;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimRftTornadoPlot::highlightSelectedParameterBar()
|
||||
{
|
||||
if ( !m_plotWidget ) return;
|
||||
|
||||
const QColor highlightColor = RiaColorTools::toQColor( m_highlightBarColor() );
|
||||
const QColor barColor = RiaColorTools::toQColor( m_barColor() );
|
||||
|
||||
for ( QwtPlotItem* item : m_plotWidget->qwtPlot()->itemList( QwtPlotItem::Rtti_PlotBarChart ) )
|
||||
{
|
||||
auto* barChart = static_cast<QwtPlotBarChart*>( item );
|
||||
auto* symbol = const_cast<QwtColumnSymbol*>( barChart->symbol() );
|
||||
if ( !symbol ) continue;
|
||||
|
||||
const QString paramName = barChart->title().text();
|
||||
|
||||
QColor color;
|
||||
if ( paramName == m_selectedParameter )
|
||||
{
|
||||
color = highlightColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = barColor;
|
||||
}
|
||||
|
||||
QPalette palette = symbol->palette();
|
||||
palette.setColor( QPalette::Window, color );
|
||||
palette.setColor( QPalette::Dark, color );
|
||||
symbol->setPalette( palette );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -88,7 +88,6 @@ private:
|
||||
void onPlotItemSelected( std::shared_ptr<RiuPlotItem> plotItem, bool toggle, int sampleIndex ) override;
|
||||
|
||||
std::map<QString, double> addDataToChartBuilder( class RiuGroupedBarChartBuilder& chartBuilder ) const;
|
||||
void highlightSelectedParameterBar();
|
||||
void updatePlotTitle();
|
||||
void cleanupBeforeClose();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user