Correlation: Sync depth range to tornado and use RFT curve depth values for filtering

This commit is contained in:
Magne Sjaastad
2026-04-29 10:16:24 +02:00
parent 97ed7121ed
commit 42a11da26b
5 changed files with 85 additions and 11 deletions
@@ -37,6 +37,7 @@
#include "RimSummaryCase.h"
#include "RimSummaryEnsemble.h"
#include "RimSummaryEnsembleTools.h"
#include "RimWellLogRftCurve.h"
#include "RimWellPath.h"
#include "RiuContextMenuLauncher.h"
@@ -178,6 +179,38 @@ RimSummaryEnsemble* RimParameterRftCrossPlot::ensemble() const
return m_ensemble();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEclipseResultCase* RimParameterRftCrossPlot::eclipseCase() const
{
return m_eclipseCase();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimParameterRftCrossPlot::useDepthRange() const
{
return m_useDepthRange();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimParameterRftCrossPlot::depthRangeMin() const
{
return m_depthRangeMin();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RimParameterRftCrossPlot::depthRangeMax() const
{
return m_depthRangeMax();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -236,16 +269,20 @@ std::vector<double> RimParameterRftCrossPlot::computeMeanPressurePerCase( RimSum
continue;
}
auto mdAddress = RifEclipseRftAddress::createAddress( wellName, timeStep, RifEclipseRftAddress::RftWellLogChannelType::MD );
std::vector<double> depths;
reader->values( mdAddress, &depths );
if ( depths.empty() && extractor ) depths = reader->computeMeasuredDepth( wellName, timeStep, extractor );
// If depths are still empty after the fallback (no MD channel and no extractor), depth range
// filtering is not possible for this case; fall through to use all pressures unfiltered.
// Use the same depth values the RFT curves use for their depth axis, so the filter
// operates on values consistent with what the user sees in the RFT plot.
std::vector<double> depths = RimWellLogRftCurve::rftCurveDepthValues( reader, wellName, timeStep, extractor );
std::vector<double> samplesInRange;
if ( useDepthRange && depths.size() == pressures.size() )
if ( useDepthRange )
{
if ( depths.size() != pressures.size() )
{
// Depth filter requested but no aligned depth data is available for this case;
// exclude rather than silently return an unfiltered mean.
pressurePerCase.push_back( std::numeric_limits<double>::infinity() );
continue;
}
for ( size_t i = 0; i < depths.size(); ++i )
if ( depths[i] >= depthRangeMin && depths[i] <= depthRangeMax ) samplesInRange.push_back( pressures[i] );
}
@@ -63,10 +63,14 @@ public:
void setDepthRange( double minMd, double maxMd );
void setEnsembleParameter( const QString& paramName );
QString ensembleParameter() const;
QString wellName() const;
QDateTime selectedTimeStep() const;
RimSummaryEnsemble* ensemble() const;
QString ensembleParameter() const;
QString wellName() const;
QDateTime selectedTimeStep() const;
RimSummaryEnsemble* ensemble() const;
RimEclipseResultCase* eclipseCase() const;
bool useDepthRange() const;
double depthRangeMin() const;
double depthRangeMax() const;
RiuQwtPlotWidget* viewer();
@@ -505,6 +505,9 @@ void RimRftCorrelationReportPlot::syncTornadoInputsFromCrossPlot()
m_correlationPlot->setWellName( m_parameterRftCrossPlot->wellName() );
m_correlationPlot->setTimeStep( m_parameterRftCrossPlot->selectedTimeStep() );
m_correlationPlot->setSelectedParameter( m_parameterRftCrossPlot->ensembleParameter() );
m_correlationPlot->setEclipseCase( m_parameterRftCrossPlot->eclipseCase() );
m_correlationPlot->setUseDepthRange( m_parameterRftCrossPlot->useDepthRange() );
m_correlationPlot->setDepthRange( m_parameterRftCrossPlot->depthRangeMin(), m_parameterRftCrossPlot->depthRangeMax() );
}
//--------------------------------------------------------------------------------------------------
@@ -1220,6 +1220,28 @@ std::vector<double> RimWellLogRftCurve::measuredDepthValues( QString& prefixText
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimWellLogRftCurve::rftCurveDepthValues( RifReaderRftInterface* reader,
const QString& wellName,
const QDateTime& timeStep,
RigEclipseWellLogExtractor* extractor )
{
if ( !reader ) return {};
auto mdAddress = RifEclipseRftAddress::createAddress( wellName, timeStep, RifEclipseRftAddress::RftWellLogChannelType::MD );
std::vector<double> depths;
reader->values( mdAddress, &depths );
if ( depths.empty() && extractor ) depths = reader->computeMeasuredDepth( wellName, timeStep, extractor );
if ( depths.empty() )
{
auto tvdAddress = RifEclipseRftAddress::createAddress( wellName, timeStep, RifEclipseRftAddress::RftWellLogChannelType::TVD );
reader->values( tvdAddress, &depths );
}
return depths;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -96,6 +96,14 @@ public:
void setScaleFactor( double factor );
// Returns the depth values an RFT curve uses for its depth axis for the given well/time step.
// Fallback chain: RFT MD channel, then extractor-derived MD, then TVD channel as a final
// fallback (the RFT plot displays TVD on the depth axis when MD is missing).
static std::vector<double> rftCurveDepthValues( RifReaderRftInterface* reader,
const QString& wellName,
const QDateTime& timeStep,
RigEclipseWellLogExtractor* extractor );
protected:
QString createCurveAutoName() override;
QString createCurveNameFromTemplate( const QString& templateText ) override;