Correlation Matrix Plot

This commit is contained in:
Gaute Lindkvist 2020-04-21 08:56:27 +02:00
parent 85851d0794
commit 78015fa19d
29 changed files with 1154 additions and 188 deletions

View File

@ -22,6 +22,8 @@
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "cafAssert.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -194,3 +196,38 @@ bool RiaSummaryCurveDefinition::operator<( const RiaSummaryCurveDefinition& othe
return ( m_summaryAddress < other.summaryAddress() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaSummaryCurveDefinitionAnalyser::RiaSummaryCurveDefinitionAnalyser( std::vector<RiaSummaryCurveDefinition> curveDefs )
{
for ( const auto& curveDef : curveDefs )
{
bool valid = false;
if ( curveDef.summaryCase() )
{
m_singleSummaryCases.insert( curveDef.summaryCase() );
if ( curveDef.summaryCase()->ensemble() )
{
m_ensembles.insert( curveDef.summaryCase()->ensemble() );
valid = true;
}
}
else if ( curveDef.ensemble() )
{
m_ensembles.insert( curveDef.ensemble() );
valid = true;
}
if ( valid )
{
RifEclipseSummaryAddress address = curveDef.summaryAddress();
m_quantityNames.insert( address.quantityName() );
address.setQuantityName( "" );
if ( !address.itemUiText().empty() ) m_summaryItems.insert( address );
}
}
}

View File

@ -54,9 +54,20 @@ public:
static QString curveDefinitionText( const QString& caseName, const RifEclipseSummaryAddress& summaryAddress );
private:
private:
RimSummaryCase* m_summaryCase;
RifEclipseSummaryAddress m_summaryAddress;
RimSummaryCaseCollection* m_ensemble;
};
class RiaSummaryCurveDefinitionAnalyser
{
public:
RiaSummaryCurveDefinitionAnalyser( std::vector<RiaSummaryCurveDefinition> curveDefs );
std::set<RimSummaryCase*> m_singleSummaryCases; // All summary cases used
std::set<RimSummaryCaseCollection*> m_ensembles; // All the ensembles referenced by the summary cases
std::set<RifEclipseSummaryAddress> m_summaryItems; // Quantity name set to "", stores only the identifiers
std::set<std::string> m_quantityNames; // Quantity names from the addresses
};

View File

@ -1,11 +1,13 @@
set (SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RicNewCorrelationPlotFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewCorrelationMatrixPlotFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicNewParameterResultCrossPlotFeature.h
)
set (SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RicNewCorrelationPlotFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewCorrelationMatrixPlotFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicNewParameterResultCrossPlotFeature.cpp
)

View File

@ -0,0 +1,82 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- 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 "RicNewCorrelationMatrixPlotFeature.h"
#include "RimCorrelationMatrixPlot.h"
#include "RimCorrelationPlot.h"
#include "RimCorrelationPlotCollection.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManager.h"
#include <QAction>
CAF_CMD_SOURCE_INIT( RicNewCorrelationMatrixPlotFeature, "RicNewCorrelationMatrixPlotFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicNewCorrelationMatrixPlotFeature::isCommandEnabled()
{
RimCorrelationPlotCollection* correlationPlotColl = nullptr;
caf::PdmObject* selObj = dynamic_cast<caf::PdmObject*>( caf::SelectionManager::instance()->selectedItem() );
if ( selObj )
{
selObj->firstAncestorOrThisOfType( correlationPlotColl );
}
if ( correlationPlotColl ) return true;
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewCorrelationMatrixPlotFeature::onActionTriggered( bool isChecked )
{
RimCorrelationPlotCollection* correlationPlotColl = nullptr;
caf::PdmObject* selObj = dynamic_cast<caf::PdmObject*>( caf::SelectionManager::instance()->selectedItem() );
if ( selObj )
{
selObj->firstAncestorOrThisOfType( correlationPlotColl );
}
if ( !correlationPlotColl ) return;
auto newPlot = correlationPlotColl->createCorrelationMatrixPlot();
newPlot->loadDataAndUpdate();
correlationPlotColl->updateConnectedEditors();
RiuPlotMainWindowTools::setExpanded( newPlot );
RiuPlotMainWindowTools::selectAsCurrentItem( newPlot );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicNewCorrelationMatrixPlotFeature::setupActionLook( QAction* actionToSetup )
{
actionToSetup->setText( "New Correlation Matrix Plot" );
actionToSetup->setIcon( QIcon( ":/AnalysisPlot16x16.png" ) );
}

View File

@ -0,0 +1,35 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020- 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 RicNewCorrelationMatrixPlotFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
protected:
// Overrides
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
};

View File

@ -52,40 +52,6 @@
#include <limits>
#include <map>
class RimCurveDefinitionAnalyser
{
public:
RimCurveDefinitionAnalyser( std::vector<RiaSummaryCurveDefinition> curveDefs )
{
for ( const auto& curveDef : curveDefs )
{
CVF_ASSERT( !curveDef.isEnsembleCurve() );
if ( curveDef.summaryCase() )
{
m_singleSummaryCases.insert( curveDef.summaryCase() );
if ( curveDef.summaryCase()->ensemble() )
{
m_ensembles.insert( curveDef.summaryCase()->ensemble() );
}
RifEclipseSummaryAddress address = curveDef.summaryAddress();
m_quantityNames.insert( address.quantityName() );
address.setQuantityName( "" );
if ( !address.itemUiText().empty() ) m_summaryItems.insert( address );
}
}
}
std::set<RimSummaryCase*> m_singleSummaryCases; // All summary cases used
std::set<RimSummaryCaseCollection*> m_ensembles; // All the ensembles referenced by the summary cases
std::set<RifEclipseSummaryAddress> m_summaryItems; // Quantity name set to "", stores only the identifiers
std::set<std::string> m_quantityNames; // Quantity names from the addresses
};
namespace caf
{
template <>
@ -233,7 +199,7 @@ std::set<RifEclipseSummaryAddress> RimAnalysisPlot::unfilteredAddresses()
{
std::set<RifEclipseSummaryAddress> addresses;
RimCurveDefinitionAnalyser* analyserOfSelectedCurveDefs = getOrCreateSelectedCurveDefAnalyser();
RiaSummaryCurveDefinitionAnalyser* analyserOfSelectedCurveDefs = getOrCreateSelectedCurveDefAnalyser();
for ( RimSummaryCase* sumCase : analyserOfSelectedCurveDefs->m_singleSummaryCases )
{
@ -251,7 +217,7 @@ std::set<EnsembleParameter> RimAnalysisPlot::ensembleParameters()
{
std::set<EnsembleParameter> ensembleParms;
RimCurveDefinitionAnalyser* analyserOfSelectedCurveDefs = getOrCreateSelectedCurveDefAnalyser();
RiaSummaryCurveDefinitionAnalyser* analyserOfSelectedCurveDefs = getOrCreateSelectedCurveDefAnalyser();
std::set<RimSummaryCaseCollection*> ensembles;
@ -584,8 +550,8 @@ QList<caf::PdmOptionItemInfo> RimAnalysisPlot::calculateValueOptions( const caf:
if ( !m_analyserOfSelectedCurveDefs )
{
m_analyserOfSelectedCurveDefs = std::unique_ptr<RimCurveDefinitionAnalyser>(
new RimCurveDefinitionAnalyser( this->curveDefinitionsWithoutEnsembleReference() ) );
m_analyserOfSelectedCurveDefs = std::unique_ptr<RiaSummaryCurveDefinitionAnalyser>(
new RiaSummaryCurveDefinitionAnalyser( this->curveDefinitionsWithoutEnsembleReference() ) );
}
if ( fieldNeedingOptions == &m_addTimestepUiField )
@ -703,8 +669,8 @@ void RimAnalysisPlot::onLoadDataAndUpdate()
{
updateMdiWindowVisibility();
m_analyserOfSelectedCurveDefs = std::unique_ptr<RimCurveDefinitionAnalyser>(
new RimCurveDefinitionAnalyser( this->curveDefinitionsWithoutEnsembleReference() ) );
m_analyserOfSelectedCurveDefs = std::unique_ptr<RiaSummaryCurveDefinitionAnalyser>(
new RiaSummaryCurveDefinitionAnalyser( this->curveDefinitionsWithoutEnsembleReference() ) );
if ( m_plotWidget )
{
@ -1607,12 +1573,12 @@ void RimAnalysisPlot::updatePlotTitle()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCurveDefinitionAnalyser* RimAnalysisPlot::getOrCreateSelectedCurveDefAnalyser()
RiaSummaryCurveDefinitionAnalyser* RimAnalysisPlot::getOrCreateSelectedCurveDefAnalyser()
{
if ( !m_analyserOfSelectedCurveDefs )
{
m_analyserOfSelectedCurveDefs = std::unique_ptr<RimCurveDefinitionAnalyser>(
new RimCurveDefinitionAnalyser( this->curveDefinitionsWithoutEnsembleReference() ) );
m_analyserOfSelectedCurveDefs = std::unique_ptr<RiaSummaryCurveDefinitionAnalyser>(
new RiaSummaryCurveDefinitionAnalyser( this->curveDefinitionsWithoutEnsembleReference() ) );
}
return m_analyserOfSelectedCurveDefs.get();

View File

@ -32,7 +32,7 @@ class RiuSummaryQwtPlot;
class RiuGroupedBarChartBuilder;
class RimAnalysisPlotDataEntry;
class RimCurveDefinitionAnalyser;
class RiaSummaryCurveDefinitionAnalyser;
class RimPlotAxisPropertiesInterface;
class RimPlotAxisProperties;
class RimPlotDataFilterCollection;
@ -151,7 +151,7 @@ private:
void addDataToChartBuilder( RiuGroupedBarChartBuilder& chartBuilder );
void updatePlotTitle();
RimCurveDefinitionAnalyser* getOrCreateSelectedCurveDefAnalyser();
RiaSummaryCurveDefinitionAnalyser* getOrCreateSelectedCurveDefAnalyser();
std::vector<RiaSummaryCurveDefinition> curveDefinitionsWithoutEnsembleReference() const;
std::vector<RiaSummaryCurveDefinition> curveDefinitionsWithEmbeddedEnsembleReference();
std::vector<RiaSummaryCurveDefinition> filteredCurveDefs();
@ -167,7 +167,7 @@ private:
void buildTestPlot( RiuGroupedBarChartBuilder& chartBuilder );
private:
std::unique_ptr<RimCurveDefinitionAnalyser> m_analyserOfSelectedCurveDefs;
std::unique_ptr<RiaSummaryCurveDefinitionAnalyser> m_analyserOfSelectedCurveDefs;
QPointer<RiuQwtPlotWidget> m_plotWidget;

View File

@ -39,6 +39,10 @@ RimAnalysisPlotDataEntry::RimAnalysisPlotDataEntry()
m_summaryCase.uiCapability()->setUiTreeChildrenHidden( true );
m_summaryCase.uiCapability()->setAutoAddingOptionFromValue( false );
CAF_PDM_InitFieldNoDefault( &m_ensemble, "Ensemble", "Ensemble", "", "", "" );
m_ensemble.uiCapability()->setUiTreeChildrenHidden( true );
m_ensemble.uiCapability()->setAutoAddingOptionFromValue( false );
CAF_PDM_InitFieldNoDefault( &m_summaryAddress, "SummaryAddress", "Summary Address", "", "", "" );
m_summaryAddress.uiCapability()->setUiHidden( true );
m_summaryAddress.uiCapability()->setUiTreeChildrenHidden( true );
@ -58,9 +62,14 @@ RimAnalysisPlotDataEntry::~RimAnalysisPlotDataEntry()
void RimAnalysisPlotDataEntry::setFromCurveDefinition( const RiaSummaryCurveDefinition& curveDef )
{
m_summaryAddress->setAddress( curveDef.summaryAddress() );
CVF_ASSERT( !curveDef.ensemble() ); // We will not support definitions of ensemble curves. Only single cases that
// might be part of an ensemble
m_summaryCase = curveDef.summaryCase();
if ( curveDef.ensemble() )
{
m_ensemble = curveDef.ensemble();
}
else
{
m_summaryCase = curveDef.summaryCase();
}
}
//--------------------------------------------------------------------------------------------------
@ -68,6 +77,10 @@ void RimAnalysisPlotDataEntry::setFromCurveDefinition( const RiaSummaryCurveDefi
//--------------------------------------------------------------------------------------------------
RiaSummaryCurveDefinition RimAnalysisPlotDataEntry::curveDefinition() const
{
if ( m_ensemble )
{
return RiaSummaryCurveDefinition( nullptr, m_summaryAddress->address(), m_ensemble() );
}
return RiaSummaryCurveDefinition( m_summaryCase(), m_summaryAddress->address(), nullptr );
}
@ -79,6 +92,14 @@ RimSummaryCase* RimAnalysisPlotDataEntry::summaryCase() const
return m_summaryCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCaseCollection* RimAnalysisPlotDataEntry::ensemble() const
{
return m_ensemble;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -39,10 +39,12 @@ public:
void setFromCurveDefinition( const RiaSummaryCurveDefinition& curveDef );
RiaSummaryCurveDefinition curveDefinition() const;
RimSummaryCase* summaryCase() const;
RifEclipseSummaryAddress summaryAddress() const;
RimSummaryCase* summaryCase() const;
RimSummaryCaseCollection* ensemble() const;
RifEclipseSummaryAddress summaryAddress() const;
private:
caf::PdmPtrField<RimSummaryCase*> m_summaryCase;
caf::PdmChildField<RimSummaryAddress*> m_summaryAddress;
caf::PdmPtrField<RimSummaryCase*> m_summaryCase;
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble;
caf::PdmChildField<RimSummaryAddress*> m_summaryAddress;
};

View File

@ -36,7 +36,7 @@ class RiuSummaryQwtPlot;
class RiuGroupedBarChartBuilder;
class RimAnalysisPlotDataEntry;
class RimCurveDefinitionAnalyser;
class RiaSummaryCurveDefinitionAnalyser;
class RimPlotAxisPropertiesInterface;
class RimPlotAxisProperties;

View File

@ -2,6 +2,7 @@
set (SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RimAbstractCorrelationPlot.h
${CMAKE_CURRENT_LIST_DIR}/RimCorrelationPlot.h
${CMAKE_CURRENT_LIST_DIR}/RimCorrelationMatrixPlot.h
${CMAKE_CURRENT_LIST_DIR}/RimParameterResultCrossPlot.h
${CMAKE_CURRENT_LIST_DIR}/RimCorrelationPlotCollection.h
)
@ -9,6 +10,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RimCorrelationPlotCollection.h
set (SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RimAbstractCorrelationPlot.cpp
${CMAKE_CURRENT_LIST_DIR}/RimCorrelationPlot.cpp
${CMAKE_CURRENT_LIST_DIR}/RimCorrelationMatrixPlot.cpp
${CMAKE_CURRENT_LIST_DIR}/RimParameterResultCrossPlot.cpp
${CMAKE_CURRENT_LIST_DIR}/RimCorrelationPlotCollection.cpp
)

View File

@ -2,9 +2,11 @@
#include "RiaApplication.h"
#include "RiaPreferences.h"
#include "RiaSummaryCurveDefinition.h"
#include "RifSummaryReaderInterface.h"
#include "RimAnalysisPlotDataEntry.h"
#include "RimEnsembleCurveSet.h"
#include "RimProject.h"
#include "RimSummaryAddress.h"
@ -24,26 +26,23 @@ CAF_PDM_ABSTRACT_SOURCE_INIT( RimAbstractCorrelationPlot, "AbstractCorrelationPl
///
//--------------------------------------------------------------------------------------------------
RimAbstractCorrelationPlot::RimAbstractCorrelationPlot()
: m_selectMultipleVectors( false )
{
CAF_PDM_InitObject( "Abstract Correlation Plot", ":/CorrelationPlot16x16.png", "", "" );
CAF_PDM_InitFieldNoDefault( &m_ensemble, "Ensemble", "Ensemble", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_selectedVarsUiField, "SelectedVariableDisplayVar", "Vector", "", "", "" );
m_selectedVarsUiField.xmlCapability()->disableIO();
m_selectedVarsUiField.uiCapability()->setUiEditorTypeName( caf::PdmUiLineEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_summaryAddressUiField, "SelectedVariableDisplayVar", "Vector", "", "", "" );
m_summaryAddressUiField.xmlCapability()->disableIO();
m_summaryAddressUiField.uiCapability()->setUiEditorTypeName( caf::PdmUiLineEditor::uiEditorTypeName() );
CAF_PDM_InitFieldNoDefault( &m_summaryAddress, "SummaryAddress", "Summary Address", "", "", "" );
m_summaryAddress.uiCapability()->setUiHidden( true );
m_summaryAddress.uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitFieldNoDefault( &m_analysisPlotDataSelection, "AnalysisPlotData", "", "", "", "" );
m_analysisPlotDataSelection.uiCapability()->setUiTreeChildrenHidden( true );
m_analysisPlotDataSelection.uiCapability()->setUiTreeHidden( true );
CAF_PDM_InitFieldNoDefault( &m_pushButtonSelectSummaryAddress, "SelectAddress", "", "", "", "" );
caf::PdmUiPushButtonEditor::configureEditorForField( &m_pushButtonSelectSummaryAddress );
m_pushButtonSelectSummaryAddress.uiCapability()->setUiLabelPosition( caf::PdmUiItemInfo::HIDDEN );
m_pushButtonSelectSummaryAddress = false;
m_summaryAddress = new RimSummaryAddress;
CAF_PDM_InitFieldNoDefault( &m_timeStep, "TimeStep", "Time Step", "", "", "" );
m_timeStep.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() );
@ -70,19 +69,28 @@ void RimAbstractCorrelationPlot::fieldChangedByUi( const caf::PdmFieldHandle* ch
if ( changedField == &m_pushButtonSelectSummaryAddress )
{
RiuSummaryVectorSelectionDialog dlg( nullptr );
RimSummaryCaseCollection* candidateEnsemble = m_ensemble;
RifEclipseSummaryAddress candicateAddress = m_summaryAddress->address();
dlg.hideSummaryCases();
dlg.setEnsembleAndAddress( candidateEnsemble, candicateAddress );
if ( m_selectMultipleVectors )
{
dlg.enableMultiSelect( true );
}
dlg.setCaseAndAddress( nullptr, RifEclipseSummaryAddress() );
dlg.setCurveSelection( curveDefinitions() );
if ( dlg.exec() == QDialog::Accepted )
{
auto curveSelection = dlg.curveSelection();
if ( !curveSelection.empty() )
{
m_summaryAddress->setAddress( curveSelection[0].summaryAddress() );
std::vector<RiaSummaryCurveDefinition> summaryVectorDefinitions = dlg.curveSelection();
m_analysisPlotDataSelection.deleteAllChildObjects();
for ( const RiaSummaryCurveDefinition& vectorDef : summaryVectorDefinitions )
{
auto plotEntry = new RimAnalysisPlotDataEntry();
plotEntry->setFromCurveDefinition( vectorDef );
m_analysisPlotDataSelection.push_back( plotEntry );
}
this->loadDataAndUpdate();
this->updateConnectedEditors();
}
@ -95,11 +103,6 @@ void RimAbstractCorrelationPlot::fieldChangedByUi( const caf::PdmFieldHandle* ch
this->loadDataAndUpdate();
this->updateConnectedEditors();
}
else if ( changedField == &m_ensemble )
{
this->loadDataAndUpdate();
this->updateConnectedEditors();
}
else if ( changedField == &m_showPlotTitle || changedField == &m_useAutoPlotTitle || changedField == &m_description )
{
this->updatePlotTitle();
@ -136,38 +139,14 @@ QList<caf::PdmOptionItemInfo>
{
QList<caf::PdmOptionItemInfo> options = RimPlot::calculateValueOptions( fieldNeedingOptions, useOptionsOnly );
if ( fieldNeedingOptions == &m_ensemble )
if ( fieldNeedingOptions == &m_timeStep )
{
RimProject* project = RiaApplication::instance()->project();
std::vector<RimSummaryCaseCollection*> summaryCaseCollections;
project->descendantsIncludingThisOfType( summaryCaseCollections );
for ( auto summaryCaseCollection : summaryCaseCollections )
std::set<time_t> allTimeSteps = allAvailableTimeSteps();
for ( time_t timeStep : allTimeSteps )
{
if ( summaryCaseCollection->isEnsemble() )
{
options.push_back( caf::PdmOptionItemInfo( summaryCaseCollection->name(), summaryCaseCollection ) );
}
}
}
else if ( fieldNeedingOptions == &m_summaryAddressUiField )
{
if ( m_ensemble )
{
RimEnsembleCurveSet::appendOptionItemsForSummaryAddresses( &options, m_ensemble );
}
}
else if ( fieldNeedingOptions == &m_timeStep )
{
QString dateTimeFormat = RiaApplication::instance()->preferences()->dateTimeFormat();
if ( m_ensemble )
{
std::set<time_t> allTimeSteps = allAvailableTimeSteps();
for ( time_t timeStep : allTimeSteps )
{
QDateTime dateTime = QDateTime::fromTime_t( timeStep );
QString timestepString = dateTime.toString( Qt::ISODate );
options.push_back( caf::PdmOptionItemInfo( timestepString, dateTime ) );
}
QDateTime dateTime = QDateTime::fromTime_t( timeStep );
QString timestepString = dateTime.toString( Qt::ISODate );
options.push_back( caf::PdmOptionItemInfo( timestepString, dateTime ) );
}
}
return options;
@ -180,19 +159,102 @@ std::set<time_t> RimAbstractCorrelationPlot::allAvailableTimeSteps()
{
std::set<time_t> timeStepUnion;
for ( RimSummaryCase* sumCase : m_ensemble->allSummaryCases() )
RiaSummaryCurveDefinitionAnalyser* analyserOfSelectedCurveDefs = getOrCreateSelectedCurveDefAnalyser();
for ( RimSummaryCaseCollection* ensemble : analyserOfSelectedCurveDefs->m_ensembles )
{
const std::vector<time_t>& timeSteps = sumCase->summaryReader()->timeSteps( m_summaryAddress->address() );
for ( time_t t : timeSteps )
{
timeStepUnion.insert( t );
}
const std::set<time_t>& timeSteps = ensemble->ensembleTimeSteps();
timeStepUnion.insert( timeSteps.begin(), timeSteps.end() );
}
return timeStepUnion;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RiaSummaryCurveDefinition> RimAbstractCorrelationPlot::curveDefinitions() const
{
std::vector<RiaSummaryCurveDefinition> curveDefs;
for ( auto dataEntry : m_analysisPlotDataSelection )
{
curveDefs.push_back( dataEntry->curveDefinition() );
}
return curveDefs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaSummaryCurveDefinitionAnalyser* RimAbstractCorrelationPlot::getOrCreateSelectedCurveDefAnalyser()
{
if ( !m_analyserOfSelectedCurveDefs )
{
m_analyserOfSelectedCurveDefs = std::unique_ptr<RiaSummaryCurveDefinitionAnalyser>(
new RiaSummaryCurveDefinitionAnalyser( this->curveDefinitions() ) );
}
return m_analyserOfSelectedCurveDefs.get();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseSummaryAddress> RimAbstractCorrelationPlot::addresses()
{
std::set<RifEclipseSummaryAddress> addresses;
RiaSummaryCurveDefinitionAnalyser* analyserOfSelectedCurveDefs = getOrCreateSelectedCurveDefAnalyser();
for ( RimSummaryCaseCollection* ensemble : analyserOfSelectedCurveDefs->m_ensembles )
{
const std::set<RifEclipseSummaryAddress>& caseAddrs = ensemble->ensembleSummaryAddresses();
addresses.insert( caseAddrs.begin(), caseAddrs.end() );
}
return addresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RimSummaryCaseCollection*> RimAbstractCorrelationPlot::ensembles()
{
RiaSummaryCurveDefinitionAnalyser* analyserOfSelectedCurveDefs = getOrCreateSelectedCurveDefAnalyser();
return analyserOfSelectedCurveDefs->m_ensembles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<EnsembleParameter> RimAbstractCorrelationPlot::ensembleParameters()
{
std::set<EnsembleParameter> ensembleParms;
RiaSummaryCurveDefinitionAnalyser* analyserOfSelectedCurveDefs = getOrCreateSelectedCurveDefAnalyser();
for ( RimSummaryCaseCollection* ensemble : analyserOfSelectedCurveDefs->m_ensembles )
{
std::vector<EnsembleParameter> parameters = ensemble->alphabeticEnsembleParameters();
ensembleParms.insert( parameters.begin(), parameters.end() );
}
return ensembleParms;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
EnsembleParameter RimAbstractCorrelationPlot::ensembleParameter( const QString& ensembleParameterName )
{
std::set<EnsembleParameter> ensembleParms = ensembleParameters();
for ( const EnsembleParameter& eParam : ensembleParms )
{
if ( eParam.name == ensembleParameterName ) return eParam;
}
return EnsembleParameter();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -313,3 +375,25 @@ time_t RimAbstractCorrelationPlot::timeDiff( time_t lhs, time_t rhs )
}
return rhs - lhs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimAbstractCorrelationPlot::selectedVarsText() const
{
QString vectorNames;
if ( m_analyserOfSelectedCurveDefs )
{
for ( const std::string& quantityName : m_analyserOfSelectedCurveDefs->m_quantityNames )
{
vectorNames += QString::fromStdString( quantityName ) + ", ";
}
if ( !vectorNames.isEmpty() )
{
vectorNames.chop( 2 );
}
}
return vectorNames;
}

View File

@ -25,6 +25,11 @@
#include "cafPdmPtrField.h"
#include <QString>
class RiaSummaryCurveDefinition;
class RiaSummaryCurveDefinitionAnalyser;
class RimAnalysisPlotDataEntry;
class RimSummaryAddress;
class RimAbstractCorrelationPlot : public RimPlot
@ -47,7 +52,14 @@ protected:
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
std::set<time_t> allAvailableTimeSteps();
std::set<time_t> allAvailableTimeSteps();
std::vector<RiaSummaryCurveDefinition> curveDefinitions() const;
RiaSummaryCurveDefinitionAnalyser* getOrCreateSelectedCurveDefAnalyser();
std::set<RifEclipseSummaryAddress> addresses();
std::set<RimSummaryCaseCollection*> ensembles();
std::set<EnsembleParameter> ensembleParameters();
EnsembleParameter ensembleParameter( const QString& ensembleParameterName );
// RimViewWindow overrides
QWidget* viewWidget() override;
@ -84,15 +96,20 @@ protected:
static time_t timeDiff( time_t lhs, time_t rhs );
QString selectedVarsText() const;
protected:
QPointer<RiuQwtPlotWidget> m_plotWidget;
std::unique_ptr<RiaSummaryCurveDefinitionAnalyser> m_analyserOfSelectedCurveDefs;
QPointer<RiuQwtPlotWidget> m_plotWidget;
bool m_selectMultipleVectors;
// Fields
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble;
caf::PdmChildField<RimSummaryAddress*> m_summaryAddress;
caf::PdmField<RifEclipseSummaryAddress> m_summaryAddressUiField;
caf::PdmField<bool> m_pushButtonSelectSummaryAddress;
caf::PdmField<QDateTime> m_timeStep;
caf::PdmChildArrayField<RimAnalysisPlotDataEntry*> m_analysisPlotDataSelection;
caf::PdmField<QString> m_selectedVarsUiField;
caf::PdmField<bool> m_pushButtonSelectSummaryAddress;
caf::PdmField<QDateTime> m_timeStep;
caf::PdmField<bool> m_showPlotTitle;
caf::PdmField<bool> m_useAutoPlotTitle;

View File

@ -0,0 +1,482 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020 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 "RimCorrelationMatrixPlot.h"
#include "RiaApplication.h"
#include "RiaColorTools.h"
#include "RiaPreferences.h"
#include "RiaStatisticsTools.h"
#include "RiuPlotMainWindowTools.h"
#include "RiuQwtLinearScaleEngine.h"
#include "RiuQwtPlotTools.h"
#include "RiuQwtPlotWidget.h"
#include "RifSummaryReaderInterface.h"
#include "RimDerivedSummaryCase.h"
#include "RimEnsembleCurveSet.h"
#include "RimPlotAxisProperties.h"
#include "RimPlotAxisPropertiesInterface.h"
#include "RimPlotDataFilterCollection.h"
#include "RimRegularLegendConfig.h"
#include "RimSummaryAddress.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryPlotAxisFormatter.h"
#include "cafPdmUiComboBoxEditor.h"
#include "cafPdmUiTreeOrdering.h"
#include "cvfScalarMapper.h"
#include "qwt_plot_marker.h"
#include "qwt_scale_draw.h"
#include "qwt_text.h"
#include <algorithm>
#include <limits>
#include <map>
#include <set>
CAF_PDM_SOURCE_INIT( RimCorrelationMatrixPlot, "CorrelationMatrixPlot" );
class TextScaleDraw : public QwtScaleDraw
{
public:
TextScaleDraw( const std::map<size_t, QString>& tickLabels )
: m_tickLabels( tickLabels )
{
}
QwtText label( double value ) const override
{
size_t intValue = static_cast<size_t>( value + 0.25 );
auto it = m_tickLabels.find( intValue );
return it != m_tickLabels.end() ? it->second : "";
}
private:
std::map<size_t, QString> m_tickLabels;
};
class CorrelationMatrixRowOrColumn
{
public:
CorrelationMatrixRowOrColumn( const QString& label,
const std::vector<double>& values,
const std::vector<QString>& entryLabels )
: m_label( label )
, m_values( values )
, m_entryLabels( entryLabels )
, m_correlationSum( 0.0 )
{
bool anyValid = false;
for ( auto value : values )
{
if ( RiaCurveDataTools::isValidValue( value, false ) )
{
m_correlationSum += value * value;
anyValid = true;
}
}
if ( !anyValid ) m_correlationSum = std::numeric_limits<double>::infinity();
}
QString m_label;
std::vector<double> m_values;
std::vector<QString> m_entryLabels;
double m_correlationSum;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCorrelationMatrixPlot::RimCorrelationMatrixPlot()
: RimAbstractCorrelationPlot()
{
CAF_PDM_InitObject( "Correlation Plot", ":/CorrelationMatrixPlot16x16.png", "", "" );
CAF_PDM_InitFieldNoDefault( &m_correlationFactor, "CorrelationFactor", "Correlation Factor", "", "", "" );
m_correlationFactor.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() );
CAF_PDM_InitField( &m_showAbsoluteValues, "CorrelationAbsValues", true, "Show Absolute Values", "", "", "" );
CAF_PDM_InitField( &m_sortByValues, "CorrelationSorting", true, "Sort Matrix by Values", "", "", "" );
CAF_PDM_InitFieldNoDefault( &m_legendConfig, "LegendConfig", "", "", "", "" );
m_legendConfig = new RimRegularLegendConfig();
m_legendConfig->setAutomaticRanges( -1.0, 1.0, -1.0, 1.0 );
m_selectMultipleVectors = true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCorrelationMatrixPlot::~RimCorrelationMatrixPlot()
{
removeMdiWindowFromMdiArea();
cleanupBeforeClose();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
RimAbstractCorrelationPlot::fieldChangedByUi( changedField, oldValue, newValue );
if ( changedField == &m_correlationFactor || changedField == &m_showAbsoluteValues || changedField == &m_sortByValues )
{
this->updateLegend();
this->loadDataAndUpdate();
this->updateConnectedEditors();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
caf::PdmUiGroup* correlationGroup = uiOrdering.addNewGroup( "Correlation Factor Settings" );
correlationGroup->add( &m_correlationFactor );
correlationGroup->add( &m_showAbsoluteValues );
correlationGroup->add( &m_sortByValues );
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Summary Vector" );
m_selectedVarsUiField = selectedVarsText();
curveDataGroup->add( &m_selectedVarsUiField );
curveDataGroup->add( &m_pushButtonSelectSummaryAddress, { false, 1, 0 } );
curveDataGroup->add( &m_timeStep );
caf::PdmUiGroup* plotGroup = uiOrdering.addNewGroup( "Plot Settings" );
plotGroup->add( &m_showPlotTitle );
plotGroup->add( &m_useAutoPlotTitle );
plotGroup->add( &m_description );
m_description.uiCapability()->setUiReadOnly( m_useAutoPlotTitle() );
RimPlot::defineUiOrdering( uiConfigName, *plotGroup );
uiOrdering.skipRemainingFields( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo>
RimCorrelationMatrixPlot::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly )
{
QList<caf::PdmOptionItemInfo> options =
RimAbstractCorrelationPlot::calculateValueOptions( fieldNeedingOptions, useOptionsOnly );
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::onLoadDataAndUpdate()
{
updateMdiWindowVisibility();
m_selectedVarsUiField = selectedVarsText();
m_analyserOfSelectedCurveDefs = std::unique_ptr<RiaSummaryCurveDefinitionAnalyser>(
new RiaSummaryCurveDefinitionAnalyser( this->curveDefinitions() ) );
if ( m_plotWidget )
{
m_plotWidget->detachItems( QwtPlotItem::Rtti_PlotBarChart );
m_plotWidget->detachItems( QwtPlotItem::Rtti_PlotScale );
m_plotWidget->detachItems( QwtPlotItem::Rtti_PlotItem );
createMatrix();
m_plotWidget->insertLegend( nullptr );
m_plotWidget->updateLegend();
this->updateAxes();
this->updatePlotTitle();
m_plotWidget->scheduleReplot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField )
{
this->loadDataAndUpdate();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering,
QString uiConfigName /*= "" */ )
{
uiTreeOrdering.add( m_legendConfig() );
uiTreeOrdering.skipRemainingChildren( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::updateAxes()
{
if ( !m_plotWidget ) return;
m_plotWidget->setAxisScaleEngine( QwtPlot::yLeft, new RiuQwtLinearScaleEngine );
m_plotWidget->setAxisTitleText( QwtPlot::yLeft, "Result Vector" );
m_plotWidget->setAxisTitleEnabled( QwtPlot::yLeft, true );
m_plotWidget->setAxisFontsAndAlignment( QwtPlot::yLeft, 11, 7, false, Qt::AlignCenter );
m_plotWidget->setAxisLabelsAndTicksEnabled( QwtPlot::yLeft, true, false );
m_plotWidget->setAxisRange( QwtPlot::yLeft, 0.0, (double)m_resultLabels.size() + 1 );
m_plotWidget->setAxisScaleDraw( QwtPlot::yLeft, new TextScaleDraw( m_resultLabels ) );
m_plotWidget->setMajorAndMinorTickIntervalsAndRange( QwtPlot::yLeft,
1.0,
0.0,
0.5,
(double)m_resultLabels.size() - 0.5,
0.0,
m_resultLabels.size() );
auto scaleDraw = new TextScaleDraw( m_paramLabels );
scaleDraw->setLabelRotation( 30.0 );
m_plotWidget->setAxisScaleDraw( QwtPlot::xBottom, scaleDraw );
m_plotWidget->setAxisScaleEngine( QwtPlot::xBottom, new RiuQwtLinearScaleEngine );
m_plotWidget->setAxisTitleText( QwtPlot::xBottom, "Ensemble Parameter" );
m_plotWidget->setAxisTitleEnabled( QwtPlot::xBottom, true );
m_plotWidget->setAxisFontsAndAlignment( QwtPlot::xBottom, 11, 6, false, Qt::AlignCenter | Qt::AlignTop );
m_plotWidget->setAxisLabelsAndTicksEnabled( QwtPlot::xBottom, true, false );
m_plotWidget->setAxisRange( QwtPlot::xBottom, 0.0, (double)m_paramLabels.size() + 1 );
// m_plotWidget->setAutoTickIntervalCounts( QwtPlot::xBottom, m_paramLabels.size(), m_paramLabels.size() );
m_plotWidget->setMajorAndMinorTickIntervalsAndRange( QwtPlot::xBottom,
1.0,
0.0,
0.5,
(double)m_paramLabels.size() - 0.5,
0.0,
(double)m_paramLabels.size() );
m_plotWidget->setAxisLabelAlignment( QwtPlot::xBottom, Qt::AlignRight );
}
void eraseInvalidEntries( std::vector<CorrelationMatrixRowOrColumn>& matrix )
{
matrix.erase( std::remove_if( matrix.begin(),
matrix.end(),
[]( auto entry ) {
return !RiaCurveDataTools::isValidValue( entry.m_correlationSum, false );
} ),
matrix.end() );
}
void sortEntries( std::vector<CorrelationMatrixRowOrColumn>& matrix )
{
std::sort( matrix.begin(),
matrix.end(),
[]( const CorrelationMatrixRowOrColumn& lhs, const CorrelationMatrixRowOrColumn& rhs ) {
return lhs.m_correlationSum > rhs.m_correlationSum;
} );
}
std::vector<CorrelationMatrixRowOrColumn> transpose( const std::vector<CorrelationMatrixRowOrColumn>& matrix )
{
std::vector<CorrelationMatrixRowOrColumn> transposedMatrix;
for ( size_t rowIdx = 0u; rowIdx < matrix[0].m_values.size(); ++rowIdx )
{
QString label = matrix[0].m_entryLabels[rowIdx];
std::vector<double> values;
std::vector<QString> entryLabels;
for ( size_t colIdx = 0u; colIdx < matrix.size(); ++colIdx )
{
values.push_back( matrix[colIdx].m_values[rowIdx] );
entryLabels.push_back( matrix[colIdx].m_label );
}
transposedMatrix.push_back( CorrelationMatrixRowOrColumn( label, values, entryLabels ) );
}
return transposedMatrix;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::createMatrix()
{
time_t selectedTimestep = m_timeStep().toTime_t();
m_paramLabels.clear();
m_resultLabels.clear();
auto curveDefs = curveDefinitions();
if ( curveDefs.empty() ) return;
std::vector<CorrelationMatrixRowOrColumn> correlationMatrixColumns;
for ( EnsembleParameter parameter : ensembleParameters() )
{
if ( parameter.isNumeric() && parameter.isValid() )
{
bool anyValidResults = false;
std::vector<double> correlations;
std::vector<QString> resultLabels;
for ( auto curveDef : curveDefs )
{
double correlation = std::numeric_limits<double>::infinity();
auto ensemble = curveDef.ensemble();
auto address = curveDef.summaryAddress();
QString resultLabel = curveDef.curveDefinitionText();
if ( ensemble )
{
std::vector<double> caseValuesAtTimestep;
std::vector<double> parameterValues;
for ( size_t caseIdx = 0u; caseIdx < ensemble->allSummaryCases().size(); ++caseIdx )
{
auto summaryCase = ensemble->allSummaryCases()[caseIdx];
RifSummaryReaderInterface* reader = summaryCase->summaryReader();
if ( reader )
{
std::vector<double> values;
double closestValue = std::numeric_limits<double>::infinity();
time_t closestTimeStep = 0;
if ( reader->values( address, &values ) )
{
const std::vector<time_t>& timeSteps = reader->timeSteps( address );
for ( size_t i = 0; i < timeSteps.size(); ++i )
{
if ( timeDiff( timeSteps[i], selectedTimestep ) <
timeDiff( selectedTimestep, closestTimeStep ) )
{
closestValue = values[i];
closestTimeStep = timeSteps[i];
}
}
}
if ( closestValue != std::numeric_limits<double>::infinity() )
{
caseValuesAtTimestep.push_back( closestValue );
double paramValue = parameter.values[caseIdx].toDouble();
parameterValues.push_back( paramValue );
}
}
}
if ( parameterValues.empty() ) continue;
if ( m_correlationFactor == CorrelationFactor::PEARSON )
{
correlation = RiaStatisticsTools::pearsonCorrelation( parameterValues, caseValuesAtTimestep );
}
else
{
correlation = RiaStatisticsTools::spearmanCorrelation( parameterValues, caseValuesAtTimestep );
}
if ( RiaCurveDataTools::isValidValue( correlation, false ) )
{
if ( m_showAbsoluteValues() ) correlation = std::abs( correlation );
anyValidResults = true;
}
}
correlations.push_back( correlation );
resultLabels.push_back( resultLabel );
}
if ( anyValidResults )
{
correlationMatrixColumns.push_back(
CorrelationMatrixRowOrColumn( parameter.name, correlations, resultLabels ) );
}
}
}
eraseInvalidEntries( correlationMatrixColumns );
if ( m_sortByValues() ) sortEntries( correlationMatrixColumns );
auto correlationMatrixRows = transpose( correlationMatrixColumns );
eraseInvalidEntries( correlationMatrixRows );
if ( m_sortByValues() ) sortEntries( correlationMatrixRows );
for ( size_t rowIdx = 0u; rowIdx < correlationMatrixRows.size(); ++rowIdx )
{
for ( size_t colIdx = 0u; colIdx < correlationMatrixRows[rowIdx].m_values.size(); ++colIdx )
{
double correlation = correlationMatrixRows[rowIdx].m_values[colIdx];
auto label = QString( "%1" ).arg( correlation, 0, 'f', 2 );
cvf::Color3ub color = m_legendConfig->scalarMapper()->mapToColor( correlation );
QColor qColor( color.r(), color.g(), color.b() );
QwtPlotItem* rectangle = RiuQwtPlotTools::createBoxShape( label,
(double)colIdx,
(double)colIdx + 1.0,
(double)rowIdx,
(double)rowIdx + 1,
qColor );
QwtText textLabel( label );
cvf::Color3f contrastColor = RiaColorTools::contrastColor( cvf::Color3f( color ) );
textLabel.setColor( RiaColorTools::toQColor( contrastColor ) );
QFont font = textLabel.font();
font.setPixelSize( RiaFontCache::pointSizeToPixelSize( 7 ) );
textLabel.setFont( font );
QwtPlotMarker* marker = new QwtPlotMarker();
marker->setLabel( textLabel );
marker->setXValue( colIdx + 0.5 );
marker->setYValue( rowIdx + 0.5 );
rectangle->attach( m_plotWidget );
marker->attach( m_plotWidget );
m_paramLabels[colIdx] = correlationMatrixRows[rowIdx].m_entryLabels[colIdx];
}
m_resultLabels[rowIdx] = correlationMatrixRows[rowIdx].m_label;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::updatePlotTitle()
{
if ( m_useAutoPlotTitle )
{
m_description = QString( "%1 Matrix for Parameters vs Result Vectors" ).arg( m_correlationFactor().uiText() );
}
m_plotWidget->setPlotTitle( m_description );
m_plotWidget->setPlotTitleEnabled( m_showPlotTitle && isMdiWindow() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimCorrelationMatrixPlot::updateLegend()
{
if ( m_showAbsoluteValues )
{
m_legendConfig->setAutomaticRanges( -1.0, 1.0, -1.0, 1.0 );
}
else
{
m_legendConfig->setAutomaticRanges( 0.0, 1.0, 0.0, 1.0 );
}
}

View File

@ -0,0 +1,75 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020 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 "RimCorrelationPlot.h"
#include "cafAppEnum.h"
#include <QDateTime>
class RimRegularLegendConfig;
class RimSummaryAddress;
class RiuGroupedBarChartBuilder;
//==================================================================================================
///
///
//==================================================================================================
class RimCorrelationMatrixPlot : public RimAbstractCorrelationPlot
{
CAF_PDM_HEADER_INIT;
public:
using CorrelationFactor = RimCorrelationPlot::CorrelationFactor;
using CorrelationFactorEnum = RimCorrelationPlot::CorrelationFactorEnum;
public:
RimCorrelationMatrixPlot();
~RimCorrelationMatrixPlot() override;
private:
// Overridden PDM methods
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly ) override;
void onLoadDataAndUpdate() override;
void childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) override;
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
void updateAxes() override;
// Private methods
void createMatrix();
void updatePlotTitle() override;
void updateLegend() override;
private:
caf::PdmField<CorrelationFactorEnum> m_correlationFactor;
caf::PdmField<bool> m_showAbsoluteValues;
caf::PdmField<bool> m_sortByValues;
caf::PdmChildField<RimRegularLegendConfig*> m_legendConfig;
std::map<size_t, QString> m_paramLabels;
std::map<size_t, QString> m_resultLabels;
};

View File

@ -110,8 +110,8 @@ void RimCorrelationPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder
}
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Summary Vector" );
curveDataGroup->add( &m_ensemble );
curveDataGroup->add( &m_summaryAddressUiField );
curveDataGroup->add( &m_selectedVarsUiField );
curveDataGroup->add( &m_pushButtonSelectSummaryAddress, { false, 1, 0 } );
curveDataGroup->add( &m_timeStep );
@ -119,6 +119,8 @@ void RimCorrelationPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrder
plotGroup->add( &m_showPlotTitle );
plotGroup->add( &m_useAutoPlotTitle );
plotGroup->add( &m_description );
RimPlot::defineUiOrdering( uiConfigName, *plotGroup );
m_description.uiCapability()->setUiReadOnly( m_useAutoPlotTitle() );
uiOrdering.skipRemainingFields( true );
}
@ -142,9 +144,12 @@ void RimCorrelationPlot::onLoadDataAndUpdate()
{
updateMdiWindowVisibility();
m_summaryAddressUiField = m_summaryAddress->address();
m_analyserOfSelectedCurveDefs = std::unique_ptr<RiaSummaryCurveDefinitionAnalyser>(
new RiaSummaryCurveDefinitionAnalyser( this->curveDefinitions() ) );
if ( m_plotWidget )
m_selectedVarsUiField = selectedVarsText();
if ( m_plotWidget && m_analyserOfSelectedCurveDefs )
{
m_plotWidget->detachItems( QwtPlotItem::Rtti_PlotBarChart );
m_plotWidget->detachItems( QwtPlotItem::Rtti_PlotScale );
@ -198,18 +203,18 @@ void RimCorrelationPlot::addDataToChartBuilder( RiuGroupedBarChartBuilder& chart
{
time_t selectedTimestep = m_timeStep().toTime_t();
if ( !m_ensemble ) return;
if ( !m_summaryAddress ) return;
std::vector<EnsembleParameter> ensembleParameters = m_ensemble->variationSortedEnsembleParameters();
if ( ensembles().empty() ) return;
if ( addresses().empty() ) return;
std::vector<double> caseValuesAtTimestep;
std::map<QString, std::vector<double>> parameterValues;
for ( size_t caseIdx = 0u; caseIdx < m_ensemble->allSummaryCases().size(); ++caseIdx )
auto ensemble = *ensembles().begin();
auto address = *addresses().begin();
for ( size_t caseIdx = 0u; caseIdx < ensemble->allSummaryCases().size(); ++caseIdx )
{
auto summaryCase = m_ensemble->allSummaryCases()[caseIdx];
auto summaryCase = ensemble->allSummaryCases()[caseIdx];
RifSummaryReaderInterface* reader = summaryCase->summaryReader();
if ( !reader ) continue;
@ -220,9 +225,9 @@ void RimCorrelationPlot::addDataToChartBuilder( RiuGroupedBarChartBuilder& chart
double closestValue = std::numeric_limits<double>::infinity();
time_t closestTimeStep = 0;
if ( reader->values( m_summaryAddress->address(), &values ) )
if ( reader->values( address, &values ) )
{
const std::vector<time_t>& timeSteps = reader->timeSteps( m_summaryAddress->address() );
const std::vector<time_t>& timeSteps = reader->timeSteps( address );
for ( size_t i = 0; i < timeSteps.size(); ++i )
{
if ( timeDiff( timeSteps[i], selectedTimestep ) < timeDiff( selectedTimestep, closestTimeStep ) )
@ -236,7 +241,7 @@ void RimCorrelationPlot::addDataToChartBuilder( RiuGroupedBarChartBuilder& chart
{
caseValuesAtTimestep.push_back( closestValue );
for ( auto parameter : ensembleParameters )
for ( auto parameter : ensembleParameters() )
{
if ( parameter.isNumeric() && parameter.isValid() )
{
@ -281,9 +286,7 @@ void RimCorrelationPlot::updatePlotTitle()
{
if ( m_useAutoPlotTitle )
{
m_description = QString( "%1 for %2" )
.arg( m_correlationFactor().uiText() )
.arg( QString::fromStdString( m_summaryAddressUiField().uiText() ) );
m_description = QString( "%1 for %2" ).arg( m_correlationFactor().uiText() ).arg( m_selectedVarsUiField );
}
m_plotWidget->setPlotTitle( m_description );
m_plotWidget->setPlotTitleEnabled( m_showPlotTitle && isMdiWindow() );

View File

@ -18,6 +18,7 @@
#include "RimCorrelationPlotCollection.h"
#include "RimCorrelationMatrixPlot.h"
#include "RimCorrelationPlot.h"
#include "RimParameterResultCrossPlot.h"
@ -49,7 +50,19 @@ RimCorrelationPlot* RimCorrelationPlotCollection::createCorrelationPlot()
RimCorrelationPlot* plot = new RimCorrelationPlot();
plot->setAsPlotMdiWindow();
// plot->enableAutoPlotTitle( true );
m_correlationPlots.push_back( plot );
return plot;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimCorrelationMatrixPlot* RimCorrelationPlotCollection::createCorrelationMatrixPlot()
{
RimCorrelationMatrixPlot* plot = new RimCorrelationMatrixPlot();
plot->setAsPlotMdiWindow();
m_correlationPlots.push_back( plot );
return plot;

View File

@ -23,6 +23,7 @@
class RimAbstractCorrelationPlot;
class RimCorrelationPlot;
class RimCorrelationMatrixPlot;
class RimParameterResultCrossPlot;
//==================================================================================================
@ -38,6 +39,7 @@ public:
~RimCorrelationPlotCollection() override;
RimCorrelationPlot* createCorrelationPlot();
RimCorrelationMatrixPlot* createCorrelationMatrixPlot();
RimParameterResultCrossPlot* createParameterResultCrossPlot();
void removePlot( RimAbstractCorrelationPlot* CorrelationPlot );

View File

@ -93,9 +93,10 @@ void RimParameterResultCrossPlot::fieldChangedByUi( const caf::PdmFieldHandle* c
//--------------------------------------------------------------------------------------------------
void RimParameterResultCrossPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
m_selectedVarsUiField = selectedVarsText();
caf::PdmUiGroup* curveDataGroup = uiOrdering.addNewGroup( "Summary Vector" );
curveDataGroup->add( &m_ensemble );
curveDataGroup->add( &m_summaryAddressUiField );
curveDataGroup->add( &m_selectedVarsUiField );
curveDataGroup->add( &m_pushButtonSelectSummaryAddress, { false, 1, 0 } );
curveDataGroup->add( &m_timeStep );
@ -106,6 +107,8 @@ void RimParameterResultCrossPlot::defineUiOrdering( QString uiConfigName, caf::P
plotGroup->add( &m_showPlotTitle );
plotGroup->add( &m_useAutoPlotTitle );
plotGroup->add( &m_description );
RimPlot::defineUiOrdering( uiConfigName, *plotGroup );
m_description.uiCapability()->setUiReadOnly( m_useAutoPlotTitle() );
uiOrdering.skipRemainingFields( true );
}
@ -120,12 +123,9 @@ QList<caf::PdmOptionItemInfo>
RimAbstractCorrelationPlot::calculateValueOptions( fieldNeedingOptions, useOptionsOnly );
if ( fieldNeedingOptions == &m_ensembleParameter )
{
if ( m_ensemble )
for ( const auto& param : ensembleParameters() )
{
for ( const auto& param : m_ensemble->variationSortedEnsembleParameters() )
{
options.push_back( caf::PdmOptionItemInfo( param.uiName(), param.name ) );
}
options.push_back( caf::PdmOptionItemInfo( param.uiName(), param.name ) );
}
}
return options;
@ -138,9 +138,12 @@ void RimParameterResultCrossPlot::onLoadDataAndUpdate()
{
updateMdiWindowVisibility();
m_summaryAddressUiField = m_summaryAddress->address();
m_analyserOfSelectedCurveDefs = std::unique_ptr<RiaSummaryCurveDefinitionAnalyser>(
new RiaSummaryCurveDefinitionAnalyser( this->curveDefinitions() ) );
if ( m_plotWidget )
m_selectedVarsUiField = selectedVarsText();
if ( m_plotWidget && m_analyserOfSelectedCurveDefs )
{
m_plotWidget->insertLegend( nullptr );
m_plotWidget->updateLegend();
@ -160,7 +163,7 @@ void RimParameterResultCrossPlot::updateAxes()
{
if ( !m_plotWidget ) return;
m_plotWidget->setAxisTitleText( QwtPlot::yLeft, QString::fromStdString( m_summaryAddressUiField().uiText() ) );
m_plotWidget->setAxisTitleText( QwtPlot::yLeft, m_selectedVarsUiField );
m_plotWidget->setAxisTitleEnabled( QwtPlot::yLeft, true );
m_plotWidget->setAxisAutoScale( QwtPlot::yLeft, true );
m_plotWidget->setAxisFontsAndAlignment( QwtPlot::yLeft, 11, 11, false, Qt::AlignCenter );
@ -178,19 +181,22 @@ void RimParameterResultCrossPlot::createPoints()
{
time_t selectedTimestep = m_timeStep().toTime_t();
if ( !m_ensemble ) return;
caf::ColorTable colorTable = RiaColorTables::categoryPaletteColors();
if ( !m_summaryAddress ) return;
if ( ensembles().empty() ) return;
if ( addresses().empty() ) return;
EnsembleParameter ensembleParameter = m_ensemble->ensembleParameter( m_ensembleParameter );
if ( !( ensembleParameter.isNumeric() && ensembleParameter.isValid() ) ) return;
auto ensemble = *ensembles().begin();
auto address = *addresses().begin();
EnsembleParameter parameter = ensembleParameter( m_ensembleParameter );
if ( !( parameter.isNumeric() && parameter.isValid() ) ) return;
for ( size_t caseIdx = 0u; caseIdx < m_ensemble->allSummaryCases().size(); ++caseIdx )
for ( size_t caseIdx = 0u; caseIdx < ensemble->allSummaryCases().size(); ++caseIdx )
{
std::vector<double> caseValuesAtTimestep;
std::vector<double> parameterValues;
auto summaryCase = m_ensemble->allSummaryCases()[caseIdx];
auto summaryCase = ensemble->allSummaryCases()[caseIdx];
RifSummaryReaderInterface* reader = summaryCase->summaryReader();
if ( !reader ) continue;
@ -201,9 +207,9 @@ void RimParameterResultCrossPlot::createPoints()
double closestValue = std::numeric_limits<double>::infinity();
time_t closestTimeStep = 0;
if ( reader->values( m_summaryAddress->address(), &values ) )
if ( reader->values( address, &values ) )
{
const std::vector<time_t>& timeSteps = reader->timeSteps( m_summaryAddress->address() );
const std::vector<time_t>& timeSteps = reader->timeSteps( address );
for ( size_t i = 0; i < timeSteps.size(); ++i )
{
if ( timeDiff( timeSteps[i], selectedTimestep ) < timeDiff( selectedTimestep, closestTimeStep ) )
@ -216,18 +222,15 @@ void RimParameterResultCrossPlot::createPoints()
if ( closestValue != std::numeric_limits<double>::infinity() )
{
caseValuesAtTimestep.push_back( closestValue );
double paramValue = ensembleParameter.values[caseIdx].toDouble();
double paramValue = parameter.values[caseIdx].toDouble();
parameterValues.push_back( paramValue );
RiuQwtPlotCurve* plotCurve = new RiuQwtPlotCurve;
plotCurve->setSamplesFromXValuesAndYValues( parameterValues, caseValuesAtTimestep, false );
plotCurve->setAppearance( RiuQwtPlotCurve::STYLE_NONE,
RiuQwtPlotCurve::INTERPOLATION_POINT_TO_POINT,
0,
QColor( Qt::red ) );
RiuQwtSymbol* symbol = new RiuQwtSymbol( RiuQwtSymbol::SYMBOL_ELLIPSE, "" );
QwtPlotCurve* plotCurve = new QwtPlotCurve;
plotCurve->setSamples( parameterValues.data(), caseValuesAtTimestep.data(), (int)parameterValues.size() );
plotCurve->setStyle( QwtPlotCurve::NoCurve );
RiuQwtSymbol* symbol = new RiuQwtSymbol( RiuQwtSymbol::SYMBOL_DIAMOND, "" );
symbol->setSize( 12, 12 );
symbol->setColor( QColor( Qt::red ) );
symbol->setColor( colorTable.cycledQColor( caseIdx ) );
plotCurve->setSymbol( symbol );
plotCurve->attach( m_plotWidget );
}
@ -241,9 +244,7 @@ void RimParameterResultCrossPlot::updatePlotTitle()
{
if ( m_useAutoPlotTitle )
{
m_description = QString( "Cross Plot %1 x %2" )
.arg( m_ensembleParameter )
.arg( QString::fromStdString( m_summaryAddressUiField().uiText() ) );
m_description = QString( "Cross Plot %1 x %2" ).arg( m_ensembleParameter ).arg( m_selectedVarsUiField() );
}
m_plotWidget->setPlotTitle( m_description );
m_plotWidget->setPlotTitleEnabled( m_showPlotTitle && isMdiWindow() );

View File

@ -39,6 +39,7 @@
#include "RimCellEdgeColors.h"
#include "RimCellRangeFilter.h"
#include "RimCellRangeFilterCollection.h"
#include "RimCorrelationMatrixPlot.h"
#include "RimCorrelationPlot.h"
#include "RimCorrelationPlotCollection.h"
#include "RimEclipseCase.h"
@ -530,12 +531,17 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
else if ( dynamic_cast<RimCorrelationPlotCollection*>( firstUiItem ) )
{
menuBuilder << "RicNewCorrelationPlotFeature";
menuBuilder << "RicNewCorrelationMatrixPlotFeature";
menuBuilder << "RicNewParameterResultCrossPlotFeature";
}
else if ( dynamic_cast<RimCorrelationPlot*>( firstUiItem ) )
{
menuBuilder << "RicNewCorrelationPlotFeature";
}
else if ( dynamic_cast<RimCorrelationMatrixPlot*>( firstUiItem ) )
{
menuBuilder << "RicNewCorrelationMatrixPlotFeature";
}
else if ( dynamic_cast<RimParameterResultCrossPlot*>( firstUiItem ) )
{
menuBuilder << "RicNewParameterResultCrossPlotFeature";

View File

@ -697,11 +697,11 @@ void RimWellLogTrack::updateXAxisAndGridTickIntervals()
{
m_plotWidget->enableGridLines( QwtPlot::xTop, false, false );
m_plotWidget->setAxisRange( QwtPlot::xTop, 0.0, 1.0 );
m_plotWidget->setAxisLabelsAndTicksEnabled( QwtPlot::xTop, false );
m_plotWidget->setAxisLabelsAndTicksEnabled( QwtPlot::xTop, false, false );
}
else
{
m_plotWidget->setAxisLabelsAndTicksEnabled( QwtPlot::xTop, true );
m_plotWidget->setAxisLabelsAndTicksEnabled( QwtPlot::xTop, true, true );
if ( m_explicitTickIntervals )
{
m_plotWidget->setMajorAndMinorTickIntervals( QwtPlot::xTop,

View File

@ -249,7 +249,7 @@ void RimSummaryCaseCollection::addCase( RimSummaryCase* summaryCase, bool update
if ( m_isEnsemble )
{
validateEnsembleCases( {summaryCase} );
validateEnsembleCases( { summaryCase } );
calculateEnsembleParametersIntersectionHash();
}
@ -339,6 +339,42 @@ std::set<RifEclipseSummaryAddress> RimSummaryCaseCollection::ensembleSummaryAddr
return addresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<time_t> RimSummaryCaseCollection::ensembleTimeSteps() const
{
std::set<time_t> allTimeSteps;
size_t maxAddrCount = 0;
int maxAddrIndex = -1;
for ( int i = 0; i < (int)m_cases.size(); i++ )
{
RimSummaryCase* currCase = m_cases[i];
if ( !currCase ) continue;
RifSummaryReaderInterface* reader = currCase->summaryReader();
if ( !reader ) continue;
size_t addrCount = reader->allResultAddresses().size();
if ( addrCount > maxAddrCount )
{
maxAddrCount = addrCount;
maxAddrIndex = (int)i;
}
}
if ( maxAddrIndex >= 0 && m_cases[maxAddrIndex]->summaryReader() )
{
const std::set<RifEclipseSummaryAddress>& addrs = m_cases[maxAddrIndex]->summaryReader()->allResultAddresses();
for ( RifEclipseSummaryAddress addr : addrs )
{
std::vector<time_t> timeSteps = m_cases[maxAddrIndex]->summaryReader()->timeSteps( addr );
allTimeSteps.insert( timeSteps.begin(), timeSteps.end() );
}
}
return allTimeSteps;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -413,6 +449,33 @@ const std::vector<EnsembleParameter>& RimSummaryCaseCollection::variationSortedE
return m_cachedSortedEnsembleParameters;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<EnsembleParameter> RimSummaryCaseCollection::alphabeticEnsembleParameters() const
{
std::set<QString> paramSet;
for ( RimSummaryCase* rimCase : this->allSummaryCases() )
{
if ( rimCase->caseRealizationParameters() != nullptr )
{
auto ps = rimCase->caseRealizationParameters()->parameters();
for ( auto p : ps )
{
paramSet.insert( p.first );
}
}
}
std::vector<EnsembleParameter> sortedEnsembleParameters;
sortedEnsembleParameters.reserve( paramSet.size() );
for ( const QString& parameterName : paramSet )
{
sortedEnsembleParameters.push_back( this->createEnsembleParameter( parameterName ) );
}
return sortedEnsembleParameters;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -102,6 +102,7 @@ public:
bool isEnsemble() const;
void setAsEnsemble( bool isEnsemble );
virtual std::set<RifEclipseSummaryAddress> ensembleSummaryAddresses() const;
virtual std::set<time_t> ensembleTimeSteps() const;
std::set<QString> wellsWithRftData() const;
std::set<QDateTime> rftTimeStepsForWell( const QString& wellName ) const;
RifReaderRftInterface* rftStatisticsReader();
@ -109,6 +110,7 @@ public:
int ensembleId() const;
const std::vector<EnsembleParameter>& variationSortedEnsembleParameters() const;
std::vector<EnsembleParameter> alphabeticEnsembleParameters() const;
EnsembleParameter ensembleParameter( const QString& paramName ) const;
void calculateEnsembleParametersIntersectionHash();

View File

@ -507,10 +507,10 @@ void RiuGroupedBarChartBuilder::addBarChartToPlot( QwtPlot* plot, Qt::Orientatio
barPoints = &( legendToBarPointsPair->second );
}
barPoints->push_back( {currentBarPosition, barDef.m_value} );
barPoints->push_back( { currentBarPosition, barDef.m_value } );
if ( !barDef.m_barText.isEmpty() )
{
positionedBarLabels[currentBarPosition] = {QwtScaleDiv::MinorTick, barDef.m_barText};
positionedBarLabels[currentBarPosition] = { QwtScaleDiv::MinorTick, barDef.m_barText };
}
// Increment the bar position for the next bar

View File

@ -622,7 +622,9 @@ void RiuMultiPlotPage::reinsertPlotWidgets()
subTitles[visibleIndex]->setVisible( m_showSubTitles );
plotWidgets[visibleIndex]->setAxisLabelsAndTicksEnabled( QwtPlot::yLeft, showYAxis( row, column ) );
plotWidgets[visibleIndex]->setAxisLabelsAndTicksEnabled( QwtPlot::yLeft,
showYAxis( row, column ),
showYAxis( row, column ) );
plotWidgets[visibleIndex]->setAxisTitleEnabled( QwtPlot::yLeft, showYAxis( row, column ) );
plotWidgets[visibleIndex]->show();

View File

@ -33,3 +33,20 @@ QwtScaleDiv RiuQwtLinearScaleEngine::divideScaleWithExplicitIntervals( double x1
return QwtScaleDiv( x1, x2, minorTicks, minorTicks, majorTicks );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QwtScaleDiv RiuQwtLinearScaleEngine::divideScaleWithExplicitIntervalsAndRange( double tickStart,
double tickEnd,
double majorStepInterval,
double minorStepInterval,
double rangeStart,
double rangeEnd )
{
QwtInterval tickInterval( tickStart, tickEnd );
QList<double> majorTicks = this->buildMajorTicks( tickInterval, majorStepInterval );
QList<double> minorTicks = this->buildMajorTicks( tickInterval, minorStepInterval );
return QwtScaleDiv( rangeStart, rangeEnd, minorTicks, minorTicks, majorTicks );
}

View File

@ -28,5 +28,14 @@
class RiuQwtLinearScaleEngine : public QwtLinearScaleEngine
{
public:
QwtScaleDiv divideScaleWithExplicitIntervals( double x1, double x2, double majorStepInterval, double minorStepInterval );
QwtScaleDiv divideScaleWithExplicitIntervals( double tickStart,
double tickEnd,
double majorStepInterval,
double minorStepInterval );
QwtScaleDiv divideScaleWithExplicitIntervalsAndRange( double tickStart,
double tickEnd,
double majorStepInterval,
double minorStepInterval,
double rangeStart,
double rangeEnd );
};

View File

@ -162,11 +162,11 @@ int RiuQwtPlotWidget::axisValueFontSize( QwtPlot::Axis axis ) const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::setAxisFontsAndAlignment( QwtPlot::Axis axis,
int titleFontSize,
int valueFontSize,
bool titleBold,
Qt::AlignmentFlag alignment )
void RiuQwtPlotWidget::setAxisFontsAndAlignment( QwtPlot::Axis axis,
int titleFontSize,
int valueFontSize,
bool titleBold,
int alignment )
{
// Axis number font
QFont axisFont = this->axisFont( axis );
@ -308,10 +308,10 @@ void RiuQwtPlotWidget::setAxisInverted( QwtPlot::Axis axis )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::setAxisLabelsAndTicksEnabled( QwtPlot::Axis axis, bool enable )
void RiuQwtPlotWidget::setAxisLabelsAndTicksEnabled( QwtPlot::Axis axis, bool enableLabels, bool enableTicks )
{
this->axisScaleDraw( axis )->enableComponent( QwtAbstractScaleDraw::Ticks, enable );
this->axisScaleDraw( axis )->enableComponent( QwtAbstractScaleDraw::Labels, enable );
this->axisScaleDraw( axis )->enableComponent( QwtAbstractScaleDraw::Ticks, enableTicks );
this->axisScaleDraw( axis )->enableComponent( QwtAbstractScaleDraw::Labels, enableLabels );
recalculateAxisExtents( axis );
}
@ -360,6 +360,31 @@ void RiuQwtPlotWidget::setMajorAndMinorTickIntervals( QwtPlot::Axis axis,
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::setMajorAndMinorTickIntervalsAndRange( QwtPlot::Axis axis,
double majorTickInterval,
double minorTickInterval,
double minTickValue,
double maxTickValue,
double rangeMin,
double rangeMax )
{
RiuQwtLinearScaleEngine* scaleEngine = dynamic_cast<RiuQwtLinearScaleEngine*>( this->axisScaleEngine( axis ) );
if ( scaleEngine )
{
QwtScaleDiv scaleDiv = scaleEngine->divideScaleWithExplicitIntervalsAndRange( minTickValue,
maxTickValue,
majorTickInterval,
minorTickInterval,
rangeMin,
rangeMax );
this->setAxisScaleDiv( axis, scaleDiv );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -71,10 +71,10 @@ public:
int axisTitleFontSize( QwtPlot::Axis axis ) const;
int axisValueFontSize( QwtPlot::Axis axis ) const;
void setAxisFontsAndAlignment( QwtPlot::Axis,
int titleFontSize,
int valueFontSize,
bool titleBold = false,
Qt::AlignmentFlag alignment = Qt::AlignRight );
int titleFontSize,
int valueFontSize,
bool titleBold = false,
int alignment = (int)Qt::AlignRight );
void setAxisTitleText( QwtPlot::Axis axis, const QString& title );
void setAxisTitleEnabled( QwtPlot::Axis axis, bool enable );
@ -91,7 +91,7 @@ public:
void setAxisRange( QwtPlot::Axis axis, double min, double max );
void setAxisInverted( QwtPlot::Axis axis );
void setAxisLabelsAndTicksEnabled( QwtPlot::Axis axis, bool enable );
void setAxisLabelsAndTicksEnabled( QwtPlot::Axis axis, bool enableLabels, bool enableTicks );
void enableGridLines( QwtPlot::Axis axis, bool majorGridLines, bool minorGridLines );
@ -100,6 +100,13 @@ public:
double minorTickInterval,
double minValue,
double maxValue );
void setMajorAndMinorTickIntervalsAndRange( QwtPlot::Axis axis,
double majorTickInterval,
double minorTickInterval,
double minTickValue,
double maxTickValue,
double rangeMin,
double rangeMax );
void setAutoTickIntervalCounts( QwtPlot::Axis axis, int maxMajorTickIntervalCount, int maxMinorTickIntervalCount );
double majorTickInterval( QwtPlot::Axis axis ) const;
double minorTickInterval( QwtPlot::Axis axis ) const;