Files
ResInsight/ApplicationLibCode/ProjectDataModel/WellLog/WellLogTrack/RimWellLogTrack.cpp
T
Magne Sjaastad 56e98ba1c4 #14476 ApplicationLibCode: Replace CVF_ASSERT with CAF_ASSERT
Migrate all assert macros in ApplicationLibCode to CAF_ASSERT and remove every
use of cvfAssert.h.

CVF_ASSERT is replaced one to one. CVF_TIGHT_ASSERT is also replaced by
CAF_ASSERT, which is semantically exact: CVF_ENABLE_TIGHT_ASSERTS is 1 only
under _DEBUG, and that is what CAF_ASSERT now does. The two CVF_FAIL_MSG sites
become CAF_ASSERT( false && "message" ), preserving the message with the idiom
already used elsewhere in the code base.

Counts before and after: CVF_ASSERT 1044 to 0, CVF_TIGHT_ASSERT 66 to 0,
CVF_FAIL_MSG 2 to 0, cvfAssert.h references 154 to 0.

Include handling: files that included cvfAssert.h directly now include
cafAssert.h instead, includes left dead by the migration are removed, and files
that were relying on cvfAssert.h transitively get an explicit cafAssert.h. Files
that reach cafAssert.h through another caf header are left unchanged; a missing
include here is a compile error, not a silently disabled assert.

ResultStatisticsCache links only LibCore and therefore had no path to
cafAssert.h. Add the cafPdmCore directory as a private include path rather than
linking the library, since cafAssert.h is header only.

Note that this stops these asserts from firing in Release and RelWithDebInfo,
where CVF_ASSERT was previously active.
2026-08-07 15:05:57 +02:00

3237 lines
137 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015- Statoil ASA
// Copyright (C) 2015- Ceetron Solutions AS
//
// 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 "RimWellLogTrack.h"
#include "RiaColorTables.h"
#include "RiaExtractionTools.h"
#include "RiaGuiApplication.h"
#include "RiaLogging.h"
#include "RiaPlotDefines.h"
#include "RiaPreferences.h"
#include "RiaResultNames.h"
#include "RiaSimWellBranchTools.h"
#include "RiaWellLogCurveMerger.h"
#include "RigEclipseCaseData.h"
#include "RigEclipseResultAddress.h"
#include "RigFemPartResultsCollection.h"
#include "RigFemResultAddress.h"
#include "RigFormationNames.h"
#include "RigGeoMechCaseData.h"
#include "RigResultAccessorFactory.h"
#include "RigStatisticsCalculator.h"
#include "Well/RigEclipseWellLogExtractor.h"
#include "Well/RigGeoMechWellLogExtractor.h"
#include "Well/RigSimWellData.h"
#include "Well/RigSimulationWellCenterLineCalculator.h"
#include "Well/RigSimulationWellCoordsAndMD.h"
#include "Well/RigWellLogCurveData.h"
#include "Well/RigWellPath.h"
#include "Well/RigWellPathFormations.h"
#include "Formations/RimFormationNames.h"
#include "RimCase.h"
#include "RimColorLegend.h"
#include "RimColorLegendCollection.h"
#include "RimColorLegendItem.h"
#include "RimEclipseCase.h"
#include "RimEclipseResultDefinition.h"
#include "RimEnsembleWellLogCurveSet.h"
#include "RimFishbones.h"
#include "RimFishbonesCollection.h"
#include "RimGeoMechCase.h"
#include "RimMainPlotCollection.h"
#include "RimPerforationCollection.h"
#include "RimPerforationInterval.h"
#include "RimProject.h"
#include "RimRftTopologyCurve.h"
#include "RimTools.h"
#include "RimWellAllocationPlot.h"
#include "RimWellBoreStabilityPlot.h"
#include "RimWellFlowRateCurve.h"
#include "RimWellLogCurve.h"
#include "RimWellLogCurveCommonDataSource.h"
#include "RimWellLogExtractionCurve.h"
#include "RimWellLogFormationSettings.h"
#include "RimWellLogPlotCollection.h"
#include "RimWellLogPropertyAxisSettings.h"
#include "RimWellLogRegionAnnotationSettings.h"
#include "RimWellLogWellPathAttributeSettings.h"
#include "RimWellPath.h"
#include "RimWellPathAttribute.h"
#include "RimWellPathAttributeCollection.h"
#include "RimWellPathCompletions.h"
#include "RimWellPathFracture.h"
#include "RimWellPathFractureCollection.h"
#include "RimWellPltPlot.h"
#include "RimWellRftPlot.h"
#include "RiuMainWindow.h"
#include "RiuPlotAnnotationTool.h"
#include "RiuPlotAxis.h"
#include "RiuPlotMainWindow.h"
#include "RiuPlotMainWindowTools.h"
#include "RiuQwtLinearScaleEngine.h"
#include "RiuQwtPlotWidget.h"
#include "RiuWellLogTrack.h"
#include "RiuWellPathComponentPlotItem.h"
#include "cafPdmFieldReorderCapability.h"
#include "cafPdmFieldScriptingCapability.h"
#include "cafPdmObjectScriptingCapability.h"
#include "cafPdmUiDoubleValueEditor.h"
#include "cafPdmUiSliderEditor.h"
#include "cafSelectionManager.h"
#include "caf.h"
#include "cafAssert.h"
#include "qwt_scale_map.h"
#include <QWheelEvent>
#include <algorithm>
#include <map>
#include <memory>
#include <set>
#define RI_LOGPLOTTRACK_MINX_DEFAULT -10.0
#define RI_LOGPLOTTRACK_MAXX_DEFAULT 100.0
#define RI_SCROLLWHEEL_ZOOMFACTOR 1.1
#define RI_SCROLLWHEEL_PANFACTOR 0.1
CAF_PDM_SOURCE_INIT( RimWellLogTrack, "WellLogPlotTrack" );
namespace internal
{
void setColorShadingLegendFromFormationCase( RimWellLogRegionAnnotationSettings* settings, RimCase* rimCase )
{
if ( !settings || !rimCase ) return;
auto* formationNames = rimCase->activeFormationNames();
if ( !formationNames ) return;
QString legendName = formationNames->shortName();
auto* legend = RimProject::current()->colorLegendCollection->findByName( legendName );
if ( legend ) settings->setColorShadingLegend( legend );
}
} // namespace internal
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogTrack::RimWellLogTrack()
: m_availablePropertyValueRangeMin( RI_LOGPLOTTRACK_MINX_DEFAULT )
, m_availablePropertyValueRangeMax( RI_LOGPLOTTRACK_MAXX_DEFAULT )
, m_availableDepthRangeMin( RI_LOGPLOTTRACK_MINX_DEFAULT )
, m_availableDepthRangeMax( RI_LOGPLOTTRACK_MAXX_DEFAULT )
{
CAF_PDM_InitScriptableObject( "Track", ":/WellLogTrack16x16.png" );
CAF_PDM_InitFieldNoDefault( &m_description, "TrackDescription", "Name" );
CAF_PDM_InitFieldNoDefault( &m_curves, "Curves", "Curves" );
auto reorderability = caf::PdmFieldReorderCapability::addToField( &m_curves );
reorderability->orderChanged.connect( this, &RimWellLogTrack::curveDataChanged );
// Property axis settings
CAF_PDM_InitFieldNoDefault( &m_propertyAxisSettings, "PropertyAxisSettings", "" );
m_propertyAxisSettings = new RimWellLogPropertyAxisSettings();
m_propertyAxisSettings.uiCapability()->setUiTreeChildrenHidden( true );
// OBSOLETE property axis fields - kept for migration from older project files
CAF_PDM_InitField( &m_visiblePropertyValueRangeMin_OBSOLETE, "VisibleXRangeMin", RI_LOGPLOTTRACK_MINX_DEFAULT, "Min" );
m_visiblePropertyValueRangeMin_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_visiblePropertyValueRangeMax_OBSOLETE, "VisibleXRangeMax", RI_LOGPLOTTRACK_MAXX_DEFAULT, "Max" );
m_visiblePropertyValueRangeMax_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_visibleDepthRangeMin, "VisibleYRangeMin", RI_LOGPLOTTRACK_MINX_DEFAULT, "Min" );
CAF_PDM_InitField( &m_visibleDepthRangeMax, "VisibleYRangeMax", RI_LOGPLOTTRACK_MAXX_DEFAULT, "Max" );
m_visibleDepthRangeMin.uiCapability()->setUiHidden( true );
m_visibleDepthRangeMin.xmlCapability()->disableIO();
m_visibleDepthRangeMax.uiCapability()->setUiHidden( true );
m_visibleDepthRangeMax.xmlCapability()->disableIO();
CAF_PDM_InitField( &m_isAutoScalePropertyValuesEnabled_OBSOLETE, "AutoScaleX", true, "Auto Scale" );
m_isAutoScalePropertyValuesEnabled_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_isPropertyLogarithmicScaleEnabled_OBSOLETE, "LogarithmicScaleX", false, "Logarithmic Scale" );
m_isPropertyLogarithmicScaleEnabled_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_invertPropertyValueAxis_OBSOLETE, "InvertPropertyValueAxis", false, "Invert Axis Range" );
m_invertPropertyValueAxis_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_isPropertyAxisEnabled_OBSOLETE, "IsPropertyAxisEnabled", true, "Show Axis" );
m_isPropertyAxisEnabled_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitFieldNoDefault( &m_propertyValueAxisGridVisibility_OBSOLETE, "ShowXGridLines", "Show Grid Lines" );
m_propertyValueAxisGridVisibility_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_explicitTickIntervalsPropertyValueAxis_OBSOLETE, "ExplicitTickIntervals", false, "Manually Set Tick Intervals" );
m_explicitTickIntervalsPropertyValueAxis_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_propertyAxisMinAndMaxTicksOnly_OBSOLETE, "MinAndMaxTicksOnly", false, "Show Ticks at Min and Max" );
m_propertyAxisMinAndMaxTicksOnly_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_majorTickIntervalPropertyAxis_OBSOLETE, "MajorTickIntervals", 0.0, "Major Tick Interval" );
m_majorTickIntervalPropertyAxis_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_minorTickIntervalPropertyAxis_OBSOLETE, "MinorTickIntervals", 0.0, "Minor Tick Interval" );
m_minorTickIntervalPropertyAxis_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitFieldNoDefault( &m_axisFontSize, "AxisFontSize", "Axis Font Size" );
// Region annotation settings
CAF_PDM_InitFieldNoDefault( &m_regionAnnotationSettings, "RegionAnnotationSettings", "" );
m_regionAnnotationSettings = new RimWellLogRegionAnnotationSettings();
m_regionAnnotationSettings.uiCapability()->setUiTreeChildrenHidden( true );
// OBSOLETE region annotation fields
CAF_PDM_InitFieldNoDefault( &m_regionAnnotationType_OBSOLETE, "AnnotationType", "Region Annotations" );
m_regionAnnotationType_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitFieldNoDefault( &m_regionAnnotationDisplay_OBSOLETE, "RegionDisplay", "Region Display" );
m_regionAnnotationDisplay_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitFieldNoDefault( &m_colorShadingLegend_OBSOLETE, "ColorShadingLegend", "Colors" );
m_colorShadingLegend_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_colorShadingTransparency_OBSOLETE, "ColorShadingTransparency", 50, "Color Transparency" );
m_colorShadingTransparency_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_showRegionLabels_OBSOLETE, "ShowFormationLabels", true, "Show Labels" );
m_showRegionLabels_OBSOLETE.xmlCapability()->setIOWritable( false );
caf::FontTools::RelativeSizeEnum regionLabelFontSizeDefault = caf::FontTools::RelativeSize::Small;
CAF_PDM_InitField( &m_regionLabelFontSize_OBSOLETE, "RegionLabelFontSize", regionLabelFontSizeDefault, "Font Size" );
m_regionLabelFontSize_OBSOLETE.xmlCapability()->setIOWritable( false );
// Formation settings
CAF_PDM_InitFieldNoDefault( &m_formationSettings, "FormationSettings", "" );
m_formationSettings = new RimWellLogFormationSettings();
m_formationSettings.uiCapability()->setUiTreeChildrenHidden( true );
// OBSOLETE formation fields
CAF_PDM_InitFieldNoDefault( &m_formationSource_OBSOLETE, "FormationSource", "Source" );
m_formationSource_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitFieldNoDefault( &m_formationTrajectoryType_OBSOLETE, "FormationTrajectoryType", "Trajectory" );
m_formationTrajectoryType_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitFieldNoDefault( &m_formationWellPathForSourceCase_OBSOLETE, "FormationWellPath", "Well Path" );
m_formationWellPathForSourceCase_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitFieldNoDefault( &m_formationWellPathForSourceWellPath_OBSOLETE, "FormationWellPathForSourceWellPath", "Well Path" );
m_formationWellPathForSourceWellPath_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_formationSimWellName_OBSOLETE, "FormationSimulationWellName", QString( "None" ), "Simulation Well" );
m_formationSimWellName_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_formationBranchIndex_OBSOLETE, "FormationBranchIndex", 0, " " );
m_formationBranchIndex_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_formationBranchDetection_OBSOLETE, "FormationBranchDetection", true, "Branch Detection" );
m_formationBranchDetection_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitFieldNoDefault( &m_formationCase_OBSOLETE, "FormationCase", "Formation Case" );
m_formationCase_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitFieldNoDefault( &m_formationLevel_OBSOLETE, "FormationLevel", "Well Pick Filter" );
m_formationLevel_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_showformationFluids_OBSOLETE, "ShowFormationFluids", false, "Show Fluids" );
m_showformationFluids_OBSOLETE.xmlCapability()->setIOWritable( false );
// Well path attribute settings
CAF_PDM_InitFieldNoDefault( &m_wellPathAttributeSettings, "WellPathAttributeSettings", "" );
m_wellPathAttributeSettings = new RimWellLogWellPathAttributeSettings();
m_wellPathAttributeSettings.uiCapability()->setUiTreeChildrenHidden( true );
// OBSOLETE well path attribute fields
CAF_PDM_InitField( &m_showWellPathAttributes_OBSOLETE, "ShowWellPathAttributes", false, "Show Well Attributes" );
m_showWellPathAttributes_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_wellPathAttributesInLegend_OBSOLETE, "WellPathAttributesInLegend", true, "Attributes in Legend" );
m_wellPathAttributesInLegend_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_showWellPathCompletions_OBSOLETE, "ShowWellPathCompletions", true, "Show Well Completions" );
m_showWellPathCompletions_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_wellPathCompletionsInLegend_OBSOLETE, "WellPathCompletionsInLegend", true, "Completions in Legend" );
m_wellPathCompletionsInLegend_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_showWellPathComponentsBothSides_OBSOLETE, "ShowWellPathAttrBothSides", true, "Show Both Sides" );
m_showWellPathComponentsBothSides_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_showWellPathComponentLabels_OBSOLETE, "ShowWellPathAttrLabels", false, "Show Labels" );
m_showWellPathComponentLabels_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitFieldNoDefault( &m_wellPathComponentSource_OBSOLETE, "AttributesWellPathSource", "Well Path" );
m_wellPathComponentSource_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitFieldNoDefault( &m_wellPathAttributeCollection_OBSOLETE, "AttributesCollection", "Well Attributes" );
m_wellPathAttributeCollection_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_overburdenHeight_OBSOLETE, "OverburdenHeight", 0.0, "Overburden Height" );
m_overburdenHeight_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_underburdenHeight_OBSOLETE, "UnderburdenHeight", 0.0, "Underburden Height" );
m_underburdenHeight_OBSOLETE.xmlCapability()->setIOWritable( false );
CAF_PDM_InitField( &m_autoCheckStateBasedOnCurveData, "AutoCheckStateBasedOnCurveData", false, "Hide Track if No Curve Data" );
CAF_PDM_InitFieldNoDefault( &m_resultDefinition, "ResultDefinition", "Result Definition" );
m_resultDefinition.uiCapability()->setUiTreeChildrenHidden( true );
m_resultDefinition = new RimEclipseResultDefinition;
CAF_PDM_InitFieldNoDefault( &m_ensembleWellLogCurveSet, "EnsembleWellLogCurveSet", "Ensemble Well Logs Curve Set" );
m_formationsForCaseWithSimWellOnly = false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogTrack::~RimWellLogTrack()
{
m_curves.deleteChildren();
deleteViewWidget();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogTrack::description() const
{
return m_description;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setDescription( const QString& description )
{
m_description = description;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::simWellOptionItems( QList<caf::PdmOptionItemInfo>* options, RimCase* rimCase )
{
CAF_ASSERT( options );
if ( !options ) return;
std::set<QString> sortedWellNames;
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
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 ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::cleanupBeforeClose()
{
detachAllPlotItems();
if ( m_plotWidget )
{
m_plotWidget->deleteLater();
m_plotWidget = nullptr;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::detachAllPlotItems()
{
for ( RimPlotCurve* curve : m_curves )
{
curve->detach();
}
for ( auto& plotObjects : m_wellPathAttributePlotObjects )
{
plotObjects->detachFromQwt();
}
if ( m_ensembleWellLogCurveSet )
{
m_ensembleWellLogCurveSet->detachPlotCurves();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::calculatePropertyValueZoomRange()
{
updateStackedCurveData();
double minValue = HUGE_VAL;
double maxValue = -HUGE_VAL;
size_t topologyCurveCount = 0;
for ( const auto& curve : m_curves )
{
double minCurveValue = HUGE_VAL;
double maxCurveValue = -HUGE_VAL;
if ( curve->isChecked() )
{
if ( curve->propertyValueRangeInData( &minCurveValue, &maxCurveValue ) )
{
if ( minCurveValue < minValue )
{
minValue = minCurveValue;
}
if ( maxCurveValue > maxValue )
{
maxValue = maxCurveValue;
}
}
}
if ( dynamic_cast<RimRftTopologyCurve*>( curve.p() ) ) topologyCurveCount++;
}
if ( topologyCurveCount == m_curves.size() )
{
// The topology track is quite narrow, and to be able to show the curves we add extra space for min/max values
const double range = maxValue - minValue;
maxValue += range * 0.5;
minValue -= range * 0.5;
}
if ( minValue == HUGE_VAL )
{
// Empty axis when there are no sensible visible curves
minValue = 0;
maxValue = 0;
}
else if ( m_propertyAxisSettings->minorTickInterval() != 0.0 )
{
std::tie( minValue, maxValue ) = adjustXRange( minValue, maxValue, m_propertyAxisSettings->minorTickInterval() );
}
else
{
double adjustmentFactor = 0.1;
auto [adjustedMin, adjustedMax] = extendMinMaxRange( minValue, maxValue, adjustmentFactor );
minValue = adjustedMin;
maxValue = adjustedMax;
}
m_availablePropertyValueRangeMin = minValue;
m_availablePropertyValueRangeMax = maxValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::calculateDepthZoomRange()
{
double minDepth = HUGE_VAL;
double maxDepth = -HUGE_VAL;
for ( RimWellLogCurve* curve : m_curves )
{
double minCurveDepth = HUGE_VAL;
double maxCurveDepth = -HUGE_VAL;
if ( curve->isChecked() && curve->depthValueRangeInData( &minCurveDepth, &maxCurveDepth ) )
{
if ( minCurveDepth < minDepth )
{
minDepth = minCurveDepth;
}
if ( maxCurveDepth > maxDepth )
{
maxDepth = maxCurveDepth;
}
}
}
if ( m_wellPathAttributeSettings->showWellPathAttributes() || m_wellPathAttributeSettings->showWellPathCompletions() )
{
for ( const std::unique_ptr<RiuWellPathComponentPlotItem>& plotObject : m_wellPathAttributePlotObjects )
{
double minObjectDepth = HUGE_VAL;
double maxObjectDepth = -HUGE_VAL;
if ( plotObject->depthValueRange( &minObjectDepth, &maxObjectDepth ) )
{
if ( minObjectDepth < minDepth )
{
minDepth = minObjectDepth;
}
if ( maxObjectDepth > maxDepth )
{
maxDepth = maxObjectDepth;
}
}
}
}
double adjustmentFactor = 0.02;
auto [adjustedMin, adjustedMax] = extendMinMaxRange( minDepth, maxDepth, adjustmentFactor );
m_availableDepthRangeMin = adjustedMin;
m_availableDepthRangeMax = adjustedMax;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updatePropertyValueZoom()
{
if ( !m_plotWidget ) return;
calculatePropertyValueZoomRange();
if ( m_propertyAxisSettings->isAutoScaleEnabled() )
{
double rangeMin = m_availablePropertyValueRangeMin;
double rangeMax = m_availablePropertyValueRangeMax;
if ( !visibleStackedCurves().empty() && !m_propertyAxisSettings->isLogarithmicScaleEnabled() )
{
// Try to ensure we include the base line whether the values are negative or positive.
rangeMin = std::min( rangeMin, 0.0 );
rangeMax = std::max( rangeMax, 0.0 );
}
m_propertyAxisSettings->setVisibleRange( rangeMin, rangeMax );
computeAndSetPropertyValueRangeMinForLogarithmicScale();
updateEditors();
}
updatePropertyValueAxisAndGridTickIntervals();
// Attribute range. Fixed range where well components are positioned [-1, 1].
// Set an extended range here to allow for some label space.
double componentRangeMax = 2.0 / ( static_cast<double>( colSpan() ) );
double componentRangeMin = -0.25;
if ( m_wellPathAttributeSettings->showBothSides() )
{
componentRangeMin = -1.5;
componentRangeMax *= 2.0;
}
if ( m_wellPathAttributeSettings->showComponentLabels() )
{
componentRangeMax *= 1.5;
}
RimDepthTrackPlot* wellLogPlot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
// Attribute components use the opposite axis to the property values
if ( wellLogPlot->depthOrientation() == RiaDefines::Orientation::VERTICAL )
{
m_plotWidget->setAxisRange( RiuPlotAxis::defaultBottom(), componentRangeMin, componentRangeMax );
}
else
{
m_plotWidget->setAxisRange( RiuPlotAxis::defaultRight(), componentRangeMin, componentRangeMax );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateDepthZoom()
{
if ( !m_plotWidget ) return;
RimDepthTrackPlot* wellLogPlot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
if ( wellLogPlot->depthOrientation() == RiaDefines::Orientation::VERTICAL )
{
m_plotWidget->setAxisRange( depthAxis(), m_visibleDepthRangeMin(), m_visibleDepthRangeMax() );
}
else
{
m_plotWidget->setAxisRange( RiuPlotAxis::defaultTop(), m_visibleDepthRangeMin(), m_visibleDepthRangeMax() );
m_plotWidget->setAxisRange( RiuPlotAxis::defaultBottom(), m_visibleDepthRangeMin(), m_visibleDepthRangeMax() );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimWellLogTrack::axisFontSize() const
{
return caf::FontTools::absolutePointSize( RiaPreferences::current()->defaultPlotFontSize(), m_axisFontSize() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
RimPlot::fieldChangedByUi( changedField, oldValue, newValue );
if ( changedField == &m_showWindow )
{
if ( m_plotWidget )
{
m_plotWidget->setVisible( m_showWindow );
}
updateParentLayout();
RimDepthTrackPlot* depthTrackPlot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
depthTrackPlot->updateDepthAxisVisibility();
}
else if ( changedField == &m_description )
{
updateParentLayout();
}
else if ( changedField == &m_autoCheckStateBasedOnCurveData )
{
updateCheckStateBasedOnCurveData();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::curveDataChanged( const caf::SignalEmitter* emitter )
{
for ( auto curve : m_curves )
{
if ( curve->isStacked() )
{
updateStackedCurveData();
break;
}
}
loadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::curveVisibilityChanged( const caf::SignalEmitter* emitter, bool visible )
{
const RimWellLogCurve* curve = dynamic_cast<const RimWellLogCurve*>( emitter );
if ( curve->isStacked() )
{
updateStackedCurveData();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::curveAppearanceChanged( const caf::SignalEmitter* emitter )
{
if ( m_plotWidget )
{
m_plotWidget->scheduleReplot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::curveStackingChanged( const caf::SignalEmitter* emitter, bool stacked )
{
updateStackedCurveData();
m_propertyAxisSettings->setAutoScaleEnabled( true );
updatePropertyValueZoom();
m_plotWidget->scheduleReplot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updatePropertyValueAxisAndGridTickIntervals()
{
if ( !m_plotWidget ) return;
bool emptyRange = isEmptyVisiblePropertyRange();
if ( emptyRange )
{
m_plotWidget->enableGridLines( valueAxis(), false, false );
m_plotWidget->setAxisRange( valueAxis(), 0.0, 1.0 );
m_plotWidget->setAxisLabelsAndTicksEnabled( valueAxis(), false, false );
}
else
{
m_plotWidget->setAxisLabelsAndTicksEnabled( valueAxis(), true, true );
auto rangeBoundaryA = m_propertyAxisSettings->visibleRangeMin();
auto rangeBoundaryB = m_propertyAxisSettings->visibleRangeMax();
if ( m_propertyAxisSettings->isAxisInverted() ) std::swap( rangeBoundaryA, rangeBoundaryB );
if ( m_propertyAxisSettings->isMinAndMaxTicksOnly() )
{
auto roundToDigits = []( double value, int numberOfDigits, bool useFloor )
{
if ( value == 0.0 ) return 0.0;
double factor = std::pow( 10.0, numberOfDigits - std::ceil( std::log10( std::fabs( value ) ) ) );
if ( useFloor )
{
// Use floor for maximum value to ensure we get a value inside the complete range
return std::floor( value * factor ) / factor;
}
// Use ceil for minimum value to ensure we get a value inside the complete range
return std::ceil( value * factor ) / factor;
};
auto div = QwtScaleDiv( rangeBoundaryA, rangeBoundaryB );
QList<double> majorTicks;
auto min = roundToDigits( rangeBoundaryA, 2, false );
auto max = roundToDigits( rangeBoundaryB, 2, true );
if ( min == max )
{
min = roundToDigits( rangeBoundaryA, 3, false );
max = roundToDigits( rangeBoundaryB, 3, true );
}
majorTicks.push_back( min );
majorTicks.push_back( max );
div.setTicks( QwtScaleDiv::TickType::MajorTick, majorTicks );
RimDepthTrackPlot* wellLogPlot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
if ( wellLogPlot->depthOrientation() == RiaDefines::Orientation::VERTICAL )
{
m_plotWidget->qwtPlot()->setAxisScaleDiv( QwtAxis::XTop, div );
}
else
{
m_plotWidget->qwtPlot()->setAxisScaleDiv( QwtAxis::YLeft, div );
}
}
else if ( m_propertyAxisSettings->isExplicitTickIntervals() )
{
m_plotWidget->setMajorAndMinorTickIntervals( valueAxis(),
m_propertyAxisSettings->majorTickInterval(),
m_propertyAxisSettings->minorTickInterval(),
rangeBoundaryA,
rangeBoundaryB );
}
else
{
int majorTickIntervals = 5;
int minorTickIntervals = 10;
m_plotWidget->setAutoTickIntervalCounts( valueAxis(), majorTickIntervals, minorTickIntervals );
m_plotWidget->setAxisRange( valueAxis(), rangeBoundaryA, rangeBoundaryB );
}
m_plotWidget->enableGridLines( valueAxis(),
m_propertyAxisSettings->gridVisibility() & RimWellLogPlot::AXIS_GRID_MAJOR,
m_propertyAxisSettings->gridVisibility() & RimWellLogPlot::AXIS_GRID_MINOR );
}
RimDepthTrackPlot* wellLogPlot = firstAncestorOrThisOfType<RimDepthTrackPlot>();
if ( wellLogPlot )
{
m_plotWidget->enableGridLines( depthAxis(),
wellLogPlot->depthAxisGridLinesEnabled() & RimWellLogPlot::AXIS_GRID_MAJOR,
wellLogPlot->depthAxisGridLinesEnabled() & RimWellLogPlot::AXIS_GRID_MINOR );
}
m_plotWidget->enableAxisNumberLabels( valueAxis(), m_propertyAxisSettings->isEnabled() );
m_plotWidget->scheduleReplot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateLegend()
{
reattachAllCurves();
if ( m_plotWidget )
{
m_plotWidget->updateLegend();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogTrack::asciiDataForPlotExport() const
{
QString out = "\n" + description() + "\n";
std::vector<QString> curveNames;
std::vector<double> curveDepths;
std::vector<std::vector<double>> curvesPlotXValues;
auto depthType = parentWellLogPlot()->depthType();
auto depthUnit = parentWellLogPlot()->depthUnit();
bool isWellAllocInflowPlot = false;
{
auto wapl = parentWellLogPlot()->firstAncestorOfType<RimWellAllocationPlot>();
if ( wapl )
{
isWellAllocInflowPlot = ( wapl->flowType() == RimWellAllocationPlot::INFLOW );
}
}
RiaWellLogCurveMerger curveMerger;
bool foundNonMatchingDepths = false;
for ( RimWellLogCurve* curve : m_curves() )
{
if ( !curve->isChecked() ) continue;
const RigWellLogCurveData& curveData = curve->curveData();
curveNames.push_back( curve->curveName() );
if ( curveNames.size() == 1 )
{
curveDepths = curveData.depthValuesByIntervals( depthType, depthUnit );
}
std::vector<double> xPlotValues = curveData.propertyValuesByIntervals();
if ( xPlotValues.empty() )
{
curveNames.pop_back();
if ( curveNames.empty() )
{
curveDepths.clear();
}
continue;
}
if ( curveDepths.size() != xPlotValues.size() )
{
foundNonMatchingDepths = true;
}
std::vector<double> depths = curveData.depthValuesByIntervals( depthType, depthUnit );
curveMerger.addCurveData( depths, xPlotValues );
curvesPlotXValues.push_back( xPlotValues );
}
// Header
if ( depthType == RiaDefines::DepthType::CONNECTION_NUMBER )
{
out += "Connection";
}
else if ( depthType == RiaDefines::DepthType::MEASURED_DEPTH )
{
out += "MD ";
}
else if ( depthType == RiaDefines::DepthType::PSEUDO_LENGTH )
{
out += "PL ";
}
else if ( depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH )
{
out += "TVDMSL ";
}
else if ( depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH_RKB )
{
out += "TVDRKB ";
}
for ( QString name : curveNames )
{
out += " \t" + name;
}
out += "\n";
// Resample when curves have different depth
if ( foundNonMatchingDepths )
{
curvesPlotXValues.clear();
curveDepths.clear();
curveMerger.computeLookupValues();
const std::vector<double>& allDepths = curveMerger.allXValues();
curveDepths = allDepths;
for ( size_t curveIdx = 0; curveIdx < curveMerger.curveCount(); ++curveIdx )
{
const std::vector<double>& curveValues = curveMerger.lookupYValuesForAllXValues( curveIdx );
curvesPlotXValues.push_back( curveValues );
}
}
for ( size_t dIdx = 0; dIdx < curveDepths.size(); ++dIdx )
{
size_t i = dIdx;
double curveDepth = curveDepths[i];
if ( depthType == RiaDefines::DepthType::CONNECTION_NUMBER )
{
if ( dIdx == 0 )
continue; // Skip the first line. (shallow depth, which is last)
// as it is a fictitious value added to make
// the plot easier to read
i = curveDepths.size() - 1 - dIdx; // Reverse the order, since the connections are coming bottom to top
if ( i == 0 )
{
if ( curveDepths.size() > 1 && curveDepths[i] == curveDepths[i + 1] )
{
continue; // Skip double depth at last connection
}
}
curveDepth = curveDepths[i];
if ( isWellAllocInflowPlot )
{
curveDepth -= 0.5; // To shift the values that was shifted to get the numbers between the changes
}
}
out += QString::number( curveDepth, 'f', 3 );
for ( std::vector<double> plotVector : curvesPlotXValues )
{
out += QString( " \t%1" ).arg( QString::number( plotVector[i], 'f', 3 ), 12 );
}
out += "\n";
}
return out;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateAxisRangesFromPlotWidget()
{
auto [xIntervalMin, xIntervalMax] = m_plotWidget->axisRange( valueAxis() );
auto [depthIntervalMin, depthIntervalMax] = m_plotWidget->axisRange( depthAxis() );
m_propertyAxisSettings->setVisibleRange( xIntervalMin, xIntervalMax );
m_visibleDepthRangeMin = depthIntervalMin;
m_visibleDepthRangeMax = depthIntervalMax;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::onAxisSelected( RiuPlotAxis axis, bool toggle )
{
RiuPlotMainWindowTools::selectOrToggleObject( this, toggle );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateAxes()
{
updatePropertyValueZoom();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimWellLogTrack::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
{
QList<caf::PdmOptionItemInfo> options;
// Formation field options are now handled by RimWellLogFormationSettings
// Region annotation field options are now handled by RimWellLogRegionAnnotationSettings
// Well path attribute field options are now handled by RimWellLogWellPathAttributeSettings
if ( fieldNeedingOptions == &m_ensembleWellLogCurveSet )
{
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::addCurve( RimWellLogCurve* curve )
{
m_curves.push_back( curve );
connectCurveSignals( curve );
if ( m_plotWidget )
{
curve->setParentPlotAndReplot( m_plotWidget );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::insertCurve( RimWellLogCurve* curve, size_t index )
{
if ( index >= m_curves.size() )
{
addCurve( curve );
}
else
{
m_curves.insert( index, curve );
connectCurveSignals( curve );
// Todo: Mark curve data to use either TVD or MD
if ( m_plotWidget )
{
curve->setParentPlotAndReplot( m_plotWidget );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::removeCurve( RimWellLogCurve* curve )
{
size_t index = m_curves.indexOf( curve );
if ( index < m_curves.size() )
{
m_curves[index]->detach();
m_curves.removeChild( curve );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::deleteAllCurves()
{
m_curves.deleteChildren();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::availablePropertyValueRange( double* minX, double* maxX )
{
calculatePropertyValueZoomRange();
*minX = m_availablePropertyValueRangeMin;
*maxX = m_availablePropertyValueRangeMax;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::availableDepthRange( double* minimumDepth, double* maximumDepth )
{
calculateDepthZoomRange();
*minimumDepth = m_availableDepthRangeMin;
*maximumDepth = m_availableDepthRangeMax;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::visiblePropertyValueRange( double* minX, double* maxX )
{
CAF_ASSERT( minX && maxX );
*minX = m_propertyAxisSettings->visibleRangeMin();
*maxX = m_propertyAxisSettings->visibleRangeMax();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::visibleDepthRange( double* minDepth, double* maxDepth )
{
CAF_ASSERT( minDepth && maxDepth );
*minDepth = m_visibleDepthRangeMin;
*maxDepth = m_visibleDepthRangeMax;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogTrack::isEmptyVisiblePropertyRange() const
{
return std::abs( m_propertyAxisSettings->visibleRangeMax() - m_propertyAxisSettings->visibleRangeMin() ) <
1.0e-6 * std::max( 1.0, std::max( m_propertyAxisSettings->visibleRangeMax(), m_propertyAxisSettings->visibleRangeMin() ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAutoCheckStateBasedOnCurveData( bool enable )
{
m_autoCheckStateBasedOnCurveData = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateCheckStateBasedOnCurveData()
{
bool curveDataPresent = false;
for ( const auto& curve : curves() )
{
curve->updateCheckStateBasedOnCurveData();
curve->updateCurveVisibility();
if ( curve->isAnyCurveDataPresent() ) curveDataPresent = true;
}
// As the visibility of a curve might have changed, update the legend
updateLegend();
if ( !m_autoCheckStateBasedOnCurveData ) return;
setShowWindow( curveDataPresent );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateAxesVisibility( RiaDefines::Orientation orientation, bool isFirstTrack, bool isLastTrack )
{
if ( !m_plotWidget ) return;
auto setAxisVisible = [this]( QwtAxis::Position axis, bool enable )
{
auto plot = m_plotWidget->qwtPlot();
if ( !plot ) return false;
bool isCurrentlyEnabled = plot->isAxisVisible( axis );
if ( enable == isCurrentlyEnabled ) return false;
m_plotWidget->setAxisEnabled( axis, enable );
return true;
};
bool needUpdate = false;
RimDepthTrackPlot* wellLogPlot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
bool showFirstTrack = wellLogPlot->depthAxisVisibility() == RiaDefines::MultiPlotAxisVisibility::ALL_VISIBLE ||
( isFirstTrack && wellLogPlot->depthAxisVisibility() == RiaDefines::MultiPlotAxisVisibility::ONE_VISIBLE );
bool showLastTrack = wellLogPlot->depthAxisVisibility() == RiaDefines::MultiPlotAxisVisibility::ALL_VISIBLE ||
( isLastTrack && wellLogPlot->depthAxisVisibility() == RiaDefines::MultiPlotAxisVisibility::ONE_VISIBLE );
if ( orientation == RiaDefines::Orientation::VERTICAL )
{
// Show depth axis only for the first track (on the left side)
needUpdate |= setAxisVisible( QwtAxis::XBottom, false );
needUpdate |= setAxisVisible( QwtAxis::XTop, true );
needUpdate |= setAxisVisible( QwtAxis::YLeft, showFirstTrack );
needUpdate |= setAxisVisible( QwtAxis::YRight, false );
}
else
{
// Show depth axis only for the last track (on the bottom side)
needUpdate |= setAxisVisible( QwtAxis::XTop, false );
needUpdate |= setAxisVisible( QwtAxis::XBottom, showLastTrack );
needUpdate |= setAxisVisible( QwtAxis::YLeft, true );
needUpdate |= setAxisVisible( QwtAxis::YRight, false );
}
if ( needUpdate ) onLoadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::onChildrenUpdated( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& updatedObjects )
{
if ( childArray == &m_curves )
{
// If multiple curves are unchecked, we need to attach/reattach to make sure the unchecked curves are not visible
detachAllCurves();
reattachAllCurves();
loadDataAndUpdate();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateDepthMarkerLine()
{
if ( m_plotWidget )
{
RimDepthTrackPlot* wellLogPlot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
if ( wellLogPlot->isDepthMarkerLineEnabled() )
{
m_plotWidget->createAnnotationsInPlot( wellLogPlot->depthAxisAnnotations() );
}
else
{
m_plotWidget->createAnnotationsInPlot( {} );
}
m_plotWidget->scheduleReplot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::onLoadDataAndUpdate()
{
auto wellLogPlot = firstAncestorOrThisOfType<RimDepthTrackPlot>();
if ( wellLogPlot && m_plotWidget )
{
m_plotWidget->setAxisTitleText( valueAxis(), m_propertyValueAxisTitle );
m_plotWidget->setAxisTitleText( depthAxis(), wellLogPlot->depthAxisTitle() );
}
for ( size_t cIdx = 0; cIdx < m_curves.size(); ++cIdx )
{
m_curves[cIdx]->loadDataAndUpdate( false );
}
if ( m_regionAnnotationSettings->annotationType() == RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS ||
m_regionAnnotationSettings->annotationType() == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
{
m_resultDefinition->loadDataAndUpdate();
}
if ( m_plotWidget )
{
updateWellPathAttributesCollection();
updateWellPathAttributesOnPlot();
m_plotWidget->updateLegend();
updateAxisScaleEngine();
updateRegionAnnotationsOnPlot();
updatePropertyValueZoom();
}
updatePropertyValueAxisAndGridTickIntervals();
updateDepthZoom();
updateLegend();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAndUpdateWellPathFormationNamesData( RimCase* rimCase, RimWellPath* wellPath )
{
m_formationSettings->setFormationCase( rimCase );
m_formationSettings->setTrajectoryType( RiaDefines::WellLogTrackTrajectoryType::WELL_PATH );
m_formationSettings->setWellPathForSourceCase( wellPath );
m_formationSettings->setSimWellName( "" );
m_formationSettings->setBranchIndex( -1 );
internal::setColorShadingLegendFromFormationCase( m_regionAnnotationSettings, rimCase );
updateConnectedEditors();
if ( m_regionAnnotationSettings->annotationType() != RiaDefines::RegionAnnotationType::NO_ANNOTATIONS )
{
updateRegionAnnotationsOnPlot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAndUpdateSimWellFormationNamesAndBranchData( RimCase* rimCase,
const QString& simWellName,
int branchIndex,
bool useBranchDetection )
{
m_formationSettings->setBranchIndex( branchIndex );
m_formationSettings->setBranchDetection( useBranchDetection );
setAndUpdateSimWellFormationNamesData( rimCase, simWellName );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAndUpdateSimWellFormationNamesData( RimCase* rimCase, const QString& simWellName )
{
m_formationSettings->setFormationCase( rimCase );
m_formationSettings->setTrajectoryType( RiaDefines::WellLogTrackTrajectoryType::SIMULATION_WELL );
m_formationSettings->setWellPathForSourceCase( nullptr );
m_formationSettings->setSimWellName( simWellName );
internal::setColorShadingLegendFromFormationCase( m_regionAnnotationSettings, rimCase );
updateConnectedEditors();
if ( m_regionAnnotationSettings->annotationType() != RiaDefines::RegionAnnotationType::NO_ANNOTATIONS )
{
updateRegionAnnotationsOnPlot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAutoScaleXEnabled( bool enabled )
{
CAF_ASSERT( "A well log track can be both vertical and horizontal, use setAutoScalePropertyValuesEnabled " );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAutoScaleYEnabled( bool enabled )
{
CAF_ASSERT( "A well log track can be both vertical and horizontal, use setAutoScaleDepthValuesEnabled " );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAutoScalePropertyValuesEnabled( bool enabled )
{
m_propertyAxisSettings->setAutoScaleEnabled( enabled );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAutoScaleDepthValuesEnabled( bool enabled )
{
if ( enabled )
{
m_visibleDepthRangeMin = m_availableDepthRangeMin;
m_visibleDepthRangeMax = m_availableDepthRangeMax;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAutoScalePropertyValuesIfNecessary()
{
// Avoid resetting if visible range has set to empty by user
bool emptyRange = isEmptyVisiblePropertyRange();
if ( !m_propertyAxisSettings->isAutoScaleEnabled() && emptyRange ) return;
const double eps = 1.0e-8;
calculatePropertyValueZoomRange();
double maxRange = std::max( m_propertyAxisSettings->visibleRangeMax() - m_propertyAxisSettings->visibleRangeMin(),
m_availablePropertyValueRangeMax - m_availablePropertyValueRangeMin );
double maxLow = std::max( m_propertyAxisSettings->visibleRangeMin(), m_availablePropertyValueRangeMin );
double minHigh = std::min( m_propertyAxisSettings->visibleRangeMax(), m_availablePropertyValueRangeMax );
double overlap = minHigh - maxLow;
if ( maxRange < eps || overlap < eps * maxRange )
{
setAutoScalePropertyValuesEnabled( true );
}
updatePropertyValueZoom();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setPropertyValueAxisTitle( const QString& text )
{
m_propertyValueAxisTitle = text;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogTrack::depthAxisTitle() const
{
RimDepthTrackPlot* parent = firstAncestorOrThisOfType<RimDepthTrackPlot>();
if ( parent )
{
return parent->depthAxisTitle();
}
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationWellPath( RimWellPath* wellPath )
{
m_formationSettings->setWellPathForSourceCase( wellPath );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RimWellLogTrack::formationWellPath() const
{
return m_formationSettings->wellPathForSourceCase();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationSimWellName( const QString& simWellName )
{
m_formationSettings->setSimWellName( simWellName );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogTrack::formationSimWellName() const
{
return m_formationSettings->simWellName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationBranchDetection( bool branchDetection )
{
m_formationSettings->setBranchDetection( branchDetection );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogTrack::formationBranchDetection() const
{
return m_formationSettings->branchDetection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationBranchIndex( int branchIndex )
{
m_formationSettings->setBranchIndex( branchIndex );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimWellLogTrack::formationBranchIndex() const
{
return m_formationSettings->branchIndex();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationCase( RimCase* rimCase )
{
m_formationSettings->setFormationCase( rimCase );
m_resultDefinition->setEclipseCase( dynamic_cast<RimEclipseCase*>( rimCase ) );
m_resultDefinition->setPorosityModel( RiaDefines::PorosityModelType::MATRIX_MODEL );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setRegionPropertyResultType( RiaDefines::ResultCatType resultCatType, const QString& resultVariable )
{
m_resultDefinition->setResultType( resultCatType );
m_resultDefinition->setResultVariable( resultVariable );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCase* RimWellLogTrack::formationCase() const
{
return m_formationSettings->formationCase();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationTrajectoryType( RiaDefines::WellLogTrackTrajectoryType trajectoryType )
{
m_formationSettings->setTrajectoryType( trajectoryType );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::WellLogTrackTrajectoryType RimWellLogTrack::formationTrajectoryType() const
{
return m_formationSettings->trajectoryType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuPlotWidget* RimWellLogTrack::doCreatePlotViewWidget( QWidget* mainWindowParent )
{
if ( m_plotWidget == nullptr )
{
m_plotWidget = new RiuWellLogTrack( this, mainWindowParent );
updateAxisScaleEngine();
for ( size_t cIdx = 0; cIdx < m_curves.size(); ++cIdx )
{
m_curves[cIdx]->setParentPlotNoReplot( m_plotWidget );
}
}
return m_plotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::deleteViewWidget()
{
cleanupBeforeClose();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::detachAllCurves()
{
detachAllPlotItems();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::reattachAllCurves()
{
for ( RimPlotCurve* curve : m_curves )
{
curve->reattach();
}
for ( auto& plotObjects : m_wellPathAttributePlotObjects )
{
plotObjects->reattachToQwt();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateParentPlotZoom()
{
if ( m_plotWidget )
{
RimDepthTrackPlot* wellLogPlot = firstAncestorOrThisOfType<RimDepthTrackPlot>();
if ( wellLogPlot )
{
wellLogPlot->updateZoom();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateEditors()
{
updateConnectedEditors();
RimPlotWindow* plotWindow = firstAncestorOrThisOfTypeAsserted<RimPlotWindow>();
plotWindow->updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setVisiblePropertyValueRange( double minValue, double maxValue )
{
setAutoScalePropertyValuesEnabled( false );
m_propertyAxisSettings->setVisibleRange( minValue, maxValue );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setVisibleDepthRange( double minValue, double maxValue )
{
m_visibleDepthRangeMin = minValue;
m_visibleDepthRangeMax = maxValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updatePlotWidgetFromAxisRanges()
{
updatePropertyValueZoom();
updateDepthZoom();
m_plotWidget->scheduleReplot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setTickIntervals( double majorTickInterval, double minorTickInterval )
{
m_propertyAxisSettings->setTickIntervals( majorTickInterval, minorTickInterval );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setMinAndMaxTicksOnly( bool enable )
{
m_propertyAxisSettings->setMinAndMaxTicksOnly( enable );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setPropertyValueAxisGridVisibility( RimWellLogPlot::AxisGridVisibility gridLines )
{
m_propertyAxisSettings->setGridVisibility( gridLines );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setColorShadingLegend( RimColorLegend* colorLegend )
{
m_regionAnnotationSettings->setColorShadingLegend( colorLegend );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAnnotationType( RiaDefines::RegionAnnotationType annotationType )
{
m_regionAnnotationSettings->setAnnotationType( annotationType );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAnnotationDisplay( RiaDefines::RegionDisplay annotationDisplay )
{
m_regionAnnotationSettings->setAnnotationDisplay( annotationDisplay );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAnnotationTransparency( int percent )
{
m_regionAnnotationSettings->setColorShadingTransparency( percent );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::RegionAnnotationType RimWellLogTrack::annotationType() const
{
return m_regionAnnotationSettings->annotationType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::RegionDisplay RimWellLogTrack::annotationDisplay() const
{
return m_regionAnnotationSettings->annotationDisplay();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogTrack::showFormations() const
{
return m_regionAnnotationSettings->annotationType() == RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setShowRegionLabels( bool on )
{
m_regionAnnotationSettings->setShowRegionLabels( on );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogTrack::showWellPathAttributes() const
{
return m_wellPathAttributeSettings->showWellPathAttributes();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setShowWellPathAttributes( bool on )
{
m_wellPathAttributeSettings->setShowWellPathAttributes( on );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setShowWellPathAttributesInLegend( bool on )
{
m_wellPathAttributeSettings->setShowAttributesInLegend( on );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setShowWellPathCompletionsInLegend( bool on )
{
m_wellPathAttributeSettings->setShowCompletionsInLegend( on );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setShowBothSidesOfWell( bool on )
{
m_wellPathAttributeSettings->setShowBothSides( on );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setWellPathAttributesSource( RimWellPath* wellPath )
{
m_wellPathAttributeSettings->setWellPathComponentSource( wellPath );
updateWellPathAttributesCollection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RimWellLogTrack::wellPathAttributeSource() const
{
return m_wellPathAttributeSettings->wellPathComponentSource();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimWellLogTrack::viewWidget()
{
return m_plotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuQwtPlotWidget* RimWellLogTrack::viewer()
{
return m_plotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuPlotWidget* RimWellLogTrack::plotWidget()
{
return m_plotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::zoomAll()
{
RimDepthTrackPlot* plot = firstAncestorOrThisOfType<RimDepthTrackPlot>();
if ( plot ) plot->zoomAll();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &m_description );
RimDepthTrackPlot* plot = firstAncestorOrThisOfType<RimDepthTrackPlot>();
bool isHorizontal = plot && plot->depthOrientation() == RiaDefines::Orientation::HORIZONTAL;
if ( isHorizontal )
uiOrdering.add( &m_rowSpan );
else
uiOrdering.add( &m_colSpan );
caf::PdmUiGroup* automationGroup = uiOrdering.addNewGroup( "Automation" );
automationGroup->setCollapsedByDefault();
automationGroup->add( &m_autoCheckStateBasedOnCurveData );
caf::PdmUiGroup* annotationGroup = uiOrdering.addNewGroup( "Regions/Annotations" );
m_regionAnnotationSettings->uiOrdering( uiConfigName, *annotationGroup );
if ( m_regionAnnotationSettings->annotationType() == RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS )
{
m_formationSettings->uiOrdering( uiConfigName, *annotationGroup, m_formationsForCaseWithSimWellOnly );
}
if ( m_regionAnnotationSettings->annotationType() == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
{
m_resultDefinition->uiOrdering( uiConfigName, *annotationGroup );
}
caf::PdmUiGroup* componentGroup = uiOrdering.addNewGroup( "Well Path Components" );
componentGroup->setCollapsedByDefault();
m_wellPathAttributeSettings->uiOrdering( uiConfigName, *componentGroup );
uiOrdering.add( &m_ensembleWellLogCurveSet );
uiOrderingForPropertyAxisSettings( uiOrdering );
uiOrdering.skipRemainingFields( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::initAfterRead()
{
if ( m_regionAnnotationSettings->annotationType() == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
{
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_formationSettings->formationCase() );
m_resultDefinition->setEclipseCase( dynamic_cast<RimEclipseCase*>( eclipseCase ) );
}
// Migrate property axis settings from obsolete fields (pre-2025.12.0)
if ( RimProject::current()->isProjectFileVersionEqualOrOlderThan( "2025.12.0" ) )
{
m_propertyAxisSettings->setEnabled( m_isPropertyAxisEnabled_OBSOLETE() );
m_propertyAxisSettings->setVisibleRange( m_visiblePropertyValueRangeMin_OBSOLETE(), m_visiblePropertyValueRangeMax_OBSOLETE() );
m_propertyAxisSettings->setAutoScaleEnabled( m_isAutoScalePropertyValuesEnabled_OBSOLETE() );
m_propertyAxisSettings->setLogarithmicScaleEnabled( m_isPropertyLogarithmicScaleEnabled_OBSOLETE() );
m_propertyAxisSettings->setAxisInverted( m_invertPropertyValueAxis_OBSOLETE() );
auto gridVisibility = m_propertyValueAxisGridVisibility_OBSOLETE();
if ( gridVisibility == RimWellLogPlot::AXIS_GRID_MINOR )
{
gridVisibility = RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR;
}
m_propertyAxisSettings->setGridVisibility( gridVisibility );
m_propertyAxisSettings->setMinAndMaxTicksOnly( m_propertyAxisMinAndMaxTicksOnly_OBSOLETE() );
m_propertyAxisSettings->setExplicitTickIntervals( m_explicitTickIntervalsPropertyValueAxis_OBSOLETE() );
if ( m_explicitTickIntervalsPropertyValueAxis_OBSOLETE() )
{
m_propertyAxisSettings->setTickIntervals( m_majorTickIntervalPropertyAxis_OBSOLETE(), m_minorTickIntervalPropertyAxis_OBSOLETE() );
}
// Migrate formation settings from obsolete fields
m_formationSettings->setFormationSource( m_formationSource_OBSOLETE() );
m_formationSettings->setFormationCase( m_formationCase_OBSOLETE() );
m_formationSettings->setTrajectoryType( m_formationTrajectoryType_OBSOLETE() );
m_formationSettings->setWellPathForSourceCase( m_formationWellPathForSourceCase_OBSOLETE() );
m_formationSettings->setWellPathForSourceWellPath( m_formationWellPathForSourceWellPath_OBSOLETE() );
m_formationSettings->setSimWellName( m_formationSimWellName_OBSOLETE() );
m_formationSettings->setBranchIndex( m_formationBranchIndex_OBSOLETE() );
m_formationSettings->setBranchDetection( m_formationBranchDetection_OBSOLETE() );
m_formationSettings->setFormationLevel( m_formationLevel_OBSOLETE() );
m_formationSettings->setShowFormationFluids( m_showformationFluids_OBSOLETE() );
// Migrate region annotation settings from obsolete fields
m_regionAnnotationSettings->setAnnotationType( m_regionAnnotationType_OBSOLETE() );
m_regionAnnotationSettings->setAnnotationDisplay( m_regionAnnotationDisplay_OBSOLETE() );
m_regionAnnotationSettings->setColorShadingLegend( m_colorShadingLegend_OBSOLETE() );
m_regionAnnotationSettings->setColorShadingTransparency( m_colorShadingTransparency_OBSOLETE() );
m_regionAnnotationSettings->setShowRegionLabels( m_showRegionLabels_OBSOLETE() );
m_regionAnnotationSettings->setRegionLabelFontSize( m_regionLabelFontSize_OBSOLETE() );
// Migrate well path attribute settings from obsolete fields
m_wellPathAttributeSettings->setShowWellPathAttributes( m_showWellPathAttributes_OBSOLETE() );
m_wellPathAttributeSettings->setShowWellPathCompletions( m_showWellPathCompletions_OBSOLETE() );
m_wellPathAttributeSettings->setShowBothSides( m_showWellPathComponentsBothSides_OBSOLETE() );
m_wellPathAttributeSettings->setShowComponentLabels( m_showWellPathComponentLabels_OBSOLETE() );
m_wellPathAttributeSettings->setShowAttributesInLegend( m_wellPathAttributesInLegend_OBSOLETE() );
m_wellPathAttributeSettings->setShowCompletionsInLegend( m_wellPathCompletionsInLegend_OBSOLETE() );
m_wellPathAttributeSettings->setWellPathComponentSource( m_wellPathComponentSource_OBSOLETE() );
m_wellPathAttributeSettings->setWellPathAttributeCollection( m_wellPathAttributeCollection_OBSOLETE() );
m_wellPathAttributeSettings->setOverburdenHeight( m_overburdenHeight_OBSOLETE() );
m_wellPathAttributeSettings->setUnderburdenHeight( m_underburdenHeight_OBSOLETE() );
}
for ( auto curve : m_curves )
{
connectCurveSignals( curve );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimWellLogTrack::userDescriptionField()
{
return &m_description;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RimWellLogTrack::curveIndex( RimWellLogCurve* curve )
{
return m_curves.indexOf( curve );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateAxisScaleEngine()
{
if ( !m_plotWidget ) return;
auto wellLogPlot = firstAncestorOrThisOfType<RimDepthTrackPlot>();
if ( wellLogPlot )
{
if ( wellLogPlot->depthOrientation() == RiaDefines::Orientation::VERTICAL )
{
m_plotWidget->setAxisInverted( RiuPlotAxis::defaultLeft(), true );
if ( m_propertyAxisSettings->isLogarithmicScaleEnabled() )
{
m_plotWidget->qwtPlot()->setAxisScaleEngine( QwtAxis::XTop, new QwtLogScaleEngine );
// NB! Must assign scale engine to bottom in order to make QwtPlotGrid work
m_plotWidget->qwtPlot()->setAxisScaleEngine( QwtAxis::XBottom, new QwtLogScaleEngine );
}
else
{
m_plotWidget->qwtPlot()->setAxisScaleEngine( QwtAxis::XTop, new RiuQwtLinearScaleEngine );
// NB! Must assign scale engine to bottom in order to make QwtPlotGrid work
m_plotWidget->qwtPlot()->setAxisScaleEngine( QwtAxis::XBottom, new RiuQwtLinearScaleEngine );
}
}
else
{
m_plotWidget->setAxisInverted( RiuPlotAxis::defaultLeft(), false );
if ( m_propertyAxisSettings->isLogarithmicScaleEnabled() )
{
m_plotWidget->qwtPlot()->setAxisScaleEngine( QwtAxis::YLeft, new QwtLogScaleEngine );
// NB! Must assign scale engine to bottom in order to make QwtPlotGrid work
m_plotWidget->qwtPlot()->setAxisScaleEngine( QwtAxis::YRight, new QwtLogScaleEngine );
}
else
{
m_plotWidget->qwtPlot()->setAxisScaleEngine( QwtAxis::YLeft, new RiuQwtLinearScaleEngine );
// NB! Must assign scale engine to bottom in order to make QwtPlotGrid work
m_plotWidget->qwtPlot()->setAxisScaleEngine( QwtAxis::YRight, new RiuQwtLinearScaleEngine );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<double, double> RimWellLogTrack::adjustXRange( double minValue, double maxValue, double tickInterval )
{
double minRemainder = std::fmod( minValue, tickInterval );
double maxRemainder = std::fmod( maxValue, tickInterval );
double adjustedMin = minValue - minRemainder;
double adjustedMax = maxValue + ( tickInterval - maxRemainder );
return std::make_pair( adjustedMin, adjustedMax );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<double, double> RimWellLogTrack::extendMinMaxRange( double minValue, double maxValue, double factor )
{
if ( minValue == std::numeric_limits<double>::infinity() || maxValue == std::numeric_limits<double>::infinity() )
{
return { minValue, maxValue };
}
auto modifiedMin = minValue;
auto modifiedMax = maxValue;
auto range = std::fabs( maxValue - minValue );
if ( range < 1e-6 )
{
// If min and max are equal, the curve is not visible. Make sure the range is larger than zero.
if ( maxValue != 0.0 )
{
range = maxValue * 0.01;
}
else
{
range = 1.0;
}
}
modifiedMax += factor * range;
auto candidateMinValue = minValue - factor * range;
if ( std::signbit( minValue ) == std::signbit( candidateMinValue ) )
{
modifiedMin = candidateMinValue;
}
else
{
// If the sign of the adjusted minimum changes, set minimum to zero to make sure that zero is located properly
modifiedMin = 0.0;
}
return { modifiedMin, modifiedMax };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateWellPathAttributesCollection()
{
m_wellPathAttributeSettings->setWellPathAttributeCollection( nullptr );
if ( m_wellPathAttributeSettings->wellPathComponentSource() )
{
std::vector<RimWellPathAttributeCollection*> attributeCollection =
m_wellPathAttributeSettings->wellPathComponentSource()->descendantsIncludingThisOfType<RimWellPathAttributeCollection>();
if ( !attributeCollection.empty() )
{
m_wellPathAttributeSettings->setWellPathAttributeCollection( attributeCollection.front() );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDepthTrackPlot* RimWellLogTrack::parentWellLogPlot() const
{
return firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::handleWheelEvent( QWheelEvent* wheelEvent )
{
auto wellLogPlot = firstAncestorOrThisOfType<RimDepthTrackPlot>();
if ( wellLogPlot )
{
if ( wheelEvent->modifiers() & Qt::ControlModifier )
{
double zoomCenter = 0.0;
auto position = caf::position( wheelEvent );
if ( wellLogPlot->depthOrientation() == RiaDefines::Orientation::VERTICAL )
{
QwtScaleMap scaleMap = m_plotWidget->qwtPlot()->canvasMap( QwtAxis::YLeft );
zoomCenter = scaleMap.invTransform( position.y() );
}
else
{
QwtScaleMap scaleMap = m_plotWidget->qwtPlot()->canvasMap( QwtAxis::XTop );
zoomCenter = scaleMap.invTransform( position.x() );
}
if ( wheelEvent->angleDelta().y() > 0 )
{
wellLogPlot->setDepthAxisRangeByFactorAndCenter( RI_SCROLLWHEEL_ZOOMFACTOR, zoomCenter );
}
else
{
wellLogPlot->setDepthAxisRangeByFactorAndCenter( 1.0 / RI_SCROLLWHEEL_ZOOMFACTOR, zoomCenter );
}
}
else
{
wellLogPlot->setDepthAxisRangeByPanDepth( wheelEvent->angleDelta().y() < 0 ? RI_SCROLLWHEEL_PANFACTOR : -RI_SCROLLWHEEL_PANFACTOR );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<std::pair<double, double>> RimWellLogTrack::waterAndRockRegions( RiaDefines::DepthType depthType,
const RigGeoMechWellLogExtractor* extractor ) const
{
double waterEndTVD = extractor->waterDepth();
if ( waterEndTVD == std::numeric_limits<double>::infinity() )
{
waterEndTVD = extractor->estimateWaterDepth();
}
if ( depthType == RiaDefines::DepthType::MEASURED_DEPTH )
{
double waterStartMD = 0.0;
if ( extractor->wellPathGeometry()->rkbDiff() != std::numeric_limits<double>::infinity() )
{
waterStartMD += extractor->wellPathGeometry()->rkbDiff();
}
double waterEndMD = extractor->cellIntersectionMDs().front();
double rockEndMD = extractor->cellIntersectionMDs().back();
return { { waterStartMD, waterEndMD }, { waterEndMD, rockEndMD } };
}
else if ( depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH )
{
double waterStartTVD = 0.0;
double rockEndTVD = extractor->cellIntersectionTVDs().back();
return { { waterStartTVD, waterEndTVD }, { waterEndTVD, rockEndTVD } };
}
else if ( depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH_RKB )
{
double waterStartTVDRKB = extractor->wellPathGeometry()->rkbDiff();
double waterEndTVDRKB = waterEndTVD + extractor->wellPathGeometry()->rkbDiff();
double rockEndTVDRKB = extractor->cellIntersectionTVDs().back() + extractor->wellPathGeometry()->rkbDiff();
return { { waterStartTVDRKB, waterEndTVDRKB }, { waterEndTVDRKB, rockEndTVDRKB } };
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::connectCurveSignals( RimWellLogCurve* curve )
{
curve->dataChanged.connect( this, &RimWellLogTrack::curveDataChanged );
curve->visibilityChanged.connect( this, &RimWellLogTrack::curveVisibilityChanged );
curve->appearanceChanged.connect( this, &RimWellLogTrack::curveAppearanceChanged );
curve->stackingChanged.connect( this, &RimWellLogTrack::curveStackingChanged );
curve->stackingColorsChanged.connect( this, &RimWellLogTrack::curveStackingChanged );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::computeAndSetPropertyValueRangeMinForLogarithmicScale()
{
if ( m_propertyAxisSettings->isAutoScaleEnabled() && m_propertyAxisSettings->isLogarithmicScaleEnabled() )
{
double pos = HUGE_VAL;
double neg = -HUGE_VAL;
for ( const auto& curve : m_curves )
{
if ( curve->isChecked() )
{
RigStatisticsCalculator::posNegClosestToZero( curve->curveData().propertyValuesByIntervals(), pos, neg );
}
}
if ( pos != HUGE_VAL )
{
m_propertyAxisSettings->setVisibleRange( pos, m_propertyAxisSettings->visibleRangeMax() );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setLogarithmicScale( bool enable )
{
m_propertyAxisSettings->setLogarithmicScaleEnabled( enable );
updateAxisScaleEngine();
computeAndSetPropertyValueRangeMinForLogarithmicScale();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogTrack::isLogarithmicScale() const
{
return m_propertyAxisSettings->isLogarithmicScaleEnabled();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::map<int, std::vector<RimWellLogCurve*>> RimWellLogTrack::visibleStackedCurves()
{
std::map<int, std::vector<RimWellLogCurve*>> stackedCurves;
for ( RimWellLogCurve* curve : m_curves )
{
if ( curve && curve->isChecked() )
{
RimWellFlowRateCurve* wfrCurve = dynamic_cast<RimWellFlowRateCurve*>( curve );
if ( wfrCurve != nullptr ) // Flow rate curves are always stacked
{
stackedCurves[wfrCurve->groupId()].push_back( wfrCurve );
}
else if ( curve->isStacked() )
{
stackedCurves[-1].push_back( curve );
}
}
}
return stackedCurves;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimWellLogCurve*> RimWellLogTrack::curves() const
{
return m_curves.childrenByType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimWellLogCurve*> RimWellLogTrack::visibleCurves() const
{
std::vector<RimWellLogCurve*> curvesVector;
for ( RimWellLogCurve* curve : m_curves.childrenByType() )
{
if ( curve->isChecked() )
{
curvesVector.push_back( curve );
}
}
return curvesVector;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::uiOrderingForRftPltFormations( caf::PdmUiOrdering& uiOrdering )
{
caf::PdmUiGroup* formationGroup = uiOrdering.addNewGroup( "Zonation/Formation Names" );
formationGroup->setCollapsedByDefault();
// Region annotation settings UI ordering
m_regionAnnotationSettings->uiOrdering( "", *formationGroup );
// Delegate to formation settings for formation-related fields
m_formationSettings->uiOrdering( "", *formationGroup, m_formationsForCaseWithSimWellOnly );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::uiOrderingForPropertyAxisSettings( caf::PdmUiOrdering& uiOrdering )
{
m_propertyAxisSettings->uiOrdering( "", uiOrdering );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::enablePropertyAxis( bool enable )
{
m_propertyAxisSettings->setEnabled( enable );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogTrack::isPropertyAxisEnabled() const
{
return m_propertyAxisSettings->isEnabled();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationsForCaseWithSimWellOnly( bool caseWithSimWellOnly )
{
m_formationsForCaseWithSimWellOnly = caseWithSimWellOnly;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigEclipseWellLogExtractor* RimWellLogTrack::createSimWellExtractor( RimWellLogPlotCollection* wellLogCollection,
RimCase* rimCase,
const QString& simWellName,
int branchIndex,
bool useBranchDetection )
{
if ( !wellLogCollection ) return nullptr;
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
if ( !eclipseCase ) return nullptr;
std::vector<const RigWellPath*> wellPaths = RiaSimWellBranchTools::simulationWellBranches( simWellName, useBranchDetection );
if ( wellPaths.empty() ) return nullptr;
CAF_ASSERT( branchIndex >= 0 && branchIndex < static_cast<int>( wellPaths.size() ) );
return ( wellLogCollection->findOrCreateSimWellExtractor( simWellName,
QString( "Find or create sim well extractor" ),
wellPaths[branchIndex],
eclipseCase->eclipseCaseData() ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CurveSamplingPointData RimWellLogTrack::curveSamplingPointData( RigEclipseWellLogExtractor* extractor, RigResultAccessor* resultAccessor )
{
CurveSamplingPointData curveData;
curveData.md = extractor->cellIntersectionMDs();
curveData.tvd = extractor->cellIntersectionTVDs();
curveData.rkbDiff = extractor->wellPathGeometry()->rkbDiff();
extractor->curveData( resultAccessor, &curveData.data );
return curveData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
CurveSamplingPointData RimWellLogTrack::curveSamplingPointData( RigGeoMechWellLogExtractor* extractor, const RigFemResultAddress& resultAddress )
{
CurveSamplingPointData curveData;
curveData.md = extractor->cellIntersectionMDs();
curveData.tvd = extractor->cellIntersectionTVDs();
curveData.rkbDiff = extractor->wellPathGeometry()->rkbDiff();
extractor->curveData( resultAddress, 0, 0, &curveData.data );
return curveData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::findRegionNamesToPlot( const CurveSamplingPointData& curveData,
const std::vector<QString>& regionNamesVector,
RimWellLogPlot::DepthTypeEnum depthType,
std::vector<QString>* regionNamesToPlot,
std::vector<std::pair<double, double>>* yValues )
{
if ( regionNamesVector.empty() ) return;
std::vector<size_t> regionNameIndicesFromCurve;
for ( double nameIdx : curveData.data )
{
if ( nameIdx != std::numeric_limits<double>::infinity() )
{
regionNameIndicesFromCurve.push_back( static_cast<size_t>( round( nameIdx ) ) );
}
else
{
regionNameIndicesFromCurve.push_back( std::numeric_limits<size_t>::max() );
}
}
if ( regionNameIndicesFromCurve.empty() ) return;
std::vector<double> depthVector;
if ( depthType == RiaDefines::DepthType::MEASURED_DEPTH || depthType == RiaDefines::DepthType::PSEUDO_LENGTH )
{
depthVector = curveData.md;
}
else if ( depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH || depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH_RKB )
{
depthVector = curveData.tvd;
if ( depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH_RKB )
{
for ( double& depthValue : depthVector )
{
depthValue += curveData.rkbDiff;
}
}
}
if ( depthVector.empty() ) return;
double currentYStart = depthVector[0];
size_t prevNameIndex = regionNameIndicesFromCurve[0];
size_t currentNameIndex;
for ( size_t i = 1; i < regionNameIndicesFromCurve.size(); i++ )
{
currentNameIndex = regionNameIndicesFromCurve[i];
if ( currentNameIndex != std::numeric_limits<size_t>::max() && currentNameIndex != prevNameIndex )
{
if ( prevNameIndex < regionNamesVector.size() )
{
regionNamesToPlot->push_back( regionNamesVector[prevNameIndex] );
yValues->push_back( std::make_pair( currentYStart, depthVector[i - 1] ) );
}
currentYStart = depthVector[i];
prevNameIndex = currentNameIndex;
}
}
size_t lastFormationIdx = regionNameIndicesFromCurve.back();
if ( lastFormationIdx < regionNamesVector.size() )
{
regionNamesToPlot->push_back( regionNamesVector[lastFormationIdx] );
yValues->push_back( std::make_pair( currentYStart, depthVector.back() ) );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QString> RimWellLogTrack::formationNamesVector( RimCase* rimCase )
{
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( rimCase );
RimGeoMechCase* geoMechCase = dynamic_cast<RimGeoMechCase*>( rimCase );
if ( eclipseCase )
{
return eclipseCase->eclipseCaseData()->formationNames();
}
else if ( geoMechCase )
{
return geoMechCase->geoMechData()->femPartResults()->formationNames();
}
return std::vector<QString>();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateStackedCurveData()
{
// See RimSummaryPlot::updateStackedCurveDataForAxis() horizontal plots
RimDepthTrackPlot* wellLogPlot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
RimWellLogPlot::DepthTypeEnum depthType = wellLogPlot->depthType();
RiaDefines::DepthUnitType displayUnit = wellLogPlot->depthUnit();
if ( depthType == RiaDefines::DepthType::CONNECTION_NUMBER )
{
displayUnit = RiaDefines::DepthUnitType::UNIT_NONE;
}
std::map<RiaDefines::PhaseType, size_t> curvePhaseCount;
// Stack the curves that are meant to be stacked
std::map<int, std::vector<RimWellLogCurve*>> stackedCurves = visibleStackedCurves();
// Reset all stacked curves
for ( auto groupCurvePair : stackedCurves )
{
const std::vector<RimWellLogCurve*>& stackedCurvesInGroup = groupCurvePair.second;
for ( auto curve : stackedCurvesInGroup )
{
curve->loadDataAndUpdate( false );
curvePhaseCount[curve->phaseType()]++;
}
}
for ( auto groupCurvePair : stackedCurves )
{
int groupId = groupCurvePair.first;
const std::vector<RimWellLogCurve*>& stackedCurvesInGroup = groupCurvePair.second;
if ( stackedCurvesInGroup.empty() ) continue;
// Z-position of curve, to draw them in correct order
double zPos = -10000.0 + 100.0 * static_cast<double>( groupId );
// We use the depths from the curve with the largest depth range.
// Trying to merge them is difficult since they may not be in order.
std::pair<double, double> maxDepthRange;
std::vector<double> allDepthValues;
for ( auto curve : stackedCurvesInGroup )
{
auto depths = curve->curveData().depths( depthType );
if ( depths.empty() ) continue;
if ( allDepthValues.empty() )
{
auto minmaxit = std::minmax_element( depths.begin(), depths.end() );
maxDepthRange = std::make_pair( *minmaxit.first, *minmaxit.second );
allDepthValues.insert( allDepthValues.end(), depths.begin(), depths.end() );
}
else
{
auto minmaxit = std::minmax_element( depths.begin(), depths.end() );
std::pair<double, double> depthRange = std::make_pair( *minmaxit.first, *minmaxit.second );
if ( std::fabs( depthRange.second - depthRange.first ) > std::fabs( maxDepthRange.second - maxDepthRange.first ) )
{
maxDepthRange = depthRange;
allDepthValues = depths;
}
}
}
if ( allDepthValues.empty() ) continue;
size_t stackIndex = 0u;
std::vector<double> allStackedValues( allDepthValues.size(), 0.0 );
for ( auto curve : stackedCurvesInGroup )
{
auto interpolatedCurveValues = curve->curveData().calculateResampledCurveData( depthType, allDepthValues );
auto xValues = interpolatedCurveValues.propertyValues();
for ( size_t i = 0; i < xValues.size(); ++i )
{
if ( xValues[i] != HUGE_VAL )
{
allStackedValues[i] += xValues[i];
}
}
RigWellLogCurveData tempCurveData;
tempCurveData.setValuesAndDepths( allStackedValues,
allDepthValues,
depthType,
0.0,
displayUnit,
false,
m_propertyAxisSettings->isLogarithmicScaleEnabled() );
auto plotDepthValues = tempCurveData.depths( depthType );
auto polyLineStartStopIndices = tempCurveData.polylineStartStopIndices();
curve->setOverrideCurveData( allStackedValues, plotDepthValues, polyLineStartStopIndices );
curve->setZOrder( zPos );
if ( !dynamic_cast<RimWellFlowRateCurve*>( curve ) )
{
// Apply a area filled style if it isn't already set
if ( curve->fillStyle() == Qt::NoBrush )
{
curve->setFillStyle( Qt::SolidPattern );
}
if ( curve->isStackedWithPhaseColors() )
{
curve->assignStackColor( stackIndex, curvePhaseCount[curve->phaseType()] );
}
}
zPos -= 1.0;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateRegionAnnotationsOnPlot()
{
removeRegionAnnotations();
if ( m_regionAnnotationSettings->annotationType() == RiaDefines::RegionAnnotationType::NO_ANNOTATIONS ) return;
if ( m_annotationTool == nullptr )
{
m_annotationTool = std::make_unique<RiuPlotAnnotationTool>();
}
if ( m_regionAnnotationSettings->annotationType() == RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS )
{
updateFormationNamesOnPlot();
}
else if ( m_regionAnnotationSettings->annotationType() == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
{
updateResultPropertyNamesOnPlot();
}
else
{
updateCurveDataRegionsOnPlot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateFormationNamesOnPlot()
{
RimDepthTrackPlot* plot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
RiaDefines::DepthUnitType fromDepthUnit = plot->caseDepthUnit();
RiaDefines::DepthUnitType toDepthUnit = plot->depthUnit();
auto orientation = plot->depthOrientation();
if ( m_formationSettings->formationSource() == RiaDefines::WellLogTrackFormationSource::WELL_PICK_FILTER )
{
if ( m_formationSettings->wellPathForSourceWellPath() == nullptr ) return;
if ( plot->depthType() != RiaDefines::DepthType::MEASURED_DEPTH && plot->depthType() != RiaDefines::DepthType::TRUE_VERTICAL_DEPTH &&
plot->depthType() != RiaDefines::DepthType::TRUE_VERTICAL_DEPTH_RKB )
{
return;
}
std::vector<double> yValues;
const RigWellPathFormations* formations = m_formationSettings->wellPathForSourceWellPath()->formationsGeometry();
if ( !formations ) return;
std::vector<QString> formationNamesToPlot;
auto formationLevel = static_cast<RigWellPathFormations::FormationLevel>( m_formationSettings->formationLevel() );
formations->depthAndFormationNamesUpToLevel( formationLevel,
&formationNamesToPlot,
&yValues,
m_formationSettings->showFormationFluids(),
plot->depthType() );
if ( plot->depthType() == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH_RKB )
{
for ( double& depthValue : yValues )
{
depthValue += m_formationSettings->wellPathForSourceWellPath()->wellPathGeometry()->rkbDiff();
}
}
std::vector<double> convertedYValues = RiaWellLogUnitTools<double>::convertDepths( yValues, fromDepthUnit, toDepthUnit );
m_annotationTool->attachWellPicks( m_plotWidget->qwtPlot(), formationNamesToPlot, convertedYValues );
}
else
{
RimMainPlotCollection* mainPlotCollection = firstAncestorOrThisOfTypeAsserted<RimMainPlotCollection>();
RimWellLogPlotCollection* wellLogCollection = mainPlotCollection->wellLogPlotCollection();
CurveSamplingPointData curveData;
RigEclipseWellLogExtractor* eclWellLogExtractor = nullptr;
RigGeoMechWellLogExtractor* geoMechWellLogExtractor = nullptr;
if ( m_formationSettings->trajectoryType() == RiaDefines::WellLogTrackTrajectoryType::SIMULATION_WELL )
{
eclWellLogExtractor = RimWellLogTrack::createSimWellExtractor( wellLogCollection,
m_formationSettings->formationCase(),
m_formationSettings->simWellName(),
m_formationSettings->branchIndex(),
m_formationSettings->branchDetection() );
}
else
{
eclWellLogExtractor =
RiaExtractionTools::findOrCreateWellLogExtractor( m_formationSettings->wellPathForSourceCase(),
dynamic_cast<RimEclipseCase*>( m_formationSettings->formationCase() ) );
}
if ( eclWellLogExtractor )
{
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_formationSettings->formationCase() );
cvf::ref<RigResultAccessor> resultAccessor =
RigResultAccessorFactory::createFromResultAddress( eclipseCase->eclipseCaseData(),
0,
RiaDefines::PorosityModelType::MATRIX_MODEL,
0,
RigEclipseResultAddress( RiaDefines::ResultCatType::FORMATION_NAMES,
RiaResultNames::activeFormationNamesResultName() ) );
if ( resultAccessor.notNull() )
{
curveData = RimWellLogTrack::curveSamplingPointData( eclWellLogExtractor, resultAccessor.p() );
}
}
else
{
geoMechWellLogExtractor =
RiaExtractionTools::findOrCreateWellLogExtractor( m_formationSettings->wellPathForSourceCase(),
dynamic_cast<RimGeoMechCase*>( m_formationSettings->formationCase() ) );
if ( !geoMechWellLogExtractor ) return;
std::string activeFormationNamesResultName = RiaResultNames::activeFormationNamesResultName().toStdString();
curveData =
RimWellLogTrack::curveSamplingPointData( geoMechWellLogExtractor,
RigFemResultAddress( RIG_FORMATION_NAMES, activeFormationNamesResultName, "" ) );
}
if ( geoMechWellLogExtractor )
{
// Attach water and rock base formations
const caf::ColorTable waterAndRockColors = RiaColorTables::waterAndRockPaletteColors();
const std::vector<std::pair<double, double>> waterAndRockIntervals =
waterAndRockRegions( plot->depthType(), geoMechWellLogExtractor );
const std::vector<std::pair<double, double>> convertedYValues =
RiaWellLogUnitTools<double>::convertDepths( waterAndRockIntervals, fromDepthUnit, toDepthUnit );
m_annotationTool->attachNamedRegions( m_plotWidget->qwtPlot(),
{ "Sea Level", "" },
orientation,
convertedYValues,
m_regionAnnotationSettings->annotationDisplay(),
waterAndRockColors,
( ( 100 - m_regionAnnotationSettings->colorShadingTransparency() ) * 255 ) / 100,
m_regionAnnotationSettings->showRegionLabels(),
RiaDefines::TrackSpan::LEFT_COLUMN,
{ Qt::SolidPattern, Qt::Dense6Pattern } );
}
if ( m_formationSettings->formationSource() == RiaDefines::WellLogTrackFormationSource::CASE && m_plotWidget )
{
if ( ( m_formationSettings->simWellName() == QString( "None" ) && m_formationSettings->wellPathForSourceCase() == nullptr ) ||
m_formationSettings->formationCase() == nullptr )
return;
std::vector<QString> formationNamesVector = RimWellLogTrack::formationNamesVector( m_formationSettings->formationCase() );
if ( m_wellPathAttributeSettings->overburdenHeight() > 0.0 )
{
addOverburden( formationNamesVector, curveData, m_wellPathAttributeSettings->overburdenHeight() );
}
if ( m_wellPathAttributeSettings->underburdenHeight() > 0.0 )
{
addUnderburden( formationNamesVector, curveData, m_wellPathAttributeSettings->underburdenHeight() );
}
std::vector<std::pair<double, double>> yValues;
std::vector<QString> formationNamesToPlot;
RimWellLogTrack::findRegionNamesToPlot( curveData, formationNamesVector, plot->depthType(), &formationNamesToPlot, &yValues );
std::vector<std::pair<double, double>> convertedYValues =
RiaWellLogUnitTools<double>::convertDepths( yValues, fromDepthUnit, toDepthUnit );
// Build color table ordered by formation name to ensure correct color mapping
// when using a legend based on a LYR-file. Falls back to palette index for
// formations not found in the legend (e.g., when using a generic color palette).
// Related to https://github.com/OPM/ResInsight/issues/12974
RimColorLegend* legend = m_regionAnnotationSettings->colorShadingLegend();
if ( !legend ) legend = RimRegularLegendConfig::mapToColorLegend( RimRegularLegendConfig::ColorRangesType::NORMAL );
if ( legend && !formationNamesToPlot.empty() )
{
std::map<QString, cvf::Color3ub> nameToColor;
for ( auto* item : legend->colorLegendItems() )
{
nameToColor[item->categoryName()] = cvf::Color3ub( item->color() );
}
cvf::Color3ubArray paletteColors = legend->colorArray();
size_t colorCount = std::max( size_t( 2 ), formationNamesToPlot.size() );
cvf::Color3ubArray orderedColors( colorCount );
orderedColors.setAll( cvf::Color3ub::GRAY );
for ( size_t i = 0; i < formationNamesToPlot.size(); i++ )
{
auto it = nameToColor.find( formationNamesToPlot[i] );
if ( it != nameToColor.end() )
{
orderedColors.set( i, it->second );
}
else if ( paletteColors.size() > 0 )
{
orderedColors.set( i, paletteColors[i % paletteColors.size()] );
}
}
caf::ColorTable colorTable( orderedColors );
m_annotationTool->attachNamedRegions( m_plotWidget->qwtPlot(),
formationNamesToPlot,
orientation,
convertedYValues,
m_regionAnnotationSettings->annotationDisplay(),
colorTable,
( ( 100 - m_regionAnnotationSettings->colorShadingTransparency() ) * 255 ) / 100,
m_regionAnnotationSettings->showRegionLabels() );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateResultPropertyNamesOnPlot()
{
RimDepthTrackPlot* plot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
RiaDefines::DepthUnitType fromDepthUnit = plot->caseDepthUnit();
RiaDefines::DepthUnitType toDepthUnit = plot->depthUnit();
auto orientation = plot->depthOrientation();
RigEclipseWellLogExtractor* eclWellLogExtractor =
RiaExtractionTools::findOrCreateWellLogExtractor( m_formationSettings->wellPathForSourceCase(),
dynamic_cast<RimEclipseCase*>( m_formationSettings->formationCase() ) );
if ( !eclWellLogExtractor )
{
RiaLogging::error( "No well log extractor found for case." );
return;
}
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_formationSettings->formationCase() );
m_resultDefinition->loadResult();
size_t m_timeStep = 0;
cvf::ref<RigResultAccessor> resultAccessor =
RigResultAccessorFactory::createFromResultDefinition( eclipseCase->eclipseCaseData(), 0, m_timeStep, m_resultDefinition );
if ( !resultAccessor.notNull() )
{
QString resultTypeStr = caf::AppEnum<RiaDefines::ResultCatType>( m_resultDefinition->resultType() ).uiText();
RiaLogging::error( QString( "Unable to find result for region annotation for '%1' track. Tried '%2' (%3) on case: '%4'" )
.arg( m_description() )
.arg( m_resultDefinition->resultVariable() )
.arg( resultTypeStr )
.arg( eclipseCase->caseUserDescription() )
.toStdString() );
return;
}
CurveSamplingPointData curveData = RimWellLogTrack::curveSamplingPointData( eclWellLogExtractor, resultAccessor.p() );
// Attach water and rock base formations
if ( m_formationSettings->formationSource() == RiaDefines::WellLogTrackFormationSource::CASE )
{
if ( ( m_formationSettings->simWellName() == QString( "None" ) && m_formationSettings->wellPathForSourceCase() == nullptr ) ||
m_formationSettings->formationCase() == nullptr )
return;
std::vector<cvf::Color3ub> colors;
// Find the largest category number.
int maxCategoryValue = std::numeric_limits<int>::min();
for ( RimColorLegendItem* legendItem : m_regionAnnotationSettings->colorShadingLegend()->colorLegendItems() )
{
maxCategoryValue = std::max( maxCategoryValue, legendItem->categoryValue() );
}
// Insert each name at index matching the category number.
std::vector<QString> namesVector( maxCategoryValue + 1 );
for ( RimColorLegendItem* legendItem : m_regionAnnotationSettings->colorShadingLegend()->colorLegendItems() )
{
namesVector[legendItem->categoryValue()] = legendItem->categoryName();
}
if ( m_wellPathAttributeSettings->overburdenHeight() > 0.0 )
{
addOverburden( namesVector, curveData, m_wellPathAttributeSettings->overburdenHeight() );
}
if ( m_wellPathAttributeSettings->underburdenHeight() > 0.0 )
{
addUnderburden( namesVector, curveData, m_wellPathAttributeSettings->underburdenHeight() );
}
std::vector<QString> namesToPlot;
std::vector<std::pair<double, double>> yValues;
RimWellLogTrack::findRegionNamesToPlot( curveData, namesVector, plot->depthType(), &namesToPlot, &yValues );
// convert to plot depth unit
std::vector<std::pair<double, double>> convertedYValues =
RiaWellLogUnitTools<double>::convertDepths( yValues, fromDepthUnit, toDepthUnit );
// TODO: unnecessarily messy!
// Need to map colors to names (since a category can be used several times)
for ( QString nameToPlot : namesToPlot )
{
bool isFound = false;
for ( RimColorLegendItem* legendItem : m_regionAnnotationSettings->colorShadingLegend()->colorLegendItems() )
{
if ( legendItem->categoryName() == nameToPlot )
{
colors.push_back( cvf::Color3ub( legendItem->color() ) );
isFound = true;
}
}
if ( !isFound )
{
colors.push_back( cvf::Color3ub( RiaColorTables::undefinedCellColor() ) );
}
}
if ( colors.empty() )
{
RiaLogging::error( "No colors found." );
return;
}
caf::ColorTable colorTable( colors );
int fontSize = caf::FontTools::absolutePointSize( RiaPreferences::current()->defaultPlotFontSize(),
m_regionAnnotationSettings->regionLabelFontSize() );
m_annotationTool->attachNamedRegions( m_plotWidget->qwtPlot(),
namesToPlot,
orientation,
convertedYValues,
m_regionAnnotationSettings->annotationDisplay(),
colorTable,
( ( 100 - m_regionAnnotationSettings->colorShadingTransparency() ) * 255 ) / 100,
m_regionAnnotationSettings->showRegionLabels(),
RiaDefines::TrackSpan::FULL_WIDTH,
{},
fontSize );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateCurveDataRegionsOnPlot()
{
RimWellBoreStabilityPlot* wellBoreStabilityPlot = firstAncestorOrThisOfType<RimWellBoreStabilityPlot>();
if ( wellBoreStabilityPlot )
{
RiaDefines::DepthUnitType fromDepthUnit = wellBoreStabilityPlot->caseDepthUnit();
RiaDefines::DepthUnitType toDepthUnit = wellBoreStabilityPlot->depthUnit();
auto orientation = wellBoreStabilityPlot->depthOrientation();
wellBoreStabilityPlot->updateCommonDataSource();
RimGeoMechCase* geoMechCase = dynamic_cast<RimGeoMechCase*>( wellBoreStabilityPlot->commonDataSource()->caseToApply() );
RimWellPath* wellPath = wellBoreStabilityPlot->commonDataSource()->wellPathToApply();
int timeStep = wellBoreStabilityPlot->commonDataSource()->timeStepToApply();
if ( geoMechCase && wellPath && timeStep >= 0 )
{
auto [stepIdx, frameIdx] = geoMechCase->geoMechData()->femPartResults()->stepListIndexToTimeStepAndDataFrameIndex( timeStep );
RigGeoMechWellLogExtractor* geoMechWellLogExtractor = nullptr;
geoMechWellLogExtractor =
RiaExtractionTools::findOrCreateWellLogExtractor( wellPath, dynamic_cast<RimGeoMechCase*>( geoMechCase ) );
if ( !geoMechWellLogExtractor ) return;
CurveSamplingPointData curveData;
curveData.md = geoMechWellLogExtractor->cellIntersectionMDs();
curveData.tvd = geoMechWellLogExtractor->cellIntersectionTVDs();
RimWellLogExtractionCurve::findAndLoadWbsParametersFromFiles( wellPath, geoMechWellLogExtractor );
RimWellBoreStabilityPlot* wbsPlot = firstAncestorOrThisOfType<RimWellBoreStabilityPlot>();
if ( wbsPlot )
{
wbsPlot->applyWbsParametersToExtractor( geoMechWellLogExtractor );
}
std::vector<double> ppSourceRegions = geoMechWellLogExtractor->porePressureSourceRegions( stepIdx, frameIdx );
std::vector<double> poissonSourceRegions = geoMechWellLogExtractor->poissonSourceRegions( stepIdx, frameIdx );
std::vector<double> ucsSourceRegions = geoMechWellLogExtractor->ucsSourceRegions( stepIdx, frameIdx );
{
caf::ColorTable colorTable( m_regionAnnotationSettings->colorShadingLegend()->colorArray() );
std::vector<QString> sourceNames =
RigWbsParameter::PP_Reservoir().allSourceUiLabels( "\n", wbsPlot->userDefinedValue( RigWbsParameter::PP_NonReservoir() ) );
curveData.data = ppSourceRegions;
std::vector<QString> sourceNamesToPlot;
std::vector<std::pair<double, double>> yValues;
RimWellLogTrack::findRegionNamesToPlot( curveData, sourceNames, wellBoreStabilityPlot->depthType(), &sourceNamesToPlot, &yValues );
// convert to plot depth unit
std::vector<std::pair<double, double>> convertedYValues =
RiaWellLogUnitTools<double>::convertDepths( yValues, fromDepthUnit, toDepthUnit );
m_annotationTool->attachNamedRegions( m_plotWidget->qwtPlot(),
sourceNamesToPlot,
orientation,
convertedYValues,
m_regionAnnotationSettings->annotationDisplay(),
colorTable,
( ( ( 100 - m_regionAnnotationSettings->colorShadingTransparency() ) * 255 ) / 100 ) / 3,
m_regionAnnotationSettings->showRegionLabels(),
RiaDefines::TrackSpan::LEFT_COLUMN );
}
{
caf::ColorTable colorTable( m_regionAnnotationSettings->colorShadingLegend()->colorArray() );
std::vector<QString> sourceNames =
RigWbsParameter::poissonRatio().allSourceUiLabels( "\n", wbsPlot->userDefinedValue( RigWbsParameter::poissonRatio() ) );
curveData.data = poissonSourceRegions;
std::vector<QString> sourceNamesToPlot;
std::vector<std::pair<double, double>> yValues;
RimWellLogTrack::findRegionNamesToPlot( curveData, sourceNames, wellBoreStabilityPlot->depthType(), &sourceNamesToPlot, &yValues );
// convert to plot depth unit
std::vector<std::pair<double, double>> convertedYValues =
RiaWellLogUnitTools<double>::convertDepths( yValues, fromDepthUnit, toDepthUnit );
m_annotationTool->attachNamedRegions( m_plotWidget->qwtPlot(),
sourceNamesToPlot,
orientation,
convertedYValues,
m_regionAnnotationSettings->annotationDisplay(),
colorTable,
( ( ( 100 - m_regionAnnotationSettings->colorShadingTransparency() ) * 255 ) / 100 ) / 3,
m_regionAnnotationSettings->showRegionLabels(),
RiaDefines::TrackSpan::CENTRE_COLUMN );
}
{
caf::ColorTable colorTable( m_regionAnnotationSettings->colorShadingLegend()->colorArray() );
std::vector<QString> sourceNames =
RigWbsParameter::UCS().allSourceUiLabels( "\n", wbsPlot->userDefinedValue( RigWbsParameter::UCS() ) );
curveData.data = ucsSourceRegions;
std::vector<QString> sourceNamesToPlot;
std::vector<std::pair<double, double>> yValues;
RimWellLogTrack::findRegionNamesToPlot( curveData, sourceNames, wellBoreStabilityPlot->depthType(), &sourceNamesToPlot, &yValues );
// convert to plot depth unit
std::vector<std::pair<double, double>> convertedYValues =
RiaWellLogUnitTools<double>::convertDepths( yValues, fromDepthUnit, toDepthUnit );
m_annotationTool->attachNamedRegions( m_plotWidget->qwtPlot(),
sourceNamesToPlot,
orientation,
convertedYValues,
m_regionAnnotationSettings->annotationDisplay(),
colorTable,
( ( ( 100 - m_regionAnnotationSettings->colorShadingTransparency() ) * 255 ) / 100 ) / 3,
m_regionAnnotationSettings->showRegionLabels(),
RiaDefines::TrackSpan::RIGHT_COLUMN );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateWellPathAttributesOnPlot()
{
m_wellPathAttributePlotObjects.clear();
if ( wellPathAttributeSource() )
{
std::vector<const RimWellPathComponentInterface*> allWellPathComponents;
if ( wellPathAttributeSource()->wellPathGeometry() &&
( m_wellPathAttributeSettings->showWellPathAttributes() || m_wellPathAttributeSettings->showWellPathCompletions() ) )
{
m_wellPathAttributePlotObjects.push_back( std::make_unique<RiuWellPathComponentPlotItem>( wellPathAttributeSource() ) );
}
if ( m_wellPathAttributeSettings->showWellPathAttributes() )
{
if ( m_wellPathAttributeSettings->wellPathAttributeCollection() )
{
std::vector<RimWellPathAttribute*> attributes = m_wellPathAttributeSettings->wellPathAttributeCollection()->attributes();
for ( const RimWellPathAttribute* attribute : attributes )
{
if ( attribute->isEnabled() )
{
allWellPathComponents.push_back( attribute );
}
}
}
}
if ( m_wellPathAttributeSettings->showWellPathCompletions() )
{
const RimWellPathCompletions* completionsCollection = wellPathAttributeSource()->completions();
std::vector<const RimWellPathComponentInterface*> allCompletions = completionsCollection->allCompletions();
for ( const RimWellPathComponentInterface* completion : allCompletions )
{
if ( completion->isEnabled() )
{
allWellPathComponents.push_back( completion );
}
}
}
const std::map<RiaDefines::WellPathComponentType, int> sortIndices = { { RiaDefines::WellPathComponentType::WELL_PATH, 0 },
{ RiaDefines::WellPathComponentType::CASING, 1 },
{ RiaDefines::WellPathComponentType::LINER, 2 },
{ RiaDefines::WellPathComponentType::PERFORATION_INTERVAL, 3 },
{ RiaDefines::WellPathComponentType::FISHBONES, 4 },
{ RiaDefines::WellPathComponentType::FRACTURE, 5 },
{ RiaDefines::WellPathComponentType::PACKER, 6 },
{ RiaDefines::WellPathComponentType::ICD, 7 },
{ RiaDefines::WellPathComponentType::AICD, 8 },
{ RiaDefines::WellPathComponentType::ICV, 9 },
{ RiaDefines::WellPathComponentType::MSW_SEGMENT, 10 },
{ RiaDefines::WellPathComponentType::SICD, 11 },
{ RiaDefines::WellPathComponentType::UNDEFINED_COMPONENT, 12 } };
std::stable_sort( allWellPathComponents.begin(),
allWellPathComponents.end(),
[&sortIndices]( const RimWellPathComponentInterface* lhs, const RimWellPathComponentInterface* rhs )
{ return sortIndices.at( lhs->componentType() ) < sortIndices.at( rhs->componentType() ); } );
std::set<QString> completionsAssignedToLegend;
for ( const RimWellPathComponentInterface* component : allWellPathComponents )
{
if ( component->componentType() == RiaDefines::WellPathComponentType::UNDEFINED_COMPONENT )
{
continue;
}
std::unique_ptr<RiuWellPathComponentPlotItem> plotItem( new RiuWellPathComponentPlotItem( wellPathAttributeSource(), component ) );
QString legendTitle = plotItem->legendTitle();
bool contributeToLegend = m_wellPathAttributeSettings->showCompletionsInLegend() &&
!completionsAssignedToLegend.count( legendTitle );
plotItem->setContributeToLegend( contributeToLegend );
m_wellPathAttributePlotObjects.push_back( std::move( plotItem ) );
completionsAssignedToLegend.insert( legendTitle );
}
RimDepthTrackPlot* wellLogPlot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
RimWellLogPlot::DepthTypeEnum depthType = wellLogPlot->depthType();
auto depthOrientation = wellLogPlot->depthOrientation();
for ( auto& attributePlotObject : m_wellPathAttributePlotObjects )
{
attributePlotObject->setDepthType( depthType );
attributePlotObject->setDepthOrientation( depthOrientation );
attributePlotObject->setShowLabel( m_wellPathAttributeSettings->showComponentLabels() );
attributePlotObject->loadDataAndUpdate( false );
attributePlotObject->setParentPlotNoReplot( m_plotWidget->qwtPlot() );
}
}
updatePropertyValueZoom();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::removeRegionAnnotations()
{
if ( m_annotationTool )
{
m_annotationTool->detachAllAnnotations();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::doUpdateLayout()
{
updateFonts();
m_plotWidget->scheduleReplot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects )
{
setAutoScalePropertyValuesEnabled( true );
updatePlotWidgetFromAxisRanges();
RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow();
mainPlotWindow->updateWellLogPlotToolBar();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setOverburdenHeight( double overburdenHeight )
{
m_wellPathAttributeSettings->setOverburdenHeight( overburdenHeight );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setUnderburdenHeight( double underburdenHeight )
{
m_wellPathAttributeSettings->setUnderburdenHeight( underburdenHeight );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::addOverburden( std::vector<QString>& namesVector, CurveSamplingPointData& curveData, double height )
{
if ( !curveData.data.empty() )
{
namesVector.push_back( "Overburden" );
// Prepend the new "fake" depth for start of overburden
double tvdTop = curveData.tvd[0];
curveData.tvd.insert( curveData.tvd.begin(), tvdTop );
curveData.tvd.insert( curveData.tvd.begin(), tvdTop - height );
// TODO: this is not always correct
double mdTop = curveData.md[0];
curveData.md.insert( curveData.md.begin(), mdTop );
curveData.md.insert( curveData.md.begin(), mdTop - height );
curveData.data.insert( curveData.data.begin(), namesVector.size() - 1 );
curveData.data.insert( curveData.data.begin(), namesVector.size() - 1 );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::addUnderburden( std::vector<QString>& namesVector, CurveSamplingPointData& curveData, double height )
{
if ( !curveData.data.empty() )
{
namesVector.push_back( "Underburden" );
size_t lastIndex = curveData.tvd.size() - 1;
// Append the new "fake" depth for start of underburden
double tvdBottom = curveData.tvd[lastIndex];
curveData.tvd.push_back( tvdBottom );
curveData.tvd.push_back( tvdBottom + height );
// TODO: this is not always correct
double mdBottom = curveData.md[lastIndex];
curveData.md.push_back( mdBottom );
curveData.md.push_back( mdBottom + height );
curveData.data.push_back( namesVector.size() - 1 );
curveData.data.push_back( namesVector.size() - 1 );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setCurvesTreeVisibility( bool isVisible )
{
m_curves.uiCapability()->setUiTreeChildrenHidden( !isVisible );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setEnsembleWellLogCurveSet( RimEnsembleWellLogCurveSet* curveSet )
{
m_ensembleWellLogCurveSet = curveSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuPlotAxis RimWellLogTrack::depthAxis() const
{
RimDepthTrackPlot* wellLogPlot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
return wellLogPlot->depthAxis();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuPlotAxis RimWellLogTrack::valueAxis() const
{
RimDepthTrackPlot* wellLogPlot = firstAncestorOrThisOfTypeAsserted<RimDepthTrackPlot>();
return wellLogPlot->valueAxis();
}