mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-31 17:17:50 -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
@@ -3,7 +3,6 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCloseCaseFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCloseSummaryCaseFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCloseSummaryCaseInCollectionFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCloseObservedDataFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewViewFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewGenericDataViewFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewContourMapViewFeature.cpp
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017- Statoil ASA
|
||||
//
|
||||
// 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 "RicCloseObservedDataFeature.h"
|
||||
|
||||
#include "Summary/RiaSummaryTools.h"
|
||||
|
||||
#include "RimMainPlotCollection.h"
|
||||
#include "RimObservedDataCollection.h"
|
||||
#include "RimObservedFmuRftData.h"
|
||||
#include "RimObservedSummaryData.h"
|
||||
#include "RimRftPlotCollection.h"
|
||||
#include "RimSummaryMultiPlot.h"
|
||||
#include "RimSummaryMultiPlotCollection.h"
|
||||
#include "RimSummaryPlot.h"
|
||||
#include "RimWellRftPlot.h"
|
||||
|
||||
#include "cafSelectionManager.h"
|
||||
|
||||
#include "cafAssert.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
CAF_CMD_SOURCE_INIT( RicCloseObservedDataFeature, "RicCloseObservedDataFeature" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicCloseObservedDataFeature::setupActionLook( QAction* actionToSetup )
|
||||
{
|
||||
actionToSetup->setText( "Close" );
|
||||
actionToSetup->setIcon( QIcon( ":/Close.svg" ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicCloseObservedDataFeature::deleteObservedSummaryData( const std::vector<RimObservedSummaryData*>& data )
|
||||
{
|
||||
RimSummaryMultiPlotCollection* summaryPlotColl = RiaSummaryTools::summaryMultiPlotCollection();
|
||||
|
||||
for ( RimObservedSummaryData* observedData : data )
|
||||
{
|
||||
for ( RimSummaryMultiPlot* multiPlot : summaryPlotColl->multiPlots() )
|
||||
{
|
||||
for ( RimSummaryPlot* summaryPlot : multiPlot->summaryPlots() )
|
||||
{
|
||||
summaryPlot->deleteCurvesAssosiatedWithCases( { observedData } );
|
||||
}
|
||||
multiPlot->updateConnectedEditors();
|
||||
}
|
||||
|
||||
RimObservedDataCollection* observedDataCollection = observedData->firstAncestorOrThisOfTypeAsserted<RimObservedDataCollection>();
|
||||
|
||||
observedDataCollection->removeObservedSummaryData( observedData );
|
||||
delete observedData;
|
||||
observedDataCollection->updateConnectedEditors();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicCloseObservedDataFeature::deleteObservedRmuRftData( const std::vector<RimObservedFmuRftData*>& data )
|
||||
{
|
||||
RimRftPlotCollection* rftPlotColl = RimMainPlotCollection::current()->rftPlotCollection();
|
||||
|
||||
for ( RimObservedFmuRftData* observedData : data )
|
||||
{
|
||||
RimObservedDataCollection* observedDataCollection = observedData->firstAncestorOrThisOfTypeAsserted<RimObservedDataCollection>();
|
||||
|
||||
for ( RimWellRftPlot* plot : rftPlotColl->rftPlots() )
|
||||
{
|
||||
plot->deleteCurvesAssosicatedWithObservedData( observedData );
|
||||
}
|
||||
observedDataCollection->removeObservedFmuRftData( observedData );
|
||||
delete observedData;
|
||||
observedDataCollection->updateConnectedEditors();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicCloseObservedDataFeature::isCommandEnabled() const
|
||||
{
|
||||
const auto summarySelection = caf::SelectionManager::instance()->objectsByType<RimObservedSummaryData>();
|
||||
const auto fmuRftSelection = caf::SelectionManager::instance()->objectsByType<RimObservedFmuRftData>();
|
||||
|
||||
if ( summarySelection.empty() && fmuRftSelection.empty() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for ( RimObservedSummaryData* data : summarySelection )
|
||||
{
|
||||
if ( !data->isObservedData() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicCloseObservedDataFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
const auto summarySelection = caf::SelectionManager::instance()->objectsByType<RimObservedSummaryData>();
|
||||
const auto fmuRftSelection = caf::SelectionManager::instance()->objectsByType<RimObservedFmuRftData>();
|
||||
|
||||
CAF_ASSERT( !( summarySelection.empty() && fmuRftSelection.empty() ) );
|
||||
|
||||
RicCloseObservedDataFeature::deleteObservedSummaryData( summarySelection );
|
||||
RicCloseObservedDataFeature::deleteObservedRmuRftData( fmuRftSelection );
|
||||
}
|
||||
@@ -19,14 +19,15 @@
|
||||
#include "RicImportWellFormationsFeature.h"
|
||||
|
||||
#include "RiaApplication.h"
|
||||
#include "RiaGuiApplication.h"
|
||||
|
||||
#include "Formations/RimWellFormationsCollection.h"
|
||||
#include "Formations/RimWellFormationsFile.h"
|
||||
#include "RimOilField.h"
|
||||
#include "RimProject.h"
|
||||
|
||||
#include "Riu3DMainWindowTools.h"
|
||||
#include "RiuFileDialogTools.h"
|
||||
#include "RiuPlotMainWindowTools.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QFileInfo>
|
||||
@@ -41,7 +42,9 @@ void RicImportWellFormationsFeature::onActionTriggered( bool isChecked )
|
||||
std::vector<RimWellFormationsFile*> importedFiles = importFilesWithDialog();
|
||||
if ( !importedFiles.empty() )
|
||||
{
|
||||
Riu3DMainWindowTools::selectAsCurrentItem( importedFiles.back() );
|
||||
// Well formations are shown in the plot window data sources tree
|
||||
RiuPlotMainWindowTools::onObjectAppended( importedFiles.back(),
|
||||
importedFiles.back()->firstAncestorOrThisOfType<RimWellFormationsCollection>() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +55,7 @@ std::vector<RimWellFormationsFile*> RicImportWellFormationsFeature::importFilesW
|
||||
{
|
||||
RiaApplication* app = RiaApplication::instance();
|
||||
QString defaultDir = app->lastUsedDialogDirectory( "WELLPATHFORMATIONS_DIR" );
|
||||
QStringList filePaths = RiuFileDialogTools::getOpenFileNames( Riu3DMainWindowTools::mainWindowWidget(),
|
||||
QStringList filePaths = RiuFileDialogTools::getOpenFileNames( RiaGuiApplication::widgetToUseAsParent(),
|
||||
"Import Well Formations",
|
||||
defaultDir,
|
||||
"Well Formations (*.csv);;All Files (*.*)" );
|
||||
|
||||
+10
-2
@@ -21,6 +21,7 @@
|
||||
#include "RimCorrelationPlotCollection.h"
|
||||
#include "RimMainPlotCollection.h"
|
||||
#include "RimRftCorrelationReportPlot.h"
|
||||
#include "RimWellPlotTools.h"
|
||||
#include "RimWellRftPlot.h"
|
||||
|
||||
#include "RiuPlotMainWindowTools.h"
|
||||
@@ -36,7 +37,14 @@ CAF_CMD_SOURCE_INIT( RicCreateRftCorrelationReportFeature, "RicCreateRftCorrelat
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicCreateRftCorrelationReportFeature::isCommandEnabled() const
|
||||
{
|
||||
return dynamic_cast<RimWellRftPlot*>( caf::SelectionManager::instance()->selectedItem() ) != nullptr;
|
||||
if ( dynamic_cast<RimWellRftPlot*>( caf::SelectionManager::instance()->selectedItem() ) ) return true;
|
||||
|
||||
if ( dynamic_cast<RimCorrelationPlotCollection*>( caf::SelectionManager::instance()->selectedItem() ) )
|
||||
{
|
||||
return !RimWellPlotTools::firstWellNameWithEnsembleRftData().isEmpty();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -44,8 +52,8 @@ bool RicCreateRftCorrelationReportFeature::isCommandEnabled() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicCreateRftCorrelationReportFeature::onActionTriggered( bool /*isChecked*/ )
|
||||
{
|
||||
// Without a source plot, a default report is created for the first available ensemble RFT data
|
||||
auto* sourcePlot = dynamic_cast<RimWellRftPlot*>( caf::SelectionManager::instance()->selectedItem() );
|
||||
if ( !sourcePlot ) return;
|
||||
|
||||
auto* correlationColl = RimMainPlotCollection::current()->correlationPlotCollection();
|
||||
if ( !correlationColl ) return;
|
||||
|
||||
@@ -145,10 +145,9 @@ std::vector<RimWellPath*> RicImportWellPaths::importWellPaths( const QStringList
|
||||
{
|
||||
RicNewGenericDataViewFeature::createInitialViewIfNeeded();
|
||||
|
||||
RimWellPath* wellPath = oilField->wellPathCollection->mostRecentlyUpdatedWellPath();
|
||||
if ( wellPath )
|
||||
if ( !wellPaths.empty() && wellPaths.back() )
|
||||
{
|
||||
Riu3DMainWindowTools::selectAsCurrentItem( wellPath );
|
||||
Riu3DMainWindowTools::selectAsCurrentItem( wellPaths.back() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-16
@@ -21,10 +21,7 @@
|
||||
#include "RiaApplication.h"
|
||||
|
||||
#include "RimMainPlotCollection.h"
|
||||
#include "RimOilField.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "RimWellPathCollection.h"
|
||||
|
||||
#include "Riu3DMainWindowTools.h"
|
||||
#include "RiuFileDialogTools.h"
|
||||
@@ -60,19 +57,6 @@ void RicWellPathFormationsImportFileFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
project->scheduleCreateDisplayModelAndRedrawAllViews();
|
||||
RimMainPlotCollection::current()->updatePlotsWithFormations();
|
||||
|
||||
RimOilField* oilField = project->activeOilField();
|
||||
|
||||
if ( !oilField ) return;
|
||||
|
||||
if ( !oilField->wellPathCollection->allWellPaths().empty() )
|
||||
{
|
||||
RimWellPath* wellPath = oilField->wellPathCollection->mostRecentlyUpdatedWellPath();
|
||||
if ( wellPath )
|
||||
{
|
||||
Riu3DMainWindowTools::selectAsCurrentItem( wellPath );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -284,6 +284,27 @@ void RifReaderFmuRft::importData()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RifReaderFmuRft::csvText() const
|
||||
{
|
||||
QString text;
|
||||
QTextStream stream( &text );
|
||||
|
||||
stream << "WELL,DATE,MEASUREMENT_ID,UTM_X,UTM_Y,MD,TVD,ZONE,PRESSURE,PRESSURE_ERROR\n";
|
||||
for ( const auto& obs : m_observations )
|
||||
{
|
||||
stream << obs.wellDate.wellName << "," << obs.wellDate.dateTime.toString( "yyyy-MM-dd" ) << "," << obs.wellDate.measurementId << ","
|
||||
<< QString::number( obs.location.utmx, 'f', 2 ) << "," << QString::number( obs.location.utmy, 'f', 2 ) << ","
|
||||
<< QString::number( obs.location.mdrkb, 'f', 2 ) << "," << QString::number( obs.location.tvdmsl, 'f', 2 ) << ","
|
||||
<< obs.location.formation << "," << QString::number( obs.pressure, 'f', 2 ) << ","
|
||||
<< QString::number( obs.pressureError, 'f', 2 ) << "\n";
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -81,6 +81,9 @@ public:
|
||||
|
||||
void importData();
|
||||
|
||||
// Imported observations as comma separated text with a header row
|
||||
QString csvText() const;
|
||||
|
||||
private:
|
||||
static std::vector<WellDate> importWellDates( const QString& fileName );
|
||||
static std::vector<Location> importLocations( const QString& fileName );
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
@@ -490,6 +490,27 @@ std::vector<RimSummaryEnsemble*> rftEnsembles()
|
||||
return rftEnsembles;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Stops at the first realization with RFT data, as querying the RFT reader of every realization is expensive
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString firstWellNameWithEnsembleRftData()
|
||||
{
|
||||
for ( RimSummaryEnsemble* ensemble : RimProject::current()->summaryEnsembles() )
|
||||
{
|
||||
if ( !ensemble || !ensemble->isEnsemble() ) continue;
|
||||
|
||||
for ( RimSummaryCase* summaryCase : ensemble->allSummaryCases() )
|
||||
{
|
||||
auto reader = summaryCase->rftReader();
|
||||
if ( !reader ) continue;
|
||||
|
||||
const auto wellNames = reader->wellNames();
|
||||
if ( !wellNames.empty() ) return *wellNames.begin();
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -85,6 +85,7 @@ std::vector<RimEclipseResultCase*> gridCasesForWell( const QString& simWellName
|
||||
std::vector<RimEclipseResultCase*> rftCasesForWell( const QString& simWellName );
|
||||
std::vector<RimSummaryEnsemble*> rftEnsemblesForWell( const QString& simWellName );
|
||||
std::vector<RimSummaryEnsemble*> rftEnsembles();
|
||||
QString firstWellNameWithEnsembleRftData();
|
||||
std::vector<RimObservedFmuRftData*> observedFmuRftDataForWell( const QString& simWellName );
|
||||
std::vector<RimObservedFmuRftData*> observedFmuRftData();
|
||||
QString simWellName( const QString& wellPathNameOrSimWellName );
|
||||
|
||||
@@ -946,30 +946,6 @@ const char* RimWellRftPlot::plotNameFormatString()
|
||||
return PLOT_NAME_QFORMAT_STRING;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellRftPlot::deleteCurvesAssosicatedWithObservedData( const RimObservedFmuRftData* observedFmuRftData )
|
||||
{
|
||||
for ( auto plot : plots() )
|
||||
{
|
||||
RimWellLogTrack* const track = dynamic_cast<RimWellLogTrack*>( plot );
|
||||
if ( track )
|
||||
{
|
||||
auto curves = track->curves();
|
||||
for ( auto curve : curves )
|
||||
{
|
||||
RimWellLogRftCurve* rftCurve = dynamic_cast<RimWellLogRftCurve*>( curve );
|
||||
if ( rftCurve && rftCurve->observedFmuRftData() == observedFmuRftData )
|
||||
{
|
||||
track->removeCurve( rftCurve );
|
||||
delete rftCurve;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -93,8 +93,6 @@ public:
|
||||
|
||||
static const char* plotNameFormatString();
|
||||
|
||||
void deleteCurvesAssosicatedWithObservedData( const RimObservedFmuRftData* observedFmuRftData );
|
||||
|
||||
bool showErrorBarsForObservedData() const;
|
||||
void onLegendDefinitionChanged();
|
||||
|
||||
|
||||
@@ -19,14 +19,13 @@
|
||||
#include "RimWellFormationsFile.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
#include "RifCsvHtmlTableTools.h"
|
||||
|
||||
#include "RimMainPlotCollection.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimWellPath.h"
|
||||
#include "Tools/RimCsvPreviewTools.h"
|
||||
|
||||
#include "cafPdmUiFilePathEditor.h"
|
||||
#include "cafPdmUiTextEditor.h"
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
@@ -44,10 +43,7 @@ RimWellFormationsFile::RimWellFormationsFile()
|
||||
m_filePath.uiCapability()->setUiEditorTypeName( caf::PdmUiFilePathEditor::uiEditorTypeName() );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_contentTable, "ContentTable", "Content" );
|
||||
m_contentTable.uiCapability()->setUiEditorTypeName( caf::PdmUiTextEditor::uiEditorTypeName() );
|
||||
m_contentTable.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosition::HIDDEN );
|
||||
m_contentTable.uiCapability()->setUiReadOnly( true );
|
||||
m_contentTable.xmlCapability()->disableIO();
|
||||
RimCsvPreviewTools::initPreviewField( m_contentTable );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
@@ -223,12 +219,7 @@ void RimWellFormationsFile::defineEditorAttribute( const caf::PdmFieldHandle* fi
|
||||
{
|
||||
if ( field == &m_contentTable )
|
||||
{
|
||||
auto myAttr = dynamic_cast<caf::PdmUiTextEditorAttribute*>( attribute );
|
||||
if ( myAttr )
|
||||
{
|
||||
myAttr->wrapMode = caf::PdmUiTextEditorAttribute::NoWrap;
|
||||
myAttr->textMode = caf::PdmUiTextEditorAttribute::HTML;
|
||||
}
|
||||
RimCsvPreviewTools::setPreviewEditorAttribute( attribute );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,15 +250,5 @@ void RimWellFormationsFile::updateUiTreeName()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellFormationsFile::updateContentTable()
|
||||
{
|
||||
const int maxRowCount = 1000;
|
||||
|
||||
auto result = RifCsvHtmlTableTools::generateHtmlTableFromFile( filePath(), maxRowCount );
|
||||
if ( result )
|
||||
{
|
||||
m_contentTable = *result;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_contentTable = result.error();
|
||||
}
|
||||
m_contentTable = RimCsvPreviewTools::htmlTableFromFile( filePath() );
|
||||
}
|
||||
@@ -49,7 +49,6 @@
|
||||
#include "RimColorLegendItem.h"
|
||||
#include "RimCorrelationMatrixPlot.h"
|
||||
#include "RimCorrelationPlot.h"
|
||||
#include "RimCorrelationPlotCollection.h"
|
||||
#include "RimCustomObjectiveFunction.h"
|
||||
#include "RimCustomObjectiveFunctionCollection.h"
|
||||
#include "RimEclipseCase.h"
|
||||
@@ -603,13 +602,6 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
|
||||
menuBuilder << "RicNewAnalysisPlotFeature";
|
||||
menuBuilder << "RicNewPlotDataFilterFeature";
|
||||
}
|
||||
else if ( dynamic_cast<RimCorrelationPlotCollection*>( firstUiItem ) )
|
||||
{
|
||||
menuBuilder << "RicNewCorrelationPlotFeature";
|
||||
menuBuilder << "RicNewCorrelationMatrixPlotFeature";
|
||||
menuBuilder << "RicNewParameterResultCrossPlotFeature";
|
||||
menuBuilder << "RicNewCorrelationReportPlotFeature";
|
||||
}
|
||||
else if ( dynamic_cast<RimCorrelationPlot*>( firstUiItem ) )
|
||||
{
|
||||
menuBuilder << "RicNewCorrelationPlotFeature";
|
||||
@@ -1072,7 +1064,6 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
|
||||
menuBuilder << "RicCloseSummaryCaseFeature";
|
||||
menuBuilder << "RicCloseSummaryCaseInCollectionFeature";
|
||||
menuBuilder << "RicDeleteSummaryCaseCollectionFeature";
|
||||
menuBuilder << "RicCloseObservedDataFeature";
|
||||
menuBuilder << "RicDeleteSubPlotFeature";
|
||||
|
||||
menuBuilder << "RicNewMultiPlotFeature";
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "RimObservedEclipseUserData.h"
|
||||
#include "RimObservedFmuRftData.h"
|
||||
#include "RimObservedSummaryData.h"
|
||||
#include "RimPlotCurve.h"
|
||||
#include "RimPressureDepthData.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimSummaryObservedDataFile.h"
|
||||
@@ -42,7 +43,9 @@
|
||||
#include "cafPdmUiPropertyViewDialog.h"
|
||||
#include "cafUtils.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QSet>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimObservedDataCollection, "ObservedDataCollection" );
|
||||
|
||||
@@ -58,24 +61,6 @@ RimObservedDataCollection::RimObservedDataCollection()
|
||||
CAF_PDM_InitFieldNoDefault( &m_observedPressureDepthArray, "PressureDepthDataArray", "" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimObservedDataCollection::removeObservedSummaryData( RimObservedSummaryData* observedData )
|
||||
{
|
||||
m_observedDataArray.removeChild( observedData );
|
||||
caf::PdmUiObjectEditorHandle::updateUiAllObjectEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimObservedDataCollection::removeObservedFmuRftData( RimObservedFmuRftData* observedFmuRftData )
|
||||
{
|
||||
m_observedFmuRftArray.removeChild( observedFmuRftData );
|
||||
caf::PdmUiObjectEditorHandle::updateUiAllObjectEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -105,6 +90,16 @@ std::vector<RimPressureDepthData*> RimObservedDataCollection::allPressureDepthDa
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimObservedDataCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects )
|
||||
{
|
||||
// Delete curves that referenced the deleted observed data
|
||||
std::set<caf::PdmObjectHandle*> uniqueReferringObjects( referringObjects.begin(), referringObjects.end() );
|
||||
for ( caf::PdmObjectHandle* obj : uniqueReferringObjects )
|
||||
{
|
||||
if ( auto curve = dynamic_cast<RimPlotCurve*>( obj ) )
|
||||
{
|
||||
curve->deleteIfDataSourceIsMissing();
|
||||
}
|
||||
}
|
||||
|
||||
RimMainPlotCollection::current()->loadDataAndUpdateAllPlots();
|
||||
}
|
||||
|
||||
@@ -240,7 +235,23 @@ RimObservedSummaryData* RimObservedDataCollection::createAndAddCvsObservedSummar
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimObservedFmuRftData* RimObservedDataCollection::createAndAddFmuRftDataFromPath( const QString& directoryPath )
|
||||
{
|
||||
QString name = QString( "Imported FMU RFT Data %1" ).arg( m_observedFmuRftArray.size() + 1 );
|
||||
// The data folder is often named e.g. "rft", so include the parent folder to make the name descriptive
|
||||
const QDir dir( directoryPath );
|
||||
QStringList pathParts = QDir::cleanPath( dir.absolutePath() ).split( '/', Qt::SkipEmptyParts );
|
||||
QString baseName = pathParts.size() >= 2 ? pathParts.mid( pathParts.size() - 2 ).join( '/' ) : dir.dirName();
|
||||
if ( baseName.isEmpty() ) baseName = "Observed FMU Data";
|
||||
|
||||
QSet<QString> existingNames;
|
||||
for ( const auto& existing : m_observedFmuRftArray )
|
||||
{
|
||||
existingNames.insert( existing->name() );
|
||||
}
|
||||
|
||||
QString name = baseName;
|
||||
for ( int i = 2; existingNames.contains( name ); ++i )
|
||||
{
|
||||
name = QString( "%1 (%2)" ).arg( baseName ).arg( i );
|
||||
}
|
||||
|
||||
RimObservedFmuRftData* fmuRftData = new RimObservedFmuRftData;
|
||||
fmuRftData->setDirectoryPath( directoryPath );
|
||||
|
||||
@@ -35,8 +35,6 @@ class RimObservedDataCollection : public caf::PdmObject
|
||||
public:
|
||||
RimObservedDataCollection();
|
||||
|
||||
void removeObservedSummaryData( RimObservedSummaryData* observedSummaryData );
|
||||
void removeObservedFmuRftData( RimObservedFmuRftData* observedFmuRftData );
|
||||
RimObservedSummaryData* createAndAddRsmObservedSummaryDataFromFile( const QString& fileName, QString* errorText = nullptr );
|
||||
RimObservedSummaryData*
|
||||
createAndAddCvsObservedSummaryDataFromFile( const QString& fileName, bool useSavedFieldsValuesInDialog, QString* errorText = nullptr );
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#include "RimObservedFmuRftData.h"
|
||||
|
||||
#include "Tools/RimCsvPreviewTools.h"
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
@@ -30,6 +32,7 @@ CAF_PDM_SOURCE_INIT( RimObservedFmuRftData, "ObservedFmuRftData" );
|
||||
RimObservedFmuRftData::RimObservedFmuRftData()
|
||||
{
|
||||
CAF_PDM_InitObject( "Observed FMU Data", ":/ObservedRFTDataFile16x16.png" );
|
||||
setDeletable( true );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_directoryPath, "ObservedFolder", "Directory" );
|
||||
m_directoryPath.uiCapability()->setUiReadOnly( true );
|
||||
@@ -38,9 +41,8 @@ RimObservedFmuRftData::RimObservedFmuRftData()
|
||||
m_directoryPath_OBSOLETE.uiCapability()->setUiReadOnly( true );
|
||||
m_directoryPath_OBSOLETE.xmlCapability()->setIOWritable( false );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_wells, "Wells", "Wells" );
|
||||
m_wells.uiCapability()->setUiReadOnly( true );
|
||||
m_wells.registerGetMethod( this, &RimObservedFmuRftData::wells );
|
||||
CAF_PDM_InitFieldNoDefault( &m_contentTable, "ContentTable", "Content" );
|
||||
RimCsvPreviewTools::initPreviewField( m_contentTable );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -58,6 +60,7 @@ void RimObservedFmuRftData::createRftReaderInterface()
|
||||
{
|
||||
m_fmuRftReader = std::make_unique<RifReaderFmuRft>( m_directoryPath().path() );
|
||||
m_fmuRftReader->importData();
|
||||
m_contentTable = "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -124,3 +127,38 @@ void RimObservedFmuRftData::initAfterRead()
|
||||
m_directoryPath = m_directoryPath_OBSOLETE();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimObservedFmuRftData::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
// Built on demand, as the table is only needed when the data is shown in the property editor
|
||||
if ( m_contentTable().isEmpty() ) updateContentTable();
|
||||
|
||||
uiOrdering.add( nameField() );
|
||||
uiOrdering.add( &m_directoryPath );
|
||||
uiOrdering.add( &m_contentTable );
|
||||
uiOrdering.skipRemainingFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimObservedFmuRftData::defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
|
||||
{
|
||||
if ( field == &m_contentTable )
|
||||
{
|
||||
RimCsvPreviewTools::setPreviewEditorAttribute( attribute );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimObservedFmuRftData::updateContentTable()
|
||||
{
|
||||
if ( !rftReader() ) return;
|
||||
|
||||
m_contentTable = RimCsvPreviewTools::htmlTableFromText( m_fmuRftReader->csvText() );
|
||||
}
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmProxyValueField.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -45,11 +44,16 @@ public:
|
||||
|
||||
protected:
|
||||
void initAfterRead() override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
|
||||
|
||||
private:
|
||||
void updateContentTable();
|
||||
|
||||
private:
|
||||
std::unique_ptr<RifReaderFmuRft> m_fmuRftReader;
|
||||
|
||||
caf::PdmField<caf::FilePath> m_directoryPath;
|
||||
caf::PdmField<QString> m_directoryPath_OBSOLETE;
|
||||
caf::PdmProxyValueField<std::vector<QString>> m_wells;
|
||||
caf::PdmField<caf::FilePath> m_directoryPath;
|
||||
caf::PdmField<QString> m_directoryPath_OBSOLETE;
|
||||
caf::PdmField<QString> m_contentTable;
|
||||
};
|
||||
@@ -1241,6 +1241,14 @@ void RimPlotCurve::deletePlotCurve()
|
||||
m_plotCurve = nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimPlotCurve::deleteIfDataSourceIsMissing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -133,11 +133,14 @@ public:
|
||||
void setParentPlotNoReplot( RiuPlotWidget* );
|
||||
void setParentPlotAndReplot( RiuPlotWidget* );
|
||||
|
||||
void attach( RiuPlotWidget* );
|
||||
void detach( bool deletePlotCurve = false );
|
||||
void reattach( bool updateParentPlot = true );
|
||||
bool isSameCurve( const RiuPlotCurve* plotCurve ) const;
|
||||
void deletePlotCurve();
|
||||
void attach( RiuPlotWidget* );
|
||||
void detach( bool deletePlotCurve = false );
|
||||
void reattach( bool updateParentPlot = true );
|
||||
bool isSameCurve( const RiuPlotCurve* plotCurve ) const;
|
||||
void deletePlotCurve();
|
||||
|
||||
// Deletes this curve if its data source is missing. Returns true if deleted; the object must not be accessed afterwards.
|
||||
virtual bool deleteIfDataSourceIsMissing();
|
||||
RiuPlotCurve* plotCurve() const;
|
||||
|
||||
std::vector<RimPlotRectAnnotation*> rectAnnotations() const;
|
||||
|
||||
@@ -33,6 +33,7 @@ CAF_PDM_ABSTRACT_SOURCE_INIT( RimObservedSummaryData, "ObservedData" );
|
||||
RimObservedSummaryData::RimObservedSummaryData()
|
||||
{
|
||||
m_isObservedData = true;
|
||||
setDeletable( true );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_importedSummaryData, "ImportedSummaryData", "Imported Summary Data" );
|
||||
m_importedSummaryData.uiCapability()->setUiEditorTypeName( caf::PdmUiTextEditor::uiEditorTypeName() );
|
||||
|
||||
@@ -1398,6 +1398,21 @@ void RimSummaryCurve::updateTimeAnnotations()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimSummaryCurve::deleteIfDataSourceIsMissing()
|
||||
{
|
||||
const bool isXCaseMissing = m_xAxisType() == RiaDefines::HorizontalAxisType::SUMMARY_VECTOR && !m_xValuesSummaryCase();
|
||||
if ( m_yValuesSummaryCase() && !isXCaseMissing ) return false;
|
||||
|
||||
auto summaryPlot = firstAncestorOrThisOfType<RimSummaryPlot>();
|
||||
if ( !summaryPlot ) return false;
|
||||
|
||||
summaryPlot->deleteCurves( { this } );
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -108,6 +108,8 @@ public:
|
||||
virtual bool isRegressionCurve() const;
|
||||
void updateLegendEntryVisibilityNoPlotUpdate() override;
|
||||
|
||||
bool deleteIfDataSourceIsMissing() override;
|
||||
|
||||
protected:
|
||||
// RimPlotCurve overrides
|
||||
QString createCurveAutoName() override;
|
||||
|
||||
@@ -3,6 +3,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimPlotAxisTools.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimAutomationSettings.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEclipseViewTools.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimCsvPreviewTools.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES})
|
||||
@@ -0,0 +1,66 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2026- Equinor ASA
|
||||
//
|
||||
// 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 "RimCsvPreviewTools.h"
|
||||
|
||||
#include "RifCsvHtmlTableTools.h"
|
||||
|
||||
#include "cafPdmUiFieldHandle.h"
|
||||
#include "cafPdmUiTextEditor.h"
|
||||
#include "cafPdmXmlFieldHandle.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimCsvPreviewTools::initPreviewField( caf::PdmField<QString>& field )
|
||||
{
|
||||
field.uiCapability()->setUiEditorTypeName( caf::PdmUiTextEditor::uiEditorTypeName() );
|
||||
field.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::LabelPosition::HIDDEN );
|
||||
field.uiCapability()->setUiReadOnly( true );
|
||||
field.xmlCapability()->disableIO();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimCsvPreviewTools::setPreviewEditorAttribute( caf::PdmUiEditorAttribute* attribute )
|
||||
{
|
||||
if ( auto myAttr = dynamic_cast<caf::PdmUiTextEditorAttribute*>( attribute ) )
|
||||
{
|
||||
myAttr->wrapMode = caf::PdmUiTextEditorAttribute::NoWrap;
|
||||
myAttr->textMode = caf::PdmUiTextEditorAttribute::HTML;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimCsvPreviewTools::htmlTableFromText( const QString& csvText, int maxRowCount )
|
||||
{
|
||||
auto result = RifCsvHtmlTableTools::generateHtmlTableFromText( csvText, maxRowCount );
|
||||
return result ? *result : result.error();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimCsvPreviewTools::htmlTableFromFile( const QString& filePath, int maxRowCount )
|
||||
{
|
||||
auto result = RifCsvHtmlTableTools::generateHtmlTableFromFile( filePath, maxRowCount );
|
||||
return result ? *result : result.error();
|
||||
}
|
||||
+23
-19
@@ -1,6 +1,6 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2017- Statoil ASA
|
||||
// Copyright (C) 2026- Equinor ASA
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@@ -18,26 +18,30 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafCmdFeature.h"
|
||||
#include "cafPdmField.h"
|
||||
|
||||
#include <vector>
|
||||
#include <QString>
|
||||
|
||||
class RimObservedFmuRftData;
|
||||
class RimObservedSummaryData;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RicCloseObservedDataFeature : public caf::CmdFeature
|
||||
namespace caf
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
class PdmUiEditorAttribute;
|
||||
}
|
||||
|
||||
public:
|
||||
static void deleteObservedSummaryData( const std::vector<RimObservedSummaryData*>& data );
|
||||
static void deleteObservedRmuRftData( const std::vector<RimObservedFmuRftData*>& data );
|
||||
//==================================================================================================
|
||||
/// Helpers for showing CSV data as a read-only HTML table in the property editor
|
||||
//==================================================================================================
|
||||
namespace RimCsvPreviewTools
|
||||
{
|
||||
const int defaultMaxRowCount = 1000;
|
||||
|
||||
protected:
|
||||
bool isCommandEnabled() const override;
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
};
|
||||
// Configures the field as a read-only, non-persistent HTML text editor without label
|
||||
void initPreviewField( caf::PdmField<QString>& field );
|
||||
|
||||
// Call from defineEditorAttribute() for the preview field
|
||||
void setPreviewEditorAttribute( caf::PdmUiEditorAttribute* attribute );
|
||||
|
||||
// Returns the HTML table, or the error message if the content could not be parsed
|
||||
QString htmlTableFromText( const QString& csvText, int maxRowCount = defaultMaxRowCount );
|
||||
QString htmlTableFromFile( const QString& filePath, int maxRowCount = defaultMaxRowCount );
|
||||
|
||||
} // namespace RimCsvPreviewTools
|
||||
@@ -327,6 +327,21 @@ RimObservedFmuRftData* RimWellLogRftCurve::observedFmuRftData() const
|
||||
return m_observedFmuRftData;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellLogRftCurve::deleteIfDataSourceIsMissing()
|
||||
{
|
||||
if ( m_eclipseCase || m_summaryCase || m_ensemble || m_observedFmuRftData || m_pressureDepthData ) return false;
|
||||
|
||||
auto track = firstAncestorOrThisOfType<RimWellLogTrack>();
|
||||
if ( !track ) return false;
|
||||
|
||||
track->removeCurve( this );
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -96,6 +96,8 @@ public:
|
||||
|
||||
void setScaleFactor( double factor );
|
||||
|
||||
bool deleteIfDataSourceIsMissing() override;
|
||||
|
||||
protected:
|
||||
QString createCurveAutoName() override;
|
||||
QString createCurveNameFromTemplate( const QString& templateText ) override;
|
||||
|
||||
@@ -392,8 +392,6 @@ void RimWellPathCollection::addWellPath( RimWellPath* wellPath )
|
||||
m_wellPaths.push_back( wellPath );
|
||||
|
||||
rebuildWellPathNodes();
|
||||
|
||||
m_mostRecentlyUpdatedWellPath = wellPath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -569,8 +567,6 @@ void RimWellPathCollection::addWellPathFormations( const QStringList& filePaths
|
||||
|
||||
QString wellFormationsCount = QString( "%1" ).arg( formations->formationNamesCount() );
|
||||
|
||||
m_mostRecentlyUpdatedWellPath = wellPath;
|
||||
|
||||
outputMessage += wellName + "\t\t";
|
||||
outputMessage += wellPath->name() + " \t\t\t";
|
||||
outputMessage += wellFormationsCount + "\n";
|
||||
@@ -925,14 +921,6 @@ void RimWellPathCollection::groupWellPaths( const std::vector<RimWellPath*>& wel
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimWellPath* RimWellPathCollection::mostRecentlyUpdatedWellPath()
|
||||
{
|
||||
return m_mostRecentlyUpdatedWellPath;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -124,8 +124,6 @@ public:
|
||||
|
||||
bool showMswSegmentBands() const;
|
||||
|
||||
RimWellPath* mostRecentlyUpdatedWellPath();
|
||||
|
||||
void readWellPathFormationFiles();
|
||||
void reloadAllWellPathFormations();
|
||||
RimWellPath* wellPathByName( const QString& wellPathName ) const;
|
||||
@@ -189,7 +187,6 @@ private:
|
||||
private:
|
||||
std::unique_ptr<RifWellPathImporter> m_wellPathImporter;
|
||||
|
||||
caf::PdmPointer<RimWellPath> m_mostRecentlyUpdatedWellPath;
|
||||
caf::PdmChildField<RimWellMeasurementCollection*> m_wellMeasurements;
|
||||
caf::PdmChildField<RimWellEventTimeline*> m_eventTimeline;
|
||||
caf::PdmChildArrayField<RimWellPath*> m_wellPaths;
|
||||
|
||||
@@ -483,6 +483,10 @@ bool RiuMultiPlotPage::hasHeightForWidth() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RiuMultiPlotPage::heightForWidth( int width ) const
|
||||
{
|
||||
// The page aspect ratio is only relevant in page preview mode. Otherwise, a parent scroll area (e.g. a dock widget) will size the
|
||||
// page taller than the visible area, and the bottom of the plot is clipped.
|
||||
if ( !m_previewMode ) return -1;
|
||||
|
||||
QPageLayout pageLayout = m_plotDefinition->pageLayout();
|
||||
QRectF rect = pageLayout.fullRectPoints();
|
||||
double aspectRatio = rect.height() / rect.width();
|
||||
|
||||
Reference in new issue
Block a user