Summary table (#9997)

Summary Table for showing summary vectors in table format
- Resampling on date resolution
- Active for group, region and well
- Right click menu option from Summary case tree
This commit is contained in:
Jørgen Herje
2023-03-23 14:10:30 +01:00
committed by GitHub
parent d9ba01b927
commit 36e01523cb
18 changed files with 1354 additions and 2 deletions

View File

@@ -40,6 +40,8 @@
#include "RimSummaryMultiPlot.h"
#include "RimSummaryMultiPlotCollection.h"
#include "RimSummaryPlot.h"
#include "RimSummaryTable.h"
#include "RimSummaryTableCollection.h"
#include "cafPdmObject.h"
@@ -203,6 +205,36 @@ bool RiaSummaryTools::isSummaryCrossPlot( const RimSummaryPlot* plot )
return dynamic_cast<const RimSummaryCrossPlot*>( plot );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryTable* RiaSummaryTools::parentSummaryTable( caf::PdmObject* object )
{
RimSummaryTable* summaryTable = nullptr;
if ( object )
{
object->firstAncestorOrThisOfType( summaryTable );
}
return summaryTable;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryTableCollection* RiaSummaryTools::parentSummaryTableCollection( caf::PdmObject* object )
{
RimSummaryTableCollection* summaryTableColl = nullptr;
if ( object )
{
object->firstAncestorOrThisOfType( summaryTableColl );
}
return summaryTableColl;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -260,7 +292,7 @@ void RiaSummaryTools::getSummaryCasesAndAddressesForCalculation( int
//--------------------------------------------------------------------------------------------------
std::pair<std::vector<time_t>, std::vector<double>> RiaSummaryTools::resampledValuesForPeriod( const RifEclipseSummaryAddress& address,
const std::vector<time_t>& timeSteps,
std::vector<double>& values,
const std::vector<double>& values,
RiaDefines::DateTimePeriod period )
{
RiaTimeHistoryCurveResampler resampler;

View File

@@ -33,6 +33,8 @@ class RimSummaryCrossPlotCollection;
class RimSummaryCaseMainCollection;
class RimSummaryCase;
class RimSummaryCaseCollection;
class RimSummaryTable;
class RimSummaryTableCollection;
class RimObservedDataCollection;
class RifEclipseSummaryAddress;
@@ -68,6 +70,9 @@ public:
static RimSummaryCrossPlotCollection* parentCrossPlotCollection( caf::PdmObject* object );
static bool isSummaryCrossPlot( const RimSummaryPlot* plot );
static RimSummaryTable* parentSummaryTable( caf::PdmObject* object );
static RimSummaryTableCollection* parentSummaryTableCollection( caf::PdmObject* object );
static bool hasAccumulatedData( const RifEclipseSummaryAddress& address );
static void getSummaryCasesAndAddressesForCalculation( int id,
std::vector<RimSummaryCase*>& cases,
@@ -75,7 +80,7 @@ public:
static std::pair<std::vector<time_t>, std::vector<double>> resampledValuesForPeriod( const RifEclipseSummaryAddress& address,
const std::vector<time_t>& timeSteps,
std::vector<double>& values,
const std::vector<double>& values,
RiaDefines::DateTimePeriod period );
static RimSummaryCase* summaryCaseById( int caseId );

View File

@@ -49,6 +49,8 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RicToggleYAxisLinkingFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicToggleXAxisLinkingFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicOpenSummaryPlotEditorFromMdiAreaFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryTableFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicDuplicateSummaryTableFeature.h
)
set(SOURCE_GROUP_SOURCE_FILES
@@ -102,6 +104,8 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RicToggleYAxisLinkingFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicToggleXAxisLinkingFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicOpenSummaryPlotEditorFromMdiAreaFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryTableFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicDuplicateSummaryTableFeature.cpp
)
list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@@ -0,0 +1,91 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- 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 "RicDuplicateSummaryTableFeature.h"
#include "RiaSummaryTools.h"
#include "RimMainPlotCollection.h"
#include "RimSummaryTable.h"
#include "RimSummaryTableCollection.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManagerTools.h"
#include "cvfAssert.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicDuplicateSummaryTableFeature, "RicDuplicateSummaryTableFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicDuplicateSummaryTableFeature::isCommandEnabled()
{
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicDuplicateSummaryTableFeature::onActionTriggered( bool isChecked )
{
caf::PdmObject* selObj = dynamic_cast<caf::PdmObject*>( caf::SelectionManager::instance()->selectedItem() );
RimSummaryTable* summaryTable = RiaSummaryTools::parentSummaryTable( selObj );
if ( !summaryTable ) return;
copyTableAndAddToCollection( summaryTable );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicDuplicateSummaryTableFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "Duplicate Summary Table" );
actionToSetup->setIcon( QIcon( ":/CorrelationMatrixPlot16x16.png" ) );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicDuplicateSummaryTableFeature::copyTableAndAddToCollection( RimSummaryTable* sourceTable )
{
RimSummaryTableCollection* summaryTableColl = RimMainPlotCollection::current()->summaryTableCollection();
if ( !summaryTableColl ) return;
RimSummaryTable* newSummaryTable =
dynamic_cast<RimSummaryTable*>( sourceTable->xmlCapability()->copyByXmlSerialization( caf::PdmDefaultObjectFactory::instance() ) );
CVF_ASSERT( newSummaryTable );
// Add table to collection
summaryTableColl->addTable( newSummaryTable );
// Resolve references after object has been inserted into the data model
newSummaryTable->resolveReferencesRecursively();
newSummaryTable->initAfterReadRecursively();
// Update name
QString nameOfCopy = QString( "Copy of " ) + sourceTable->description();
newSummaryTable->setDescription( nameOfCopy );
summaryTableColl->updateConnectedEditors();
newSummaryTable->loadDataAndUpdate();
}

View File

@@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
class RimSummaryTable;
//==================================================================================================
///
//==================================================================================================
class RicDuplicateSummaryTableFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
private:
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
private:
void copyTableAndAddToCollection( RimSummaryTable* sourceTable );
};

View File

@@ -0,0 +1,116 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- 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 "RicNewSummaryTableFeature.h"
#include "RiaSummaryTools.h"
#include "RimMainPlotCollection.h"
#include "RimSummaryAddress.h"
#include "RimSummaryTable.h"
#include "RimSummaryTableCollection.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManagerTools.h"
#include "cvfAssert.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicNewSummaryTableFeature, "RicNewSummaryTableFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewSummaryTableFeature::isCommandEnabled()
{
RimSummaryTableCollection* tableColl = nullptr;
// Summary table collection selection
caf::PdmObject* selObj = dynamic_cast<caf::PdmObject*>( caf::SelectionManager::instance()->selectedItem() );
if ( selObj )
{
tableColl = RiaSummaryTools::parentSummaryTableCollection( selObj );
}
if ( tableColl ) return true;
// Summary Address selection - only for enabled categories
RimSummaryAddress* selectedSummaryAddress = nullptr;
if ( selObj )
{
selObj->firstAncestorOrThisOfType( selectedSummaryAddress );
}
if ( selectedSummaryAddress && m_enabledCategories.contains( selectedSummaryAddress->address().category() ) ) return true;
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewSummaryTableFeature::onActionTriggered( bool isChecked )
{
RimSummaryTableCollection* summaryTableColl = RimMainPlotCollection::current()->summaryTableCollection();
if ( !summaryTableColl ) return;
caf::PdmObject* selObj = dynamic_cast<caf::PdmObject*>( caf::SelectionManager::instance()->selectedItem() );
RimSummaryAddress* selectedSummaryAddress = nullptr;
if ( selObj )
{
selObj->firstAncestorOrThisOfType( selectedSummaryAddress );
}
RimSummaryTable* summaryTable = nullptr;
if ( selectedSummaryAddress )
{
const auto adrObj = selectedSummaryAddress->address();
if ( !m_enabledCategories.contains( adrObj.category() ) ) return;
RimSummaryCase* summaryCase = RiaSummaryTools::summaryCaseById( selectedSummaryAddress->caseId() );
if ( !summaryCase ) return;
summaryTable = summaryTableColl->createSummaryTableFromCategoryAndVectorName( summaryCase,
adrObj.category(),
QString::fromStdString( adrObj.vectorName() ) );
}
else
{
summaryTable = summaryTableColl->createDefaultSummaryTable();
}
// Add summary table to collection
if ( summaryTable )
{
summaryTableColl->addTable( summaryTable );
summaryTableColl->updateConnectedEditors();
summaryTable->loadDataAndUpdate();
RiuPlotMainWindowTools::showPlotMainWindow();
RiuPlotMainWindowTools::onObjectAppended( summaryTable );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewSummaryTableFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "New Summary Table" );
actionToSetup->setIcon( QIcon( ":/CorrelationMatrixPlot16x16.png" ) );
}

View File

@@ -0,0 +1,43 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
#include "RifEclipseSummaryAddress.h"
#include <set>
//==================================================================================================
///
//==================================================================================================
class RicNewSummaryTableFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
private:
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
private:
const std::set<RifEclipseSummaryAddress::SummaryVarCategory> m_enabledCategories = { RifEclipseSummaryAddress::SUMMARY_WELL,
RifEclipseSummaryAddress::SUMMARY_REGION,
RifEclipseSummaryAddress::SUMMARY_GROUP };
};

View File

@@ -134,6 +134,8 @@
#include "RimSummaryMultiPlot.h"
#include "RimSummaryMultiPlotCollection.h"
#include "RimSummaryPlot.h"
#include "RimSummaryTable.h"
#include "RimSummaryTableCollection.h"
#include "RimSummaryTimeAxisProperties.h"
#include "RimSurface.h"
#include "RimSurfaceCollection.h"
@@ -609,6 +611,14 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "Separator";
menuBuilder << "RicNewSummaryCrossPlotFeature";
}
else if ( dynamic_cast<RimSummaryTableCollection*>( firstUiItem ) )
{
menuBuilder << "RicNewSummaryTableFeature";
}
else if ( dynamic_cast<RimSummaryTable*>( firstUiItem ) )
{
menuBuilder << "RicDuplicateSummaryTableFeature";
}
else if ( dynamic_cast<RimWellLogPlot*>( firstUiItem ) && !dynamic_cast<RimWellPltPlot*>( firstUiItem ) )
{
menuBuilder << "RicPasteWellLogPlotFeature";
@@ -1244,6 +1254,8 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicNewSummaryMultiPlotFromDataVectorFeature";
menuBuilder << "RicAppendSummaryCurvesForSummaryAddressesFeature";
menuBuilder << "RicAppendSummaryPlotsForSummaryAddressesFeature";
menuBuilder << "Separator";
menuBuilder << "RicNewSummaryTableFeature";
}
#ifdef USE_ODB_API
else if ( dynamic_cast<RimWellIASettings*>( firstUiItem ) )

View File

@@ -45,6 +45,7 @@
#include "RimSummaryMultiPlot.h"
#include "RimSummaryMultiPlotCollection.h"
#include "RimSummaryPlotCollection.h"
#include "RimSummaryTableCollection.h"
#include "RimVfpPlotCollection.h"
#include "RimViewWindow.h"
#include "RimWellLogPlot.h"
@@ -97,6 +98,9 @@ RimMainPlotCollection::RimMainPlotCollection()
CAF_PDM_InitFieldNoDefault( &m_summaryCrossPlotCollection, "SummaryCrossPlotCollection", "Summary Cross Plots" );
m_summaryCrossPlotCollection.uiCapability()->setUiTreeHidden( true );
CAF_PDM_InitFieldNoDefault( &m_summaryTableCollection, "SummaryTableCollection", "Summary Tables" );
m_summaryTableCollection.uiCapability()->setUiTreeHidden( true );
CAF_PDM_InitFieldNoDefault( &m_flowPlotCollection, "FlowPlotCollection", "Flow Diagnostics Plots" );
m_flowPlotCollection.uiCapability()->setUiTreeHidden( true );
@@ -127,6 +131,7 @@ RimMainPlotCollection::RimMainPlotCollection()
m_pltPlotCollection = new RimPltPlotCollection();
m_summaryMultiPlotCollection = new RimSummaryMultiPlotCollection();
m_summaryCrossPlotCollection = new RimSummaryCrossPlotCollection();
m_summaryTableCollection = new RimSummaryTableCollection();
m_flowPlotCollection = new RimFlowPlotCollection();
m_gridCrossPlotCollection = new RimGridCrossPlotCollection;
m_saturationPressurePlotCollection = new RimSaturationPressurePlotCollection;
@@ -237,6 +242,14 @@ RimSummaryCrossPlotCollection* RimMainPlotCollection::summaryCrossPlotCollection
return m_summaryCrossPlotCollection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryTableCollection* RimMainPlotCollection::summaryTableCollection() const
{
return m_summaryTableCollection();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -443,6 +456,7 @@ std::vector<RimPlotCollection*> RimMainPlotCollection::allPlotCollections() cons
plotCollections.push_back( wellLogPlotCollection() );
plotCollections.push_back( summaryMultiPlotCollection() );
plotCollections.push_back( summaryCrossPlotCollection() );
plotCollections.push_back( summaryTableCollection() );
plotCollections.push_back( gridCrossPlotCollection() );
plotCollections.push_back( analysisPlotCollection() );
plotCollections.push_back( vfpPlotCollection() );

View File

@@ -34,6 +34,7 @@ class RimGridCrossPlotCollection;
class RimMultiPlotCollection;
class RimSummaryMultiPlotCollection;
class RimSummaryCrossPlotCollection;
class RimSummaryTableCollection;
class RimSummaryPlot;
class RimSummaryPlotCollection;
class RifReaderEclipseSummary;
@@ -68,6 +69,7 @@ public:
RimPltPlotCollection* pltPlotCollection() const;
RimSummaryMultiPlotCollection* summaryMultiPlotCollection() const;
RimSummaryCrossPlotCollection* summaryCrossPlotCollection() const;
RimSummaryTableCollection* summaryTableCollection() const;
RimAnalysisPlotCollection* analysisPlotCollection() const;
RimCorrelationPlotCollection* correlationPlotCollection() const;
RimFlowPlotCollection* flowPlotCollection() const;
@@ -111,6 +113,7 @@ private:
caf::PdmChildField<RimPltPlotCollection*> m_pltPlotCollection;
caf::PdmChildField<RimSummaryMultiPlotCollection*> m_summaryMultiPlotCollection;
caf::PdmChildField<RimSummaryCrossPlotCollection*> m_summaryCrossPlotCollection;
caf::PdmChildField<RimSummaryTableCollection*> m_summaryTableCollection;
caf::PdmChildField<RimAnalysisPlotCollection*> m_analysisPlotCollection;
caf::PdmChildField<RimCorrelationPlotCollection*> m_correlationPlotCollection;
caf::PdmChildField<RimFlowPlotCollection*> m_flowPlotCollection;

View File

@@ -79,6 +79,7 @@
#include "RimSummaryCaseMainCollection.h"
#include "RimSummaryCrossPlotCollection.h"
#include "RimSummaryMultiPlotCollection.h"
#include "RimSummaryTableCollection.h"
#include "RimSurfaceCollection.h"
#include "RimTools.h"
#include "RimUserDefinedPolylinesAnnotation.h"
@@ -1412,6 +1413,11 @@ void RimProject::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, Q
uiTreeOrdering.add( m_mainPlotCollection->summaryCrossPlotCollection() );
}
if ( m_mainPlotCollection->summaryTableCollection() )
{
uiTreeOrdering.add( m_mainPlotCollection->summaryTableCollection() );
}
if ( m_mainPlotCollection->wellLogPlotCollection() )
{
uiTreeOrdering.add( m_mainPlotCollection->wellLogPlotCollection() );

View File

@@ -47,6 +47,8 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimSummaryAddressModifier.h
${CMAKE_CURRENT_LIST_DIR}/RimRftCase.h
${CMAKE_CURRENT_LIST_DIR}/RimCsvSummaryCase.h
${CMAKE_CURRENT_LIST_DIR}/RimSummaryTable.h
${CMAKE_CURRENT_LIST_DIR}/RimSummaryTableCollection.h
)
set(SOURCE_GROUP_SOURCE_FILES
@@ -98,6 +100,8 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimSummaryAddressModifier.cpp
${CMAKE_CURRENT_LIST_DIR}/RimRftCase.cpp
${CMAKE_CURRENT_LIST_DIR}/RimCsvSummaryCase.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSummaryTable.cpp
${CMAKE_CURRENT_LIST_DIR}/RimSummaryTableCollection.cpp
)
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})

View File

@@ -0,0 +1,652 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- 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 "RimSummaryTable.h"
#include "RiaPreferences.h"
#include "RiaQDateTimeTools.h"
#include "RiaSummaryTools.h"
#include "RiaTimeHistoryCurveResampler.h"
#include "RifSummaryReaderInterface.h"
#include "RimEclipseResultCase.h"
#include "RimEclipseView.h"
#include "RimRegularLegendConfig.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseMainCollection.h"
#include "RimTools.h"
#include "RiuMatrixPlotWidget.h"
#include "cafPdmUiComboBoxEditor.h"
#include "cafPdmUiPushButtonEditor.h"
#include "cafPdmUiToolButtonEditor.h"
#include "cafPdmUiTreeSelectionEditor.h"
#include "cvfScalarMapper.h"
CAF_PDM_SOURCE_INIT( RimSummaryTable, "RimSummaryTable" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryTable::RimSummaryTable()
{
CAF_PDM_InitObject( "Summary Table", ":/CorrelationMatrixPlot16x16.png" );
uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitField( &m_tableName, "TableName", QString( "Summary Table" ), "Name" );
CAF_PDM_InitField( &m_isAutomaticName, "AutomaticTableName", true, "Automatic Name" );
CAF_PDM_InitFieldNoDefault( &m_case, "SummaryCase", "Case" );
m_case.uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitFieldNoDefault( &m_vector, "Vectors", "Vector" );
m_vector.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_categories, "Categories", "Category" );
m_categories.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() );
m_categories = RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL;
CAF_PDM_InitFieldNoDefault( &m_resamplingSelection, "ResamplingSelection", "Date Resampling" );
m_resamplingSelection.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() );
m_resamplingSelection = RiaDefines::DateTimePeriod::YEAR;
CAF_PDM_InitField( &m_thresholdValue, "ThresholdValue", 0.0, "Threshold" );
// Table settings
CAF_PDM_InitField( &m_showValueLabels, "ShowValueLabels", false, "Show Value Labels" );
// Font control
CAF_PDM_InitFieldNoDefault( &m_axisTitleFontSize, "AxisTitleFontSize", "Axis Title Font Size" );
CAF_PDM_InitFieldNoDefault( &m_axisLabelFontSize, "AxisLabelFontSize", "Axis Label Font Size" );
CAF_PDM_InitFieldNoDefault( &m_valueLabelFontSize, "ValueLabelFontSize", "Value Label Font Size" );
m_axisTitleFontSize = caf::FontTools::RelativeSize::Large;
m_axisLabelFontSize = caf::FontTools::RelativeSize::Medium;
CAF_PDM_InitFieldNoDefault( &m_legendConfig, "LegendConfig", "" );
m_legendConfig = new RimRegularLegendConfig();
m_legendConfig->setShowLegend( true );
m_legendConfig->setAutomaticRanges( 0.0, 100.0, 0.0, 100.0 );
m_legendConfig->setColorLegend( RimRegularLegendConfig::mapToColorLegend( RimRegularLegendConfig::ColorRangesType::HEAT_MAP ) );
setLegendsVisible( true );
setAsPlotMdiWindow();
setShowWindow( true );
setDeletable( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryTable::~RimSummaryTable()
{
if ( isMdiWindow() ) removeMdiWindowFromMdiArea();
cleanupBeforeClose();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTable::setDefaultCaseAndCategoryAndVectorName()
{
const auto summaryCases = getToplevelSummaryCases();
m_case = nullptr;
m_categories = RifEclipseSummaryAddress::SUMMARY_WELL;
m_vector = "";
m_tableName = createTableName();
if ( summaryCases.empty() ) return;
m_case = summaryCases.front();
const auto summaryReader = m_case->summaryReader();
if ( !summaryReader ) return;
const auto categoryVectors = getCategoryVectorsFromSummaryReader( summaryReader, m_categories() );
if ( !categoryVectors.empty() )
{
m_vector = *categoryVectors.begin();
}
m_tableName = createTableName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTable::setFromCaseAndCategoryAndVectorName( RimSummaryCase* summaryCase,
RifEclipseSummaryAddress::SummaryVarCategory category,
const QString& vectorName )
{
m_case = summaryCase;
m_categories = category;
m_vector = vectorName;
m_tableName = createTableName();
onLoadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTable::setDescription( const QString& description )
{
m_tableName = description;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTable::cleanupBeforeClose()
{
if ( m_matrixPlotWidget )
{
m_matrixPlotWidget->qwtPlot()->detachItems();
m_matrixPlotWidget->setParent( nullptr );
delete m_matrixPlotWidget;
m_matrixPlotWidget = nullptr;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTable::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
{
RimViewWindow::fieldChangedByUi( changedField, oldValue, newValue );
if ( changedField == &m_case )
{
if ( m_case )
{
auto* summaryReader = m_case->summaryReader();
const auto categoryVectors = getCategoryVectorsFromSummaryReader( summaryReader, m_categories() );
if ( summaryReader && !categoryVectors.empty() )
{
m_vector = *categoryVectors.begin();
}
else
{
m_vector = QString( "" );
}
}
if ( m_isAutomaticName )
{
m_tableName = createTableName();
}
onLoadDataAndUpdate();
}
else if ( changedField == &m_categories )
{
if ( m_case )
{
auto* summaryReader = m_case->summaryReader();
const auto categoryVectors = getCategoryVectorsFromSummaryReader( summaryReader, m_categories() );
if ( summaryReader && !categoryVectors.empty() )
{
m_vector = *categoryVectors.begin();
}
else
{
m_vector = QString( "" );
}
}
else
{
m_vector = QString( " " );
}
if ( m_isAutomaticName )
{
m_tableName = createTableName();
}
onLoadDataAndUpdate();
}
else if ( changedField == &m_vector || changedField == &m_resamplingSelection || changedField == &m_thresholdValue )
{
if ( m_isAutomaticName )
{
m_tableName = createTableName();
}
onLoadDataAndUpdate();
}
else if ( changedField == &m_isAutomaticName && m_isAutomaticName )
{
m_tableName = createTableName();
}
else if ( m_matrixPlotWidget && changedField == &m_showValueLabels )
{
m_matrixPlotWidget->setShowValueLabel( m_showValueLabels );
}
else if ( m_matrixPlotWidget && ( changedField == &m_titleFontSize || changedField == &m_legendFontSize ||
changedField == &m_axisTitleFontSize || changedField == &m_axisLabelFontSize ) )
{
m_matrixPlotWidget->setPlotTitleFontSize( titleFontSize() );
m_matrixPlotWidget->setLegendFontSize( legendFontSize() );
m_matrixPlotWidget->setAxisTitleFontSize( axisTitleFontSize() );
m_matrixPlotWidget->setAxisLabelFontSize( axisLabelFontSize() );
}
else if ( changedField == &m_valueLabelFontSize && m_matrixPlotWidget )
{
m_matrixPlotWidget->setValueFontSize( valueLabelFontSize() );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTable::childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField )
{
onLoadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTable::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
RimViewWindow::defineUiOrdering( uiConfigName, uiOrdering );
caf::PdmUiGroup& dataGroup = *uiOrdering.addNewGroup( "Plot Data" );
dataGroup.add( &m_tableName );
dataGroup.add( &m_isAutomaticName );
dataGroup.add( &m_case );
dataGroup.add( &m_categories );
dataGroup.add( &m_vector );
dataGroup.add( &m_resamplingSelection );
dataGroup.add( &m_thresholdValue );
caf::PdmUiGroup* tableSettingsGroup = uiOrdering.addNewGroup( "Table Settings" );
tableSettingsGroup->add( &m_showValueLabels );
m_legendConfig->uiOrdering( "FlagColorsAndMappingModeOnly", *tableSettingsGroup );
caf::PdmUiGroup* fontGroup = uiOrdering.addNewGroup( "Fonts" );
fontGroup->setCollapsedByDefault();
RimPlotWindow::uiOrderingForFonts( uiConfigName, *fontGroup );
fontGroup->add( &m_axisTitleFontSize );
fontGroup->add( &m_axisLabelFontSize );
fontGroup->add( &m_valueLabelFontSize );
uiOrdering.skipRemainingFields( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimSummaryTable::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
{
QList<caf::PdmOptionItemInfo> options = RimPlotWindow::calculateValueOptions( fieldNeedingOptions );
if ( !options.empty() )
{
return options;
}
else if ( fieldNeedingOptions == &m_case )
{
std::vector<RimSummaryCase*> summaryCases = getToplevelSummaryCases();
for ( auto* summaryCase : summaryCases )
{
options.push_back( caf::PdmOptionItemInfo( summaryCase->displayCaseName(), summaryCase, false, summaryCase->uiIconProvider() ) );
}
}
else if ( fieldNeedingOptions == &m_categories )
{
options.push_back( caf::PdmOptionItemInfo( caf::AppEnum<RifEclipseSummaryAddress::SummaryVarCategory>::uiText(
RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL ),
RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL ) );
options.push_back( caf::PdmOptionItemInfo( caf::AppEnum<RifEclipseSummaryAddress::SummaryVarCategory>::uiText(
RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_GROUP ),
RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_GROUP ) );
options.push_back( caf::PdmOptionItemInfo( caf::AppEnum<RifEclipseSummaryAddress::SummaryVarCategory>::uiText(
RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_REGION ),
RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_REGION ) );
}
else if ( fieldNeedingOptions == &m_vector && m_case )
{
auto* summaryReader = m_case->summaryReader();
if ( summaryReader )
{
const auto categoryVectorsUnion = getCategoryVectorsFromSummaryReader( summaryReader, m_categories() );
for ( const auto& vectorName : categoryVectorsUnion )
{
options.push_back( caf::PdmOptionItemInfo( vectorName, vectorName ) );
}
}
}
else if ( fieldNeedingOptions == &m_axisTitleFontSize || fieldNeedingOptions == &m_axisLabelFontSize ||
fieldNeedingOptions == &m_valueLabelFontSize )
{
options = caf::FontTools::relativeSizeValueOptions( RiaPreferences::current()->defaultPlotFontSize() );
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTable::onLoadDataAndUpdate()
{
updateMdiWindowVisibility();
if ( m_matrixPlotWidget == nullptr || m_case == nullptr )
{
return;
}
const auto summaryReader = m_case->summaryReader();
if ( !summaryReader )
{
return;
}
// Struct for storing vector data
struct VectorData
{
QString category;
QString name;
std::vector<double> values;
time_t firstTimeStep;
time_t lastTimeStep;
bool hasValueAboveThreshold;
};
// Create time step value for vectors with no values above threshold
const time_t invalidTimeStep = 0;
// Get all summary addresses for selected category (group, region, well)
std::vector<VectorData> vectorDataCollection;
std::set<time_t> timeStepsUnion;
const auto summaryAddresses = getSummaryAddressesFromReader( summaryReader, m_categories(), m_vector() );
QString unitName;
for ( const auto& adr : summaryAddresses )
{
std::vector<double> values;
summaryReader->values( adr, &values );
const std::vector<time_t> timeSteps = summaryReader->timeSteps( adr );
const QString vectorName = QString::fromStdString( adr.vectorName() );
const QString categoryName = getCategoryNameFromAddress( adr );
unitName = QString::fromStdString( summaryReader->unitName( adr ) );
// Get re-sampled time steps and values
const auto [resampledTimeSteps, resampledValues] =
RiaSummaryTools::resampledValuesForPeriod( adr, timeSteps, values, m_resamplingSelection() );
// First and last time step with value above threshold and set flag (first and last should be valid/invalid simultaneously)
const auto firstItr =
std::find_if( resampledValues.begin(), resampledValues.end(), [&]( double value ) { return value > m_thresholdValue; } );
const auto lastItr =
std::find_if( resampledValues.rbegin(), resampledValues.rend(), [&]( double value ) { return value > m_thresholdValue; } );
const auto firstIdx = static_cast<size_t>( std::distance( resampledValues.begin(), firstItr ) );
const auto lastIdx = resampledValues.size() - static_cast<size_t>( std::distance( resampledValues.rbegin(), lastItr ) ) - 1;
const bool hasValueAboveThreshold = firstIdx < resampledTimeSteps.size() && lastIdx < resampledTimeSteps.size();
const auto firstTimeStep = hasValueAboveThreshold ? resampledTimeSteps[firstIdx] : invalidTimeStep;
const auto lastTimeStep = hasValueAboveThreshold ? resampledTimeSteps[lastIdx] : invalidTimeStep;
// Add to vector of VectorData
VectorData vectorData{ .category = categoryName,
.name = vectorName,
.values = resampledValues,
.firstTimeStep = firstTimeStep,
.lastTimeStep = lastTimeStep,
.hasValueAboveThreshold = hasValueAboveThreshold };
vectorDataCollection.push_back( vectorData );
// Build union of resampled time steps
timeStepsUnion.insert( resampledTimeSteps.begin(), resampledTimeSteps.end() );
}
// Sort vector data on date (vectors with no values above threshold placed last):
std::sort( vectorDataCollection.begin(), vectorDataCollection.end(), []( const VectorData& v1, const VectorData& v2 ) {
if ( !v1.hasValueAboveThreshold ) return false;
if ( v1.hasValueAboveThreshold && !v2.hasValueAboveThreshold ) return true;
if ( v1.firstTimeStep < v2.firstTimeStep ) return true;
if ( v1.firstTimeStep == v2.firstTimeStep && v1.lastTimeStep < v2.lastTimeStep ) return true;
return false;
} );
// Convert to strings
std::vector<QString> timeStepStrings;
for ( const auto& timeStep : timeStepsUnion )
{
timeStepStrings.push_back( RiaQDateTimeTools::fromTime_t( timeStep ).toString( dateFormatString() ) );
}
// Clear matrix plot
m_matrixPlotWidget->clearPlotData();
m_matrixPlotWidget->setColumnHeaders( timeStepStrings );
double maxValue = 0.0;
double minValue = 0.0;
for ( const auto& vectorData : vectorDataCollection )
{
const auto maxRowValue = *std::max_element( vectorData.values.begin(), vectorData.values.end() );
const auto minRowValue = *std::min_element( vectorData.values.begin(), vectorData.values.end() );
if ( maxRowValue < m_thresholdValue() ) continue;
maxValue = std::max( maxValue, maxRowValue );
minValue = std::min( minValue, minRowValue );
m_matrixPlotWidget->setRowValues( vectorData.category, vectorData.values );
}
if ( m_legendConfig )
{
m_legendConfig->setAutomaticRanges( minValue, maxValue, 0.0, 0.0 );
}
// Set titles and font sizes
const QString title =
QString( "Summary Table - %1 [%2]<br>Date Resampling: %3</br>" ).arg( m_vector() ).arg( unitName ).arg( m_resamplingSelection().uiText() );
m_matrixPlotWidget->setPlotTitle( title );
m_matrixPlotWidget->setRowTitle( QString( "%1s" ).arg( m_categories().uiText() ) );
m_matrixPlotWidget->setColumnTitle( "Time steps" );
m_matrixPlotWidget->setPlotTitleFontSize( titleFontSize() );
m_matrixPlotWidget->setLegendFontSize( legendFontSize() );
m_matrixPlotWidget->setAxisTitleFontSize( axisTitleFontSize() );
m_matrixPlotWidget->setAxisLabelFontSize( axisLabelFontSize() );
m_matrixPlotWidget->createPlot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimSummaryTable::viewWidget()
{
return m_matrixPlotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QImage RimSummaryTable::snapshotWindowContent()
{
QImage image;
if ( m_matrixPlotWidget )
{
QPixmap pix = m_matrixPlotWidget->grab();
image = pix.toImage();
}
return image;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTable::zoomAll()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* RimSummaryTable::createViewWidget( QWidget* mainWindowParent )
{
m_matrixPlotWidget = new RiuMatrixPlotWidget( this, m_legendConfig, mainWindowParent );
m_matrixPlotWidget->setShowValueLabel( m_showValueLabels );
m_matrixPlotWidget->setUseInvalidValueColor( true );
return m_matrixPlotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTable::deleteViewWidget()
{
cleanupBeforeClose();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryTable::description() const
{
return m_tableName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTable::doRenderWindowContent( QPaintDevice* paintDevice )
{
return;
}
caf::PdmFieldHandle* RimSummaryTable::userDescriptionField()
{
return &m_tableName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSummaryTable::axisTitleFontSize() const
{
return caf::FontTools::absolutePointSize( RiaPreferences::current()->defaultPlotFontSize(), m_axisTitleFontSize() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSummaryTable::axisLabelFontSize() const
{
return caf::FontTools::absolutePointSize( RiaPreferences::current()->defaultPlotFontSize(), m_axisLabelFontSize() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimSummaryTable::valueLabelFontSize() const
{
return caf::FontTools::absolutePointSize( RiaPreferences::current()->defaultPlotFontSize(), m_valueLabelFontSize() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryTable::createTableName() const
{
return QString( "Summary Table - %1" ).arg( m_vector() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<double, double> RimSummaryTable::createLegendMinMaxValues( const double maxTableValue ) const
{
return std::make_pair( 0.0, maxTableValue );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryTable::dateFormatString() const
{
return RiaQDateTimeTools::dateFormatString( RiaPreferences::current()->dateFormat(),
RiaDefines::DateFormatComponents::DATE_FORMAT_YEAR_MONTH_DAY );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RimSummaryTable::getSummaryAddressesFromReader( const RifSummaryReaderInterface* summaryReader,
RifEclipseSummaryAddress::SummaryVarCategory category,
const QString& vector ) const
{
if ( !summaryReader ) return std::set<RifEclipseSummaryAddress>();
std::set<RifEclipseSummaryAddress> categoryAddresses;
const std::set<RifEclipseSummaryAddress> allResultAddresses = summaryReader->allResultAddresses();
const std::string selectedVector = vector.toStdString();
for ( const auto& resAdr : allResultAddresses )
{
if ( resAdr.category() != category || resAdr.vectorName() != selectedVector ) continue;
categoryAddresses.emplace( resAdr );
}
return categoryAddresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QString> RimSummaryTable::getCategoryVectorsFromSummaryReader( const RifSummaryReaderInterface* summaryReader,
RifEclipseSummaryAddress::SummaryVarCategory category ) const
{
if ( !summaryReader ) return std::set<QString>();
if ( category != RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL &&
category != RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_GROUP &&
category != RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_REGION )
{
return std::set<QString>();
}
std::set<QString> categoryVectors;
const std::set<RifEclipseSummaryAddress> allResultAddresses = summaryReader->allResultAddresses();
for ( const auto& resAdr : allResultAddresses )
{
if ( resAdr.category() != category ) continue;
const QString vectorName = QString::fromStdString( resAdr.vectorName() );
categoryVectors.emplace( vectorName );
}
return categoryVectors;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimSummaryTable::getCategoryNameFromAddress( const RifEclipseSummaryAddress& address ) const
{
if ( address.category() == RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_WELL )
{
return QString::fromStdString( address.wellName() );
}
else if ( address.category() == RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_GROUP )
{
return QString::fromStdString( address.groupName() );
}
else if ( address.category() == RifEclipseSummaryAddress::SummaryVarCategory::SUMMARY_REGION )
{
return QString( "Region %1" ).arg( address.regionNumber() );
}
return QString();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCase*> RimSummaryTable::getToplevelSummaryCases() const
{
RimSummaryCaseMainCollection* summaryCaseMainCollection = RiaSummaryTools::summaryCaseMainCollection();
if ( !summaryCaseMainCollection ) return {};
return summaryCaseMainCollection->topLevelSummaryCases();
}

View File

@@ -0,0 +1,120 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimPlotWindow.h"
#include "RiaDateTimeDefines.h"
#include "RifEclipseSummaryAddress.h"
#include "cafPdmField.h"
#include "cafPdmPtrField.h"
#include <QDateTime>
#include <QPointer>
#include <QString>
class RifSummaryReaderInterface;
class RimSummaryCase;
class RimRegularLegendConfig;
class RiuMatrixPlotWidget;
//==================================================================================================
///
//==================================================================================================
class RimSummaryTable : public RimPlotWindow
{
CAF_PDM_HEADER_INIT;
public:
RimSummaryTable();
~RimSummaryTable() override;
void setDefaultCaseAndCategoryAndVectorName();
void setFromCaseAndCategoryAndVectorName( RimSummaryCase* summaryCase,
RifEclipseSummaryAddress::SummaryVarCategory category,
const QString& vectorName );
void setDescription( const QString& description );
virtual QString description() const override;
private:
void cleanupBeforeClose();
void onLoadDataAndUpdate() override;
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
// Inherited via RimPlotWindow
virtual void doRenderWindowContent( QPaintDevice* paintDevice ) override;
// Inherited via RimViewWindow
virtual QWidget* viewWidget() override;
virtual QImage snapshotWindowContent() override;
virtual void zoomAll() override;
virtual QWidget* createViewWidget( QWidget* mainWindowParent ) override;
virtual void deleteViewWidget() override;
// PDM methods
caf::PdmFieldHandle* userDescriptionField() override;
int axisTitleFontSize() const;
int axisLabelFontSize() const;
int valueLabelFontSize() const;
QString createTableName() const;
private:
std::pair<double, double> createLegendMinMaxValues( const double maxTableValue ) const;
QString dateFormatString() const;
std::set<RifEclipseSummaryAddress> getSummaryAddressesFromReader( const RifSummaryReaderInterface* summaryReader,
RifEclipseSummaryAddress::SummaryVarCategory category,
const QString& vector ) const;
std::set<QString> getCategoryVectorsFromSummaryReader( const RifSummaryReaderInterface* summaryReader,
RifEclipseSummaryAddress::SummaryVarCategory category ) const;
QString getCategoryNameFromAddress( const RifEclipseSummaryAddress& address ) const;
std::vector<RimSummaryCase*> getToplevelSummaryCases() const;
private:
// Matrix plot for visualizing table data
QPointer<RiuMatrixPlotWidget> m_matrixPlotWidget;
caf::PdmField<QString> m_tableName;
caf::PdmField<bool> m_isAutomaticName;
caf::PdmPtrField<RimSummaryCase*> m_case;
caf::PdmField<caf::AppEnum<RifEclipseSummaryAddress::SummaryVarCategory>> m_categories;
caf::PdmField<QString> m_vector;
caf::PdmField<caf::AppEnum<RiaDefines::DateTimePeriod>> m_resamplingSelection;
caf::PdmField<double> m_thresholdValue;
caf::PdmChildField<RimRegularLegendConfig*> m_legendConfig;
caf::PdmField<caf::FontTools::RelativeSizeEnum> m_axisTitleFontSize;
caf::PdmField<caf::FontTools::RelativeSizeEnum> m_axisLabelFontSize;
caf::PdmField<caf::FontTools::RelativeSizeEnum> m_valueLabelFontSize;
caf::PdmField<bool> m_showValueLabels;
const int m_initialNumberOfTimeSteps = 10;
};

View File

@@ -0,0 +1,140 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RimSummaryTableCollection.h"
#include "RimProject.h"
#include "RimSummaryCase.h"
#include "RimSummaryCrossPlot.h"
#include "RimSummaryPlot.h"
#include "cafPdmFieldReorderCapability.h"
CAF_PDM_SOURCE_INIT( RimSummaryTableCollection, "RimSummaryTableCollection" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryTableCollection::RimSummaryTableCollection()
{
CAF_PDM_InitObject( "Summary Tables", ":/CorrelationMatrixPlot16x16.png" );
CAF_PDM_InitFieldNoDefault( &m_summaryTables, "SummaryTables", "Summary Tables" );
m_summaryTables.uiCapability()->setUiTreeHidden( true );
caf::PdmFieldReorderCapability::addToField( &m_summaryTables );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryTableCollection::~RimSummaryTableCollection()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTableCollection::deleteAllPlots()
{
m_summaryTables.deleteChildren();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTableCollection::loadDataAndUpdateAllPlots()
{
for ( RimSummaryTable* table : m_summaryTables )
{
if ( !table ) continue;
table->loadDataAndUpdate();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RimSummaryTableCollection::plotCount() const
{
return tableCount();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryTable*> RimSummaryTableCollection::tables() const
{
return m_summaryTables.children();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RimSummaryTableCollection::tableCount() const
{
return m_summaryTables.size();
}
void RimSummaryTableCollection::addTable( RimSummaryTable* table )
{
insertTable( table, tableCount() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTableCollection::insertTable( RimSummaryTable* table, size_t index )
{
m_summaryTables.insert( index, table );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryTableCollection::removeTable( RimSummaryTable* table )
{
m_summaryTables.removeChild( table );
updateAllRequiredEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryTable* RimSummaryTableCollection::createDefaultSummaryTable()
{
RimSummaryTable* table = new RimSummaryTable();
table->setDefaultCaseAndCategoryAndVectorName();
table->setAsPlotMdiWindow();
return table;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryTable* RimSummaryTableCollection::createSummaryTableFromCategoryAndVectorName( RimSummaryCase* summaryCase,
RifEclipseSummaryAddress::SummaryVarCategory category,
const QString& vectorName )
{
RimSummaryTable* table = new RimSummaryTable();
table->setFromCaseAndCategoryAndVectorName( summaryCase, category, vectorName );
table->setAsPlotMdiWindow();
return table;
}

View File

@@ -0,0 +1,58 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023- 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.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimAbstractPlotCollection.h"
#include "RimSummaryTable.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmObject.h"
class RimSummaryCase;
//==================================================================================================
///
///
//==================================================================================================
class RimSummaryTableCollection : public caf::PdmObject, public RimPlotCollection
{
CAF_PDM_HEADER_INIT;
public:
RimSummaryTableCollection();
~RimSummaryTableCollection() override;
void deleteAllPlots() override;
void loadDataAndUpdateAllPlots() override;
size_t plotCount() const override;
std::vector<RimSummaryTable*> tables() const;
size_t tableCount() const;
void addTable( RimSummaryTable* table );
void insertTable( RimSummaryTable* table, size_t index );
void removeTable( RimSummaryTable* table );
RimSummaryTable* createDefaultSummaryTable();
RimSummaryTable* createSummaryTableFromCategoryAndVectorName( RimSummaryCase* summaryCase,
RifEclipseSummaryAddress::SummaryVarCategory category,
const QString& vectorName );
private:
caf::PdmChildArrayField<RimSummaryTable*> m_summaryTables;
};

View File

@@ -194,6 +194,16 @@ RimViewWindow* RiuMatrixPlotWidget::ownerViewWindow() const
return m_ownerViewWindow;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMatrixPlotWidget::contextMenuEvent( QContextMenuEvent* )
{
// Added empty override to preventing menu for Mdi Area
// I.e.: RiuContextMenuLauncher for RiuPlotMainWindow (mdi area)
return;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -77,6 +77,9 @@ public:
RimViewWindow* ownerViewWindow() const override;
protected:
void contextMenuEvent( QContextMenuEvent* ) override;
private slots:
void onPlotItemSelected( std::shared_ptr<RiuPlotItem> plotItem, bool toggle, int sampleIndex );