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