ResInsight/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogCurveCommonDataSource.cpp
Magne Sjaastad e2e239fd07
Several RFT plot adjustments
* #9923 Call loadDataAndUpdate() after visibility of curves is updated
This will ensure that all zoom ranges are recalculated based on visible curves.

* #9923 Put new segment plots in RFT Plot collection
* #9923 Add "Create Rft Sement Plot" to RFT plot collection
* #9923 Make sure the main window is displayed when required
Make sure the main window is opened and views updated when a grid model is opened from a summary case.

* #9923 Make sure fieldChanged is triggered when required
Exclude field having the target state. If these fields are included, the one and only call to setValueWithFieldChanged() can contain a field with the target state value. When setting a value to a field with the same value, nothing happens and the UI will get an inconsistent state (some curves toggled off are still visible in a plot).
2023-03-08 07:35:27 +01:00

1213 lines
46 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016 Statoil 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 "RimWellLogCurveCommonDataSource.h"
#include "RiaSimWellBranchTools.h"
#include "RiaSummaryTools.h"
#include "RimCase.h"
#include "RimDataSourceSteppingTools.h"
#include "RimEclipseCase.h"
#include "RimEclipseResultCase.h"
#include "RimGeoMechCase.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimRftTools.h"
#include "RimRftTopologyCurve.h"
#include "RimSummaryCase.h"
#include "RimTools.h"
#include "RimWellFlowRateCurve.h"
#include "RimWellLogExtractionCurve.h"
#include "RimWellLogFileCurve.h"
#include "RimWellLogPlot.h"
#include "RimWellLogPlotCollection.h"
#include "RimWellLogRftCurve.h"
#include "RimWellLogTrack.h"
#include "RimWellLogWbsCurve.h"
#include "RimWellMeasurementCurve.h"
#include "RimWellPath.h"
#include "RimWellPathCollection.h"
#include "cafPdmUiCheckBoxEditor.h"
#include "cafPdmUiCheckBoxTristateEditor.h"
#include "cafPdmUiComboBoxEditor.h"
#include "cafPdmUiLineEditor.h"
#include <algorithm>
CAF_PDM_SOURCE_INIT( RimWellLogCurveCommonDataSource, "ChangeDataSourceFeatureUi" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogCurveCommonDataSource::DoubleComparator::DoubleComparator( double eps /*= 1.0e-8 */ )
: m_eps( eps )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogCurveCommonDataSource::DoubleComparator::operator()( const double& lhs, const double& rhs ) const
{
double diff = lhs - rhs;
return diff < -m_eps;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogCurveCommonDataSource::RimWellLogCurveCommonDataSource()
: m_caseType( RiaDefines::CaseType::UNDEFINED_CASE )
{
CAF_PDM_InitObject( "Change Data Source" );
CAF_PDM_InitFieldNoDefault( &m_case, "CurveCase", "Case" );
CAF_PDM_InitFieldNoDefault( &m_summaryCase, "SummaryCase", "Summary Case" );
CAF_PDM_InitFieldNoDefault( &m_trajectoryType, "TrajectoryType", "Trajectory Type" );
CAF_PDM_InitFieldNoDefault( &m_wellPath, "CurveWellPath", "Well Path" );
CAF_PDM_InitFieldNoDefault( &m_simWellName, "SimulationWellName", "Well Name" );
CAF_PDM_InitFieldNoDefault( &m_branchDetection,
"BranchDetection",
"Branch Detection",
"",
"Compute branches based on how simulation well cells are organized",
"" );
CAF_PDM_InitField( &m_allow3DSelectionLink, "Allow3DSelectionLink", true, "Allow Well Selection from 3D View" );
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_allow3DSelectionLink );
m_branchDetection.v() = caf::Tristate::State::PartiallyTrue;
m_branchDetection.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxTristateEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_branchIndex, "Branch", -1, "Branch Index" );
CAF_PDM_InitField( &m_timeStep, "CurveTimeStep", -1, "Time Step" );
CAF_PDM_InitFieldNoDefault( &m_wbsSmoothing, "WBSSmoothing", "Smooth Curves" );
m_wbsSmoothing.uiCapability()->setUiEditorTypeName( caf::PdmUiCheckBoxTristateEditor::uiEditorTypeName() );
m_wbsSmoothing.v() = caf::Tristate::State::PartiallyTrue;
CAF_PDM_InitField( &m_wbsSmoothingThreshold, "WBSSmoothingThreshold", -1.0, "Smoothing Threshold" );
CAF_PDM_InitFieldNoDefault( &m_rftTimeStep, "RftTimeStep", "RFT Time Step" );
CAF_PDM_InitFieldNoDefault( &m_rftWellName, "RftWellName", "RFT Well Name" );
CAF_PDM_InitFieldNoDefault( &m_rftSegmentBranchIndex, "SegmentBranchIndex", "RFT Branch" );
CAF_PDM_InitFieldNoDefault( &m_rftSegmentBranchType, "SegmentBranchType", "RFT Completion" );
m_case = nullptr;
m_wellPath = nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::setCaseType( RiaDefines::CaseType caseType )
{
m_caseType = caseType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCase* RimWellLogCurveCommonDataSource::caseToApply() const
{
return m_case;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::setSummaryCaseToApply( RimSummaryCase* val )
{
m_summaryCase = val;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::setCaseToApply( RimCase* val )
{
m_case = val;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RimWellLogCurveCommonDataSource::summaryCaseToApply() const
{
return m_summaryCase();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimWellLogCurveCommonDataSource::trajectoryTypeToApply() const
{
return m_trajectoryType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::setTrajectoryTypeToApply( int val )
{
m_trajectoryType = val;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RimWellLogCurveCommonDataSource::wellPathToApply() const
{
return m_wellPath;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::setWellPathToApply( RimWellPath* val )
{
m_wellPath = val;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimWellLogCurveCommonDataSource::branchIndexToApply() const
{
return m_branchIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::setBranchIndexToApply( int val )
{
m_branchIndex = val;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::Tristate RimWellLogCurveCommonDataSource::branchDetectionToApply() const
{
return m_branchDetection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::setBranchDetectionToApply( caf::Tristate::State val )
{
m_branchDetection.v() = val;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::Tristate RimWellLogCurveCommonDataSource::wbsSmoothingToApply() const
{
return m_wbsSmoothing();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::setWbsSmoothingToApply( caf::Tristate::State val )
{
m_wbsSmoothing.v() = val;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimWellLogCurveCommonDataSource::wbsSmoothingThreshold() const
{
return m_wbsSmoothingThreshold;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::setWbsSmoothingThreshold( double smoothingThreshold )
{
m_wbsSmoothingThreshold = smoothingThreshold;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogCurveCommonDataSource::simWellNameToApply() const
{
return m_simWellName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::setSimWellNameToApply( const QString& val )
{
m_simWellName = val;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimWellLogCurveCommonDataSource::timeStepToApply() const
{
return m_timeStep;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::setTimeStepToApply( int val )
{
m_timeStep = val;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::resetSourceStepFields()
{
setCaseToApply( nullptr );
setSummaryCaseToApply( nullptr );
setTrajectoryTypeToApply( -1 );
setWellPathToApply( nullptr );
setBranchIndexToApply( -1 );
setBranchDetectionToApply( caf::Tristate::State::PartiallyTrue );
setSimWellNameToApply( QString( "" ) );
setTimeStepToApply( -1 );
setWbsSmoothingToApply( caf::Tristate::State::PartiallyTrue );
setWbsSmoothingThreshold( -1.0 );
m_uniqueCases.clear();
m_uniqueSummaryCases.clear();
m_uniqueTrajectoryTypes.clear();
m_uniqueWellPaths.clear();
m_uniqueWellNames.clear();
m_uniqueTimeSteps.clear();
m_uniqueBranchIndices.clear();
m_uniqueBranchDetection.clear();
m_uniqueWbsSmoothing.clear();
m_uniqueWbsSmoothingThreshold.clear();
m_uniqueRftTimeSteps.clear();
m_uniqueRftWellNames.clear();
m_uniqueRftBranchIndices.clear();
m_uniqueRftBranchTypes.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::analyseCurvesAndTracks( const std::vector<RimWellLogCurve*>& curves,
const std::vector<RimWellLogTrack*>& tracks )
{
// Reset all source step fields in the UI
resetSourceStepFields();
// Check to see if the parameters are unique
for ( RimWellLogCurve* curve : curves )
{
auto* extractionCurve = dynamic_cast<RimWellLogExtractionCurve*>( curve );
auto* fileCurve = dynamic_cast<RimWellLogFileCurve*>( curve );
auto* flowRateCurve = dynamic_cast<RimWellFlowRateCurve*>( curve );
auto* rftCurve = dynamic_cast<RimWellLogRftCurve*>( curve );
if ( extractionCurve )
{
auto* wbsCurve = dynamic_cast<RimWellLogWbsCurve*>( extractionCurve );
if ( wbsCurve )
{
m_uniqueWbsSmoothing.insert( wbsCurve->smoothCurve() );
m_uniqueWbsSmoothingThreshold.insert( wbsCurve->smoothingThreshold() );
}
if ( extractionCurve->rimCase() )
{
m_uniqueCases.insert( extractionCurve->rimCase() );
}
m_uniqueTrajectoryTypes.insert( static_cast<int>( extractionCurve->trajectoryType() ) );
if ( extractionCurve->trajectoryType() == RimWellLogExtractionCurve::WELL_PATH )
{
if ( extractionCurve->wellPath() )
{
m_uniqueWellPaths.insert( extractionCurve->wellPath() );
}
}
else if ( extractionCurve->trajectoryType() == RimWellLogExtractionCurve::SIMULATION_WELL )
{
if ( !extractionCurve->wellName().isEmpty() )
{
m_uniqueWellNames.insert( extractionCurve->wellName() );
}
}
m_uniqueTimeSteps.insert( extractionCurve->currentTimeStep() );
m_uniqueBranchDetection.insert( extractionCurve->branchDetection() );
m_uniqueBranchIndices.insert( extractionCurve->branchIndex() );
}
else if ( fileCurve )
{
m_uniqueWellPaths.insert( fileCurve->wellPath() );
m_uniqueWellNames.insert( fileCurve->wellName() );
}
else if ( flowRateCurve )
{
m_uniqueTrajectoryTypes.insert( RimWellLogExtractionCurve::SIMULATION_WELL );
m_uniqueWellNames.insert( flowRateCurve->wellName() );
m_uniqueCases.insert( flowRateCurve->rimCase() );
m_uniqueTimeSteps.insert( flowRateCurve->timeStep() );
}
else if ( rftCurve )
{
if ( rftCurve->summaryCase() ) m_uniqueSummaryCases.insert( rftCurve->summaryCase() );
if ( rftCurve->eclipseResultCase() ) m_uniqueCases.insert( rftCurve->eclipseResultCase() );
m_uniqueWellNames.insert( rftCurve->wellName() );
auto adr = rftCurve->rftAddress();
if ( adr.wellLogChannel() == RifEclipseRftAddress::RftWellLogChannelType::SEGMENT_VALUES && adr.segmentResultName() != "None" )
{
m_uniqueRftWellNames.insert( adr.wellName() );
m_uniqueRftTimeSteps.insert( adr.timeStep() );
m_uniqueRftBranchIndices.insert( adr.segmentBranchIndex() );
m_uniqueRftBranchTypes.insert( adr.segmentBranchType() );
}
}
}
for ( RimWellLogTrack* track : tracks )
{
if ( track->showWellPathAttributes() )
{
m_uniqueTrajectoryTypes.insert( static_cast<int>( RimWellLogExtractionCurve::WELL_PATH ) );
m_uniqueWellPaths.insert( track->wellPathAttributeSource() );
}
if ( track->showFormations() )
{
m_uniqueTrajectoryTypes.insert( track->formationTrajectoryType() );
if ( track->formationTrajectoryType() == RimWellLogTrack::WELL_PATH )
{
m_uniqueWellPaths.insert( track->formationWellPath() );
}
else if ( track->formationTrajectoryType() == RimWellLogTrack::SIMULATION_WELL )
{
m_uniqueWellNames.insert( track->formationSimWellName() );
}
m_uniqueBranchDetection.insert( track->formationBranchDetection() );
m_uniqueBranchIndices.insert( track->formationBranchIndex() );
m_uniqueCases.insert( track->formationNamesCase() );
m_uniqueWellPaths.insert( track->formationWellPath() );
}
}
if ( m_uniqueCases.size() == 1u )
{
setCaseToApply( *m_uniqueCases.begin() );
}
if ( m_uniqueSummaryCases.size() == 1u )
{
setSummaryCaseToApply( *m_uniqueSummaryCases.begin() );
}
if ( m_uniqueTrajectoryTypes.size() == 1u )
{
m_trajectoryType = *m_uniqueTrajectoryTypes.begin();
if ( m_uniqueWellPaths.size() == 1u )
{
setWellPathToApply( *m_uniqueWellPaths.begin() );
}
if ( m_uniqueBranchIndices.size() == 1u )
{
setBranchIndexToApply( *m_uniqueBranchIndices.begin() );
}
if ( m_uniqueBranchDetection.size() == 1u )
{
setBranchDetectionToApply( *m_uniqueBranchDetection.begin() == true ? caf::Tristate::State::True : caf::Tristate::State::False );
}
if ( m_uniqueWellNames.size() == 1u )
{
setSimWellNameToApply( *m_uniqueWellNames.begin() );
}
}
if ( m_uniqueTimeSteps.size() == 1u )
{
setTimeStepToApply( *m_uniqueTimeSteps.begin() );
}
if ( m_uniqueWbsSmoothing.size() == 1u )
{
setWbsSmoothingToApply( *m_uniqueWbsSmoothing.begin() == true ? caf::Tristate::State::True : caf::Tristate::State::False );
}
if ( m_uniqueWbsSmoothingThreshold.size() == 1u )
{
setWbsSmoothingThreshold( *m_uniqueWbsSmoothingThreshold.begin() );
}
if ( m_uniqueRftWellNames.size() == 1u )
{
m_rftWellName = *( m_uniqueRftWellNames.begin() );
}
if ( m_uniqueRftTimeSteps.size() == 1u )
{
m_rftTimeStep = *( m_uniqueRftTimeSteps.begin() );
}
if ( m_uniqueRftBranchIndices.size() == 1u )
{
m_rftSegmentBranchIndex = *( m_uniqueRftBranchIndices.begin() );
}
if ( m_uniqueRftBranchTypes.size() == 1u )
{
m_rftSegmentBranchType = *( m_uniqueRftBranchTypes.begin() );
}
else
m_rftSegmentBranchType = RiaDefines::RftBranchType::RFT_UNKNOWN;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::analyseCurvesAndTracks()
{
RimWellLogPlot* parentPlot = nullptr;
this->firstAncestorOrThisOfType( parentPlot );
if ( parentPlot )
{
std::vector<RimWellLogCurve*> curves;
parentPlot->descendantsIncludingThisOfType( curves );
std::vector<RimWellLogTrack*> tracks;
parentPlot->descendantsIncludingThisOfType( tracks );
this->analyseCurvesAndTracks( curves, tracks );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::applyDataSourceChanges( const std::vector<RimWellLogCurve*>& curves,
const std::vector<RimWellLogTrack*>& tracks )
{
std::set<RimWellLogPlot*> plots;
for ( RimWellLogCurve* curve : curves )
{
auto* fileCurve = dynamic_cast<RimWellLogFileCurve*>( curve );
auto* extractionCurve = dynamic_cast<RimWellLogExtractionCurve*>( curve );
auto* measurementCurve = dynamic_cast<RimWellMeasurementCurve*>( curve );
auto* rftCurve = dynamic_cast<RimWellLogRftCurve*>( curve );
auto* topologyCurve = dynamic_cast<RimRftTopologyCurve*>( curve );
if ( fileCurve )
{
if ( wellPathToApply() != nullptr )
{
fileCurve->setWellPath( wellPathToApply() );
if ( !fileCurve->wellLogChannelUiName().isEmpty() )
{
RimWellLogFile* logFile = wellPathToApply()->firstWellLogFileMatchingChannelName( fileCurve->wellLogChannelUiName() );
fileCurve->setWellLogFile( logFile );
RimWellLogPlot* parentPlot = nullptr;
fileCurve->firstAncestorOrThisOfTypeAsserted( parentPlot );
plots.insert( parentPlot );
}
}
}
else if ( extractionCurve )
{
bool updatedSomething = false;
if ( caseToApply() != nullptr )
{
extractionCurve->setCase( caseToApply() );
updatedSomething = true;
}
if ( wellPathToApply() != nullptr )
{
extractionCurve->setWellPath( wellPathToApply() );
updatedSomething = true;
}
if ( m_trajectoryType() != -1 )
{
extractionCurve->setTrajectoryType( static_cast<RimWellLogExtractionCurve::TrajectoryType>( m_trajectoryType() ) );
if ( m_trajectoryType() == (int)RimWellLogExtractionCurve::SIMULATION_WELL )
{
if ( m_branchDetection().isTrue() )
{
extractionCurve->setBranchDetection( true );
}
else if ( m_branchDetection().isFalse() )
{
extractionCurve->setBranchDetection( false );
}
if ( m_branchIndex() != -1 )
{
extractionCurve->setBranchIndex( m_branchIndex() );
}
if ( m_simWellName() != QString( "" ) )
{
extractionCurve->setWellName( m_simWellName() );
}
}
updatedSomething = true;
}
if ( timeStepToApply() != -1 )
{
extractionCurve->setCurrentTimeStep( timeStepToApply() );
updatedSomething = true;
}
auto* wbsCurve = dynamic_cast<RimWellLogWbsCurve*>( extractionCurve );
if ( wbsCurve )
{
if ( !wbsSmoothingToApply().isPartiallyTrue() )
{
wbsCurve->setSmoothCurve( wbsSmoothingToApply().isTrue() );
updatedSomething = true;
}
if ( wbsSmoothingThreshold() != 1.0 )
{
wbsCurve->setSmoothingThreshold( wbsSmoothingThreshold() );
updatedSomething = true;
}
}
if ( updatedSomething )
{
RimWellLogPlot* parentPlot = nullptr;
extractionCurve->firstAncestorOrThisOfTypeAsserted( parentPlot );
plots.insert( parentPlot );
}
}
else if ( measurementCurve )
{
if ( wellPathToApply() != nullptr )
{
measurementCurve->setWellPath( wellPathToApply() );
}
}
else if ( rftCurve )
{
if ( m_summaryCase() ) rftCurve->setSummaryCase( m_summaryCase() );
rftCurve->setTimeStep( m_rftTimeStep() );
rftCurve->setWellName( m_rftWellName() );
rftCurve->setSegmentBranchIndex( m_rftSegmentBranchIndex() );
if ( m_rftSegmentBranchType() != RiaDefines::RftBranchType::RFT_UNKNOWN )
rftCurve->setSegmentBranchType( m_rftSegmentBranchType() );
RimWellLogPlot* parentPlot = nullptr;
rftCurve->firstAncestorOrThisOfTypeAsserted( parentPlot );
plots.insert( parentPlot );
}
else if ( topologyCurve )
{
topologyCurve->setDataSource( m_summaryCase, m_rftTimeStep, m_rftWellName, m_rftSegmentBranchIndex );
}
curve->updateConnectedEditors();
}
for ( RimWellLogTrack* track : tracks )
{
bool updatedSomething = false;
if ( track->showWellPathAttributes() )
{
if ( wellPathToApply() )
{
track->setWellPathAttributesSource( wellPathToApply() );
updatedSomething = true;
}
}
if ( track->showFormations() )
{
if ( caseToApply() != nullptr )
{
track->setFormationCase( caseToApply() );
updatedSomething = true;
}
if ( wellPathToApply() != nullptr )
{
track->setFormationWellPath( wellPathToApply() );
updatedSomething = true;
}
if ( !simWellNameToApply().isEmpty() )
{
track->setFormationSimWellName( simWellNameToApply() );
updatedSomething = true;
}
if ( !branchDetectionToApply().isPartiallyTrue() )
{
track->setFormationSimWellName( simWellNameToApply() );
updatedSomething = true;
}
if ( branchIndexToApply() >= 0 )
{
track->setFormationBranchIndex( branchIndexToApply() );
updatedSomething = true;
}
}
if ( updatedSomething )
{
RimWellLogPlot* parentPlot = nullptr;
track->firstAncestorOrThisOfTypeAsserted( parentPlot );
plots.insert( parentPlot );
track->updateConnectedEditors();
}
}
for ( RimWellLogPlot* plot : plots )
{
plot->loadDataAndUpdate();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::applyDataSourceChanges()
{
RimWellLogPlot* parentPlot = nullptr;
this->firstAncestorOrThisOfType( parentPlot );
if ( parentPlot )
{
std::vector<RimWellLogCurve*> curves;
parentPlot->descendantsIncludingThisOfType( curves );
std::vector<RimWellLogTrack*> tracks;
parentPlot->descendantsIncludingThisOfType( tracks );
this->applyDataSourceChanges( curves, tracks );
// plot->loadDataAndUpdate() has been called in applyDataSourceChanges(), and this is required before the visibility of tracks and
// curves can be updated. However, if the visibility of curves changes, another loadDataAndUpdate() is required to calculate zoom
// based on visible curves.
for ( auto& track : tracks )
{
track->updateCheckStateBasedOnCurveData();
}
parentPlot->loadDataAndUpdate();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::applyPrevCase()
{
modifyCurrentIndex( &m_case, -1 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::applyNextCase()
{
modifyCurrentIndex( &m_case, 1 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::applyPrevWell()
{
if ( m_trajectoryType() == RimWellLogExtractionCurve::WELL_PATH )
{
modifyCurrentIndex( &m_wellPath, -1 );
}
else if ( m_trajectoryType() == RimWellLogExtractionCurve::SIMULATION_WELL )
{
modifyCurrentIndex( &m_simWellName, -1 );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::applyNextWell()
{
if ( m_trajectoryType() == RimWellLogExtractionCurve::WELL_PATH )
{
modifyCurrentIndex( &m_wellPath, 1 );
}
else if ( m_trajectoryType() == RimWellLogExtractionCurve::SIMULATION_WELL )
{
modifyCurrentIndex( &m_simWellName, 1 );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::applyPrevTimeStep()
{
modifyCurrentIndex( &m_timeStep, -1 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::applyNextTimeStep()
{
modifyCurrentIndex( &m_timeStep, 1 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<caf::PdmFieldHandle*> RimWellLogCurveCommonDataSource::fieldsToShowInToolbar()
{
analyseCurvesAndTracks();
std::vector<caf::PdmFieldHandle*> fieldsToDisplay;
if ( !m_uniqueCases.empty() )
{
fieldsToDisplay.push_back( &m_case );
if ( trajectoryTypeToApply() == RimWellLogExtractionCurve::WELL_PATH )
{
fieldsToDisplay.push_back( &m_wellPath );
}
else if ( trajectoryTypeToApply() == RimWellLogExtractionCurve::SIMULATION_WELL )
{
fieldsToDisplay.push_back( &m_simWellName );
}
}
if ( m_uniqueRftWellNames.size() == 1u ) fieldsToDisplay.push_back( &m_rftWellName );
if ( m_uniqueTimeSteps.size() == 1u ) fieldsToDisplay.push_back( &m_timeStep );
if ( m_uniqueRftTimeSteps.size() == 1u ) fieldsToDisplay.push_back( &m_rftTimeStep );
if ( m_uniqueRftBranchIndices.size() == 1u ) fieldsToDisplay.push_back( &m_rftSegmentBranchIndex );
if ( m_uniqueRftBranchTypes.size() == 1u ) fieldsToDisplay.push_back( &m_rftSegmentBranchType );
return fieldsToDisplay;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogCurveCommonDataSource::smoothingUiOrderinglabel()
{
return "ApplySmoothing";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
RimWellLogPlot* parentPlot = nullptr;
this->firstAncestorOrThisOfType( parentPlot );
if ( changedField == &m_branchDetection && m_branchDetection().isPartiallyTrue() )
{
// The Tristate is cycled from false -> partially true -> true
// Partially true is used for "Mixed state" and is not settable by the user so cycle on to true.
m_branchDetection.v() = caf::Tristate::State::True;
}
if ( changedField == &m_wbsSmoothing && m_wbsSmoothing().isPartiallyTrue() )
{
m_wbsSmoothing.v() = caf::Tristate::State::True;
}
this->applyDataSourceChanges();
if ( changedField == &m_rftWellName )
{
// The segment branch index is depending on the well name. Make sure that the combo box for branch index is
// updated.
m_rftSegmentBranchIndex.uiCapability()->updateConnectedEditors();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimWellLogCurveCommonDataSource::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
{
QList<caf::PdmOptionItemInfo> options;
this->analyseCurvesAndTracks();
if ( fieldNeedingOptions == &m_case )
{
if ( m_caseType == RiaDefines::CaseType::GEOMECH_ODB_CASE )
{
RimTools::geoMechCaseOptionItems( &options );
}
else if ( m_caseType == RiaDefines::CaseType::ECLIPSE_RESULT_CASE || m_caseType == RiaDefines::CaseType::ECLIPSE_INPUT_CASE ||
m_caseType == RiaDefines::CaseType::ECLIPSE_SOURCE_CASE || m_caseType == RiaDefines::CaseType::ECLIPSE_STAT_CASE )
{
RimTools::eclipseCaseOptionItems( &options );
}
else
{
RimTools::caseOptionItems( &options );
}
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
}
if ( fieldNeedingOptions == &m_summaryCase )
{
options = RiaSummaryTools::optionsForAllSummaryCases();
}
else if ( fieldNeedingOptions == &m_trajectoryType )
{
if ( m_trajectoryType() == -1 )
{
if ( !m_uniqueTrajectoryTypes.empty() )
{
options.push_back( caf::PdmOptionItemInfo( "Mixed Trajectory Types", -1 ) );
}
else
{
options.push_back( caf::PdmOptionItemInfo( "No Trajectory Types", -1 ) );
}
}
std::vector<RimWellLogExtractionCurve::TrajectoryType> trajectoryTypes = { RimWellLogExtractionCurve::WELL_PATH,
RimWellLogExtractionCurve::SIMULATION_WELL };
for ( RimWellLogExtractionCurve::TrajectoryType trajectoryType : trajectoryTypes )
{
caf::PdmOptionItemInfo item( caf::AppEnum<RimWellLogExtractionCurve::TrajectoryType>::uiText( trajectoryType ),
static_cast<int>( trajectoryType ) );
options.push_back( item );
}
}
else if ( fieldNeedingOptions == &m_wellPath )
{
RimTools::wellPathOptionItems( &options );
if ( wellPathToApply() == nullptr )
{
if ( !m_uniqueWellPaths.empty() )
{
options.push_front( caf::PdmOptionItemInfo( "Mixed Well Paths", nullptr ) );
}
else
{
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
}
}
}
else if ( fieldNeedingOptions == &m_timeStep )
{
if ( m_case() )
{
RimTools::timeStepsForCase( m_case, &options );
if ( timeStepToApply() == -1 )
{
if ( !m_uniqueTimeSteps.empty() )
{
options.push_front( caf::PdmOptionItemInfo( "Mixed Time Steps", -1 ) );
}
else
{
options.push_front( caf::PdmOptionItemInfo( "No Time Steps", -1 ) );
}
}
}
}
else if ( fieldNeedingOptions == &m_simWellName )
{
auto* eclipseCase = dynamic_cast<RimEclipseCase*>( m_case() );
if ( eclipseCase )
{
std::set<QString> sortedWellNames = eclipseCase->sortedSimWellNames();
caf::IconProvider simWellIcon( ":/Well.svg" );
for ( const QString& wname : sortedWellNames )
{
options.push_back( caf::PdmOptionItemInfo( wname, wname, false, simWellIcon ) );
}
if ( m_simWellName().isEmpty() )
{
if ( !m_uniqueWellNames.empty() )
{
options.push_front( caf::PdmOptionItemInfo( "Mixed Well Names", "" ) );
}
else
{
options.push_front( caf::PdmOptionItemInfo( "None", "None" ) );
}
}
}
}
else if ( fieldNeedingOptions == &m_branchIndex )
{
bool hasCommonBranchDetection = !m_branchDetection().isPartiallyTrue();
if ( hasCommonBranchDetection )
{
bool doBranchDetection = m_branchDetection().isTrue();
auto branches = RiaSimWellBranchTools::simulationWellBranches( m_simWellName, doBranchDetection );
options = RiaSimWellBranchTools::valueOptionsForBranchIndexField( branches );
if ( m_branchIndex() == -1 )
{
if ( !m_uniqueBranchIndices.empty() )
{
options.push_front( caf::PdmOptionItemInfo( "Mixed Branches", -1 ) );
}
else
{
options.push_front( caf::PdmOptionItemInfo( "No Branches", -1 ) );
}
}
}
}
else if ( fieldNeedingOptions == &m_rftTimeStep )
{
if ( !m_uniqueRftWellNames.empty() )
options = RimRftTools::segmentTimeStepOptions( rftReader(), *( m_uniqueRftWellNames.begin() ) );
}
else if ( fieldNeedingOptions == &m_rftWellName )
{
options = RimRftTools::wellNameOptions( rftReader() );
}
else if ( fieldNeedingOptions == &m_rftSegmentBranchIndex )
{
options = RimRftTools::segmentBranchIndexOptions( rftReader(), m_rftWellName(), m_rftTimeStep(), m_rftSegmentBranchType() );
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
analyseCurvesAndTracks();
caf::PdmUiGroup* group = uiOrdering.addNewGroup( "Data Source" );
if ( m_case() ) group->add( &m_case );
if ( m_summaryCase() ) group->add( &m_summaryCase );
const auto* eclipseCase = dynamic_cast<RimEclipseCase*>( m_case() );
if ( eclipseCase )
{
group->add( &m_trajectoryType );
if ( trajectoryTypeToApply() == RimWellLogExtractionCurve::WELL_PATH )
{
group->add( &m_wellPath );
}
else if ( trajectoryTypeToApply() == RimWellLogExtractionCurve::SIMULATION_WELL )
{
group->add( &m_simWellName );
group->add( &m_allow3DSelectionLink );
if ( RiaSimWellBranchTools::simulationWellBranches( m_simWellName(), true ).size() > 1 )
{
group->add( &m_branchDetection );
bool hasCommonBranchDetection = !m_branchDetection().isPartiallyTrue();
if ( hasCommonBranchDetection )
{
bool doBranchDetection = m_branchDetection().isTrue();
if ( RiaSimWellBranchTools::simulationWellBranches( m_simWellName(), doBranchDetection ).size() > 1 )
{
group->add( &m_branchIndex );
}
}
}
}
group->add( &m_timeStep );
}
else
{
if ( m_wellPath() ) group->add( &m_wellPath );
}
if ( uiConfigName == smoothingUiOrderinglabel() )
{
group->add( &m_wbsSmoothing );
group->add( &m_wbsSmoothingThreshold );
}
if ( !m_uniqueRftTimeSteps.empty() ) group->add( &m_rftTimeStep );
if ( !m_uniqueRftWellNames.empty() ) group->add( &m_rftWellName );
if ( !m_uniqueRftBranchTypes.empty() ) group->add( &m_rftSegmentBranchType );
if ( !m_uniqueRftBranchIndices.empty() ) group->add( &m_rftSegmentBranchIndex );
uiOrdering.skipRemainingFields( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute )
{
auto* myAttr = dynamic_cast<caf::PdmUiComboBoxEditorAttribute*>( attribute );
if ( myAttr )
{
if ( field == &m_case || field == &m_summaryCase || field == &m_simWellName || field == &m_wellPath || field == &m_timeStep ||
field == &m_rftTimeStep || field == &m_rftSegmentBranchIndex || field == &m_rftWellName )
{
myAttr->showPreviousAndNextButtons = true;
myAttr->nextIcon = QIcon( ":/ComboBoxDown.svg" );
myAttr->previousIcon = QIcon( ":/ComboBoxUp.svg" );
}
QString modifierText;
if ( field == &m_case )
{
modifierText = ( "(Shift+" );
myAttr->minimumContentsLength = 14;
}
else if ( field == &m_wellPath || field == &m_simWellName )
{
modifierText = ( "(Ctrl+" );
}
else if ( field == &m_timeStep )
{
modifierText = ( "(" );
myAttr->minimumContentsLength = 12;
}
if ( !modifierText.isEmpty() )
{
myAttr->nextButtonText = "Next " + modifierText + "PgDown)";
myAttr->prevButtonText = "Previous " + modifierText + "PgUp)";
}
}
auto* uiDisplayStringAttr = dynamic_cast<caf::PdmUiLineEditorAttributeUiDisplayString*>( attribute );
if ( uiDisplayStringAttr && wbsSmoothingThreshold() == -1.0 )
{
QString displayString = "Mixed";
if ( m_uniqueWbsSmoothingThreshold.size() > 1u )
{
auto minmax_it = std::minmax_element( m_uniqueWbsSmoothingThreshold.begin(), m_uniqueWbsSmoothingThreshold.end() );
displayString += QString( " [%1, %2]" ).arg( *( minmax_it.first ) ).arg( *( minmax_it.second ) );
}
uiDisplayStringAttr->m_displayString = displayString;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::modifyCurrentIndex( caf::PdmValueField* field, int indexOffset )
{
QList<caf::PdmOptionItemInfo> options = calculateValueOptions( field );
RimDataSourceSteppingTools::modifyCurrentIndex( field, options, indexOffset );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderRftInterface* RimWellLogCurveCommonDataSource::rftReader()
{
auto eclipseCase = dynamic_cast<RimEclipseResultCase*>( m_case() );
if ( eclipseCase && eclipseCase->rftReader() ) return eclipseCase->rftReader();
if ( m_summaryCase() && m_summaryCase()->rftReader() ) return m_summaryCase->rftReader();
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogCurveCommonDataSource::selectWell( QString wellName )
{
if ( !m_allow3DSelectionLink() ) return;
if ( m_trajectoryType() == RimWellLogExtractionCurve::WELL_PATH )
{
QList<caf::PdmOptionItemInfo> options;
RimTools::wellPathOptionItems( &options );
for ( auto& opt : options )
{
if ( opt.optionUiText() == wellName )
{
QVariant oldPath = m_wellPath.toQVariant();
RimWellPath* wellPath = RimProject::current()->activeOilField()->wellPathCollection->wellPathByName( wellName );
m_wellPath = wellPath;
m_wellPath.uiCapability()->notifyFieldChanged( oldPath, opt.value() );
break;
}
}
}
else if ( m_trajectoryType() == RimWellLogExtractionCurve::SIMULATION_WELL )
{
auto* eclipseCase = dynamic_cast<RimEclipseCase*>( m_case() );
if ( eclipseCase )
{
std::set<QString> sortedWellNames = eclipseCase->sortedSimWellNames();
if ( std::count( sortedWellNames.begin(), sortedWellNames.end(), wellName ) > 0 )
{
m_simWellName.setValueWithFieldChanged( wellName );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogCurveCommonDataSource::rftWellName() const
{
return m_rftWellName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QDateTime RimWellLogCurveCommonDataSource::rftTime() const
{
return m_rftTimeStep();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimWellLogCurveCommonDataSource::rftBranchIndex() const
{
if ( m_uniqueRftBranchIndices.size() == 1 ) return m_rftSegmentBranchIndex();
return -1;
}