///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RiuPvtPlotPanel.h" #include "RiuDockedQwtPlot.h" #include "RiuGuiTheme.h" #include "RiuPvtPlotUpdater.h" #include "RiaEclipseUnitTools.h" #include "RigFlowDiagSolverInterface.h" #include "cvfAssert.h" #include "cvfMath.h" #include "qwt_legend.h" #include "qwt_picker_machine.h" #include "qwt_plot.h" #include "qwt_plot_curve.h" #include "qwt_plot_grid.h" #include "qwt_plot_layout.h" #include "qwt_plot_marker.h" #include "qwt_plot_picker.h" #include "qwt_symbol.h" #include "qwt_text.h" #include #include #include #include #include //================================================================================================== // // // //================================================================================================== class PvtQwtPlot : public RiuDockedQwtPlot { public: PvtQwtPlot( QWidget* parent ) : RiuDockedQwtPlot( parent ) { } QSize sizeHint() const override { return QSize( 100, 100 ); } QSize minimumSizeHint() const override { return QSize( 0, 0 ); } }; //================================================================================================== // // // //================================================================================================== class RiuPvtQwtPicker : public QwtPicker { public: RiuPvtQwtPicker( QwtPlot* plot, RiuPvtTrackerTextProvider* trackerTextProvider ) : QwtPicker( QwtPicker::NoRubberBand, QwtPicker::AlwaysOn, plot->canvas() ) , m_trackerTextProvider( trackerTextProvider ) { setStateMachine( new QwtPickerTrackerMachine ); } QwtText trackerText( const QPoint& ) const override { QwtText text( m_trackerTextProvider->trackerText() ); text.setRenderFlags( Qt::AlignLeft ); return text; } private: const RiuPvtTrackerTextProvider* m_trackerTextProvider; }; //================================================================================================== /// /// \class RiuPvtPlotWidget /// /// /// //================================================================================================== //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuPvtPlotWidget::RiuPvtPlotWidget( RiuPvtPlotPanel* parent ) : QWidget( parent ) , m_trackerPlotMarker( nullptr ) { m_qwtPlot = new PvtQwtPlot( this ); m_qwtPlot->setProperty( "qss-class", "PvtPlot" ); setPlotDefaults( m_qwtPlot ); applyFontSizes( false ); QHBoxLayout* layout = new QHBoxLayout(); layout->addWidget( m_qwtPlot ); layout->setSpacing( 0 ); layout->setContentsMargins( 0, 0, 0, 0 ); setLayout( layout ); m_qwtPicker = new RiuPvtQwtPicker( m_qwtPlot, this ); RiuGuiTheme::styleQwtItem( m_qwtPicker ); connect( m_qwtPicker, SIGNAL( activated( bool ) ), this, SLOT( slotPickerActivated( bool ) ) ); connect( m_qwtPicker, SIGNAL( moved( const QPoint& ) ), this, SLOT( slotPickerPointChanged( const QPoint& ) ) ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPvtPlotWidget::setPlotDefaults( QwtPlot* plot ) { plot->setAutoFillBackground( true ); QFrame* canvasFrame = dynamic_cast( plot->canvas() ); if ( canvasFrame ) { canvasFrame->setFrameShape( QFrame::NoFrame ); } // Grid { QwtPlotGrid* grid = new QwtPlotGrid; grid->attach( plot ); RiuGuiTheme::styleQwtItem( grid ); } // Axis number font { QFont axisFont = plot->axisFont( QwtAxis::XBottom ); axisFont.setPointSize( 8 ); plot->setAxisFont( QwtAxis::XBottom, axisFont ); plot->setAxisFont( QwtAxis::YLeft, axisFont ); } // Axis title font { QwtText axisTitle = plot->axisTitle( QwtAxis::XBottom ); QFont axisTitleFont = axisTitle.font(); axisTitleFont.setPointSize( 8 ); axisTitleFont.setBold( false ); axisTitle.setFont( axisTitleFont ); axisTitle.setRenderFlags( Qt::AlignRight ); plot->setAxisTitle( QwtAxis::XBottom, axisTitle ); plot->setAxisTitle( QwtAxis::YLeft, axisTitle ); } // Title font { QwtText plotTitle = plot->title(); QFont titleFont = plotTitle.font(); titleFont.setPointSize( 12 ); plotTitle.setFont( titleFont ); plot->setTitle( plotTitle ); } plot->setAxisMaxMinor( QwtAxis::XBottom, 2 ); plot->setAxisMaxMinor( QwtAxis::YLeft, 3 ); plot->plotLayout()->setAlignCanvasToScales( true ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPvtPlotWidget::plotCurves( RiaDefines::EclipseUnitSystem unitSystem, const std::vector& curveArr, double pressure, double pointMarkerYValue, const QString& pointMarkerLabel, const QString& plotTitle, const QString& yAxisTitle ) { m_qwtPlot->detachItems( QwtPlotItem::Rtti_PlotCurve ); m_qwtPlot->detachItems( QwtPlotItem::Rtti_PlotMarker ); m_qwtCurveArr.clear(); m_pvtCurveArr.clear(); m_trackerPlotMarker = nullptr; // Construct an auxiliary curve that connects the first point in all the input curves as a visual aid // This should only be shown when the phase being plotted is oil // Will not be added to our array of qwt curves since we do not expect the user to interact with it { std::vector xVals; std::vector yVals; for ( size_t i = 0; i < curveArr.size(); i++ ) { const RigFlowDiagSolverInterface::PvtCurve& curve = curveArr[i]; if ( curve.phase == RigFlowDiagSolverInterface::PvtCurve::OIL && curve.pressureVals.size() > 0 && curve.yVals.size() > 0 ) { xVals.push_back( curve.pressureVals[0] ); yVals.push_back( curve.yVals[0] ); } } if ( xVals.size() > 1 ) { QwtPlotCurve* qwtCurve = new QwtPlotCurve( "Auxiliary" ); qwtCurve->setSamples( xVals.data(), yVals.data(), static_cast( xVals.size() ) ); qwtCurve->setStyle( QwtPlotCurve::Lines ); qwtCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true ); qwtCurve->attach( m_qwtPlot ); RiuGuiTheme::styleQwtItem( qwtCurve ); } } // Add the primary curves for ( size_t i = 0; i < curveArr.size(); i++ ) { const RigFlowDiagSolverInterface::PvtCurve& curve = curveArr[i]; QwtPlotCurve* qwtCurve = new QwtPlotCurve(); QwtSymbol* curveSymbol = new QwtSymbol( QwtSymbol::Ellipse ); CVF_ASSERT( curve.pressureVals.size() == curve.yVals.size() ); qwtCurve->setSamples( curve.pressureVals.data(), curve.yVals.data(), static_cast( curve.pressureVals.size() ) ); qwtCurve->setStyle( QwtPlotCurve::Lines ); if ( curve.phase == RigFlowDiagSolverInterface::PvtCurve::GAS ) { qwtCurve->setTitle( "Gas" ); } else if ( curve.phase == RigFlowDiagSolverInterface::PvtCurve::OIL ) { qwtCurve->setTitle( "Oil" ); } else { qwtCurve->setTitle( "Undefined" ); } qwtCurve->setRenderHint( QwtPlotItem::RenderAntialiased, true ); curveSymbol->setSize( 6, 6 ); curveSymbol->setBrush( Qt::NoBrush ); qwtCurve->setSymbol( curveSymbol ); qwtCurve->attach( m_qwtPlot ); RiuGuiTheme::styleQwtItem( qwtCurve ); m_qwtCurveArr.push_back( qwtCurve ); } m_pvtCurveArr = curveArr; CVF_ASSERT( m_pvtCurveArr.size() == m_qwtCurveArr.size() ); // Add vertical marker line to indicate cell pressure if ( pressure != HUGE_VAL ) { QwtPlotMarker* lineMarker = new QwtPlotMarker; QPen pen; pen.setStyle( Qt::DashLine ); lineMarker->setLinePen( pen ); lineMarker->setXValue( pressure ); lineMarker->setLineStyle( QwtPlotMarker::VLine ); lineMarker->setLabel( QString( "PRESSURE" ) ); lineMarker->setLabelAlignment( Qt::AlignTop | Qt::AlignRight ); lineMarker->setLabelOrientation( Qt::Vertical ); lineMarker->attach( m_qwtPlot ); RiuGuiTheme::styleQwtItem( lineMarker ); } // Then point marker if ( pressure != HUGE_VAL && pointMarkerYValue != HUGE_VAL ) { QwtPlotMarker* pointMarker = new QwtPlotMarker; pointMarker->setValue( pressure, pointMarkerYValue ); QwtSymbol* symbol = new QwtSymbol( QwtSymbol::Ellipse ); symbol->setSize( 13, 13 ); QPen pen; pen.setWidth( 2 ); symbol->setPen( pen ); symbol->setBrush( Qt::NoBrush ); pointMarker->setSymbol( symbol ); if ( !pointMarkerLabel.isEmpty() ) { QwtText text( pointMarkerLabel ); text.setRenderFlags( Qt::AlignLeft ); text.setColor( RiuGuiTheme::getColorByVariableName( "textColor" ) ); pointMarker->setLabel( text ); pointMarker->setLabelAlignment( Qt::AlignTop | Qt::AlignRight ); } pointMarker->attach( m_qwtPlot ); RiuGuiTheme::styleQwtItem( pointMarker ); } m_qwtPlot->setTitle( plotTitle ); m_qwtPlot->setAxisTitle( QwtAxis::XBottom, QString( "Pressure [%1]" ).arg( RiaEclipseUnitTools::unitStringPressure( unitSystem ) ) ); m_qwtPlot->setAxisTitle( QwtAxis::YLeft, yAxisTitle ); updateTrackerPlotMarkerAndLabelFromPicker(); m_qwtPlot->replot(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPvtPlotWidget::applyFontSizes( bool replot ) { m_qwtPlot->applyFontSizes( replot ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPvtPlotWidget::updateTrackerPlotMarkerAndLabelFromPicker() { bool hasValidSamplePoint = false; QPointF samplePoint; QString mixRatioText = ""; double mixRat = HUGE_VAL; if ( m_qwtPicker && m_qwtPicker->isActive() ) { const QPoint trackerPos = m_qwtPicker->trackerPosition(); int pointSampleIdx = -1; const QwtPlotCurve* closestQwtCurve = closestCurveSample( trackerPos, &pointSampleIdx ); if ( closestQwtCurve && pointSampleIdx >= 0 ) { samplePoint = closestQwtCurve->sample( pointSampleIdx ); hasValidSamplePoint = true; size_t curveIdx = indexOfQwtCurve( closestQwtCurve ); if ( curveIdx < m_pvtCurveArr.size() ) { const RigFlowDiagSolverInterface::PvtCurve& pvtCurve = m_pvtCurveArr[curveIdx]; if ( static_cast( pointSampleIdx ) < pvtCurve.mixRatVals.size() ) { mixRat = pvtCurve.mixRatVals[pointSampleIdx]; // The text is Rs or Rv depending on phase mixRatioText = ( pvtCurve.phase == RigFlowDiagSolverInterface::PvtCurve::GAS ) ? "Rv" : "Rs"; } } } } m_trackerLabel = ""; bool needsReplot = false; if ( hasValidSamplePoint ) { if ( !m_trackerPlotMarker ) { m_trackerPlotMarker = new QwtPlotMarker; m_trackerPlotMarker->setTitle( QString( "TrackedPoint" ) ); QwtSymbol* symbol = new QwtSymbol( QwtSymbol::Ellipse ); symbol->setSize( 13, 13 ); symbol->setBrush( Qt::NoBrush ); m_trackerPlotMarker->setSymbol( symbol ); m_trackerPlotMarker->attach( m_qwtPlot ); RiuGuiTheme::styleQwtItem( m_trackerPlotMarker ); needsReplot = true; } if ( m_trackerPlotMarker->value() != samplePoint ) { m_trackerPlotMarker->setValue( samplePoint ); needsReplot = true; } m_trackerLabel = QString( "%1 (%2)" ).arg( samplePoint.y() ).arg( samplePoint.x() ); if ( mixRat != HUGE_VAL ) { m_trackerLabel += QString( "\n%1 = %2" ).arg( mixRatioText ).arg( mixRat ); } } else { if ( m_trackerPlotMarker ) { m_trackerPlotMarker->detach(); delete m_trackerPlotMarker; m_trackerPlotMarker = nullptr; needsReplot = true; } } if ( needsReplot ) { m_qwtPlot->replot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const QwtPlotCurve* RiuPvtPlotWidget::closestCurveSample( const QPoint& cursorPosition, int* closestSampleIndex ) const { // Construct a set containing the relevant qwt curves to consider // These are the curves that have a corresponding Pvt source curve std::set relevantQwtCurvesSet( m_qwtCurveArr.begin(), m_qwtCurveArr.end() ); if ( closestSampleIndex ) *closestSampleIndex = -1; const QwtPlotCurve* closestCurve = nullptr; double distMin = HUGE_VAL; int closestPointSampleIndex = -1; const QwtPlotItemList& itemList = m_qwtPlot->itemList(); for ( QwtPlotItemIterator it = itemList.begin(); it != itemList.end(); it++ ) { if ( ( *it )->rtti() == QwtPlotItem::Rtti_PlotCurve ) { const QwtPlotCurve* curve = static_cast( *it ); if ( relevantQwtCurvesSet.find( curve ) != relevantQwtCurvesSet.end() ) { double dist = HUGE_VAL; int candidateSampleIndex = curve->closestPoint( cursorPosition, &dist ); if ( dist < distMin ) { closestCurve = curve; closestPointSampleIndex = candidateSampleIndex; distMin = dist; } } } } if ( closestCurve && closestPointSampleIndex >= 0 && distMin < 50 ) { if ( closestSampleIndex ) *closestSampleIndex = closestPointSampleIndex; return closestCurve; } else { return nullptr; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RiuPvtPlotWidget::indexOfQwtCurve( const QwtPlotCurve* qwtCurve ) const { for ( size_t i = 0; i < m_qwtCurveArr.size(); i++ ) { if ( m_qwtCurveArr[i] == qwtCurve ) { return i; } } return cvf::UNDEFINED_SIZE_T; } //-------------------------------------------------------------------------------------------------- /// Implements the RiuPvtTrackerTextProvider interface //-------------------------------------------------------------------------------------------------- QString RiuPvtPlotWidget::trackerText() const { return m_trackerLabel; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPvtPlotWidget::slotPickerPointChanged( const QPoint& pt ) { updateTrackerPlotMarkerAndLabelFromPicker(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPvtPlotWidget::slotPickerActivated( bool on ) { updateTrackerPlotMarkerAndLabelFromPicker(); } //================================================================================================== /// /// \class RiuPvtPlotPanel /// /// /// //================================================================================================== //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuPvtPlotPanel::RiuPvtPlotPanel( QWidget* parent ) : QWidget( parent ) , m_unitSystem( RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN ) , m_plotUpdater( new RiuPvtPlotUpdater( this ) ) { m_phaseComboBox = new QComboBox( this ); m_phaseComboBox->setEditable( false ); m_phaseComboBox->addItem( "Oil", QVariant( RigFlowDiagSolverInterface::PvtCurve::OIL ) ); m_phaseComboBox->addItem( "Gas", QVariant( RigFlowDiagSolverInterface::PvtCurve::GAS ) ); m_titleLabel = new QLabel( "", this ); m_titleLabel->setAlignment( Qt::AlignHCenter ); QFont font = m_titleLabel->font(); font.setPointSize( 10 ); font.setBold( true ); m_titleLabel->setFont( font ); QHBoxLayout* topLayout = new QHBoxLayout(); topLayout->addWidget( new QLabel( "Phase:" ) ); topLayout->addWidget( m_phaseComboBox ); topLayout->addWidget( m_titleLabel, 1 ); topLayout->setContentsMargins( 5, 5, 0, 0 ); m_fvfPlot = new RiuPvtPlotWidget( this ); m_viscosityPlot = new RiuPvtPlotWidget( this ); QHBoxLayout* plotLayout = new QHBoxLayout(); plotLayout->addWidget( m_fvfPlot ); plotLayout->addWidget( m_viscosityPlot ); plotLayout->setSpacing( 0 ); plotLayout->setContentsMargins( 0, 0, 0, 0 ); QVBoxLayout* mainLayout = new QVBoxLayout(); mainLayout->addLayout( topLayout ); mainLayout->addLayout( plotLayout ); mainLayout->setContentsMargins( 0, 0, 0, 0 ); setLayout( mainLayout ); connect( m_phaseComboBox, SIGNAL( currentIndexChanged( int ) ), SLOT( slotPhaseComboCurrentIndexChanged( int ) ) ); plotUiSelectedCurves(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuPvtPlotPanel::~RiuPvtPlotPanel() { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPvtPlotPanel::setPlotData( RiaDefines::EclipseUnitSystem unitSystem, const std::vector& fvfCurveArr, const std::vector& viscosityCurveArr, const FvfDynProps& fvfDynProps, const ViscosityDynProps& viscosityDynProps, const CellValues& cellValues, const QString& cellReferenceText ) { // cvf::Trace::show("RiuPvtPlotPanel::setPlotData()"); m_unitSystem = unitSystem; m_allFvfCurvesArr = fvfCurveArr; m_allViscosityCurvesArr = viscosityCurveArr; m_fvfDynProps = fvfDynProps; m_viscosityDynProps = viscosityDynProps; m_cellValues = cellValues; m_cellReferenceText = cellReferenceText; plotUiSelectedCurves(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPvtPlotPanel::clearPlot() { // cvf::Trace::show("RiuPvtPlotPanel::clearPlot()"); if ( m_allFvfCurvesArr.empty() && m_allViscosityCurvesArr.empty() && m_cellReferenceText.isEmpty() ) { return; } m_unitSystem = RiaDefines::EclipseUnitSystem::UNITS_UNKNOWN; m_allFvfCurvesArr.clear(); m_allViscosityCurvesArr.clear(); m_fvfDynProps = FvfDynProps(); m_viscosityDynProps = ViscosityDynProps(); m_cellValues = CellValues(); m_cellReferenceText.clear(); plotUiSelectedCurves(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuPvtPlotUpdater* RiuPvtPlotPanel::plotUpdater() { return m_plotUpdater.get(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPvtPlotPanel::applyFontSizes( bool replot ) { if ( m_fvfPlot ) m_fvfPlot->applyFontSizes( replot ); if ( m_viscosityPlot ) m_viscosityPlot->applyFontSizes( replot ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPvtPlotPanel::plotUiSelectedCurves() { // Determine which curves (phase) to actually plot based on selection in GUI const int currComboIdx = m_phaseComboBox->currentIndex(); const RigFlowDiagSolverInterface::PvtCurve::Phase phaseToPlot = static_cast( m_phaseComboBox->itemData( currComboIdx ).toInt() ); QString phaseString = ""; if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::GAS ) { phaseString = "Gas "; } else if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::OIL ) { phaseString = "Oil "; } // FVF plot { RigFlowDiagSolverInterface::PvtCurve::Ident curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Unknown; double pointMarkerFvfValue = HUGE_VAL; QString pointMarkerLabel = ""; if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::GAS ) { curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Bg; pointMarkerFvfValue = m_fvfDynProps.bg; pointMarkerLabel = QString( "%1 (%2)" ).arg( pointMarkerFvfValue ).arg( m_cellValues.pressure ); if ( m_cellValues.rv != HUGE_VAL ) { pointMarkerLabel += QString( "\nRv = %1" ).arg( m_cellValues.rv ); } } else if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::OIL ) { curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Bo; pointMarkerFvfValue = m_fvfDynProps.bo; pointMarkerLabel = QString( "%1 (%2)" ).arg( pointMarkerFvfValue ).arg( m_cellValues.pressure ); if ( m_cellValues.rs != HUGE_VAL ) { pointMarkerLabel += QString( "\nRs = %1" ).arg( m_cellValues.rs ); } } std::vector selectedFvfCurves; for ( RigFlowDiagSolverInterface::PvtCurve curve : m_allFvfCurvesArr ) { if ( curve.ident == curveIdentToPlot ) { selectedFvfCurves.push_back( curve ); } } const QString plotTitle = QString( "%1 Formation Volume Factor" ).arg( phaseString ); const QString yAxisTitle = QString( "%1 Formation Volume Factor [%2]" ) .arg( phaseString ) .arg( unitLabelFromCurveIdent( m_unitSystem, curveIdentToPlot ) ); m_fvfPlot->plotCurves( m_unitSystem, selectedFvfCurves, m_cellValues.pressure, pointMarkerFvfValue, pointMarkerLabel, plotTitle, yAxisTitle ); } // Viscosity plot { RigFlowDiagSolverInterface::PvtCurve::Ident curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Unknown; double pointMarkerViscosityValue = HUGE_VAL; QString pointMarkerLabel = ""; if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::GAS ) { curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Visc_g; pointMarkerViscosityValue = m_viscosityDynProps.mu_g; pointMarkerLabel = QString( "%1 (%2)" ).arg( pointMarkerViscosityValue ).arg( m_cellValues.pressure ); if ( m_cellValues.rv != HUGE_VAL ) { pointMarkerLabel += QString( "\nRv = %1" ).arg( m_cellValues.rv ); } } else if ( phaseToPlot == RigFlowDiagSolverInterface::PvtCurve::OIL ) { curveIdentToPlot = RigFlowDiagSolverInterface::PvtCurve::Visc_o; pointMarkerViscosityValue = m_viscosityDynProps.mu_o; pointMarkerLabel = QString( "%1 (%2)" ).arg( pointMarkerViscosityValue ).arg( m_cellValues.pressure ); if ( m_cellValues.rs != HUGE_VAL ) { pointMarkerLabel += QString( "\nRs = %1" ).arg( m_cellValues.rs ); } } std::vector selectedViscosityCurves; for ( RigFlowDiagSolverInterface::PvtCurve curve : m_allViscosityCurvesArr ) { if ( curve.ident == curveIdentToPlot ) { selectedViscosityCurves.push_back( curve ); } } const QString plotTitle = QString( "%1 Viscosity" ).arg( phaseString ); const QString yAxisTitle = QString( "%1 Viscosity [%2]" ).arg( phaseString ).arg( unitLabelFromCurveIdent( m_unitSystem, curveIdentToPlot ) ); m_viscosityPlot->plotCurves( m_unitSystem, selectedViscosityCurves, m_cellValues.pressure, pointMarkerViscosityValue, pointMarkerLabel, plotTitle, yAxisTitle ); } // Update the label on top in our panel QString titleStr = "PVT"; if ( !m_cellReferenceText.isEmpty() ) { titleStr += ", " + m_cellReferenceText; } m_titleLabel->setText( titleStr ); } //-------------------------------------------------------------------------------------------------- /// Static helper to get unit labels //-------------------------------------------------------------------------------------------------- QString RiuPvtPlotPanel::unitLabelFromCurveIdent( RiaDefines::EclipseUnitSystem unitSystem, RigFlowDiagSolverInterface::PvtCurve::Ident curveIdent ) { if ( curveIdent == RigFlowDiagSolverInterface::PvtCurve::Bo ) { switch ( unitSystem ) { case RiaDefines::EclipseUnitSystem::UNITS_METRIC: return "rm3/sm3"; case RiaDefines::EclipseUnitSystem::UNITS_FIELD: return "rb/stb"; case RiaDefines::EclipseUnitSystem::UNITS_LAB: return "rcc/scc"; default: return ""; } } else if ( curveIdent == RigFlowDiagSolverInterface::PvtCurve::Bg ) { switch ( unitSystem ) { case RiaDefines::EclipseUnitSystem::UNITS_METRIC: return "rm3/sm3"; case RiaDefines::EclipseUnitSystem::UNITS_FIELD: return "rb/Mscf"; case RiaDefines::EclipseUnitSystem::UNITS_LAB: return "rcc/scc"; default: return ""; } } else if ( curveIdent == RigFlowDiagSolverInterface::PvtCurve::Visc_o || curveIdent == RigFlowDiagSolverInterface::PvtCurve::Visc_g ) { switch ( unitSystem ) { case RiaDefines::EclipseUnitSystem::UNITS_METRIC: return "cP"; case RiaDefines::EclipseUnitSystem::UNITS_FIELD: return "cP"; case RiaDefines::EclipseUnitSystem::UNITS_LAB: return "cP"; default: return ""; } } return ""; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuPvtPlotPanel::slotPhaseComboCurrentIndexChanged( int ) { plotUiSelectedCurves(); }