Files
ResInsight/ApplicationLibCode/Commands/RicCreateEnsembleWellLogFeature.cpp
T

306 lines
12 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaColorTables.h"
#include "RiaGuiApplication.h"
#include "RiaImportEclipseCaseTools.h"
#include "RiaLogging.h"
#include "RiaPreferencesGrid.h"
#include "RiaQStringFormatter.h"
#include "RiaResultNames.h"
#include "RicCloseCaseFeature.h"
#include "RicCreateEnsembleWellLogUi.h"
#include "RicImportEnsembleWellLogsFeature.h"
#include "RicImportGeneralDataFeature.h"
#include "RicRecursiveFileSearchDialog.h"
#include "RifReaderSettings.h"
#include "WellPathCommands/RicImportWellPaths.h"
#include "RigLasFileExporter.h"
#include "RimDialogData.h"
#include "RimEclipseCase.h"
#include "RimEnsembleWellLogCurveSet.h"
#include "RimMainPlotCollection.h"
#include "RimProject.h"
#include "RimWellLogExtractionCurve.h"
#include "RimWellLogTrack.h"
#include "RimWellPath.h"
#include "RimcWellLogPlot.h"
#include "RimcWellLogPlotCollection.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>
#include <memory>
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( RiaGuiApplication::widgetToUseAsParent(),
"Choose Eclipse Cases",
defaultDir,
pathFilter,
fileNameFilter,
{ RicRecursiveFileSearchDialog::FileType::GRDECL,
RicRecursiveFileSearchDialog::FileType::EGRID } );
if ( !result.ok || result.files.isEmpty() )
{
return;
}
// Use case data from first case
RimEclipseCase* eclipseCase = loadEclipseCase( result.files[0] );
if ( !eclipseCase ) return;
RicCreateEnsembleWellLogUi* ui = RimProject::current()->dialogData()->createEnsembleWellLogUi();
ui->setCaseData( eclipseCase->eclipseCaseData() );
// Automatically selected the well path the dialog was triggered on (if any)
auto* wellPath = caf::SelectionManager::instance()->selectedItemOfType<RimWellPath>();
if ( wellPath )
{
ui->setWellPathSource( RicCreateEnsembleWellLogUi::WellPathSource::PROJECT_WELLS );
ui->setWellPathFromProject( wellPath );
}
RiuPropertyViewTabWidget propertyDialog( Riu3DMainWindowTools::mainWindowWidget(), ui, "Create Ensemble Well Log", ui->tabNames() );
if ( propertyDialog.exec() == QDialog::Accepted && !ui->properties().empty() )
{
auto stdList = std::list<QString>( result.files.begin(), result.files.end() );
executeCommand( *ui, stdList );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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 = RimMainPlotCollection::current()->wellLogPlotCollection();
RimWellPath* wellPath = nullptr;
if ( ui.wellPathSource() == RicCreateEnsembleWellLogUi::WellPathSource::FILE )
{
if ( ui.wellPathFilePath().isEmpty() ) return;
// Load well path from file
QStringList wellPathFilePaths;
wellPathFilePaths << ui.wellPathFilePath();
QStringList errorMessages;
std::vector<RimWellPath*> wellPaths = RicImportWellPaths::importWellPaths( wellPathFilePaths, &errorMessages );
if ( wellPaths.empty() ) return;
wellPath = wellPaths[0];
}
else
{
CAF_ASSERT( ui.wellPathSource() == RicCreateEnsembleWellLogUi::WellPathSource::PROJECT_WELLS );
wellPath = ui.wellPathFromProject();
}
if ( !wellPath ) return;
QStringList allLasFileNames;
for ( const 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( std::format( "Failed to load model from file: ", fileName ) );
return;
}
// Create missing directories before extraction
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( std::format( "Unable to create directory for well log export: ", exportFolder ) );
RicCloseCaseFeature::deleteEclipseCase( eclipseCase );
return;
}
}
// Create standalone extraction curves for each property and load data
std::vector<std::unique_ptr<RimWellLogExtractionCurve>> curves;
for ( const auto& property : properties )
{
const QString& propertyName = property.first;
RiaDefines::ResultCatType resultCategoryType = property.second;
auto curve = std::make_unique<RimWellLogExtractionCurve>();
curve->setWellPath( wellPath );
curve->setCase( eclipseCase );
curve->setCurrentTimeStep( ui.timeStep() );
if ( resultCategoryType == RiaDefines::ResultCatType::FORMATION_NAMES )
curve->setEclipseResultVariable( RiaResultNames::activeFormationNamesResultName() );
else
curve->setEclipseResultVariable( propertyName );
curve->setEclipseResultCategory( resultCategoryType );
curve->loadDataAndUpdate( false );
curves.push_back( std::move( curve ) );
}
// Export to LAS file
std::vector<RimWellLogCurve*> wellLogCurves;
for ( const auto& curve : curves )
wellLogCurves.push_back( curve.get() );
const QString filePrefix = "";
const bool capitalizeFileName = false;
const bool alwaysOverwrite = true;
const bool convertCurveUnits = false;
RigLasFileExporter lasExporter( wellLogCurves );
std::vector<QString> lasFiles =
lasExporter.writeToFolder( exportFolder, filePrefix, capitalizeFileName, alwaysOverwrite, convertCurveUnits );
for ( const auto& lasFile : lasFiles )
allLasFileNames << lasFile;
RicCloseCaseFeature::deleteEclipseCase( eclipseCase );
}
if ( ui.autoCreateEnsembleWellLogs() )
{
std::vector<RimEnsembleWellLogs*> ensembleWellLogs =
RicImportEnsembleWellLogsFeature::createEnsembleWellLogsFromFiles( allLasFileNames,
RiaDefines::EnsembleGroupingMode::FMU_FOLDER_STRUCTURE );
for ( auto ensembleWellLog : ensembleWellLogs )
{
if ( ensembleWellLog )
{
RimEclipseCase* eclipseCase = nullptr;
// Create the well log plot
RimWellLogPlot* wellLogPlot =
RimcWellLogPlotCollection_newWellLogPlot::createWellLogPlot( plotCollection, wellPath, eclipseCase );
// Create a track per property
int trackNum = 0;
for ( const auto& property : properties )
{
// Create well log track
cvf::Color3f color = RiaColorTables::normalPaletteColors().cycledColor3f( trackNum );
QString title = QString( "Track %1" ).arg( trackNum );
RimWellLogTrack* wellLogTrack =
RimcWellLogPlot_newWellLogTrack::createWellLogTrack( wellLogPlot, eclipseCase, wellPath, title );
auto* ensembleWellLogCurveSet = new RimEnsembleWellLogCurveSet();
ensembleWellLogCurveSet->setEnsembleWellLogs( ensembleWellLog );
ensembleWellLogCurveSet->setColor( color );
ensembleWellLogCurveSet->setWellLogChannelName( property.first );
wellLogTrack->setEnsembleWellLogCurveSet( ensembleWellLogCurveSet );
ensembleWellLogCurveSet->loadDataAndUpdate( true );
trackNum++;
}
wellLogPlot->updateConnectedEditors();
plotCollection->updateConnectedEditors();
RiuPlotMainWindowTools::showPlotMainWindow();
RiuPlotMainWindowTools::onObjectAppended( 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 );
}
bool createView = false;
bool createPlot = false;
RifReaderSettings readerSettings = RiaPreferencesGrid::gridOnlyReaderSettings();
auto openResult =
RicImportGeneralDataFeature::openEclipseFilesFromFileNames( QStringList( { absolutePath } ), createPlot, createView, readerSettings );
if ( !openResult.createdCaseIds.empty() )
{
return RimProject::current()->eclipseCaseFromCaseId( openResult.createdCaseIds.front() );
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateEnsembleWellLogFeature::onActionTriggered( bool isChecked )
{
openDialogAndExecuteCommand();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicCreateEnsembleWellLogFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "Create Ensemble Well Log..." );
}