#14772 Python: Add EclipseCase.create_saturation_pressure_plots as object method and forward createSaturationPressurePlots to it

RimEclipseResultCase_createSaturationPressurePlots exposes the time step
(the legacy command hardcodes 0) and returns an error when no plots
could be created. It only shows the plot window when a GUI is running;
the legacy code dereferenced RiaGuiApplication::instance()
unconditionally. RicfCreateSaturationPressurePlots resolves the cases
and loops, treating per-case failures as warnings as before.

The hand-written Case.create_saturation_pressure_plots() Python wrapper
is removed since the generated EclipseCase method shadows it.
This commit is contained in:
Kristian Bendiksen committed 2026-09-22 14:19:23 +02:00
1 parent 3ce81c4eca
commit cc1f09b665
5 files changed
+119 -57

No files matched your search

@@ -19,15 +19,13 @@
#include "RicfCreateSaturationPressurePlots.h"
#include "GridCrossPlotCommands/RicCreateSaturationPressurePlotsFeature.h"
#include "RiaGuiApplication.h"
#include "RiaLogging.h"
#include "RicfCommandForwarding.h"
#include "RimEclipseResultCase.h"
#include "RimMainPlotCollection.h"
#include "RimProject.h"
#include "RimSaturationPressurePlotCollection.h"
#include "RimcEclipseCase.h"
#include "cafPdmFieldScriptingCapability.h"
@@ -46,54 +44,48 @@ RicfCreateSaturationPressurePlots::RicfCreateSaturationPressurePlots()
//--------------------------------------------------------------------------------------------------
caf::PdmScriptResponse RicfCreateSaturationPressurePlots::execute()
{
std::vector<int> caseIds = m_caseIds();
if ( caseIds.empty() )
{
RimProject* project = RimProject::current();
if ( project )
{
auto eclipeCases = project->eclipseCases();
for ( auto c : eclipeCases )
{
caseIds.push_back( c->caseId() );
}
}
}
if ( caseIds.empty() )
{
QString error( "createSaturationPressurePlots: No cases found" );
RiaLogging::error( error.toStdString() );
return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, error );
}
const QString commandName = classKeyword();
RimProject* project = RimProject::current();
if ( !project )
{
QString error( "No project loaded" );
RiaLogging::error( error.toStdString() );
return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, error );
}
if ( !project ) return RicfForwarding::errorResponse( "No project loaded", commandName );
auto eclipeCases = project->eclipseCases();
for ( auto c : eclipeCases )
// Collect the result cases. No ids means all Eclipse result cases in the project.
std::vector<RimEclipseResultCase*> resultCases;
if ( m_caseIds().empty() )
{
auto eclipseResultCase = dynamic_cast<RimEclipseResultCase*>( c );
if ( !eclipseResultCase ) continue;
for ( auto caseId : caseIds )
for ( RimEclipseCase* c : project->eclipseCases() )
{
if ( c->caseId() == caseId )
{
int timeStep = 0;
RicCreateSaturationPressurePlotsFeature::createPlots( eclipseResultCase, timeStep );
}
if ( auto* resultCase = dynamic_cast<RimEclipseResultCase*>( c ) ) resultCases.push_back( resultCase );
}
}
else
{
for ( int caseId : m_caseIds() )
{
auto rimCase = RicfForwarding::findCase( caseId );
if ( !rimCase ) return RicfForwarding::errorResponse( rimCase.error(), commandName );
if ( auto* resultCase = dynamic_cast<RimEclipseResultCase*>( rimCase.value() ) ) resultCases.push_back( resultCase );
}
}
RimSaturationPressurePlotCollection* collection = RimMainPlotCollection::current()->saturationPressurePlotCollection();
collection->updateAllRequiredEditors();
RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow();
if ( resultCases.empty() ) return RicfForwarding::errorResponse( "No cases found", commandName );
return caf::PdmScriptResponse();
caf::PdmScriptResponse response;
for ( RimEclipseResultCase* resultCase : resultCases )
{
RimEclipseResultCase_createSaturationPressurePlots method( resultCase );
method.setTimeStep( 0 );
auto result = method.execute();
if ( !result )
{
// Legacy behavior: a case without the required data is skipped, not an error
QString warning = QString( "%1: %2" ).arg( commandName ).arg( result.error() );
RiaLogging::warning( warning.toStdString() );
response.updateStatus( caf::PdmScriptResponse::COMMAND_WARNING, warning );
}
}
return response;
}
@@ -29,6 +29,7 @@
#include "ExportCommands/RicExportLgrFeature.h"
#include "FractureCommands/RicCreateMultipleFracturesOptionItemUi.h"
#include "FractureCommands/RicCreateMultipleFracturesUi.h"
#include "GridCrossPlotCommands/RicCreateSaturationPressurePlotsFeature.h"
#include "RicCreateTemporaryLgrFeature.h"
#include "RicDeleteTemporaryLgrsFeature.h"
@@ -59,6 +60,7 @@
#include "RimOilField.h"
#include "RimProject.h"
#include "RimRoffCase.h"
#include "RimSaturationPressurePlotCollection.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
@@ -1450,3 +1452,56 @@ std::expected<caf::PdmObjectHandle*, QString> RimEclipseResultCase_exportFlowCha
return nullptr;
}
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseResultCase, RimEclipseResultCase_createSaturationPressurePlots, "createSaturationPressurePlots" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEclipseResultCase_createSaturationPressurePlots::RimEclipseResultCase_createSaturationPressurePlots( caf::PdmObjectHandle* self )
: caf::PdmVoidObjectMethod( self )
{
CAF_PDM_InitObject( "Create Saturation Pressure Plots",
"",
"",
"Create saturation pressure plots (PRESSURE vs PBUB/PDEW per EQUIL region) for the case" );
CAF_PDM_InitScriptableField( &m_timeStep, "TimeStep", 0, "Time Step", "", "", "Zero-based time step index" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEclipseResultCase_createSaturationPressurePlots::setTimeStep( int timeStep )
{
m_timeStep = timeStep;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimEclipseResultCase_createSaturationPressurePlots::execute()
{
auto* eclipseCase = self<RimEclipseResultCase>();
if ( !eclipseCase ) return std::unexpected( "No case is available." );
auto plots = RicCreateSaturationPressurePlotsFeature::createPlots( eclipseCase, m_timeStep() );
if ( plots.empty() )
{
return std::unexpected( QString( "No saturation pressure plots created for case '%1'. The case must have EQUIL data and the "
"PRESSURE, PBUB and PDEW results." )
.arg( eclipseCase->caseUserDescription() ) );
}
if ( auto* collection = RimMainPlotCollection::current()->saturationPressurePlotCollection() )
{
collection->updateAllRequiredEditors();
}
if ( RiaGuiApplication::isRunning() )
{
RiaGuiApplication::instance()->getOrCreateAndShowMainPlotWindow();
}
return nullptr;
}
@@ -404,3 +404,21 @@ private:
caf::PdmField<double> m_minimumCommunication;
caf::PdmField<double> m_aquiferCellThreshold;
};
//==================================================================================================
/// Create saturation pressure plots (PRESSURE vs PBUB/PDEW per EQUIL region) for the case.
//==================================================================================================
class RimEclipseResultCase_createSaturationPressurePlots : public caf::PdmVoidObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimEclipseResultCase_createSaturationPressurePlots( caf::PdmObjectHandle* self );
void setTimeStep( int timeStep );
std::expected<caf::PdmObjectHandle*, QString> execute() override;
private:
caf::PdmField<int> m_timeStep;
};
-11
View File
@@ -561,17 +561,6 @@ def create_lgr_for_completion(
)
@add_method(Case)
def create_saturation_pressure_plots(self) -> Any:
"""
Create saturation pressure plots for the current case
"""
case_ids = [self.id]
return self._execute_command(
createSaturationPressurePlots=Cmd.CreateSatPressPlotRequest(caseIds=case_ids)
)
@add_method(Case)
def available_properties(
self,
@@ -451,3 +451,11 @@ def test_10k_result_alias(rips_instance, initialize_test):
with pytest.raises(rips.RipsError, match="No such result"):
case.grid_property(rips.PropertyType.DYNAMIC_NATIVE, "SPOIL", 3)
def test_create_saturation_pressure_plots_requires_data(rips_instance, initialize_test):
# None of the test models carry EQUIL/PBUB/PDEW data, so the method must report a clear error
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
case = rips_instance.project.load_case(case_path)
with pytest.raises(rips.RipsError):
case.create_saturation_pressure_plots()