#7928 Add user interface for exporting multiple well logs.

This commit is contained in:
Kristian Bendiksen 2021-09-06 09:32:24 +02:00
parent a3a2aac9b6
commit 8f5beb8851
19 changed files with 782 additions and 43 deletions

View File

@ -75,6 +75,8 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RicImportGridModelFromSummaryCurveFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicGenerateMultipleSurfacesFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicGenerateMultipleSurfacesUi.h
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleWellLogFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleWellLogUi.h
)
set(SOURCE_GROUP_SOURCE_FILES
@ -153,6 +155,8 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RicImportGridModelFromSummaryCurveFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicGenerateMultipleSurfacesFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicGenerateMultipleSurfacesUi.cpp
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleWellLogFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleWellLogUi.cpp
)
if(Qt5Charts_FOUND)

View File

@ -0,0 +1,281 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicCreateEnsembleWellLogFeature.h"
#include "RiaApplication.h"
#include "RiaColorTables.h"
#include "RiaImportEclipseCaseTools.h"
#include "RiaLogging.h"
#include "ExportCommands/RicExportToLasFileFeature.h"
#include "RicCreateEnsembleWellLogUi.h"
#include "RicImportEnsembleWellLogsFeature.h"
#include "RicRecursiveFileSearchDialog.h"
#include "WellPathCommands/RicImportWellPaths.h"
#include "RimDialogData.h"
#include "RimEclipseCase.h"
#include "RimEnsembleWellLogCurveSet.h"
#include "RimMainPlotCollection.h"
#include "RimProject.h"
#include "RimWellLogTrack.h"
#include "RimcWellLogPlot.h"
#include "RimcWellLogPlotCollection.h"
#include "RimcWellLogTrack.h"
#include "Riu3DMainWindowTools.h"
#include "RiuPlotMainWindowTools.h"
#include "RiuPropertyViewTabWidget.h"
#include "cafCmdFeatureManager.h"
#include "cafPdmSettings.h"
#include "cafPdmUiPropertyViewDialog.h"
#include "cafProgressInfo.h"
#include "cafSelectionManager.h"
#include <QAction>
#include <QDir>
#include <QFileInfo>
CAF_CMD_SOURCE_INIT( RicCreateEnsembleWellLogFeature, "RicCreateEnsembleWellLogFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateEnsembleWellLogFeature::openDialogAndExecuteCommand()
{
// Get the list of egrid files
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory( "BINARY_GRID" );
QString pathFilter( "*" );
QString fileNameFilter( "*" );
RicRecursiveFileSearchDialogResult result =
RicRecursiveFileSearchDialog::runRecursiveSearchDialog( nullptr,
"Choose Eclipse Cases",
defaultDir,
pathFilter,
fileNameFilter,
QStringList( ".EGRID" ) );
if ( !result.ok || result.files.isEmpty() )
{
return;
}
// Use case data from first case
RimEclipseCase* eclipseCase = loadEclipseCase( result.files[0] );
RicCreateEnsembleWellLogUi* ui = RimProject::current()->dialogData()->createEnsembleWellLogUi();
ui->setCaseData( eclipseCase->eclipseCaseData() );
RiuPropertyViewTabWidget propertyDialog( Riu3DMainWindowTools::mainWindowWidget(),
ui,
"Create Ensemble Well Log",
ui->tabNames() );
if ( propertyDialog.exec() == QDialog::Accepted && !ui->properties().empty() && !ui->wellPathFilePath().isEmpty() )
{
executeCommand( *ui, result.files.toStdList() );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateEnsembleWellLogFeature::executeCommand( const RicCreateEnsembleWellLogUi& ui,
const std::list<QString>& fileNames )
{
caf::ProgressInfo progress( fileNames.size(), "Creating ensemble well log" );
std::vector<std::pair<QString, RiaDefines::ResultCatType>> properties = ui.properties();
RimWellLogPlotCollection* plotCollection = RimProject::current()->mainPlotCollection()->wellLogPlotCollection();
// Load well path from file
QStringList wellPathFilePaths;
wellPathFilePaths << ui.wellPathFilePath();
bool importGrouped = false;
QStringList errorMessages;
std::vector<RimWellPath*> wellPaths =
RicImportWellPaths::importWellPaths( wellPathFilePaths, importGrouped, &errorMessages );
if ( wellPaths.empty() ) return;
RimWellPath* wellPath = wellPaths[0];
QStringList allLasFileNames;
for ( auto fileName : fileNames )
{
auto task = progress.task( QString( "Extracting well log for %1" ).arg( fileName ) );
// Load eclipse case
RimEclipseCase* eclipseCase = loadEclipseCase( fileName );
if ( !eclipseCase )
{
RiaLogging::error( QString( "Failed to load model from file: " ).arg( fileName ) );
return;
}
// Create the well log plot
RimWellLogPlot* wellLogPlot =
RimcWellLogPlotCollection_newWellLogPlot::createWellLogPlot( plotCollection, wellPath, eclipseCase );
// Create well log track
QString title = "Track";
RimWellLogTrack* wellLogTrack =
RimcWellLogPlot_newWellLogTrack::createWellLogTrack( wellLogPlot, eclipseCase, wellPath, title );
// Create a well log curve for each property
for ( auto property : properties )
{
QString propertyName = property.first;
RiaDefines::ResultCatType resultCategoryType = property.second;
int timeStep = ui.timeStep();
RimcWellLogTrack_addExtractionCurve::addExtractionCurve( wellLogTrack,
eclipseCase,
wellPath,
propertyName,
resultCategoryType,
timeStep );
}
{
// Create missing directories
QString wellLogExportDirName = "lasexport";
QFileInfo fi( fileName );
QString exportFolder = fi.absoluteDir().absolutePath() + QString( "/%1/" ).arg( wellLogExportDirName );
if ( !fi.absoluteDir().exists( wellLogExportDirName ) )
{
if ( !fi.absoluteDir().mkpath( wellLogExportDirName ) )
{
RiaLogging::error( QString( "Unable to create directory for well log export: " ).arg( exportFolder ) );
return;
}
}
// Export to las file
QString filePrefix = "";
bool exportTvdRkb = false;
bool capitalizeFileNames = false;
bool alwaysOverwrite = true;
double resampleInterval = 0.0;
bool convertCurveUnits = false;
std::vector<QString> lasFiles = RicExportToLasFileFeature::exportToLasFiles( exportFolder,
filePrefix,
wellLogPlot,
exportTvdRkb,
capitalizeFileNames,
alwaysOverwrite,
resampleInterval,
convertCurveUnits );
for ( auto lasFile : lasFiles )
allLasFileNames << lasFile;
}
// Remove the temporary plots after export
plotCollection->removePlot( wellLogPlot );
}
if ( ui.autoCreateEnsembleWellLogs() )
{
RimEnsembleWellLogs* ensembleWellLogs =
RicImportEnsembleWellLogsFeature::createEnsembleWellLogsFromFiles( allLasFileNames );
if ( ensembleWellLogs )
{
RimEclipseCase* eclipseCase = nullptr;
// Create the well log plot
RimWellLogPlot* wellLogPlot =
RimcWellLogPlotCollection_newWellLogPlot::createWellLogPlot( plotCollection, wellPath, eclipseCase );
// Create a track per property
for ( auto property : properties )
{
// Create well log track
cvf::Color3f color = RiaColorTables::normalPaletteColors().cycledColor3f( wellLogPlot->plotCount() );
QString title = QString( "Track %1" ).arg( wellLogPlot->plotCount() );
RimWellLogTrack* wellLogTrack =
RimcWellLogPlot_newWellLogTrack::createWellLogTrack( wellLogPlot, eclipseCase, wellPath, title );
RimEnsembleWellLogCurveSet* ensembleWellLogCurveSet = new RimEnsembleWellLogCurveSet();
ensembleWellLogCurveSet->setEnsembleWellLogs( ensembleWellLogs );
ensembleWellLogCurveSet->setColor( color );
ensembleWellLogCurveSet->setWellLogChannelName( property.first );
wellLogTrack->setEnsembleWellLogCurveSet( ensembleWellLogCurveSet );
ensembleWellLogCurveSet->loadDataAndUpdate( true );
}
wellLogPlot->updateConnectedEditors();
RiuPlotMainWindowTools::showPlotMainWindow();
RiuPlotMainWindowTools::selectAsCurrentItem( wellLogPlot );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEclipseCase* RicCreateEnsembleWellLogFeature::loadEclipseCase( const QString& fileName )
{
QString absolutePath = fileName;
QFileInfo projectPathInfo( absolutePath );
if ( !projectPathInfo.exists() )
{
QDir startDir( RiaApplication::instance()->startDir() );
absolutePath = startDir.absoluteFilePath( fileName );
}
RiaImportEclipseCaseTools::FileCaseIdMap fileCaseIdMap;
bool createView = false;
bool doNotShowDialog = true;
bool ok = RiaImportEclipseCaseTools::openEclipseCasesFromFile( QStringList( { absolutePath } ),
createView,
&fileCaseIdMap,
doNotShowDialog );
if ( !ok || fileCaseIdMap.empty() ) return nullptr;
return RimProject::current()->eclipseCaseFromCaseId( fileCaseIdMap.begin()->second );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicCreateEnsembleWellLogFeature::isCommandEnabled()
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateEnsembleWellLogFeature::onActionTriggered( bool isChecked )
{
openDialogAndExecuteCommand();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateEnsembleWellLogFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "Create Ensemble Well Log..." );
}

View File

@ -0,0 +1,44 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
#include <list>
class RicCreateEnsembleWellLogUi;
class RimEclipseCase;
//==================================================================================================
///
//==================================================================================================
class RicCreateEnsembleWellLogFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
public:
static void openDialogAndExecuteCommand();
static void executeCommand( const RicCreateEnsembleWellLogUi& ui, const std::list<QString>& fileNames );
static RimEclipseCase* loadEclipseCase( const QString& fileName );
protected:
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
};

View File

@ -0,0 +1,231 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicCreateEnsembleWellLogUi.h"
#include "RiaApplication.h"
#include "RiaDefines.h"
#include "RigEclipseCaseData.h"
#include "RigEclipseResultAddress.h"
#include "RimEclipseCase.h"
#include "RimEclipseResultDefinition.h"
#include "RimTools.h"
#include "cafPdmObject.h"
#include "cafPdmUiCheckBoxEditor.h"
#include "cafPdmUiListEditor.h"
#include "cafPdmUiOrdering.h"
#include "cafPdmUiTreeSelectionEditor.h"
CAF_PDM_SOURCE_INIT( RicCreateEnsembleWellLogUi, "RicCreateEnsembleWellLogUi" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicCreateEnsembleWellLogUi::RicCreateEnsembleWellLogUi()
{
CAF_PDM_InitObject( "Create Ensemble Well Log", "", "", "" );
CAF_PDM_InitField( &m_autoCreateEnsembleWellLogs,
"AutoCreateEnsembleWellLogs",
false,
"Create Ensemble Well Logs From Exported Files",
"",
"",
"" );
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_autoCreateEnsembleWellLogs );
CAF_PDM_InitField( &m_timeStep, "TimeStep", 0, "Time Step", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_well, "Well", "Well", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_selectedKeywords, "SelectedProperties", "Selected Properties", "", "", "" );
m_selectedKeywords.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
m_tabNames << "Well"
<< "Properties";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicCreateEnsembleWellLogUi::~RicCreateEnsembleWellLogUi()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QStringList& RicCreateEnsembleWellLogUi::tabNames() const
{
return m_tabNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateEnsembleWellLogUi::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
if ( uiConfigName == m_tabNames[0] )
{
uiOrdering.add( &m_well );
uiOrdering.add( &m_autoCreateEnsembleWellLogs );
}
else if ( uiConfigName == m_tabNames[1] )
{
uiOrdering.add( &m_selectedKeywords );
uiOrdering.add( &m_timeStep );
}
uiOrdering.skipRemainingFields( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo>
RicCreateEnsembleWellLogUi::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly )
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_selectedKeywords )
{
RigCaseCellResultsData* resultData = m_caseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
std::vector<RiaDefines::ResultCatType> resultCategories = validResultCategories();
for ( auto catType : resultCategories )
{
QList<caf::PdmOptionItemInfo> allOptions =
RimEclipseResultDefinition::calcOptionsForVariableUiFieldStandard( catType, resultData );
bool isFirstOfCategory = true;
for ( caf::PdmOptionItemInfo option : allOptions )
{
if ( resultData->hasResultEntry( RigEclipseResultAddress( catType, option.optionUiText() ) ) )
{
if ( isFirstOfCategory )
{
// Add the category title only when there is at least one valid result
options.push_back(
caf::PdmOptionItemInfo::createHeader( caf::AppEnum<RiaDefines::ResultCatType>::uiText( catType ),
true ) );
isFirstOfCategory = false;
}
options.push_back( option );
}
}
}
}
else if ( fieldNeedingOptions == &m_timeStep )
{
RimTools::timeStepsForCase( m_caseData->ownerCase(), &options );
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicCreateEnsembleWellLogUi::autoCreateEnsembleWellLogs() const
{
return m_autoCreateEnsembleWellLogs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<QString, RiaDefines::ResultCatType>> RicCreateEnsembleWellLogUi::properties() const
{
std::vector<QString> selectedKeyWords = m_selectedKeywords();
auto findResultCategory = []( const QString& keyword,
const std::vector<RiaDefines::ResultCatType>& categories,
RigEclipseCaseData* caseData ) {
// Find the result category for a given keyword
RigCaseCellResultsData* resultData = caseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
for ( auto category : categories )
if ( resultData->hasResultEntry( RigEclipseResultAddress( category, keyword ) ) ) return category;
return RiaDefines::ResultCatType::UNDEFINED;
};
std::vector<RiaDefines::ResultCatType> resultCategories = validResultCategories();
std::vector<std::pair<QString, RiaDefines::ResultCatType>> props;
for ( auto keyword : selectedKeyWords )
{
auto resultCategory = findResultCategory( keyword, resultCategories, m_caseData );
props.push_back( std::make_pair( keyword, resultCategory ) );
}
return props;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RiaDefines::ResultCatType> RicCreateEnsembleWellLogUi::validResultCategories() const
{
return { RiaDefines::ResultCatType::STATIC_NATIVE,
RiaDefines::ResultCatType::DYNAMIC_NATIVE,
RiaDefines::ResultCatType::INPUT_PROPERTY };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RicCreateEnsembleWellLogUi::timeStep() const
{
return m_timeStep;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RicCreateEnsembleWellLogUi::wellPathFilePath() const
{
return m_well().path();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateEnsembleWellLogUi::setCaseData( RigEclipseCaseData* caseData )
{
m_caseData = caseData;
if ( m_selectedKeywords().empty() )
{
RigCaseCellResultsData* resultData = caseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL );
std::vector<QString> defaultKeywords = { "INDEX_K", "PORO", "PERMZ", "PRESSURE" };
std::vector<RiaDefines::ResultCatType> categories = validResultCategories();
for ( auto keyword : defaultKeywords )
{
for ( auto category : categories )
{
if ( resultData->hasResultEntry( RigEclipseResultAddress( category, keyword ) ) )
{
m_selectedKeywords.v().push_back( keyword );
break;
}
}
}
}
}

View File

@ -0,0 +1,68 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RiaDefines.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include <QString>
#include <QStringList>
class RigEclipseCaseData;
//==================================================================================================
///
//==================================================================================================
class RicCreateEnsembleWellLogUi : public caf::PdmObject
{
CAF_PDM_HEADER_INIT;
public:
RicCreateEnsembleWellLogUi();
~RicCreateEnsembleWellLogUi() override;
const QStringList& tabNames() const;
bool autoCreateEnsembleWellLogs() const;
int timeStep() const;
QString wellPathFilePath() const;
std::vector<std::pair<QString, RiaDefines::ResultCatType>> properties() const;
void setCaseData( RigEclipseCaseData* caseData );
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
std::vector<RiaDefines::ResultCatType> validResultCategories() const;
private:
caf::PdmField<caf::FilePath> m_well;
caf::PdmField<bool> m_autoCreateEnsembleWellLogs;
caf::PdmField<std::vector<QString>> m_selectedKeywords;
caf::PdmField<int> m_timeStep;
QStringList m_tabNames;
RigEclipseCaseData* m_caseData;
};

View File

@ -19,10 +19,9 @@
#include "RicImportEnsembleWellLogsFeature.h"
#include "RiaApplication.h"
#include "RiaEnsembleNameTools.h"
#include "RiaLogging.h"
#include "WellLogCommands/RicWellLogsImportFileFeature.h"
#include "RimEnsembleWellLogs.h"
#include "RimEnsembleWellLogsCollection.h"
#include "RimOilField.h"
@ -30,6 +29,7 @@
#include "RimWellLogFile.h"
#include "RicRecursiveFileSearchDialog.h"
#include "WellLogCommands/RicWellLogsImportFileFeature.h"
#include <QAction>
#include <QFileInfo>
@ -63,8 +63,15 @@ void RicImportEnsembleWellLogsFeature::onActionTriggered( bool isChecked )
QStringList fileNames = runRecursiveFileSearchDialog( "Import Ensemble Well Logs", pathCacheName );
if ( fileNames.isEmpty() ) return;
QString ensembleName = "Ensemble Well Logs";
if ( ensembleName.isEmpty() ) return;
createEnsembleWellLogsFromFiles( fileNames );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEnsembleWellLogs* RicImportEnsembleWellLogsFeature::createEnsembleWellLogsFromFiles( const QStringList& fileNames )
{
if ( fileNames.isEmpty() ) return nullptr;
std::vector<RimWellLogFile*> cases;
for ( QString fileNames : fileNames )
@ -78,15 +85,19 @@ void RicImportEnsembleWellLogsFeature::onActionTriggered( bool isChecked )
}
}
if ( cases.empty() ) return;
if ( cases.empty() ) return nullptr;
RimEnsembleWellLogs* ensemble = new RimEnsembleWellLogs;
QString ensembleName = RiaEnsembleNameTools::findSuitableEnsembleName( fileNames );
ensemble->setName( ensembleName );
for ( auto wellLogFile : cases )
ensemble->addWellLogFile( wellLogFile );
RimProject::current()->activeOilField()->ensembleWellLogsCollection->addEnsembleWellLogs( ensemble );
RimProject::current()->activeOilField()->ensembleWellLogsCollection->updateConnectedEditors();
return ensemble;
}
//--------------------------------------------------------------------------------------------------

View File

@ -22,6 +22,8 @@
#include <QString>
class RimEnsembleWellLogs;
//==================================================================================================
///
//==================================================================================================
@ -31,6 +33,8 @@ class RicImportEnsembleWellLogsFeature : public caf::CmdFeature
RicImportEnsembleWellLogsFeature();
static RimEnsembleWellLogs* createEnsembleWellLogsFromFiles( const QStringList& fileNames );
protected:
// Overrides
bool isCommandEnabled() override;

View File

@ -42,9 +42,10 @@ public:
RicImportWellPaths();
caf::PdmScriptResponse execute() override;
protected:
static std::vector<RimWellPath*>
importWellPaths( const QStringList& wellPathFilePaths, bool importGrouped, QStringList* errorMessages );
importWellPaths( const QStringList& wellPathFilePaths, bool importGrouped, QStringList* errorMessages );
protected:
static QStringList wellPathNameFilters();
bool isCommandEnabled() override;

View File

@ -340,6 +340,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
{
menuBuilder << "RicNewEditableWellPathFeature";
menuBuilder << "RicPasteModeledWellPathFeature";
menuBuilder << "RicCreateEnsembleWellLogFeature";
menuBuilder.addSeparator();
menuBuilder.subMenuStart( "Import" );
menuBuilder << "RicWellPathsImportFileFeature";

View File

@ -27,6 +27,7 @@
#include "ExportCommands/RicExportWellPathsUi.h"
#include "FractureCommands/RicCreateMultipleFracturesUi.h"
#include "HoloLensCommands/RicHoloLensExportToFolderUi.h"
#include "RicCreateEnsembleWellLogUi.h"
#include "RicGenerateMultipleSurfacesUi.h"
CAF_PDM_SOURCE_INIT( RimDialogData, "RimDialogData" );
@ -74,6 +75,9 @@ RimDialogData::RimDialogData()
"",
"" );
m_generateEnsembleSurfacesUi = new RicGenerateMultipleSurfacesUi();
CAF_PDM_InitFieldNoDefault( &m_createEnsembleWellLogUi, "CreateEnsembleWellLogUi", "Create Ensemble Well Log Ui", "", "", "" );
m_createEnsembleWellLogUi = new RicCreateEnsembleWellLogUi();
}
//--------------------------------------------------------------------------------------------------
@ -172,3 +176,11 @@ RicGenerateMultipleSurfacesUi* RimDialogData::generateEnsembleSurfacesUi() const
{
return m_generateEnsembleSurfacesUi;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicCreateEnsembleWellLogUi* RimDialogData::createEnsembleWellLogUi() const
{
return m_createEnsembleWellLogUi;
}

View File

@ -30,6 +30,7 @@ class RicExportWellPathsUi;
class RicExportLgrUi;
class RimMockModelSettings;
class RicGenerateMultipleSurfacesUi;
class RicCreateEnsembleWellLogUi;
//==================================================================================================
///
@ -63,6 +64,7 @@ public:
RicExportEclipseSectorModelUi* exportSectorModelUi() const;
RimMockModelSettings* mockModelSettings() const;
RicGenerateMultipleSurfacesUi* generateEnsembleSurfacesUi() const;
RicCreateEnsembleWellLogUi* createEnsembleWellLogUi() const;
private:
caf::PdmChildField<RicExportCarfinUi*> m_exportCarfin;
@ -74,4 +76,5 @@ private:
caf::PdmChildField<RicExportEclipseSectorModelUi*> m_exportSectorModelData;
caf::PdmChildField<RimMockModelSettings*> m_mockModelSettings;
caf::PdmChildField<RicGenerateMultipleSurfacesUi*> m_generateEnsembleSurfacesUi;
caf::PdmChildField<RicCreateEnsembleWellLogUi*> m_createEnsembleWellLogUi;
};

View File

@ -764,6 +764,7 @@ void RimEnsembleWellLogCurveSet::updateEnsembleCurves( const std::vector<RimWell
{
RimWellLogFileCurve* curve = new RimWellLogFileCurve;
plotTrack->addCurve( curve );
curve->setUiTreeHidden( true );
QString errorMessage;
if ( wellLogFile->readFile( &errorMessage ) )
@ -1153,3 +1154,19 @@ void RimEnsembleWellLogCurveSet::initAfterRead()
{
connectEnsembleCurveSetFilterSignals();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::setEnsembleWellLogs( RimEnsembleWellLogs* ensembleWellLogs )
{
m_ensembleWellLogs = ensembleWellLogs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::setWellLogChannelName( const QString& wellLogChannelName )
{
m_wellLogChannelName = wellLogChannelName;
}

View File

@ -117,6 +117,9 @@ public:
void updateStatistics();
void setEnsembleWellLogs( RimEnsembleWellLogs* ensembleWellLogs );
void setWellLogChannelName( const QString& wellLogChannelName );
private:
void updateEnsembleCurves( const std::vector<RimWellLogFile*>& curves );
void updateStatisticsCurves( const std::vector<RimWellLogFile*>& curves );

View File

@ -60,9 +60,20 @@ caf::PdmObjectHandle* RimcWellLogPlot_newWellLogTrack::execute()
if ( !wellLogPlot ) return nullptr;
RimWellLogTrack* plotTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, m_title, wellLogPlot );
if ( m_case() ) plotTrack->setFormationCase( m_case );
if ( m_wellPath() ) plotTrack->setFormationWellPath( m_wellPath );
return createWellLogTrack( wellLogPlot, m_case(), m_wellPath(), m_title() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogTrack* RimcWellLogPlot_newWellLogTrack::createWellLogTrack( RimWellLogPlot* wellLogPlot,
RimEclipseCase* eclipseCase,
RimWellPath* wellPath,
const QString& title )
{
RimWellLogTrack* plotTrack = RicNewWellLogPlotFeatureImpl::createWellLogPlotTrack( false, title, wellLogPlot );
if ( eclipseCase ) plotTrack->setFormationCase( eclipseCase );
if ( wellPath ) plotTrack->setFormationWellPath( wellPath );
plotTrack->setColSpan( RimPlot::TWO );
plotTrack->setLegendsVisible( true );
plotTrack->setPlotTitleVisible( true );

View File

@ -28,6 +28,7 @@
class RimEclipseCase;
class RimWellPath;
class RimWellLogTrack;
//==================================================================================================
///
@ -43,6 +44,11 @@ public:
bool resultIsPersistent() const override;
std::unique_ptr<PdmObjectHandle> defaultResult() const override;
static RimWellLogTrack* createWellLogTrack( RimWellLogPlot* wellLogPlot,
RimEclipseCase* eclipseCase,
RimWellPath* wellPath,
const QString& title );
private:
caf::PdmField<QString> m_title;
caf::PdmPtrField<RimEclipseCase*> m_case;

View File

@ -20,6 +20,7 @@
#include "RiaApplication.h"
#include "RiaGuiApplication.h"
#include "RimcWellLogPlot.h"
#include "WellLogCommands/RicNewWellLogPlotFeatureImpl.h"
#include "RimEclipseCase.h"
@ -64,20 +65,31 @@ caf::PdmObjectHandle* RimcWellLogPlotCollection_newWellLogPlot::execute()
if ( m_case && m_wellPath && wellLogPlotCollection )
{
newWellLogPlot = new RimWellLogPlot;
newWellLogPlot->setAsPlotMdiWindow();
wellLogPlotCollection->addWellLogPlot( newWellLogPlot );
newWellLogPlot->commonDataSource()->setCaseToApply( m_case );
newWellLogPlot->commonDataSource()->setWellPathToApply( m_wellPath );
newWellLogPlot->loadDataAndUpdate();
newWellLogPlot->updateConnectedEditors();
newWellLogPlot = createWellLogPlot( wellLogPlotCollection, m_wellPath, m_case );
}
return newWellLogPlot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogPlot* RimcWellLogPlotCollection_newWellLogPlot::createWellLogPlot( RimWellLogPlotCollection* wellLogPlotCollection,
RimWellPath* wellPath,
RimEclipseCase* eclipseCase )
{
RimWellLogPlot* newWellLogPlot = new RimWellLogPlot;
newWellLogPlot->setAsPlotMdiWindow();
wellLogPlotCollection->addWellLogPlot( newWellLogPlot );
newWellLogPlot->commonDataSource()->setCaseToApply( eclipseCase );
newWellLogPlot->commonDataSource()->setWellPathToApply( wellPath );
newWellLogPlot->loadDataAndUpdate();
newWellLogPlot->updateConnectedEditors();
return newWellLogPlot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -42,6 +42,10 @@ public:
bool resultIsPersistent() const override;
std::unique_ptr<PdmObjectHandle> defaultResult() const override;
static RimWellLogPlot* createWellLogPlot( RimWellLogPlotCollection* wellLogPlotCollection,
RimWellPath* wellPath,
RimEclipseCase* eclipseCase );
private:
caf::PdmPtrField<RimEclipseCase*> m_case;
caf::PdmPtrField<RimWellPath*> m_wellPath;

View File

@ -18,6 +18,7 @@
#include "RimcWellLogTrack.h"
#include "RiaApplication.h"
#include "RiaDefines.h"
#include "RiaGuiApplication.h"
#include "WellLogCommands/RicNewWellLogPlotFeatureImpl.h"
@ -61,37 +62,52 @@ caf::PdmObjectHandle* RimcWellLogTrack_addExtractionCurve::execute()
if ( m_case && m_wellPath && wellLogTrack )
{
RimWellLogExtractionCurve* curve = new RimWellLogExtractionCurve;
curve->setWellPath( m_wellPath );
curve->setCase( m_case );
curve->setCurrentTimeStep( m_timeStep );
curve->setEclipseResultVariable( m_propertyName );
RiaDefines::ResultCatType resultCategoryType = caf::AppEnum<RiaDefines::ResultCatType>::fromText( m_propertyType );
curve->setEclipseResultCategory( resultCategoryType );
wellLogTrack->addCurve( curve );
curve->loadDataAndUpdate( true );
curve->updateConnectedEditors();
wellLogTrack->setXAxisGridVisibility( RimWellLogPlot::AXIS_GRID_MAJOR );
wellLogTrack->setShowRegionLabels( true );
wellLogTrack->setAutoScaleXEnabled( true );
wellLogTrack->updateConnectedEditors();
wellLogTrack->setShowWindow( true );
RiaApplication::instance()->project()->updateConnectedEditors();
RimWellLogPlot* wellLogPlot = dynamic_cast<RimWellLogPlot*>( wellLogTrack->parentField() );
if ( wellLogPlot ) wellLogPlot->loadDataAndUpdate();
return curve;
return addExtractionCurve( wellLogTrack, m_case, m_wellPath, m_propertyName, resultCategoryType, m_timeStep );
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogExtractionCurve*
RimcWellLogTrack_addExtractionCurve::addExtractionCurve( RimWellLogTrack* wellLogTrack,
RimEclipseCase* eclipseCase,
RimWellPath* wellPath,
const QString& propertyName,
RiaDefines::ResultCatType resultCategoryType,
int timeStep )
{
RimWellLogExtractionCurve* curve = new RimWellLogExtractionCurve;
curve->setWellPath( wellPath );
curve->setCase( eclipseCase );
curve->setCurrentTimeStep( timeStep );
curve->setEclipseResultVariable( propertyName );
curve->setEclipseResultCategory( resultCategoryType );
wellLogTrack->addCurve( curve );
curve->loadDataAndUpdate( true );
curve->updateConnectedEditors();
wellLogTrack->setXAxisGridVisibility( RimWellLogPlot::AXIS_GRID_MAJOR );
wellLogTrack->setShowRegionLabels( true );
wellLogTrack->setAutoScaleXEnabled( true );
wellLogTrack->updateConnectedEditors();
wellLogTrack->setShowWindow( true );
RiaApplication::instance()->project()->updateConnectedEditors();
RimWellLogPlot* wellLogPlot = dynamic_cast<RimWellLogPlot*>( wellLogTrack->parentField() );
if ( wellLogPlot ) wellLogPlot->loadDataAndUpdate();
return curve;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -18,6 +18,8 @@
#pragma once
#include "RiaDefines.h"
#include "cafPdmField.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmObjectMethod.h"
@ -27,6 +29,7 @@
class RimEclipseCase;
class RimWellPath;
class RimWellLogTrack;
class RimWellLogExtractionCurve;
//==================================================================================================
///
@ -42,6 +45,13 @@ public:
bool resultIsPersistent() const override;
std::unique_ptr<PdmObjectHandle> defaultResult() const override;
static RimWellLogExtractionCurve* addExtractionCurve( RimWellLogTrack* wellLogTrack,
RimEclipseCase* eclipseCase,
RimWellPath* wellPath,
const QString& propertyName,
RiaDefines::ResultCatType resultCategoryType,
int timeStep );
private:
caf::PdmPtrField<RimEclipseCase*> m_case;
caf::PdmPtrField<RimWellPath*> m_wellPath;