mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
#14878: Add well-pick zone filtering to RFT cross plot and tornado plot
Let the RFT parameter cross plot reference a RimWellFormationsFile and use its well-pick formations to filter/group data by zone, pushed down to the tornado plot and RFT correlation sub plots.
This commit is contained in:
1 parent
45814555b5
commit
6c42ba5ae0
9 files changed
+535
-101
No files matched your search
+124
-28
@@ -26,8 +26,12 @@
|
||||
#include "RigEnsembleParameter.h"
|
||||
#include "RigStatisticsTools.h"
|
||||
|
||||
#include "Formations/RimWellFormationsCollection.h"
|
||||
#include "Formations/RimWellFormationsFile.h"
|
||||
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseResultCase.h"
|
||||
#include "RimOilField.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimRftCrossPlotTools.h"
|
||||
#include "RimSummaryCase.h"
|
||||
@@ -44,6 +48,7 @@
|
||||
|
||||
#include "cafPdmPointer.h"
|
||||
#include "cafPdmUiComboBoxEditor.h"
|
||||
#include "cafPdmUiTreeSelectionEditor.h"
|
||||
|
||||
#include "qwt_picker_machine.h"
|
||||
#include "qwt_plot.h"
|
||||
@@ -86,9 +91,15 @@ RimParameterRftCrossPlot::RimParameterRftCrossPlot()
|
||||
CAF_PDM_InitFieldNoDefault( &m_selectedTimeStep, "TimeStep", "Time Step" );
|
||||
m_selectedTimeStep.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() );
|
||||
CAF_PDM_InitFieldNoDefault( &m_eclipseCase, "EclipseCase", "Eclipse Case (MD fallback)" );
|
||||
CAF_PDM_InitField( &m_useDepthRange, "UseDepthRange", false, "Filter by Depth Range" );
|
||||
CAF_PDM_InitField( &m_filterMode,
|
||||
"FilterMode",
|
||||
RimRftCrossPlotTools::DepthFilterModeEnum( RimRftCrossPlotTools::DepthFilterMode::NONE ),
|
||||
"Depth Filter" );
|
||||
CAF_PDM_InitField( &m_depthRangeMin, "DepthRangeMin", 0.0, "Min Depth" );
|
||||
CAF_PDM_InitField( &m_depthRangeMax, "DepthRangeMax", 5000.0, "Max Depth" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_wellFormations, "WellFormations", "Well Formations File" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_selectedZones, "SelectedZones", "Zones" );
|
||||
m_selectedZones.uiCapability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName() );
|
||||
CAF_PDM_InitField( &m_depthType, "DepthType", caf::AppEnum<RiaDefines::DepthType>( RiaDefines::DepthType::MEASURED_DEPTH ), "Depth Type" );
|
||||
m_depthType.uiCapability()->setUiHidden( true ); // driven by the parent RimRftCorrelationReportPlot
|
||||
CAF_PDM_InitField( &m_samplingMode, "SamplingMode", SamplingModeEnum( SamplingMode::MEAN_PER_REALIZATION ), "Sampling" );
|
||||
@@ -164,6 +175,14 @@ void RimParameterRftCrossPlot::setEnsembleParameter( const QString& paramName )
|
||||
m_ensembleParameter = paramName;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimParameterRftCrossPlot::setWellFormations( RimWellFormationsFile* wellFormationsFile )
|
||||
{
|
||||
m_wellFormations = wellFormationsFile;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -209,7 +228,7 @@ RimEclipseResultCase* RimParameterRftCrossPlot::eclipseCase() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimParameterRftCrossPlot::useDepthRange() const
|
||||
{
|
||||
return m_useDepthRange();
|
||||
return m_filterMode() != RimRftCrossPlotTools::DepthFilterMode::NONE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -236,6 +255,30 @@ RiaDefines::DepthType RimParameterRftCrossPlot::depthType() const
|
||||
return m_depthType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimRftCrossPlotTools::DepthFilterMode RimParameterRftCrossPlot::filterMode() const
|
||||
{
|
||||
return m_filterMode();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<QString> RimParameterRftCrossPlot::selectedZones() const
|
||||
{
|
||||
return m_selectedZones();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellFormationsFile* RimParameterRftCrossPlot::wellFormationsFile() const
|
||||
{
|
||||
return m_wellFormations();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -244,6 +287,21 @@ RiuQwtPlotWidget* RimParameterRftCrossPlot::viewer()
|
||||
return m_plotWidget;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimRftCrossPlotTools::DepthInterval> RimParameterRftCrossPlot::depthIntervals() const
|
||||
{
|
||||
return RimRftCrossPlotTools::buildDepthIntervals( useDepthRange(),
|
||||
m_filterMode(),
|
||||
m_depthRangeMin(),
|
||||
m_depthRangeMax(),
|
||||
m_wellFormations(),
|
||||
m_wellName(),
|
||||
m_selectedZones(),
|
||||
m_depthType() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -268,9 +326,7 @@ std::vector<RimParameterRftCrossPlot::CaseData> RimParameterRftCrossPlot::create
|
||||
m_wellName(),
|
||||
m_selectedTimeStep(),
|
||||
m_eclipseCase(),
|
||||
m_useDepthRange(),
|
||||
m_depthRangeMin(),
|
||||
m_depthRangeMax(),
|
||||
depthIntervals(),
|
||||
m_depthType() );
|
||||
|
||||
if ( samplesPerCase.size() != allCases.size() ) return {};
|
||||
@@ -292,9 +348,7 @@ std::vector<RimParameterRftCrossPlot::CaseData> RimParameterRftCrossPlot::create
|
||||
m_wellName(),
|
||||
m_selectedTimeStep(),
|
||||
m_eclipseCase(),
|
||||
m_useDepthRange(),
|
||||
m_depthRangeMin(),
|
||||
m_depthRangeMax(),
|
||||
depthIntervals(),
|
||||
m_depthType() );
|
||||
|
||||
if ( pressurePerCase.size() != allCases.size() ) return {};
|
||||
@@ -333,13 +387,15 @@ void RimParameterRftCrossPlot::updateAxes()
|
||||
const int axisTitleSize = caf::FontTools::absolutePointSize( RiaPreferences::current()->defaultPlotFontSize(), m_axisTitleFontSize() );
|
||||
const int axisValueSize = caf::FontTools::absolutePointSize( RiaPreferences::current()->defaultPlotFontSize(), m_axisValueFontSize() );
|
||||
|
||||
const QString pressureLabel = m_samplingMode() == SamplingMode::ALL_SAMPLES ? "Pressure" : "Mean Pressure";
|
||||
const QString depthLabel = m_useDepthRange() ? QString( "%1 [%2 %3 - %4]" )
|
||||
.arg( pressureLabel )
|
||||
.arg( RimRftCrossPlotTools::depthTypeAbbreviation( m_depthType() ) )
|
||||
.arg( m_depthRangeMin() )
|
||||
.arg( m_depthRangeMax() )
|
||||
: pressureLabel;
|
||||
const QString pressureLabel = m_samplingMode() == SamplingMode::ALL_SAMPLES ? "Pressure" : "Mean Pressure";
|
||||
const QString filterDescription = RimRftCrossPlotTools::depthFilterDescription( useDepthRange(),
|
||||
m_filterMode(),
|
||||
m_depthType(),
|
||||
m_depthRangeMin(),
|
||||
m_depthRangeMax(),
|
||||
m_selectedZones() );
|
||||
const QString depthLabel = filterDescription.isEmpty() ? pressureLabel
|
||||
: QString( "%1 [%2]" ).arg( pressureLabel ).arg( filterDescription );
|
||||
|
||||
m_plotWidget->setAxisTitleText( RiuPlotAxis::defaultLeft(), depthLabel );
|
||||
m_plotWidget->setAxisTitleEnabled( RiuPlotAxis::defaultLeft(), true );
|
||||
@@ -518,11 +574,18 @@ void RimParameterRftCrossPlot::defineUiOrdering( QString uiConfigName, caf::PdmU
|
||||
|
||||
auto* depthGroup =
|
||||
uiOrdering.addNewGroup( QString( "Depth Range (%1)" ).arg( RimRftCrossPlotTools::depthTypeAbbreviation( m_depthType() ) ) );
|
||||
depthGroup->add( &m_useDepthRange );
|
||||
depthGroup->add( &m_filterMode );
|
||||
depthGroup->add( &m_depthRangeMin );
|
||||
depthGroup->add( &m_depthRangeMax );
|
||||
m_depthRangeMin.uiCapability()->setUiReadOnly( !m_useDepthRange() );
|
||||
m_depthRangeMax.uiCapability()->setUiReadOnly( !m_useDepthRange() );
|
||||
depthGroup->add( &m_wellFormations );
|
||||
depthGroup->add( &m_selectedZones );
|
||||
|
||||
const bool useRange = m_filterMode() == RimRftCrossPlotTools::DepthFilterMode::DEPTH_RANGE;
|
||||
const bool useZones = m_filterMode() == RimRftCrossPlotTools::DepthFilterMode::ZONES;
|
||||
m_depthRangeMin.uiCapability()->setUiHidden( !useRange );
|
||||
m_depthRangeMax.uiCapability()->setUiHidden( !useRange );
|
||||
m_wellFormations.uiCapability()->setUiHidden( !useZones );
|
||||
m_selectedZones.uiCapability()->setUiHidden( !useZones || !m_wellFormations() );
|
||||
|
||||
auto* crossPlotGroup = uiOrdering.addNewGroup( "Cross Plot Parameter" );
|
||||
crossPlotGroup->add( &m_ensembleParameter );
|
||||
@@ -564,6 +627,13 @@ void RimParameterRftCrossPlot::fieldChangedByUi( const caf::PdmFieldHandle* chan
|
||||
m_selectedTimeStep = timeSteps.empty() ? QDateTime() : *timeSteps.begin();
|
||||
}
|
||||
|
||||
if ( changedField == &m_wellName || changedField == &m_wellFormations )
|
||||
{
|
||||
// The selected zones belong to the previous well/formations file; clear them so stale zone
|
||||
// names are not silently applied as a filter.
|
||||
m_selectedZones = std::vector<QString>();
|
||||
}
|
||||
|
||||
RimPlot::fieldChangedByUi( changedField, oldValue, newValue );
|
||||
loadDataAndUpdate();
|
||||
}
|
||||
@@ -626,6 +696,32 @@ QList<caf::PdmOptionItemInfo> RimParameterRftCrossPlot::calculateValueOptions( c
|
||||
options.push_back( caf::PdmOptionItemInfo( rc->caseUserDescription(), rc ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_wellFormations )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( "None", static_cast<RimWellFormationsFile*>( nullptr ) ) );
|
||||
auto* project = RimProject::current();
|
||||
if ( project && project->activeOilField() && project->activeOilField()->wellFormationsCollection() )
|
||||
{
|
||||
for ( RimWellFormationsFile* file : project->activeOilField()->wellFormationsCollection()->wellFormationsFiles() )
|
||||
options.push_back( caf::PdmOptionItemInfo( file->shortName(), file ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_filterMode )
|
||||
{
|
||||
using DepthFilterMode = RimRftCrossPlotTools::DepthFilterMode;
|
||||
for ( auto mode : { DepthFilterMode::NONE, DepthFilterMode::DEPTH_RANGE, DepthFilterMode::ZONES } )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( RimRftCrossPlotTools::DepthFilterModeEnum::uiText( mode ), mode ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_selectedZones )
|
||||
{
|
||||
if ( m_wellFormations() )
|
||||
{
|
||||
for ( const QString& zoneName : m_wellFormations->zoneNames( m_wellName() ) )
|
||||
options.push_back( caf::PdmOptionItemInfo( zoneName, zoneName ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_ensembleParameter )
|
||||
{
|
||||
if ( m_ensemble() )
|
||||
@@ -641,9 +737,7 @@ QList<caf::PdmOptionItemInfo> RimParameterRftCrossPlot::calculateValueOptions( c
|
||||
m_wellName(),
|
||||
m_selectedTimeStep(),
|
||||
m_eclipseCase(),
|
||||
m_useDepthRange(),
|
||||
m_depthRangeMin(),
|
||||
m_depthRangeMax(),
|
||||
depthIntervals(),
|
||||
m_depthType() );
|
||||
}
|
||||
|
||||
@@ -750,14 +844,16 @@ void RimParameterRftCrossPlot::updatePlotTitle()
|
||||
|
||||
if ( m_useAutoPlotTitle && m_ensemble() )
|
||||
{
|
||||
if ( m_useDepthRange() )
|
||||
const QString filterDescription = RimRftCrossPlotTools::depthFilterDescription( useDepthRange(),
|
||||
m_filterMode(),
|
||||
m_depthType(),
|
||||
m_depthRangeMin(),
|
||||
m_depthRangeMax(),
|
||||
m_selectedZones() );
|
||||
if ( !filterDescription.isEmpty() )
|
||||
{
|
||||
m_description = QString( "%1 vs RFT Pressure [%2 %3 - %4 m], %5" )
|
||||
.arg( m_ensembleParameter() )
|
||||
.arg( RimRftCrossPlotTools::depthTypeAbbreviation( m_depthType() ) )
|
||||
.arg( m_depthRangeMin() )
|
||||
.arg( m_depthRangeMax() )
|
||||
.arg( m_ensemble->name() );
|
||||
m_description =
|
||||
QString( "%1 vs RFT Pressure [%2], %3" ).arg( m_ensembleParameter() ).arg( filterDescription ).arg( m_ensemble->name() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "Appearance/RimFontSizeField.h"
|
||||
#include "RiaDefines.h"
|
||||
#include "RimPlot.h"
|
||||
#include "RimRftCrossPlotTools.h"
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
#include "cafPdmField.h"
|
||||
@@ -35,6 +36,7 @@
|
||||
class RimEclipseResultCase;
|
||||
class RimSummaryEnsemble;
|
||||
class RimSummaryCase;
|
||||
class RimWellFormationsFile;
|
||||
class RiuQwtPlotWidget;
|
||||
|
||||
//==================================================================================================
|
||||
@@ -74,16 +76,20 @@ public:
|
||||
void setDepthRange( double minMd, double maxMd );
|
||||
void setDepthType( RiaDefines::DepthType depthType );
|
||||
void setEnsembleParameter( const QString& paramName );
|
||||
void setWellFormations( RimWellFormationsFile* wellFormationsFile );
|
||||
|
||||
QString ensembleParameter() const;
|
||||
QString wellName() const;
|
||||
QDateTime selectedTimeStep() const;
|
||||
RimSummaryEnsemble* ensemble() const;
|
||||
RimEclipseResultCase* eclipseCase() const;
|
||||
bool useDepthRange() const;
|
||||
double depthRangeMin() const;
|
||||
double depthRangeMax() const;
|
||||
RiaDefines::DepthType depthType() 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;
|
||||
RiaDefines::DepthType depthType() const;
|
||||
RimRftCrossPlotTools::DepthFilterMode filterMode() const;
|
||||
std::vector<QString> selectedZones() const;
|
||||
RimWellFormationsFile* wellFormationsFile() const;
|
||||
|
||||
RiuQwtPlotWidget* viewer();
|
||||
|
||||
@@ -120,17 +126,21 @@ private:
|
||||
void cleanupBeforeClose();
|
||||
RimSummaryCase* findClosestCase( const QPoint& canvasPos );
|
||||
|
||||
std::vector<RimRftCrossPlotTools::DepthInterval> depthIntervals() const;
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimSummaryEnsemble*> m_ensemble;
|
||||
caf::PdmField<QString> m_wellName;
|
||||
caf::PdmField<QDateTime> m_selectedTimeStep;
|
||||
caf::PdmPtrField<RimEclipseResultCase*> m_eclipseCase;
|
||||
caf::PdmField<bool> m_useDepthRange;
|
||||
caf::PdmField<double> m_depthRangeMin;
|
||||
caf::PdmField<double> m_depthRangeMax;
|
||||
caf::PdmField<caf::AppEnum<RiaDefines::DepthType>> m_depthType;
|
||||
caf::PdmField<SamplingModeEnum> m_samplingMode;
|
||||
caf::PdmField<QString> m_ensembleParameter;
|
||||
caf::PdmPtrField<RimSummaryEnsemble*> m_ensemble;
|
||||
caf::PdmField<QString> m_wellName;
|
||||
caf::PdmField<QDateTime> m_selectedTimeStep;
|
||||
caf::PdmPtrField<RimEclipseResultCase*> m_eclipseCase;
|
||||
caf::PdmField<RimRftCrossPlotTools::DepthFilterModeEnum> m_filterMode;
|
||||
caf::PdmField<double> m_depthRangeMin;
|
||||
caf::PdmField<double> m_depthRangeMax;
|
||||
caf::PdmPtrField<RimWellFormationsFile*> m_wellFormations;
|
||||
caf::PdmField<std::vector<QString>> m_selectedZones;
|
||||
caf::PdmField<caf::AppEnum<RiaDefines::DepthType>> m_depthType;
|
||||
caf::PdmField<SamplingModeEnum> m_samplingMode;
|
||||
caf::PdmField<QString> m_ensembleParameter;
|
||||
|
||||
caf::PdmField<bool> m_useAutoPlotTitle;
|
||||
caf::PdmField<QString> m_description;
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "RimWellLogTrack.h"
|
||||
#include "RimWellRftPlot.h"
|
||||
|
||||
#include "Formations/RimWellFormationsFile.h"
|
||||
|
||||
#include "RiuInterfaceToViewWindow.h"
|
||||
#include "RiuPlotWidget.h"
|
||||
#include "RiuQwtPlotWidget.h"
|
||||
@@ -528,6 +530,8 @@ void RimRftCorrelationReportPlot::syncTornadoInputsFromCrossPlot()
|
||||
{
|
||||
if ( !m_tornadoPlot() || !m_parameterRftCrossPlot() ) return;
|
||||
|
||||
applyWellFormationsToSubPlots();
|
||||
|
||||
m_tornadoPlot->setEnsemble( m_parameterRftCrossPlot->ensemble() );
|
||||
m_tornadoPlot->setWellName( m_parameterRftCrossPlot->wellName() );
|
||||
m_tornadoPlot->setTimeStep( m_parameterRftCrossPlot->selectedTimeStep() );
|
||||
@@ -536,6 +540,22 @@ void RimRftCorrelationReportPlot::syncTornadoInputsFromCrossPlot()
|
||||
m_tornadoPlot->setUseDepthRange( m_parameterRftCrossPlot->useDepthRange() );
|
||||
m_tornadoPlot->setDepthRange( m_parameterRftCrossPlot->depthRangeMin(), m_parameterRftCrossPlot->depthRangeMax() );
|
||||
m_tornadoPlot->setDepthType( m_parameterRftCrossPlot->depthType() );
|
||||
m_tornadoPlot->setFilterMode( m_parameterRftCrossPlot->filterMode() );
|
||||
m_tornadoPlot->setSelectedZones( m_parameterRftCrossPlot->selectedZones() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Pushes the user's manual "Well Formations File" selection in the cross plot down to the sub
|
||||
/// plots so their "Filter By: Zones" option becomes available.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimRftCorrelationReportPlot::applyWellFormationsToSubPlots()
|
||||
{
|
||||
if ( !m_parameterRftCrossPlot() ) return;
|
||||
|
||||
RimWellFormationsFile* wellFormationsFile = m_parameterRftCrossPlot->wellFormationsFile();
|
||||
|
||||
m_parameterRftCrossPlot->setWellFormations( wellFormationsFile );
|
||||
if ( m_tornadoPlot() ) m_tornadoPlot->setWellFormations( wellFormationsFile );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -90,6 +90,7 @@ private:
|
||||
void onTornadoParameterSelected( const QString& paramName );
|
||||
void syncTornadoInputsFromCrossPlot();
|
||||
void applyDepthTypeToSubPlots();
|
||||
void applyWellFormationsToSubPlots();
|
||||
|
||||
private:
|
||||
caf::PdmProxyValueField<QString> m_name;
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#include "RiaExtractionTools.h"
|
||||
|
||||
#include "Well/RigEclipseWellLogExtractor.h"
|
||||
#include "Well/RigWellPathFormations.h"
|
||||
|
||||
#include "Formations/RimWellFormationsFile.h"
|
||||
|
||||
#include "RimEclipseResultCase.h"
|
||||
#include "RimProject.h"
|
||||
@@ -30,9 +33,22 @@
|
||||
#include "RimSummaryEnsemble.h"
|
||||
#include "RimWellPath.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template <>
|
||||
void caf::AppEnum<RimRftCrossPlotTools::DepthFilterMode>::setUp()
|
||||
{
|
||||
addItem( RimRftCrossPlotTools::DepthFilterMode::NONE, "NONE", "None" );
|
||||
addItem( RimRftCrossPlotTools::DepthFilterMode::DEPTH_RANGE, "DEPTH_RANGE", "Depth Range" );
|
||||
addItem( RimRftCrossPlotTools::DepthFilterMode::ZONES, "ZONES", "Formation" );
|
||||
setDefault( RimRftCrossPlotTools::DepthFilterMode::NONE );
|
||||
}
|
||||
} // namespace caf
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -76,7 +92,59 @@ std::vector<double> RimRftCrossPlotTools::filterPressuresByDepthRange( const std
|
||||
double depthRangeMin,
|
||||
double depthRangeMax )
|
||||
{
|
||||
if ( !useDepthRange ) return pressures;
|
||||
std::vector<DepthInterval> intervals;
|
||||
if ( useDepthRange ) intervals.push_back( { depthRangeMin, depthRangeMax } );
|
||||
|
||||
return filterPressuresByDepthIntervals( depths, pressures, intervals );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimRftCrossPlotTools::DepthInterval> RimRftCrossPlotTools::buildDepthIntervals( bool useFilter,
|
||||
DepthFilterMode mode,
|
||||
double depthRangeMin,
|
||||
double depthRangeMax,
|
||||
RimWellFormationsFile* wellFormationsFile,
|
||||
const QString& wellName,
|
||||
const std::vector<QString>& selectedZones,
|
||||
RiaDefines::DepthType depthType )
|
||||
{
|
||||
if ( !useFilter || mode == DepthFilterMode::NONE ) return {};
|
||||
|
||||
if ( mode == DepthFilterMode::DEPTH_RANGE ) return { DepthInterval{ depthRangeMin, depthRangeMax } };
|
||||
|
||||
// ZONES mode
|
||||
if ( !wellFormationsFile || selectedZones.empty() ) return {};
|
||||
|
||||
std::optional<RigWellPathFormations> formations = wellFormationsFile->formationsForWell( wellName );
|
||||
if ( !formations.has_value() ) return {};
|
||||
|
||||
std::vector<DepthInterval> intervals;
|
||||
for ( size_t i = 0; i < formations->formationCount(); ++i )
|
||||
{
|
||||
const RigWellPathFormation& formation = formations->formationAt( i );
|
||||
|
||||
bool isSelected = std::find( selectedZones.begin(), selectedZones.end(), formation.formationName ) != selectedZones.end();
|
||||
if ( !isSelected ) continue;
|
||||
|
||||
if ( depthType == RiaDefines::DepthType::TRUE_VERTICAL_DEPTH )
|
||||
intervals.push_back( { formation.tvdTop, formation.tvdBase } );
|
||||
else
|
||||
intervals.push_back( { formation.mdTop, formation.mdBase } );
|
||||
}
|
||||
|
||||
return intervals;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimRftCrossPlotTools::filterPressuresByDepthIntervals( const std::vector<double>& depths,
|
||||
const std::vector<double>& pressures,
|
||||
const std::vector<DepthInterval>& depthIntervals )
|
||||
{
|
||||
if ( depthIntervals.empty() ) return pressures;
|
||||
|
||||
// Depth filter requested but no aligned depth data is available; exclude rather than
|
||||
// silently return an unfiltered set of samples.
|
||||
@@ -84,11 +152,45 @@ std::vector<double> RimRftCrossPlotTools::filterPressuresByDepthRange( const std
|
||||
|
||||
std::vector<double> samplesInRange;
|
||||
for ( size_t i = 0; i < depths.size(); ++i )
|
||||
if ( depths[i] >= depthRangeMin && depths[i] <= depthRangeMax ) samplesInRange.push_back( pressures[i] );
|
||||
{
|
||||
for ( const DepthInterval& interval : depthIntervals )
|
||||
{
|
||||
if ( depths[i] >= interval.top && depths[i] <= interval.base )
|
||||
{
|
||||
samplesInRange.push_back( pressures[i] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return samplesInRange;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimRftCrossPlotTools::depthFilterDescription( bool useFilter,
|
||||
DepthFilterMode mode,
|
||||
RiaDefines::DepthType depthType,
|
||||
double depthRangeMin,
|
||||
double depthRangeMax,
|
||||
const std::vector<QString>& selectedZones )
|
||||
{
|
||||
if ( !useFilter || mode == DepthFilterMode::NONE ) return {};
|
||||
|
||||
if ( mode == DepthFilterMode::ZONES )
|
||||
{
|
||||
if ( selectedZones.empty() ) return {};
|
||||
|
||||
QStringList zoneList;
|
||||
for ( const QString& zone : selectedZones )
|
||||
zoneList << zone;
|
||||
return QString( "Zones: %1" ).arg( zoneList.join( ", " ) );
|
||||
}
|
||||
|
||||
return QString( "%1 %2 - %3 m" ).arg( depthTypeAbbreviation( depthType ) ).arg( depthRangeMin ).arg( depthRangeMax );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -102,14 +204,12 @@ double RimRftCrossPlotTools::computeMean( const std::vector<double>& samples )
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<std::vector<double>> RimRftCrossPlotTools::computePressureSamplesPerCase( RimSummaryEnsemble* ensemble,
|
||||
const QString& wellName,
|
||||
const QDateTime& timeStep,
|
||||
RimEclipseResultCase* eclipseCase,
|
||||
bool useDepthRange,
|
||||
double depthRangeMin,
|
||||
double depthRangeMax,
|
||||
RiaDefines::DepthType depthType )
|
||||
std::vector<std::vector<double>> RimRftCrossPlotTools::computePressureSamplesPerCase( RimSummaryEnsemble* ensemble,
|
||||
const QString& wellName,
|
||||
const QDateTime& timeStep,
|
||||
RimEclipseResultCase* eclipseCase,
|
||||
const std::vector<DepthInterval>& depthIntervals,
|
||||
RiaDefines::DepthType depthType )
|
||||
{
|
||||
if ( !ensemble || wellName.isEmpty() || !timeStep.isValid() ) return {};
|
||||
|
||||
@@ -154,7 +254,7 @@ std::vector<std::vector<double>> RimRftCrossPlotTools::computePressureSamplesPer
|
||||
// operates on values consistent with what the user sees in the RFT plot.
|
||||
std::vector<double> depths = rftCurveDepthValues( reader, wellName, timeStep, extractor, depthType );
|
||||
|
||||
samplesPerCase.push_back( filterPressuresByDepthRange( depths, pressures, useDepthRange, depthRangeMin, depthRangeMax ) );
|
||||
samplesPerCase.push_back( filterPressuresByDepthIntervals( depths, pressures, depthIntervals ) );
|
||||
}
|
||||
|
||||
return samplesPerCase;
|
||||
@@ -163,17 +263,15 @@ std::vector<std::vector<double>> RimRftCrossPlotTools::computePressureSamplesPer
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimRftCrossPlotTools::computeMeanPressurePerCase( RimSummaryEnsemble* ensemble,
|
||||
const QString& wellName,
|
||||
const QDateTime& timeStep,
|
||||
RimEclipseResultCase* eclipseCase,
|
||||
bool useDepthRange,
|
||||
double depthRangeMin,
|
||||
double depthRangeMax,
|
||||
RiaDefines::DepthType depthType )
|
||||
std::vector<double> RimRftCrossPlotTools::computeMeanPressurePerCase( RimSummaryEnsemble* ensemble,
|
||||
const QString& wellName,
|
||||
const QDateTime& timeStep,
|
||||
RimEclipseResultCase* eclipseCase,
|
||||
const std::vector<DepthInterval>& depthIntervals,
|
||||
RiaDefines::DepthType depthType )
|
||||
{
|
||||
const std::vector<std::vector<double>> samplesPerCase =
|
||||
computePressureSamplesPerCase( ensemble, wellName, timeStep, eclipseCase, useDepthRange, depthRangeMin, depthRangeMax, depthType );
|
||||
computePressureSamplesPerCase( ensemble, wellName, timeStep, eclipseCase, depthIntervals, depthType );
|
||||
|
||||
std::vector<double> pressurePerCase;
|
||||
pressurePerCase.reserve( samplesPerCase.size() );
|
||||
|
||||
@@ -19,8 +19,11 @@
|
||||
|
||||
#include "RiaDefines.h"
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -28,6 +31,7 @@ class RifReaderRftInterface;
|
||||
class RigEclipseWellLogExtractor;
|
||||
class RimEclipseResultCase;
|
||||
class RimSummaryEnsemble;
|
||||
class RimWellFormationsFile;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
@@ -37,6 +41,23 @@ class RimSummaryEnsemble;
|
||||
//==================================================================================================
|
||||
namespace RimRftCrossPlotTools
|
||||
{
|
||||
// How the active depth filter selects samples: a single depth range, or a set of named zones
|
||||
// looked up in a well formations file.
|
||||
enum class DepthFilterMode
|
||||
{
|
||||
NONE,
|
||||
DEPTH_RANGE,
|
||||
ZONES
|
||||
};
|
||||
using DepthFilterModeEnum = caf::AppEnum<DepthFilterMode>;
|
||||
|
||||
// A single inclusive depth interval, in the unit/datum of whichever depth type it was built for.
|
||||
struct DepthInterval
|
||||
{
|
||||
double top = 0.0;
|
||||
double base = 0.0;
|
||||
};
|
||||
|
||||
// Short abbreviation used in axis titles and plot titles for the active depth type.
|
||||
QString depthTypeAbbreviation( RiaDefines::DepthType depthType );
|
||||
|
||||
@@ -61,28 +82,53 @@ std::vector<double> filterPressuresByDepthRange( const std::vector<double>& dept
|
||||
double depthRangeMin,
|
||||
double depthRangeMax );
|
||||
|
||||
// Builds the active depth filter intervals from either a depth range or a set of selected zones.
|
||||
// Returns an empty vector (meaning "no filter") when useFilter is false, or when ZONES mode is
|
||||
// selected but no well formations file, well name, or matching zones are available.
|
||||
std::vector<DepthInterval> buildDepthIntervals( bool useFilter,
|
||||
DepthFilterMode mode,
|
||||
double depthRangeMin,
|
||||
double depthRangeMax,
|
||||
RimWellFormationsFile* wellFormationsFile,
|
||||
const QString& wellName,
|
||||
const std::vector<QString>& selectedZones,
|
||||
RiaDefines::DepthType depthType );
|
||||
|
||||
// Returns the subset of pressures whose corresponding depth lies within any of depthIntervals
|
||||
// (inclusive). An empty depthIntervals list means "no filter", returning pressures unchanged; a
|
||||
// size mismatch between depths/pressures returns an empty vector (no aligned depth data).
|
||||
std::vector<double> filterPressuresByDepthIntervals( const std::vector<double>& depths,
|
||||
const std::vector<double>& pressures,
|
||||
const std::vector<DepthInterval>& depthIntervals );
|
||||
|
||||
// Short description of the active depth filter for titles/axis labels/group text, e.g.
|
||||
// "MD 1000 - 2000 m" or "Zones: Valysar, Therys". Empty when filtering is disabled.
|
||||
QString depthFilterDescription( bool useFilter,
|
||||
DepthFilterMode mode,
|
||||
RiaDefines::DepthType depthType,
|
||||
double depthRangeMin,
|
||||
double depthRangeMax,
|
||||
const std::vector<QString>& selectedZones );
|
||||
|
||||
// Arithmetic mean of the given samples, or infinity if samples is empty.
|
||||
double computeMean( const std::vector<double>& samples );
|
||||
|
||||
// Computes the individual RFT pressure samples within the depth range per ensemble case.
|
||||
// Indices match ensemble->allSummaryCases(). A case with no data gets an empty vector.
|
||||
std::vector<std::vector<double>> computePressureSamplesPerCase( RimSummaryEnsemble* ensemble,
|
||||
const QString& wellName,
|
||||
const QDateTime& timeStep,
|
||||
RimEclipseResultCase* eclipseCase,
|
||||
bool useDepthRange,
|
||||
double depthRangeMin,
|
||||
double depthRangeMax,
|
||||
// Computes the individual RFT pressure samples within depthIntervals per ensemble case.
|
||||
// Indices match ensemble->allSummaryCases(). A case with no data gets an empty vector. An empty
|
||||
// depthIntervals list means no filtering.
|
||||
std::vector<std::vector<double>> computePressureSamplesPerCase( RimSummaryEnsemble* ensemble,
|
||||
const QString& wellName,
|
||||
const QDateTime& timeStep,
|
||||
RimEclipseResultCase* eclipseCase,
|
||||
const std::vector<DepthInterval>& depthIntervals,
|
||||
RiaDefines::DepthType depthType = RiaDefines::DepthType::MEASURED_DEPTH );
|
||||
|
||||
// Computes mean RFT pressure per ensemble case (one entry per case, infinity = no data).
|
||||
// Indices match ensemble->allSummaryCases().
|
||||
std::vector<double> computeMeanPressurePerCase( RimSummaryEnsemble* ensemble,
|
||||
const QString& wellName,
|
||||
const QDateTime& timeStep,
|
||||
RimEclipseResultCase* eclipseCase,
|
||||
bool useDepthRange,
|
||||
double depthRangeMin,
|
||||
double depthRangeMax,
|
||||
RiaDefines::DepthType depthType = RiaDefines::DepthType::MEASURED_DEPTH );
|
||||
std::vector<double> computeMeanPressurePerCase( RimSummaryEnsemble* ensemble,
|
||||
const QString& wellName,
|
||||
const QDateTime& timeStep,
|
||||
RimEclipseResultCase* eclipseCase,
|
||||
const std::vector<DepthInterval>& depthIntervals,
|
||||
RiaDefines::DepthType depthType = RiaDefines::DepthType::MEASURED_DEPTH );
|
||||
} // namespace RimRftCrossPlotTools
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "RimSummaryEnsemble.h"
|
||||
#include "RimSummaryEnsembleTools.h"
|
||||
|
||||
#include "Formations/RimWellFormationsFile.h"
|
||||
|
||||
#include "RiuContextMenuLauncher.h"
|
||||
#include "RiuGroupedBarChartBuilder.h"
|
||||
#include "RiuPlotItem.h"
|
||||
@@ -60,8 +62,14 @@ RimRftTornadoPlot::RimRftTornadoPlot()
|
||||
CAF_PDM_InitFieldNoDefault( &m_selectedTimeStep, "TimeStep", "Time Step" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_eclipseCase, "EclipseCase", "Eclipse Case (MD fallback)" );
|
||||
CAF_PDM_InitField( &m_useDepthRange, "UseDepthRange", false, "Filter by Depth Range" );
|
||||
CAF_PDM_InitField( &m_filterMode,
|
||||
"FilterMode",
|
||||
RimRftCrossPlotTools::DepthFilterModeEnum( RimRftCrossPlotTools::DepthFilterMode::DEPTH_RANGE ),
|
||||
"Filter By" );
|
||||
CAF_PDM_InitField( &m_depthRangeMin, "DepthRangeMin", 0.0, "Min Depth" );
|
||||
CAF_PDM_InitField( &m_depthRangeMax, "DepthRangeMax", 5000.0, "Max Depth" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_wellFormations, "WellFormations", "Well Formations File" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_selectedZones, "SelectedZones", "Zones" );
|
||||
CAF_PDM_InitField( &m_depthType, "DepthType", caf::AppEnum<RiaDefines::DepthType>( RiaDefines::DepthType::MEASURED_DEPTH ), "Depth Type" );
|
||||
m_depthType.uiCapability()->setUiHidden( true ); // driven by the parent RimRftCorrelationReportPlot
|
||||
|
||||
@@ -155,6 +163,30 @@ void RimRftTornadoPlot::setDepthType( RiaDefines::DepthType depthType )
|
||||
m_depthType = depthType;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimRftTornadoPlot::setFilterMode( RimRftCrossPlotTools::DepthFilterMode filterMode )
|
||||
{
|
||||
m_filterMode = filterMode;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimRftTornadoPlot::setWellFormations( RimWellFormationsFile* wellFormationsFile )
|
||||
{
|
||||
m_wellFormations = wellFormationsFile;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimRftTornadoPlot::setSelectedZones( const std::vector<QString>& zones )
|
||||
{
|
||||
m_selectedZones = zones;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -360,6 +392,21 @@ void RimRftTornadoPlot::onPlotItemSelected( std::shared_ptr<RiuPlotItem> plotIte
|
||||
if ( !paramName.isEmpty() && m_parameterSelectedCallback ) m_parameterSelectedCallback( paramName );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimRftCrossPlotTools::DepthInterval> RimRftTornadoPlot::depthIntervals() const
|
||||
{
|
||||
return RimRftCrossPlotTools::buildDepthIntervals( m_useDepthRange(),
|
||||
m_filterMode(),
|
||||
m_depthRangeMin(),
|
||||
m_depthRangeMax(),
|
||||
m_wellFormations(),
|
||||
m_wellName(),
|
||||
m_selectedZones(),
|
||||
m_depthType() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -376,9 +423,7 @@ std::map<QString, double> RimRftTornadoPlot::addDataToChartBuilder( RiuGroupedBa
|
||||
m_wellName(),
|
||||
m_selectedTimeStep(),
|
||||
m_eclipseCase(),
|
||||
m_useDepthRange(),
|
||||
m_depthRangeMin(),
|
||||
m_depthRangeMax(),
|
||||
depthIntervals(),
|
||||
m_depthType() );
|
||||
|
||||
// For each numeric parameter, compute Pearson correlation against pressurePerCase
|
||||
@@ -421,12 +466,14 @@ void RimRftTornadoPlot::updatePlotTitle()
|
||||
|
||||
if ( m_useAutoPlotTitle() && m_ensemble() )
|
||||
{
|
||||
const QString rangeStr = m_useDepthRange() ? QString( " [%1 %2 - %3 m]" )
|
||||
.arg( RimRftCrossPlotTools::depthTypeAbbreviation( m_depthType() ) )
|
||||
.arg( m_depthRangeMin() )
|
||||
.arg( m_depthRangeMax() )
|
||||
: QString();
|
||||
m_description = QString( "Parameter Correlation vs RFT Pressure%1, %2" ).arg( rangeStr ).arg( m_ensemble->name() );
|
||||
const QString filterDescription = RimRftCrossPlotTools::depthFilterDescription( m_useDepthRange(),
|
||||
m_filterMode(),
|
||||
m_depthType(),
|
||||
m_depthRangeMin(),
|
||||
m_depthRangeMax(),
|
||||
m_selectedZones() );
|
||||
const QString rangeStr = filterDescription.isEmpty() ? QString() : QString( " [%1]" ).arg( filterDescription );
|
||||
m_description = QString( "Parameter Correlation vs RFT Pressure%1, %2" ).arg( rangeStr ).arg( m_ensemble->name() );
|
||||
}
|
||||
|
||||
m_plotWidget->setPlotTitle( m_description() );
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "Appearance/RimFontSizeField.h"
|
||||
#include "RiaDefines.h"
|
||||
#include "RimRftCrossPlotTools.h"
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
#include "cafPdmField.h"
|
||||
@@ -35,6 +36,7 @@
|
||||
|
||||
class RimEclipseResultCase;
|
||||
class RimSummaryEnsemble;
|
||||
class RimWellFormationsFile;
|
||||
class RiuQwtPlotWidget;
|
||||
|
||||
//==================================================================================================
|
||||
@@ -63,6 +65,9 @@ public:
|
||||
void setUseDepthRange( bool useDepthRange );
|
||||
void setDepthRange( double minMd, double maxMd );
|
||||
void setDepthType( RiaDefines::DepthType depthType );
|
||||
void setFilterMode( RimRftCrossPlotTools::DepthFilterMode filterMode );
|
||||
void setWellFormations( RimWellFormationsFile* wellFormationsFile );
|
||||
void setSelectedZones( const std::vector<QString>& zones );
|
||||
void setSelectedParameter( const QString& paramName );
|
||||
|
||||
RiuQwtPlotWidget* viewer();
|
||||
@@ -94,16 +99,21 @@ private:
|
||||
void updatePlotTitle();
|
||||
void cleanupBeforeClose();
|
||||
|
||||
std::vector<RimRftCrossPlotTools::DepthInterval> depthIntervals() const;
|
||||
|
||||
private:
|
||||
// Data source inputs
|
||||
caf::PdmPtrField<RimSummaryEnsemble*> m_ensemble;
|
||||
caf::PdmField<QString> m_wellName;
|
||||
caf::PdmField<QDateTime> m_selectedTimeStep;
|
||||
caf::PdmPtrField<RimEclipseResultCase*> m_eclipseCase;
|
||||
caf::PdmField<bool> m_useDepthRange;
|
||||
caf::PdmField<double> m_depthRangeMin;
|
||||
caf::PdmField<double> m_depthRangeMax;
|
||||
caf::PdmField<caf::AppEnum<RiaDefines::DepthType>> m_depthType;
|
||||
caf::PdmPtrField<RimSummaryEnsemble*> m_ensemble;
|
||||
caf::PdmField<QString> m_wellName;
|
||||
caf::PdmField<QDateTime> m_selectedTimeStep;
|
||||
caf::PdmPtrField<RimEclipseResultCase*> m_eclipseCase;
|
||||
caf::PdmField<bool> m_useDepthRange;
|
||||
caf::PdmField<RimRftCrossPlotTools::DepthFilterModeEnum> m_filterMode;
|
||||
caf::PdmField<double> m_depthRangeMin;
|
||||
caf::PdmField<double> m_depthRangeMax;
|
||||
caf::PdmPtrField<RimWellFormationsFile*> m_wellFormations;
|
||||
caf::PdmField<std::vector<QString>> m_selectedZones;
|
||||
caf::PdmField<caf::AppEnum<RiaDefines::DepthType>> m_depthType;
|
||||
|
||||
// Tornado settings
|
||||
caf::PdmField<bool> m_showAbsoluteValues;
|
||||
|
||||
@@ -103,3 +103,109 @@ TEST( RimRftCrossPlotToolsTest, DepthTypeAbbreviation )
|
||||
EXPECT_EQ( QString( "MD" ), RimRftCrossPlotTools::depthTypeAbbreviation( RiaDefines::DepthType::MEASURED_DEPTH ) );
|
||||
EXPECT_EQ( QString( "TVD" ), RimRftCrossPlotTools::depthTypeAbbreviation( RiaDefines::DepthType::TRUE_VERTICAL_DEPTH ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Disabled filtering returns no intervals regardless of mode.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RimRftCrossPlotToolsTest, BuildDepthIntervals_DisabledReturnsEmpty )
|
||||
{
|
||||
auto intervals = RimRftCrossPlotTools::buildDepthIntervals( false,
|
||||
RimRftCrossPlotTools::DepthFilterMode::DEPTH_RANGE,
|
||||
1000.0,
|
||||
2000.0,
|
||||
nullptr,
|
||||
QString(),
|
||||
{},
|
||||
RiaDefines::DepthType::MEASURED_DEPTH );
|
||||
EXPECT_TRUE( intervals.empty() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Depth range mode produces a single interval matching the requested range.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RimRftCrossPlotToolsTest, BuildDepthIntervals_DepthRangeProducesSingleInterval )
|
||||
{
|
||||
auto intervals = RimRftCrossPlotTools::buildDepthIntervals( true,
|
||||
RimRftCrossPlotTools::DepthFilterMode::DEPTH_RANGE,
|
||||
1000.0,
|
||||
2000.0,
|
||||
nullptr,
|
||||
QString(),
|
||||
{},
|
||||
RiaDefines::DepthType::MEASURED_DEPTH );
|
||||
ASSERT_EQ( size_t( 1 ), intervals.size() );
|
||||
EXPECT_DOUBLE_EQ( 1000.0, intervals[0].top );
|
||||
EXPECT_DOUBLE_EQ( 2000.0, intervals[0].base );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Zones mode with no well formations file available produces no intervals.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RimRftCrossPlotToolsTest, BuildDepthIntervals_ZonesWithoutFileReturnsEmpty )
|
||||
{
|
||||
auto intervals = RimRftCrossPlotTools::buildDepthIntervals( true,
|
||||
RimRftCrossPlotTools::DepthFilterMode::ZONES,
|
||||
1000.0,
|
||||
2000.0,
|
||||
nullptr,
|
||||
"WELL-A",
|
||||
{ "ZoneA" },
|
||||
RiaDefines::DepthType::MEASURED_DEPTH );
|
||||
EXPECT_TRUE( intervals.empty() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// An empty interval list means no filtering, so all pressures pass through.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RimRftCrossPlotToolsTest, FilterPressuresByDepthIntervals_EmptyIntervalsReturnsAllSamples )
|
||||
{
|
||||
std::vector<double> depths{ 1000.0, 2000.0, 3000.0 };
|
||||
std::vector<double> pressures{ 10.0, 20.0, 30.0 };
|
||||
|
||||
auto filtered = RimRftCrossPlotTools::filterPressuresByDepthIntervals( depths, pressures, {} );
|
||||
|
||||
EXPECT_EQ( pressures, filtered );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Only samples within any of the given (possibly non-contiguous) intervals are returned.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RimRftCrossPlotToolsTest, FilterPressuresByDepthIntervals_FiltersByMultipleIntervals )
|
||||
{
|
||||
std::vector<double> depths{ 1000.0, 1500.0, 2000.0, 2500.0, 3000.0 };
|
||||
std::vector<double> pressures{ 10.0, 15.0, 20.0, 25.0, 30.0 };
|
||||
|
||||
std::vector<RimRftCrossPlotTools::DepthInterval> intervals{ { 1000.0, 1500.0 }, { 2800.0, 3200.0 } };
|
||||
auto filtered = RimRftCrossPlotTools::filterPressuresByDepthIntervals( depths, pressures, intervals );
|
||||
|
||||
std::vector<double> expected{ 10.0, 15.0, 30.0 };
|
||||
EXPECT_EQ( expected, filtered );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// A filter description is empty when filtering is disabled.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RimRftCrossPlotToolsTest, DepthFilterDescription_DisabledReturnsEmpty )
|
||||
{
|
||||
QString description = RimRftCrossPlotTools::depthFilterDescription( false,
|
||||
RimRftCrossPlotTools::DepthFilterMode::DEPTH_RANGE,
|
||||
RiaDefines::DepthType::MEASURED_DEPTH,
|
||||
1000.0,
|
||||
2000.0,
|
||||
{} );
|
||||
EXPECT_TRUE( description.isEmpty() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Zone mode description lists the selected zone names.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RimRftCrossPlotToolsTest, DepthFilterDescription_ZonesListsSelectedZoneNames )
|
||||
{
|
||||
QString description = RimRftCrossPlotTools::depthFilterDescription( true,
|
||||
RimRftCrossPlotTools::DepthFilterMode::ZONES,
|
||||
RiaDefines::DepthType::MEASURED_DEPTH,
|
||||
1000.0,
|
||||
2000.0,
|
||||
{ "Valysar", "Therys" } );
|
||||
EXPECT_EQ( QString( "Zones: Valysar, Therys" ), description );
|
||||
}
|
||||
Reference in new issue
Block a user