mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-26 07:00:17 -05:00
* Add Add Well Picks button to well log formation settings * Expose formation zone colors and shading alpha from RFT track * Average observed pressures per formation with full min/max range * Show formation-colored observed pressure and depth filter in RFT correlation plots * Default new RFT correlation plots to formation filter and ensemble parameter coloring * Move Qwt code out of RFT correlation Rim classes * Align RFT correlation depth filter bars and click zones with displayed track formations
506 lines
21 KiB
C++
506 lines
21 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2026- 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 "RimWellLogFormationSettings.h"
|
|
|
|
#include "RiaSimWellBranchTools.h"
|
|
|
|
#include "RiaWellLogTrackDefines.h"
|
|
#include "RimCase.h"
|
|
#include "RimEclipseCase.h"
|
|
#include "RimOilField.h"
|
|
#include "RimProject.h"
|
|
#include "RimTools.h"
|
|
#include "RimWellLogTrack.h"
|
|
#include "RimWellPath.h"
|
|
|
|
#include "RicImportWellFormationsFeature.h"
|
|
|
|
#include "Formations/RimWellFormationsCollection.h"
|
|
#include "Formations/RimWellFormationsFile.h"
|
|
|
|
#include "RigEclipseCaseData.h"
|
|
|
|
#include "cafPdmUiComboBoxEditor.h"
|
|
#include "cafPdmUiGroup.h"
|
|
|
|
CAF_PDM_SOURCE_INIT( RimWellLogFormationSettings, "RimWellLogFormationSettings" );
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimWellLogFormationSettings::RimWellLogFormationSettings()
|
|
{
|
|
CAF_PDM_InitObject( "Formation Settings" );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_formationSource, "FormationSource", "Source" );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_formationTrajectoryType, "FormationTrajectoryType", "Trajectory" );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_formationWellPathForSourceCase, "FormationWellPath", "Well Path" );
|
|
m_formationWellPathForSourceCase.uiCapability()->setUiTreeChildrenHidden( true );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_formationWellPathForSourceWellPath, "FormationWellPathForSourceWellPath", "Well Path" );
|
|
m_formationWellPathForSourceWellPath.uiCapability()->setUiTreeChildrenHidden( true );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_wellFormationsFile, "FormationWellFormationsFile", "Formations File" );
|
|
m_wellFormationsFile.uiCapability()->setUiTreeChildrenHidden( true );
|
|
|
|
CAF_PDM_InitField( &m_wellNameInFormationsFile, "FormationWellNameInFile", QString(), "Well" );
|
|
m_wellNameInFormationsFile.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() );
|
|
|
|
CAF_PDM_InitField( &m_formationSimWellName, "FormationSimulationWellName", QString( "None" ), "Simulation Well" );
|
|
CAF_PDM_InitField( &m_formationBranchIndex, "FormationBranchIndex", 0, " " );
|
|
CAF_PDM_InitField( &m_formationBranchDetection,
|
|
"FormationBranchDetection",
|
|
true,
|
|
"Branch Detection",
|
|
"",
|
|
"Compute branches based on how simulation well cells are organized",
|
|
"" );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_formationCase, "FormationCase", "Formation Case" );
|
|
m_formationCase.uiCapability()->setUiTreeChildrenHidden( true );
|
|
|
|
CAF_PDM_InitFieldNoDefault( &m_formationLevel, "FormationLevel", "Well Pick Filter" );
|
|
|
|
CAF_PDM_InitField( &m_showFormationFluids, "ShowFormationFluids", false, "Show Fluids" );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RiaDefines::WellLogTrackFormationSource RimWellLogFormationSettings::formationSource() const
|
|
{
|
|
return m_formationSource();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setFormationSource( RiaDefines::WellLogTrackFormationSource source )
|
|
{
|
|
m_formationSource = source;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimCase* RimWellLogFormationSettings::formationCase() const
|
|
{
|
|
return m_formationCase();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setFormationCase( RimCase* rimCase )
|
|
{
|
|
m_formationCase = rimCase;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RiaDefines::WellLogTrackTrajectoryType RimWellLogFormationSettings::trajectoryType() const
|
|
{
|
|
return m_formationTrajectoryType();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setTrajectoryType( RiaDefines::WellLogTrackTrajectoryType trajectoryType )
|
|
{
|
|
m_formationTrajectoryType = trajectoryType;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimWellPath* RimWellLogFormationSettings::wellPathForSourceCase() const
|
|
{
|
|
return m_formationWellPathForSourceCase();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setWellPathForSourceCase( RimWellPath* wellPath )
|
|
{
|
|
m_formationWellPathForSourceCase = wellPath;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimWellPath* RimWellLogFormationSettings::wellPathForSourceWellPath() const
|
|
{
|
|
return m_formationWellPathForSourceWellPath();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setWellPathForSourceWellPath( RimWellPath* wellPath )
|
|
{
|
|
m_formationWellPathForSourceWellPath = wellPath;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimWellFormationsFile* RimWellLogFormationSettings::wellFormationsFile() const
|
|
{
|
|
return m_wellFormationsFile();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setWellFormationsFile( RimWellFormationsFile* file )
|
|
{
|
|
m_wellFormationsFile = file;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimWellLogFormationSettings::wellNameInFormationsFile() const
|
|
{
|
|
return m_wellNameInFormationsFile();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setWellNameInFormationsFile( const QString& wellName )
|
|
{
|
|
m_wellNameInFormationsFile = wellName;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const RigWellPathFormations* RimWellLogFormationSettings::resolveWellPickFormations() const
|
|
{
|
|
if ( m_formationSource() == RiaDefines::WellLogTrackFormationSource::WELL_PICK_FILTER && m_formationWellPathForSourceWellPath() )
|
|
{
|
|
return m_formationWellPathForSourceWellPath->formationsGeometry();
|
|
}
|
|
|
|
if ( m_formationSource() == RiaDefines::WellLogTrackFormationSource::WELL_PICKS_NO_TRAJECTORY && m_wellFormationsFile() &&
|
|
!m_wellNameInFormationsFile().isEmpty() )
|
|
{
|
|
return m_wellFormationsFile->formationsForWell( m_wellNameInFormationsFile() );
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RimWellLogFormationSettings::simWellName() const
|
|
{
|
|
return m_formationSimWellName();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setSimWellName( const QString& simWellName )
|
|
{
|
|
m_formationSimWellName = simWellName;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
int RimWellLogFormationSettings::branchIndex() const
|
|
{
|
|
return m_formationBranchIndex();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setBranchIndex( int branchIndex )
|
|
{
|
|
m_formationBranchIndex = branchIndex;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RimWellLogFormationSettings::branchDetection() const
|
|
{
|
|
return m_formationBranchDetection();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setBranchDetection( bool branchDetection )
|
|
{
|
|
m_formationBranchDetection = branchDetection;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RiaDefines::WellLogTrackFormationLevel RimWellLogFormationSettings::formationLevel() const
|
|
{
|
|
return m_formationLevel();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setFormationLevel( RiaDefines::WellLogTrackFormationLevel level )
|
|
{
|
|
m_formationLevel = level;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RimWellLogFormationSettings::showFormationFluids() const
|
|
{
|
|
return m_showFormationFluids();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::setShowFormationFluids( bool show )
|
|
{
|
|
m_showFormationFluids = show;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::uiOrdering( const QString& uiConfigName, caf::PdmUiOrdering& uiOrdering, bool formationsForCaseWithSimWellOnly )
|
|
{
|
|
if ( !formationsForCaseWithSimWellOnly )
|
|
{
|
|
uiOrdering.add( &m_formationSource );
|
|
}
|
|
|
|
if ( m_formationSource() == RiaDefines::WellLogTrackFormationSource::CASE )
|
|
{
|
|
uiOrdering.add( &m_formationCase );
|
|
|
|
if ( !formationsForCaseWithSimWellOnly )
|
|
{
|
|
uiOrdering.add( &m_formationTrajectoryType );
|
|
|
|
if ( m_formationTrajectoryType() == RiaDefines::WellLogTrackTrajectoryType::WELL_PATH )
|
|
{
|
|
uiOrdering.add( &m_formationWellPathForSourceCase );
|
|
}
|
|
}
|
|
|
|
if ( formationsForCaseWithSimWellOnly || m_formationTrajectoryType() == RiaDefines::WellLogTrackTrajectoryType::SIMULATION_WELL )
|
|
{
|
|
uiOrdering.add( &m_formationSimWellName );
|
|
|
|
RiaSimWellBranchTools::appendSimWellBranchFieldsIfRequiredFromSimWellName( &uiOrdering,
|
|
m_formationSimWellName,
|
|
m_formationBranchDetection,
|
|
m_formationBranchIndex );
|
|
}
|
|
}
|
|
else if ( m_formationSource() == RiaDefines::WellLogTrackFormationSource::WELL_PICK_FILTER )
|
|
{
|
|
// The direct Formations File fallback (no well path selected) has moved to the dedicated
|
|
// WELL_PICKS_NO_TRAJECTORY source, so this source only ever shows the well path picker.
|
|
uiOrdering.add( &m_formationWellPathForSourceWellPath );
|
|
|
|
if ( resolveWellPickFormations() )
|
|
{
|
|
uiOrdering.add( &m_formationLevel );
|
|
uiOrdering.add( &m_showFormationFluids );
|
|
}
|
|
}
|
|
else if ( m_formationSource() == RiaDefines::WellLogTrackFormationSource::WELL_PICKS_NO_TRAJECTORY )
|
|
{
|
|
// Well picks use explicit top/base depths and do not require a well path trajectory, so
|
|
// this source can be used e.g. for an RFT well with no associated/modelled well path.
|
|
uiOrdering.add( &m_wellFormationsFile, { .newRow = true, .totalColumnSpan = 2, .leftLabelColumnSpan = 1 } );
|
|
uiOrdering.addNewButton( "Add Well Picks",
|
|
[this]() { onAddWellPicksClicked(); },
|
|
{ .newRow = false, .totalColumnSpan = 1, .leftLabelColumnSpan = 0 } );
|
|
if ( m_wellFormationsFile() ) uiOrdering.add( &m_wellNameInFormationsFile );
|
|
|
|
if ( resolveWellPickFormations() )
|
|
{
|
|
uiOrdering.add( &m_formationLevel );
|
|
uiOrdering.add( &m_showFormationFluids );
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
|
{
|
|
if ( changedField == &m_formationSource && m_formationSource() == RiaDefines::WellLogTrackFormationSource::WELL_PICK_FILTER )
|
|
{
|
|
std::vector<RimWellPath*> wellPaths;
|
|
RimTools::wellPathWithFormations( &wellPaths );
|
|
for ( RimWellPath* wellPath : wellPaths )
|
|
{
|
|
if ( wellPath == m_formationWellPathForSourceCase )
|
|
{
|
|
m_formationWellPathForSourceWellPath = m_formationWellPathForSourceCase();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if ( changedField == &m_formationSource && m_formationSource() == RiaDefines::WellLogTrackFormationSource::WELL_PICKS_NO_TRAJECTORY )
|
|
{
|
|
// The WELL_PICKS_NO_TRAJECTORY source always resolves formations directly from
|
|
// m_wellFormationsFile, so clear any well path left over from a previous WELL_PICK_FILTER
|
|
// selection.
|
|
m_formationWellPathForSourceWellPath = nullptr;
|
|
}
|
|
else if ( changedField == &m_wellFormationsFile )
|
|
{
|
|
// Reset the selected well name when the file changes, picking the first well as a
|
|
// convenient default (mirrors RimWellPath's behavior when linking a formations file).
|
|
QStringList wellNames = m_wellFormationsFile() ? m_wellFormationsFile->wellNames() : QStringList();
|
|
m_wellNameInFormationsFile = wellNames.isEmpty() ? QString() : wellNames.first();
|
|
}
|
|
|
|
auto track = firstAncestorOrThisOfType<RimWellLogTrack>();
|
|
if ( track )
|
|
{
|
|
track->loadDataAndUpdate();
|
|
track->updateConnectedEditors();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RimWellLogFormationSettings::onAddWellPicksClicked()
|
|
{
|
|
std::vector<RimWellFormationsFile*> importedFiles = RicImportWellFormationsFeature::importFilesWithDialog();
|
|
if ( importedFiles.empty() ) return;
|
|
|
|
RimWellFormationsFile* file = importedFiles.back();
|
|
m_wellFormationsFile = file;
|
|
|
|
QStringList wellNames = file->wellNames();
|
|
m_wellNameInFormationsFile = wellNames.isEmpty() ? QString() : wellNames.first();
|
|
|
|
if ( auto track = firstAncestorOrThisOfType<RimWellLogTrack>() )
|
|
{
|
|
track->loadDataAndUpdate();
|
|
track->updateEditors();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QList<caf::PdmOptionItemInfo> RimWellLogFormationSettings::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
|
|
{
|
|
QList<caf::PdmOptionItemInfo> options;
|
|
|
|
if ( fieldNeedingOptions == &m_formationWellPathForSourceCase )
|
|
{
|
|
RimTools::wellPathOptionItems( &options );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_formationWellPathForSourceWellPath )
|
|
{
|
|
RimTools::wellPathWithFormationsOptionItems( &options );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_wellFormationsFile )
|
|
{
|
|
options.push_back( caf::PdmOptionItemInfo( "None", static_cast<RimWellFormationsFile*>( nullptr ) ) );
|
|
|
|
RimProject* proj = RimProject::current();
|
|
if ( proj && proj->activeOilField() && proj->activeOilField()->wellFormationsCollection() )
|
|
{
|
|
for ( RimWellFormationsFile* file : proj->activeOilField()->wellFormationsCollection()->wellFormationsFiles() )
|
|
{
|
|
options.push_back( caf::PdmOptionItemInfo( file->shortName(), file, false, file->uiCapability()->uiIconProvider() ) );
|
|
}
|
|
}
|
|
}
|
|
else if ( fieldNeedingOptions == &m_wellNameInFormationsFile )
|
|
{
|
|
if ( m_wellFormationsFile() )
|
|
{
|
|
for ( const QString& wellName : m_wellFormationsFile->wellNames() )
|
|
{
|
|
options.push_back( caf::PdmOptionItemInfo( wellName, wellName ) );
|
|
}
|
|
}
|
|
}
|
|
else if ( fieldNeedingOptions == &m_formationCase )
|
|
{
|
|
RimTools::caseOptionItems( &options );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_formationSimWellName )
|
|
{
|
|
std::set<QString> sortedWellNames;
|
|
|
|
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_formationCase.value() );
|
|
if ( eclipseCase && eclipseCase->eclipseCaseData() )
|
|
{
|
|
sortedWellNames = eclipseCase->eclipseCaseData()->findSortedWellNames();
|
|
}
|
|
|
|
caf::IconProvider simWellIcon( ":/Well.svg" );
|
|
for ( const QString& wname : sortedWellNames )
|
|
{
|
|
options.push_back( caf::PdmOptionItemInfo( wname, wname, false, simWellIcon ) );
|
|
}
|
|
}
|
|
else if ( fieldNeedingOptions == &m_formationBranchIndex )
|
|
{
|
|
auto simulationWellBranches = RiaSimWellBranchTools::simulationWellBranches( m_formationSimWellName(), m_formationBranchDetection );
|
|
options = RiaSimWellBranchTools::valueOptionsForBranchIndexField( simulationWellBranches );
|
|
}
|
|
else if ( fieldNeedingOptions == &m_formationLevel )
|
|
{
|
|
if ( auto formations = resolveWellPickFormations() )
|
|
{
|
|
using FormationLevelEnum = caf::AppEnum<RiaDefines::WellLogTrackFormationLevel>;
|
|
|
|
options.push_back( caf::PdmOptionItemInfo( FormationLevelEnum::uiText( RiaDefines::WellLogTrackFormationLevel::NONE ),
|
|
RiaDefines::WellLogTrackFormationLevel::NONE ) );
|
|
|
|
options.push_back( caf::PdmOptionItemInfo( FormationLevelEnum::uiText( RiaDefines::WellLogTrackFormationLevel::ALL ),
|
|
RiaDefines::WellLogTrackFormationLevel::ALL ) );
|
|
|
|
for ( const auto& level : formations->formationsLevelsPresent() )
|
|
{
|
|
options.push_back( caf::PdmOptionItemInfo( FormationLevelEnum::uiText( level ), level ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
return options;
|
|
}
|