ResInsight/ApplicationLibCode/ProjectDataModel/WellLog/RimWellLogTrack.cpp
Magne Sjaastad c248c9fb57
RFT segment plot adjustments (#9912)
* Delete RFT plot when associated case is deleted
* Rename
* Hide track/curves with no data
2023-03-06 14:34:22 +01:00

3514 lines
141 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 "RiaSimWellBranchTools.h"
#include "RiaWellLogCurveMerger.h"
#include "RigEclipseCaseData.h"
#include "RigEclipseResultAddress.h"
#include "RigEclipseWellLogExtractor.h"
#include "RigFemPartResultsCollection.h"
#include "RigFemResultAddress.h"
#include "RigFormationNames.h"
#include "RigGeoMechCaseData.h"
#include "RigGeoMechWellLogExtractor.h"
#include "RigResultAccessorFactory.h"
#include "RigSimWellData.h"
#include "RigSimulationWellCenterLineCalculator.h"
#include "RigSimulationWellCoordsAndMD.h"
#include "RigStatisticsCalculator.h"
#include "RigWellLogCurveData.h"
#include "RigWellPath.h"
#include "RigWellPathFormations.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 "RimWellLogPlotCollection.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 "cvfAssert.h"
#include "qwt_scale_map.h"
#include <QWheelEvent>
#include <algorithm>
#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 caf
{
template <>
void AppEnum<RimWellLogTrack::TrajectoryType>::setUp()
{
addItem( RimWellLogTrack::WELL_PATH, "WELL_PATH", "Well Path" );
addItem( RimWellLogTrack::SIMULATION_WELL, "SIMULATION_WELL", "Simulation Well" );
setDefault( RimWellLogTrack::WELL_PATH );
}
template <>
void AppEnum<RimWellLogTrack::FormationSource>::setUp()
{
addItem( RimWellLogTrack::FormationSource::CASE, "CASE", "Case" );
addItem( RimWellLogTrack::FormationSource::WELL_PICK_FILTER, "WELL_PICK_FILTER", "Well Picks for Well Path" );
setDefault( RimWellLogTrack::FormationSource::CASE );
}
template <>
void AppEnum<RigWellPathFormations::FormationLevel>::setUp()
{
addItem( RigWellPathFormations::NONE, "NONE", "None" );
addItem( RigWellPathFormations::ALL, "ALL", "All" );
addItem( RigWellPathFormations::GROUP, "GROUP", "Formation Group" );
addItem( RigWellPathFormations::LEVEL0, "LEVEL0", "Formation" );
addItem( RigWellPathFormations::LEVEL1, "LEVEL1", "Formation 1" );
addItem( RigWellPathFormations::LEVEL2, "LEVEL2", "Formation 2" );
addItem( RigWellPathFormations::LEVEL3, "LEVEL3", "Formation 3" );
addItem( RigWellPathFormations::LEVEL4, "LEVEL4", "Formation 4" );
addItem( RigWellPathFormations::LEVEL5, "LEVEL5", "Formation 5" );
addItem( RigWellPathFormations::LEVEL6, "LEVEL6", "Formation 6" );
addItem( RigWellPathFormations::LEVEL7, "LEVEL7", "Formation 7" );
addItem( RigWellPathFormations::LEVEL8, "LEVEL8", "Formation 8" );
addItem( RigWellPathFormations::LEVEL9, "LEVEL9", "Formation 9" );
addItem( RigWellPathFormations::LEVEL10, "LEVEL10", "Formation 10" );
setDefault( RigWellPathFormations::ALL );
}
template <>
void AppEnum<RiaDefines::RegionAnnotationType>::setUp()
{
addItem( RiaDefines::RegionAnnotationType::NO_ANNOTATIONS, "NO_ANNOTATIONS", "No Annotations" );
addItem( RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS, "FORMATIONS", "Formations" );
addItem( RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS, "RESULT_PROPERTY", "Result Property" );
setDefault( RiaDefines::RegionAnnotationType::NO_ANNOTATIONS );
}
template <>
void AppEnum<RiaDefines::RegionDisplay>::setUp()
{
addItem( RiaDefines::DARK_LINES, "DARK_LINES", "Dark Lines" );
addItem( RiaDefines::LIGHT_LINES, "LIGHT_LINES", "Light Lines" );
addItem( RiaDefines::COLORED_LINES, "COLORED_LINES", "Colored Lines" );
addItem( RiaDefines::COLOR_SHADING, "COLOR_SHADING", "Color Shading" );
addItem( RiaDefines::COLOR_SHADING_AND_LINES, "SHADING_AND_LINES", "Color Shading and Lines" );
setDefault( RiaDefines::COLOR_SHADING_AND_LINES );
}
} // namespace caf
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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", "" );
m_curves.uiCapability()->setUiTreeHidden( true );
auto reorderability = caf::PdmFieldReorderCapability::addToField( &m_curves );
reorderability->orderChanged.connect( this, &RimWellLogTrack::curveDataChanged );
CAF_PDM_InitField( &m_visiblePropertyValueRangeMin, "VisibleXRangeMin", RI_LOGPLOTTRACK_MINX_DEFAULT, "Min" );
m_visiblePropertyValueRangeMin.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_visiblePropertyValueRangeMax, "VisibleXRangeMax", RI_LOGPLOTTRACK_MAXX_DEFAULT, "Max" );
m_visiblePropertyValueRangeMax.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleValueEditor::uiEditorTypeName() );
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, "AutoScaleX", true, "Auto Scale" );
m_isAutoScalePropertyValuesEnabled.uiCapability()->setUiHidden( true );
CAF_PDM_InitField( &m_isPropertyLogarithmicScaleEnabled, "LogarithmicScaleX", false, "Logarithmic Scale" );
CAF_PDM_InitField( &m_invertPropertyValueAxis, "InvertPropertyValueAxis", false, "Invert Axis Range" );
CAF_PDM_InitField( &m_isPropertyAxisEnabled, "IsPropertyAxisEnabled", true, "Show Axis" );
CAF_PDM_InitFieldNoDefault( &m_propertyValueAxisGridVisibility, "ShowXGridLines", "Show Grid Lines" );
CAF_PDM_InitField( &m_explicitTickIntervalsPropertyValueAxis, "ExplicitTickIntervals", false, "Manually Set Tick Intervals" );
CAF_PDM_InitField( &m_propertyAxisMinAndMaxTicksOnly, "MinAndMaxTicksOnly", false, "Show Ticks at Min and Max" );
CAF_PDM_InitField( &m_majorTickIntervalPropertyAxis, "MajorTickIntervals", 0.0, "Major Tick Interval" );
CAF_PDM_InitField( &m_minorTickIntervalPropertyAxis, "MinorTickIntervals", 0.0, "Minor Tick Interval" );
m_majorTickIntervalPropertyAxis.uiCapability()->setUiHidden( true );
m_minorTickIntervalPropertyAxis.uiCapability()->setUiHidden( true );
CAF_PDM_InitFieldNoDefault( &m_axisFontSize, "AxisFontSize", "Axis Font Size" );
CAF_PDM_InitFieldNoDefault( &m_regionAnnotationType, "AnnotationType", "Region Annotations" );
CAF_PDM_InitFieldNoDefault( &m_regionAnnotationDisplay, "RegionDisplay", "Region Display" );
CAF_PDM_InitFieldNoDefault( &m_colorShadingLegend, "ColorShadingLegend", "Colors" );
m_colorShadingLegend = RimRegularLegendConfig::mapToColorLegend( RimRegularLegendConfig::ColorRangesType::NORMAL );
CAF_PDM_InitField( &m_colorShadingTransparency, "ColorShadingTransparency", 50, "Color Transparency" );
m_colorShadingTransparency.uiCapability()->setUiEditorTypeName( caf::PdmUiSliderEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_showRegionLabels, "ShowFormationLabels", true, "Show Labels" );
caf::FontTools::RelativeSizeEnum regionLabelFontSizeDefault = caf::FontTools::RelativeSize::XSmall;
CAF_PDM_InitField( &m_regionLabelFontSize, "RegionLabelFontSize", regionLabelFontSizeDefault, "Font Size" );
CAF_PDM_InitFieldNoDefault( &m_formationSource, "FormationSource", "Source" );
CAF_PDM_InitFieldNoDefault( &m_formationTrajectoryType, "FormationTrajectoryType", "Trajectory" );
CAF_PDM_InitFieldNoDefault( &m_formationWellPathForSourceCase, "FormationWellPath", "Well Path" );
m_formationWellPathForSourceCase.uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitFieldNoDefault( &m_formationWellPathForSourceWellPath, "FormationWellPathForSourceWellPath", "Well Path" );
m_formationWellPathForSourceWellPath.uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitField( &m_formationSimWellName, "FormationSimulationWellName", QString( "None" ), "Simulation Well" );
CAF_PDM_InitField( &m_formationBranchIndex, "FormationBranchIndex", 0, " " );
CAF_PDM_InitField( &m_formationBranchDetection,
"FormationBranchDetection",
true,
"Branch Detection",
"",
"Compute branches based on how simulation well cells are organized",
"" );
CAF_PDM_InitFieldNoDefault( &m_formationCase, "FormationCase", "Formation Case" );
m_formationCase.uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitFieldNoDefault( &m_formationLevel, "FormationLevel", "Well Pick Filter" );
CAF_PDM_InitField( &m_showformationFluids, "ShowFormationFluids", false, "Show Fluids" );
CAF_PDM_InitField( &m_showWellPathAttributes, "ShowWellPathAttributes", false, "Show Well Attributes" );
CAF_PDM_InitField( &m_wellPathAttributesInLegend, "WellPathAttributesInLegend", true, "Attributes in Legend" );
CAF_PDM_InitField( &m_showWellPathCompletions, "ShowWellPathCompletions", true, "Show Well Completions" );
CAF_PDM_InitField( &m_wellPathCompletionsInLegend, "WellPathCompletionsInLegend", true, "Completions in Legend" );
CAF_PDM_InitField( &m_showWellPathComponentsBothSides, "ShowWellPathAttrBothSides", true, "Show Both Sides" );
CAF_PDM_InitField( &m_showWellPathComponentLabels, "ShowWellPathAttrLabels", false, "Show Labels" );
CAF_PDM_InitFieldNoDefault( &m_wellPathComponentSource, "AttributesWellPathSource", "Well Path" );
CAF_PDM_InitFieldNoDefault( &m_wellPathAttributeCollection, "AttributesCollection", "Well Attributes" );
CAF_PDM_InitField( &m_autoCheckStateBasedOnCurveData, "AutoCheckStateBasedOnCurveData", false, "Hide Track if No Curve Data" );
CAF_PDM_InitField( &m_overburdenHeight, "OverburdenHeight", 0.0, "Overburden Height" );
m_overburdenHeight.uiCapability()->setUiHidden( true );
CAF_PDM_InitField( &m_underburdenHeight, "UnderburdenHeight", 0.0, "Underburden Height" );
m_underburdenHeight.uiCapability()->setUiHidden( true );
CAF_PDM_InitFieldNoDefault( &m_resultDefinition, "ResultDefinition", "Result Definition" );
m_resultDefinition.uiCapability()->setUiTreeHidden( true );
m_resultDefinition.uiCapability()->setUiTreeChildrenHidden( true );
m_resultDefinition = new RimEclipseResultDefinition;
CAF_PDM_InitFieldNoDefault( &m_ensembleWellLogCurveSet, "EnsembleWellLogCurveSet", "Ensemble Well Logs Curve Set" );
m_ensembleWellLogCurveSet.uiCapability()->setUiTreeHidden( true );
m_formationsForCaseWithSimWellOnly = false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogTrack::~RimWellLogTrack()
{
m_curves.deleteChildren();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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 )
{
CVF_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();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::calculatePropertyValueZoomRange()
{
updateStackedCurveData();
double minValue = HUGE_VAL;
double maxValue = -HUGE_VAL;
size_t topologyCurveCount = 0;
size_t visibleCurves = 0u;
for ( const auto& curve : m_curves )
{
double minCurveValue = HUGE_VAL;
double maxCurveValue = -HUGE_VAL;
if ( curve->isChecked() )
{
visibleCurves++;
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_minorTickIntervalPropertyAxis() != 0.0 )
{
std::tie( minValue, maxValue ) = adjustXRange( minValue, maxValue, m_minorTickIntervalPropertyAxis() );
}
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_showWellPathAttributes || m_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_isAutoScalePropertyValuesEnabled )
{
m_visiblePropertyValueRangeMin = m_availablePropertyValueRangeMin;
m_visiblePropertyValueRangeMax = m_availablePropertyValueRangeMax;
if ( !visibleStackedCurves().empty() && !m_isPropertyLogarithmicScaleEnabled )
{
// Try to ensure we include the base line whether the values are negative or positive.
m_visiblePropertyValueRangeMin = std::min( m_visiblePropertyValueRangeMin(), 0.0 );
m_visiblePropertyValueRangeMax = std::max( m_visiblePropertyValueRangeMax(), 0.0 );
}
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_showWellPathComponentsBothSides )
{
componentRangeMin = -1.5;
componentRangeMax *= 2.0;
}
if ( m_showWellPathComponentLabels )
{
componentRangeMax *= 1.5;
}
RimDepthTrackPlot* wellLogPlot;
this->firstAncestorOrThisOfTypeAsserted( wellLogPlot );
// 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;
this->firstAncestorOrThisOfTypeAsserted( wellLogPlot );
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;
this->firstAncestorOrThisOfTypeAsserted( depthTrackPlot );
depthTrackPlot->updateDepthAxisVisibility();
}
else if ( changedField == &m_description )
{
updateParentLayout();
}
else if ( changedField == &m_explicitTickIntervalsPropertyValueAxis )
{
if ( m_plotWidget )
{
m_majorTickIntervalPropertyAxis = m_plotWidget->majorTickInterval( valueAxis() );
m_minorTickIntervalPropertyAxis = m_plotWidget->minorTickInterval( valueAxis() );
}
m_majorTickIntervalPropertyAxis.uiCapability()->setUiHidden( !m_explicitTickIntervalsPropertyValueAxis() );
m_minorTickIntervalPropertyAxis.uiCapability()->setUiHidden( !m_explicitTickIntervalsPropertyValueAxis() );
if ( !m_explicitTickIntervalsPropertyValueAxis() )
{
updatePropertyValueAxisAndGridTickIntervals();
}
}
else if ( changedField == &m_isPropertyAxisEnabled )
{
updatePropertyValueAxisAndGridTickIntervals();
updateParentLayout();
}
else if ( changedField == &m_propertyValueAxisGridVisibility || changedField == &m_majorTickIntervalPropertyAxis ||
changedField == &m_minorTickIntervalPropertyAxis || changedField == &m_propertyAxisMinAndMaxTicksOnly ||
changedField == &m_invertPropertyValueAxis )
{
updatePropertyValueAxisAndGridTickIntervals();
}
else if ( changedField == &m_visiblePropertyValueRangeMin || changedField == &m_visiblePropertyValueRangeMax )
{
bool emptyRange = isEmptyVisiblePropertyRange();
m_explicitTickIntervalsPropertyValueAxis.uiCapability()->setUiReadOnly( emptyRange );
m_propertyValueAxisGridVisibility.uiCapability()->setUiReadOnly( emptyRange );
m_isAutoScalePropertyValuesEnabled = false;
updatePropertyValueZoom();
m_plotWidget->scheduleReplot();
updateEditors();
}
else if ( changedField == &m_isAutoScalePropertyValuesEnabled )
{
if ( m_isAutoScalePropertyValuesEnabled() )
{
updatePropertyValueZoom();
m_plotWidget->scheduleReplot();
}
}
else if ( changedField == &m_isPropertyLogarithmicScaleEnabled )
{
updateAxisScaleEngine();
if ( m_isPropertyLogarithmicScaleEnabled() )
{
m_explicitTickIntervalsPropertyValueAxis = false;
}
m_explicitTickIntervalsPropertyValueAxis.uiCapability()->setUiHidden( m_isPropertyLogarithmicScaleEnabled() );
updatePropertyValueZoom();
loadDataAndUpdate();
}
else if ( changedField == &m_regionAnnotationType || changedField == &m_regionAnnotationDisplay || changedField == &m_formationSource ||
changedField == &m_colorShadingTransparency || changedField == &m_colorShadingLegend )
{
if ( changedField == &m_formationSource && m_formationSource == FormationSource::WELL_PICK_FILTER )
{
std::vector<RimWellPath*> wellPaths;
RimTools::wellPathWithFormations( &wellPaths );
for ( RimWellPath* wellPath : wellPaths )
{
if ( wellPath == m_formationWellPathForSourceCase )
{
m_formationWellPathForSourceWellPath = m_formationWellPathForSourceCase();
break;
}
}
}
loadDataAndUpdate();
updateParentLayout();
updateConnectedEditors();
RiuPlotMainWindowTools::refreshToolbars();
}
else if ( changedField == &m_showRegionLabels || changedField == &m_regionLabelFontSize )
{
loadDataAndUpdate();
}
else if ( changedField == &m_formationCase )
{
QList<caf::PdmOptionItemInfo> options;
RimWellLogTrack::simWellOptionItems( &options, m_formationCase );
if ( options.isEmpty() || m_formationCase == nullptr )
{
m_formationSimWellName = QString( "None" );
}
loadDataAndUpdate();
updateParentLayout();
RiuPlotMainWindowTools::refreshToolbars();
}
else if ( changedField == &m_formationWellPathForSourceCase )
{
loadDataAndUpdate();
updateParentLayout();
RiuPlotMainWindowTools::refreshToolbars();
}
else if ( changedField == &m_formationSimWellName )
{
loadDataAndUpdate();
updateParentLayout();
RiuPlotMainWindowTools::refreshToolbars();
}
else if ( changedField == &m_formationTrajectoryType )
{
if ( m_formationTrajectoryType == WELL_PATH )
{
RimProject* proj = RimProject::current();
m_formationWellPathForSourceCase = proj->wellPathFromSimWellName( m_formationSimWellName );
}
else
{
if ( m_formationWellPathForSourceCase )
{
m_formationSimWellName = m_formationWellPathForSourceCase->associatedSimulationWellName();
}
}
loadDataAndUpdate();
updateParentLayout();
RiuPlotMainWindowTools::refreshToolbars();
}
else if ( changedField == &m_formationBranchIndex || changedField == &m_formationBranchDetection )
{
m_formationBranchIndex =
RiaSimWellBranchTools::clampBranchIndex( m_formationSimWellName, m_formationBranchIndex, m_formationBranchDetection );
loadDataAndUpdate();
updateParentLayout();
RiuPlotMainWindowTools::refreshToolbars();
}
else if ( changedField == &m_formationWellPathForSourceWellPath )
{
loadDataAndUpdate();
updateParentLayout();
RiuPlotMainWindowTools::refreshToolbars();
}
else if ( changedField == &m_formationLevel )
{
loadDataAndUpdate();
}
else if ( changedField == &m_showformationFluids )
{
loadDataAndUpdate();
}
else if ( changedField == &m_showWellPathAttributes || changedField == &m_showWellPathCompletions ||
changedField == &m_showWellPathComponentsBothSides || changedField == &m_showWellPathComponentLabels ||
changedField == &m_wellPathAttributesInLegend || changedField == &m_wellPathCompletionsInLegend )
{
updateWellPathAttributesOnPlot();
updateParentLayout();
RiuPlotMainWindowTools::refreshToolbars();
}
else if ( changedField == &m_wellPathComponentSource )
{
updateWellPathAttributesCollection();
updateWellPathAttributesOnPlot();
updateParentLayout();
RiuPlotMainWindowTools::refreshToolbars();
}
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_isAutoScalePropertyValuesEnabled = 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_visiblePropertyValueRangeMin();
auto rangeBoundaryB = m_visiblePropertyValueRangeMax();
if ( m_invertPropertyValueAxis() ) std::swap( rangeBoundaryA, rangeBoundaryB );
if ( m_propertyAxisMinAndMaxTicksOnly )
{
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;
this->firstAncestorOrThisOfTypeAsserted( wellLogPlot );
if ( wellLogPlot->depthOrientation() == RiaDefines::Orientation::VERTICAL )
{
m_plotWidget->qwtPlot()->setAxisScaleDiv( QwtAxis::XTop, div );
}
else
{
m_plotWidget->qwtPlot()->setAxisScaleDiv( QwtAxis::YLeft, div );
}
}
else if ( m_explicitTickIntervalsPropertyValueAxis )
{
m_plotWidget->setMajorAndMinorTickIntervals( valueAxis(),
m_majorTickIntervalPropertyAxis(),
m_minorTickIntervalPropertyAxis(),
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_propertyValueAxisGridVisibility() & RimWellLogPlot::AXIS_GRID_MAJOR,
m_propertyValueAxisGridVisibility() & RimWellLogPlot::AXIS_GRID_MINOR );
}
RimDepthTrackPlot* wellLogPlot = nullptr;
this->firstAncestorOrThisOfType( wellLogPlot );
if ( wellLogPlot )
{
m_plotWidget->enableGridLines( depthAxis(),
wellLogPlot->depthAxisGridLinesEnabled() & RimWellLogPlot::AXIS_GRID_MAJOR,
wellLogPlot->depthAxisGridLinesEnabled() & RimWellLogPlot::AXIS_GRID_MINOR );
}
m_plotWidget->enableAxisNumberLabels( valueAxis(), m_isPropertyAxisEnabled() );
m_plotWidget->scheduleReplot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateLegend()
{
reattachAllCurves();
if ( m_plotWidget )
{
m_plotWidget->updateLegend();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogTrack::asciiDataForPlotExport() const
{
QString out = "\n" + this->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;
{
RimWellAllocationPlot* wapl = nullptr;
parentWellLogPlot()->firstAncestorOfType( wapl );
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();
if ( !curveData ) continue;
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::DepthTypeEnum::CONNECTION_NUMBER )
{
out += "Connection";
}
else if ( depthType == RiaDefines::DepthTypeEnum::MEASURED_DEPTH )
{
out += "MD ";
}
else if ( depthType == RiaDefines::DepthTypeEnum::PSEUDO_LENGTH )
{
out += "PL ";
}
else if ( depthType == RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH )
{
out += "TVDMSL ";
}
else if ( depthType == RiaDefines::DepthTypeEnum::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::DepthTypeEnum::CONNECTION_NUMBER )
{
if ( dIdx == 0 )
continue; // Skip the first line. (shallow depth, which is last)
// as it is a fictious 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( " %1" ).arg( QString::number( plotVector[i], 'f', 3 ), 12 );
}
out += "\n";
}
return out;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateZoomFromParentPlot()
{
auto [xIntervalMin, xIntervalMax] = m_plotWidget->axisRange( valueAxis() );
auto [depthIntervalMin, depthIntervalMax] = m_plotWidget->axisRange( depthAxis() );
m_visiblePropertyValueRangeMin = xIntervalMin;
m_visiblePropertyValueRangeMax = 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;
if ( fieldNeedingOptions == &m_formationWellPathForSourceCase )
{
RimTools::wellPathOptionItems( &options );
}
else if ( fieldNeedingOptions == &m_formationWellPathForSourceWellPath )
{
RimTools::wellPathWithFormationsOptionItems( &options );
}
else if ( fieldNeedingOptions == &m_formationCase )
{
RimTools::caseOptionItems( &options );
}
else if ( fieldNeedingOptions == &m_formationSimWellName )
{
RimWellLogTrack::simWellOptionItems( &options, m_formationCase );
}
else if ( fieldNeedingOptions == &m_formationBranchIndex )
{
auto simulationWellBranches = RiaSimWellBranchTools::simulationWellBranches( m_formationSimWellName(), m_formationBranchDetection );
options = RiaSimWellBranchTools::valueOptionsForBranchIndexField( simulationWellBranches );
}
else if ( fieldNeedingOptions == &m_formationLevel )
{
if ( m_formationWellPathForSourceWellPath )
{
const RigWellPathFormations* formations = m_formationWellPathForSourceWellPath->formationsGeometry();
if ( formations )
{
using FormationLevelEnum = caf::AppEnum<RigWellPathFormations::FormationLevel>;
options.push_back(
caf::PdmOptionItemInfo( FormationLevelEnum::uiText( RigWellPathFormations::NONE ), RigWellPathFormations::NONE ) );
options.push_back(
caf::PdmOptionItemInfo( FormationLevelEnum::uiText( RigWellPathFormations::ALL ), RigWellPathFormations::ALL ) );
for ( const RigWellPathFormations::FormationLevel& level : formations->formationsLevelsPresent() )
{
size_t index = FormationLevelEnum::index( level );
if ( index >= FormationLevelEnum::size() ) continue;
options.push_back(
caf::PdmOptionItemInfo( FormationLevelEnum::uiTextFromIndex( index ), FormationLevelEnum::fromIndex( index ) ) );
}
}
}
}
else if ( fieldNeedingOptions == &m_wellPathComponentSource )
{
RimTools::wellPathOptionItems( &options );
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
}
else if ( fieldNeedingOptions == &m_colorShadingLegend )
{
RimTools::colorLegendOptionItems( &options );
}
else 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_visiblePropertyValueRangeMin;
*maxX = m_visiblePropertyValueRangeMax;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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_visiblePropertyValueRangeMax() - m_visiblePropertyValueRangeMin ) <
1.0e-6 * std::max( 1.0, std::max( m_visiblePropertyValueRangeMax(), m_visiblePropertyValueRangeMin() ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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;
this->firstAncestorOrThisOfTypeAsserted( wellLogPlot );
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 )
{
loadDataAndUpdate();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateDepthMarkerLine()
{
if ( m_plotWidget )
{
RimDepthTrackPlot* wellLogPlot;
this->firstAncestorOrThisOfTypeAsserted( wellLogPlot );
if ( wellLogPlot->isDepthMarkerLineEnabled() )
{
m_plotWidget->createAnnotationsInPlot( wellLogPlot->depthAxisAnnotations() );
}
else
{
m_plotWidget->createAnnotationsInPlot( {} );
}
m_plotWidget->scheduleReplot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::onLoadDataAndUpdate()
{
RimDepthTrackPlot* wellLogPlot = nullptr;
firstAncestorOrThisOfType( wellLogPlot );
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_regionAnnotationType == RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS ||
m_regionAnnotationType == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
{
m_resultDefinition->loadDataAndUpdate();
setFormationFieldsUiReadOnly( false );
}
else
{
setFormationFieldsUiReadOnly( true );
}
bool noAnnotations = m_regionAnnotationType() == RiaDefines::RegionAnnotationType::NO_ANNOTATIONS;
m_regionAnnotationDisplay.uiCapability()->setUiReadOnly( noAnnotations );
m_showRegionLabels.uiCapability()->setUiReadOnly( noAnnotations );
if ( m_plotWidget )
{
this->updateWellPathAttributesCollection();
this->updateWellPathAttributesOnPlot();
m_plotWidget->updateLegend();
this->updateAxisScaleEngine();
this->updateRegionAnnotationsOnPlot();
this->updatePropertyValueZoom();
}
this->updatePropertyValueAxisAndGridTickIntervals();
m_majorTickIntervalPropertyAxis.uiCapability()->setUiHidden( !m_explicitTickIntervalsPropertyValueAxis() );
m_minorTickIntervalPropertyAxis.uiCapability()->setUiHidden( !m_explicitTickIntervalsPropertyValueAxis() );
bool emptyRange = isEmptyVisiblePropertyRange();
m_explicitTickIntervalsPropertyValueAxis.uiCapability()->setUiReadOnly( emptyRange );
m_propertyValueAxisGridVisibility.uiCapability()->setUiReadOnly( emptyRange );
updateDepthZoom();
updateLegend();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAndUpdateWellPathFormationNamesData( RimCase* rimCase, RimWellPath* wellPath )
{
m_formationCase = rimCase;
m_formationTrajectoryType = RimWellLogTrack::WELL_PATH;
m_formationWellPathForSourceCase = wellPath;
m_formationSimWellName = "";
m_formationBranchIndex = -1;
updateConnectedEditors();
if ( m_regionAnnotationType != RiaDefines::RegionAnnotationType::NO_ANNOTATIONS )
{
updateRegionAnnotationsOnPlot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAndUpdateSimWellFormationNamesAndBranchData( RimCase* rimCase,
const QString& simWellName,
int branchIndex,
bool useBranchDetection )
{
m_formationBranchIndex = branchIndex;
m_formationBranchDetection = useBranchDetection;
setAndUpdateSimWellFormationNamesData( rimCase, simWellName );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAndUpdateSimWellFormationNamesData( RimCase* rimCase, const QString& simWellName )
{
m_formationCase = rimCase;
m_formationTrajectoryType = RimWellLogTrack::SIMULATION_WELL;
m_formationWellPathForSourceCase = nullptr;
m_formationSimWellName = simWellName;
updateConnectedEditors();
if ( m_regionAnnotationType != 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_isAutoScalePropertyValuesEnabled = 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_isAutoScalePropertyValuesEnabled && emptyRange ) return;
const double eps = 1.0e-8;
calculatePropertyValueZoomRange();
double maxRange = std::max( m_visiblePropertyValueRangeMax - m_visiblePropertyValueRangeMin,
m_availablePropertyValueRangeMax - m_availablePropertyValueRangeMin );
double maxLow = std::max( m_visiblePropertyValueRangeMin(), m_availablePropertyValueRangeMin );
double minHigh = std::min( m_visiblePropertyValueRangeMax(), 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;
this->firstAncestorOrThisOfType( parent );
if ( parent )
{
return parent->depthAxisTitle();
}
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationWellPath( RimWellPath* wellPath )
{
m_formationWellPathForSourceCase = wellPath;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RimWellLogTrack::formationWellPath() const
{
return m_formationWellPathForSourceCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationSimWellName( const QString& simWellName )
{
m_formationSimWellName = simWellName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogTrack::formationSimWellName() const
{
return m_formationSimWellName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationBranchDetection( bool branchDetection )
{
m_formationBranchDetection = branchDetection;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogTrack::formationBranchDetection() const
{
return m_formationBranchDetection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationBranchIndex( int branchIndex )
{
m_formationBranchIndex = branchIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimWellLogTrack::formationBranchIndex() const
{
return m_formationBranchIndex;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationCase( RimCase* rimCase )
{
m_formationCase = 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::formationNamesCase() const
{
return m_formationCase();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setFormationTrajectoryType( TrajectoryType trajectoryType )
{
m_formationTrajectoryType = trajectoryType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogTrack::TrajectoryType RimWellLogTrack::formationTrajectoryType() const
{
return m_formationTrajectoryType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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( wellLogPlot );
if ( wellLogPlot )
{
wellLogPlot->updateZoom();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateEditors()
{
this->updateConnectedEditors();
RimPlotWindow* plotWindow = nullptr;
firstAncestorOrThisOfTypeAsserted( plotWindow );
plotWindow->updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setVisiblePropertyValueRange( double minValue, double maxValue )
{
this->setAutoScalePropertyValuesEnabled( false );
m_visiblePropertyValueRangeMin = minValue;
m_visiblePropertyValueRangeMax = maxValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setVisibleDepthRange( double minValue, double maxValue )
{
m_visibleDepthRangeMin = minValue;
m_visibleDepthRangeMax = maxValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateZoomInParentPlot()
{
updatePropertyValueZoom();
updateDepthZoom();
m_plotWidget->scheduleReplot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setTickIntervals( double majorTickInterval, double minorTickInterval )
{
m_explicitTickIntervalsPropertyValueAxis = true;
m_majorTickIntervalPropertyAxis = majorTickInterval;
m_minorTickIntervalPropertyAxis = minorTickInterval;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setMinAndMaxTicksOnly( bool enable )
{
m_propertyAxisMinAndMaxTicksOnly = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setPropertyValueAxisGridVisibility( RimWellLogPlot::AxisGridVisibility gridLines )
{
m_propertyValueAxisGridVisibility = gridLines;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setColorShadingLegend( RimColorLegend* colorLegend )
{
m_colorShadingLegend = colorLegend;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAnnotationType( RiaDefines::RegionAnnotationType annotationType )
{
m_regionAnnotationType = annotationType;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAnnotationDisplay( RiaDefines::RegionDisplay annotationDisplay )
{
m_regionAnnotationDisplay = annotationDisplay;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setAnnotationTransparency( int percent )
{
m_colorShadingTransparency = percent;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::RegionAnnotationType RimWellLogTrack::annotationType() const
{
return m_regionAnnotationType();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaDefines::RegionDisplay RimWellLogTrack::annotationDisplay() const
{
return m_regionAnnotationDisplay();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogTrack::showFormations() const
{
return m_regionAnnotationType() == RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setShowRegionLabels( bool on )
{
m_showRegionLabels = on;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogTrack::showWellPathAttributes() const
{
return m_showWellPathAttributes;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setShowWellPathAttributes( bool on )
{
m_showWellPathAttributes = on;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setShowWellPathAttributesInLegend( bool on )
{
m_wellPathAttributesInLegend = on;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setShowWellPathCompletionsInLegend( bool on )
{
m_wellPathCompletionsInLegend = on;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setShowBothSidesOfWell( bool on )
{
m_showWellPathComponentsBothSides = on;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setWellPathAttributesSource( RimWellPath* wellPath )
{
m_wellPathComponentSource = wellPath;
updateWellPathAttributesCollection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellPath* RimWellLogTrack::wellPathAttributeSource() const
{
return m_wellPathComponentSource;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimWellLogTrack::viewWidget()
{
return m_plotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuQwtPlotWidget* RimWellLogTrack::viewer()
{
return m_plotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuPlotWidget* RimWellLogTrack::plotWidget()
{
return m_plotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QImage RimWellLogTrack::snapshotWindowContent()
{
QImage image;
if ( m_plotWidget )
{
QPixmap pix = m_plotWidget->grab();
image = pix.toImage();
}
return image;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::zoomAll()
{
RimDepthTrackPlot* plot = nullptr;
firstAncestorOrThisOfType( plot );
if ( plot ) plot->zoomAll();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmObject* RimWellLogTrack::findPdmObjectFromPlotCurve( const RiuPlotCurve* curve ) const
{
for ( size_t idx = 0; idx < m_curves.size(); idx++ )
{
if ( m_curves[idx]->isSameCurve( curve ) )
{
return m_curves[idx];
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &m_description );
RimDepthTrackPlot* plot = nullptr;
firstAncestorOrThisOfType( plot );
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" );
annotationGroup->setCollapsedByDefault();
annotationGroup->add( &m_regionAnnotationType );
annotationGroup->add( &m_regionAnnotationDisplay );
annotationGroup->add( &m_showRegionLabels );
if ( m_regionAnnotationType() == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
annotationGroup->add( &m_regionLabelFontSize );
if ( m_regionAnnotationDisplay() & RiaDefines::COLOR_SHADING || m_regionAnnotationDisplay() & RiaDefines::COLORED_LINES )
{
annotationGroup->add( &m_colorShadingLegend );
if ( m_regionAnnotationDisplay() & RiaDefines::COLOR_SHADING )
{
annotationGroup->add( &m_colorShadingTransparency );
}
}
if ( !m_formationsForCaseWithSimWellOnly )
{
annotationGroup->add( &m_formationSource );
}
else
{
m_formationSource = FormationSource::CASE;
}
if ( m_formationSource() == FormationSource::CASE )
{
annotationGroup->add( &m_formationCase );
if ( !m_formationsForCaseWithSimWellOnly )
{
annotationGroup->add( &m_formationTrajectoryType );
if ( m_formationTrajectoryType() == WELL_PATH )
{
annotationGroup->add( &m_formationWellPathForSourceCase );
}
}
if ( m_formationsForCaseWithSimWellOnly || m_formationTrajectoryType() == SIMULATION_WELL )
{
annotationGroup->add( &m_formationSimWellName );
RiaSimWellBranchTools::appendSimWellBranchFieldsIfRequiredFromSimWellName( annotationGroup,
m_formationSimWellName,
m_formationBranchDetection,
m_formationBranchIndex );
}
}
else if ( m_formationSource() == FormationSource::WELL_PICK_FILTER )
{
annotationGroup->add( &m_formationWellPathForSourceWellPath );
if ( m_formationWellPathForSourceWellPath() )
{
annotationGroup->add( &m_formationLevel );
annotationGroup->add( &m_showformationFluids );
}
}
if ( m_regionAnnotationType() == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
{
m_resultDefinition->uiOrdering( uiConfigName, *annotationGroup );
}
caf::PdmUiGroup* componentGroup = uiOrdering.addNewGroup( "Well Path Components" );
componentGroup->add( &m_showWellPathAttributes );
componentGroup->add( &m_showWellPathCompletions );
componentGroup->add( &m_wellPathAttributesInLegend );
componentGroup->add( &m_wellPathCompletionsInLegend );
componentGroup->add( &m_showWellPathComponentsBothSides );
componentGroup->add( &m_showWellPathComponentLabels );
componentGroup->add( &m_wellPathComponentSource );
uiOrdering.add( &m_ensembleWellLogCurveSet );
uiOrderingForPropertyAxisSettings( uiOrdering );
uiOrdering.skipRemainingFields( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::initAfterRead()
{
if ( m_regionAnnotationType() == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
{
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_formationCase.value() );
m_resultDefinition->setEclipseCase( dynamic_cast<RimEclipseCase*>( eclipseCase ) );
}
if ( m_propertyValueAxisGridVisibility() == RimWellLogPlot::AXIS_GRID_MINOR )
{
m_propertyValueAxisGridVisibility = RimWellLogPlot::AXIS_GRID_MAJOR_AND_MINOR;
}
for ( auto curve : m_curves )
{
connectCurveSignals( curve );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
{
if ( field == &m_colorShadingTransparency )
{
auto sliderAttrib = dynamic_cast<caf::PdmUiSliderEditorAttribute*>( attribute );
if ( sliderAttrib )
{
sliderAttrib->m_minimum = 0;
sliderAttrib->m_maximum = 100;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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;
RimDepthTrackPlot* wellLogPlot = nullptr;
this->firstAncestorOrThisOfType( wellLogPlot );
if ( wellLogPlot )
{
if ( wellLogPlot->depthOrientation() == RiaDefines::Orientation::VERTICAL )
{
m_plotWidget->setAxisInverted( RiuPlotAxis::defaultLeft(), true );
if ( m_isPropertyLogarithmicScaleEnabled )
{
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_isPropertyLogarithmicScaleEnabled )
{
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_wellPathAttributeCollection = nullptr;
if ( m_wellPathComponentSource )
{
std::vector<RimWellPathAttributeCollection*> attributeCollection;
m_wellPathComponentSource->descendantsIncludingThisOfType( attributeCollection );
if ( !attributeCollection.empty() )
{
m_wellPathAttributeCollection = attributeCollection.front();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimDepthTrackPlot* RimWellLogTrack::parentWellLogPlot() const
{
RimDepthTrackPlot* wellLogPlot = nullptr;
this->firstAncestorOrThisOfTypeAsserted( wellLogPlot );
return wellLogPlot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::handleWheelEvent( QWheelEvent* wheelEvent )
{
RimDepthTrackPlot* wellLogPlot = nullptr;
this->firstAncestorOrThisOfType( wellLogPlot );
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::DepthTypeEnum depthType,
const RigGeoMechWellLogExtractor* extractor ) const
{
double waterEndTVD = extractor->waterDepth();
if ( waterEndTVD == std::numeric_limits<double>::infinity() )
{
waterEndTVD = extractor->estimateWaterDepth();
}
if ( depthType == RiaDefines::DepthTypeEnum::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::DepthTypeEnum::TRUE_VERTICAL_DEPTH )
{
double waterStartTVD = 0.0;
double rockEndTVD = extractor->cellIntersectionTVDs().back();
return { { waterStartTVD, waterEndTVD }, { waterEndTVD, rockEndTVD } };
}
else if ( depthType == RiaDefines::DepthTypeEnum::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_isAutoScalePropertyValuesEnabled && m_isPropertyLogarithmicScaleEnabled )
{
double pos = HUGE_VAL;
double neg = -HUGE_VAL;
for ( const auto& curve : m_curves )
{
if ( curve->isChecked() && curve->curveData() )
{
RigStatisticsCalculator::posNegClosestToZero( curve->curveData()->propertyValuesByIntervals(), pos, neg );
}
}
if ( pos != HUGE_VAL )
{
m_visiblePropertyValueRangeMin = pos;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setLogarithmicScale( bool enable )
{
m_isPropertyLogarithmicScaleEnabled = enable;
updateAxisScaleEngine();
computeAndSetPropertyValueRangeMinForLogarithmicScale();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogTrack::isLogarithmicScale() const
{
return m_isPropertyLogarithmicScaleEnabled;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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.children();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimWellLogCurve*> RimWellLogTrack::visibleCurves() const
{
std::vector<RimWellLogCurve*> curvesVector;
for ( RimWellLogCurve* curve : m_curves.children() )
{
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();
formationGroup->add( &m_regionAnnotationType );
formationGroup->add( &m_regionAnnotationDisplay );
formationGroup->add( &m_formationSource );
if ( m_formationSource == FormationSource::CASE )
{
formationGroup->add( &m_formationCase );
}
if ( m_formationSource == FormationSource::WELL_PICK_FILTER )
{
if ( m_formationWellPathForSourceWellPath() && m_formationWellPathForSourceWellPath()->hasFormations() )
{
formationGroup->add( &m_formationLevel );
formationGroup->add( &m_showformationFluids );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::uiOrderingForPropertyAxisSettings( caf::PdmUiOrdering& uiOrdering )
{
caf::PdmUiGroup* gridGroup = uiOrdering.addNewGroup( "Property Axis Settings" );
gridGroup->add( &m_isPropertyAxisEnabled );
gridGroup->add( &m_isPropertyLogarithmicScaleEnabled );
gridGroup->add( &m_visiblePropertyValueRangeMin );
gridGroup->add( &m_visiblePropertyValueRangeMax );
gridGroup->add( &m_invertPropertyValueAxis );
gridGroup->add( &m_propertyValueAxisGridVisibility );
gridGroup->add( &m_propertyAxisMinAndMaxTicksOnly );
// TODO Revisit if these settings are required
// See issue https://github.com/OPM/ResInsight/issues/4367
// gridGroup->add( &m_explicitTickIntervals );
// gridGroup->add( &m_majorTickInterval );
// gridGroup->add( &m_minorTickInterval );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::enablePropertyAxis( bool enable )
{
m_isPropertyAxisEnabled = enable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogTrack::isPropertyAxisEnabled() const
{
return m_isPropertyAxisEnabled();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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.size() == 0 ) return nullptr;
CVF_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::DepthTypeEnum::MEASURED_DEPTH || depthType == RiaDefines::DepthTypeEnum::PSEUDO_LENGTH )
{
depthVector = curveData.md;
}
else if ( depthType == RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH || depthType == RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH_RKB )
{
depthVector = curveData.tvd;
if ( depthType == RiaDefines::DepthTypeEnum::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()
{
RimDepthTrackPlot* wellLogPlot;
firstAncestorOrThisOfTypeAsserted( wellLogPlot );
RimWellLogPlot::DepthTypeEnum depthType = wellLogPlot->depthType();
RiaDefines::DepthUnitType displayUnit = wellLogPlot->depthUnit();
if ( depthType == RiaDefines::DepthTypeEnum::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_isPropertyLogarithmicScaleEnabled );
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::setFormationFieldsUiReadOnly( bool readOnly /*= true*/ )
{
m_formationSource.uiCapability()->setUiReadOnly( readOnly );
m_formationTrajectoryType.uiCapability()->setUiReadOnly( readOnly );
m_formationSimWellName.uiCapability()->setUiReadOnly( readOnly );
m_formationCase.uiCapability()->setUiReadOnly( readOnly );
m_formationWellPathForSourceCase.uiCapability()->setUiReadOnly( readOnly );
m_formationWellPathForSourceWellPath.uiCapability()->setUiReadOnly( readOnly );
m_formationBranchDetection.uiCapability()->setUiReadOnly( readOnly );
m_formationBranchIndex.uiCapability()->setUiReadOnly( readOnly );
m_formationLevel.uiCapability()->setUiReadOnly( readOnly );
m_showformationFluids.uiCapability()->setUiReadOnly( readOnly );
m_colorShadingTransparency.uiCapability()->setUiReadOnly( readOnly );
m_colorShadingLegend.uiCapability()->setUiReadOnly( readOnly );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateRegionAnnotationsOnPlot()
{
removeRegionAnnotations();
if ( m_regionAnnotationType == RiaDefines::RegionAnnotationType::NO_ANNOTATIONS ) return;
if ( m_annotationTool == nullptr )
{
m_annotationTool = std::unique_ptr<RiuPlotAnnotationTool>( new RiuPlotAnnotationTool() );
}
if ( m_regionAnnotationType == RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS )
{
updateFormationNamesOnPlot();
}
else if ( m_regionAnnotationType == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
{
updateResultPropertyNamesOnPlot();
}
else
{
updateCurveDataRegionsOnPlot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateFormationNamesOnPlot()
{
RimDepthTrackPlot* plot = nullptr;
firstAncestorOrThisOfTypeAsserted( plot );
RiaDefines::DepthUnitType fromDepthUnit = plot->caseDepthUnit();
RiaDefines::DepthUnitType toDepthUnit = plot->depthUnit();
auto orientation = plot->depthOrientation();
if ( m_formationSource() == FormationSource::WELL_PICK_FILTER )
{
if ( m_formationWellPathForSourceWellPath == nullptr ) return;
if ( !( plot->depthType() == RiaDefines::DepthTypeEnum::MEASURED_DEPTH ||
plot->depthType() == RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH ||
plot->depthType() == RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH_RKB ) )
{
return;
}
std::vector<double> yValues;
const RigWellPathFormations* formations = m_formationWellPathForSourceWellPath->formationsGeometry();
if ( !formations ) return;
std::vector<QString> formationNamesToPlot;
formations->depthAndFormationNamesUpToLevel( m_formationLevel(),
&formationNamesToPlot,
&yValues,
m_showformationFluids(),
plot->depthType() );
if ( plot->depthType() == RiaDefines::DepthTypeEnum::TRUE_VERTICAL_DEPTH_RKB )
{
for ( double& depthValue : yValues )
{
depthValue += m_formationWellPathForSourceWellPath->wellPathGeometry()->rkbDiff();
}
}
std::vector<double> convertedYValues = RiaWellLogUnitTools<double>::convertDepths( yValues, fromDepthUnit, toDepthUnit );
m_annotationTool->attachWellPicks( m_plotWidget->qwtPlot(), formationNamesToPlot, convertedYValues );
}
else
{
RimMainPlotCollection* mainPlotCollection;
this->firstAncestorOrThisOfTypeAsserted( mainPlotCollection );
RimWellLogPlotCollection* wellLogCollection = mainPlotCollection->wellLogPlotCollection();
CurveSamplingPointData curveData;
RigEclipseWellLogExtractor* eclWellLogExtractor = nullptr;
RigGeoMechWellLogExtractor* geoMechWellLogExtractor = nullptr;
if ( m_formationTrajectoryType == SIMULATION_WELL )
{
eclWellLogExtractor = RimWellLogTrack::createSimWellExtractor( wellLogCollection,
m_formationCase,
m_formationSimWellName,
m_formationBranchIndex,
m_formationBranchDetection );
}
else
{
eclWellLogExtractor = RiaExtractionTools::findOrCreateWellLogExtractor( m_formationWellPathForSourceCase,
dynamic_cast<RimEclipseCase*>( m_formationCase() ) );
}
if ( eclWellLogExtractor )
{
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_formationCase() );
cvf::ref<RigResultAccessor> resultAccessor =
RigResultAccessorFactory::createFromResultAddress( eclipseCase->eclipseCaseData(),
0,
RiaDefines::PorosityModelType::MATRIX_MODEL,
0,
RigEclipseResultAddress( RiaDefines::ResultCatType::FORMATION_NAMES,
RiaResultNames::activeFormationNamesResultName() ) );
curveData = RimWellLogTrack::curveSamplingPointData( eclWellLogExtractor, resultAccessor.p() );
}
else
{
geoMechWellLogExtractor = RiaExtractionTools::findOrCreateWellLogExtractor( m_formationWellPathForSourceCase,
dynamic_cast<RimGeoMechCase*>( m_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_regionAnnotationDisplay(),
waterAndRockColors,
( ( 100 - m_colorShadingTransparency ) * 255 ) / 100,
m_showRegionLabels(),
RiaDefines::TrackSpan::LEFT_COLUMN,
{ Qt::SolidPattern, Qt::Dense6Pattern } );
}
if ( m_formationSource == FormationSource::CASE && m_plotWidget )
{
if ( ( m_formationSimWellName == QString( "None" ) && m_formationWellPathForSourceCase == nullptr ) || m_formationCase == nullptr )
return;
std::vector<QString> formationNamesVector = RimWellLogTrack::formationNamesVector( m_formationCase );
if ( m_overburdenHeight > 0.0 )
{
addOverburden( formationNamesVector, curveData, m_overburdenHeight );
}
if ( m_underburdenHeight > 0.0 )
{
addUnderburden( formationNamesVector, curveData, m_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 );
caf::ColorTable colorTable( m_colorShadingLegend->colorArray() );
m_annotationTool->attachNamedRegions( m_plotWidget->qwtPlot(),
formationNamesToPlot,
orientation,
convertedYValues,
m_regionAnnotationDisplay(),
colorTable,
( ( 100 - m_colorShadingTransparency ) * 255 ) / 100,
m_showRegionLabels() );
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateResultPropertyNamesOnPlot()
{
RimDepthTrackPlot* plot = nullptr;
firstAncestorOrThisOfTypeAsserted( plot );
RiaDefines::DepthUnitType fromDepthUnit = plot->caseDepthUnit();
RiaDefines::DepthUnitType toDepthUnit = plot->depthUnit();
auto orientation = plot->depthOrientation();
RigEclipseWellLogExtractor* eclWellLogExtractor =
RiaExtractionTools::findOrCreateWellLogExtractor( m_formationWellPathForSourceCase, dynamic_cast<RimEclipseCase*>( m_formationCase() ) );
if ( !eclWellLogExtractor )
{
RiaLogging::error( "No well log extractor found for case." );
return;
}
RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_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() ) );
return;
}
CurveSamplingPointData curveData = RimWellLogTrack::curveSamplingPointData( eclWellLogExtractor, resultAccessor.p() );
// Attach water and rock base formations
if ( m_formationSource == FormationSource::CASE )
{
if ( ( m_formationSimWellName == QString( "None" ) && m_formationWellPathForSourceCase == nullptr ) || m_formationCase == nullptr )
return;
std::vector<cvf::Color3ub> colors;
// Find the largest category number.
int maxCategoryValue = std::numeric_limits<int>::min();
for ( RimColorLegendItem* legendItem : m_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_colorShadingLegend()->colorLegendItems() )
{
namesVector[legendItem->categoryValue()] = legendItem->categoryName();
}
if ( m_overburdenHeight > 0.0 )
{
addOverburden( namesVector, curveData, m_overburdenHeight );
}
if ( m_underburdenHeight > 0.0 )
{
addUnderburden( namesVector, curveData, m_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_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_regionLabelFontSize() );
m_annotationTool->attachNamedRegions( m_plotWidget->qwtPlot(),
namesToPlot,
orientation,
convertedYValues,
m_regionAnnotationDisplay(),
colorTable,
( ( 100 - m_colorShadingTransparency ) * 255 ) / 100,
m_showRegionLabels(),
RiaDefines::TrackSpan::FULL_WIDTH,
{},
fontSize );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateCurveDataRegionsOnPlot()
{
RimWellBoreStabilityPlot* wellBoreStabilityPlot = nullptr;
this->firstAncestorOrThisOfType( wellBoreStabilityPlot );
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::findAndLoadWbsParametersFromLasFiles( wellPath, geoMechWellLogExtractor );
RimWellBoreStabilityPlot* wbsPlot;
this->firstAncestorOrThisOfType( wbsPlot );
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_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_regionAnnotationDisplay(),
colorTable,
( ( ( 100 - m_colorShadingTransparency ) * 255 ) / 100 ) / 3,
m_showRegionLabels(),
RiaDefines::TrackSpan::LEFT_COLUMN );
}
{
caf::ColorTable colorTable( m_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_regionAnnotationDisplay(),
colorTable,
( ( ( 100 - m_colorShadingTransparency ) * 255 ) / 100 ) / 3,
m_showRegionLabels(),
RiaDefines::TrackSpan::CENTRE_COLUMN );
}
{
caf::ColorTable colorTable( m_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_regionAnnotationDisplay(),
colorTable,
( ( ( 100 - m_colorShadingTransparency ) * 255 ) / 100 ) / 3,
m_showRegionLabels(),
RiaDefines::TrackSpan::RIGHT_COLUMN );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::updateWellPathAttributesOnPlot()
{
m_wellPathAttributePlotObjects.clear();
if ( wellPathAttributeSource() )
{
std::vector<const RimWellPathComponentInterface*> allWellPathComponents;
if ( wellPathAttributeSource()->wellPathGeometry() && ( m_showWellPathAttributes || m_showWellPathCompletions ) )
{
m_wellPathAttributePlotObjects.push_back(
std::unique_ptr<RiuWellPathComponentPlotItem>( new RiuWellPathComponentPlotItem( wellPathAttributeSource() ) ) );
}
if ( m_showWellPathAttributes )
{
if ( m_wellPathAttributeCollection )
{
std::vector<RimWellPathAttribute*> attributes = m_wellPathAttributeCollection->attributes();
for ( const RimWellPathAttribute* attribute : attributes )
{
if ( attribute->isEnabled() )
{
allWellPathComponents.push_back( attribute );
}
}
}
}
if ( m_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 } };
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 )
{
std::unique_ptr<RiuWellPathComponentPlotItem> plotItem( new RiuWellPathComponentPlotItem( wellPathAttributeSource(), component ) );
QString legendTitle = plotItem->legendTitle();
bool contributeToLegend = m_wellPathCompletionsInLegend() && !completionsAssignedToLegend.count( legendTitle );
plotItem->setContributeToLegend( contributeToLegend );
m_wellPathAttributePlotObjects.push_back( std::move( plotItem ) );
completionsAssignedToLegend.insert( legendTitle );
}
RimDepthTrackPlot* wellLogPlot;
this->firstAncestorOrThisOfTypeAsserted( wellLogPlot );
RimWellLogPlot::DepthTypeEnum depthType = wellLogPlot->depthType();
auto depthOrientation = wellLogPlot->depthOrientation();
for ( auto& attributePlotObject : m_wellPathAttributePlotObjects )
{
attributePlotObject->setDepthType( depthType );
attributePlotObject->setDepthOrientation( depthOrientation );
attributePlotObject->setShowLabel( m_showWellPathComponentLabels() );
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 );
updateZoomInParentPlot();
RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow();
mainPlotWindow->updateWellLogPlotToolBar();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setOverburdenHeight( double overburdenHeight )
{
m_overburdenHeight = overburdenHeight;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogTrack::setUnderburdenHeight( double underburdenHeight )
{
m_underburdenHeight = 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;
this->firstAncestorOrThisOfTypeAsserted( wellLogPlot );
return wellLogPlot->depthAxis();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuPlotAxis RimWellLogTrack::valueAxis() const
{
RimDepthTrackPlot* wellLogPlot;
this->firstAncestorOrThisOfTypeAsserted( wellLogPlot );
return wellLogPlot->valueAxis();
}