mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-26 07:00:17 -05:00
#14889: RFT Ensemble: Additional UI fixes
* #14889: Do not change main window when importing well picks * #14889: Fix clipped bottom of plots in dock windows * #14889: Add Create RFT Correlation Report to Ensemble Correlation Plots menu * #14889: Show imported observed FMU RFT data as table * #14889: Use time step from source RFT plot in RFT correlation report * #14889: Show observed data in RFT cross plot when no RFT samples are available * #14889: Keep RFT plot zoom when toggling formation in RFT correlation report * #14889: Do not change main window when importing formations * #14889: Use general delete for observed data and improve FMU RFT data name
This commit is contained in:
1 parent
fb566f112c
commit
c57864df51
36 files changed
+373
-319
No files matched your search
+24
-8
@@ -36,6 +36,8 @@
|
||||
#include "RimWellRftEnsembleCurveSet.h"
|
||||
#include "RimWellRftPlot.h"
|
||||
|
||||
#include "cafCmdFeatureMenuBuilder.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimCorrelationPlotCollection, "CorrelationPlotCollection" );
|
||||
|
||||
namespace
|
||||
@@ -211,12 +213,12 @@ RimRftCorrelationReportPlot* RimCorrelationPlotCollection::createRftCorrelationR
|
||||
{
|
||||
auto* report = new RimRftCorrelationReportPlot;
|
||||
report->dockAsPlotWindow();
|
||||
report->initializeFromSourcePlot( source );
|
||||
|
||||
if ( source )
|
||||
auto* rftPlot = report->wellRftPlot();
|
||||
if ( rftPlot )
|
||||
{
|
||||
report->initializeFromSourcePlot( source );
|
||||
|
||||
const auto ensembles = source->selectedEnsembles();
|
||||
const auto ensembles = rftPlot->selectedEnsembles();
|
||||
if ( !ensembles.empty() )
|
||||
{
|
||||
auto* ensemble = ensembles.front();
|
||||
@@ -229,7 +231,7 @@ RimRftCorrelationReportPlot* RimCorrelationPlotCollection::createRftCorrelationR
|
||||
{
|
||||
report->crossPlot()->setEnsembleParameter( param.name );
|
||||
|
||||
if ( auto* curveSet = report->wellRftPlot()->findEnsembleCurveSet( ensemble ) )
|
||||
if ( auto* curveSet = rftPlot->findEnsembleCurveSet( ensemble ) )
|
||||
{
|
||||
curveSet->setColorByEnsembleParameter( param.name );
|
||||
}
|
||||
@@ -237,7 +239,8 @@ RimRftCorrelationReportPlot* RimCorrelationPlotCollection::createRftCorrelationR
|
||||
}
|
||||
}
|
||||
}
|
||||
report->crossPlot()->setWellName( source->simWellOrWellPathName() );
|
||||
const QString wellName = rftPlot->simWellOrWellPathName();
|
||||
report->crossPlot()->setWellName( wellName );
|
||||
|
||||
// Default to filtering by formation when a formations file has data for the well
|
||||
if ( auto* project = RimProject::current();
|
||||
@@ -245,7 +248,7 @@ RimRftCorrelationReportPlot* RimCorrelationPlotCollection::createRftCorrelationR
|
||||
{
|
||||
for ( RimWellFormationsFile* file : project->activeOilField()->wellFormationsCollection()->wellFormationsFiles() )
|
||||
{
|
||||
if ( file->formationsForWell( source->simWellOrWellPathName() ) )
|
||||
if ( file->formationsForWell( wellName ) )
|
||||
{
|
||||
report->crossPlot()->setWellFormations( file );
|
||||
report->crossPlot()->setFilterMode( RimRftCrossPlotTools::DepthFilterMode::ZONES );
|
||||
@@ -254,7 +257,7 @@ RimRftCorrelationReportPlot* RimCorrelationPlotCollection::createRftCorrelationR
|
||||
}
|
||||
}
|
||||
|
||||
const auto timeSteps = source->selectedTimeSteps();
|
||||
const auto timeSteps = rftPlot->selectedTimeSteps();
|
||||
if ( !timeSteps.empty() ) report->crossPlot()->setTimeStep( timeSteps.front() );
|
||||
}
|
||||
|
||||
@@ -270,6 +273,19 @@ std::vector<RimRftCorrelationReportPlot*> RimCorrelationPlotCollection::rftRepor
|
||||
return m_rftCorrelationReports.childrenByType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimCorrelationPlotCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const
|
||||
{
|
||||
menuBuilder << "RicNewCorrelationPlotFeature";
|
||||
menuBuilder << "RicNewCorrelationMatrixPlotFeature";
|
||||
menuBuilder << "RicNewParameterResultCrossPlotFeature";
|
||||
menuBuilder << "RicNewCorrelationReportPlotFeature";
|
||||
menuBuilder.addSeparator();
|
||||
menuBuilder << "RicCreateRftCorrelationReportFeature";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -81,6 +81,8 @@ public:
|
||||
std::vector<RimRftCorrelationReportPlot*> rftReports() const;
|
||||
|
||||
private:
|
||||
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
|
||||
|
||||
void applyFirstEnsembleFieldAddressesToPlot( RimAbstractCorrelationPlot* plot, const std::vector<QString>& quantityNames = {} );
|
||||
void applyEnsembleFieldAndTimeStepToPlot( RimAbstractCorrelationPlot* plot,
|
||||
RimSummaryEnsemble* ensemble,
|
||||
|
||||
@@ -755,7 +755,6 @@ void RimParameterRftCrossPlot::createPoints()
|
||||
caf::ColorTable colorTable = RiaColorTables::categoryPaletteColors();
|
||||
|
||||
auto caseData = createCaseData();
|
||||
if ( caseData.empty() ) return;
|
||||
|
||||
std::set<RimSummaryCase*> selectedSummaryCases;
|
||||
auto selectedTreeViewItems = RiuDockWidgetTools::selectedItemsInTreeView( RiuDockWidgetTools::plotMainWindowDataSourceTreeName() );
|
||||
@@ -806,21 +805,14 @@ void RimParameterRftCrossPlot::createPoints()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimParameterRftCrossPlot::attachObservedPressure()
|
||||
{
|
||||
const auto observedPressures =
|
||||
RimRftCrossPlotTools::computeObservedPressures( m_wellName(),
|
||||
m_selectedTimeStep(),
|
||||
depthIntervals(),
|
||||
m_depthType(),
|
||||
RimRftCrossPlotTools::buildAllZoneIntervals( m_wellFormations(),
|
||||
m_wellName(),
|
||||
m_depthType() ) );
|
||||
if ( observedPressures.empty() ) return;
|
||||
const auto pressures = observedPressures();
|
||||
if ( pressures.empty() ) return;
|
||||
|
||||
auto attachLine = [this]( double value, Qt::PenStyle style, const QString& label, const QColor& color )
|
||||
{ RiuRftCorrelationPlotTools::attachHorizontalLine( m_plotWidget, value, style, label, color ); };
|
||||
|
||||
bool isFirst = true;
|
||||
for ( const auto& observed : observedPressures )
|
||||
for ( const auto& observed : pressures )
|
||||
{
|
||||
// Use the formation color when known; otherwise fall back to black lines and no shaded band
|
||||
std::optional<QColor> zoneColor;
|
||||
@@ -850,6 +842,20 @@ void RimParameterRftCrossPlot::attachObservedPressure()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Shared by drawing and range computation so the axis range matches the drawn zone averages
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimRftCrossPlotTools::ObservedPressure> RimParameterRftCrossPlot::observedPressures() const
|
||||
{
|
||||
return RimRftCrossPlotTools::computeObservedPressures( m_wellName(),
|
||||
m_selectedTimeStep(),
|
||||
depthIntervals(),
|
||||
m_depthType(),
|
||||
RimRftCrossPlotTools::buildAllZoneIntervals( m_wellFormations(),
|
||||
m_wellName(),
|
||||
m_depthType() ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -895,25 +901,35 @@ void RimParameterRftCrossPlot::updateValueRanges()
|
||||
yMax = std::max( yMax, pressureValue );
|
||||
}
|
||||
|
||||
for ( const auto& observed :
|
||||
RimRftCrossPlotTools::computeObservedPressures( m_wellName(), m_selectedTimeStep(), depthIntervals(), m_depthType() ) )
|
||||
for ( const auto& observed : observedPressures() )
|
||||
{
|
||||
yMin = std::min( yMin, observed.rangeMin );
|
||||
yMax = std::max( yMax, observed.rangeMax );
|
||||
}
|
||||
|
||||
if ( xMin == std::numeric_limits<double>::infinity() )
|
||||
// Without RFT samples, use the parameter range so the X axis does not keep the range of a previous time step
|
||||
if ( xMin == std::numeric_limits<double>::infinity() && m_ensemble() && !m_ensembleParameter().isEmpty() )
|
||||
{
|
||||
m_xValueRange = std::nullopt;
|
||||
m_yValueRange = std::nullopt;
|
||||
return;
|
||||
const RigEnsembleParameter parameter = m_ensemble->ensembleParameter( m_ensembleParameter );
|
||||
if ( parameter.isNumeric() && parameter.isValid() )
|
||||
{
|
||||
xMin = parameter.minValue;
|
||||
xMax = parameter.maxValue;
|
||||
}
|
||||
}
|
||||
|
||||
const double xRange = xMax - xMin;
|
||||
const double yRange = yMax - yMin;
|
||||
// Observed data is shown even when there are no RFT samples, so the ranges are computed independently
|
||||
auto paddedRange = []( double minValue, double maxValue ) -> std::optional<std::pair<double, double>>
|
||||
{
|
||||
if ( minValue == std::numeric_limits<double>::infinity() ) return std::nullopt;
|
||||
|
||||
m_xValueRange = std::make_pair( xMin - xRange * 0.1, xMax + xRange * 0.1 );
|
||||
m_yValueRange = std::make_pair( yMin - yRange * 0.1, yMax + yRange * 0.1 );
|
||||
const double range = maxValue - minValue;
|
||||
const double padding = range > 0.0 ? range * 0.1 : std::max( std::abs( minValue ) * 0.01, 1.0 );
|
||||
return std::make_pair( minValue - padding, maxValue + padding );
|
||||
};
|
||||
|
||||
m_xValueRange = paddedRange( xMin, xMax );
|
||||
m_yValueRange = paddedRange( yMin, yMax );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -132,7 +132,8 @@ private:
|
||||
void cleanupBeforeClose();
|
||||
RimSummaryCase* findClosestCase( const QPoint& canvasPos );
|
||||
|
||||
std::vector<RimRftCrossPlotTools::DepthInterval> depthIntervals() const;
|
||||
std::vector<RimRftCrossPlotTools::DepthInterval> depthIntervals() const;
|
||||
std::vector<RimRftCrossPlotTools::ObservedPressure> observedPressures() const;
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimSummaryEnsemble*> m_ensemble;
|
||||
|
||||
+16
-7
@@ -25,6 +25,7 @@
|
||||
#include "RimRftCrossPlotTools.h"
|
||||
#include "RimRftTornadoPlot.h"
|
||||
#include "RimWellLogTrack.h"
|
||||
#include "RimWellPlotTools.h"
|
||||
#include "RimWellRftEnsembleCurveSet.h"
|
||||
#include "RimWellRftPlot.h"
|
||||
|
||||
@@ -207,14 +208,13 @@ RimParameterRftCrossPlot* RimRftCorrelationReportPlot::crossPlot() const
|
||||
/// Initialize the owned RimWellRftPlot from the source plot's selected data sources.
|
||||
/// We keep the fresh (curve-free) child plot and call initializeDataSources(source) so
|
||||
/// syncCurvesFromUiSelection builds curves from scratch without touching unresolved copies.
|
||||
/// Without a source plot, the first well with ensemble RFT data is used with all available data sources.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimRftCorrelationReportPlot::initializeFromSourcePlot( RimWellRftPlot* source )
|
||||
{
|
||||
if ( !source ) return;
|
||||
|
||||
applyDepthTypeToSubPlots();
|
||||
|
||||
m_wellRftPlot->setSimWellOrWellPathName( source->simWellOrWellPathName() );
|
||||
m_wellRftPlot->setSimWellOrWellPathName( source ? source->simWellOrWellPathName() : RimWellPlotTools::firstWellNameWithEnsembleRftData() );
|
||||
|
||||
// A fresh RimWellRftPlot has no tracks; syncCurvesFromUiSelection exits early without one.
|
||||
// Guard against duplicate track creation if this is called more than once.
|
||||
@@ -227,10 +227,14 @@ void RimRftCorrelationReportPlot::initializeFromSourcePlot( RimWellRftPlot* sour
|
||||
|
||||
m_wellRftPlot->initializeDataSources( source );
|
||||
|
||||
// The correlation report operates on a single time step; trim any extras that
|
||||
// initializeDataSources may have preselected when only a few were available.
|
||||
// The correlation report operates on a single time step; prefer the time step selected in the
|
||||
// source plot, and trim any extras that initializeDataSources may have preselected.
|
||||
auto selectedTimeSteps = m_wellRftPlot->selectedTimeSteps();
|
||||
if ( selectedTimeSteps.size() > 1 )
|
||||
if ( source && !source->selectedTimeSteps().empty() )
|
||||
{
|
||||
m_wellRftPlot->setSelectedTimeSteps( { source->selectedTimeSteps().front() } );
|
||||
}
|
||||
else if ( selectedTimeSteps.size() > 1 )
|
||||
{
|
||||
m_wellRftPlot->setSelectedTimeSteps( { selectedTimeSteps.front() } );
|
||||
}
|
||||
@@ -706,7 +710,12 @@ void RimRftCorrelationReportPlot::onRftTrackDepthClicked( RimWellLogTrack* track
|
||||
|
||||
m_parameterRftCrossPlot->setFilterMode( RimRftCrossPlotTools::DepthFilterMode::ZONES );
|
||||
m_parameterRftCrossPlot->setSelectedZones( zones );
|
||||
loadDataAndUpdate();
|
||||
|
||||
// The zone filter does not affect the RFT curves; skip reloading the RFT plot to keep its zoom
|
||||
updateSelectedZoneHighlight();
|
||||
syncTornadoInputsFromCrossPlot();
|
||||
m_tornadoPlot->loadDataAndUpdate();
|
||||
m_parameterRftCrossPlot->loadDataAndUpdate();
|
||||
updateConnectedEditors();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user