#14772 Python: Add WellPathCollection.import_well_paths as object method and forward importWellPaths to it

RimWellPathCollection_importWellPaths imports well path files given
explicitly and/or all well path files in a folder, and returns the
names of the imported well paths. The legacy RicImportWellPaths
command (a RICF_SOURCE_INIT feature in Commands/) forwards to it.
This commit is contained in:
Kristian Bendiksen committed 2026-09-22 14:19:23 +02:00
1 parent 6548c4f4db
commit 06d6e2da65
4 files changed
+294 -66

No files matched your search

@@ -29,6 +29,8 @@
#include "RimProject.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#include "RimcDataContainerString.h"
#include "RimcWellPathCollection.h"
#include "Riu3DMainWindowTools.h"
#include "RiuFileDialogTools.h"
@@ -74,83 +76,47 @@ RicImportWellPaths::RicImportWellPaths()
//--------------------------------------------------------------------------------------------------
caf::PdmScriptResponse RicImportWellPaths::execute()
{
QStringList errorMessages, warningMessages;
QStringList wellPathFiles;
QDir wellPathDir;
if ( m_wellPathFolder().isEmpty() )
RimProject* project = RimProject::current();
if ( !project || !project->activeOilField() || !project->activeOilField()->wellPathCollection() )
{
wellPathDir = QDir( RiaApplication::instance()->startDir() );
}
else
{
wellPathDir = QDir( m_wellPathFolder );
return caf::PdmScriptResponse( caf::PdmScriptResponse::COMMAND_ERROR, "importWellPaths: No well path collection available" );
}
if ( !m_wellPathFolder().isEmpty() )
{
if ( wellPathDir.exists() )
{
QStringList nameFilters;
nameFilters << RicImportWellPaths::wellPathNameFilters();
QStringList relativePaths = wellPathDir.entryList( nameFilters, QDir::Files | QDir::NoDotAndDotDot );
for ( const QString& relativePath : relativePaths )
{
wellPathFiles.push_back( wellPathDir.absoluteFilePath( relativePath ) );
}
}
else
{
errorMessages << ( wellPathDir.absolutePath() + " does not exist" );
}
}
RimWellPathCollection_importWellPaths method( project->activeOilField()->wellPathCollection() );
method.setWellPathFiles( m_wellPathFiles() );
method.setWellPathFolder( m_wellPathFolder() );
for ( const QString& wellPathFile : m_wellPathFiles() )
{
if ( QFileInfo::exists( wellPathFile ) )
{
wellPathFiles.push_back( wellPathFile );
}
else if ( QFileInfo::exists( wellPathDir.absoluteFilePath( wellPathFile ) ) )
{
wellPathFiles.push_back( wellPathDir.absoluteFilePath( wellPathFile ) );
}
else
{
errorMessages << ( wellPathFile + " does not exist" );
}
}
auto result = method.execute();
caf::PdmScriptResponse response;
if ( !wellPathFiles.empty() )
{
std::vector<RimWellPath*> importedWellPaths = importWellPaths( wellPathFiles, &warningMessages );
if ( !importedWellPaths.empty() )
{
RicImportWellPathsResult* wellPathsResult = new RicImportWellPathsResult;
for ( RimWellPath* wellPath : importedWellPaths )
{
wellPathsResult->wellPathNames.v().push_back( wellPath->name() );
}
response.setResult( wellPathsResult );
}
}
else
{
warningMessages << "No well paths found";
}
for ( const QString& warningMessage : warningMessages )
for ( const QString& warningMessage : method.warnings() )
{
response.updateStatus( caf::PdmScriptResponse::COMMAND_WARNING, warningMessage );
}
for ( const QString& errorMessage : errorMessages )
if ( !result )
{
response.updateStatus( caf::PdmScriptResponse::COMMAND_ERROR, errorMessage );
// Legacy behavior: "no files found" is a warning, missing files are errors
if ( result.error() == "No well path files found" )
{
response.updateStatus( caf::PdmScriptResponse::COMMAND_WARNING, "No well paths found" );
}
else
{
response.updateStatus( caf::PdmScriptResponse::COMMAND_ERROR, result.error() );
}
return response;
}
auto* names = dynamic_cast<RimcDataContainerString*>( result.value() );
if ( names && !names->m_stringValues().empty() )
{
auto* wellPathsResult = new RicImportWellPathsResult;
wellPathsResult->wellPathNames = names->m_stringValues();
response.setResult( wellPathsResult );
}
delete names;
return response;
}
@@ -43,10 +43,9 @@ public:
caf::PdmScriptResponse execute() override;
static std::vector<RimWellPath*> importWellPaths( const QStringList& wellPathFilePaths, QStringList* errorMessages );
static QStringList wellPathNameFilters();
protected:
static QStringList wellPathNameFilters();
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
@@ -21,19 +21,25 @@
#include "RiaApplication.h"
#include "RiaKeyValueStoreUtil.h"
#include "WellLogCommands/RicWellLogsImportFileFeature.h"
#include "WellPathCommands/RicImportWellPaths.h"
#include "RimEclipseCase.h"
#include "RimModeledWellPath.h"
#include "RimPointBasedWellPath.h"
#include "RimProject.h"
#include "RimWellLogLasFile.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#include "RimcDataContainerString.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cvfVector3.h"
#include <QDir>
#include <QFileInfo>
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimWellPathCollection, RimcWellPathCollection_importWellPath, "ImportWellPath" );
//--------------------------------------------------------------------------------------------------
@@ -209,3 +215,205 @@ std::expected<caf::PdmObjectHandle*, QString> RimcWellPathCollection_setMswNameG
return nullptr;
}
namespace
{
//--------------------------------------------------------------------------------------------------
/// Resolve explicit file paths (absolute, or relative to the folder / start dir) and all files in the folder matching
/// the name filters. Missing files are reported as errors.
//--------------------------------------------------------------------------------------------------
std::expected<QStringList, QString> resolveImportFiles( const std::vector<QString>& files, const QString& folder, const QStringList& nameFilters )
{
QStringList errorMessages;
QStringList resolvedFiles;
QDir baseDir = folder.isEmpty() ? QDir( RiaApplication::instance()->startDir() ) : QDir( folder );
if ( !folder.isEmpty() )
{
if ( baseDir.exists() )
{
for ( const QString& relativePath : baseDir.entryList( nameFilters, QDir::Files | QDir::NoDotAndDotDot ) )
{
resolvedFiles.push_back( baseDir.absoluteFilePath( relativePath ) );
}
}
else
{
errorMessages << ( baseDir.absolutePath() + " does not exist" );
}
}
for ( const QString& file : files )
{
if ( QFileInfo::exists( file ) )
{
resolvedFiles.push_back( file );
}
else if ( QFileInfo::exists( baseDir.absoluteFilePath( file ) ) )
{
resolvedFiles.push_back( baseDir.absoluteFilePath( file ) );
}
else
{
errorMessages << ( file + " does not exist" );
}
}
if ( !errorMessages.empty() ) return std::unexpected( errorMessages.join( "\n" ) );
return resolvedFiles;
}
} // namespace
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimWellPathCollection, RimWellPathCollection_importWellPaths, "importWellPaths" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPathCollection_importWellPaths::RimWellPathCollection_importWellPaths( caf::PdmObjectHandle* self )
: caf::PdmObjectMethod( self, PdmObjectMethod::NullPointerType::NULL_IS_INVALID, PdmObjectMethod::ResultType::PERSISTENT_FALSE )
{
CAF_PDM_InitObject( "Import Well Paths", "", "", "Import well paths from files and/or all well path files in a folder" );
CAF_PDM_InitScriptableField( &m_wellPathFiles, "WellPathFiles", std::vector<QString>(), "Well Path Files", "", "", "Well path files to import" );
CAF_PDM_InitScriptableField( &m_wellPathFolder,
"WellPathFolder",
QString(),
"Well Path Folder",
"",
"",
"Folder to import all well path files from. Also used to resolve relative file paths." );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathCollection_importWellPaths::setWellPathFiles( const std::vector<QString>& wellPathFiles )
{
m_wellPathFiles = wellPathFiles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathCollection_importWellPaths::setWellPathFolder( const QString& wellPathFolder )
{
m_wellPathFolder = wellPathFolder;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList RimWellPathCollection_importWellPaths::warnings() const
{
return m_warnings;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimWellPathCollection_importWellPaths::execute()
{
m_warnings.clear();
auto wellPathCollection = self<RimWellPathCollection>();
if ( !wellPathCollection ) return std::unexpected( "No well path collection is available." );
auto files = resolveImportFiles( m_wellPathFiles(), m_wellPathFolder(), RicImportWellPaths::wellPathNameFilters() );
if ( !files ) return std::unexpected( files.error() );
if ( files->empty() ) return std::unexpected( "No well path files found" );
std::vector<RimWellPath*> importedWellPaths = RicImportWellPaths::importWellPaths( files.value(), &m_warnings );
auto* result = new RimcDataContainerString();
for ( RimWellPath* wellPath : importedWellPaths )
{
result->m_stringValues.v().push_back( wellPath->name() );
}
return result;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellPathCollection_importWellPaths::classKeywordReturnedType() const
{
return RimcDataContainerString::classKeywordStatic();
}
CAF_PDM_OBJECT_METHOD_SOURCE_INIT( RimWellPathCollection, RimWellPathCollection_importWellLogFiles, "importWellLogFiles" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPathCollection_importWellLogFiles::RimWellPathCollection_importWellLogFiles( caf::PdmObjectHandle* self )
: caf::PdmObjectMethod( self, PdmObjectMethod::NullPointerType::NULL_IS_INVALID, PdmObjectMethod::ResultType::PERSISTENT_FALSE )
{
CAF_PDM_InitObject( "Import Well Log Files", "", "", "Import LAS files and attach them to the well paths with matching names" );
CAF_PDM_InitScriptableField( &m_wellLogFiles, "WellLogFiles", std::vector<QString>(), "Well Log Files", "", "", "Well log files to import" );
CAF_PDM_InitScriptableField( &m_wellLogFolder,
"WellLogFolder",
QString(),
"Well Log Folder",
"",
"",
"Folder to import all well log files from. Also used to resolve relative file paths." );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathCollection_importWellLogFiles::setWellLogFiles( const std::vector<QString>& wellLogFiles )
{
m_wellLogFiles = wellLogFiles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellPathCollection_importWellLogFiles::setWellLogFolder( const QString& wellLogFolder )
{
m_wellLogFolder = wellLogFolder;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList RimWellPathCollection_importWellLogFiles::warnings() const
{
return m_warnings;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::expected<caf::PdmObjectHandle*, QString> RimWellPathCollection_importWellLogFiles::execute()
{
m_warnings.clear();
auto wellPathCollection = self<RimWellPathCollection>();
if ( !wellPathCollection ) return std::unexpected( "No well path collection is available." );
auto files = resolveImportFiles( m_wellLogFiles(), m_wellLogFolder(), RicWellLogsImportFileFeature::wellLogFileNameFilters() );
if ( !files ) return std::unexpected( files.error() );
if ( files->empty() ) return std::unexpected( "No well log files found" );
std::vector<RimWellLogLasFile*> importedFiles = RicWellLogsImportFileFeature::importWellLogFiles( files.value(), &m_warnings );
auto* result = new RimcDataContainerString();
for ( RimWellLogLasFile* wellLogFile : importedFiles )
{
result->m_stringValues.v().push_back( wellLogFile->wellName() );
}
return result;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellPathCollection_importWellLogFiles::classKeywordReturnedType() const
{
return RimcDataContainerString::classKeywordStatic();
}
@@ -23,6 +23,7 @@
#include "cafPdmObjectMethod.h"
#include <QString>
#include <QStringList>
class RimEclipseResultCase;
@@ -78,3 +79,57 @@ public:
private:
caf::PdmField<QString> m_mswNameGrouping;
};
//==================================================================================================
/// Import well paths from a list of files and/or all well path files in a folder.
/// Returns the names of the imported well paths as a string container.
//==================================================================================================
class RimWellPathCollection_importWellPaths : public caf::PdmObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimWellPathCollection_importWellPaths( caf::PdmObjectHandle* self );
void setWellPathFiles( const std::vector<QString>& wellPathFiles );
void setWellPathFolder( const QString& wellPathFolder );
std::expected<caf::PdmObjectHandle*, QString> execute() override;
QString classKeywordReturnedType() const override;
/// Warnings from the last execute(), e.g. files that could not be parsed
QStringList warnings() const;
private:
caf::PdmField<std::vector<QString>> m_wellPathFiles;
caf::PdmField<QString> m_wellPathFolder;
QStringList m_warnings;
};
//==================================================================================================
/// Import well log files (LAS) from a list of files and/or all well log files in a folder, and attach
/// them to the well paths with matching names. Returns the names of the affected well paths.
//==================================================================================================
class RimWellPathCollection_importWellLogFiles : public caf::PdmObjectMethod
{
CAF_PDM_HEADER_INIT;
public:
RimWellPathCollection_importWellLogFiles( caf::PdmObjectHandle* self );
void setWellLogFiles( const std::vector<QString>& wellLogFiles );
void setWellLogFolder( const QString& wellLogFolder );
std::expected<caf::PdmObjectHandle*, QString> execute() override;
QString classKeywordReturnedType() const override;
/// Warnings from the last execute(), e.g. files that could not be parsed
QStringList warnings() const;
private:
caf::PdmField<std::vector<QString>> m_wellLogFiles;
caf::PdmField<QString> m_wellLogFolder;
QStringList m_warnings;
};