#14235 Correlation report: synchronise all sub-plots and control data source from the report

Selecting a summary vector in a correlation report now propagates to the contained tornado, cross and summary plots by selecting the first matrix cell, which sends the existing selection signal handled by the report. A virtual onDataSourceChanged() hook on the abstract correlation plot is called after the summary vector selection dialog, and the matrix and tornado plots override it to re-select their first item so dependent plots update.

When a plot is used as a sub-plot of a correlation report, the data source and correlation settings are controlled from the report, so its property editor exposes only the plot settings. Used individually the plots show the complete set of options. Whether a plot is a report sub-plot is tracked with a flag set by the owning report on construction and after read.

Use updateAllRequiredEditors() for sub-plot interactions and for time step changes driven from the summary plot, so the project tree text and property panel reflect the updated auto-generated titles. Re-apply the configured dock title bar visibility after toggling a sub-plot dock, so the title bar stays hidden when a hidden sub-plot is shown again.
This commit is contained in:
Magne Sjaastad
2026-06-26 17:09:26 +02:00
parent 189bf3e35c
commit 931c8d066c
8 changed files with 163 additions and 51 deletions
@@ -138,7 +138,7 @@ void RimAbstractCorrelationPlot::fieldChangedByUi( const caf::PdmFieldHandle* ch
if ( changedField == &m_timeStep )
{
loadDataAndUpdate();
updateConnectedEditors();
updateAllRequiredEditors();
}
else if ( changedField == &m_showPlotTitle || changedField == &m_useAutoPlotTitle || changedField == &m_description )
{
@@ -169,7 +169,7 @@ void RimAbstractCorrelationPlot::fieldChangedByUi( const caf::PdmFieldHandle* ch
}
}
updateConnectedEditors();
updateAllRequiredEditors();
}
else if ( changedField == &m_curveSetForFiltering )
{
@@ -727,6 +727,22 @@ void RimAbstractCorrelationPlot::appendDataSourceFields( QString uiConfigName, c
m_editCaseFilter.uiCapability()->setUiHidden( !m_useCaseFilter() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimAbstractCorrelationPlot::isContainedInReportPlot() const
{
return m_isReportSubPlot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimAbstractCorrelationPlot::setReportSubPlot( bool enable )
{
m_isReportSubPlot = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -799,7 +815,15 @@ void RimAbstractCorrelationPlot::onSelectVariablesButtonClicked()
}
connectAllCaseSignals();
loadDataAndUpdate();
updateConnectedEditors();
updateAllRequiredEditors();
onDataSourceChanged();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimAbstractCorrelationPlot::onDataSourceChanged()
{
}
@@ -64,6 +64,8 @@ public:
void setExcludedSummaryCases( const std::vector<RimSummaryCase*>& summaryCases );
std::vector<RimSummaryCase*> excludedSummaryCases() const;
void setReportSubPlot( bool enable );
RiuQwtPlotWidget* viewer();
RiuPlotWidget* plotWidget() override;
void detachAllCurves() override;
@@ -125,6 +127,16 @@ protected:
void appendDataSourceFields( QString uiConfigName, caf::PdmUiOrdering& uiOrdering );
// True when this plot is a sub-plot of a correlation report. The report controls the data source and
// correlation settings, so individually only the plot settings are exposed in the property editor. The
// flag is set by the owning report (see setReportSubPlot) rather than derived by walking ancestors.
bool isContainedInReportPlot() const;
// Called after the selected summary vectors (data source) have been changed through the selection dialog.
// Subclasses may override to propagate the change to dependent plots. The matrix plot uses this to select its
// first cell, which in turn updates the sibling plots in a correlation report.
virtual void onDataSourceChanged();
private:
void onCaseRemoved( const SignalEmitter* emitter, RimSummaryCase* summaryCase );
void connectAllCaseSignals();
@@ -158,4 +170,7 @@ private:
caf::PdmField<bool> m_editCaseFilter;
std::vector<RimSummaryCase*> m_excludedCases;
// Set by the owning correlation report; not serialized, re-established by the report on construction and read.
bool m_isReportSubPlot = false;
};
@@ -301,46 +301,71 @@ void RimCorrelationMatrixPlot::fieldChangedByUi( const caf::PdmFieldHandle* chan
}
updateLegend();
loadDataAndUpdate();
updateConnectedEditors();
updateAllRequiredEditors();
auto curves = curveDefinitions();
auto parameters = m_selectedParametersList();
if ( !curves.empty() && !parameters.empty() )
{
auto firstCurve = curves.front();
auto firstParameter = parameters.front();
matrixCellSelected.send( { firstParameter, firstCurve } );
}
selectFirstItem();
}
}
//--------------------------------------------------------------------------------------------------
/// Select the first matrix cell (first parameter / first summary vector) and notify listeners. In a
/// correlation report this propagates the current data source to the tornado, cross and summary plots.
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::selectFirstItem()
{
auto curves = curveDefinitions();
auto parameters = m_selectedParametersList();
if ( !curves.empty() && !parameters.empty() )
{
matrixCellSelected.send( { parameters.front(), curves.front() } );
}
}
//--------------------------------------------------------------------------------------------------
/// When the selected summary vectors change, re-select the first cell so the dependent plots in a
/// correlation report are updated with the new data source.
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::onDataSourceChanged()
{
if ( m_selectedParametersList().empty() ) selectAllParameters();
selectFirstItem();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
caf::PdmUiGroup* correlationGroup = uiOrdering.addNewGroup( "Correlation Settings" );
correlationGroup->add( &m_excludeParametersWithoutVariation );
correlationGroup->add( &m_selectedParametersList );
correlationGroup->add( &m_showAbsoluteValues );
correlationGroup->add( &m_sortByValues );
if ( !m_showAbsoluteValues() && m_sortByValues() != Sorting::NO_SORTING )
bool embeddedInReportPanel = ( uiConfigName == "report" );
// When selected individually inside a correlation report, the data source and correlation settings are
// controlled from the report plot, so only the plot settings are exposed here. Outside a report, or when
// the fields are embedded in the report's own panel, the full set is shown.
if ( embeddedInReportPanel || !isContainedInReportPlot() )
{
correlationGroup->add( &m_sortByAbsoluteValues );
}
if ( m_sortByValues() != Sorting::NO_SORTING )
{
correlationGroup->add( &m_showOnlyTopNCorrelations );
if ( m_showOnlyTopNCorrelations() )
caf::PdmUiGroup* correlationGroup = uiOrdering.addNewGroup( "Correlation Settings" );
correlationGroup->add( &m_excludeParametersWithoutVariation );
correlationGroup->add( &m_selectedParametersList );
correlationGroup->add( &m_showAbsoluteValues );
correlationGroup->add( &m_sortByValues );
if ( !m_showAbsoluteValues() && m_sortByValues() != Sorting::NO_SORTING )
{
correlationGroup->add( &m_topNFilterCount );
correlationGroup->add( &m_sortByAbsoluteValues );
}
if ( m_sortByValues() != Sorting::NO_SORTING )
{
correlationGroup->add( &m_showOnlyTopNCorrelations );
if ( m_showOnlyTopNCorrelations() )
{
correlationGroup->add( &m_topNFilterCount );
}
}
appendDataSourceFields( uiConfigName, uiOrdering );
}
appendDataSourceFields( uiConfigName, uiOrdering );
if ( uiConfigName != "report" )
if ( !embeddedInReportPanel )
{
caf::PdmUiGroup* plotGroup = uiOrdering.addNewGroup( "Plot Settings" );
plotGroup->add( &m_showPlotTitle );
@@ -124,6 +124,7 @@ private:
void onLoadDataAndUpdate() override;
void childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) override;
void onDataSourceChanged() override;
void updateAxes() override;
@@ -133,6 +134,7 @@ private:
void updateLegend() override;
void onPlotItemSelected( std::shared_ptr<RiuPlotItem> plotItem, bool toggle, int sampleIndex ) override;
void applySelectedParameterHighlight();
void selectFirstItem();
private:
caf::PdmField<bool> m_showAbsoluteValues;
@@ -108,7 +108,7 @@ void RimCorrelationPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedFie
selectAllParameters();
}
loadDataAndUpdate();
updateConnectedEditors();
updateAllRequiredEditors();
}
}
@@ -117,23 +117,28 @@ void RimCorrelationPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedFie
//--------------------------------------------------------------------------------------------------
void RimCorrelationPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
caf::PdmUiGroup* correlationGroup = uiOrdering.addNewGroup( "Correlation Settings" );
correlationGroup->add( &m_excludeParametersWithoutVariation );
correlationGroup->add( &m_selectedParametersList );
correlationGroup->add( &m_showAbsoluteValues );
if ( !m_showAbsoluteValues() )
// When used as a sub-plot of a correlation report, the data source and correlation settings are controlled
// from the report plot, so only the plot settings are exposed here.
if ( !isContainedInReportPlot() )
{
correlationGroup->add( &m_sortByAbsoluteValues );
}
caf::PdmUiGroup* correlationGroup = uiOrdering.addNewGroup( "Correlation Settings" );
correlationGroup->add( &m_excludeParametersWithoutVariation );
correlationGroup->add( &m_selectedParametersList );
correlationGroup->add( &m_showOnlyTopNCorrelations );
if ( m_showOnlyTopNCorrelations() )
{
correlationGroup->add( &m_topNFilterCount );
}
correlationGroup->add( &m_showAbsoluteValues );
if ( !m_showAbsoluteValues() )
{
correlationGroup->add( &m_sortByAbsoluteValues );
}
appendDataSourceFields( uiConfigName, uiOrdering );
correlationGroup->add( &m_showOnlyTopNCorrelations );
if ( m_showOnlyTopNCorrelations() )
{
correlationGroup->add( &m_topNFilterCount );
}
appendDataSourceFields( uiConfigName, uiOrdering );
}
caf::PdmUiGroup* plotGroup = uiOrdering.addNewGroup( "Plot Settings" );
plotGroup->add( &m_showPlotTitle );
@@ -208,6 +213,23 @@ void RimCorrelationPlot::onLoadDataAndUpdate()
}
}
//--------------------------------------------------------------------------------------------------
/// When the selected summary vector changes, notify listeners so the sibling plots in a correlation
/// report are updated with the new data source.
//--------------------------------------------------------------------------------------------------
void RimCorrelationPlot::onDataSourceChanged()
{
auto curves = curveDefinitions();
if ( curves.empty() ) return;
if ( m_selectedParametersList().empty() ) selectAllParameters();
auto parameters = m_selectedParametersList();
if ( parameters.empty() ) return;
tornadoItemSelected.send( { parameters.front(), curves.front() } );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -67,6 +67,7 @@ private:
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
void onLoadDataAndUpdate() override;
void onDataSourceChanged() override;
void updateAxes() override;
QString asciiDataForPlotExport() const override;
@@ -230,12 +230,15 @@ RimCorrelationReportPlot::RimCorrelationReportPlot()
m_correlationMatrixPlot = new RimCorrelationMatrixPlot;
m_correlationMatrixPlot->setLegendsVisible( false );
m_correlationMatrixPlot->setReportSubPlot( true );
m_correlationPlot = new RimCorrelationPlot;
m_correlationPlot->setLegendsVisible( false );
m_correlationPlot->setReportSubPlot( true );
m_parameterResultCrossPlot = new RimParameterResultCrossPlot;
m_parameterResultCrossPlot->setLegendsVisible( true );
m_parameterResultCrossPlot->setReportSubPlot( true );
m_summaryPlot = new RimSummaryPlot();
m_summaryPlot->setLegendsVisible( false );
@@ -622,6 +625,11 @@ void RimCorrelationReportPlot::onLoadDataAndUpdate()
//--------------------------------------------------------------------------------------------------
void RimCorrelationReportPlot::initAfterRead()
{
// The report sub-plot flag is not serialized, so re-establish it on the deserialized child plots.
m_correlationMatrixPlot->setReportSubPlot( true );
m_correlationPlot->setReportSubPlot( true );
m_parameterResultCrossPlot->setReportSubPlot( true );
updateSummaryPlotTimeAnnotation();
}
@@ -725,6 +733,10 @@ void RimCorrelationReportPlot::childFieldChangedByUi( const caf::PdmFieldHandle*
else if ( m_summaryDockWidget && changedChildField == &m_summaryPlot )
m_summaryDockWidget->toggleView( m_summaryPlot->showWindow() );
// Re-showing a dock widget creates a new dock area whose title bar defaults to visible, so re-apply
// the configured title bar visibility.
updateDockTitleBarsVisibility();
// onLoadDataAndUpdate treats the matrix plot as the source of truth and copies its shared
// properties to the others. When the change originated on the correlation or cross plot,
// first mirror it back to the matrix plot so the subsequent propagation reflects the change.
@@ -797,7 +809,9 @@ void RimCorrelationReportPlot::onDataSelection( const caf::SignalEmitter*
updateSummaryPlotTimeAnnotation();
updateConnectedEditors();
// updateAllRequiredEditors (not just updateConnectedEditors) so the project tree refreshes the
// displayed text of the contained plot items when their data source changes.
updateAllRequiredEditors();
}
//--------------------------------------------------------------------------------------------------
@@ -815,6 +829,10 @@ void RimCorrelationReportPlot::onSummaryPlotMousePressed( double xPlotCoordinate
m_correlationMatrixPlot->setTimeStep( *it );
loadDataAndUpdate();
// The time step is part of the auto-generated titles, so refresh all editors to update the project
// tree text and the time step field in the property panel.
updateAllRequiredEditors();
}
//--------------------------------------------------------------------------------------------------
@@ -170,7 +170,7 @@ void RimParameterResultCrossPlot::fieldChangedByUi( const caf::PdmFieldHandle* c
if ( changedField == &m_ensembleParameter )
{
loadDataAndUpdate();
updateConnectedEditors();
updateAllRequiredEditors();
}
}
@@ -179,13 +179,18 @@ void RimParameterResultCrossPlot::fieldChangedByUi( const caf::PdmFieldHandle* c
//--------------------------------------------------------------------------------------------------
void RimParameterResultCrossPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
appendDataSourceFields( uiConfigName, uiOrdering );
// When used as a sub-plot of a correlation report, the data source, cross plot parameter and filter are
// controlled from the report plot, so only the plot settings are exposed here.
if ( !isContainedInReportPlot() )
{
appendDataSourceFields( uiConfigName, uiOrdering );
caf::PdmUiGroup* crossPlotGroup = uiOrdering.addNewGroup( "Cross Plot Parameters" );
crossPlotGroup->add( &m_ensembleParameter );
caf::PdmUiGroup* crossPlotGroup = uiOrdering.addNewGroup( "Cross Plot Parameters" );
crossPlotGroup->add( &m_ensembleParameter );
auto filterGroup = uiOrdering.addNewGroup( "Filter" );
appendFilterFields( *filterGroup );
auto filterGroup = uiOrdering.addNewGroup( "Filter" );
appendFilterFields( *filterGroup );
}
caf::PdmUiGroup* plotGroup = uiOrdering.addNewGroup( "Plot Settings" );
plotGroup->setCollapsedByDefault();