From a9f902e5c235d2e414553d028b2c3b0046fc3994 Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Wed, 13 Nov 2024 14:06:23 +0100 Subject: [PATCH] Add Statistics Contour Map for eclipse grid ensembles. --- .../Commands/CMakeLists_files.cmake | 2 + .../RicNewStatisticsContourMapViewFeature.cpp | 128 ++++++++ .../RicNewStatisticsContourMapViewFeature.h | 41 +++ .../ProjectDataModel/CMakeLists_files.cmake | 4 + .../RimGeoMechContourMapProjection.cpp | 26 +- .../GeoMech/RimGeoMechContourMapProjection.h | 1 + .../Rim3dOverlayInfoConfig.cpp | 8 +- .../RimContourMapProjection.h | 9 +- .../RimEclipseContourMapProjection.cpp | 9 + .../RimEclipseContourMapProjection.h | 1 + .../RimEclipseContourMapView.cpp | 2 +- .../RimEclipseContourMapView.h | 11 +- .../RimEclipseResultDefinition.cpp | 6 +- .../ProjectDataModel/RimReloadCaseTools.cpp | 3 +- .../RimStatisticsContourMap.cpp | 135 +++++++- .../RimStatisticsContourMap.h | 35 +- .../RimStatisticsContourMapProjection.cpp | 304 ++++++++++++++++++ .../RimStatisticsContourMapProjection.h | 85 +++++ .../RimStatisticsContourMapView.cpp | 194 +++++++++++ .../RimStatisticsContourMapView.h | 46 +++ .../ReservoirDataModel/CMakeLists_files.cmake | 2 + .../ReservoirDataModel/RigContourMapGrid.h | 9 + .../RigContourMapProjection.h | 4 +- .../RigStatisticsContourMapProjection.cpp | 139 ++++++++ .../RigStatisticsContourMapProjection.h | 56 ++++ 25 files changed, 1232 insertions(+), 28 deletions(-) create mode 100644 ApplicationLibCode/Commands/RicNewStatisticsContourMapViewFeature.cpp create mode 100644 ApplicationLibCode/Commands/RicNewStatisticsContourMapViewFeature.h create mode 100644 ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapProjection.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapProjection.h create mode 100644 ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapView.cpp create mode 100644 ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapView.h create mode 100644 ApplicationLibCode/ReservoirDataModel/RigStatisticsContourMapProjection.cpp create mode 100644 ApplicationLibCode/ReservoirDataModel/RigStatisticsContourMapProjection.h diff --git a/ApplicationLibCode/Commands/CMakeLists_files.cmake b/ApplicationLibCode/Commands/CMakeLists_files.cmake index fabb8395fe..a9316b1a07 100644 --- a/ApplicationLibCode/Commands/CMakeLists_files.cmake +++ b/ApplicationLibCode/Commands/CMakeLists_files.cmake @@ -98,6 +98,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RicNewCustomVfpPlotFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewWellTargetCandidatesGeneratorFeature.h ${CMAKE_CURRENT_LIST_DIR}/RicNewStatisticsContourMapFeature.h + ${CMAKE_CURRENT_LIST_DIR}/RicNewStatisticsContourMapViewFeature.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -200,6 +201,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RicNewCustomVfpPlotFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewWellTargetCandidatesGeneratorFeature.cpp ${CMAKE_CURRENT_LIST_DIR}/RicNewStatisticsContourMapFeature.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewStatisticsContourMapViewFeature.cpp ) if(RESINSIGHT_USE_QT_CHARTS) diff --git a/ApplicationLibCode/Commands/RicNewStatisticsContourMapViewFeature.cpp b/ApplicationLibCode/Commands/RicNewStatisticsContourMapViewFeature.cpp new file mode 100644 index 0000000000..74d12fa253 --- /dev/null +++ b/ApplicationLibCode/Commands/RicNewStatisticsContourMapViewFeature.cpp @@ -0,0 +1,128 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicNewStatisticsContourMapViewFeature.h" + +#include "RimCellFilterCollection.h" +#include "RimEclipseCase.h" +#include "RimEclipseContourMapViewCollection.h" +#include "RimFaultInViewCollection.h" +#include "RimOilField.h" +#include "RimProject.h" +#include "RimSimWellInViewCollection.h" +#include "RimStatisticsContourMap.h" +#include "RimStatisticsContourMapView.h" +#include "RimSurfaceInViewCollection.h" + +#include "Riu3DMainWindowTools.h" +#include "RiuGuiTheme.h" + +#include "RiaColorTools.h" + +#include "cafPdmDocument.h" +#include "cafSelectionManager.h" + +#include + +CAF_CMD_SOURCE_INIT( RicNewStatisticsContourMapViewFeature, "RicNewStatisticsContourMapViewFeature" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicNewStatisticsContourMapViewFeature::isCommandEnabled() const +{ + auto contourMap = caf::SelectionManager::instance()->selectedItemOfType(); + return contourMap != nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewStatisticsContourMapViewFeature::onActionTriggered( bool isChecked ) +{ + auto contourMap = caf::SelectionManager::instance()->selectedItemOfType(); + if ( !contourMap ) return; + + RimEclipseCase* eclipseCase = contourMap->eclipseCase(); + if ( !eclipseCase ) return; + + if ( auto eclipseContourMap = createStatisticsContourMapView( contourMap, eclipseCase ) ) + { + // Must be run before buildViewItems, as wells are created in this function + eclipseContourMap->loadDataAndUpdate(); + + // make sure no surfaces are shown in the view when the contourmap is generated + if ( eclipseContourMap->surfaceInViewCollection() ) eclipseContourMap->surfaceInViewCollection()->setCheckState( Qt::Unchecked ); + + if ( eclipseCase ) + { + eclipseCase->updateConnectedEditors(); + eclipseContourMap->cellFilterCollection()->setCase( eclipseCase ); + } + caf::SelectionManager::instance()->setSelectedItem( eclipseContourMap ); + + eclipseContourMap->createDisplayModelAndRedraw(); + eclipseContourMap->zoomAll(); + + RimProject* project = RimProject::current(); + + RimOilField* oilField = project->activeOilField(); + + oilField->eclipseContourMapCollection()->updateConnectedEditors(); + + Riu3DMainWindowTools::setExpanded( eclipseContourMap ); + Riu3DMainWindowTools::selectAsCurrentItem( eclipseContourMap ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicNewStatisticsContourMapViewFeature::setupActionLook( QAction* actionToSetup ) +{ + actionToSetup->setText( "Create View" ); + actionToSetup->setIcon( QIcon( ":/2DMap16x16.png" ) ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimStatisticsContourMapView* RicNewStatisticsContourMapViewFeature::createStatisticsContourMapView( RimStatisticsContourMap* statisticsContourMap, + RimEclipseCase* eclipseCase ) +{ + RimStatisticsContourMapView* contourMap = new RimStatisticsContourMapView; + contourMap->setStatisticsContourMap( statisticsContourMap ); + contourMap->setEclipseCase( eclipseCase ); + + caf::PdmDocument::updateUiIconStateRecursively( contourMap ); + + size_t i = eclipseCase->contourMapCollection()->views().size(); + contourMap->setName( QString( "Contour Map %1" ).arg( i + 1 ) ); + + contourMap->faultCollection()->setActive( false ); + contourMap->wellCollection()->isActive = false; + + eclipseCase->contourMapCollection()->addView( contourMap ); + + auto col = RiuGuiTheme::getColorByVariableName( "backgroundColor2" ); + contourMap->setBackgroundColor( RiaColorTools::fromQColorTo3f( col ) ); // Ignore original view background + + contourMap->initAfterReadRecursively(); + + return contourMap; +} diff --git a/ApplicationLibCode/Commands/RicNewStatisticsContourMapViewFeature.h b/ApplicationLibCode/Commands/RicNewStatisticsContourMapViewFeature.h new file mode 100644 index 0000000000..836461b784 --- /dev/null +++ b/ApplicationLibCode/Commands/RicNewStatisticsContourMapViewFeature.h @@ -0,0 +1,41 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + +class RimEclipseCase; +class RimStatisticsContourMapView; +class RimStatisticsContourMap; + +//================================================================================================== +/// +//================================================================================================== +class RicNewStatisticsContourMapViewFeature : public caf::CmdFeature +{ + CAF_CMD_HEADER_INIT; + +protected: + bool isCommandEnabled() const override; + void onActionTriggered( bool isChecked ) override; + void setupActionLook( QAction* actionToSetup ) override; + + static RimStatisticsContourMapView* createStatisticsContourMapView( RimStatisticsContourMap* statisticsContourMap, + RimEclipseCase* eclipseCase ); +}; diff --git a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake index 11f9257dc5..67290883d1 100644 --- a/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ProjectDataModel/CMakeLists_files.cmake @@ -135,6 +135,8 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RimCameraPosition.h ${CMAKE_CURRENT_LIST_DIR}/RimWellTargetCandidatesGenerator.h ${CMAKE_CURRENT_LIST_DIR}/RimStatisticsContourMap.h + ${CMAKE_CURRENT_LIST_DIR}/RimStatisticsContourMapProjection.h + ${CMAKE_CURRENT_LIST_DIR}/RimStatisticsContourMapView.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -270,6 +272,8 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RimCameraPosition.cpp ${CMAKE_CURRENT_LIST_DIR}/RimWellTargetCandidatesGenerator.cpp ${CMAKE_CURRENT_LIST_DIR}/RimStatisticsContourMap.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimStatisticsContourMapProjection.cpp + ${CMAKE_CURRENT_LIST_DIR}/RimStatisticsContourMapView.cpp ) if(RESINSIGHT_USE_QT_CHARTS) diff --git a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechContourMapProjection.cpp b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechContourMapProjection.cpp index 411abdb862..babb262fc7 100644 --- a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechContourMapProjection.cpp +++ b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechContourMapProjection.cpp @@ -75,12 +75,36 @@ QString RimGeoMechContourMapProjection::resultDescriptionText() const return resultText; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimGeoMechContourMapProjection::resultVariableName() const +{ + if ( auto v = view() ) + { + if ( auto c = v->cellResult() ) + { + return c->resultFieldUiName(); + } + } + + return ""; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimRegularLegendConfig* RimGeoMechContourMapProjection::legendConfig() const { - return view()->cellResult()->legendConfig(); + if ( auto v = view() ) + { + if ( auto c = v->cellResult() ) + { + return c->legendConfig(); + } + } + + return nullptr; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechContourMapProjection.h b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechContourMapProjection.h index f78d0079e0..44beb8c2a0 100644 --- a/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechContourMapProjection.h +++ b/ApplicationLibCode/ProjectDataModel/GeoMech/RimGeoMechContourMapProjection.h @@ -45,6 +45,7 @@ class RimGeoMechContourMapProjection : public RimContourMapProjection ~RimGeoMechContourMapProjection() override; // GeoMech case overrides for contour map methods + QString resultVariableName() const override; QString resultDescriptionText() const override; RimRegularLegendConfig* legendConfig() const override; void updateLegend() override; diff --git a/ApplicationLibCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp b/ApplicationLibCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp index 54cf91d21a..59e3709f1a 100644 --- a/ApplicationLibCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp +++ b/ApplicationLibCode/ProjectDataModel/Rim3dOverlayInfoConfig.cpp @@ -316,15 +316,17 @@ QString Rim3dOverlayInfoConfig::caseInfoText( RimEclipseView* eclipseView ) RimEclipseContourMapView* contourMap = dynamic_cast( eclipseView ); if ( contourMap && contourMap->contourMapProjection() && contourMap->contourMapProjection()->mapProjection() ) { + RimEclipseContourMapProjection* eclipseProjection = + dynamic_cast( contourMap->contourMapProjection() ); QString totCellCount = localeWithSpaceAsGroupSeparator.toString( contourMap->contourMapProjection()->mapProjection()->numberOfCells() ); cvf::uint validCellCount = contourMap->contourMapProjection()->mapProjection()->numberOfValidCells(); QString activeCellCountText = localeWithSpaceAsGroupSeparator.toString( validCellCount ); QString aggregationType = contourMap->contourMapProjection()->resultAggregationText(); QString weightingParameterString; - if ( contourMap->contourMapProjection()->weightingParameter() != "None" ) + if ( eclipseProjection && eclipseProjection->weightingParameter() != "None" ) { - weightingParameterString += QString( " (Weight: %1)" ).arg( contourMap->contourMapProjection()->weightingParameter() ); + weightingParameterString += QString( " (Weight: %1)" ).arg( eclipseProjection->weightingParameter() ); } infoText += QString( "

-- Contour Map: %1 --

" @@ -452,7 +454,7 @@ QString Rim3dOverlayInfoConfig::resultInfoText( const RigHistogramData& histData bool isResultsInfoRelevant = contourMap->contourMapProjection()->mapProjection()->numberOfValidCells() > 0u; if ( isResultsInfoRelevant ) { - QString propName = eclipseView->cellResult()->resultVariableUiShortName(); + QString propName = contourMap->contourMapProjection()->resultVariableName(); QString diffResString = eclipseView->cellResult()->additionalResultText(); if ( !contourMap->contourMapProjection()->isColumnResult() ) { diff --git a/ApplicationLibCode/ProjectDataModel/RimContourMapProjection.h b/ApplicationLibCode/ProjectDataModel/RimContourMapProjection.h index 551983515f..c62720e028 100644 --- a/ApplicationLibCode/ProjectDataModel/RimContourMapProjection.h +++ b/ApplicationLibCode/ProjectDataModel/RimContourMapProjection.h @@ -63,14 +63,14 @@ class RimContourMapProjection : public RimCheckableNamedObject bool showContourLines() const; bool showContourLabels() const; - QString resultAggregationText() const; + virtual QString resultAggregationText() const; QString caseName() const; QString currentTimeStepName() const; - bool isColumnResult() const; - bool isMeanResult() const; - bool isStraightSummationResult() const; + virtual bool isColumnResult() const; + bool isMeanResult() const; + bool isStraightSummationResult() const; void setPickPoint( cvf::Vec2d globalPickPoint ); cvf::Vec2d pickPoint() const; @@ -78,6 +78,7 @@ class RimContourMapProjection : public RimCheckableNamedObject cvf::Vec3d origin3d() const; // Pure-virtual public methods which should be overridden by Eclipse and Geo-mechanical contour map implementations + virtual QString resultVariableName() const = 0; virtual QString resultDescriptionText() const = 0; virtual RimRegularLegendConfig* legendConfig() const = 0; virtual void updateLegend() = 0; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapProjection.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapProjection.cpp index a18e45e2eb..c805398731 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapProjection.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapProjection.cpp @@ -75,6 +75,15 @@ QString RimEclipseContourMapProjection::resultDescriptionText() const return resultText; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimEclipseContourMapProjection::resultVariableName() const +{ + if ( !isColumnResult() ) return view()->cellResult()->resultVariable(); + return resultAggregationText(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapProjection.h b/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapProjection.h index 6129329231..1da539845c 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapProjection.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapProjection.h @@ -48,6 +48,7 @@ class RimEclipseContourMapProjection : public RimContourMapProjection void clearGridMappingAndRedraw(); // Eclipse case overrides for contour map methods + QString resultVariableName() const override; QString resultDescriptionText() const override; RimRegularLegendConfig* legendConfig() const override; void updateLegend() override; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapView.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapView.cpp index e1dfa286ae..1427da563a 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapView.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapView.cpp @@ -88,7 +88,7 @@ RimEclipseContourMapView::RimEclipseContourMapView() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimEclipseContourMapProjection* RimEclipseContourMapView::contourMapProjection() const +RimContourMapProjection* RimEclipseContourMapView::contourMapProjection() const { return m_contourMapProjection().p(); } diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapView.h b/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapView.h index 80ee753c13..e26a1a0503 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapView.h +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseContourMapView.h @@ -28,6 +28,7 @@ class RimRegularLegendConfig; class RimViewNameConfig; class RimScaleLegendConfig; class RivContourMapProjectionPartMgr; +class RimContourMapProjection; class RimEclipseContourMapView : public RimEclipseView { @@ -35,7 +36,7 @@ class RimEclipseContourMapView : public RimEclipseView public: RimEclipseContourMapView(); - RimEclipseContourMapProjection* contourMapProjection() const; + RimContourMapProjection* contourMapProjection() const; RiaDefines::View3dContent viewContent() const override; @@ -83,14 +84,12 @@ class RimEclipseContourMapView : public RimEclipseView void onLegendConfigChanged( const caf::SignalEmitter* emitter, RimLegendConfigChangeType changeType ); -private: + cvf::ref m_contourMapProjectionPartMgr; + caf::PdmChildField m_contourMapProjection; + bool isFaultLinesVisible() const; void setFaultLinesVisible( const bool& visible ); -private: - cvf::ref m_contourMapProjectionPartMgr; - caf::PdmChildField m_contourMapProjection; - caf::PdmProxyValueField m_showFaultLines; caf::PdmField m_showAxisLines; caf::PdmField m_showScaleLegend; diff --git a/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp b/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp index e35bddd12b..09271c34b5 100644 --- a/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimEclipseResultDefinition.cpp @@ -326,7 +326,8 @@ void RimEclipseResultDefinition::fieldChangedByUi( const caf::PdmFieldHandle* ch if ( contourMapView ) { - contourMapView->contourMapProjection()->clearGridMappingAndRedraw(); + if ( auto projection = dynamic_cast( contourMapView->contourMapProjection() ) ) + projection->clearGridMappingAndRedraw(); } loadDataAndUpdate(); @@ -336,7 +337,8 @@ void RimEclipseResultDefinition::fieldChangedByUi( const caf::PdmFieldHandle* ch { if ( contourMapView ) { - contourMapView->contourMapProjection()->clearGridMappingAndRedraw(); + if ( auto projection = dynamic_cast( contourMapView->contourMapProjection() ) ) + projection->clearGridMappingAndRedraw(); } loadDataAndUpdate(); diff --git a/ApplicationLibCode/ProjectDataModel/RimReloadCaseTools.cpp b/ApplicationLibCode/ProjectDataModel/RimReloadCaseTools.cpp index 83f979a4fb..b7b0662273 100644 --- a/ApplicationLibCode/ProjectDataModel/RimReloadCaseTools.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimReloadCaseTools.cpp @@ -150,7 +150,8 @@ void RimReloadCaseTools::updateAll3dViews( RimEclipseCase* eclipseCase ) // computations are updated based on new data. // See RimEclipseContourMapProjection::generateResults() contourMap->contourMapProjection()->clearGeometry(); - contourMap->contourMapProjection()->clearGridMappingAndRedraw(); + if ( auto projection = dynamic_cast( contourMap->contourMapProjection() ) ) + projection->clearGridMappingAndRedraw(); } contourMap->loadDataAndUpdate(); diff --git a/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMap.cpp b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMap.cpp index 17b3f1dda3..493bc83629 100644 --- a/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMap.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMap.cpp @@ -22,6 +22,7 @@ #include "RiaStatisticsTools.h" #include "RigCaseCellResultsData.h" +#include "RigContourMapCalculator.h" #include "RigContourMapGrid.h" #include "RigEclipseCaseData.h" #include "RigEclipseContourMapProjection.h" @@ -36,6 +37,7 @@ #include "RimProject.h" #include "RimTools.h" +#include "cafCmdFeatureMenuBuilder.h" #include "cafPdmUiDoubleSliderEditor.h" #include "cafPdmUiPushButtonEditor.h" #include "cafProgressInfo.h" @@ -44,6 +46,21 @@ CAF_PDM_SOURCE_INIT( RimStatisticsContourMap, "RimStatisticalContourMap" ); +namespace caf +{ +template <> +void caf::AppEnum::setUp() +{ + addItem( RimStatisticsContourMap::StatisticsType::P10, "P10", "P10" ); + addItem( RimStatisticsContourMap::StatisticsType::P50, "P50", "P50" ); + addItem( RimStatisticsContourMap::StatisticsType::P90, "P90", "P90" ); + addItem( RimStatisticsContourMap::StatisticsType::MEAN, "MEAN", "Mean" ); + addItem( RimStatisticsContourMap::StatisticsType::MIN, "MIN", "Minimum" ); + addItem( RimStatisticsContourMap::StatisticsType::MAX, "MAX", "Maximum" ); + setDefault( RimStatisticsContourMap::StatisticsType::MEAN ); +} +}; // namespace caf + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -93,6 +110,14 @@ void RimStatisticsContourMap::setEclipseCase( RimEclipseCase* eclipseCase ) m_resultDefinition->setEclipseCase( eclipseCase ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseCaseEnsemble* RimStatisticsContourMap::ensemble() const +{ + return firstAncestorOrThisOfType(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -198,6 +223,12 @@ void RimStatisticsContourMap::computeStatistics() auto contourMapGrid = std::make_unique( gridBoundingBox, sampleSpacing ); + auto firstEclipseCaseData = firstEclipseCase->eclipseCaseData(); + auto firstResultData = firstEclipseCaseData->results( RiaDefines::PorosityModelType::MATRIX_MODEL ); + + RigEclipseContourMapProjection contourMapProjection( *contourMapGrid, *firstEclipseCaseData, *firstResultData ); + m_gridMapping = contourMapProjection.generateGridMapping( resultAggregation, {} ); + std::vector> results; for ( RimEclipseCase* eclipseCase : ensemble->cases() ) { @@ -235,17 +266,107 @@ void RimStatisticsContourMap::computeStatistics() for ( size_t s = 0; s < numSamples; s++ ) samples[s] = results[s][i]; - double p10, p50, p90, mean; + double p10 = std::numeric_limits::infinity(); + double p50 = std::numeric_limits::infinity(); + double p90 = std::numeric_limits::infinity(); + double mean = std::numeric_limits::infinity(); RigStatisticsMath::calculateStatisticsCurves( samples, &p10, &p50, &p90, &mean, RigStatisticsMath::PercentileStyle::SWITCHED ); - p10Results[i] = p10; - p50Results[i] = p50; - p90Results[i] = p90; - meanResults[i] = mean; + if ( RiaStatisticsTools::isValidNumber( p10 ) ) p10Results[i] = p10; + if ( RiaStatisticsTools::isValidNumber( p50 ) ) p50Results[i] = p50; + if ( RiaStatisticsTools::isValidNumber( p90 ) ) p90Results[i] = p90; + if ( RiaStatisticsTools::isValidNumber( mean ) ) meanResults[i] = mean; - minResults[i] = RiaStatisticsTools::minimumValue( samples ); - maxResults[i] = RiaStatisticsTools::maximumValue( samples ); + double minValue = RiaStatisticsTools::minimumValue( samples ); + if ( RiaStatisticsTools::isValidNumber( minValue ) && minValue < std::numeric_limits::max() ) minResults[i] = minValue; + + double maxValue = RiaStatisticsTools::maximumValue( samples ); + if ( RiaStatisticsTools::isValidNumber( maxValue ) && maxValue > -std::numeric_limits::max() ) maxResults[i] = maxValue; } + + m_contourMapGrid = std::move( contourMapGrid ); + m_result[StatisticsType::P10] = p10Results; + m_result[StatisticsType::P50] = p50Results; + m_result[StatisticsType::P90] = p90Results; + m_result[StatisticsType::MEAN] = meanResults; + m_result[StatisticsType::MIN] = minResults; + m_result[StatisticsType::MAX] = maxResults; } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseCase* RimStatisticsContourMap::eclipseCase() const +{ + auto ensemble = firstAncestorOrThisOfType(); + if ( !ensemble || ensemble->cases().empty() ) return nullptr; + + return ensemble->cases().front(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMap::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const +{ + menuBuilder << "RicNewStatisticsContourMapViewFeature"; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigContourMapGrid* RimStatisticsContourMap::contourMapGrid() const +{ + return m_contourMapGrid.get(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimStatisticsContourMap::result( StatisticsType statisticsType ) const +{ + if ( auto it = m_result.find( statisticsType ); it != m_result.end() ) return it->second; + return {}; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMap::ensureResultsComputed() +{ + if ( !m_contourMapGrid ) computeStatistics(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimStatisticsContourMap::resultAggregationText() const +{ + return m_resultAggregation().uiText(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimStatisticsContourMap::resultVariable() const +{ + return m_resultDefinition()->resultVariable(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimStatisticsContourMap::isColumnResult() const +{ + return RigContourMapCalculator::isColumnResult( m_resultAggregation() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimStatisticsContourMap::sampleSpacingFactor() const +{ + return m_relativeSampleSpacing; +} diff --git a/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMap.h b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMap.h index ae4100e801..01b5a6c1c8 100644 --- a/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMap.h +++ b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMap.h @@ -23,8 +23,11 @@ #include "RimContourMapProjection.h" +#include + class RimEclipseCase; class RimEclipseResultDefinition; +class RimEclipseCaseEnsemble; //================================================================================================== // @@ -36,15 +39,41 @@ class RimStatisticsContourMap : public caf::PdmObject CAF_PDM_HEADER_INIT; public: + enum class StatisticsType + { + P10, + P50, + P90, + MEAN, + MIN, + MAX + }; + RimStatisticsContourMap(); - void setEclipseCase( RimEclipseCase* eclipseCase ); + void setEclipseCase( RimEclipseCase* eclipseCase ); + RimEclipseCase* eclipseCase() const; + + RimEclipseCaseEnsemble* ensemble() const; + + RigContourMapGrid* contourMapGrid() const; + std::vector result( StatisticsType statisticsType ) const; + + std::vector>> gridMapping() const; + + void ensureResultsComputed(); + + QString resultAggregationText() const; + QString resultVariable() const; + double sampleSpacingFactor() const; + bool isColumnResult() const; protected: void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override; void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; void initAfterRead() override; + void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override; QList calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override; private: @@ -56,4 +85,8 @@ class RimStatisticsContourMap : public caf::PdmObject caf::PdmChildField m_resultDefinition; caf::PdmField m_computeStatisticsButton; + + std::unique_ptr m_contourMapGrid; + std::map> m_result; + std::vector>> m_gridMapping; }; diff --git a/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapProjection.cpp b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapProjection.cpp new file mode 100644 index 0000000000..bb72331264 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapProjection.cpp @@ -0,0 +1,304 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimStatisticsContourMapProjection.h" + +#include "RigCaseCellResultsData.h" +#include "RigContourMapCalculator.h" +#include "RigContourMapGrid.h" +#include "RigContourMapProjection.h" +#include "RigEclipseCaseData.h" +#include "RigStatisticsContourMapProjection.h" + +#include "RimEclipseCase.h" +#include "RimEclipseCellColors.h" +#include "RimEclipseResultDefinition.h" +#include "RimEclipseView.h" +#include "RimRegularLegendConfig.h" +#include "RimStatisticsContourMap.h" +#include "RimStatisticsContourMapView.h" + +#include + +CAF_PDM_SOURCE_INIT( RimStatisticsContourMapProjection, "RimStatisticsContourMapProjection" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimStatisticsContourMapProjection::RimStatisticsContourMapProjection() + : RimContourMapProjection() +{ + CAF_PDM_InitObject( "RimStatisticsContourMapProjection", ":/2DMapProjection16x16.png" ); + + CAF_PDM_InitFieldNoDefault( &m_statisticsType, "StatisticsType", "Statistics Type" ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimStatisticsContourMapProjection::~RimStatisticsContourMapProjection() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimStatisticsContourMapProjection::resultDescriptionText() const +{ + QString resultText; + if ( auto scm = statisticsContourMap() ) + { + resultText = scm->resultAggregationText(); + QString statisticsText = m_statisticsType().uiText(); + + if ( !scm->isColumnResult() ) + { + resultText += QString( ", %1" ).arg( scm->resultVariable() ); + } + resultText += ", " + statisticsText; + } + + return resultText; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimStatisticsContourMapProjection::resultVariableName() const +{ + if ( auto scm = statisticsContourMap() ) + { + QString stasticsText = m_statisticsType().uiText(); + if ( !scm->isColumnResult() ) + return scm->resultVariable() + ", " + stasticsText; + else + return scm->resultAggregationText() + ", " + stasticsText; + } + + return ""; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimRegularLegendConfig* RimStatisticsContourMapProjection::legendConfig() const +{ + return view()->cellResult()->legendConfig(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMapProjection::updateLegend() +{ + double minVal = m_contourMapProjection ? m_contourMapProjection->minValue() : std::numeric_limits::infinity(); + double maxVal = m_contourMapProjection ? m_contourMapProjection->maxValue() : -std::numeric_limits::infinity(); + + auto [minValAllTimeSteps, maxValAllTimeSteps] = minmaxValuesAllTimeSteps(); + + legendConfig()->setAutomaticRanges( minValAllTimeSteps, maxValAllTimeSteps, minVal, maxVal ); + + if ( statisticsContourMap()->isColumnResult() ) + { + legendConfig()->setTitle( QString( "Map Projection\n%1" ).arg( resultVariableName() ) ); + } + else + { + QString projectionLegendText = QString( "Map Projection\n%1" ).arg( resultAggregationText() ); + projectionLegendText += QString( "\nResult: %1" ).arg( resultVariableName() ); + + legendConfig()->setTitle( projectionLegendText ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RimStatisticsContourMapProjection::sampleSpacing() const +{ + if ( RimStatisticsContourMap* contourMap = statisticsContourMap() ) + { + if ( RigContourMapGrid* contourMapGrid = contourMap->contourMapGrid() ) + { + return contourMapGrid->sampleSpacing(); + } + } + + return 1.0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMapProjection::clearGridMappingAndRedraw() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimStatisticsContourMapProjection::generateResults( int timeStep ) const +{ + return {}; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMapProjection::generateAndSaveResults( int timeStep ) +{ + if ( auto statistics = statisticsContourMap() ) + { + dynamic_cast( m_contourMapProjection.get() ) + ->generateAndSaveResults( statistics->result( m_statisticsType() ) ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimStatisticsContourMapProjection::resultVariableChanged() const +{ + return false; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMapProjection::clearResultVariable() +{ + m_currentResultName = ""; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMapProjection::updateGridInformation() +{ + RimStatisticsContourMap* contourMap = statisticsContourMap(); + contourMap->ensureResultsComputed(); + + m_contourMapGrid = std::make_unique( *contourMap->contourMapGrid() ); + m_contourMapProjection = std::make_unique( *m_contourMapGrid ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RimStatisticsContourMapProjection::retrieveParameterWeights() +{ + return {}; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimEclipseCase* RimStatisticsContourMapProjection::eclipseCase() const +{ + auto v = view(); + if ( !v ) return nullptr; + + return dynamic_cast( v->ownerCase() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimStatisticsContourMap* RimStatisticsContourMapProjection::statisticsContourMap() const +{ + auto v = view(); + if ( !v ) return nullptr; + + return v->statisticsContourMap(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimGridView* RimStatisticsContourMapProjection::baseView() const +{ + return view(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimStatisticsContourMapView* RimStatisticsContourMapProjection::view() const +{ + return firstAncestorOrThisOfTypeAsserted(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMapProjection::updateAfterResultGeneration( int timeStep ) +{ + m_currentResultTimestep = timeStep; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RimStatisticsContourMapProjection::minmaxValuesAllTimeSteps() +{ + if ( !resultRangeIsValid() ) + { + clearTimeStepRange(); + + std::vector aggregatedResults = statisticsContourMap()->result( m_statisticsType() ); + m_minResultAllTimeSteps = RigContourMapProjection::minValue( aggregatedResults ); + m_maxResultAllTimeSteps = RigContourMapProjection::maxValue( aggregatedResults ); + } + + return std::make_pair( m_minResultAllTimeSteps, m_maxResultAllTimeSteps ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMapProjection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) +{ + uiOrdering.add( &m_statisticsType ); + + caf::PdmUiGroup* mainGroup = uiOrdering.addNewGroup( "Projection Settings" ); + mainGroup->add( &m_showContourLines ); + mainGroup->add( &m_showContourLabels ); + m_showContourLabels.uiCapability()->setUiReadOnly( !m_showContourLines() ); + mainGroup->add( &m_smoothContourLines ); + m_smoothContourLines.uiCapability()->setUiReadOnly( !m_showContourLines() ); + uiOrdering.skipRemainingFields( true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RimStatisticsContourMapProjection::isColumnResult() const +{ + return ( statisticsContourMap() && statisticsContourMap()->isColumnResult() ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimStatisticsContourMapProjection::resultAggregationText() const +{ + if ( statisticsContourMap() ) + return statisticsContourMap()->resultAggregationText(); + else + return ""; +} diff --git a/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapProjection.h b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapProjection.h new file mode 100644 index 0000000000..110fd49bc7 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapProjection.h @@ -0,0 +1,85 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimContourMapProjection.h" +#include "RimStatisticsContourMap.h" + +#include "cafAppEnum.h" +#include "cafPdmField.h" +#include "cafPdmObject.h" + +class RigActiveCellInfo; +class RigMainGrid; +class RigContourMapGrid; +class RigResultAccessor; +class RimStatisticsContourMapView; +class RimEclipseCase; +class RimEclipseResultDefinition; + +//================================================================================================== +/// +/// +//================================================================================================== +class RimStatisticsContourMapProjection : public RimContourMapProjection +{ + CAF_PDM_HEADER_INIT; + +public: + RimStatisticsContourMapProjection(); + ~RimStatisticsContourMapProjection() override; + + void clearGridMappingAndRedraw(); + + QString resultVariableName() const override; + QString resultDescriptionText() const override; + RimRegularLegendConfig* legendConfig() const override; + void updateLegend() override; + + double sampleSpacing() const override; + + bool isColumnResult() const override; + QString resultAggregationText() const override; + +protected: + void updateGridInformation() override; + std::vector retrieveParameterWeights() override; + std::vector generateResults( int timeStep ) const override; + void generateAndSaveResults( int timeStep ) override; + bool resultVariableChanged() const override; + void clearResultVariable() override; + RimGridView* baseView() const override; + + RimEclipseCase* eclipseCase() const; + RimStatisticsContourMap* statisticsContourMap() const; + RimStatisticsContourMapView* view() const; + + std::pair minmaxValuesAllTimeSteps() override; + + void updateAfterResultGeneration( int timeStep ) override; + +protected: + // Framework overrides + void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override; + +protected: + caf::PdmField> m_statisticsType; + + QString m_currentResultName; +}; diff --git a/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapView.cpp b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapView.cpp new file mode 100644 index 0000000000..1b4cfe8d84 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapView.cpp @@ -0,0 +1,194 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RimStatisticsContourMapView.h" + +#include "RiuViewer.h" + +#include "RivContourMapProjectionPartMgr.h" + +#include "Rim3dOverlayInfoConfig.h" +#include "RimAnnotationInViewCollection.h" +#include "RimCase.h" +#include "RimCellFilterCollection.h" +#include "RimEclipseCaseEnsemble.h" +#include "RimEclipseCellColors.h" +#include "RimEclipseContourMapView.h" +#include "RimEclipseFaultColors.h" +#include "RimFaultInViewCollection.h" +#include "RimRegularLegendConfig.h" +#include "RimSimWellInViewCollection.h" +#include "RimStatisticsContourMap.h" +#include "RimStatisticsContourMapProjection.h" +#include "RimViewLinker.h" +#include "RimViewNameConfig.h" + +#include "cafPdmUiTreeOrdering.h" +#include "cafProgressInfo.h" + +CAF_PDM_SOURCE_INIT( RimStatisticsContourMapView, "RimStatisticsContourMapView" ); + +RimStatisticsContourMapView::RimStatisticsContourMapView() + : RimEclipseContourMapView() +{ + CAF_PDM_InitObject( "Contour Map View", ":/2DMap16x16.png", "", "", "StatisticsContourMap", "A contour map for Eclipse cases" ); + + CAF_PDM_InitFieldNoDefault( &m_statisticsContourMap, "StatisticsContourMap", "Statistics Contour Map" ); + + m_contourMapProjection = new RimStatisticsContourMapProjection(); + + setFaultVisParameters(); + setDefaultCustomName(); + + m_contourMapProjectionPartMgr = new RivContourMapProjectionPartMgr( contourMapProjection() ); + + cellResult()->setTernaryEnabled( false ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMapView::setStatisticsContourMap( RimStatisticsContourMap* statisticsContourMap ) +{ + m_statisticsContourMap = statisticsContourMap; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimStatisticsContourMapView::createAutoName() const +{ + QStringList autoName; + + if ( !nameConfig()->customName().isEmpty() ) + { + autoName.push_back( nameConfig()->customName() ); + } + + QStringList generatedAutoTags; + + if ( nameConfig()->addCaseName() && m_statisticsContourMap->ensemble() ) + { + generatedAutoTags.push_back( m_statisticsContourMap->ensemble()->name() ); + } + + if ( nameConfig()->addAggregationType() ) + { + generatedAutoTags.push_back( m_statisticsContourMap->resultAggregationText() ); + } + + if ( nameConfig()->addProperty() && !m_statisticsContourMap->isColumnResult() ) + { + generatedAutoTags.push_back( m_statisticsContourMap->resultVariable() ); + } + + if ( nameConfig()->addSampleSpacing() ) + { + generatedAutoTags.push_back( QString( "%1" ).arg( m_statisticsContourMap->sampleSpacingFactor(), 3, 'f', 2 ) ); + } + + if ( !generatedAutoTags.empty() ) + { + autoName.push_back( generatedAutoTags.join( ", " ) ); + } + return autoName.join( ": " ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMapView::setDefaultCustomName() +{ + nameConfig()->setCustomName( "Contour Map" ); + nameConfig()->hideCaseNameField( false ); + nameConfig()->hideAggregationTypeField( false ); + nameConfig()->hidePropertyField( false ); + nameConfig()->hideSampleSpacingField( false ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMapView::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/ ) +{ + uiTreeOrdering.add( m_overlayInfoConfig() ); + uiTreeOrdering.add( m_contourMapProjection ); + uiTreeOrdering.add( cellResult()->legendConfig() ); + uiTreeOrdering.add( wellCollection() ); + uiTreeOrdering.add( faultCollection() ); + uiTreeOrdering.add( annotationCollection() ); + + uiTreeOrdering.skipRemainingChildren(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimStatisticsContourMapView::onUpdateLegends() +{ + if ( nativeOrOverrideViewer() ) + { + if ( !isUsingOverrideViewer() ) + { + nativeOrOverrideViewer()->removeAllColorLegends(); + } + else if ( cellResult() && cellResult()->legendConfig() ) + { + nativeOrOverrideViewer()->removeColorLegend( cellResult()->legendConfig()->titledOverlayFrame() ); + } + + if ( m_contourMapProjection && m_contourMapProjection->isChecked() ) + { + RimRegularLegendConfig* projectionLegend = m_contourMapProjection->legendConfig(); + if ( projectionLegend ) + { + m_contourMapProjection->updateLegend(); + if ( projectionLegend->showLegend() ) + { + nativeOrOverrideViewer()->addColorLegendToBottomLeftCorner( projectionLegend->titledOverlayFrame(), + isUsingOverrideViewer() ); + } + } + } + + // Hide the scale widget if any 3D views are present, as the display of the scale widget is only working for + // default rotation. The update is triggered in RimViewLinker::updateScaleWidgetVisibility() + + bool any3DViewsLinked = false; + + if ( auto viewLinker = assosiatedViewLinker() ) + { + auto views = viewLinker->allViews(); + for ( auto v : views ) + { + if ( dynamic_cast( v ) ) continue; + any3DViewsLinked = true; + } + } + + nativeOrOverrideViewer()->showScaleLegend( any3DViewsLinked ? false : m_showScaleLegend() ); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RimStatisticsContourMap* RimStatisticsContourMapView::statisticsContourMap() const +{ + return m_statisticsContourMap; +} diff --git a/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapView.h b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapView.h new file mode 100644 index 0000000000..6e32bd07f7 --- /dev/null +++ b/ApplicationLibCode/ProjectDataModel/RimStatisticsContourMapView.h @@ -0,0 +1,46 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RimEclipseContourMapView.h" + +class RimStatisticsContourMap; + +class RimStatisticsContourMapView : public RimEclipseContourMapView +{ + CAF_PDM_HEADER_INIT; + +public: + RimStatisticsContourMapView(); + + void setStatisticsContourMap( RimStatisticsContourMap* statisticsContourMap ); + RimStatisticsContourMap* statisticsContourMap() const; + + QString createAutoName() const override; + void setDefaultCustomName(); + +protected: + void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override; + + void createContourMapGeometry(); + void onUpdateLegends() override; + +private: + caf::PdmPtrField m_statisticsContourMap; +}; diff --git a/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake b/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake index a8fe60820b..d598d43bd7 100644 --- a/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake +++ b/ApplicationLibCode/ReservoirDataModel/CMakeLists_files.cmake @@ -88,6 +88,7 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RigContourMapTrianglesGenerator.h ${CMAKE_CURRENT_LIST_DIR}/RigEclipseContourMapProjection.h ${CMAKE_CURRENT_LIST_DIR}/RigGeoMechContourMapProjection.h + ${CMAKE_CURRENT_LIST_DIR}/RigStatisticsContourMapProjection.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -178,6 +179,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RigContourMapTrianglesGenerator.cpp ${CMAKE_CURRENT_LIST_DIR}/RigEclipseContourMapProjection.cpp ${CMAKE_CURRENT_LIST_DIR}/RigGeoMechContourMapProjection.cpp + ${CMAKE_CURRENT_LIST_DIR}/RigStatisticsContourMapProjection.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/ReservoirDataModel/RigContourMapGrid.h b/ApplicationLibCode/ReservoirDataModel/RigContourMapGrid.h index 89cc155d50..13acdf208d 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigContourMapGrid.h +++ b/ApplicationLibCode/ReservoirDataModel/RigContourMapGrid.h @@ -33,6 +33,15 @@ class RigContourMapGrid RigContourMapGrid( const cvf::BoundingBox& originalBoundingBox, double sampleSpacing ); RigContourMapGrid( const cvf::BoundingBox& originalBoundingBox, const cvf::BoundingBox& expandedBoundingBox, double sampleSpacing ); + // Copy constructor + RigContourMapGrid( const RigContourMapGrid& other ) + : m_sampleSpacing( other.m_sampleSpacing ) + , m_mapSize( other.m_mapSize ) + , m_expandedBoundingBox( other.m_expandedBoundingBox ) + , m_originalBoundingBox( other.m_originalBoundingBox ) + { + } + double sampleSpacing() const; cvf::Vec2ui numberOfElementsIJ() const; diff --git a/ApplicationLibCode/ReservoirDataModel/RigContourMapProjection.h b/ApplicationLibCode/ReservoirDataModel/RigContourMapProjection.h index 1a702f5971..26dd25fbb5 100644 --- a/ApplicationLibCode/ReservoirDataModel/RigContourMapProjection.h +++ b/ApplicationLibCode/ReservoirDataModel/RigContourMapProjection.h @@ -80,7 +80,7 @@ class RigContourMapProjection void setCellVisibility( cvf::ref cellVisibility ); cvf::ref getCellVisibility() const; - std::vector>> + virtual std::vector>> generateGridMapping( RigContourMapCalculator::ResultAggregationType resultAggregation, const std::vector& weights ); double interpolateValue( const cvf::Vec2d& gridPosition2d ) const; @@ -90,7 +90,7 @@ class RigContourMapProjection const std::vector>>& projected3dGridIndices() const; // Cell index and position conversion - std::vector cellsAtIJ( unsigned int i, unsigned int j ) const; + virtual std::vector cellsAtIJ( unsigned int i, unsigned int j ) const; static double maxValue( const std::vector& aggregatedResults ); static double minValue( const std::vector& aggregatedResults ); diff --git a/ApplicationLibCode/ReservoirDataModel/RigStatisticsContourMapProjection.cpp b/ApplicationLibCode/ReservoirDataModel/RigStatisticsContourMapProjection.cpp new file mode 100644 index 0000000000..6b91287e47 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigStatisticsContourMapProjection.cpp @@ -0,0 +1,139 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RigStatisticsContourMapProjection.h" + +#include "RigContourMapCalculator.h" +#include "RigContourMapGrid.h" + +#include "cafAssert.h" + +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigStatisticsContourMapProjection::RigStatisticsContourMapProjection( const RigContourMapGrid& contourMapGrid ) + : RigContourMapProjection( contourMapGrid ) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RigStatisticsContourMapProjection::~RigStatisticsContourMapProjection() +{ +} + +std::vector>> + RigStatisticsContourMapProjection::generateGridMapping( RigContourMapCalculator::ResultAggregationType resultAggregation, + const std::vector& weights ) +{ + // The grid mapping is usually necessary to produce the data. For the statistics projection + // the data is already available, so we can just ignore it. + return {}; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RigStatisticsContourMapProjection::generateAndSaveResults( const std::vector& result ) +{ + m_aggregatedResults = result; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigStatisticsContourMapProjection::findIntersectingCells( const cvf::BoundingBox& bbox ) const +{ + CAF_ASSERT( false ); + return {}; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RigStatisticsContourMapProjection::kLayer( size_t globalCellIdx ) const +{ + CAF_ASSERT( false ); + return 0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t RigStatisticsContourMapProjection::kLayers() const +{ + CAF_ASSERT( false ); + return 0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigStatisticsContourMapProjection::calculateOverlapVolume( size_t globalCellIdx, const cvf::BoundingBox& bbox ) const +{ + CAF_ASSERT( false ); + return 0.0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigStatisticsContourMapProjection::calculateRayLengthInCell( size_t globalCellIdx, + const cvf::Vec3d& highestPoint, + const cvf::Vec3d& lowestPoint ) const +{ + CAF_ASSERT( false ); + return 0.0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double RigStatisticsContourMapProjection::getParameterWeightForCell( size_t cellResultIdx, const std::vector& cellWeights ) const +{ + return 1.0; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RigStatisticsContourMapProjection::getMapCellVisibility( int viewStepIndex, + RigContourMapCalculator::ResultAggregationType resultAggregation ) + +{ + return std::vector( numberOfCells(), true ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> RigStatisticsContourMapProjection::cellsAtIJ( unsigned int i, unsigned int j ) const +{ + size_t cellIndex = m_contourMapGrid.cellIndexFromIJ( i, j ); + if ( cellIndex < m_aggregatedResults.size() && !std::isinf( m_aggregatedResults[cellIndex] ) && + !std::isnan( m_aggregatedResults[cellIndex] ) ) + { + return { std::make_pair( cellIndex, m_aggregatedResults[cellIndex] ) }; + } + + return std::vector>(); +} diff --git a/ApplicationLibCode/ReservoirDataModel/RigStatisticsContourMapProjection.h b/ApplicationLibCode/ReservoirDataModel/RigStatisticsContourMapProjection.h new file mode 100644 index 0000000000..34c9f8d838 --- /dev/null +++ b/ApplicationLibCode/ReservoirDataModel/RigStatisticsContourMapProjection.h @@ -0,0 +1,56 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2024- 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 +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RigContourMapCalculator.h" +#include "RigContourMapProjection.h" + +#include "cvfBoundingBox.h" + +class RigContourMapGrid; + +//================================================================================================== +/// +/// +//================================================================================================== +class RigStatisticsContourMapProjection : public RigContourMapProjection +{ +public: + RigStatisticsContourMapProjection( const RigContourMapGrid& contourMapGrid ); + virtual ~RigStatisticsContourMapProjection(); + + std::vector> cellsAtIJ( unsigned int i, unsigned int j ) const override; + + void generateAndSaveResults( const std::vector& results ); + + std::vector>> + generateGridMapping( RigContourMapCalculator::ResultAggregationType resultAggregation, const std::vector& weights ) override; + + std::vector getMapCellVisibility( int viewStepIndex, RigContourMapCalculator::ResultAggregationType resultAggregation ) override; + +protected: + using CellIndexAndResult = RigContourMapProjection::CellIndexAndResult; + + std::vector findIntersectingCells( const cvf::BoundingBox& bbox ) const override; + size_t kLayer( size_t globalCellIdx ) const override; + size_t kLayers() const override; + double calculateOverlapVolume( size_t globalCellIdx, const cvf::BoundingBox& bbox ) const override; + double calculateRayLengthInCell( size_t globalCellIdx, const cvf::Vec3d& highestPoint, const cvf::Vec3d& lowestPoint ) const override; + double getParameterWeightForCell( size_t cellResultIdx, const std::vector& parameterWeights ) const override; +};