mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
#14772 Python: Add EclipseView.export_current_property and forward exportPropertyInViews to it
RimEclipseView_exportCurrentProperty exports the cell result shown in the view at its current time step to a GRDECL style text file, and requires an explicit export file. RicfExportPropertyInViews selects the views by id/name, resolves the default file names from the command file executor's PROPERTIES export folder, and forwards to it for each view. The method is named exportCurrentProperty rather than exportProperty to avoid shadowing the legacy View.export_property() wrapper (different signature) in the generated Python class hierarchy. The legacy wrapper is kept and emits a DeprecationWarning.
This commit is contained in:
1 parent
d2078613a8
commit
1f06f02b39
5 files changed
+188
-88
No files matched your search
@@ -16,30 +16,24 @@
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RicfExportProperty.h"
|
||||
|
||||
#include "ExportCommands/RicEclipseCellResultToFileImpl.h"
|
||||
#include "RicfExportPropertyInViews.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
|
||||
#include "RicfApplicationTools.h"
|
||||
#include "RicfCommandFileExecutor.h"
|
||||
#include "RicfExportPropertyInViews.h"
|
||||
|
||||
#include "RigResultAccessorFactory.h"
|
||||
#include "RicfCommandForwarding.h"
|
||||
|
||||
#include "Rim3dView.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseCellColors.h"
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimcEclipseView.h"
|
||||
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafUtils.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RicfExportPropertyInViews, "exportPropertyInViews" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -58,108 +52,66 @@ RicfExportPropertyInViews::RicfExportPropertyInViews()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
caf::PdmScriptResponse RicfExportPropertyInViews::execute()
|
||||
{
|
||||
using TOOLS = RicfApplicationTools;
|
||||
const QString commandName = classKeyword();
|
||||
|
||||
RimEclipseCase* eclipseCase = TOOLS::caseFromId( m_caseId() );
|
||||
auto rimCase = RicfForwarding::findCase( m_caseId() );
|
||||
if ( !rimCase ) return RicfForwarding::errorResponse( rimCase.error(), commandName );
|
||||
|
||||
auto* eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase.value() );
|
||||
if ( !eclipseCase )
|
||||
{
|
||||
QString error( QString( "exportProperty: Could not find case with ID %1" ).arg( m_caseId() ) );
|
||||
RiaLogging::error( error.toStdString() );
|
||||
return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, error );
|
||||
return RicfForwarding::errorResponse( QString( "Case with ID %1 is not an Eclipse case" ).arg( m_caseId() ), commandName );
|
||||
}
|
||||
|
||||
// Select the views by id or name. No filter means all views of the case.
|
||||
std::vector<RimEclipseView*> viewsForExport;
|
||||
|
||||
for ( Rim3dView* v : eclipseCase->views() )
|
||||
{
|
||||
RimEclipseView* view = dynamic_cast<RimEclipseView*>( v );
|
||||
auto* view = dynamic_cast<RimEclipseView*>( v );
|
||||
if ( !view ) continue;
|
||||
|
||||
if ( m_viewNames().empty() && m_viewIds().empty() )
|
||||
{
|
||||
viewsForExport.push_back( view );
|
||||
}
|
||||
else
|
||||
{
|
||||
bool matchingIdOrName = false;
|
||||
bool matching = m_viewNames().empty() && m_viewIds().empty();
|
||||
|
||||
for ( auto viewId : m_viewIds() )
|
||||
if ( !matching )
|
||||
{
|
||||
matching = std::find( m_viewIds().begin(), m_viewIds().end(), view->id() ) != m_viewIds().end();
|
||||
}
|
||||
|
||||
if ( !matching )
|
||||
{
|
||||
for ( const auto& viewName : m_viewNames() )
|
||||
{
|
||||
if ( view->id() == viewId )
|
||||
if ( view->name().compare( viewName, Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
matchingIdOrName = true;
|
||||
matching = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !matchingIdOrName )
|
||||
{
|
||||
for ( const auto& viewName : m_viewNames() )
|
||||
{
|
||||
if ( view->name().compare( viewName, Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
matchingIdOrName = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( matchingIdOrName )
|
||||
{
|
||||
viewsForExport.push_back( view );
|
||||
}
|
||||
}
|
||||
|
||||
if ( matching ) viewsForExport.push_back( view );
|
||||
}
|
||||
|
||||
// Resolve the default export folder from the command file executor state. The Rimc method requires an explicit file.
|
||||
QDir propertiesDir( RicfCommandFileExecutor::instance()->getExportPath( RicfCommandFileExecutor::ExportType::PROPERTIES ) );
|
||||
|
||||
caf::PdmScriptResponse response;
|
||||
|
||||
for ( const auto& view : viewsForExport )
|
||||
for ( RimEclipseView* view : viewsForExport )
|
||||
{
|
||||
cvf::ref<RigResultAccessor> resultAccessor = nullptr;
|
||||
RimEclipseView_exportCurrentProperty method( view );
|
||||
method.setExportFile( propertiesDir.filePath( RimEclipseView_exportCurrentProperty::defaultFileBaseName( view ) ) );
|
||||
method.setUndefinedValue( m_undefinedValue() );
|
||||
|
||||
auto result = method.execute();
|
||||
if ( !result )
|
||||
{
|
||||
const int mainGridIndex = 0;
|
||||
|
||||
resultAccessor = RigResultAccessorFactory::createFromResultDefinition( eclipseCase->eclipseCaseData(),
|
||||
mainGridIndex,
|
||||
view->currentTimeStep(),
|
||||
view->cellResult() );
|
||||
}
|
||||
|
||||
const QString propertyName = view->cellResult()->resultVariableUiShortName();
|
||||
|
||||
if ( resultAccessor.isNull() )
|
||||
{
|
||||
QString warning = QString( "exportProperty: Could not find property. Case ID %1, time step %2, property '%3'" )
|
||||
.arg( m_caseId() )
|
||||
.arg( view->currentTimeStep() )
|
||||
.arg( propertyName );
|
||||
// Legacy behavior: a missing property in one view is a warning, not an error, and the export continues
|
||||
QString warning = QString( "%1: %2" ).arg( commandName ).arg( result.error() );
|
||||
RiaLogging::warning( warning.toStdString() );
|
||||
response.updateStatus( caf::PdmScriptResponse::COMMAND_WARNING, warning );
|
||||
continue;
|
||||
}
|
||||
|
||||
QDir propertiesDir( RicfCommandFileExecutor::instance()->getExportPath( RicfCommandFileExecutor::ExportType::PROPERTIES ) );
|
||||
|
||||
QString fileName =
|
||||
QString( "%1-%2-T%3-%4" ).arg( eclipseCase->caseUserDescription() ).arg( view->name() ).arg( view->currentTimeStep() ).arg( propertyName );
|
||||
|
||||
fileName = caf::Utils::makeValidFileBasename( fileName );
|
||||
const QString filePath = propertiesDir.filePath( fileName );
|
||||
|
||||
QString errorMsg;
|
||||
|
||||
bool writeEchoKeywords = false;
|
||||
bool worked = RicEclipseCellResultToFileImpl::writeResultToTextFile( filePath,
|
||||
eclipseCase->eclipseCaseData(),
|
||||
resultAccessor.p(),
|
||||
propertyName,
|
||||
m_undefinedValue,
|
||||
"exportPropertiesInViews",
|
||||
writeEchoKeywords,
|
||||
&errorMsg );
|
||||
if ( !worked )
|
||||
{
|
||||
return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, errorMsg );
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -18,6 +18,13 @@
|
||||
|
||||
#include "RimcEclipseView.h"
|
||||
|
||||
#include "ExportCommands/RicEclipseCellResultToFileImpl.h"
|
||||
|
||||
#include "RigResultAccessor.h"
|
||||
#include "RigResultAccessorFactory.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseCellColors.h"
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimFaultDistance.h"
|
||||
#include "RimFaultDistanceCollection.h"
|
||||
@@ -26,6 +33,7 @@
|
||||
|
||||
#include "cafPdmAbstractFieldScriptingCapability.h"
|
||||
#include "cafPdmFieldScriptingCapability.h"
|
||||
#include "cafUtils.h"
|
||||
|
||||
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseView, RimcEclipseView_addFaultDistance, "add_fault_distance" );
|
||||
|
||||
@@ -82,3 +90,94 @@ QString RimcEclipseView_addFaultDistance::classKeywordReturnedType() const
|
||||
{
|
||||
return RimFaultDistance::classKeywordStatic();
|
||||
}
|
||||
|
||||
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimEclipseView, RimEclipseView_exportCurrentProperty, "exportCurrentProperty" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEclipseView_exportCurrentProperty::RimEclipseView_exportCurrentProperty( caf::PdmObjectHandle* self )
|
||||
: caf::PdmVoidObjectMethod( self )
|
||||
{
|
||||
CAF_PDM_InitObject( "Export Current Property", "", "", "Export the cell result currently shown in the view to a GRDECL style text file" );
|
||||
|
||||
CAF_PDM_InitScriptableField( &m_exportFile, "ExportFile", QString(), "Export File", "", "", "Full path of the file to write" );
|
||||
CAF_PDM_InitScriptableField( &m_undefinedValue, "UndefinedValue", 0.0, "Undefined Value", "", "", "Value written for undefined cells" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEclipseView_exportCurrentProperty::setExportFile( const QString& exportFile )
|
||||
{
|
||||
m_exportFile = exportFile;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEclipseView_exportCurrentProperty::setUndefinedValue( double undefinedValue )
|
||||
{
|
||||
m_undefinedValue = undefinedValue;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::expected<caf::PdmObjectHandle*, QString> RimEclipseView_exportCurrentProperty::execute()
|
||||
{
|
||||
auto* view = self<RimEclipseView>();
|
||||
if ( !view ) return std::unexpected( "No view is available." );
|
||||
|
||||
if ( m_exportFile().isEmpty() ) return std::unexpected( "No export file specified." );
|
||||
|
||||
RimEclipseCase* eclipseCase = view->eclipseCase();
|
||||
if ( !eclipseCase || !eclipseCase->eclipseCaseData() ) return std::unexpected( "The view has no case data." );
|
||||
|
||||
const int mainGridIndex = 0;
|
||||
|
||||
cvf::ref<RigResultAccessor> resultAccessor = RigResultAccessorFactory::createFromResultDefinition( eclipseCase->eclipseCaseData(),
|
||||
mainGridIndex,
|
||||
view->currentTimeStep(),
|
||||
view->cellResult() );
|
||||
|
||||
const QString propertyName = view->cellResult()->resultVariableUiShortName();
|
||||
|
||||
if ( resultAccessor.isNull() )
|
||||
{
|
||||
return std::unexpected( QString( "Could not find property '%1' at time step %2 in view '%3'" )
|
||||
.arg( propertyName )
|
||||
.arg( view->currentTimeStep() )
|
||||
.arg( view->name() ) );
|
||||
}
|
||||
|
||||
const bool writeEchoKeywords = false;
|
||||
QString errorMessage;
|
||||
if ( !RicEclipseCellResultToFileImpl::writeResultToTextFile( m_exportFile(),
|
||||
eclipseCase->eclipseCaseData(),
|
||||
resultAccessor.p(),
|
||||
propertyName,
|
||||
m_undefinedValue(),
|
||||
"exportProperty",
|
||||
writeEchoKeywords,
|
||||
&errorMessage ) )
|
||||
{
|
||||
return std::unexpected( errorMessage );
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimEclipseView_exportCurrentProperty::defaultFileBaseName( const RimEclipseView* view )
|
||||
{
|
||||
if ( !view || !view->eclipseCase() ) return {};
|
||||
|
||||
const QString propertyName = view->cellResult()->resultVariableUiShortName();
|
||||
const QString fileName =
|
||||
QString( "%1-%2-T%3-%4" ).arg( view->eclipseCase()->caseUserDescription() ).arg( view->name() ).arg( view->currentTimeStep() ).arg( propertyName );
|
||||
|
||||
return caf::Utils::makeValidFileBasename( fileName );
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
class RimEclipseView;
|
||||
class RimFaultInView;
|
||||
|
||||
//==================================================================================================
|
||||
@@ -44,3 +45,26 @@ private:
|
||||
caf::PdmField<QString> m_resultName;
|
||||
caf::PdmPtrArrayField<RimFaultInView*> m_faults;
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
/// Export the cell result currently shown in the view (at the current time step) to a GRDECL style text file.
|
||||
//==================================================================================================
|
||||
class RimEclipseView_exportCurrentProperty : public caf::PdmVoidObjectMethod
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimEclipseView_exportCurrentProperty( caf::PdmObjectHandle* self );
|
||||
|
||||
void setExportFile( const QString& exportFile );
|
||||
void setUndefinedValue( double undefinedValue );
|
||||
|
||||
std::expected<caf::PdmObjectHandle*, QString> execute() override;
|
||||
|
||||
/// Default file base name: <case>-<view>-T<time step>-<property>
|
||||
static QString defaultFileBaseName( const RimEclipseView* view );
|
||||
|
||||
private:
|
||||
caf::PdmField<QString> m_exportFile;
|
||||
caf::PdmField<double> m_undefinedValue;
|
||||
};
|
||||
@@ -287,3 +287,19 @@ def test_export_property(rips_instance, initialize_test):
|
||||
)
|
||||
with pytest.raises(rips.RipsError):
|
||||
case.export_property(time_step=0, property_name="PORO")
|
||||
|
||||
|
||||
def test_export_current_property(rips_instance, initialize_test):
|
||||
case_path = dataroot.PATH + "/TEST10K_FLT_LGR_NNC/TEST10K_FLT_LGR_NNC.EGRID"
|
||||
case = rips_instance.project.load_case(case_path)
|
||||
view = case.create_view()
|
||||
view.set_time_step(1)
|
||||
with tempfile.TemporaryDirectory(prefix="rips") as tmpdirname:
|
||||
export_file = os.path.join(tmpdirname, "current.grdecl")
|
||||
view.export_current_property(export_file=export_file)
|
||||
assert os.path.exists(export_file)
|
||||
with open(export_file) as f:
|
||||
assert "SOIL" in f.read(200)
|
||||
|
||||
with pytest.raises(rips.RipsError):
|
||||
view.export_current_property()
|
||||
@@ -5,6 +5,7 @@ ResInsight 3d view module
|
||||
import Commands_pb2 as Cmd
|
||||
|
||||
import uuid
|
||||
import warnings
|
||||
import rips.project
|
||||
|
||||
import rips.case # Circular import of Case, which already imports View. Use full name.
|
||||
@@ -162,9 +163,17 @@ def export_visible_cells(
|
||||
def export_property(self, undefined_value=0.0):
|
||||
"""Export the current Eclipse property from the view
|
||||
|
||||
Deprecated: use EclipseView.export_current_property(export_file=...) instead, which requires
|
||||
an explicit file. This method writes to the PROPERTIES folder set by Instance.set_export_folder().
|
||||
|
||||
Arguments:
|
||||
undefined_value (double): Value to use for undefined values. Defaults to 0.0
|
||||
"""
|
||||
warnings.warn(
|
||||
"View.export_property() is deprecated, use EclipseView.export_current_property() with an explicit export_file instead",
|
||||
DeprecationWarning,
|
||||
stacklevel=3,
|
||||
)
|
||||
case_id = self.case().id
|
||||
return self._execute_command(
|
||||
exportPropertyInViews=Cmd.ExportPropertyInViewsRequest(
|
||||
|
||||
Reference in new issue
Block a user