ResInsight/ApplicationLibCode/ProjectDataModel/WellLog/RimEnsembleWellLogCurveSet.cpp
Magne Sjaastad 5ec32f8613
Update text for curve names and plot titles when source data changes
* Update titles after dropping vectors into plot
* Do not replace _Name variables
* Make sure signals are wired when opening a project file
* Add auto name field and set default on
* Remove includes from header files
2022-12-09 08:46:36 +01:00

1318 lines
48 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2021- 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 "RimEnsembleWellLogCurveSet.h"
#include "RiaColorTools.h"
#include "RiaLogging.h"
#include "RiaOptionItemFactory.h"
#include "RiaResultNames.h"
#include "RimEnsembleCurveFilter.h"
#include "RimEnsembleCurveFilterCollection.h"
#include "RimEnsembleCurveSet.h"
#include "RimEnsembleStatistics.h"
#include "RimEnsembleWellLogStatistics.h"
#include "RimEnsembleWellLogStatisticsCurve.h"
#include "RimEnsembleWellLogs.h"
#include "RimEnsembleWellLogsCollection.h"
#include "RimFormationNames.h"
#include "RimFormationNamesCollection.h"
#include "RimMainPlotCollection.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimWellLogCurve.h"
#include "RimWellLogFile.h"
#include "RimWellLogFileChannel.h"
#include "RimWellLogFileCurve.h"
#include "RimWellLogPlot.h"
#include "RimWellLogTrack.h"
#include "RimWellPath.h"
#include "RigFormationNames.h"
#include "RigWellLogIndexDepthOffset.h"
#include "RiuAbstractLegendFrame.h"
#include "RiuDraggableOverlayFrame.h"
#include "RiuPlotMainWindow.h"
#include "RiuQwtPlotCurveDefines.h"
#include "RiuQwtPlotWidget.h"
#include "RiuQwtSymbol.h"
#include "RiuTextContentFrame.h"
#include "cafPdmObject.h"
#include "cafPdmUiItem.h"
#include "cafPdmUiTreeOrdering.h"
#include "cvfObject.h"
#include "qwt_plot.h"
#include "qwt_plot_curve.h"
#include "qwt_symbol.h"
#include <algorithm>
#include <vector>
//--------------------------------------------------------------------------------------------------
/// Internal functions
//--------------------------------------------------------------------------------------------------
int statisticsCurveSymbolSize( RiuPlotCurveSymbol::PointSymbolEnum symbol );
namespace caf
{
template <>
void AppEnum<RimEnsembleWellLogCurveSet::ColorMode>::setUp()
{
addItem( RimEnsembleWellLogCurveSet::ColorMode::SINGLE_COLOR, "SINGLE_COLOR", "Single Color" );
addItem( RimEnsembleWellLogCurveSet::ColorMode::COLOR_BY_ENSEMBLE_CURVE_SET,
"BY_ENSEMBLE_CURVE_SET",
"Color by Ensemble Curve Set" );
setDefault( RimEnsembleWellLogCurveSet::ColorMode::SINGLE_COLOR );
}
}; // namespace caf
CAF_PDM_SOURCE_INIT( RimEnsembleWellLogCurveSet, "RimEnsembleWellLogCurveSet" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEnsembleWellLogCurveSet::RimEnsembleWellLogCurveSet()
: filterChanged( this )
{
CAF_PDM_InitObject( "Ensemble Curve Set", ":/EnsembleCurveSet16x16.png" );
CAF_PDM_InitFieldNoDefault( &m_curves, "EnsembleCurveSet", "Ensemble Curve Set" );
m_curves.uiCapability()->setUiHidden( true );
m_curves.uiCapability()->setUiTreeChildrenHidden( false );
CAF_PDM_InitField( &m_showCurves, "IsActive", true, "Show Curves" );
m_showCurves.uiCapability()->setUiHidden( true );
CAF_PDM_InitFieldNoDefault( &m_ensembleWellLogs, "EnsembleWellLogs", "Ensemble Well Logs" );
m_ensembleWellLogs.uiCapability()->setUiTreeChildrenHidden( true );
CAF_PDM_InitField( &m_wellLogChannelName, "WellLogChannelName", QString( "None" ), "Well Log Channel Name" );
CAF_PDM_InitFieldNoDefault( &m_ensembleCurveSet, "FilterEnsembleCurveSet", "Filter by Ensemble Curve Set" );
CAF_PDM_InitFieldNoDefault( &m_depthEqualization, "DepthEqualization", "Depth Equalization" );
CAF_PDM_InitField( &m_colorMode, "ColorMode", caf::AppEnum<ColorMode>( ColorMode::SINGLE_COLOR ), "Coloring Mode" );
CAF_PDM_InitField( &m_color, "Color", RiaColorTools::textColor3f(), "Color" );
CAF_PDM_InitFieldNoDefault( &m_statistics, "Statistics", "Statistics" );
m_statistics = new RimEnsembleStatistics( this );
m_statistics.uiCapability()->setUiTreeHidden( true );
CAF_PDM_InitField( &m_userDefinedName, "UserDefinedName", QString( "Ensemble Curve Set" ), "Curve Set Name" );
CAF_PDM_InitFieldNoDefault( &m_autoGeneratedName, "AutoGeneratedName", "Curve Set Name" );
m_autoGeneratedName.registerGetMethod( this, &RimEnsembleWellLogCurveSet::createAutoName );
m_autoGeneratedName.uiCapability()->setUiReadOnly( true );
m_autoGeneratedName.xmlCapability()->disableIO();
CAF_PDM_InitField( &m_isUsingAutoName, "AutoName", true, "Auto Name" );
CAF_PDM_InitFieldNoDefault( &m_curveAppearance, "PlotCurveAppearance", "PlotCurveAppearance" );
m_curveAppearance = new RimPlotCurveAppearance;
m_curveAppearance.uiCapability()->setUiTreeHidden( true );
m_curveAppearance->setInterpolationVisible( false );
m_curveAppearance->setColorVisible( false );
m_curveAppearance->setFillOptionsVisible( false );
m_curveAppearance->setSymbol( RiuPlotCurveSymbol::PointSymbolEnum::SYMBOL_ELLIPSE );
m_curveAppearance->setSymbolSize( 5 );
m_curveAppearance->setLineStyle( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_NONE );
m_curveAppearance->setSymbolEdgeColor( cvf::Color3f::BLACK );
m_curveAppearance->appearanceChanged.connect( this, &RimEnsembleWellLogCurveSet::onEnsembleCurvesAppearanceChanged );
m_qwtPlotCurveForLegendText = new QwtPlotCurve;
m_qwtPlotCurveForLegendText->setLegendAttribute( QwtPlotCurve::LegendShowSymbol, true );
m_ensembleWellLogStatistics.reset( new RimEnsembleWellLogStatistics );
m_disableStatisticCurves = false;
m_isCurveSetFiltered = false;
setDeletable( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEnsembleWellLogCurveSet::~RimEnsembleWellLogCurveSet()
{
RimWellLogTrack* plotTrack = nullptr;
firstAncestorOrThisOfType( plotTrack );
if ( plotTrack && plotTrack->viewer() )
{
if ( m_legendOverlayFrame )
{
plotTrack->viewer()->removeOverlayFrame( m_legendOverlayFrame );
}
}
if ( m_legendOverlayFrame )
{
m_legendOverlayFrame->setParent( nullptr );
delete m_legendOverlayFrame;
}
if ( m_filterOverlayFrame )
{
m_filterOverlayFrame->setParent( nullptr );
delete m_filterOverlayFrame;
}
delete m_qwtPlotCurveForLegendText;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEnsembleWellLogCurveSet::isCurvesVisible()
{
return m_showCurves();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::setColor( cvf::Color3f color )
{
m_color = color;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::loadDataAndUpdate( bool updateParentPlot )
{
updateAllCurves();
updateFilterLegend();
updateAllTextInPlot();
if ( updateParentPlot )
{
RimWellLogTrack* parentPlot;
firstAncestorOrThisOfTypeAsserted( parentPlot );
parentPlot->viewer()->scheduleReplot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::setParentPlotNoReplot( RiuPlotWidget* plot )
{
for ( RimWellLogCurve* curve : m_curves )
{
curve->setParentPlotNoReplot( plot );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::detachPlotCurves()
{
for ( RimWellLogCurve* curve : m_curves )
{
curve->detach();
}
m_qwtPlotCurveForLegendText->detach();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::reattachPlotCurves()
{
for ( RimWellLogCurve* curve : m_curves )
{
curve->reattach();
}
m_qwtPlotCurveForLegendText->detach();
RimWellLogTrack* plot = nullptr;
firstAncestorOrThisOfType( plot );
if ( plot )
{
m_qwtPlotCurveForLegendText->attach( plot->viewer()->qwtPlot() );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimWellLogCurve*> RimEnsembleWellLogCurveSet::curves() const
{
return m_curves.ptrReferencedObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::deleteEnsembleCurves()
{
RimWellLogTrack* plotTrack = nullptr;
firstAncestorOrThisOfType( plotTrack );
CVF_ASSERT( plotTrack );
std::vector<size_t> curvesIndexesToDelete;
for ( size_t c = 0; c < m_curves.size(); c++ )
{
RimWellLogCurve* curve = m_curves[c];
if ( dynamic_cast<RimEnsembleWellLogStatisticsCurve*>( curve ) == nullptr )
{
plotTrack->removeCurve( m_curves[c] );
curvesIndexesToDelete.push_back( c );
}
}
while ( curvesIndexesToDelete.size() > 0 )
{
size_t currIndex = curvesIndexesToDelete.back();
m_curves.erase( currIndex );
curvesIndexesToDelete.pop_back();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::deleteStatisticsCurves()
{
RimWellLogTrack* plotTrack = nullptr;
firstAncestorOrThisOfType( plotTrack );
CVF_ASSERT( plotTrack );
std::vector<size_t> curvesIndexesToDelete;
for ( size_t c = 0; c < m_curves.size(); c++ )
{
RimWellLogCurve* curve = m_curves[c];
if ( dynamic_cast<RimEnsembleWellLogStatisticsCurve*>( curve ) != nullptr )
{
plotTrack->removeCurve( m_curves[c] );
curvesIndexesToDelete.push_back( c );
}
}
while ( curvesIndexesToDelete.size() > 0 )
{
size_t currIndex = curvesIndexesToDelete.back();
m_curves.erase( currIndex );
curvesIndexesToDelete.pop_back();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuDraggableOverlayFrame* RimEnsembleWellLogCurveSet::legendFrame() const
{
return m_legendOverlayFrame;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEnsembleWellLogCurveSet::ColorMode RimEnsembleWellLogCurveSet::colorMode() const
{
return m_colorMode();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::setColorMode( ColorMode mode )
{
m_colorMode = mode;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::onEnsembleCurvesAppearanceChanged( const caf::SignalEmitter* emitter )
{
loadDataAndUpdate( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::updateAllCurves()
{
RimEnsembleWellLogs* group = m_ensembleWellLogs;
if ( group )
{
std::vector<RimWellLogFile*> allWellLogFiles = group->wellLogFiles();
std::vector<RimWellLogFile*> filteredCases = filterEnsembleCases( allWellLogFiles );
m_isCurveSetFiltered = filteredCases.size() < allWellLogFiles.size();
updateEnsembleCurves( filteredCases );
updateStatisticsCurves( m_statistics->basedOnFilteredCases() ? filteredCases : allWellLogFiles );
}
filterChanged.send();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::updateEditors()
{
updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue )
{
RimWellLogPlot* plot = nullptr;
firstAncestorOrThisOfType( plot );
CVF_ASSERT( plot );
bool updateTextInPlot = false;
if ( changedField == &m_showCurves )
{
loadDataAndUpdate( true );
updateConnectedEditors();
RimWellLogPlot* summaryPlot = nullptr;
this->firstAncestorOrThisOfTypeAsserted( summaryPlot );
summaryPlot->updateConnectedEditors();
updateTextInPlot = true;
}
else if ( changedField == &m_ensembleWellLogs )
{
updateAllCurves();
updateTextInPlot = true;
}
else if ( changedField == &m_ensembleCurveSet )
{
connectEnsembleCurveSetFilterSignals();
updateAllCurves();
loadDataAndUpdate( true );
updateTextInPlot = true;
}
else if ( changedField == &m_wellLogChannelName )
{
updateAllCurves();
updateTextInPlot = true;
}
else if ( changedField == &m_depthEqualization )
{
updateAllCurves();
updateTextInPlot = true;
}
else if ( changedField == &m_color )
{
updateCurveColors();
updateTextInPlot = true;
}
else if ( changedField == &m_colorMode )
{
updateCurveColors();
updateTextInPlot = true;
}
else if ( changedField == &m_isUsingAutoName )
{
if ( !m_isUsingAutoName )
{
m_userDefinedName = createAutoName();
}
updateTextInPlot = true;
}
else if ( changedField == &m_userDefinedName )
{
updateTextInPlot = true;
}
if ( updateTextInPlot )
{
updateAllTextInPlot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &m_ensembleWellLogs );
uiOrdering.add( &m_wellLogChannelName );
uiOrdering.add( &m_ensembleCurveSet );
uiOrdering.add( &m_depthEqualization );
bool hasKLayerIndex = hasPropertyInFile( RiaResultNames::indexKResultName() );
m_depthEqualization.uiCapability()->setUiReadOnly( !hasKLayerIndex );
appendColorGroup( uiOrdering );
{
caf::PdmUiGroup* nameGroup = uiOrdering.addNewGroup( "Curve Name" );
nameGroup->setCollapsedByDefault();
nameGroup->add( &m_isUsingAutoName );
if ( m_isUsingAutoName )
{
nameGroup->add( &m_autoGeneratedName );
}
else
{
nameGroup->add( &m_userDefinedName );
}
}
caf::PdmUiGroup* statGroup = uiOrdering.addNewGroup( "Statistics" );
m_statistics->defineUiOrdering( uiConfigName, *statGroup );
caf::PdmUiGroup* curveAppearanceGroup = uiOrdering.addNewGroup( "Curve Appearance" );
QString configName = "AppearanceOrdering";
m_curveAppearance->uiOrdering( configName, *curveAppearanceGroup );
uiOrdering.skipRemainingFields( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::appendColorGroup( caf::PdmUiOrdering& uiOrdering )
{
caf::PdmUiGroup* colorsGroup = uiOrdering.addNewGroup( "Colors" );
colorsGroup->add( &m_colorMode );
if ( m_colorMode == ColorMode::SINGLE_COLOR )
{
colorsGroup->add( &m_color );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering,
QString uiConfigName /*= ""*/ )
{
uiTreeOrdering.skipRemainingChildren( true );
caf::IconProvider iconProvider = this->uiIconProvider();
if ( !iconProvider.valid() ) return;
this->setUiIcon( iconProvider );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimEnsembleWellLogCurveSet::userDescriptionField()
{
if ( m_isUsingAutoName )
{
return &m_autoGeneratedName;
}
else
{
return &m_userDefinedName;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::PdmFieldHandle* RimEnsembleWellLogCurveSet::objectToggleField()
{
return &m_showCurves;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo>
RimEnsembleWellLogCurveSet::calculateValueOptions( const caf::PdmFieldHandle* fieldNeedingOptions )
{
QList<caf::PdmOptionItemInfo> options;
if ( fieldNeedingOptions == &m_ensembleWellLogs )
{
RimProject* proj = RimProject::current();
std::vector<RimEnsembleWellLogs*> groups =
proj->activeOilField()->ensembleWellLogsCollection()->ensembleWellLogs();
for ( RimEnsembleWellLogs* ensemble : groups )
{
options.push_back( caf::PdmOptionItemInfo( ensemble->name(), ensemble ) );
}
options.push_front( caf::PdmOptionItemInfo( "None", nullptr ) );
}
else if ( fieldNeedingOptions == &m_wellLogChannelName )
{
if ( m_ensembleWellLogs )
{
std::set<QString> wellLogChannelNames;
for ( auto wellLogFile : m_ensembleWellLogs->wellLogFiles() )
{
std::vector<RimWellLogFileChannel*> fileLogs = wellLogFile->wellLogChannels();
for ( size_t i = 0; i < fileLogs.size(); i++ )
{
QString wellLogChannelName = fileLogs[i]->name();
wellLogChannelNames.insert( wellLogChannelName );
}
}
for ( auto wellLogChannelName : wellLogChannelNames )
{
options.push_back( caf::PdmOptionItemInfo( wellLogChannelName, wellLogChannelName ) );
}
}
if ( options.size() == 0 )
{
options.push_back( caf::PdmOptionItemInfo( "None", "None" ) );
}
}
else if ( fieldNeedingOptions == &m_ensembleCurveSet )
{
RiaOptionItemFactory::appendOptionItemsForEnsembleCurveSets( &options );
}
else if ( fieldNeedingOptions == &m_colorMode )
{
auto singleColorOption = caf::AppEnum<ColorMode>( ColorMode::SINGLE_COLOR );
options.push_back( caf::PdmOptionItemInfo( singleColorOption.uiText(), ColorMode::SINGLE_COLOR ) );
if ( m_ensembleWellLogs && m_ensembleCurveSet )
{
auto byEnsembleOption = caf::AppEnum<ColorMode>( ColorMode::COLOR_BY_ENSEMBLE_CURVE_SET );
options.push_back( caf::PdmOptionItemInfo( byEnsembleOption.uiText(), ColorMode::COLOR_BY_ENSEMBLE_CURVE_SET ) );
}
}
return options;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::updateFilterLegend()
{
RimWellLogTrack* plotTrack;
firstAncestorOrThisOfType( plotTrack );
if ( plotTrack && plotTrack->viewer() )
{
if ( m_ensembleCurveSet != nullptr && m_ensembleCurveSet->isFiltered() )
{
if ( !m_filterOverlayFrame )
{
m_filterOverlayFrame = new RiuDraggableOverlayFrame( plotTrack->viewer()->qwtPlot()->canvas(),
plotTrack->viewer()->overlayMargins() );
}
m_filterOverlayFrame->setContentFrame( m_ensembleCurveSet->curveFilters()->makeFilterDescriptionFrame() );
plotTrack->viewer()->addOverlayFrame( m_filterOverlayFrame );
}
else
{
if ( m_filterOverlayFrame )
{
plotTrack->viewer()->removeOverlayFrame( m_filterOverlayFrame );
}
}
plotTrack->viewer()->scheduleReplot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RimEnsembleWellLogCurveSet::findMatchingSummaryCase( RimWellLogFileCurve* wellLogCurve ) const
{
RimSummaryCaseCollection* summaryCaseCollection = m_ensembleCurveSet->summaryCaseCollection();
std::vector<RimSummaryCase*> sumCases = summaryCaseCollection->allSummaryCases();
for ( auto sumCase : sumCases )
{
if ( isSameRealization( sumCase, wellLogCurve->wellLogFile() ) )
{
return sumCase;
}
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::updateCurveColors()
{
if ( m_colorMode == ColorMode::COLOR_BY_ENSEMBLE_CURVE_SET )
{
if ( m_ensembleCurveSet != nullptr )
{
// Fint the curves to color (skip the statistics)
std::vector<RimWellLogCurve*> curvesToColor;
std::vector<RimSummaryCase*> summaryCases;
for ( auto& curve : m_curves )
{
// Statistics curves have separate color settings
if ( dynamic_cast<RimEnsembleWellLogStatisticsCurve*>( curve.p() ) == nullptr )
{
// Look for a matching summary case
RimSummaryCase* summaryCase =
findMatchingSummaryCase( dynamic_cast<RimWellLogFileCurve*>( curve.p() ) );
if ( summaryCase )
{
summaryCases.push_back( summaryCase );
curvesToColor.push_back( curve.p() );
}
}
}
// Get the colors
std::vector<cvf::Color3f> caseColors = m_ensembleCurveSet->generateColorsForCases( summaryCases );
// Apply the colors
if ( caseColors.size() != curvesToColor.size() ) return;
for ( size_t i = 0; i < curvesToColor.size(); i++ )
{
curvesToColor[i]->setColor( caseColors[i] );
curvesToColor[i]->updateCurveAppearance();
}
}
}
else if ( m_colorMode == ColorMode::SINGLE_COLOR )
{
for ( auto& curve : m_curves )
{
// Statistics curves have separate color settings
if ( dynamic_cast<RimEnsembleWellLogStatisticsCurve*>( curve.p() ) == nullptr )
{
curve->setColor( m_color );
curve->updateCurveAppearance();
}
}
}
RimWellLogTrack* plotTrack;
firstAncestorOrThisOfType( plotTrack );
if ( plotTrack && plotTrack->viewer() )
{
if ( m_colorMode != ColorMode::SINGLE_COLOR && m_ensembleCurveSet != nullptr &&
m_ensembleCurveSet->colorMode() != RimEnsembleCurveSet::ColorMode::SINGLE_COLOR )
{
if ( !m_legendOverlayFrame )
{
m_legendOverlayFrame = new RiuDraggableOverlayFrame( plotTrack->viewer()->getParentForOverlay(),
plotTrack->viewer()->overlayMargins() );
}
m_legendOverlayFrame->setContentFrame( m_ensembleCurveSet->legendConfig()->makeLegendFrame() );
plotTrack->viewer()->addOverlayFrame( m_legendOverlayFrame );
}
else
{
if ( m_legendOverlayFrame )
{
plotTrack->viewer()->removeOverlayFrame( m_legendOverlayFrame );
}
}
plotTrack->viewer()->scheduleReplot();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::updateEnsembleCurves( const std::vector<RimWellLogFile*>& sumCases )
{
RimWellLogTrack* plotTrack = nullptr;
firstAncestorOrThisOfType( plotTrack );
CVF_ASSERT( plotTrack );
RimWellLogPlot* wellLogPlot = nullptr;
firstAncestorOrThisOfType( wellLogPlot );
CVF_ASSERT( wellLogPlot );
deleteEnsembleCurves();
m_qwtPlotCurveForLegendText->detach();
deleteStatisticsCurves();
if ( m_statistics->hideEnsembleCurves() ) return;
std::shared_ptr<RigWellLogIndexDepthOffset> offsets;
cvf::ref<RigWellPathFormations> wellPathFormations;
if ( m_depthEqualization() == RimEnsembleWellLogStatistics::DepthEqualization::K_LAYER )
{
offsets = RimEnsembleWellLogStatistics::calculateIndexDepthOffset( sumCases );
wellPathFormations = createWellPathFormations( offsets );
}
m_qwtPlotCurveForLegendText->attach( plotTrack->viewer()->qwtPlot() );
QString wellLogChannelName = m_wellLogChannelName();
if ( plotTrack && wellLogChannelName != "None" )
{
if ( isCurvesVisible() )
{
bool isFirst = true;
for ( auto& wellLogFile : sumCases )
{
RimWellLogFileCurve* curve = new RimWellLogFileCurve;
curve->setUiTreeHidden( true );
curve->setUiTreeChildrenHidden( true );
plotTrack->addCurve( curve );
QString errorMessage;
if ( wellLogFile->readFile( &errorMessage ) )
{
RigWellLogFile* wellLogDataFile = wellLogFile->wellLogFileData();
CVF_ASSERT( wellLogDataFile );
if ( isFirst )
{
// Initialize plot with depth unit from the first log file
wellLogPlot->setDepthUnit( wellLogDataFile->depthUnit() );
isFirst = false;
}
}
else
{
RiaLogging::warning( errorMessage );
}
RimWellPath* wellPath = RimProject::current()->wellPathByName( wellLogFile->wellName() );
if ( wellPathFormations.notNull() ) wellPath->setFormationsGeometry( wellPathFormations );
curve->setWellPath( wellPath );
curve->setWellLogChannelName( wellLogChannelName );
curve->setWellLogFile( wellLogFile );
curve->setSymbol( m_curveAppearance->symbol() );
curve->setSymbolSize( m_curveAppearance->symbolSize() );
curve->setSymbolSkipDistance( m_curveAppearance->symbolSkipDistance() );
curve->setSymbolEdgeColor( m_curveAppearance->symbolEdgeColor() );
curve->setLineStyle( m_curveAppearance->lineStyle() );
curve->setLineThickness( m_curveAppearance->lineThickness() );
if ( offsets ) curve->setIndexDepthOffsets( offsets );
curve->loadDataAndUpdate( true );
curve->updateCurveVisibility();
curve->setShowInLegend( false );
m_curves.push_back( curve );
}
updateCurveColors();
setLogScaleFromSelectedResult( wellLogChannelName );
}
}
plotTrack->updateLegend();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::setLogScaleFromSelectedResult( const QString resVar )
{
if ( RiaResultNames::isLogarithmicResult( resVar ) )
{
RimWellLogTrack* track = nullptr;
this->firstAncestorOrThisOfType( track );
if ( track ) track->setLogarithmicScale( true );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEnsembleWellLogCurveSet::updateStatistics()
{
return updateStatistics( std::vector<RimWellLogFile*>() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEnsembleWellLogCurveSet::updateStatistics( const std::vector<RimWellLogFile*>& sumCases )
{
RimEnsembleWellLogs* ensembleWellLogs = m_ensembleWellLogs;
QString wellLogChannelName = m_wellLogChannelName();
if ( !isCurvesVisible() || m_disableStatisticCurves || !ensembleWellLogs || wellLogChannelName == "None" )
{
m_ensembleWellLogStatistics->clearData();
return false;
}
// Calculate
std::vector<RimWellLogFile*> wellLogFiles = sumCases;
if ( wellLogFiles.empty() )
{
if ( m_statistics->basedOnFilteredCases() )
wellLogFiles = filterEnsembleCases( ensembleWellLogs->wellLogFiles() );
else
wellLogFiles = ensembleWellLogs->wellLogFiles();
}
m_ensembleWellLogStatistics->calculate( wellLogFiles, wellLogChannelName, m_depthEqualization() );
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::updateStatisticsCurves( const std::vector<RimWellLogFile*>& sumCases )
{
deleteStatisticsCurves();
if ( !updateStatistics( sumCases ) ) return;
RimWellLogPlot* plot = nullptr;
firstAncestorOrThisOfType( plot );
CVF_ASSERT( plot );
std::vector<RimEnsembleWellLogStatistics::StatisticsType> statisticsTypes;
if ( m_statistics->isActive() )
{
if ( m_statistics->showP10Curve() && m_ensembleWellLogStatistics->hasP10Data() )
statisticsTypes.push_back( RimEnsembleWellLogStatistics::StatisticsType::P10 );
if ( m_statistics->showP50Curve() && m_ensembleWellLogStatistics->hasP50Data() )
statisticsTypes.push_back( RimEnsembleWellLogStatistics::StatisticsType::P50 );
if ( m_statistics->showP90Curve() && m_ensembleWellLogStatistics->hasP90Data() )
statisticsTypes.push_back( RimEnsembleWellLogStatistics::StatisticsType::P90 );
if ( m_statistics->showMeanCurve() && m_ensembleWellLogStatistics->hasMeanData() )
statisticsTypes.push_back( RimEnsembleWellLogStatistics::StatisticsType::MEAN );
}
auto statisticsCurveSymbolFromStatistics = []( RimEnsembleWellLogStatistics::StatisticsType statisticsType ) {
if ( statisticsType == RimEnsembleWellLogStatistics::StatisticsType::P10 )
return RiuPlotCurveSymbol::SYMBOL_TRIANGLE;
if ( statisticsType == RimEnsembleWellLogStatistics::StatisticsType::P90 )
return RiuPlotCurveSymbol::SYMBOL_DOWN_TRIANGLE;
if ( statisticsType == RimEnsembleWellLogStatistics::StatisticsType::P50 )
return RiuPlotCurveSymbol::SYMBOL_DIAMOND;
return RiuPlotCurveSymbol::SYMBOL_ELLIPSE;
};
RimWellLogTrack* plotTrack = nullptr;
firstAncestorOrThisOfType( plotTrack );
CVF_ASSERT( plotTrack );
for ( auto statisticsType : statisticsTypes )
{
auto curve = new RimEnsembleWellLogStatisticsCurve();
curve->setUiTreeHidden( true );
curve->setUiTreeChildrenHidden( true );
curve->setEnsembleWellLogCurveSet( this );
curve->setStatisticsType( statisticsType );
m_curves.push_back( curve );
curve->setColor( m_statistics->color() );
auto symbol = statisticsCurveSymbolFromStatistics( statisticsType );
curve->setSymbol( symbol );
curve->setSymbolSize( statisticsCurveSymbolSize( symbol ) );
curve->setSymbolSkipDistance( 150 );
if ( m_statistics->showCurveLabels() )
{
curve->setSymbolLabel( caf::AppEnum<RimEnsembleWellLogStatistics::StatisticsType>::uiText( statisticsType ) );
}
curve->setLineStyle( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_SOLID );
plotTrack->addCurve( curve );
curve->updateCurveVisibility();
curve->loadDataAndUpdate( false );
}
updateCurveColors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::updateStatisticsCurves()
{
updateStatisticsCurves( std::vector<RimWellLogFile*>() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::showCurves( bool show )
{
m_showCurves = show;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimEnsembleWellLogStatistics::DepthEqualization RimEnsembleWellLogCurveSet::depthEqualization() const
{
return m_depthEqualization();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::setDepthEqualization( RimEnsembleWellLogStatistics::DepthEqualization depthEqualization )
{
m_depthEqualization = depthEqualization;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::setFilterByEnsembleCurveSet( RimEnsembleCurveSet* ensembleCurveSet )
{
m_ensembleCurveSet = ensembleCurveSet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::updateAllTextInPlot()
{
RimWellLogTrack* plotTrack = nullptr;
firstAncestorOrThisOfType( plotTrack );
CVF_ASSERT( plotTrack );
plotTrack->viewer()->setPlotTitle( name() );
updateEnsembleLegendItem();
plotTrack->updateLegend();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimWellLogFile*>
RimEnsembleWellLogCurveSet::filterEnsembleCases( const std::vector<RimWellLogFile*>& wellLogFiles )
{
std::vector<RimWellLogFile*> filteredCases;
if ( m_ensembleCurveSet != nullptr && m_statistics->basedOnFilteredCases() )
{
// Get the summary cases from the related ensemble summary curve set.
RimSummaryCaseCollection* summaryCaseCollection = m_ensembleCurveSet->summaryCaseCollection();
//
std::vector<RimSummaryCase*> sumCases =
m_ensembleCurveSet->filterEnsembleCases( summaryCaseCollection->allSummaryCases() );
for ( auto sumCase : sumCases )
{
for ( auto wellLogFile : wellLogFiles )
{
if ( isSameRealization( sumCase, wellLogFile ) )
{
filteredCases.push_back( wellLogFile );
}
}
}
}
else
{
filteredCases = wellLogFiles;
}
return filteredCases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEnsembleWellLogCurveSet::isSameRealization( RimSummaryCase* summaryCase, RimWellLogFile* wellLogFile ) const
{
QString wellLogFileName = wellLogFile->fileName();
//
if ( summaryCase->hasCaseRealizationParameters() )
{
// TODO: make less naive..
int realizationNumber = summaryCase->caseRealizationParameters()->realizationNumber();
QString summaryCaseFileName = summaryCase->summaryHeaderFilename();
if ( wellLogFileName.contains( QString( "realization-%1" ).arg( realizationNumber ) ) )
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::disableStatisticCurves()
{
m_disableStatisticCurves = true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEnsembleWellLogCurveSet::isFiltered() const
{
return m_isCurveSetFiltered;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEnsembleWellLogCurveSet::hasP10Data() const
{
return m_ensembleWellLogStatistics->hasP10Data();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEnsembleWellLogCurveSet::hasP50Data() const
{
return m_ensembleWellLogStatistics->hasP50Data();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEnsembleWellLogCurveSet::hasP90Data() const
{
return m_ensembleWellLogStatistics->hasP90Data();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEnsembleWellLogCurveSet::hasMeanData() const
{
return m_ensembleWellLogStatistics->hasMeanData();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const RimEnsembleWellLogStatistics* RimEnsembleWellLogCurveSet::ensembleWellLogStatistics() const
{
return m_ensembleWellLogStatistics.get();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::updateEnsembleLegendItem()
{
m_qwtPlotCurveForLegendText->setTitle( name() );
{
QwtSymbol* symbol = nullptr;
if ( m_colorMode == ColorMode::SINGLE_COLOR )
{
symbol = new QwtSymbol( QwtSymbol::HLine );
QColor curveColor( m_color.value().rByte(), m_color.value().gByte(), m_color.value().bByte() );
QPen curvePen( curveColor );
curvePen.setWidth( 2 );
symbol->setPen( curvePen );
symbol->setSize( 6, 6 );
}
else if ( m_colorMode == ColorMode::COLOR_BY_ENSEMBLE_CURVE_SET )
{
QPixmap p = QPixmap( ":/Legend.png" );
symbol = new QwtSymbol;
symbol->setPixmap( p );
symbol->setSize( 8, 8 );
}
m_qwtPlotCurveForLegendText->setSymbol( symbol );
}
bool showLegendItem = isCurvesVisible();
m_qwtPlotCurveForLegendText->setItemAttribute( QwtPlotItem::Legend, showLegendItem );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimEnsembleWellLogCurveSet::name() const
{
QString curveSetName;
if ( m_isUsingAutoName )
{
curveSetName = m_autoGeneratedName();
}
else
{
curveSetName += m_userDefinedName();
}
return curveSetName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimEnsembleWellLogCurveSet::createAutoName() const
{
QStringList nameParts;
if ( m_ensembleWellLogs() )
{
nameParts.append( m_ensembleWellLogs->name() );
nameParts.append( m_wellLogChannelName() );
}
if ( !nameParts.isEmpty() )
return nameParts.join( " - " );
else
return "Ensemble Well Log Curve Set";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::connectEnsembleCurveSetFilterSignals()
{
if ( m_ensembleCurveSet() )
{
m_ensembleCurveSet()->filterChanged.connect( this, &RimEnsembleWellLogCurveSet::onFilterSourceChanged );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::onFilterSourceChanged( const caf::SignalEmitter* emitter )
{
if ( m_ensembleCurveSet() ) loadDataAndUpdate( true );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::initAfterRead()
{
connectEnsembleCurveSetFilterSignals();
// Hide the ensemble and statistics curves in the project tree on reload
for ( auto c : m_curves() )
{
c->setUiTreeHidden( true );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::setEnsembleWellLogs( RimEnsembleWellLogs* ensembleWellLogs )
{
m_ensembleWellLogs = ensembleWellLogs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimEnsembleWellLogCurveSet::setWellLogChannelName( const QString& wellLogChannelName )
{
m_wellLogChannelName = wellLogChannelName;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::ref<RigWellPathFormations>
RimEnsembleWellLogCurveSet::createWellPathFormations( std::shared_ptr<RigWellLogIndexDepthOffset> offsets )
{
RimFormationNamesCollection* formationNamesCollection =
RimProject::current()->activeOilField()->formationNamesCollection.v();
if ( !formationNamesCollection ) return nullptr;
if ( formationNamesCollection->formationNamesList().empty() ) return nullptr;
RimFormationNames* rimFormationNames = formationNamesCollection->formationNamesList()[0];
if ( !rimFormationNames ) return nullptr;
RigFormationNames* formationNames = rimFormationNames->formationNamesData();
if ( !formationNames ) return nullptr;
std::vector<RigWellPathFormation> wellPathFormationItems;
for ( int kLayer : offsets->sortedIndexes() )
{
RigWellPathFormation wellPathFormation;
wellPathFormation.mdTop = offsets->getTopMd( kLayer );
wellPathFormation.mdBase = offsets->getBottomMd( kLayer );
wellPathFormation.formationName = formationNames->formationNameFromKLayerIdx( kLayer - 1 );
wellPathFormationItems.push_back( wellPathFormation );
}
QString unusedFilePath = "";
cvf::ref<RigWellPathFormations> wellPathFormations =
new RigWellPathFormations( wellPathFormationItems, unusedFilePath, "Ensemble formation" );
return wellPathFormations;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RimEnsembleWellLogCurveSet::hasPropertyInFile( const QString& property ) const
{
RimEnsembleWellLogs* group = m_ensembleWellLogs;
if ( !group ) return false;
std::vector<RimWellLogFile*> allWellLogFiles = group->wellLogFiles();
for ( auto& wellLogFile : allWellLogFiles )
{
QString errorMessage;
if ( !wellLogFile->readFile( &errorMessage ) ) return false;
RigWellLogFile* wellLogDataFile = wellLogFile->wellLogFileData();
CVF_ASSERT( wellLogDataFile );
std::vector<double> values = wellLogDataFile->values( RiaResultNames::indexKResultName() );
if ( values.empty() ) return false;
}
return true;
}