From 769274b15b22633578bcf730cda0307b5af5549d Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 8 Aug 2026 14:30:58 +0200 Subject: [PATCH 1/2] #14493 Clear referring curve sets directly when an ensemble is deleted The destructor called updateReferringCurveSets(), which runs loadDataAndUpdate() on every referring curve set. At that point the summary cases are already deleted, so reloading the curve data has nothing to read. The reload also syncs UI fields, reloads the curve filters, rebuilds the address list, recomputes statistics over an empty case set and updates three legends, and it calls updateAll() on the parent plot once per curve set instead of once per plot. Add clearReferringCurveSets(), which deletes the ensemble and statistics curves directly and updates each affected plot once. For an ensemble with many realizations spread over several curve sets in the same plot this removes most of the work done while deleting. Query the referring objects as RimEnsembleCurveSet instead of walking all referring objects and casting. The previous loop discarded everything that was not a curve set, so the behavior is unchanged. --- .../Summary/RimSummaryEnsemble.cpp | 35 ++++++++++++++++++- .../Summary/RimSummaryEnsemble.h | 1 + 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.cpp index 633d6ff53a7..b9c7ed443a7 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.cpp @@ -53,6 +53,7 @@ #include #include +#include CAF_PDM_SOURCE_INIT( RimSummaryEnsemble, "SummaryCaseSubCollection" ); @@ -118,7 +119,8 @@ RimSummaryEnsemble::~RimSummaryEnsemble() { m_cases.deleteChildren(); - updateReferringCurveSets(); + // The cases are gone at this point, so the referring curve sets are cleared and their plots redrawn without data. + clearReferringCurveSets(); } //-------------------------------------------------------------------------------------------------- @@ -787,6 +789,37 @@ void RimSummaryEnsemble::updateReferringCurveSets() updateReferringCurveSets( false ); } +//-------------------------------------------------------------------------------------------------- +/// Clear the curves of the curve sets referring to this ensemble, and redraw the affected plots. +/// +/// Used when the summary cases have been deleted. Reloading the curve data has nothing to read at that point, so this +/// deletes the curves directly instead of going through loadDataAndUpdate(). Each plot is updated once, even when it +/// holds several curve sets referring to this ensemble. +//-------------------------------------------------------------------------------------------------- +void RimSummaryEnsemble::clearReferringCurveSets() +{ + std::set plotsToUpdate; + + for ( auto curveSet : objectsWithReferringPtrFieldsOfType() ) + { + if ( !curveSet ) continue; + + curveSet->deleteEnsembleCurves(); + curveSet->deleteStatisticsCurves(); + curveSet->filterChanged.send(); + + if ( auto parentPlot = curveSet->firstAncestorOrThisOfType() ) + { + plotsToUpdate.insert( parentPlot ); + } + } + + for ( auto plot : plotsToUpdate ) + { + plot->updateAll(); + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.h index 2a84c41a9af..ce17ef3ad06 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryEnsemble.h @@ -113,6 +113,7 @@ class RimSummaryEnsemble : public caf::PdmObject void updateReferringCurveSets(); void updateReferringCurveSetsZoomAll(); + void clearReferringCurveSets(); RiaSummaryAddressAnalyzer* addressAnalyzer(); From eb1af64461057701f2697fc1f2d264c6bd41b5cf Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 8 Aug 2026 14:46:11 +0200 Subject: [PATCH 2/2] #14493 Delete curves for all cases in one pass when deleting a summary ensemble deleteSummaryCaseCollection() looped over every case in the ensemble, and for each case scanned every summary plot and called updateConnectedEditors() on every multi plot. For an ensemble with many realizations this scanned each plot once per realization, and updated the connected editors once per realization and multi plot. This showed up as a hot spot in the profiler. Replace deleteCurvesAssosiatedWithCase() with deleteCurvesAssosiatedWithCases(), which takes a set of cases and returns whether anything was deleted. Each plot is now scanned once, and the connected editors of a multi plot are updated only when that multi plot actually lost a curve. RicCloseSummaryCaseFeature and RicCloseObservedDataFeature are updated to the new signature. RicCloseSummaryCaseFeature also scans each plot once instead of once per case. --- .../Commands/RicCloseObservedDataFeature.cpp | 2 +- .../Commands/RicCloseSummaryCaseFeature.cpp | 15 ++++++------ .../RicDeleteSummaryCaseCollectionFeature.cpp | 23 +++++++++++++------ .../Summary/RimSummaryCurveCollection.cpp | 6 +++-- .../Summary/RimSummaryCurveCollection.h | 5 +++- .../Summary/RimSummaryPlot.cpp | 6 +++-- .../ProjectDataModel/Summary/RimSummaryPlot.h | 3 ++- 7 files changed, 39 insertions(+), 21 deletions(-) diff --git a/ApplicationLibCode/Commands/RicCloseObservedDataFeature.cpp b/ApplicationLibCode/Commands/RicCloseObservedDataFeature.cpp index aa7ff8ea74a..3c3c0bad19e 100644 --- a/ApplicationLibCode/Commands/RicCloseObservedDataFeature.cpp +++ b/ApplicationLibCode/Commands/RicCloseObservedDataFeature.cpp @@ -60,7 +60,7 @@ void RicCloseObservedDataFeature::deleteObservedSummaryData( const std::vectorsummaryPlots() ) { - summaryPlot->deleteCurvesAssosiatedWithCase( observedData ); + summaryPlot->deleteCurvesAssosiatedWithCases( { observedData } ); } multiPlot->updateConnectedEditors(); } diff --git a/ApplicationLibCode/Commands/RicCloseSummaryCaseFeature.cpp b/ApplicationLibCode/Commands/RicCloseSummaryCaseFeature.cpp index 10d3e659339..3170bd1e9d3 100644 --- a/ApplicationLibCode/Commands/RicCloseSummaryCaseFeature.cpp +++ b/ApplicationLibCode/Commands/RicCloseSummaryCaseFeature.cpp @@ -42,6 +42,8 @@ #include +#include + CAF_CMD_SOURCE_INIT( RicCloseSummaryCaseFeature, "RicCloseSummaryCaseFeature" ); //-------------------------------------------------------------------------------------------------- @@ -66,16 +68,15 @@ void RicCloseSummaryCaseFeature::deleteSummaryCases( std::vector( cases ); - for ( RimSummaryCase* summaryCase : cases ) + const std::set casesToDelete( cases.begin(), cases.end() ); + + for ( RimSummaryMultiPlot* multiPlot : summaryPlotColl->multiPlots() ) { - for ( RimSummaryMultiPlot* multiPlot : summaryPlotColl->multiPlots() ) + for ( RimSummaryPlot* summaryPlot : multiPlot->summaryPlots() ) { - for ( RimSummaryPlot* summaryPlot : multiPlot->summaryPlots() ) - { - summaryPlot->deleteCurvesAssosiatedWithCase( summaryCase ); - } - plotsToUpdate.insert( multiPlot ); + summaryPlot->deleteCurvesAssosiatedWithCases( casesToDelete ); } + plotsToUpdate.insert( multiPlot ); } summaryCaseMainCollection->removeCases( cases ); diff --git a/ApplicationLibCode/Commands/RicDeleteSummaryCaseCollectionFeature.cpp b/ApplicationLibCode/Commands/RicDeleteSummaryCaseCollectionFeature.cpp index 1bde3cee12d..c6c569b5718 100644 --- a/ApplicationLibCode/Commands/RicDeleteSummaryCaseCollectionFeature.cpp +++ b/ApplicationLibCode/Commands/RicDeleteSummaryCaseCollectionFeature.cpp @@ -41,6 +41,8 @@ #include #include +#include + CAF_CMD_SOURCE_INIT( RicDeleteSummaryCaseCollectionFeature, "RicDeleteSummaryCaseCollectionFeature" ); //-------------------------------------------------------------------------------------------------- @@ -48,18 +50,25 @@ CAF_CMD_SOURCE_INIT( RicDeleteSummaryCaseCollectionFeature, "RicDeleteSummaryCas //-------------------------------------------------------------------------------------------------- void RicDeleteSummaryCaseCollectionFeature::deleteSummaryCaseCollection( RimSummaryEnsemble* caseCollection ) { + auto cases = caseCollection->allSummaryCases(); + if ( cases.empty() ) return; + + // Delete the curves for all the cases in one pass per plot, and update each multi plot only if it actually lost a + // curve. Doing this per case meant scanning every plot once per realization and updating the connected editors + // once per realization and multi plot. + const std::set casesToDelete( cases.begin(), cases.end() ); + RimSummaryMultiPlotCollection* summaryPlotColl = RiaSummaryTools::summaryMultiPlotCollection(); - for ( RimSummaryCase* summaryCase : caseCollection->allSummaryCases() ) + for ( RimSummaryMultiPlot* multiPlot : summaryPlotColl->multiPlots() ) { - for ( RimSummaryMultiPlot* multiPlot : summaryPlotColl->multiPlots() ) + bool curvesDeleted = false; + for ( RimSummaryPlot* summaryPlot : multiPlot->summaryPlots() ) { - for ( RimSummaryPlot* summaryPlot : multiPlot->summaryPlots() ) - { - summaryPlot->deleteCurvesAssosiatedWithCase( summaryCase ); - } - multiPlot->updateConnectedEditors(); + if ( summaryPlot->deleteCurvesAssosiatedWithCases( casesToDelete ) ) curvesDeleted = true; } + + if ( curvesDeleted ) multiPlot->updateConnectedEditors(); } } diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp index bf1954bcc7d..830d696dfaf 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.cpp @@ -229,7 +229,7 @@ std::vector RimSummaryCurveCollection::curves() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSummaryCurveCollection::deleteCurvesAssosiatedWithCase( RimSummaryCase* summaryCase ) +bool RimSummaryCurveCollection::deleteCurvesAssosiatedWithCases( const std::set& summaryCases ) { std::vector summaryCurvesToDelete; @@ -238,7 +238,7 @@ void RimSummaryCurveCollection::deleteCurvesAssosiatedWithCase( RimSummaryCase* if ( !summaryCurve ) continue; if ( !summaryCurve->summaryCaseY() ) continue; - if ( summaryCurve->summaryCaseY() == summaryCase ) + if ( summaryCases.contains( summaryCurve->summaryCaseY() ) ) { summaryCurvesToDelete.push_back( summaryCurve ); } @@ -248,6 +248,8 @@ void RimSummaryCurveCollection::deleteCurvesAssosiatedWithCase( RimSummaryCase* m_curves.removeChild( summaryCurve ); delete summaryCurve; } + + return !summaryCurvesToDelete.empty(); } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.h index 391f7f734db..b6e05e6a0dd 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryCurveCollection.h @@ -26,6 +26,8 @@ #include "cafPdmField.h" #include "cafPdmObject.h" +#include + class RimSummaryCase; class RimSummaryCurve; class RimSummaryPlot; @@ -75,7 +77,8 @@ class RimSummaryCurveCollection : public caf::PdmObject void deleteCurve( RimSummaryCurve* curve ); void removeCurve( RimSummaryCurve* curve ); - void deleteCurvesAssosiatedWithCase( RimSummaryCase* summaryCase ); + /// Delete the curves associated with any of the given cases. Returns true if any curve was deleted. + bool deleteCurvesAssosiatedWithCases( const std::set& summaryCases ); void deleteAllCurves(); void updateCaseNameHasChanged(); diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp index 3fe81d10ebd..817d8af98b7 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.cpp @@ -1497,12 +1497,14 @@ void RimSummaryPlot::deleteCurves( const std::vector& curves ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void RimSummaryPlot::deleteCurvesAssosiatedWithCase( RimSummaryCase* summaryCase ) +bool RimSummaryPlot::deleteCurvesAssosiatedWithCases( const std::set& summaryCases ) { if ( m_summaryCurveCollection ) { - m_summaryCurveCollection->deleteCurvesAssosiatedWithCase( summaryCase ); + return m_summaryCurveCollection->deleteCurvesAssosiatedWithCases( summaryCases ); } + + return false; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h index 4c4c3f49453..04e39531c11 100644 --- a/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h +++ b/ApplicationLibCode/ProjectDataModel/Summary/RimSummaryPlot.h @@ -107,7 +107,8 @@ class RimSummaryPlot : public RimPlot, public RimSummaryDataSourceStepping, publ void deleteCurves( const std::vector& curves ); - void deleteCurvesAssosiatedWithCase( RimSummaryCase* summaryCase ); + /// Delete the curves associated with any of the given cases. Returns true if any curve was deleted. + bool deleteCurvesAssosiatedWithCases( const std::set& summaryCases ); RimEnsembleCurveSetCollection* ensembleCurveSetCollection() const;