mirror of
https://github.com/OPM/ResInsight.git
synced 2026-08-27 05:37:21 -05:00
Add new and more general histogram plots.
This commit is contained in:
@@ -134,6 +134,7 @@ list(
|
||||
ProjectDataModelCommands/CommandRouter/CMakeLists_files.cmake
|
||||
ProjectDataModel/VerticalFlowPerformance/CMakeLists_files.cmake
|
||||
ProjectDataModel/QuickAccess/CMakeLists_files.cmake
|
||||
ProjectDataModel/Histogram/CMakeLists_files.cmake
|
||||
GeoMech/GeoMechVisualization/CMakeLists_files.cmake
|
||||
ModelVisualization/CMakeLists_files.cmake
|
||||
ModelVisualization/Faults/CMakeLists_files.cmake
|
||||
|
||||
@@ -63,6 +63,7 @@ set(COMMAND_REFERENCED_CMAKE_FILES
|
||||
Sumo/CMakeLists_files.cmake
|
||||
ToolCommands/CMakeLists_files.cmake
|
||||
3dView/CMakeLists_files.cmake
|
||||
Histogram/CMakeLists_files.cmake
|
||||
)
|
||||
|
||||
# Include source file lists from *.cmake files
|
||||
|
||||
@@ -101,6 +101,7 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateContourMapPolygonTools.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicPolygonFromImageDialog.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateSummaryEnsembleFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicHistogramPlotTools.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -206,6 +207,7 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateContourMapPolygonTools.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicPolygonFromImageDialog.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateSummaryEnsembleFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicHistogramPlotTools.cpp
|
||||
)
|
||||
|
||||
if(RESINSIGHT_USE_QT_CHARTS)
|
||||
|
||||
@@ -4,6 +4,8 @@ set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewCorrelationMatrixPlotFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewParameterResultCrossPlotFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleFromFilteredCasesFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateHistogramForEnsembleParameterFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateHistogramForSummaryVectorFeature.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -12,6 +14,8 @@ set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewParameterResultCrossPlotFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewCorrelationReportPlotFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateEnsembleFromFilteredCasesFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateHistogramForEnsembleParameterFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicCreateHistogramForSummaryVectorFeature.cpp
|
||||
)
|
||||
|
||||
list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RicCreateHistogramForEnsembleParameterFeature.h"
|
||||
|
||||
#include "RicHistogramPlotTools.h"
|
||||
|
||||
#include "Histogram/RimEnsembleParameterHistogramDataSource.h"
|
||||
#include "RimCorrelationPlotCollection.h"
|
||||
#include "RimCorrelationReportPlot.h"
|
||||
#include "RimParameterResultCrossPlot.h"
|
||||
|
||||
#include "cafSelectionManagerTools.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
CAF_CMD_SOURCE_INIT( RicCreateHistogramForEnsembleParameterFeature, "RicCreateHistogramForEnsembleParameterFeature" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicCreateHistogramForEnsembleParameterFeature::isCommandEnabled() const
|
||||
{
|
||||
return selectedCrossPlot() != nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicCreateHistogramForEnsembleParameterFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
if ( auto crossPlot = selectedCrossPlot() )
|
||||
{
|
||||
auto multiplot = RicHistogramPlotTools::addNewHistogramMultiplot();
|
||||
auto histogramPlot = RicHistogramPlotTools::addNewHistogramPlot( multiplot );
|
||||
|
||||
QString ensembleParameter = crossPlot->ensembleParameter();
|
||||
auto ensembles = crossPlot->ensembles();
|
||||
for ( RimSummaryEnsemble* ensemble : ensembles )
|
||||
{
|
||||
auto dataSource = new RimEnsembleParameterHistogramDataSource();
|
||||
dataSource->setEnsembleParameter( ensembleParameter );
|
||||
dataSource->setEnsemble( ensemble );
|
||||
RicHistogramPlotTools::createHistogramCurve( histogramPlot, dataSource );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicCreateHistogramForEnsembleParameterFeature::setupActionLook( QAction* actionToSetup )
|
||||
{
|
||||
actionToSetup->setIcon( QIcon( ":/SummaryEnsemble.svg" ) );
|
||||
actionToSetup->setText( "Create Histogram Plot For Ensemble Parameter" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimParameterResultCrossPlot* RicCreateHistogramForEnsembleParameterFeature::selectedCrossPlot()
|
||||
{
|
||||
auto selectedPlots = caf::selectedObjectsByTypeStrict<RimParameterResultCrossPlot*>();
|
||||
if ( selectedPlots.size() == 1 ) return selectedPlots.front();
|
||||
|
||||
if ( auto reportPlot = caf::firstAncestorOfTypeFromSelectedObject<RimCorrelationReportPlot>() )
|
||||
{
|
||||
return reportPlot->crossPlot();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 RimParameterResultCrossPlot;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RicCreateHistogramForEnsembleParameterFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
private:
|
||||
bool isCommandEnabled() const override;
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
|
||||
static RimParameterResultCrossPlot* selectedCrossPlot();
|
||||
};
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RicCreateHistogramForSummaryVectorFeature.h"
|
||||
|
||||
#include "Histogram/RimEnsembleSummaryVectorHistogramDataSource.h"
|
||||
#include "RicHistogramPlotTools.h"
|
||||
|
||||
#include "Histogram/RimEnsembleParameterHistogramDataSource.h"
|
||||
#include "RimCorrelationPlotCollection.h"
|
||||
#include "RimCorrelationReportPlot.h"
|
||||
#include "RimParameterResultCrossPlot.h"
|
||||
|
||||
#include "cafSelectionManagerTools.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
CAF_CMD_SOURCE_INIT( RicCreateHistogramForSummaryVectorFeature, "RicCreateHistogramForSummaryVectorFeature" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicCreateHistogramForSummaryVectorFeature::isCommandEnabled() const
|
||||
{
|
||||
return selectedCrossPlot() != nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicCreateHistogramForSummaryVectorFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
if ( auto crossPlot = selectedCrossPlot() )
|
||||
{
|
||||
auto multiplot = RicHistogramPlotTools::addNewHistogramMultiplot();
|
||||
auto histogramPlot = RicHistogramPlotTools::addNewHistogramPlot( multiplot );
|
||||
|
||||
auto ensembles = crossPlot->ensembles();
|
||||
auto timeStep = crossPlot->timeStep();
|
||||
auto addresses = crossPlot->addresses();
|
||||
for ( RimSummaryEnsemble* ensemble : ensembles )
|
||||
{
|
||||
for ( auto address : addresses )
|
||||
{
|
||||
auto dataSource = new RimEnsembleSummaryVectorHistogramDataSource();
|
||||
dataSource->setEnsemble( ensemble );
|
||||
dataSource->setSummaryAddress( address );
|
||||
dataSource->setTimeStep( timeStep );
|
||||
RicHistogramPlotTools::createHistogramCurve( histogramPlot, dataSource );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicCreateHistogramForSummaryVectorFeature::setupActionLook( QAction* actionToSetup )
|
||||
{
|
||||
actionToSetup->setIcon( QIcon( ":/SummaryEnsemble.svg" ) );
|
||||
actionToSetup->setText( "Create Histogram Plot For Summary Vector" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimParameterResultCrossPlot* RicCreateHistogramForSummaryVectorFeature::selectedCrossPlot()
|
||||
{
|
||||
auto selectedPlots = caf::selectedObjectsByTypeStrict<RimParameterResultCrossPlot*>();
|
||||
if ( selectedPlots.size() == 1 ) return selectedPlots.front();
|
||||
|
||||
if ( auto reportPlot = caf::firstAncestorOfTypeFromSelectedObject<RimCorrelationReportPlot>() )
|
||||
{
|
||||
return reportPlot->crossPlot();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 RimParameterResultCrossPlot;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RicCreateHistogramForSummaryVectorFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
private:
|
||||
bool isCommandEnabled() const override;
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
|
||||
static RimParameterResultCrossPlot* selectedCrossPlot();
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewDefaultHistogramPlotFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewHistogramCurveFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewHistogramMultiPlotFeature.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewDefaultHistogramPlotFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewHistogramCurveFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewHistogramMultiPlotFeature.cpp
|
||||
)
|
||||
|
||||
list(APPEND COMMAND_CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
list(APPEND COMMAND_CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES})
|
||||
@@ -0,0 +1,59 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- 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 "RicNewDefaultHistogramPlotFeature.h"
|
||||
|
||||
#include "Histogram/RimHistogramMultiPlot.h"
|
||||
#include "Histogram/RimHistogramPlot.h"
|
||||
|
||||
#include "RicHistogramPlotTools.h"
|
||||
#include "cafSelectionManager.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
CAF_CMD_SOURCE_INIT( RicNewDefaultHistogramPlotFeature, "RicNewDefaultHistogramPlotFeature" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicNewDefaultHistogramPlotFeature::isCommandEnabled() const
|
||||
{
|
||||
RimHistogramMultiPlot* multiPlot = dynamic_cast<RimHistogramMultiPlot*>( caf::SelectionManager::instance()->selectedItem() );
|
||||
return multiPlot != nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewDefaultHistogramPlotFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
RimHistogramMultiPlot* multiPlot = dynamic_cast<RimHistogramMultiPlot*>( caf::SelectionManager::instance()->selectedItem() );
|
||||
if ( multiPlot )
|
||||
{
|
||||
RicHistogramPlotTools::addNewHistogramPlot( multiPlot );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewDefaultHistogramPlotFeature::setupActionLook( QAction* actionToSetup )
|
||||
{
|
||||
actionToSetup->setText( "Add Histogram Plot" );
|
||||
actionToSetup->setIcon( QIcon( ":/SummaryPlotLight16x16.png" ) );
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- 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 RicNewDefaultHistogramPlotFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
protected:
|
||||
bool isCommandEnabled() const override;
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- 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 "RicNewHistogramCurveFeature.h"
|
||||
|
||||
#include "RiaGuiApplication.h"
|
||||
|
||||
#include "Histogram/RimEnsembleParameterHistogramDataSource.h"
|
||||
#include "Histogram/RimEnsembleSummaryVectorHistogramDataSource.h"
|
||||
#include "Histogram/RimGridStatisticsHistogramDataSource.h"
|
||||
#include "Histogram/RimHistogramCurve.h"
|
||||
#include "Histogram/RimHistogramCurveCollection.h"
|
||||
#include "Histogram/RimHistogramPlot.h"
|
||||
#include "RicHistogramPlotTools.h"
|
||||
#include "RimProject.h"
|
||||
|
||||
#include "RiuPlotMainWindow.h"
|
||||
#include "RiuPlotMainWindowTools.h"
|
||||
|
||||
#include "cafSelectionManager.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
CAF_CMD_SOURCE_INIT( RicNewHistogramCurveFeature, "RicNewHistogramCurveFeature" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicNewHistogramCurveFeature::isCommandEnabled() const
|
||||
{
|
||||
return selectedHistogramPlot();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewHistogramCurveFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
auto getDataSourceFromString = []( const QString& dataSourceType ) -> RimHistogramDataSource*
|
||||
{
|
||||
if ( dataSourceType == "Ensemble Parameter" )
|
||||
return new RimEnsembleParameterHistogramDataSource();
|
||||
else if ( dataSourceType == "Grid Statistics" )
|
||||
return new RimGridStatisticsHistogramDataSource();
|
||||
else if ( dataSourceType == "Summary Vector" )
|
||||
return new RimEnsembleSummaryVectorHistogramDataSource();
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
RimHistogramPlot* plot = selectedHistogramPlot();
|
||||
if ( plot )
|
||||
{
|
||||
RimHistogramDataSource* dataSource = getDataSourceFromString( userData().toString() );
|
||||
RicHistogramPlotTools::createHistogramCurve( plot, dataSource );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewHistogramCurveFeature::setupActionLook( QAction* actionToSetup )
|
||||
{
|
||||
actionToSetup->setText( "New Histogram Curve" );
|
||||
actionToSetup->setIcon( QIcon( ":/SummaryCurve16x16.png" ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramPlot* RicNewHistogramCurveFeature::selectedHistogramPlot() const
|
||||
{
|
||||
caf::PdmObject* selObj = dynamic_cast<caf::PdmObject*>( caf::SelectionManager::instance()->selectedItem() );
|
||||
if ( selObj )
|
||||
{
|
||||
return selObj->firstAncestorOrThisOfType<RimHistogramPlot>();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- 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 RimHistogramPlot;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RicNewHistogramCurveFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
protected:
|
||||
bool isCommandEnabled() const override;
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
|
||||
private:
|
||||
RimHistogramPlot* selectedHistogramPlot() const;
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RicNewHistogramMultiPlotFeature.h"
|
||||
|
||||
#include "Histogram/RimHistogramMultiPlotCollection.h"
|
||||
|
||||
#include "RicHistogramPlotTools.h"
|
||||
|
||||
#include "cafSelectionManager.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
CAF_CMD_SOURCE_INIT( RicNewHistogramMultiPlotFeature, "RicNewHistogramMultiPlotFeature" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicNewHistogramMultiPlotFeature::isCommandEnabled() const
|
||||
{
|
||||
std::vector<RimHistogramMultiPlotCollection*> selectedItems =
|
||||
caf::SelectionManager::instance()->objectsByType<RimHistogramMultiPlotCollection>();
|
||||
|
||||
return ( selectedItems.size() == 1 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewHistogramMultiPlotFeature::onActionTriggered( bool isChecked )
|
||||
{
|
||||
std::vector<RimHistogramMultiPlotCollection*> selectedItems =
|
||||
caf::SelectionManager::instance()->objectsByType<RimHistogramMultiPlotCollection>();
|
||||
if ( selectedItems.size() != 1 ) return;
|
||||
|
||||
if ( RimHistogramMultiPlotCollection* coll = selectedItems[0] )
|
||||
{
|
||||
RicHistogramPlotTools::addNewHistogramMultiplot( coll );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewHistogramMultiPlotFeature::setupActionLook( QAction* actionToSetup )
|
||||
{
|
||||
actionToSetup->setText( "New Histogram Plot" );
|
||||
actionToSetup->setIcon( QIcon( ":/MultiPlot16x16.png" ) );
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 RimSummaryCase;
|
||||
class RimSummaryEnsemble;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RicNewHistogramMultiPlotFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
protected:
|
||||
bool isCommandEnabled() const override;
|
||||
void onActionTriggered( bool isChecked ) override;
|
||||
void setupActionLook( QAction* actionToSetup ) override;
|
||||
};
|
||||
@@ -0,0 +1,105 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- 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 "RicHistogramPlotTools.h"
|
||||
|
||||
#include "Histogram/RimHistogramCurve.h"
|
||||
#include "Histogram/RimHistogramDataSource.h"
|
||||
#include "Histogram/RimHistogramMultiPlot.h"
|
||||
#include "Histogram/RimHistogramMultiPlotCollection.h"
|
||||
#include "Histogram/RimHistogramPlot.h"
|
||||
#include "RimMainPlotCollection.h"
|
||||
#include "RimProject.h"
|
||||
|
||||
#include "RiaColorTables.h"
|
||||
#include "RiaGuiApplication.h"
|
||||
|
||||
#include "RiuPlotMainWindow.h"
|
||||
#include "RiuPlotMainWindowTools.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicHistogramPlotTools::createHistogramCurve( RimHistogramPlot* plot, RimHistogramDataSource* dataSource )
|
||||
{
|
||||
RiaGuiApplication* app = RiaGuiApplication::instance();
|
||||
RimProject* project = app->project();
|
||||
CAF_ASSERT( project );
|
||||
|
||||
RimHistogramCurve* newCurve = new RimHistogramCurve();
|
||||
|
||||
newCurve->setDataSource( dataSource );
|
||||
|
||||
cvf::Color3f curveColor = RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f( plot->curveCount() );
|
||||
newCurve->setColor( curveColor );
|
||||
newCurve->setIsStacked( true );
|
||||
newCurve->setFillColor( curveColor );
|
||||
|
||||
plot->addCurveNoUpdate( newCurve );
|
||||
|
||||
plot->loadDataAndUpdate();
|
||||
plot->updateConnectedEditors();
|
||||
|
||||
RiuPlotMainWindow* mainPlotWindow = app->mainPlotWindow();
|
||||
mainPlotWindow->updateMultiPlotToolBar();
|
||||
|
||||
RiuPlotMainWindowTools::onObjectAppended( newCurve, plot );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramMultiPlot* RicHistogramPlotTools::addNewHistogramMultiplot()
|
||||
{
|
||||
auto collection = RimMainPlotCollection::current()->histogramMultiPlotCollection();
|
||||
if ( !collection ) return nullptr;
|
||||
|
||||
return addNewHistogramMultiplot( collection );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramMultiPlot* RicHistogramPlotTools::addNewHistogramMultiplot( RimHistogramMultiPlotCollection* collection )
|
||||
{
|
||||
CAF_ASSERT( collection );
|
||||
|
||||
RimHistogramMultiPlot* multiplot = collection->appendHistogramMultiPlot();
|
||||
multiplot->setAsPlotMdiWindow();
|
||||
multiplot->setShowWindow( true );
|
||||
multiplot->loadDataAndUpdate();
|
||||
collection->updateConnectedEditors();
|
||||
|
||||
RiuPlotMainWindowTools::onObjectAppended( multiplot, collection );
|
||||
|
||||
return multiplot;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramPlot* RicHistogramPlotTools::addNewHistogramPlot( RimHistogramMultiPlot* histogramMultiPlot )
|
||||
{
|
||||
RimHistogramPlot* plot = new RimHistogramPlot();
|
||||
plot->enableAutoPlotTitle( true );
|
||||
histogramMultiPlot->addPlot( plot );
|
||||
|
||||
RiuPlotMainWindowTools::onObjectAppended( plot, histogramMultiPlot );
|
||||
|
||||
return plot;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- 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
|
||||
|
||||
class RimHistogramDataSource;
|
||||
class RimHistogramPlot;
|
||||
class RimHistogramMultiPlot;
|
||||
class RimHistogramMultiPlotCollection;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
class RicHistogramPlotTools
|
||||
{
|
||||
public:
|
||||
static void createHistogramCurve( RimHistogramPlot* plot, RimHistogramDataSource* dataSource );
|
||||
|
||||
static RimHistogramMultiPlot* addNewHistogramMultiplot();
|
||||
static RimHistogramMultiPlot* addNewHistogramMultiplot( RimHistogramMultiPlotCollection* collection );
|
||||
static RimHistogramPlot* addNewHistogramPlot( RimHistogramMultiPlot* histogramMultiPlot );
|
||||
};
|
||||
@@ -513,7 +513,7 @@ std::set<RigEnsembleParameter> RimAbstractCorrelationPlot::variationSortedEnsemb
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigEnsembleParameter RimAbstractCorrelationPlot::ensembleParameter( const QString& ensembleParameterName ) const
|
||||
RigEnsembleParameter RimAbstractCorrelationPlot::ensembleParameterByName( const QString& ensembleParameterName ) const
|
||||
{
|
||||
std::set<RigEnsembleParameter> ensembleParms = ensembleParameters();
|
||||
for ( const RigEnsembleParameter& eParam : ensembleParms )
|
||||
@@ -574,7 +574,10 @@ RiuPlotWidget* RimAbstractCorrelationPlot::doCreatePlotViewWidget( QWidget* main
|
||||
m_plotWidget = new RiuQwtPlotWidget( this, mainWindowParent );
|
||||
updatePlotTitle();
|
||||
|
||||
new RiuContextMenuLauncher( m_plotWidget, { "RicShowPlotDataFeature" } );
|
||||
new RiuContextMenuLauncher( m_plotWidget,
|
||||
{ "RicShowPlotDataFeature",
|
||||
"RicCreateHistogramForEnsembleParameterFeature",
|
||||
"RicCreateHistogramForSummaryVectorFeature" } );
|
||||
}
|
||||
|
||||
return m_plotWidget;
|
||||
|
||||
@@ -79,6 +79,8 @@ public:
|
||||
void setAxisValueFontSize( caf::FontTools::RelativeSize fontSize );
|
||||
std::set<time_t> allAvailableTimeSteps();
|
||||
|
||||
std::set<RifEclipseSummaryAddress> addresses() const;
|
||||
|
||||
protected:
|
||||
// Overridden PDM methods
|
||||
|
||||
@@ -88,10 +90,9 @@ protected:
|
||||
caf::PdmFieldHandle* userDescriptionField() override;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
|
||||
std::set<RifEclipseSummaryAddress> addresses() const;
|
||||
std::set<RigEnsembleParameter> ensembleParameters() const;
|
||||
std::set<RigEnsembleParameter> variationSortedEnsembleParameters();
|
||||
RigEnsembleParameter ensembleParameter( const QString& ensembleParameterName ) const;
|
||||
std::set<RigEnsembleParameter> ensembleParameters() const;
|
||||
std::set<RigEnsembleParameter> variationSortedEnsembleParameters();
|
||||
RigEnsembleParameter ensembleParameterByName( const QString& ensembleParameterName ) const;
|
||||
|
||||
// RimViewWindow overrides
|
||||
QWidget* viewWidget() override;
|
||||
|
||||
+13
-2
@@ -110,6 +110,14 @@ void RimParameterResultCrossPlot::setEnsembleParameter( const QString& ensembleP
|
||||
updateFilterRanges();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimParameterResultCrossPlot::ensembleParameter() const
|
||||
{
|
||||
return m_ensembleParameter;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -465,7 +473,7 @@ void RimParameterResultCrossPlot::detachAllCurves()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimParameterResultCrossPlot::CaseData> RimParameterResultCrossPlot::createCaseData() const
|
||||
{
|
||||
RigEnsembleParameter parameter = ensembleParameter( m_ensembleParameter );
|
||||
RigEnsembleParameter parameter = ensembleParameterByName( m_ensembleParameter );
|
||||
if ( !( parameter.isNumeric() && parameter.isValid() ) ) return {};
|
||||
|
||||
std::vector<RimParameterResultCrossPlot::CaseData> caseData;
|
||||
@@ -600,7 +608,10 @@ RiuPlotWidget* RimParameterResultCrossPlot::doCreatePlotViewWidget( QWidget* mai
|
||||
m_plotWidget = new RiuQwtPlotWidget( this, mainWindowParent );
|
||||
updatePlotTitle();
|
||||
|
||||
new RiuContextMenuLauncher( m_plotWidget, { "RicShowPlotDataFeature", "RicCreateEnsembleFromFilteredCasesFeature" } );
|
||||
new RiuContextMenuLauncher( m_plotWidget,
|
||||
{ "RicShowPlotDataFeature",
|
||||
"RicCreateEnsembleFromFilteredCasesFeature",
|
||||
"RicCreateHistogramForEnsembleParameterFeature" } );
|
||||
}
|
||||
|
||||
if ( m_plotWidget )
|
||||
|
||||
@@ -36,7 +36,8 @@ class RimParameterResultCrossPlot : public RimAbstractCorrelationPlot
|
||||
public:
|
||||
RimParameterResultCrossPlot();
|
||||
~RimParameterResultCrossPlot() override;
|
||||
void setEnsembleParameter( const QString& ensembleParameter );
|
||||
void setEnsembleParameter( const QString& ensembleParameter );
|
||||
QString ensembleParameter() const;
|
||||
|
||||
std::vector<RimSummaryCase*> summaryCasesExcludedByFilter() const;
|
||||
void appendFilterFields( caf::PdmUiOrdering& uiOrdering );
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
set(SOURCE_GROUP_HEADER_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleParameterHistogramDataSource.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleSummaryVectorHistogramDataSource.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimGridStatisticsHistogramDataSource.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramCurve.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramCurveCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramDataSource.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramMultiPlot.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramMultiPlotCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramPlot.h
|
||||
)
|
||||
|
||||
set(SOURCE_GROUP_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleParameterHistogramDataSource.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleSummaryVectorHistogramDataSource.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimGridStatisticsHistogramDataSource.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramCurve.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramCurveCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramDataSource.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramMultiPlot.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramMultiPlotCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimHistogramPlot.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES})
|
||||
list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES})
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimEnsembleParameterHistogramDataSource.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
|
||||
#include "Histogram/RimHistogramPlot.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimSummaryEnsemble.h"
|
||||
|
||||
#include "RigStatisticsMath.h"
|
||||
|
||||
CAF_PDM_XML_SOURCE_INIT( RimEnsembleParameterHistogramDataSource, "EnsembleParameterHistogramDataSource" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEnsembleParameterHistogramDataSource::RimEnsembleParameterHistogramDataSource()
|
||||
{
|
||||
CAF_PDM_InitObject( "Ensemble Parameter Histogram Data Source", );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_ensemble, "Ensemble", "Ensemble" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_parameter, "Parameter", "Parameter" );
|
||||
CAF_PDM_InitField( &m_numBins, "NumBins", 15, "Number of Bins" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEnsembleParameterHistogramDataSource::~RimEnsembleParameterHistogramDataSource()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo> RimEnsembleParameterHistogramDataSource::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
|
||||
if ( fieldNeedingOptions == &m_ensemble )
|
||||
{
|
||||
RimProject* proj = RimProject::current();
|
||||
|
||||
for ( RimSummaryEnsemble* ensemble : proj->summaryEnsembles() )
|
||||
{
|
||||
if ( ensemble->isEnsemble() ) options.push_back( caf::PdmOptionItemInfo( ensemble->name(), ensemble ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_parameter )
|
||||
{
|
||||
if ( m_ensemble )
|
||||
{
|
||||
for ( const RigEnsembleParameter& p : m_ensemble->variationSortedEnsembleParameters() )
|
||||
{
|
||||
if ( p.isNumeric() )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( p.name, p.name ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleParameterHistogramDataSource ::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_ensemble );
|
||||
uiOrdering.add( &m_parameter );
|
||||
uiOrdering.add( &m_numBins );
|
||||
|
||||
uiOrdering.skipRemainingFields( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleParameterHistogramDataSource::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
if ( changedField == &m_ensemble )
|
||||
{
|
||||
if ( m_ensemble )
|
||||
{
|
||||
// Try to find a new parameter if the current parameter is empty or not available
|
||||
// when changing ensemble.
|
||||
auto parameter = m_ensemble->ensembleParameter( m_parameter );
|
||||
if ( !parameter.isNumeric() || !parameter.isValid() )
|
||||
{
|
||||
// Find first valid numeric parameter
|
||||
for ( const RigEnsembleParameter& p : m_ensemble->variationSortedEnsembleParameters() )
|
||||
{
|
||||
if ( p.isNumeric() && p.isValid() )
|
||||
{
|
||||
m_parameter = p.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dataSourceChanged.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimEnsembleParameterHistogramDataSource::unitNameY() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimEnsembleParameterHistogramDataSource::unitNameX() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimEnsembleParameterHistogramDataSource::valuesX( RimHistogramPlot::GraphType graphType ) const
|
||||
{
|
||||
if ( !m_ensemble ) return {};
|
||||
|
||||
auto parameter = m_ensemble->ensembleParameter( m_parameter );
|
||||
if ( !parameter.isNumeric() || !parameter.isValid() ) return {};
|
||||
|
||||
double min = parameter.minValue;
|
||||
double max = parameter.maxValue;
|
||||
return computeHistogramBins( min, max, m_numBins, graphType );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimEnsembleParameterHistogramDataSource::valuesY( RimHistogramPlot::GraphType graphType,
|
||||
RimHistogramPlot::FrequencyType frequencyType ) const
|
||||
{
|
||||
if ( !m_ensemble ) return {};
|
||||
|
||||
auto parameter = m_ensemble->ensembleParameter( m_parameter );
|
||||
if ( !parameter.isNumeric() || !parameter.isValid() ) return {};
|
||||
|
||||
std::vector<double> values;
|
||||
for ( const QVariant& v : parameter.values )
|
||||
{
|
||||
values.push_back( v.toDouble() );
|
||||
}
|
||||
|
||||
double min = parameter.minValue;
|
||||
double max = parameter.maxValue;
|
||||
|
||||
std::vector<size_t> histogram;
|
||||
RigHistogramCalculator histCalc( min, max, m_numBins, &histogram );
|
||||
histCalc.addData( values );
|
||||
|
||||
double p10 = histCalc.calculatePercentil( 0.1, RigStatisticsMath::PercentileStyle::REGULAR );
|
||||
double p50 = histCalc.calculatePercentil( 0.5, RigStatisticsMath::PercentileStyle::REGULAR );
|
||||
double p90 = histCalc.calculatePercentil( 0.9, RigStatisticsMath::PercentileStyle::REGULAR );
|
||||
|
||||
RiaLogging::info( QString( "%1: P10=%2 Mean=%3 P90=%4" ).arg( QString::fromStdString( name() ) ).arg( p10 ).arg( p50 ).arg( p90 ) );
|
||||
|
||||
return computeHistogramFrequencies( histogram, graphType, frequencyType );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimEnsembleParameterHistogramDataSource::name() const
|
||||
{
|
||||
std::string name = "";
|
||||
if ( m_ensemble ) name = m_ensemble->name().toStdString();
|
||||
if ( !m_parameter().isEmpty() ) name += ", " + m_parameter().toStdString();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleParameterHistogramDataSource::setEnsembleParameter( const QString& ensembleParameter )
|
||||
{
|
||||
m_parameter = ensembleParameter;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleParameterHistogramDataSource::setEnsemble( RimSummaryEnsemble* ensemble )
|
||||
{
|
||||
m_ensemble = ensemble;
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimHistogramDataSource.h"
|
||||
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
class RimSummaryEnsemble;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimEnsembleParameterHistogramDataSource : public RimHistogramDataSource
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimEnsembleParameterHistogramDataSource();
|
||||
~RimEnsembleParameterHistogramDataSource() override;
|
||||
|
||||
void setEnsembleParameter( const QString& ensembleParameter );
|
||||
void setEnsemble( RimSummaryEnsemble* ensemble );
|
||||
|
||||
std::string unitNameX() const override;
|
||||
std::string unitNameY() const override;
|
||||
|
||||
std::vector<double> valuesX( RimHistogramPlot::GraphType graphType ) const override;
|
||||
std::vector<double> valuesY( RimHistogramPlot::GraphType graphType, RimHistogramPlot::FrequencyType frequencyType ) const override;
|
||||
|
||||
std::string name() const override;
|
||||
|
||||
protected:
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
caf::PdmPtrField<RimSummaryEnsemble*> m_ensemble;
|
||||
caf::PdmField<QString> m_parameter;
|
||||
caf::PdmField<int> m_numBins;
|
||||
};
|
||||
+310
@@ -0,0 +1,310 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimEnsembleSummaryVectorHistogramDataSource.h"
|
||||
|
||||
#include "RiaLogging.h"
|
||||
#include "RiaPreferences.h"
|
||||
#include "RiaQDateTimeTools.h"
|
||||
#include "RiaResultNames.h"
|
||||
|
||||
#include "RifSummaryReaderInterface.h"
|
||||
|
||||
#include "Histogram/RimHistogramPlot.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimSummaryCase.h"
|
||||
#include "RimSummaryEnsemble.h"
|
||||
|
||||
#include "RigStatisticsMath.h"
|
||||
|
||||
#include "cafPdmUiComboBoxEditor.h"
|
||||
#include "cafPdmUiLineEditor.h"
|
||||
|
||||
CAF_PDM_XML_SOURCE_INIT( RimEnsembleSummaryVectorHistogramDataSource, "EnsembleSummaryVectorHistogramDataSource" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEnsembleSummaryVectorHistogramDataSource::RimEnsembleSummaryVectorHistogramDataSource()
|
||||
{
|
||||
CAF_PDM_InitObject( "Ensemble Summary Vector Histogram Data Source", );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_ensemble, "Ensemble", "Ensemble" );
|
||||
|
||||
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()->setUiTreeChildrenHidden( true );
|
||||
m_summaryAddress = new RimSummaryAddress;
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_timeStep, "TimeStep", "Time Step" );
|
||||
m_timeStep.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() );
|
||||
|
||||
CAF_PDM_InitField( &m_numBins, "NumBins", 15, "Number of Bins" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimEnsembleSummaryVectorHistogramDataSource::~RimEnsembleSummaryVectorHistogramDataSource()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo> RimEnsembleSummaryVectorHistogramDataSource::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
|
||||
if ( fieldNeedingOptions == &m_ensemble )
|
||||
{
|
||||
RimProject* proj = RimProject::current();
|
||||
|
||||
for ( RimSummaryEnsemble* ensemble : proj->summaryEnsembles() )
|
||||
{
|
||||
if ( ensemble->isEnsemble() ) options.push_back( caf::PdmOptionItemInfo( ensemble->name(), ensemble ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_summaryAddressUiField )
|
||||
{
|
||||
appendOptionItemsForSummaryAddresses( &options, m_ensemble );
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_timeStep )
|
||||
{
|
||||
if ( m_ensemble )
|
||||
{
|
||||
std::set<time_t> allTimeSteps = m_ensemble->ensembleTimeSteps();
|
||||
QString dateFormatString = RiaQDateTimeTools::dateFormatString( RiaPreferences::current()->dateFormat(),
|
||||
RiaDefines::DateFormatComponents::DATE_FORMAT_YEAR_MONTH_DAY );
|
||||
|
||||
std::vector<QDateTime> allDateTimes;
|
||||
for ( time_t timeStep : allTimeSteps )
|
||||
{
|
||||
QDateTime dateTime = RiaQDateTimeTools::fromTime_t( timeStep );
|
||||
options.push_back(
|
||||
caf::PdmOptionItemInfo( RiaQDateTimeTools::toStringUsingApplicationLocale( dateTime, dateFormatString ), dateTime ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleSummaryVectorHistogramDataSource::appendOptionItemsForSummaryAddresses( QList<caf::PdmOptionItemInfo>* options,
|
||||
RimSummaryEnsemble* summaryCaseGroup )
|
||||
{
|
||||
if ( !summaryCaseGroup ) return;
|
||||
|
||||
auto allSummaryCases = summaryCaseGroup->allSummaryCases();
|
||||
|
||||
auto addressesForEnsemble = summaryCaseGroup->ensembleSummaryAddresses();
|
||||
|
||||
for ( const auto& addr : addressesForEnsemble )
|
||||
{
|
||||
std::string name = addr.uiText();
|
||||
QString s = QString::fromStdString( name );
|
||||
options->push_back( caf::PdmOptionItemInfo( s, QVariant::fromValue( addr ) ) );
|
||||
}
|
||||
|
||||
options->push_front( caf::PdmOptionItemInfo( RiaResultNames::undefinedResultName(), QVariant::fromValue( RifEclipseSummaryAddress() ) ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleSummaryVectorHistogramDataSource::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
m_summaryAddressUiField = m_summaryAddress->address();
|
||||
|
||||
uiOrdering.add( &m_ensemble );
|
||||
uiOrdering.add( &m_summaryAddressUiField );
|
||||
uiOrdering.add( &m_timeStep );
|
||||
uiOrdering.add( &m_numBins );
|
||||
|
||||
uiOrdering.skipRemainingFields( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleSummaryVectorHistogramDataSource::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
if ( changedField == &m_ensemble )
|
||||
{
|
||||
updateConnectedEditors();
|
||||
}
|
||||
else if ( changedField == &m_summaryAddressUiField )
|
||||
{
|
||||
m_summaryAddress->setAddress( m_summaryAddressUiField() );
|
||||
}
|
||||
|
||||
dataSourceChanged.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimEnsembleSummaryVectorHistogramDataSource::unitNameY() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimEnsembleSummaryVectorHistogramDataSource::unitNameX() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimEnsembleSummaryVectorHistogramDataSource::extractValuesFromEnsemble() const
|
||||
{
|
||||
std::vector<double> values;
|
||||
|
||||
time_t selectedTimestep = m_timeStep().toSecsSinceEpoch();
|
||||
|
||||
auto timeDiff = []( time_t lhs, time_t rhs ) -> time_t
|
||||
{
|
||||
if ( lhs >= rhs )
|
||||
{
|
||||
return lhs - rhs;
|
||||
}
|
||||
return rhs - lhs;
|
||||
};
|
||||
|
||||
if ( m_summaryAddress && m_ensemble )
|
||||
{
|
||||
for ( size_t caseIdx = 0u; caseIdx < m_ensemble->allSummaryCases().size(); ++caseIdx )
|
||||
{
|
||||
auto summaryCase = m_ensemble->allSummaryCases()[caseIdx];
|
||||
|
||||
RifSummaryReaderInterface* reader = summaryCase->summaryReader();
|
||||
if ( !reader ) continue;
|
||||
|
||||
double summaryValue = std::numeric_limits<double>::infinity();
|
||||
time_t closestTimeStep = 0;
|
||||
auto [isOk, summaryValues] = reader->values( m_summaryAddressUiField );
|
||||
if ( isOk )
|
||||
{
|
||||
const std::vector<time_t>& timeSteps = reader->timeSteps( m_summaryAddressUiField );
|
||||
for ( size_t i = 0; i < timeSteps.size(); ++i )
|
||||
{
|
||||
if ( timeDiff( timeSteps[i], selectedTimestep ) < timeDiff( selectedTimestep, closestTimeStep ) )
|
||||
{
|
||||
summaryValue = summaryValues[i];
|
||||
closestTimeStep = timeSteps[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( summaryValue != std::numeric_limits<double>::infinity() ) values.push_back( summaryValue );
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimEnsembleSummaryVectorHistogramDataSource::valuesX( RimHistogramPlot::GraphType graphType ) const
|
||||
{
|
||||
std::vector<double> values = extractValuesFromEnsemble();
|
||||
if ( values.empty() ) return {};
|
||||
|
||||
auto [min_it, max_it] = std::minmax_element( values.begin(), values.end() );
|
||||
|
||||
double min = *min_it;
|
||||
double max = *max_it;
|
||||
return computeHistogramBins( min, max, m_numBins, graphType );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimEnsembleSummaryVectorHistogramDataSource::valuesY( RimHistogramPlot::GraphType graphType,
|
||||
RimHistogramPlot::FrequencyType frequencyType ) const
|
||||
{
|
||||
std::vector<double> values = extractValuesFromEnsemble();
|
||||
if ( values.empty() ) return {};
|
||||
|
||||
auto [min_it, max_it] = std::minmax_element( values.begin(), values.end() );
|
||||
|
||||
double min = *min_it;
|
||||
double max = *max_it;
|
||||
|
||||
std::vector<size_t> histogram;
|
||||
RigHistogramCalculator histCalc( min, max, m_numBins, &histogram );
|
||||
histCalc.addData( values );
|
||||
|
||||
double p10 = histCalc.calculatePercentil( 0.1, RigStatisticsMath::PercentileStyle::REGULAR );
|
||||
double p50 = histCalc.calculatePercentil( 0.5, RigStatisticsMath::PercentileStyle::REGULAR );
|
||||
double p90 = histCalc.calculatePercentil( 0.9, RigStatisticsMath::PercentileStyle::REGULAR );
|
||||
|
||||
RiaLogging::info( QString( "%1: P10=%2 Mean=%3 P90=%4" ).arg( QString::fromStdString( name() ) ).arg( p10 ).arg( p50 ).arg( p90 ) );
|
||||
|
||||
return computeHistogramFrequencies( histogram, graphType, frequencyType );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimEnsembleSummaryVectorHistogramDataSource::name() const
|
||||
{
|
||||
std::string name = "";
|
||||
if ( m_ensemble ) name = m_ensemble->name().toStdString();
|
||||
if ( !m_summaryAddress->address().uiText().empty() ) name += ", " + m_summaryAddress->address().uiText();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleSummaryVectorHistogramDataSource::setEnsemble( RimSummaryEnsemble* ensemble )
|
||||
{
|
||||
m_ensemble = ensemble;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleSummaryVectorHistogramDataSource::setSummaryAddress( RifEclipseSummaryAddress& summaryAddress )
|
||||
{
|
||||
m_summaryAddressUiField = summaryAddress;
|
||||
m_summaryAddress->setAddress( m_summaryAddressUiField );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimEnsembleSummaryVectorHistogramDataSource::setTimeStep( QDateTime& timeStep )
|
||||
{
|
||||
m_timeStep = timeStep;
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimHistogramDataSource.h"
|
||||
|
||||
#include "RimSummaryAddress.h"
|
||||
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
class RimSummaryEnsemble;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimEnsembleSummaryVectorHistogramDataSource : public RimHistogramDataSource
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimEnsembleSummaryVectorHistogramDataSource();
|
||||
~RimEnsembleSummaryVectorHistogramDataSource() override;
|
||||
|
||||
void setEnsemble( RimSummaryEnsemble* ensemble );
|
||||
void setSummaryAddress( RifEclipseSummaryAddress& summaryAddress );
|
||||
void setTimeStep( QDateTime& timeStep );
|
||||
|
||||
std::string unitNameX() const override;
|
||||
std::string unitNameY() const override;
|
||||
|
||||
std::vector<double> valuesX( RimHistogramPlot::GraphType graphType ) const override;
|
||||
std::vector<double> valuesY( RimHistogramPlot::GraphType graphType, RimHistogramPlot::FrequencyType frequencyType ) const override;
|
||||
|
||||
std::string name() const override;
|
||||
|
||||
protected:
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
void appendOptionItemsForSummaryAddresses( QList<caf::PdmOptionItemInfo>* options, RimSummaryEnsemble* summaryCaseGroup );
|
||||
std::vector<double> extractValuesFromEnsemble() const;
|
||||
|
||||
caf::PdmPtrField<RimSummaryEnsemble*> m_ensemble;
|
||||
caf::PdmChildField<RimSummaryAddress*> m_summaryAddress;
|
||||
caf::PdmField<RifEclipseSummaryAddress> m_summaryAddressUiField;
|
||||
caf::PdmField<QDateTime> m_timeStep;
|
||||
caf::PdmField<int> m_numBins;
|
||||
};
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimGridStatisticsHistogramDataSource.h"
|
||||
|
||||
#include "Histogram/RimHistogramPlot.h"
|
||||
#include "RimEclipseCase.h"
|
||||
#include "RimEclipseResultDefinition.h"
|
||||
#include "RimEclipseView.h"
|
||||
#include "RimHistogramCalculator.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimTools.h"
|
||||
|
||||
#include "cafPdmUiComboBoxEditor.h"
|
||||
|
||||
CAF_PDM_XML_SOURCE_INIT( RimGridStatisticsHistogramDataSource, "GridStatisticsHistogramDataSource" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimGridStatisticsHistogramDataSource::RimGridStatisticsHistogramDataSource()
|
||||
{
|
||||
CAF_PDM_InitObject( "Ensemble Parameter Histogram Data Source", );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_case, "Case", "Case" );
|
||||
m_case.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
CAF_PDM_InitField( &m_timeStep, "TimeStep", -1, "Time Step" );
|
||||
m_timeStep.uiCapability()->setUiEditorTypeName( caf::PdmUiComboBoxEditor::uiEditorTypeName() );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_cellFilterView, "VisibleCellView", "Filter by 3d View Visibility" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_property, "Property", "Property" );
|
||||
m_property = new RimEclipseResultDefinition( caf::PdmUiItemInfo::TOP );
|
||||
m_property.uiCapability()->setUiTreeChildrenHidden( true );
|
||||
m_property->setTernaryEnabled( false );
|
||||
|
||||
CAF_PDM_InitField( &m_numBins, "NumBins", 15, "Number of Bins" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimGridStatisticsHistogramDataSource::~RimGridStatisticsHistogramDataSource()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo> RimGridStatisticsHistogramDataSource::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
|
||||
if ( fieldNeedingOptions == &m_case )
|
||||
{
|
||||
RimTools::eclipseCaseOptionItems( &options );
|
||||
if ( options.empty() )
|
||||
{
|
||||
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_timeStep )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( "All Time Steps", -1 ) );
|
||||
|
||||
RimTools::timeStepsForCase( m_case, &options );
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_cellFilterView )
|
||||
{
|
||||
if ( RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_case() ) )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( "Disabled", nullptr ) );
|
||||
for ( RimEclipseView* view : eclipseCase->reservoirViews() )
|
||||
{
|
||||
CVF_ASSERT( view && "Really always should have a valid view pointer in ReservoirViews" );
|
||||
options.push_back( caf::PdmOptionItemInfo( view->name(), view, false, view->uiIconProvider() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridStatisticsHistogramDataSource ::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
uiOrdering.add( &m_case );
|
||||
if ( m_case )
|
||||
{
|
||||
uiOrdering.add( &m_timeStep );
|
||||
uiOrdering.add( &m_cellFilterView );
|
||||
caf::PdmUiGroup* propertyGroup = uiOrdering.addNewGroup( "Property" );
|
||||
m_property->uiOrdering( uiConfigName, *propertyGroup );
|
||||
}
|
||||
|
||||
uiOrdering.add( &m_numBins );
|
||||
|
||||
uiOrdering.skipRemainingFields( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimGridStatisticsHistogramDataSource::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
const QVariant& oldValue,
|
||||
const QVariant& newValue )
|
||||
{
|
||||
if ( changedField == &m_case )
|
||||
{
|
||||
if ( RimEclipseCase* eclipseCase = dynamic_cast<RimEclipseCase*>( m_case.value() ) )
|
||||
{
|
||||
m_property->setEclipseCase( eclipseCase );
|
||||
m_property->updateConnectedEditors();
|
||||
dataSourceChanged.send();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dataSourceChanged.send();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimGridStatisticsHistogramDataSource::unitNameY() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimGridStatisticsHistogramDataSource::unitNameX() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimGridStatisticsHistogramDataSource::valuesX( RimHistogramPlot::GraphType graphType ) const
|
||||
{
|
||||
RigHistogramData histogramData = createStatisticsData();
|
||||
if ( !histogramData.isHistogramVectorValid() ) return {};
|
||||
|
||||
double min = histogramData.min;
|
||||
double max = histogramData.max;
|
||||
|
||||
return computeHistogramBins( min, max, m_numBins, graphType );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimGridStatisticsHistogramDataSource::valuesY( RimHistogramPlot::GraphType graphType,
|
||||
RimHistogramPlot::FrequencyType frequencyType ) const
|
||||
{
|
||||
RigHistogramData histogramData = createStatisticsData();
|
||||
if ( !histogramData.isHistogramVectorValid() ) return {};
|
||||
|
||||
return computeHistogramFrequencies( histogramData.histogram, graphType, frequencyType );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RigHistogramData RimGridStatisticsHistogramDataSource::createStatisticsData() const
|
||||
{
|
||||
std::unique_ptr<RimHistogramCalculator> histogramCalculator = std::make_unique<RimHistogramCalculator>();
|
||||
histogramCalculator->setNumBins( static_cast<size_t>( m_numBins() ) );
|
||||
|
||||
RimHistogramCalculator::StatisticsCellRangeType cellRange = RimHistogramCalculator::StatisticsCellRangeType::ALL_CELLS;
|
||||
|
||||
RimHistogramCalculator::StatisticsTimeRangeType timeRange = RimHistogramCalculator::StatisticsTimeRangeType::ALL_TIMESTEPS;
|
||||
int timeStep = 0;
|
||||
if ( m_timeStep() != -1 && !m_property()->hasStaticResult() )
|
||||
{
|
||||
timeStep = m_timeStep();
|
||||
timeRange = RimHistogramCalculator::StatisticsTimeRangeType::CURRENT_TIMESTEP;
|
||||
}
|
||||
|
||||
if ( m_cellFilterView.value() )
|
||||
{
|
||||
// Filter by visible cells of the view
|
||||
cellRange = RimHistogramCalculator::StatisticsCellRangeType::VISIBLE_CELLS;
|
||||
RimEclipseView* eclipseView = dynamic_cast<RimEclipseView*>( m_cellFilterView.value() );
|
||||
return histogramCalculator->histogramData( eclipseView, m_property.value(), cellRange, timeRange, timeStep );
|
||||
}
|
||||
else
|
||||
{
|
||||
RimEclipseView* eclipseView = nullptr;
|
||||
return histogramCalculator->histogramData( eclipseView, m_property.value(), cellRange, timeRange, timeStep );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimGridStatisticsHistogramDataSource::name() const
|
||||
{
|
||||
if ( m_case() == nullptr ) return "Undefined";
|
||||
|
||||
QStringList nameTags;
|
||||
nameTags += m_property()->resultVariable();
|
||||
nameTags += m_case()->caseUserDescription();
|
||||
|
||||
auto createTimeStepString = [this]() -> QString
|
||||
{
|
||||
if ( m_case() && m_property->hasDynamicResult() )
|
||||
{
|
||||
if ( m_timeStep == -1 ) return "All Time Steps";
|
||||
return m_case->timeStepStrings()[m_timeStep];
|
||||
}
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
QString timeStepStr = createTimeStepString();
|
||||
if ( !timeStepStr.isEmpty() )
|
||||
{
|
||||
nameTags += timeStepStr;
|
||||
}
|
||||
|
||||
return nameTags.join( ", " ).toStdString();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RigHistogramData.h"
|
||||
#include "RimHistogramDataSource.h"
|
||||
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
class RimSummaryEnsemble;
|
||||
class RimCase;
|
||||
class RimGridView;
|
||||
class RimEclipseResultDefinition;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimGridStatisticsHistogramDataSource : public RimHistogramDataSource
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimGridStatisticsHistogramDataSource();
|
||||
~RimGridStatisticsHistogramDataSource() override;
|
||||
|
||||
std::string unitNameX() const override;
|
||||
std::string unitNameY() const override;
|
||||
|
||||
std::vector<double> valuesX( RimHistogramPlot::GraphType graphType ) const override;
|
||||
std::vector<double> valuesY( RimHistogramPlot::GraphType graphType, RimHistogramPlot::FrequencyType frequencyType ) const override;
|
||||
|
||||
std::string name() const override;
|
||||
|
||||
protected:
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
RigHistogramData createStatisticsData() const;
|
||||
|
||||
caf::PdmPtrField<RimCase*> m_case;
|
||||
caf::PdmField<int> m_timeStep;
|
||||
caf::PdmPtrField<RimGridView*> m_cellFilterView;
|
||||
caf::PdmChildField<RimEclipseResultDefinition*> m_property;
|
||||
caf::PdmField<int> m_numBins;
|
||||
};
|
||||
@@ -0,0 +1,407 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimHistogramCurve.h"
|
||||
|
||||
#include "RiaGuiApplication.h"
|
||||
#include "RiaPlotDefines.h"
|
||||
|
||||
#include "RimHistogramCurveCollection.h"
|
||||
#include "RimHistogramDataSource.h"
|
||||
#include "RimHistogramPlot.h"
|
||||
#include "RimPlotAxisProperties.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimTools.h"
|
||||
|
||||
#include "RiuPlotAxis.h"
|
||||
#include "RiuPlotCurve.h"
|
||||
#include "RiuPlotMainWindow.h"
|
||||
|
||||
#include "cafAssert.h"
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimHistogramCurve, "HistogramCurve" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramCurve::RimHistogramCurve()
|
||||
{
|
||||
CAF_PDM_InitObject( "Histogram Curve", ":/SummaryCurve16x16.png" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_yPlotAxisProperties, "YAxis", "Y Axis" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_xPlotAxisProperties, "XAxis", "X Axis" );
|
||||
CAF_PDM_InitFieldNoDefault( &m_dataSource, "DataSource", "Data Source" );
|
||||
m_dataSource.uiCapability()->setUiTreeHidden( true );
|
||||
|
||||
setSymbolSkipDistance( 10.0f );
|
||||
setLineThickness( 2 );
|
||||
|
||||
setDeletable( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramCurve::~RimHistogramCurve()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::setTopOrBottomAxisX( RiuPlotAxis plotAxis )
|
||||
{
|
||||
CAF_ASSERT( plotAxis.isHorizontal() );
|
||||
|
||||
RimHistogramPlot* plot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
m_xPlotAxisProperties = plot->axisPropertiesForPlotAxis( plotAxis );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::setDataSource( RimHistogramDataSource* dataSource )
|
||||
{
|
||||
m_dataSource = dataSource;
|
||||
|
||||
if ( m_dataSource )
|
||||
{
|
||||
m_dataSource->uiCapability()->setUiTreeHidden( true );
|
||||
m_dataSource->dataSourceChanged.connect( this, &RimHistogramCurve::onDataSourceChanged );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiuPlotAxis RimHistogramCurve::axisX() const
|
||||
{
|
||||
if ( m_xPlotAxisProperties )
|
||||
return m_xPlotAxisProperties->plotAxis();
|
||||
else
|
||||
return RiuPlotAxis::defaultBottom();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimHistogramCurve::unitNameY() const
|
||||
{
|
||||
if ( m_dataSource )
|
||||
return m_dataSource()->unitNameY();
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RimHistogramCurve::unitNameX() const
|
||||
{
|
||||
if ( m_dataSource )
|
||||
return m_dataSource()->unitNameX();
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimHistogramCurve::valuesY() const
|
||||
{
|
||||
if ( m_dataSource )
|
||||
{
|
||||
RimHistogramPlot* plot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
return m_dataSource()->valuesY( plot->graphType(), plot->frequencyType() );
|
||||
}
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimHistogramCurve::valuesX() const
|
||||
{
|
||||
if ( m_dataSource )
|
||||
{
|
||||
RimHistogramPlot* plot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
return m_dataSource()->valuesX( plot->graphType() );
|
||||
}
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::setLeftOrRightAxisY( RiuPlotAxis plotAxis )
|
||||
{
|
||||
CAF_ASSERT( plotAxis.isVertical() );
|
||||
|
||||
RimHistogramPlot* plot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
m_yPlotAxisProperties = plot->axisPropertiesForPlotAxis( plotAxis );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiuPlotAxis RimHistogramCurve::axisY() const
|
||||
{
|
||||
if ( m_yPlotAxisProperties )
|
||||
return m_yPlotAxisProperties->plotAxis();
|
||||
else
|
||||
return RiuPlotAxis::defaultLeft();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo> RimHistogramCurve::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options = RimPlotCurve::calculateValueOptions( fieldNeedingOptions );
|
||||
if ( !options.isEmpty() )
|
||||
return options;
|
||||
else if ( fieldNeedingOptions == &m_yPlotAxisProperties )
|
||||
{
|
||||
auto plot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
|
||||
for ( auto axis : plot->plotAxes( RimPlotAxisProperties::Orientation::VERTICAL ) )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( axis->objectName(), axis ) );
|
||||
}
|
||||
}
|
||||
else if ( fieldNeedingOptions == &m_xPlotAxisProperties )
|
||||
{
|
||||
auto plot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
|
||||
for ( auto axis : plot->plotAxes( RimPlotAxisProperties::Orientation::HORIZONTAL ) )
|
||||
{
|
||||
options.push_back( caf::PdmOptionItemInfo( axis->objectName(), axis ) );
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimHistogramCurve::createCurveAutoName()
|
||||
{
|
||||
QString curveName = "";
|
||||
if ( m_dataSource )
|
||||
{
|
||||
curveName = QString::fromStdString( m_dataSource->name() );
|
||||
}
|
||||
|
||||
if ( curveName.isEmpty() )
|
||||
{
|
||||
curveName = "Curve Name Placeholder";
|
||||
}
|
||||
|
||||
return curveName;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::updateZoomInParentPlot()
|
||||
{
|
||||
auto plot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
|
||||
plot->updatePlotWidgetFromAxisRanges();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::onLoadDataAndUpdate( bool updateParentPlot )
|
||||
{
|
||||
RimPlotCurve::updateCurvePresentation( updateParentPlot );
|
||||
|
||||
updateConnectedEditors();
|
||||
|
||||
if ( isChecked() )
|
||||
{
|
||||
std::vector<double> curveValuesX = valuesX();
|
||||
std::vector<double> curveValuesY = valuesY();
|
||||
|
||||
auto plot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
bool useLogarithmicScale = plot->isLogarithmicScaleEnabled( axisY() );
|
||||
|
||||
setSamplesFromXYValues( curveValuesX, curveValuesY, useLogarithmicScale );
|
||||
}
|
||||
|
||||
if ( updateParentPlot && hasParentPlot() )
|
||||
{
|
||||
updateZoomInParentPlot();
|
||||
replotParentPlot();
|
||||
}
|
||||
|
||||
if ( updateParentPlot ) updatePlotAxis();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::updateLegendsInPlot()
|
||||
{
|
||||
auto plot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
plot->updateLegend();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/ )
|
||||
{
|
||||
RimPlotCurve::defineUiTreeOrdering( uiTreeOrdering, uiConfigName );
|
||||
|
||||
caf::IconProvider iconProvider = uiIconProvider();
|
||||
if ( !iconProvider.valid() ) return;
|
||||
|
||||
uiTreeOrdering.skipRemainingChildren( true );
|
||||
|
||||
setUiIcon( iconProvider );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
RimPlotCurve::updateFieldUiState();
|
||||
|
||||
if ( m_dataSource )
|
||||
{
|
||||
caf::PdmUiGroup* dataSourceGroup = uiOrdering.addNewGroup( "Data Source" );
|
||||
m_dataSource->uiOrdering( uiConfigName, *dataSourceGroup );
|
||||
}
|
||||
|
||||
caf::PdmUiGroup* stackingGroup = uiOrdering.addNewGroup( "Stacking" );
|
||||
RimStackablePlotCurve::stackingUiOrdering( *stackingGroup );
|
||||
|
||||
caf::PdmUiGroup* appearanceGroup = uiOrdering.addNewGroup( "Appearance" );
|
||||
RimPlotCurve::appearanceUiOrdering( *appearanceGroup );
|
||||
|
||||
caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup( "Curve Name" );
|
||||
nameGroup->setCollapsedByDefault();
|
||||
nameGroup->add( &m_showLegend );
|
||||
RimPlotCurve::curveNameUiOrdering( *nameGroup );
|
||||
|
||||
uiOrdering.skipRemainingFields();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::updatePlotAxis()
|
||||
{
|
||||
updateYAxisInPlot( axisY() );
|
||||
updateXAxisInPlot( axisX() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
||||
{
|
||||
RimStackablePlotCurve::fieldChangedByUi( changedField, oldValue, newValue );
|
||||
|
||||
auto plot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
|
||||
bool loadAndUpdate = false;
|
||||
if ( &m_showCurve == changedField )
|
||||
{
|
||||
plot->updateAxes();
|
||||
plot->updatePlotTitle();
|
||||
}
|
||||
else if ( changedField == &m_yPlotAxisProperties )
|
||||
{
|
||||
updateYAxisInPlot( axisY() );
|
||||
plot->updateAxes();
|
||||
dataChanged.send();
|
||||
}
|
||||
else if ( changedField == &m_xPlotAxisProperties )
|
||||
{
|
||||
updateXAxisInPlot( axisX() );
|
||||
plot->updateAxes();
|
||||
dataChanged.send();
|
||||
}
|
||||
|
||||
if ( loadAndUpdate )
|
||||
{
|
||||
loadAndUpdateDataAndPlot();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::loadAndUpdateDataAndPlot()
|
||||
{
|
||||
loadDataAndUpdate( true );
|
||||
|
||||
auto plot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
|
||||
plot->updateAxes();
|
||||
plot->updatePlotTitle();
|
||||
plot->updateConnectedEditors();
|
||||
|
||||
RiuPlotMainWindow* mainPlotWindow = RiaGuiApplication::instance()->mainPlotWindow();
|
||||
mainPlotWindow->updateMultiPlotToolBar();
|
||||
|
||||
dataChanged.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::updateLegendEntryVisibilityNoPlotUpdate()
|
||||
{
|
||||
if ( !m_plotCurve ) return;
|
||||
|
||||
bool showLegendInPlot = m_showLegend();
|
||||
|
||||
m_plotCurve->setVisibleInLegend( showLegendInPlot );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimHistogramCurve::canCurveBeAttached() const
|
||||
{
|
||||
if ( !RimPlotCurve::canCurveBeAttached() ) return false;
|
||||
|
||||
bool isVisibleInPossibleParent = true;
|
||||
|
||||
auto histogramCurveCollection = firstAncestorOrThisOfType<RimHistogramCurveCollection>();
|
||||
if ( histogramCurveCollection ) isVisibleInPossibleParent = histogramCurveCollection->isCurvesVisible();
|
||||
|
||||
return isVisibleInPossibleParent;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurve::onDataSourceChanged( const caf::SignalEmitter* emitter )
|
||||
{
|
||||
loadAndUpdateDataAndPlot();
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "cafPdmChildField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
#include "RimStackablePlotCurve.h"
|
||||
|
||||
class RimPlotAxisPropertiesInterface;
|
||||
class RimHistogramDataSource;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimHistogramCurve : public RimStackablePlotCurve
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimHistogramCurve();
|
||||
~RimHistogramCurve() override;
|
||||
|
||||
// Y Axis functions
|
||||
std::string unitNameY() const;
|
||||
virtual std::vector<double> valuesY() const;
|
||||
void setLeftOrRightAxisY( RiuPlotAxis plotAxis );
|
||||
RiuPlotAxis axisY() const;
|
||||
|
||||
// X Axis functions
|
||||
std::string unitNameX() const;
|
||||
virtual std::vector<double> valuesX() const;
|
||||
void setTopOrBottomAxisX( RiuPlotAxis plotAxis );
|
||||
RiuPlotAxis axisX() const;
|
||||
|
||||
void updatePlotAxis();
|
||||
void updateLegendEntryVisibilityNoPlotUpdate() override;
|
||||
|
||||
void setDataSource( RimHistogramDataSource* dataSource );
|
||||
|
||||
protected:
|
||||
// RimPlotCurve overrides
|
||||
QString createCurveAutoName() override;
|
||||
void updateZoomInParentPlot() override;
|
||||
void onLoadDataAndUpdate( bool updateParentPlot ) override;
|
||||
|
||||
void loadAndUpdateDataAndPlot();
|
||||
|
||||
void updateLegendsInPlot() override;
|
||||
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
bool canCurveBeAttached() const override;
|
||||
|
||||
// Overridden PDM methods
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
QList<caf::PdmOptionItemInfo> calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
|
||||
void hideXAxisGroup();
|
||||
|
||||
void onDataSourceChanged( const caf::SignalEmitter* emitter );
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimPlotAxisPropertiesInterface*> m_yPlotAxisProperties;
|
||||
caf::PdmPtrField<RimPlotAxisPropertiesInterface*> m_xPlotAxisProperties;
|
||||
|
||||
caf::PdmChildField<RimHistogramDataSource*> m_dataSource;
|
||||
};
|
||||
@@ -0,0 +1,302 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- 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 "RimHistogramCurveCollection.h"
|
||||
|
||||
#include "RimHistogramCurve.h"
|
||||
#include "RimHistogramPlot.h"
|
||||
|
||||
#include "cafPdmFieldReorderCapability.h"
|
||||
#include "cafPdmUiTreeAttributes.h"
|
||||
#include "cafPdmUiTreeViewEditor.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimHistogramCurveCollection, "RimHistogramCurveCollection" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramCurveCollection::RimHistogramCurveCollection()
|
||||
: curvesChanged( this )
|
||||
{
|
||||
CAF_PDM_InitObject( "Histogram Curves", ":/HistogramCurveFilter16x16.png" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_curves, "CollectionCurves", "Curves" );
|
||||
caf::PdmFieldReorderCapability::addToFieldWithCallback( &m_curves, this, &RimHistogramCurveCollection::onCurvesReordered );
|
||||
|
||||
CAF_PDM_InitField( &m_showCurves, "IsActive", true, "Show Curves" );
|
||||
m_showCurves.uiCapability()->setUiHidden( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimHistogramCurveCollection::isCurvesVisible()
|
||||
{
|
||||
return m_showCurves();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::loadDataAndUpdate( bool updateParentPlot )
|
||||
{
|
||||
for ( RimHistogramCurve* curve : m_curves )
|
||||
{
|
||||
curve->loadDataAndUpdate( false );
|
||||
curve->updatePlotAxis();
|
||||
}
|
||||
|
||||
if ( updateParentPlot )
|
||||
{
|
||||
auto parentPlot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
parentPlot->updateAll();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::onChildrenUpdated( caf::PdmChildArrayFieldHandle* childArray,
|
||||
std::vector<caf::PdmObjectHandle*>& updatedObjects )
|
||||
{
|
||||
if ( childArray == &m_curves )
|
||||
{
|
||||
for ( auto obj : updatedObjects )
|
||||
{
|
||||
// Must use firstAncestorOrThisOfType, since we need to update the curve appearance if the object is a child of a
|
||||
// RimHistogramCurve. This is the case when modifying curve appearance.
|
||||
if ( auto curve = obj->firstAncestorOrThisOfType<RimHistogramCurve>() )
|
||||
{
|
||||
curve->updateCurveAppearance();
|
||||
}
|
||||
}
|
||||
|
||||
auto parentPlot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
parentPlot->plotWidget()->scheduleReplot();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::setParentPlotAndReplot( RiuPlotWidget* plot )
|
||||
{
|
||||
setParentPlotNoReplot( plot );
|
||||
|
||||
if ( plot ) plot->replot();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::setParentPlotNoReplot( RiuPlotWidget* plot )
|
||||
{
|
||||
for ( RimHistogramCurve* curve : m_curves )
|
||||
{
|
||||
curve->setParentPlotNoReplot( plot );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::detachPlotCurves()
|
||||
{
|
||||
for ( RimHistogramCurve* curve : m_curves )
|
||||
{
|
||||
curve->detach();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::reattachPlotCurves()
|
||||
{
|
||||
for ( RimHistogramCurve* curve : m_curves )
|
||||
{
|
||||
if ( curve->isChecked() ) curve->reattach();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::addCurve( RimHistogramCurve* curve )
|
||||
{
|
||||
if ( curve )
|
||||
{
|
||||
m_curves.push_back( curve );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::insertCurve( RimHistogramCurve* curve, size_t index )
|
||||
{
|
||||
if ( index >= m_curves.size() )
|
||||
{
|
||||
m_curves.push_back( curve );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curves.insert( index, curve );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::deleteCurve( RimHistogramCurve* curve )
|
||||
{
|
||||
removeCurve( curve );
|
||||
if ( curve )
|
||||
{
|
||||
delete curve;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::removeCurve( RimHistogramCurve* curve )
|
||||
{
|
||||
if ( curve )
|
||||
{
|
||||
m_curves.removeChild( curve );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimHistogramCurve*> RimHistogramCurveCollection::curves() const
|
||||
{
|
||||
return m_curves.childrenByType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::deleteAllCurves()
|
||||
{
|
||||
m_curves.deleteChildren();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::updateCaseNameHasChanged()
|
||||
{
|
||||
for ( RimHistogramCurve* curve : m_curves )
|
||||
{
|
||||
curve->updateCurveNameNoLegendUpdate();
|
||||
curve->updateConnectedEditors();
|
||||
}
|
||||
|
||||
auto parentPlot = firstAncestorOrThisOfTypeAsserted<RimHistogramPlot>();
|
||||
|
||||
parentPlot->updatePlotTitle();
|
||||
if ( parentPlot->plotWidget() ) parentPlot->plotWidget()->updateLegend();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::setCurrentHistogramCurve( RimHistogramCurve* curve )
|
||||
{
|
||||
m_currentHistogramCurve = curve;
|
||||
|
||||
updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<caf::PdmFieldHandle*> RimHistogramCurveCollection::fieldsToShowInToolbar()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
||||
{
|
||||
if ( changedField == &m_showCurves )
|
||||
{
|
||||
loadDataAndUpdate( true );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::onCurvesReordered( const SignalEmitter* emitter )
|
||||
{
|
||||
updateCurveOrder();
|
||||
curvesChanged.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::onChildDeleted( caf::PdmChildArrayFieldHandle* childArray,
|
||||
std::vector<caf::PdmObjectHandle*>& referringObjects )
|
||||
{
|
||||
curvesChanged.send();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
caf::PdmFieldHandle* RimHistogramCurveCollection::objectToggleField()
|
||||
{
|
||||
return &m_showCurves;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute )
|
||||
{
|
||||
caf::PdmUiTreeViewEditorAttribute* myAttr = dynamic_cast<caf::PdmUiTreeViewEditorAttribute*>( attribute );
|
||||
if ( myAttr && m_currentHistogramCurve.notNull() )
|
||||
{
|
||||
myAttr->currentObject = m_currentHistogramCurve.p();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramCurveCollection::updateCurveOrder()
|
||||
{
|
||||
detachPlotCurves();
|
||||
reattachPlotCurves();
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025- 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 "cafPdmChildArrayField.h"
|
||||
#include "cafPdmChildField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
class RimHistogramPlot;
|
||||
class RimHistogramCurve;
|
||||
class RiuPlotWidget;
|
||||
class RiuPlotCurve;
|
||||
class QKeyEvent;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimHistogramCurveCollection : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
private:
|
||||
caf::Signal<> curvesChanged;
|
||||
|
||||
public:
|
||||
RimHistogramCurveCollection();
|
||||
|
||||
bool isCurvesVisible();
|
||||
|
||||
std::vector<RimHistogramCurve*> curves() const;
|
||||
|
||||
void loadDataAndUpdate( bool updateParentPlot );
|
||||
|
||||
void updateCurveOrder();
|
||||
|
||||
private:
|
||||
void setParentPlotAndReplot( RiuPlotWidget* plot );
|
||||
void setParentPlotNoReplot( RiuPlotWidget* plot );
|
||||
void detachPlotCurves();
|
||||
void reattachPlotCurves();
|
||||
|
||||
void addCurve( RimHistogramCurve* curve );
|
||||
void insertCurve( RimHistogramCurve* curve, size_t index );
|
||||
void deleteCurve( RimHistogramCurve* curve );
|
||||
void removeCurve( RimHistogramCurve* curve );
|
||||
|
||||
void deleteAllCurves();
|
||||
void updateCaseNameHasChanged();
|
||||
|
||||
void setCurrentHistogramCurve( RimHistogramCurve* curve );
|
||||
|
||||
std::vector<caf::PdmFieldHandle*> fieldsToShowInToolbar();
|
||||
|
||||
private:
|
||||
caf::PdmFieldHandle* objectToggleField() override;
|
||||
void defineObjectEditorAttribute( QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override;
|
||||
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
void onCurvesReordered( const SignalEmitter* emitter );
|
||||
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
|
||||
|
||||
void onChildrenUpdated( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& updatedObjects ) override;
|
||||
|
||||
private:
|
||||
friend class RimHistogramPlot;
|
||||
|
||||
caf::PdmField<bool> m_showCurves;
|
||||
caf::PdmChildArrayField<RimHistogramCurve*> m_curves;
|
||||
|
||||
caf::PdmPointer<RimHistogramCurve> m_currentHistogramCurve;
|
||||
};
|
||||
@@ -0,0 +1,99 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimHistogramDataSource.h"
|
||||
|
||||
CAF_PDM_XML_ABSTRACT_SOURCE_INIT( RimHistogramDataSource, "HistogramDataSource" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramDataSource::RimHistogramDataSource()
|
||||
: dataSourceChanged( this )
|
||||
{
|
||||
CAF_PDM_InitObject( "Histogram Data Source", );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramDataSource::~RimHistogramDataSource()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimHistogramDataSource::computeHistogramBins( double min, double max, int numBins, RimHistogramPlot::GraphType graphType )
|
||||
{
|
||||
const double binSize = ( max - min ) / numBins;
|
||||
|
||||
std::vector<double> values;
|
||||
for ( int i = 0; i < numBins; i++ )
|
||||
{
|
||||
if ( graphType == RimHistogramPlot::GraphType::BAR_GRAPH )
|
||||
{
|
||||
values.push_back( min + binSize * i );
|
||||
values.push_back( min + binSize * ( i + 1 ) );
|
||||
}
|
||||
else if ( graphType == RimHistogramPlot::GraphType::LINE_GRAPH )
|
||||
{
|
||||
double centerOfBin = min + binSize * i + binSize / 2.0;
|
||||
values.push_back( centerOfBin );
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimHistogramDataSource::computeHistogramFrequencies( const std::vector<size_t>& values,
|
||||
RimHistogramPlot::GraphType graphType,
|
||||
RimHistogramPlot::FrequencyType frequencyType )
|
||||
{
|
||||
std::vector<double> valuesAsDouble( values.begin(), values.end() );
|
||||
return computeHistogramFrequencies( valuesAsDouble, graphType, frequencyType );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<double> RimHistogramDataSource::computeHistogramFrequencies( const std::vector<double>& values,
|
||||
RimHistogramPlot::GraphType graphType,
|
||||
RimHistogramPlot::FrequencyType frequencyType )
|
||||
{
|
||||
double sumElements = 0.0;
|
||||
for ( double value : values )
|
||||
sumElements += value;
|
||||
|
||||
std::vector<double> frequencies;
|
||||
for ( double frequency : values )
|
||||
{
|
||||
double value = frequency;
|
||||
if ( frequencyType == RimHistogramPlot::FrequencyType::RELATIVE_FREQUENCY ) value /= sumElements;
|
||||
if ( frequencyType == RimHistogramPlot::FrequencyType::RELATIVE_FREQUENCY_PERCENT ) value = value / sumElements * 100.0;
|
||||
|
||||
frequencies.push_back( value );
|
||||
if ( graphType == RimHistogramPlot::GraphType::BAR_GRAPH )
|
||||
{
|
||||
frequencies.push_back( value );
|
||||
}
|
||||
}
|
||||
return frequencies;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimHistogramPlot.h"
|
||||
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafSignal.h"
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimHistogramDataSource : public caf::PdmObject
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimHistogramDataSource();
|
||||
~RimHistogramDataSource() override;
|
||||
|
||||
caf::Signal<> dataSourceChanged;
|
||||
|
||||
virtual std::string unitNameX() const = 0;
|
||||
virtual std::string unitNameY() const = 0;
|
||||
|
||||
virtual std::vector<double> valuesX( RimHistogramPlot::GraphType graphType ) const = 0;
|
||||
virtual std::vector<double> valuesY( RimHistogramPlot::GraphType graphType, RimHistogramPlot::FrequencyType frequencyType ) const = 0;
|
||||
|
||||
virtual std::string name() const = 0;
|
||||
|
||||
static std::vector<double> computeHistogramBins( double min, double max, int numBins, RimHistogramPlot::GraphType graphType );
|
||||
static std::vector<double> computeHistogramFrequencies( const std::vector<size_t>& values,
|
||||
RimHistogramPlot::GraphType graphType,
|
||||
RimHistogramPlot::FrequencyType frequencyType );
|
||||
static std::vector<double> computeHistogramFrequencies( const std::vector<double>& values,
|
||||
RimHistogramPlot::GraphType graphType,
|
||||
RimHistogramPlot::FrequencyType frequencyType );
|
||||
};
|
||||
@@ -0,0 +1,614 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimHistogramMultiPlot.h"
|
||||
|
||||
#include "RiaNumericalTools.h"
|
||||
#include "RiaPlotDefines.h"
|
||||
|
||||
#include "RimEnsembleCurveSet.h"
|
||||
#include "RimHistogramPlot.h"
|
||||
#include "RimMainPlotCollection.h"
|
||||
#include "RimMultiPlotCollection.h"
|
||||
#include "RimPlotAxisProperties.h"
|
||||
|
||||
#include "RiuPlotMainWindowTools.h"
|
||||
#include "RiuQwtPlotWidget.h"
|
||||
|
||||
#include "cafPdmUiCheckBoxEditor.h"
|
||||
#include "cafPdmUiPushButtonEditor.h"
|
||||
#include "cafPdmUiTreeOrdering.h"
|
||||
|
||||
#include "qwt_scale_engine.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimHistogramMultiPlot, "MultiHistogramPlot" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramMultiPlot::RimHistogramMultiPlot()
|
||||
: duplicatePlot( this )
|
||||
{
|
||||
CAF_PDM_InitObject( "Multi Histogram Plot", ":/HistogramPlotLight16x16.png" );
|
||||
setDeletable( true );
|
||||
|
||||
CAF_PDM_InitField( &m_autoPlotTitle, "AutoPlotTitle", true, "Auto Plot Title" );
|
||||
CAF_PDM_InitField( &m_autoSubPlotTitle, "AutoSubPlotTitle", true, "Auto Sub Plot Title" );
|
||||
|
||||
CAF_PDM_InitField( &m_createPlotDuplicate, "DuplicatePlot", false, "", "", "Duplicate Plot" );
|
||||
caf::PdmUiPushButtonEditor::configureEditorLabelHidden( &m_createPlotDuplicate );
|
||||
m_createPlotDuplicate.uiCapability()->setUiIconFromResourceString( ":/Copy.svg" );
|
||||
|
||||
CAF_PDM_InitField( &m_disableWheelZoom, "DisableWheelZoom", true, "", "", "Disable Mouse Wheel Zooming in Multi Histogram Plot" );
|
||||
caf::PdmUiPushButtonEditor::configureEditorLabelHidden( &m_disableWheelZoom );
|
||||
m_disableWheelZoom.uiCapability()->setUiIconFromResourceString( ":/DisableZoom.png" );
|
||||
|
||||
CAF_PDM_InitField( &m_autoAdjustAppearance, "AutoAdjustAppearance", true, "Auto Plot Settings" );
|
||||
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_autoAdjustAppearance );
|
||||
CAF_PDM_InitField( &m_allow3DSelectionLink, "Allow3DSelectionLink", true, "Allow Well Selection from 3D View" );
|
||||
caf::PdmUiNativeCheckBoxEditor::configureFieldForEditor( &m_allow3DSelectionLink );
|
||||
|
||||
CAF_PDM_InitField( &m_hidePlotsWithValuesBelow, "HidePlotsWithValuesBelow", false, "" );
|
||||
caf::PdmUiPushButtonEditor::configureEditorLabelHidden( &m_hidePlotsWithValuesBelow );
|
||||
|
||||
setBottomMargin( 40 );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramMultiPlot::~RimHistogramMultiPlot()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::addPlot( RimPlot* plot )
|
||||
{
|
||||
auto* sumPlot = dynamic_cast<RimHistogramPlot*>( plot );
|
||||
CVF_ASSERT( sumPlot != nullptr );
|
||||
if ( sumPlot )
|
||||
{
|
||||
RimMultiPlot::addPlot( plot );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::insertPlot( RimPlot* plot, size_t index )
|
||||
{
|
||||
auto* sumPlot = dynamic_cast<RimHistogramPlot*>( plot );
|
||||
CVF_ASSERT( sumPlot != nullptr );
|
||||
if ( sumPlot )
|
||||
{
|
||||
sumPlot->curvesChanged.connect( this, &RimHistogramMultiPlot::onSubPlotChanged );
|
||||
sumPlot->titleChanged.connect( this, &RimHistogramMultiPlot::onSubPlotChanged );
|
||||
sumPlot->autoTitleChanged.connect( this, &RimHistogramMultiPlot::onSubPlotAutoTitleChanged );
|
||||
|
||||
RimMultiPlot::insertPlot( plot, index );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::removePlot( RimPlot* plot )
|
||||
{
|
||||
auto* sumPlot = dynamic_cast<RimHistogramPlot*>( plot );
|
||||
CVF_ASSERT( sumPlot != nullptr );
|
||||
if ( sumPlot )
|
||||
{
|
||||
RimMultiPlot::removePlot( plot );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::removePlotNoUpdate( RimPlot* plot )
|
||||
{
|
||||
auto* sumPlot = dynamic_cast<RimHistogramPlot*>( plot );
|
||||
CVF_ASSERT( sumPlot != nullptr );
|
||||
if ( sumPlot )
|
||||
{
|
||||
RimMultiPlot::removePlotNoUpdate( plot );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::updateAfterPlotRemove()
|
||||
{
|
||||
onPlotAdditionOrRemoval();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
auto titlesGroup = uiOrdering.addNewGroup( "Main Plot Settings" );
|
||||
titlesGroup->setCollapsedByDefault();
|
||||
|
||||
// If a checkbox is first in the group, it is not responding to mouse clicks. Set title as first element.
|
||||
// https://github.com/OPM/ResInsight/issues/10321
|
||||
titlesGroup->add( &m_plotWindowTitle );
|
||||
titlesGroup->add( &m_autoPlotTitle );
|
||||
titlesGroup->add( &m_showPlotWindowTitle );
|
||||
titlesGroup->add( &m_titleFontSize );
|
||||
|
||||
auto subPlotSettingsGroup = uiOrdering.addNewGroup( "Sub Plot Settings" );
|
||||
subPlotSettingsGroup->setCollapsedByDefault();
|
||||
subPlotSettingsGroup->add( &m_autoSubPlotTitle );
|
||||
subPlotSettingsGroup->add( &m_showIndividualPlotTitles );
|
||||
subPlotSettingsGroup->add( &m_subTitleFontSize );
|
||||
|
||||
auto legendsGroup = uiOrdering.addNewGroup( "Legends" );
|
||||
legendsGroup->setCollapsedByDefault();
|
||||
legendsGroup->add( &m_showPlotLegends );
|
||||
legendsGroup->add( &m_plotLegendsHorizontal );
|
||||
legendsGroup->add( &m_legendPosition );
|
||||
legendsGroup->add( &m_legendFontSize );
|
||||
|
||||
uiOrdering.skipRemainingFields( true );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue )
|
||||
{
|
||||
if ( changedField == &m_autoPlotTitle || changedField == &m_autoSubPlotTitle )
|
||||
{
|
||||
onLoadDataAndUpdate();
|
||||
updateLayout();
|
||||
}
|
||||
else if ( changedField == &m_hidePlotsWithValuesBelow )
|
||||
{
|
||||
m_hidePlotsWithValuesBelow = false;
|
||||
updatePlotVisibility();
|
||||
}
|
||||
else if ( changedField == &m_createPlotDuplicate )
|
||||
{
|
||||
m_createPlotDuplicate = false;
|
||||
duplicate();
|
||||
}
|
||||
else if ( changedField == &m_autoAdjustAppearance )
|
||||
{
|
||||
analyzePlotsAndAdjustAppearanceSettings();
|
||||
}
|
||||
else if ( changedField == &m_plotWindowTitle )
|
||||
{
|
||||
// If the user has changed the plot title, disable the auto plot title
|
||||
// Workaround for https://github.com/OPM/ResInsight/issues/9681
|
||||
|
||||
m_autoPlotTitle = false;
|
||||
}
|
||||
|
||||
RimMultiPlot::fieldChangedByUi( changedField, oldValue, newValue );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::updatePlotTitles()
|
||||
{
|
||||
if ( m_autoPlotTitle )
|
||||
{
|
||||
auto collection = RimMainPlotCollection::current()->histogramMultiPlotCollection();
|
||||
|
||||
size_t index = 0;
|
||||
for ( auto p : collection->histogramMultiPlots() )
|
||||
{
|
||||
index++;
|
||||
if ( p == this ) break;
|
||||
}
|
||||
|
||||
QString title = QString( "Plot %1" ).arg( index );
|
||||
|
||||
setMultiPlotTitle( title );
|
||||
}
|
||||
|
||||
if ( !m_viewer.isNull() ) m_viewer->scheduleTitleUpdate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::setAutoPlotTitle( bool enable )
|
||||
{
|
||||
m_autoPlotTitle = enable;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::setAutoSubPlotTitle( bool enable )
|
||||
{
|
||||
m_autoSubPlotTitle = enable;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimHistogramPlot*> RimHistogramMultiPlot::histogramPlots() const
|
||||
{
|
||||
std::vector<RimHistogramPlot*> typedPlots;
|
||||
|
||||
for ( auto plot : plots() )
|
||||
{
|
||||
auto histogramPlot = dynamic_cast<RimHistogramPlot*>( plot );
|
||||
if ( histogramPlot ) typedPlots.push_back( histogramPlot );
|
||||
}
|
||||
|
||||
return typedPlots;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimHistogramPlot*> RimHistogramMultiPlot::visibleHistogramPlots() const
|
||||
{
|
||||
std::vector<RimHistogramPlot*> visiblePlots;
|
||||
|
||||
for ( auto plot : histogramPlots() )
|
||||
{
|
||||
if ( plot->showWindow() ) visiblePlots.push_back( plot );
|
||||
}
|
||||
|
||||
return visiblePlots;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimHistogramMultiPlot::handleGlobalKeyEvent( QKeyEvent* keyEvent )
|
||||
{
|
||||
if ( isMouseCursorInsidePlot() )
|
||||
{
|
||||
if ( keyEvent->key() == Qt::Key_PageUp )
|
||||
{
|
||||
m_viewer->goToPrevPage();
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( keyEvent->key() == Qt::Key_PageDown )
|
||||
{
|
||||
m_viewer->goToNextPage();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimHistogramMultiPlot::handleGlobalWheelEvent( QWheelEvent* wheelEvent )
|
||||
{
|
||||
if ( m_disableWheelZoom )
|
||||
{
|
||||
if ( isMouseCursorInsidePlot() )
|
||||
{
|
||||
if ( wheelEvent->angleDelta().y() > 0 )
|
||||
{
|
||||
m_viewer->goToPrevPage();
|
||||
}
|
||||
else if ( wheelEvent->angleDelta().y() < 0 )
|
||||
{
|
||||
m_viewer->goToNextPage();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::initAfterRead()
|
||||
{
|
||||
RimMultiPlot::initAfterRead();
|
||||
|
||||
for ( auto plot : histogramPlots() )
|
||||
{
|
||||
plot->curvesChanged.connect( this, &RimHistogramMultiPlot::onSubPlotChanged );
|
||||
plot->titleChanged.connect( this, &RimHistogramMultiPlot::onSubPlotChanged );
|
||||
plot->autoTitleChanged.connect( this, &RimHistogramMultiPlot::onSubPlotAutoTitleChanged );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::onLoadDataAndUpdate()
|
||||
{
|
||||
RimMultiPlot::onLoadDataAndUpdate();
|
||||
updatePlotTitles();
|
||||
|
||||
for ( auto p : histogramPlots() )
|
||||
{
|
||||
p->updateAxes();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::zoomAll()
|
||||
{
|
||||
// Reset zoom to make sure the complete range for min/max is available
|
||||
RimMultiPlot::zoomAll();
|
||||
|
||||
syncAxisRanges();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::syncAxisRanges()
|
||||
{
|
||||
// Reset zoom for axes with no custom range set to make sure the complete range for min/max is available
|
||||
|
||||
for ( auto p : histogramPlots() )
|
||||
{
|
||||
for ( auto ax : p->plotAxes( RimPlotAxisProperties::Orientation::ANY ) )
|
||||
{
|
||||
ax->setAutoZoomIfNoCustomRangeIsSet();
|
||||
}
|
||||
}
|
||||
updateZoom();
|
||||
|
||||
std::map<QString, std::pair<double, double>> axisRanges;
|
||||
|
||||
// gather current min/max values for each category (axis label)
|
||||
for ( auto plot : histogramPlots() )
|
||||
{
|
||||
for ( auto axis : plot->plotAxes( RimPlotAxisProperties::Orientation::ANY ) )
|
||||
{
|
||||
double minVal = axis->visibleRangeMin();
|
||||
double maxVal = axis->visibleRangeMax();
|
||||
if ( axis->isAxisInverted() ) std::swap( minVal, maxVal );
|
||||
|
||||
auto key = axis->objectName();
|
||||
if ( axisRanges.count( key ) == 0 )
|
||||
{
|
||||
axisRanges[key] = std::make_pair( minVal, maxVal );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& [currentMin, currentMax] = axisRanges[key];
|
||||
axisRanges[key] = std::make_pair( std::min( currentMin, minVal ), std::max( currentMax, maxVal ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set all plots to use the global min/max values for each category
|
||||
for ( auto plot : histogramPlots() )
|
||||
{
|
||||
for ( auto axis : plot->plotAxes( RimPlotAxisProperties::Orientation::ANY ) )
|
||||
{
|
||||
auto [minVal, maxVal] = axisRanges[axis->objectName()];
|
||||
if ( axis->isAxisInverted() ) std::swap( minVal, maxVal );
|
||||
axis->setAutoZoom( false );
|
||||
|
||||
axis->setAutoValueVisibleRangeMin( minVal );
|
||||
axis->setAutoValueVisibleRangeMax( maxVal );
|
||||
}
|
||||
|
||||
plot->updateAxes();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::updatePlotVisibility()
|
||||
{
|
||||
for ( auto plot : histogramPlots() )
|
||||
{
|
||||
plot->setShowWindow( true );
|
||||
}
|
||||
|
||||
updateLayout();
|
||||
|
||||
if ( !m_viewer.isNull() ) m_viewer->scheduleUpdate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::duplicate()
|
||||
{
|
||||
duplicatePlot.send( this );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::analyzePlotsAndAdjustAppearanceSettings()
|
||||
{
|
||||
if ( m_autoAdjustAppearance )
|
||||
{
|
||||
// Required to sync axis ranges before computing the auto scale
|
||||
syncAxisRanges();
|
||||
|
||||
const bool notifyFieldChanged = false;
|
||||
|
||||
for ( auto p : histogramPlots() )
|
||||
{
|
||||
for ( auto* axisProp : p->plotAxes( RimPlotAxisProperties::Orientation::ANY ) )
|
||||
{
|
||||
auto tickMarkCount = ( rowsPerPage() == 1 ) ? RimPlotAxisProperties::LegendTickmarkCount::TICKMARK_DEFAULT
|
||||
: RimPlotAxisProperties::LegendTickmarkCount::TICKMARK_FEW;
|
||||
|
||||
axisProp->setAutoValueForMajorTickmarkCount( tickMarkCount, notifyFieldChanged );
|
||||
|
||||
axisProp->computeAndSetAutoValueForScaleFactor();
|
||||
|
||||
auto [row, col] = gridLayoutInfoForSubPlot( p );
|
||||
|
||||
bool isFirstColumn = ( col == 0 );
|
||||
axisProp->setShowUnitText( isFirstColumn );
|
||||
axisProp->setShowDescription( isFirstColumn );
|
||||
}
|
||||
|
||||
p->updateAxes();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( auto p : histogramPlots() )
|
||||
{
|
||||
for ( auto* axisProp : p->plotAxes( RimPlotAxisProperties::Orientation::ANY ) )
|
||||
{
|
||||
axisProp->computeAndSetAutoValueForScaleFactor();
|
||||
axisProp->setShowUnitText( true );
|
||||
axisProp->setShowDescription( true );
|
||||
}
|
||||
|
||||
p->updateAxes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::makeSureIsVisible( RimHistogramPlot* histogramPlot )
|
||||
{
|
||||
if ( histogramPlot->plotWidget() && !m_viewer.isNull() ) m_viewer->scrollToPlot( histogramPlot->plotWidget() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<int, int> RimHistogramMultiPlot::gridLayoutInfoForSubPlot( RimHistogramPlot* histogramPlot ) const
|
||||
{
|
||||
auto it = m_gridLayoutInfo.find( histogramPlot );
|
||||
if ( it != m_gridLayoutInfo.end() ) return it->second;
|
||||
|
||||
return { -1, -1 };
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::setLayoutInfo( RimHistogramPlot* histogramPlot, int row, int col )
|
||||
{
|
||||
m_gridLayoutInfo[histogramPlot] = std::make_pair( row, col );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::clearLayoutInfo()
|
||||
{
|
||||
m_gridLayoutInfo.clear();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::onSubPlotChanged( const caf::SignalEmitter* emitter )
|
||||
{
|
||||
updatePlotTitles();
|
||||
applyPlotWindowTitleToWidgets();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::onSubPlotAutoTitleChanged( const caf::SignalEmitter* emitter, bool isEnabled )
|
||||
{
|
||||
m_autoSubPlotTitle = isEnabled;
|
||||
|
||||
loadDataAndUpdate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<double, double> RimHistogramMultiPlot::adjustedMinMax( const RimPlotAxisProperties* axis, double min, double max ) const
|
||||
{
|
||||
if ( !axis->isLogarithmicScaleEnabled() )
|
||||
{
|
||||
int maxMajorTickIntervalCount = RimPlotAxisProperties::tickmarkCountFromEnum( axis->majorTickmarkCount() );
|
||||
double stepSize = 0.0;
|
||||
QwtLinearScaleEngine scaleEngine;
|
||||
|
||||
// Do not adjust minimum value, as we usually want to keep zero unchanged
|
||||
double adjustedMin = min;
|
||||
|
||||
// Adjust the max value to get some space between the top of the plot and the top of the curve
|
||||
double adjustedMax = max * 1.05;
|
||||
|
||||
scaleEngine.autoScale( maxMajorTickIntervalCount, adjustedMin, adjustedMax, stepSize );
|
||||
|
||||
return { adjustedMin, adjustedMax };
|
||||
}
|
||||
|
||||
auto adjustedMin = RiaNumericalTools::roundToClosestPowerOfTenFloor( min );
|
||||
auto adjustedMax = RiaNumericalTools::roundToClosestPowerOfTenCeil( max );
|
||||
|
||||
return { adjustedMin, adjustedMax };
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QWidget* RimHistogramMultiPlot::createViewWidget( QWidget* mainWindowParent )
|
||||
{
|
||||
if ( m_viewer.isNull() )
|
||||
{
|
||||
m_viewer = new RiuMultiPlotBook( this, mainWindowParent );
|
||||
}
|
||||
recreatePlotWidgets();
|
||||
|
||||
return m_viewer;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::onPlotAdditionOrRemoval()
|
||||
{
|
||||
m_disableWheelZoom = ( histogramPlots().size() > 1 );
|
||||
|
||||
RimMultiPlot::onPlotAdditionOrRemoval();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlot::keepVisiblePageAfterUpdate( bool keepPage )
|
||||
{
|
||||
if ( !m_viewer ) return;
|
||||
|
||||
if ( keepPage ) m_viewer->keepCurrentPageAfterUpdate();
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimMultiPlot.h"
|
||||
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmUiItem.h"
|
||||
#include "cafSignal.h"
|
||||
|
||||
#include <QList>
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimHistogramPlot;
|
||||
class RimPlotAxisProperties;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimHistogramMultiPlot : public RimMultiPlot
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
caf::Signal<RimHistogramMultiPlot*> duplicatePlot;
|
||||
|
||||
public:
|
||||
RimHistogramMultiPlot();
|
||||
~RimHistogramMultiPlot() override;
|
||||
|
||||
void setLayoutInfo( RimHistogramPlot* histogramPlot, int row, int col );
|
||||
void clearLayoutInfo();
|
||||
|
||||
void setAutoPlotTitle( bool enable );
|
||||
void setAutoSubPlotTitle( bool enable );
|
||||
|
||||
void addPlot( RimPlot* plot ) override;
|
||||
void insertPlot( RimPlot* plot, size_t index ) override;
|
||||
void removePlot( RimPlot* plot ) override;
|
||||
|
||||
void removePlotNoUpdate( RimPlot* plot ) override;
|
||||
void updateAfterPlotRemove() override;
|
||||
void updatePlotTitles() override;
|
||||
|
||||
void syncAxisRanges();
|
||||
|
||||
void histogramPlotItemInfos( QList<caf::PdmOptionItemInfo>* optionInfos ) const;
|
||||
|
||||
std::vector<RimHistogramPlot*> histogramPlots() const;
|
||||
std::vector<RimHistogramPlot*> visibleHistogramPlots() const;
|
||||
|
||||
void makeSureIsVisible( RimHistogramPlot* plot );
|
||||
|
||||
void setSubPlotAxesLinked( bool enable );
|
||||
bool isSubPlotAxesLinked() const;
|
||||
|
||||
std::pair<int, int> gridLayoutInfoForSubPlot( RimHistogramPlot* histogramPlot ) const;
|
||||
|
||||
void zoomAll() override;
|
||||
|
||||
void setDefaultRangeAggregationSteppingDimension();
|
||||
void analyzePlotsAndAdjustAppearanceSettings();
|
||||
|
||||
void keepVisiblePageAfterUpdate( bool keepPage );
|
||||
|
||||
protected:
|
||||
bool handleGlobalKeyEvent( QKeyEvent* keyEvent ) override;
|
||||
bool handleGlobalWheelEvent( QWheelEvent* wheelEvent ) override;
|
||||
|
||||
void initAfterRead() override;
|
||||
void onLoadDataAndUpdate() override;
|
||||
|
||||
QWidget* createViewWidget( QWidget* mainWindowParent ) override;
|
||||
|
||||
void onPlotAdditionOrRemoval() override;
|
||||
|
||||
private:
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
|
||||
void computeAggregatedAxisRange();
|
||||
void updateSourceStepper();
|
||||
|
||||
void updatePlotVisibility();
|
||||
|
||||
void duplicate();
|
||||
|
||||
void appendSubPlotByStepping( int direction );
|
||||
void appendCurveByStepping( int direction );
|
||||
|
||||
void onSubPlotChanged( const caf::SignalEmitter* emitter );
|
||||
void onSubPlotAutoTitleChanged( const caf::SignalEmitter* emitter, bool isEnabled );
|
||||
|
||||
std::pair<double, double> adjustedMinMax( const RimPlotAxisProperties* axis, double min, double max ) const;
|
||||
|
||||
private:
|
||||
caf::PdmField<bool> m_autoPlotTitle;
|
||||
caf::PdmField<bool> m_autoSubPlotTitle;
|
||||
caf::PdmField<bool> m_disableWheelZoom;
|
||||
caf::PdmField<bool> m_createPlotDuplicate;
|
||||
caf::PdmField<bool> m_autoAdjustAppearance;
|
||||
caf::PdmField<bool> m_allow3DSelectionLink;
|
||||
|
||||
caf::PdmField<bool> m_hidePlotsWithValuesBelow;
|
||||
caf::PdmField<double> m_plotFilterYAxisThreshold;
|
||||
|
||||
std::map<RimHistogramPlot*, std::pair<int, int>> m_gridLayoutInfo;
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RimHistogramMultiPlotCollection.h"
|
||||
|
||||
#include "RimHistogramMultiPlot.h"
|
||||
#include "RimMainPlotCollection.h"
|
||||
#include "RimProject.h"
|
||||
|
||||
#include "cafCmdFeatureMenuBuilder.h"
|
||||
|
||||
CAF_PDM_SOURCE_INIT( RimHistogramMultiPlotCollection, "RimHistogramMultiPlotCollection" );
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramMultiPlotCollection::RimHistogramMultiPlotCollection()
|
||||
{
|
||||
CAF_PDM_InitObject( "Histogram Plots", ":/MultiPlot16x16.png" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_histogramMultiPlots, "HistogramMultiPlots", "Histogram Plots" );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramMultiPlotCollection* RimHistogramMultiPlotCollection::instance()
|
||||
{
|
||||
return RimProject::current()->mainPlotCollection()->histogramMultiPlotCollection();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramMultiPlot* RimHistogramMultiPlotCollection::appendHistogramMultiPlot()
|
||||
{
|
||||
auto* histogramMultiPlot = new RimHistogramMultiPlot();
|
||||
m_histogramMultiPlots.push_back( histogramMultiPlot );
|
||||
return histogramMultiPlot;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimHistogramMultiPlot*> RimHistogramMultiPlotCollection::histogramMultiPlots() const
|
||||
{
|
||||
return m_histogramMultiPlots.childrenByType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlotCollection::loadDataAndUpdateAllPlots()
|
||||
{
|
||||
for ( auto plot : histogramMultiPlots() )
|
||||
{
|
||||
plot->loadDataAndUpdateAllPlots();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlotCollection::deleteAllPlots()
|
||||
{
|
||||
m_histogramMultiPlots.deleteChildren();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RimHistogramMultiPlotCollection::plotCount() const
|
||||
{
|
||||
return m_histogramMultiPlots.size();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimHistogramMultiPlotCollection::appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const
|
||||
{
|
||||
menuBuilder.addCmdFeature( "RicNewHistogramMultiPlotFeature", "New Histogram Plot" );
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "cafPdmChildArrayField.h"
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
class RimHistogramMultiPlot;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimHistogramMultiPlotCollection : public caf::PdmObject, public RimPlotCollection
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimHistogramMultiPlotCollection();
|
||||
|
||||
static RimHistogramMultiPlotCollection* instance();
|
||||
|
||||
RimHistogramMultiPlot* appendHistogramMultiPlot();
|
||||
|
||||
std::vector<RimHistogramMultiPlot*> histogramMultiPlots() const;
|
||||
|
||||
void loadDataAndUpdateAllPlots() override;
|
||||
size_t plotCount() const override;
|
||||
void deleteAllPlots() override;
|
||||
|
||||
private:
|
||||
void appendMenuItems( caf::CmdFeatureMenuBuilder& menuBuilder ) const override;
|
||||
|
||||
private:
|
||||
caf::PdmChildArrayField<RimHistogramMultiPlot*> m_histogramMultiPlots;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,236 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2025 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 "RiaDateTimeDefines.h"
|
||||
#include "RiaPlotDefines.h"
|
||||
|
||||
#include "RimPlot.h"
|
||||
#include "RimPlotAxisProperties.h"
|
||||
|
||||
#include "RiuPlotWidget.h"
|
||||
|
||||
#include "cafPdmChildArrayField.h"
|
||||
#include "cafPdmObjectHandle.h"
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class RimHistogramCurve;
|
||||
class RimHistogramCurveCollection;
|
||||
class RimPlotAxisPropertiesInterface;
|
||||
class RimPlotAxisProperties;
|
||||
class RimPlotTemplateFileItem;
|
||||
class RimStackablePlotCurve;
|
||||
|
||||
class PdmUiTreeOrdering;
|
||||
|
||||
class QwtInterval;
|
||||
class QwtPlotCurve;
|
||||
class QwtPlotTextLabel;
|
||||
|
||||
class QKeyEvent;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimHistogramPlot : public RimPlot
|
||||
{
|
||||
Q_OBJECT;
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
caf::Signal<> curvesChanged;
|
||||
caf::Signal<RimHistogramPlot*> axisChanged;
|
||||
caf::Signal<> titleChanged;
|
||||
caf::Signal<RimHistogramPlot*> axisChangedReloadRequired;
|
||||
caf::Signal<bool> autoTitleChanged;
|
||||
|
||||
public:
|
||||
enum class FrequencyType
|
||||
{
|
||||
ABSOLUTE_FREQUENCY,
|
||||
RELATIVE_FREQUENCY,
|
||||
RELATIVE_FREQUENCY_PERCENT
|
||||
};
|
||||
|
||||
enum class GraphType
|
||||
{
|
||||
BAR_GRAPH,
|
||||
LINE_GRAPH
|
||||
};
|
||||
|
||||
RimHistogramPlot();
|
||||
~RimHistogramPlot() override;
|
||||
|
||||
void setDescription( const QString& description );
|
||||
QString description() const override;
|
||||
|
||||
void enableAutoPlotTitle( bool enable );
|
||||
bool autoPlotTitle() const;
|
||||
|
||||
void addCurveNoUpdate( RimHistogramCurve* curve, bool autoAssignPlotAxis = true );
|
||||
|
||||
size_t curveCount() const;
|
||||
|
||||
void detachAllCurves() override;
|
||||
void reattachAllCurves() override;
|
||||
|
||||
void updateAxes() override;
|
||||
|
||||
bool isLogarithmicScaleEnabled( RiuPlotAxis plotAxis ) const;
|
||||
|
||||
bool isCurveHighlightSupported() const override;
|
||||
|
||||
QWidget* viewWidget() override;
|
||||
|
||||
QString asciiDataForPlotExport() const override;
|
||||
QString asciiDataForHistogramPlotExport( RiaDefines::DateTimePeriod resamplingPeriod, bool showTimeAsLongString ) const;
|
||||
|
||||
FrequencyType frequencyType() const;
|
||||
GraphType graphType() const;
|
||||
|
||||
void updatePlotTitle();
|
||||
|
||||
void updateCurveNames();
|
||||
|
||||
void copyMatchingAxisPropertiesFromOther( const RimHistogramPlot& sourceHistogramPlot );
|
||||
|
||||
void updateAll();
|
||||
void updateLegend() override;
|
||||
void setLegendPosition( RiuPlotWidget::Legend position );
|
||||
|
||||
void showPlotInfoLabel( bool show );
|
||||
void updatePlotInfoLabel();
|
||||
|
||||
void applyDefaultCurveAppearances();
|
||||
|
||||
void setNormalizationEnabled( bool enable );
|
||||
bool isNormalizationEnabled();
|
||||
|
||||
void setAutoScaleXEnabled( bool enabled ) override;
|
||||
void setAutoScaleYEnabled( bool enabled ) override;
|
||||
RiuPlotWidget* plotWidget() override;
|
||||
void zoomAll() override;
|
||||
void updatePlotWidgetFromAxisRanges() override;
|
||||
void updateAxisRangesFromPlotWidget() override;
|
||||
|
||||
void onAxisSelected( RiuPlotAxis axis, bool toggle ) override;
|
||||
|
||||
std::vector<RimPlotAxisProperties*> plotAxes( RimPlotAxisProperties::Orientation orientation ) const;
|
||||
|
||||
RimPlotAxisPropertiesInterface* axisPropertiesForPlotAxis( RiuPlotAxis plotAxis ) const;
|
||||
RimPlotAxisProperties* addNewAxisProperties( RiaDefines::PlotAxis, const QString& name );
|
||||
RimPlotAxisProperties* addNewAxisProperties( RiuPlotAxis plotAxis, const QString& name );
|
||||
|
||||
std::vector<RimPlotCurve*> visibleCurvesForLegend() override;
|
||||
|
||||
void scheduleReplotIfVisible();
|
||||
|
||||
public:
|
||||
// RimViewWindow overrides
|
||||
void deleteViewWidget() override;
|
||||
bool isDeletable() const override;
|
||||
|
||||
caf::PdmFieldHandle* userDescriptionField() override;
|
||||
|
||||
void zoomAllForMultiPlot() override;
|
||||
|
||||
private:
|
||||
RiuPlotWidget* doCreatePlotViewWidget( QWidget* mainWindowParent = nullptr ) override;
|
||||
|
||||
void doUpdateLayout() override;
|
||||
|
||||
void detachAllPlotItems();
|
||||
void deleteAllPlotCurves();
|
||||
|
||||
void onCurveCollectionChanged( const SignalEmitter* emitter );
|
||||
void onPlotItemSelected( std::shared_ptr<RiuPlotItem> plotItem, bool toggle, int sampleIndex ) override;
|
||||
|
||||
void connectCurveToPlot( RimHistogramCurve* curve, bool update, bool autoAssignPlotAxis );
|
||||
|
||||
protected:
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
void childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) override;
|
||||
void onChildDeleted( caf::PdmChildArrayFieldHandle* childArray, std::vector<caf::PdmObjectHandle*>& referringObjects ) override;
|
||||
|
||||
void defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
void onLoadDataAndUpdate() override;
|
||||
|
||||
QImage snapshotWindowContent() override;
|
||||
|
||||
private slots:
|
||||
void onPlotZoomed();
|
||||
void onUpdateCurveOrder();
|
||||
|
||||
private:
|
||||
void updateNumericalAxis( RiaDefines::PlotAxis plotAxis );
|
||||
void updateZoomForAxis( RimPlotAxisPropertiesInterface* axisProperties );
|
||||
void updateZoomForNumericalAxis( RimPlotAxisProperties* axisProperties );
|
||||
|
||||
void deletePlotCurvesAndPlotWidget();
|
||||
|
||||
void connectCurveSignals( RimStackablePlotCurve* curve );
|
||||
void disconnectCurveSignals( RimStackablePlotCurve* curve );
|
||||
|
||||
void curveDataChanged( const caf::SignalEmitter* emitter );
|
||||
void curveVisibilityChanged( const caf::SignalEmitter* emitter, bool visible );
|
||||
void curveAppearanceChanged( const caf::SignalEmitter* emitter );
|
||||
void curveStackingChanged( const caf::SignalEmitter* emitter, bool stacked );
|
||||
void curveStackingColorsChanged( const caf::SignalEmitter* emitter, bool stackWithPhaseColors );
|
||||
|
||||
void connectAxisSignals( RimPlotAxisProperties* axis );
|
||||
void axisSettingsChanged( const caf::SignalEmitter* emitter );
|
||||
void axisLogarithmicChanged( const caf::SignalEmitter* emitter, bool isLogarithmic );
|
||||
void axisPositionChanged( const caf::SignalEmitter* emitter,
|
||||
RimPlotAxisProperties* axisProperties,
|
||||
RiuPlotAxis oldPlotAxis,
|
||||
RiuPlotAxis newPlotAxis );
|
||||
|
||||
std::vector<RimPlotAxisPropertiesInterface*> allPlotAxes() const;
|
||||
|
||||
std::vector<RimHistogramCurve*> histogramCurves() const;
|
||||
std::vector<RimHistogramCurve*> visibleHistogramCurvesForAxis( RiuPlotAxis plotAxis ) const;
|
||||
|
||||
void assignPlotAxis( RimHistogramCurve* curve );
|
||||
|
||||
void updateStackedCurveData();
|
||||
|
||||
private:
|
||||
caf::PdmField<bool> m_normalizeCurveYValues;
|
||||
caf::PdmField<bool> m_useAutoPlotTitle;
|
||||
caf::PdmField<QString> m_description;
|
||||
caf::PdmField<QString> m_fallbackPlotName;
|
||||
|
||||
caf::PdmChildField<RimHistogramCurveCollection*> m_histogramCurveCollection;
|
||||
|
||||
caf::PdmChildArrayField<RimPlotAxisPropertiesInterface*> m_axisPropertiesArray;
|
||||
|
||||
caf::PdmField<caf::AppEnum<FrequencyType>> m_histogramFrequencyType;
|
||||
caf::PdmField<caf::AppEnum<GraphType>> m_graphType;
|
||||
|
||||
std::unique_ptr<RiuPlotWidget> m_histogramPlot;
|
||||
|
||||
bool m_isValid;
|
||||
RiuPlotWidget::Legend m_legendPosition;
|
||||
};
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "ContourMap/RimEclipseContourMapViewCollection.h"
|
||||
#include "Formations/RimFormationNames.h"
|
||||
#include "Formations/RimFormationNamesCollection.h"
|
||||
#include "Histogram/RimHistogramMultiPlot.h"
|
||||
#include "Histogram/RimHistogramPlot.h"
|
||||
#include "PlotTemplates/RimPlotTemplateFileItem.h"
|
||||
#include "PlotTemplates/RimPlotTemplateFolderItem.h"
|
||||
#include "Rim3dOverlayInfoConfig.h"
|
||||
@@ -992,6 +994,25 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
|
||||
menuBuilder << "RicSaveMultiPlotTemplateFeature";
|
||||
menuBuilder << "RicPasteSummaryMultiPlotFeature";
|
||||
}
|
||||
else if ( dynamic_cast<RimHistogramMultiPlot*>( firstUiItem ) )
|
||||
{
|
||||
menuBuilder << "RicNewDefaultHistogramPlotFeature";
|
||||
}
|
||||
else if ( dynamic_cast<RimHistogramPlot*>( firstUiItem ) )
|
||||
{
|
||||
menuBuilder.subMenuStart( "New Histogram Curve" );
|
||||
|
||||
// TODO: make an enum of these?
|
||||
std::vector<QString> curveTypes = { "Ensemble Parameter", "Grid Statistics", "Summary Vector" };
|
||||
|
||||
for ( const QString& curveType : curveTypes )
|
||||
{
|
||||
QString menuText = curveType;
|
||||
menuBuilder.addCmdFeatureWithUserData( "RicNewHistogramCurveFeature", menuText, QVariant( curveType ) );
|
||||
}
|
||||
|
||||
menuBuilder.subMenuEnd();
|
||||
}
|
||||
else if ( dynamic_cast<RimMultiPlot*>( firstUiItem ) )
|
||||
{
|
||||
menuBuilder << "RicSnapshotViewToPdfFeature";
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "Summary/RiaSummaryDefines.h"
|
||||
#include "Summary/RiaSummaryPlotTools.h"
|
||||
|
||||
#include "Histogram/RimHistogramMultiPlotCollection.h"
|
||||
#include "RimAbstractPlotCollection.h"
|
||||
#include "RimAnalysisPlotCollection.h"
|
||||
#include "RimCorrelationPlotCollection.h"
|
||||
@@ -109,6 +110,9 @@ RimMainPlotCollection::RimMainPlotCollection()
|
||||
CAF_PDM_InitFieldNoDefault( &m_stimPlanModelPlotCollection, "StimPlanModelPlotCollection", "" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_vfpPlotCollection, "VfpPlotCollection", "" );
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_histogramMultiPlotCollection, "HistogramMultiPlotCollection", "" );
|
||||
|
||||
#ifdef USE_QTCHARTS
|
||||
CAF_PDM_InitFieldNoDefault( &m_gridStatisticsPlotCollection, "GridStatisticsPlotCollection", "" );
|
||||
|
||||
@@ -129,6 +133,7 @@ RimMainPlotCollection::RimMainPlotCollection()
|
||||
m_correlationPlotCollection = new RimCorrelationPlotCollection;
|
||||
m_stimPlanModelPlotCollection = new RimStimPlanModelPlotCollection;
|
||||
m_vfpPlotCollection = new RimVfpPlotCollection();
|
||||
m_histogramMultiPlotCollection = new RimHistogramMultiPlotCollection();
|
||||
#ifdef USE_QTCHARTS
|
||||
m_gridStatisticsPlotCollection = new RimGridStatisticsPlotCollection;
|
||||
m_ensembleFractureStatisticsPlotCollection = new RimEnsembleFractureStatisticsPlotCollection;
|
||||
@@ -325,6 +330,14 @@ RimStimPlanModelPlotCollection* RimMainPlotCollection::stimPlanModelPlotCollecti
|
||||
return m_stimPlanModelPlotCollection();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimHistogramMultiPlotCollection* RimMainPlotCollection::histogramMultiPlotCollection() const
|
||||
{
|
||||
return m_histogramMultiPlotCollection();
|
||||
}
|
||||
|
||||
#ifdef USE_QTCHARTS
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
@@ -494,6 +507,7 @@ std::vector<RimPlotCollection*> RimMainPlotCollection::allPlotCollections() cons
|
||||
plotCollections.push_back( correlationPlotCollection() );
|
||||
plotCollections.push_back( saturationPressurePlotCollection() );
|
||||
plotCollections.push_back( multiPlotCollection() );
|
||||
plotCollections.push_back( histogramMultiPlotCollection() );
|
||||
|
||||
#ifdef USE_QTCHARTS
|
||||
plotCollections.push_back( gridStatisticsPlotCollection() );
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Histogram/RimHistogramMultiPlotCollection.h"
|
||||
#include "cafPdmChildField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
@@ -44,6 +45,7 @@ class RimSaturationPressurePlotCollection;
|
||||
class RimStimPlanModelPlotCollection;
|
||||
class RimVfpPlotCollection;
|
||||
class RimPlotCollection;
|
||||
class RimHistogramMultiPlotCollection;
|
||||
|
||||
#ifdef USE_QTCHARTS
|
||||
class RimGridStatisticsPlotCollection;
|
||||
@@ -77,6 +79,7 @@ public:
|
||||
RimMultiPlotCollection* multiPlotCollection() const;
|
||||
RimStimPlanModelPlotCollection* stimPlanModelPlotCollection() const;
|
||||
RimVfpPlotCollection* vfpPlotCollection() const;
|
||||
RimHistogramMultiPlotCollection* histogramMultiPlotCollection() const;
|
||||
|
||||
#ifdef USE_QTCHARTS
|
||||
RimGridStatisticsPlotCollection* gridStatisticsPlotCollection() const;
|
||||
@@ -121,6 +124,7 @@ private:
|
||||
caf::PdmChildField<RimMultiPlotCollection*> m_multiPlotCollection;
|
||||
caf::PdmChildField<RimStimPlanModelPlotCollection*> m_stimPlanModelPlotCollection;
|
||||
caf::PdmChildField<RimVfpPlotCollection*> m_vfpPlotCollection;
|
||||
caf::PdmChildField<RimHistogramMultiPlotCollection*> m_histogramMultiPlotCollection;
|
||||
#ifdef USE_QTCHARTS
|
||||
caf::PdmChildField<RimGridStatisticsPlotCollection*> m_gridStatisticsPlotCollection;
|
||||
caf::PdmChildField<RimEnsembleFractureStatisticsPlotCollection*> m_ensembleFractureStatisticsPlotCollection;
|
||||
|
||||
@@ -1007,6 +1007,9 @@ void RimPlotCurve::updateCurveAppearance()
|
||||
QColor fillColor = RiaColorTools::toQColor( m_curveAppearance->fillColor() );
|
||||
|
||||
fillColor = RiaColorTools::blendQColors( fillColor, QColor( Qt::white ), 3, 1 );
|
||||
|
||||
// TODO: this is a workaround. Create proper api for setting fill color transparency.
|
||||
fillColor.setAlphaF( 0.5 );
|
||||
QBrush fillBrush( fillColor, fillStyle() );
|
||||
m_plotCurve->setAppearance( m_curveAppearance->lineStyle(),
|
||||
m_curveAppearance->interpolation(),
|
||||
|
||||
@@ -1463,6 +1463,12 @@ void RimProject::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, Q
|
||||
{
|
||||
uiTreeOrdering.add( m_mainPlotCollection->vfpPlotCollection() );
|
||||
}
|
||||
|
||||
if ( m_mainPlotCollection->histogramMultiPlotCollection() )
|
||||
{
|
||||
uiTreeOrdering.add( m_mainPlotCollection->histogramMultiPlotCollection() );
|
||||
}
|
||||
|
||||
#ifdef USE_QTCHARTS
|
||||
if ( m_mainPlotCollection->gridStatisticsPlotCollection() || m_mainPlotCollection->ensembleFractureStatisticsPlotCollection() )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user