///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2016 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 "RimSummaryPlot.h" #include "RiaColorTables.h" #include "RiaDefines.h" #include "RiaFieldHandleTools.h" #include "RiaPlotDefines.h" #include "RiaPreferences.h" #include "RiaRegressionTestRunner.h" #include "RiaSummaryAddressAnalyzer.h" #include "RiaSummaryCurveDefinition.h" #include "RiaSummaryTools.h" #include "RiaTimeHistoryCurveResampler.h" #include "RicfCommandObject.h" #include "SummaryPlotCommands/RicSummaryPlotEditorUi.h" #include "PlotTemplates/RimPlotTemplateFileItem.h" #include "PlotTemplates/RimPlotTemplateFolderItem.h" #include "RimAsciiDataCurve.h" #include "RimEnsembleCurveSet.h" #include "RimEnsembleCurveSetCollection.h" #include "RimGridTimeHistoryCurve.h" #include "RimMultiPlot.h" #include "RimPlotAxisLogRangeCalculator.h" #include "RimPlotAxisProperties.h" #include "RimProject.h" #include "RimSummaryAddress.h" #include "RimSummaryCase.h" #include "RimSummaryCurve.h" #include "RimSummaryCurveCollection.h" #include "RimSummaryCurvesData.h" #include "RimSummaryPlotAxisFormatter.h" #include "RimSummaryPlotCollection.h" #include "RimSummaryPlotFilterTextCurveSetEditor.h" #include "RimSummaryPlotNameHelper.h" #include "RimSummaryTimeAxisProperties.h" #include "RiuPlotAxis.h" #include "RiuPlotMainWindowTools.h" #include "RiuSummaryQwtPlot.h" #include "RiuTreeViewEventFilter.h" #ifdef USE_QTCHARTS #include "RiuSummaryQtChartsPlot.h" #endif #include "cvfColor3.h" #include "cafPdmFieldScriptingCapability.h" #include "cafPdmUiCheckBoxEditor.h" #include "cafPdmUiTreeOrdering.h" #include "cafSelectionManager.h" #include "qwt_plot.h" #include "qwt_plot_curve.h" #include "qwt_plot_textlabel.h" #include #include #include #include #include #include #include #include #include CAF_PDM_SOURCE_INIT( RimSummaryPlot, "SummaryPlot" ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimSummaryPlot::RimSummaryPlot( bool isCrossPlot ) : RimPlot() , m_isCrossPlot( isCrossPlot ) { CAF_PDM_InitScriptableObject( "Summary Plot", ":/SummaryPlotLight16x16.png", "", "A Summary Plot" ); CAF_PDM_InitScriptableField( &m_useAutoPlotTitle, "IsUsingAutoName", true, "Auto Title" ); CAF_PDM_InitScriptableField( &m_description, "PlotDescription", QString( "Summary Plot" ), "Name" ); CAF_PDM_InitScriptableField( &m_normalizeCurveYValues, "normalizeCurveYValues", false, "Normalize all curves" ); #ifdef USE_QTCHARTS bool useQtChart = RiaPreferences::current()->useQtChartsAsDefaultPlotType(); CAF_PDM_InitScriptableField( &m_useQtChartsPlot, "useQtChartsPlot", useQtChart, "Use Qt Charts" ); #endif CAF_PDM_InitFieldNoDefault( &m_summaryCurveCollection, "SummaryCurveCollection", "" ); m_summaryCurveCollection.uiCapability()->setUiTreeHidden( true ); m_summaryCurveCollection = new RimSummaryCurveCollection; m_summaryCurveCollection->curvesChanged.connect( this, &RimSummaryPlot::onCurveCollectionChanged ); CAF_PDM_InitFieldNoDefault( &m_ensembleCurveSetCollection, "EnsembleCurveSetCollection", "" ); m_ensembleCurveSetCollection.uiCapability()->setUiTreeHidden( true ); m_ensembleCurveSetCollection = new RimEnsembleCurveSetCollection(); CAF_PDM_InitFieldNoDefault( &m_gridTimeHistoryCurves, "GridTimeHistoryCurves", "" ); m_gridTimeHistoryCurves.uiCapability()->setUiTreeHidden( true ); CAF_PDM_InitFieldNoDefault( &m_asciiDataCurves, "AsciiDataCurves", "" ); m_asciiDataCurves.uiCapability()->setUiTreeHidden( true ); CAF_PDM_InitFieldNoDefault( &m_axisProperties, "AxisProperties", "Axes", ":/Axes16x16.png" ); RimPlotAxisProperties* leftYAxisProperties = new RimPlotAxisProperties; leftYAxisProperties->setNameAndAxis( "Left", RiaDefines::PlotAxis::PLOT_AXIS_LEFT, 0 ); m_axisProperties.push_back( leftYAxisProperties ); connectAxisSignals( leftYAxisProperties ); RimPlotAxisProperties* rightYAxisProperties = new RimPlotAxisProperties; rightYAxisProperties->setNameAndAxis( "Right", RiaDefines::PlotAxis::PLOT_AXIS_RIGHT, 0 ); m_axisProperties.push_back( rightYAxisProperties ); connectAxisSignals( rightYAxisProperties ); if ( m_isCrossPlot ) { RimPlotAxisProperties* bottomAxisProperties = new RimPlotAxisProperties; bottomAxisProperties->setNameAndAxis( "Bottom", RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM, 0 ); m_axisProperties.push_back( bottomAxisProperties ); } else { RimSummaryTimeAxisProperties* timeAxisProperties = new RimSummaryTimeAxisProperties; m_axisProperties.push_back( timeAxisProperties ); } CAF_PDM_InitFieldNoDefault( &m_textCurveSetEditor, "SummaryPlotFilterTextCurveSetEditor", "Text Filter Curve Creator" ); m_textCurveSetEditor.uiCapability()->setUiTreeHidden( true ); m_textCurveSetEditor = new RimSummaryPlotFilterTextCurveSetEditor; m_nameHelperAllCurves.reset( new RimSummaryPlotNameHelper ); CAF_PDM_InitFieldNoDefault( &m_sourceStepping, "SourceStepping", "" ); m_sourceStepping = new RimSummaryPlotSourceStepping; m_sourceStepping->setSourceSteppingType( RimSummaryDataSourceStepping::Axis::Y_AXIS ); m_sourceStepping->setSourceSteppingObject( this ); m_sourceStepping.uiCapability()->setUiTreeHidden( true ); m_sourceStepping.uiCapability()->setUiTreeChildrenHidden( true ); m_sourceStepping.xmlCapability()->disableIO(); setPlotInfoLabel( "Filters Active" ); // Obsolete axis fields CAF_PDM_InitFieldNoDefault( &m_leftYAxisProperties_OBSOLETE, "LeftYAxisProperties", "Left Y Axis" ); m_leftYAxisProperties_OBSOLETE.uiCapability()->setUiTreeHidden( true ); m_leftYAxisProperties_OBSOLETE.xmlCapability()->setIOWritable( false ); m_leftYAxisProperties_OBSOLETE = new RimPlotAxisProperties; CAF_PDM_InitFieldNoDefault( &m_rightYAxisProperties_OBSOLETE, "RightYAxisProperties", "Right Y Axis" ); m_rightYAxisProperties_OBSOLETE.uiCapability()->setUiTreeHidden( true ); m_rightYAxisProperties_OBSOLETE.xmlCapability()->setIOWritable( false ); m_rightYAxisProperties_OBSOLETE = new RimPlotAxisProperties; CAF_PDM_InitFieldNoDefault( &m_bottomAxisProperties_OBSOLETE, "BottomAxisProperties", "Bottom X Axis" ); m_bottomAxisProperties_OBSOLETE.uiCapability()->setUiTreeHidden( true ); m_bottomAxisProperties_OBSOLETE.xmlCapability()->setIOWritable( false ); m_bottomAxisProperties_OBSOLETE = new RimPlotAxisProperties; CAF_PDM_InitFieldNoDefault( &m_timeAxisProperties_OBSOLETE, "TimeAxisProperties", "Time Axis" ); m_timeAxisProperties_OBSOLETE.uiCapability()->setUiTreeHidden( true ); m_timeAxisProperties_OBSOLETE.xmlCapability()->setIOWritable( false ); m_timeAxisProperties_OBSOLETE = new RimSummaryTimeAxisProperties; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimSummaryPlot::~RimSummaryPlot() { removeMdiWindowFromMdiArea(); cleanupBeforeClose(); delete m_summaryCurveCollection; delete m_ensembleCurveSetCollection; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateAxes() { updateAxis( RiaDefines::PlotAxis::PLOT_AXIS_LEFT ); updateAxis( RiaDefines::PlotAxis::PLOT_AXIS_RIGHT ); if ( timeAxisProperties() && plotWidget() ) { m_summaryPlot->updateAnnotationObjects( timeAxisProperties() ); } RimPlotAxisPropertiesInterface* leftYAxisProperties = axisPropertiesForPlotAxis( RiuPlotAxis::defaultLeft() ); if ( leftYAxisProperties && plotWidget() ) { m_summaryPlot->updateAnnotationObjects( leftYAxisProperties ); } if ( m_isCrossPlot ) { updateAxis( RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM ); } else { updateTimeAxis( timeAxisProperties() ); } plotWidget()->scheduleReplot(); updateZoomInParentPlot(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimSummaryPlot::isLogarithmicScaleEnabled( RiuPlotAxis plotAxis ) const { return axisPropertiesForPlotAxis( plotAxis )->isLogarithmicScaleEnabled(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimSummaryTimeAxisProperties* RimSummaryPlot::timeAxisProperties() { // Find the first time axis (which is correct since there is only one). for ( auto ap : m_axisProperties ) { RimSummaryTimeAxisProperties* timeAxis = dynamic_cast( ap.p() ); if ( timeAxis ) return timeAxis; } return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- time_t RimSummaryPlot::firstTimeStepOfFirstCurve() { RimSummaryCurve* firstCurve = nullptr; if ( m_summaryCurveCollection ) { std::vector curves = m_summaryCurveCollection->curves(); size_t i = 0; while ( firstCurve == nullptr && i < curves.size() ) { firstCurve = curves[i]; ++i; } } if ( firstCurve && firstCurve->timeStepsY().size() > 0 ) { return firstCurve->timeStepsY()[0]; } else return time_t( 0 ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QWidget* RimSummaryPlot::viewWidget() { return plotWidget(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuPlotWidget* RimSummaryPlot::plotWidget() { if ( !m_summaryPlot ) return nullptr; return m_summaryPlot->plotWidget(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimSummaryPlot::asciiDataForPlotExport() const { return asciiDataForSummaryPlotExport( RiaQDateTimeTools::DateTimePeriod::YEAR, false ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimSummaryPlot::asciiDataForSummaryPlotExport( RiaQDateTimeTools::DateTimePeriod resamplingPeriod, bool showTimeAsLongString ) const { std::vector curves; this->descendantsIncludingThisOfType( curves ); auto gridCurves = m_gridTimeHistoryCurves.childObjects(); auto asciiCurves = m_asciiDataCurves.childObjects(); QString text = RimSummaryCurvesData::createTextForExport( curves, asciiCurves, gridCurves, resamplingPeriod, showTimeAsLongString ); return text; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- caf::PdmObject* RimSummaryPlot::findPdmObjectFromPlotCurve( const RiuPlotCurve* plotCurve ) const { for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) { if ( curve->isSameCurve( plotCurve ) ) { return curve; } } for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) { if ( curve->isSameCurve( plotCurve ) ) { return curve; } } if ( m_summaryCurveCollection ) { RimSummaryCurve* foundCurve = m_summaryCurveCollection->findRimCurveFromPlotCurve( plotCurve ); if ( foundCurve ) { m_summaryCurveCollection->setCurrentSummaryCurve( foundCurve ); return foundCurve; } } if ( m_ensembleCurveSetCollection ) { RimSummaryCurve* foundCurve = m_ensembleCurveSetCollection->findRimCurveFromPlotCurve( plotCurve ); if ( foundCurve ) { return foundCurve; } } return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::onAxisSelected( int axis, bool toggle ) { RiuPlotMainWindowTools::showPlotMainWindow(); caf::PdmObject* itemToSelect = nullptr; if ( axis == QwtPlot::yLeft ) { itemToSelect = m_leftYAxisProperties_OBSOLETE; } else if ( axis == QwtPlot::yRight ) { itemToSelect = m_rightYAxisProperties_OBSOLETE; } else if ( axis == QwtPlot::xBottom ) { if ( m_isCrossPlot ) { itemToSelect = m_bottomAxisProperties_OBSOLETE; } else { itemToSelect = m_timeAxisProperties_OBSOLETE; } } if ( toggle ) { RiuPlotMainWindowTools::toggleItemInSelection( itemToSelect ); } else { RiuPlotMainWindowTools::selectAsCurrentItem( itemToSelect ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::moveCurvesToPlot( RimSummaryPlot* plot, const std::vector curves, int insertAtPosition ) { CAF_ASSERT( plot ); std::set srcPlots; for ( auto curve : curves ) { RimSummaryPlot* srcPlot = nullptr; curve->firstAncestorOrThisOfTypeAsserted( srcPlot ); srcPlot->removeCurve( curve ); srcPlots.insert( srcPlot ); } for ( auto srcPlot : srcPlots ) { srcPlot->updateConnectedEditors(); srcPlot->loadDataAndUpdate(); } for ( size_t cIdx = 0; cIdx < curves.size(); ++cIdx ) { if ( insertAtPosition >= 0 ) { size_t position = (size_t)insertAtPosition + cIdx; plot->insertCurve( curves[cIdx], position ); } else { plot->addCurveNoUpdate( curves[cIdx] ); } } plot->updateConnectedEditors(); plot->updateStackedCurveData(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::curvesForStepping( RimSummaryDataSourceStepping::Axis axis ) const { auto curveForStepping = summaryCurveCollection()->curveForSourceStepping(); if ( curveForStepping ) { return { curveForStepping }; } return summaryCurves(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::curveSets() const { return ensembleCurveSetCollection()->curveSets(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::allCurves( RimSummaryDataSourceStepping::Axis axis ) const { return summaryCurves(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::availableAxes() const { if ( m_isCrossPlot ) return { RimSummaryDataSourceStepping::Axis::X_AXIS, RimSummaryDataSourceStepping::Axis::Y_AXIS }; return { RimSummaryDataSourceStepping::Axis::X_AXIS }; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::summaryAndEnsembleCurves() const { std::vector curves = summaryCurves(); for ( const auto& curveSet : ensembleCurveSetCollection()->curveSets() ) { for ( const auto& curve : curveSet->curves() ) { curves.push_back( curve ); } } return curves; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::set RimSummaryPlot::summaryAndEnsembleCurveDefinitions() const { std::set allCurveDefs; for ( const auto& curve : this->summaryAndEnsembleCurves() ) { allCurveDefs.insert( RiaSummaryCurveDefinition( curve->summaryCaseY(), curve->summaryAddressY(), curve->isEnsembleCurve() ) ); } return allCurveDefs; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::summaryCurves() const { return m_summaryCurveCollection->curves(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::deleteAllSummaryCurves() { m_summaryCurveCollection->deleteAllCurves(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimSummaryCurveCollection* RimSummaryPlot::summaryCurveCollection() const { return m_summaryCurveCollection(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::visibleStackedSummaryCurvesForAxis( RiuPlotAxis plotAxis ) { auto visibleCurves = visibleSummaryCurvesForAxis( plotAxis ); std::vector visibleStackedCurves; std::copy_if( visibleCurves.begin(), visibleCurves.end(), std::back_inserter( visibleStackedCurves ), []( RimSummaryCurve* curve ) { return curve->isStacked(); } ); return visibleStackedCurves; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updatePlotTitle() { m_nameHelperAllCurves->clear(); updateNameHelperWithCurveData( m_nameHelperAllCurves.get() ); if ( m_useAutoPlotTitle ) { m_description = m_nameHelperAllCurves->plotTitle(); } updateCurveNames(); updateMdiWindowTitle(); if ( plotWidget() ) { QString plotTitle = description(); plotWidget()->setPlotTitle( plotTitle ); plotWidget()->setPlotTitleEnabled( m_showPlotTitle && !isSubPlot() ); plotWidget()->scheduleReplot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const RimSummaryNameHelper* RimSummaryPlot::activePlotTitleHelperAllCurves() const { if ( m_useAutoPlotTitle() ) { return m_nameHelperAllCurves.get(); } return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const RimSummaryNameHelper* RimSummaryPlot::plotTitleHelper() const { return m_nameHelperAllCurves.get(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimSummaryPlot::generatedPlotTitleFromAllCurves() const { RimSummaryPlotNameHelper nameHelper; updateNameHelperWithCurveData( &nameHelper ); return nameHelper.plotTitle(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::copyAxisPropertiesFromOther( const RimSummaryPlot& sourceSummaryPlot ) { for ( auto ap : sourceSummaryPlot.plotAxes() ) { QString data = ap->writeObjectToXmlString(); axisPropertiesForPlotAxis( ap->plotAxisType() ) ->readObjectFromXmlString( data, caf::PdmDefaultObjectFactory::instance() ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateAll() { if ( plotWidget() ) { updatePlotTitle(); plotWidget()->updateLegend(); updateAxes(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateLegend() { if ( plotWidget() ) { plotWidget()->setInternalLegendVisible( m_showPlotLegends && !isSubPlot() ); for ( auto c : summaryCurves() ) { c->updateLegendEntryVisibilityNoPlotUpdate(); } } reattachAllCurves(); if ( plotWidget() ) { plotWidget()->updateLegend(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::setPlotInfoLabel( const QString& label ) { auto qwtText = QwtText( label ); qwtText.setRenderFlags( Qt::AlignBottom | Qt::AlignRight ); QFont font; font.setBold( true ); qwtText.setFont( font ); m_plotInfoLabel.reset( new QwtPlotTextLabel() ); m_plotInfoLabel->setText( qwtText ); m_plotInfoLabel->setMargin( 10 ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::showPlotInfoLabel( bool show ) { RiuQwtPlotWidget* qwtPlotWidget = dynamic_cast( plotWidget() ); if ( !qwtPlotWidget ) return; if ( show ) m_plotInfoLabel->attach( qwtPlotWidget->qwtPlot() ); else m_plotInfoLabel->detach(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updatePlotInfoLabel() { bool anyCurveSetFiltered = false; for ( auto group : m_ensembleCurveSetCollection->curveSets() ) { if ( group->isFiltered() ) { anyCurveSetFiltered = true; break; } } showPlotInfoLabel( anyCurveSetFiltered ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimSummaryPlot::containsResamplableCurves() const { std::vector summaryCurves = summaryAndEnsembleCurves(); size_t resamplableSummaryCurveCount = std::count_if( summaryCurves.begin(), summaryCurves.end(), []( RimSummaryCurve* curve ) { return curve->summaryCaseY() ? !curve->summaryCaseY()->isObservedData() : false; } ); return !m_gridTimeHistoryCurves.empty() || resamplableSummaryCurveCount > 0; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RimSummaryPlot::singleColorCurveCount() const { auto allCurveSets = ensembleCurveSetCollection()->curveSets(); size_t colorIndex = std::count_if( allCurveSets.begin(), allCurveSets.end(), []( RimEnsembleCurveSet* curveSet ) { return curveSet->colorMode() == RimEnsembleCurveSet::ColorMode::SINGLE_COLOR; } ); colorIndex += curveCount(); return colorIndex; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::applyDefaultCurveAppearances() { std::set allCurveDefs = this->summaryAndEnsembleCurveDefinitions(); RimSummaryCurveAppearanceCalculator curveLookCalc( allCurveDefs ); // Summary curves for ( auto& curve : this->summaryCurves() ) { curve->resetAppearance(); curveLookCalc.setupCurveLook( curve ); } // Ensemble curve sets int colorIndex = 0; for ( auto& curveSet : this->ensembleCurveSetCollection()->curveSets() ) { if ( curveSet->colorMode() != RimEnsembleCurveSet::ColorMode::SINGLE_COLOR ) continue; curveSet->setColor( RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f( colorIndex++ ) ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::setNormalizationEnabled( bool enable ) { m_normalizeCurveYValues = enable; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimSummaryPlot::isNormalizationEnabled() { return m_normalizeCurveYValues(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateAxis( RiaDefines::PlotAxis plotAxis ) { if ( !plotWidget() ) return; for ( RimPlotAxisPropertiesInterface* yAxisProperties : m_axisProperties ) { RiuPlotAxis riuPlotAxis = yAxisProperties->plotAxisType(); if ( riuPlotAxis.axis() == plotAxis ) { RimPlotAxisProperties* axisProperties = dynamic_cast( yAxisProperties ); if ( yAxisProperties->isActive() && hasVisibleCurvesForAxis( riuPlotAxis ) && axisProperties ) { plotWidget()->enableAxis( riuPlotAxis, true ); std::set timeHistoryQuantities; for ( auto c : visibleTimeHistoryCurvesForAxis( riuPlotAxis ) ) { timeHistoryQuantities.insert( c->quantityName() ); } RimSummaryPlotAxisFormatter calc( axisProperties, visibleSummaryCurvesForAxis( riuPlotAxis ), {}, visibleAsciiDataCurvesForAxis( riuPlotAxis ), timeHistoryQuantities ); calc.applyAxisPropertiesToPlot( plotWidget() ); } else { plotWidget()->enableAxis( riuPlotAxis, false ); } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateZoomForAxis( RiuPlotAxis plotAxis ) { RimPlotAxisPropertiesInterface* yAxisProps = axisPropertiesForPlotAxis( plotAxis ); if ( yAxisProps->isAutoZoom() ) { if ( yAxisProps->isLogarithmicScaleEnabled() ) { plotWidget()->setAxisScaleType( yAxisProps->plotAxisType(), RiuQwtPlotWidget::AxisScaleType::LOGARITHMIC ); std::vector plotCurves; for ( RimSummaryCurve* c : visibleSummaryCurvesForAxis( plotAxis ) ) { plotCurves.push_back( c ); } for ( RimGridTimeHistoryCurve* c : visibleTimeHistoryCurvesForAxis( plotAxis ) ) { plotCurves.push_back( c ); } for ( RimAsciiDataCurve* c : visibleAsciiDataCurvesForAxis( plotAxis ) ) { plotCurves.push_back( c ); } double min, max; RimPlotAxisLogRangeCalculator calc( RiaDefines::PlotAxis::PLOT_AXIS_LEFT, plotCurves ); calc.computeAxisRange( &min, &max ); if ( yAxisProps->isAxisInverted() ) { std::swap( min, max ); } plotWidget()->setAxisScale( yAxisProps->plotAxisType(), min, max ); } else { plotWidget()->setAxisAutoScale( yAxisProps->plotAxisType(), true ); } } else { plotWidget()->setAxisScale( yAxisProps->plotAxisType(), yAxisProps->visibleRangeMin(), yAxisProps->visibleRangeMax() ); } plotWidget()->setAxisInverted( yAxisProps->plotAxisType(), yAxisProps->isAxisInverted() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::visibleSummaryCurvesForAxis( RiuPlotAxis plotAxis ) const { std::vector curves; if ( plotAxis.axis() == RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM ) { if ( m_summaryCurveCollection && m_summaryCurveCollection->isCurvesVisible() ) { for ( RimSummaryCurve* curve : m_summaryCurveCollection->curves() ) { if ( curve->isCurveVisible() ) { curves.push_back( curve ); } } } } else { if ( m_summaryCurveCollection && m_summaryCurveCollection->isCurvesVisible() ) { for ( RimSummaryCurve* curve : m_summaryCurveCollection->curves() ) { if ( curve->isCurveVisible() && curve->axisY() == plotAxis ) { curves.push_back( curve ); } } } if ( m_ensembleCurveSetCollection && m_ensembleCurveSetCollection->isCurveSetsVisible() ) { for ( RimEnsembleCurveSet* curveSet : m_ensembleCurveSetCollection->curveSets() ) { for ( RimSummaryCurve* curve : curveSet->curves() ) { if ( curve->isCurveVisible() && curve->axisY() == plotAxis ) { curves.push_back( curve ); } } } } } return curves; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimSummaryPlot::hasVisibleCurvesForAxis( RiuPlotAxis plotAxis ) const { if ( visibleSummaryCurvesForAxis( plotAxis ).size() > 0 ) { return true; } if ( visibleTimeHistoryCurvesForAxis( plotAxis ).size() > 0 ) { return true; } if ( visibleAsciiDataCurvesForAxis( plotAxis ).size() > 0 ) { return true; } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimPlotAxisPropertiesInterface* RimSummaryPlot::axisPropertiesForPlotAxis( RiuPlotAxis plotAxis ) const { for ( RimPlotAxisPropertiesInterface* axisProperties : m_axisProperties ) { if ( axisProperties->plotAxisType() == plotAxis ) return axisProperties; } CVF_ASSERT( false && "No axis properties found for axis" ); return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::visibleTimeHistoryCurvesForAxis( RiuPlotAxis plotAxis ) const { std::vector curves; for ( auto c : m_gridTimeHistoryCurves ) { if ( c->isCurveVisible() ) { if ( c->yAxis() == plotAxis || plotAxis.axis() == RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM ) { curves.push_back( c ); } } } return curves; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::visibleAsciiDataCurvesForAxis( RiuPlotAxis plotAxis ) const { std::vector curves; for ( auto c : m_asciiDataCurves ) { if ( c->isCurveVisible() ) { if ( c->yAxis() == plotAxis || plotAxis.axis() == RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM ) { curves.push_back( c ); } } } return curves; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateTimeAxis( RimSummaryTimeAxisProperties* timeAxisProperties ) { if ( !plotWidget() ) return; if ( !timeAxisProperties->isActive() ) { plotWidget()->enableAxis( RiuPlotAxis::defaultBottom(), false ); return; } if ( timeAxisProperties->timeMode() == RimSummaryTimeAxisProperties::DATE ) { RiaQDateTimeTools::DateFormatComponents dateComponents = timeAxisProperties->dateComponents(); RiaQDateTimeTools::TimeFormatComponents timeComponents = timeAxisProperties->timeComponents(); QString dateFormat = timeAxisProperties->dateFormat(); QString timeFormat = timeAxisProperties->timeFormat(); m_summaryPlot->useDateBasedTimeAxis( dateFormat, timeFormat, dateComponents, timeComponents ); } else { m_summaryPlot->useTimeBasedTimeAxis(); } plotWidget()->enableAxis( RiuPlotAxis::defaultBottom(), true ); { Qt::AlignmentFlag alignment = Qt::AlignCenter; if ( timeAxisProperties->titlePosition() == RimPlotAxisPropertiesInterface::AXIS_TITLE_END ) { alignment = Qt::AlignRight; } plotWidget()->setAxisFontsAndAlignment( RiuPlotAxis::defaultBottom(), timeAxisProperties->titleFontSize(), timeAxisProperties->valuesFontSize(), true, alignment ); plotWidget()->setAxisTitleText( RiuPlotAxis::defaultBottom(), timeAxisProperties->title() ); plotWidget()->setAxisTitleEnabled( RiuPlotAxis::defaultBottom(), timeAxisProperties->showTitle ); { RimSummaryTimeAxisProperties::LegendTickmarkCount tickmarkCountEnum = timeAxisProperties->majorTickmarkCount(); int maxTickmarkCount = 8; switch ( tickmarkCountEnum ) { case RimSummaryTimeAxisProperties::LegendTickmarkCount::TICKMARK_VERY_FEW: maxTickmarkCount = 2; break; case RimSummaryTimeAxisProperties::LegendTickmarkCount::TICKMARK_FEW: maxTickmarkCount = 4; break; case RimSummaryTimeAxisProperties::LegendTickmarkCount::TICKMARK_DEFAULT: maxTickmarkCount = 8; // Taken from QwtPlot::initAxesData() break; case RimSummaryTimeAxisProperties::LegendTickmarkCount::TICKMARK_MANY: maxTickmarkCount = 10; break; default: break; } plotWidget()->setAxisMaxMajor( RiuPlotAxis::defaultBottom(), maxTickmarkCount ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateCaseNameHasChanged() { if ( m_summaryCurveCollection ) { m_summaryCurveCollection->updateCaseNameHasChanged(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::addTimeAnnotation( time_t time ) { RimSummaryTimeAxisProperties* axisProps = timeAxisProperties(); { RimTimeAxisAnnotation* annotation = new RimTimeAxisAnnotation; annotation->setTime( time ); axisProps->appendAnnotation( annotation ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::addTimeRangeAnnotation( time_t startTime, time_t endTime ) { RimSummaryTimeAxisProperties* axisProps = timeAxisProperties(); { RimTimeAxisAnnotation* annotation = new RimTimeAxisAnnotation; annotation->setTimeRange( startTime, endTime ); axisProps->appendAnnotation( annotation ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::removeAllTimeAnnotations() { RimSummaryTimeAxisProperties* axisProps = timeAxisProperties(); axisProps->removeAllAnnotations(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::zoomAll() { setAutoScaleXEnabled( true ); setAutoScaleYEnabled( true ); updateZoomInParentPlot(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::addCurveAndUpdate( RimSummaryCurve* curve, bool autoAssignPlotAxis ) { if ( curve ) { m_summaryCurveCollection->addCurve( curve ); connectCurveToPlot( curve, true, autoAssignPlotAxis ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::addCurveNoUpdate( RimSummaryCurve* curve, bool autoAssignPlotAxis ) { if ( curve ) { m_summaryCurveCollection->addCurve( curve ); connectCurveToPlot( curve, false, autoAssignPlotAxis ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::insertCurve( RimSummaryCurve* curve, size_t insertAtPosition ) { if ( curve ) { m_summaryCurveCollection->insertCurve( curve, insertAtPosition ); connectCurveToPlot( curve, false, true ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::connectCurveToPlot( RimSummaryCurve* curve, bool update, bool autoAssignPlotAxis ) { if ( autoAssignPlotAxis ) assignPlotAxis( curve ); connectCurveSignals( curve ); if ( plotWidget() ) { if ( update ) { curve->setParentPlotAndReplot( plotWidget() ); this->updateAxes(); } else { curve->setParentPlotNoReplot( plotWidget() ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::removeCurve( RimSummaryCurve* curve ) { m_summaryCurveCollection->removeCurve( curve ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::deleteCurve( RimSummaryCurve* curve ) { deleteCurves( { curve } ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::deleteCurves( const std::vector& curves ) { for ( const auto curve : curves ) { if ( m_summaryCurveCollection ) { for ( auto& c : m_summaryCurveCollection->curves() ) { if ( c == curve ) { disconnectCurveSignals( curve ); m_summaryCurveCollection->deleteCurve( curve ); continue; } } } if ( m_ensembleCurveSetCollection ) { for ( auto& curveSet : m_ensembleCurveSetCollection->curveSets() ) { for ( auto& c : curveSet->curves() ) { if ( c == curve ) { curveSet->deleteCurve( curve ); if ( curveSet->curves().empty() ) { if ( curveSet->colorMode() == RimEnsembleCurveSet::ColorMode::BY_ENSEMBLE_PARAM && plotWidget() && curveSet->legendFrame() ) { plotWidget()->removeOverlayFrame( curveSet->legendFrame() ); } m_ensembleCurveSetCollection->deleteCurveSet( curveSet ); } continue; } } } } } RiuPlotMainWindowTools::refreshToolbars(); updateCaseNameHasChanged(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::deleteCurvesAssosiatedWithCase( RimSummaryCase* summaryCase ) { if ( m_summaryCurveCollection ) { m_summaryCurveCollection->deleteCurvesAssosiatedWithCase( summaryCase ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimEnsembleCurveSetCollection* RimSummaryPlot::ensembleCurveSetCollection() const { return m_ensembleCurveSetCollection; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::addGridTimeHistoryCurve( RimGridTimeHistoryCurve* curve ) { CVF_ASSERT( curve ); m_gridTimeHistoryCurves.push_back( curve ); if ( plotWidget() ) { curve->setParentPlotAndReplot( plotWidget() ); this->updateAxes(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::addGridTimeHistoryCurveNoUpdate( RimGridTimeHistoryCurve* curve ) { CVF_ASSERT( curve ); m_gridTimeHistoryCurves.push_back( curve ); if ( plotWidget() ) { curve->setParentPlotNoReplot( plotWidget() ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::gridTimeHistoryCurves() const { return m_gridTimeHistoryCurves.childObjects(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::addAsciiDataCruve( RimAsciiDataCurve* curve ) { CVF_ASSERT( curve ); m_asciiDataCurves.push_back( curve ); if ( plotWidget() ) { curve->setParentPlotAndReplot( plotWidget() ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- caf::PdmFieldHandle* RimSummaryPlot::userDescriptionField() { return &m_description; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) { RimPlot::fieldChangedByUi( changedField, oldValue, newValue ); if ( changedField == &m_showPlotTitle || changedField == &m_description || changedField == &m_useAutoPlotTitle ) { updatePlotTitle(); updateConnectedEditors(); if ( !m_useAutoPlotTitle ) { // When auto name of plot is turned off, update the auto name for all curves for ( auto c : summaryCurves() ) { c->updateCurveNameNoLegendUpdate(); } } } if ( changedField == &m_showPlotLegends ) updateLegend(); #ifdef USE_QTCHARTS if ( changedField == &m_useQtChartsPlot ) { // Hide window setShowWindow( false ); // Detach and destroy plot curves for ( auto c : summaryCurves() ) { c->detach( true ); } for ( auto& curveSet : this->ensembleCurveSetCollection()->curveSets() ) { curveSet->detachPlotCurves( true ); } // Destroy viewer removeMdiWindowFromMdiArea(); cleanupBeforeClose(); } #endif if ( changedField == &m_normalizeCurveYValues ) { this->loadDataAndUpdate(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) { updateStackedCurveData(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateStackedCurveData() { for ( RimPlotAxisPropertiesInterface* axisProperties : m_axisProperties ) { if ( axisProperties->plotAxisType().axis() == RiaDefines::PlotAxis::PLOT_AXIS_LEFT || axisProperties->plotAxisType().axis() == RiaDefines::PlotAxis::PLOT_AXIS_RIGHT ) updateStackedCurveDataForAxis( axisProperties->plotAxisType() ); } if ( plotWidget() ) { reattachAllCurves(); plotWidget()->scheduleReplot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateStackedCurveDataForAxis( RiuPlotAxis plotAxis ) { std::map curvePhaseCount; auto stackedCurves = visibleStackedSummaryCurvesForAxis( plotAxis ); // Reset all curves for ( RimSummaryCurve* curve : stackedCurves ) { // Apply a area filled style if it isn't already set if ( curve->fillStyle() == Qt::NoBrush ) { curve->setFillStyle( Qt::SolidPattern ); } curve->loadDataAndUpdate( false ); curvePhaseCount[curve->phaseType()]++; } { // Z-position of curve, to draw them in correct order double zPos = -10000.0; std::vector allTimeSteps; for ( RimSummaryCurve* curve : stackedCurves ) { allTimeSteps.insert( allTimeSteps.end(), curve->timeStepsY().begin(), curve->timeStepsY().end() ); } std::sort( allTimeSteps.begin(), allTimeSteps.end() ); allTimeSteps.erase( std::unique( allTimeSteps.begin(), allTimeSteps.end() ), allTimeSteps.end() ); std::vector allStackedValues( allTimeSteps.size(), 0.0 ); size_t stackIndex = 0u; for ( RimSummaryCurve* curve : stackedCurves ) { for ( size_t i = 0; i < allTimeSteps.size(); ++i ) { double value = curve->yValueAtTimeT( allTimeSteps[i] ); if ( value != std::numeric_limits::infinity() ) { allStackedValues[i] += value; } } curve->setOverrideCurveDataY( allTimeSteps, allStackedValues ); curve->setZOrder( zPos ); if ( curve->isStackedWithPhaseColors() ) { curve->assignStackColor( stackIndex, curvePhaseCount[curve->phaseType()] ); } zPos -= 1.0; } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QImage RimSummaryPlot::snapshotWindowContent() { QImage image; if ( plotWidget() ) { QPixmap pix = plotWidget()->grab(); image = pix.toImage(); } return image; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::defineUiTreeOrdering( caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName /*= ""*/ ) { if ( uiConfigName == RicSummaryPlotEditorUi::CONFIGURATION_NAME ) { uiTreeOrdering.add( &m_summaryCurveCollection ); if ( !m_isCrossPlot ) { uiTreeOrdering.add( &m_ensembleCurveSetCollection ); } } else { uiTreeOrdering.add( &m_axisProperties ); uiTreeOrdering.add( &m_summaryCurveCollection ); if ( !m_isCrossPlot ) { uiTreeOrdering.add( &m_ensembleCurveSetCollection ); } uiTreeOrdering.add( &m_gridTimeHistoryCurves ); uiTreeOrdering.add( &m_asciiDataCurves ); } uiTreeOrdering.skipRemainingChildren( true ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::onLoadDataAndUpdate() { updatePlotTitle(); updateMdiWindowVisibility(); if ( m_summaryCurveCollection ) { m_summaryCurveCollection->loadDataAndUpdate( false ); } m_ensembleCurveSetCollection->loadDataAndUpdate( false ); for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) { curve->loadDataAndUpdate( false ); } for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) { curve->loadDataAndUpdate( false ); } if ( plotWidget() ) { plotWidget()->setInternalLegendVisible( m_showPlotLegends && !isSubPlot() ); plotWidget()->setLegendFontSize( legendFontSize() ); plotWidget()->updateLegend(); } this->updateAxes(); m_textCurveSetEditor->updateTextFilter(); updateStackedCurveData(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateZoomInParentPlot() { if ( plotWidget() ) { for ( auto axisProperty : m_axisProperties ) { updateZoomForAxis( axisProperty->plotAxisType() ); } plotWidget()->updateAxes(); updateZoomFromParentPlot(); plotWidget()->scheduleReplot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateZoomFromParentPlot() { if ( !plotWidget() ) return; for ( RimPlotAxisPropertiesInterface* axisProperties : m_axisProperties ) { auto [axisMin, axisMax] = plotWidget()->axisRange( axisProperties->plotAxisType() ); axisProperties->setVisibleRangeMax( axisMax ); axisProperties->setVisibleRangeMin( axisMin ); axisProperties->updateConnectedEditors(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::cleanupBeforeClose() { if ( isDeletable() ) { detachAllPlotItems(); if ( plotWidget() ) { plotWidget()->setParent( nullptr ); } if ( m_summaryPlot ) { m_summaryPlot.reset(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::connectCurveSignals( RimSummaryCurve* curve ) { curve->dataChanged.connect( this, &RimSummaryPlot::curveDataChanged ); curve->visibilityChanged.connect( this, &RimSummaryPlot::curveVisibilityChanged ); curve->appearanceChanged.connect( this, &RimSummaryPlot::curveAppearanceChanged ); curve->stackingChanged.connect( this, &RimSummaryPlot::curveStackingChanged ); curve->stackingColorsChanged.connect( this, &RimSummaryPlot::curveStackingColorsChanged ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::disconnectCurveSignals( RimSummaryCurve* curve ) { curve->dataChanged.disconnect( this ); curve->visibilityChanged.disconnect( this ); curve->appearanceChanged.disconnect( this ); curve->stackingChanged.disconnect( this ); curve->stackingColorsChanged.disconnect( this ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::curveDataChanged( const caf::SignalEmitter* emitter ) { loadDataAndUpdate(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::curveVisibilityChanged( const caf::SignalEmitter* emitter, bool visible ) { loadDataAndUpdate(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::curveAppearanceChanged( const caf::SignalEmitter* emitter ) { if ( plotWidget() ) { plotWidget()->scheduleReplot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::curveStackingChanged( const caf::SignalEmitter* emitter, bool stacked ) { loadDataAndUpdate(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::curveStackingColorsChanged( const caf::SignalEmitter* emitter, bool stackWithPhaseColors ) { loadDataAndUpdate(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::connectAxisSignals( RimPlotAxisProperties* axis ) { axis->settingsChanged.connect( this, &RimSummaryPlot::axisSettingsChanged ); axis->logarithmicChanged.connect( this, &RimSummaryPlot::axisLogarithmicChanged ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::axisSettingsChanged( const caf::SignalEmitter* emitter ) { updateAxes(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::axisLogarithmicChanged( const caf::SignalEmitter* emitter, bool isLogarithmic ) { loadDataAndUpdate(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::deleteAllGridTimeHistoryCurves() { m_gridTimeHistoryCurves.deleteAllChildObjects(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::setDescription( const QString& description ) { m_description = description; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimSummaryPlot::description() const { return m_description(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::enableAutoPlotTitle( bool enable ) { m_useAutoPlotTitle = enable; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimSummaryPlot::autoPlotTitle() const { return m_useAutoPlotTitle; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::handleDroppedObjects( const std::vector& objects ) { for ( auto obj : objects ) { auto summaryAdr = dynamic_cast( obj ); if ( summaryAdr ) { if ( summaryAdr->isEnsemble() ) { // TODO: Add drop support for ensemble curves } else { auto summaryCase = RiaSummaryTools::summaryCaseById( summaryAdr->caseId() ); if ( summaryCase ) { auto* newCurve = new RimSummaryCurve(); newCurve->setSummaryCaseY( summaryCase ); newCurve->setSummaryAddressYAndApplyInterpolation( summaryAdr->address() ); addCurveNoUpdate( newCurve ); newCurve->loadDataAndUpdate( true ); } } } } updateConnectedEditors(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::onPlotZoomed() { setAutoScaleXEnabled( false ); setAutoScaleYEnabled( false ); updateZoomFromParentPlot(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { { auto group = uiOrdering.addNewGroup( "Data Source" ); m_sourceStepping()->uiOrdering( uiConfigName, *group ); } caf::PdmUiGroup* mainOptions = uiOrdering.addNewGroup( "General Plot Options" ); mainOptions->setCollapsedByDefault( true ); #ifdef USE_QTCHARTS mainOptions->add( &m_useQtChartsPlot ); #endif if ( isMdiWindow() ) { mainOptions->add( &m_showPlotTitle ); if ( m_showPlotTitle ) { mainOptions->add( &m_useAutoPlotTitle ); mainOptions->add( &m_description ); } } else { mainOptions->add( &m_useAutoPlotTitle ); mainOptions->add( &m_description ); mainOptions->add( &m_rowSpan ); mainOptions->add( &m_colSpan ); } m_description.uiCapability()->setUiReadOnly( m_useAutoPlotTitle ); if ( isMdiWindow() ) { uiOrderingForPlotLayout( uiConfigName, *mainOptions ); } mainOptions->add( &m_normalizeCurveYValues ); uiOrdering.skipRemainingFields( true ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuPlotWidget* RimSummaryPlot::doCreatePlotViewWidget( QWidget* mainWindowParent ) { if ( !plotWidget() ) { #ifdef USE_QTCHARTS bool useQtCharts = m_useQtChartsPlot; auto regTestRunner = RiaRegressionTestRunner::instance(); if ( regTestRunner->isRunningRegressionTests() ) { if ( regTestRunner->overridePlotEngine() == RiaRegressionTest::PlotEngine::USE_QWT ) useQtCharts = false; else if ( regTestRunner->overridePlotEngine() == RiaRegressionTest::PlotEngine::USER_QTCHARTS ) useQtCharts = true; } if ( useQtCharts ) { m_summaryPlot = std::make_unique( this, mainWindowParent ); } else { m_summaryPlot = std::make_unique( this, mainWindowParent ); } #else m_summaryPlot = std::make_unique( this, mainWindowParent ); #endif for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) { curve->setParentPlotNoReplot( plotWidget() ); } for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) { curve->setParentPlotNoReplot( plotWidget() ); } if ( m_summaryCurveCollection ) { m_summaryCurveCollection->setParentPlotAndReplot( plotWidget() ); } if ( m_ensembleCurveSetCollection ) { m_ensembleCurveSetCollection->setParentPlotAndReplot( plotWidget() ); } this->connect( plotWidget(), SIGNAL( plotZoomed() ), SLOT( onPlotZoomed() ) ); updatePlotTitle(); } return plotWidget(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::deleteViewWidget() { cleanupBeforeClose(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::initAfterRead() { RimViewWindow::initAfterRead(); if ( RimProject::current()->isProjectFileVersionEqualOrOlderThan( "2021.10.2" ) ) { auto copyAxis = [this]( RiuPlotAxis axis, auto axisProperties ) { QString data = axisProperties->writeObjectToXmlString(); axisPropertiesForPlotAxis( axis )->readObjectFromXmlString( data, caf::PdmDefaultObjectFactory::instance() ); }; copyAxis( RiuPlotAxis::defaultLeft(), m_leftYAxisProperties_OBSOLETE.v() ); copyAxis( RiuPlotAxis::defaultRight(), m_rightYAxisProperties_OBSOLETE.v() ); if ( m_isCrossPlot ) copyAxis( RiuPlotAxis::defaultBottom(), m_bottomAxisProperties_OBSOLETE.v() ); else copyAxis( RiuPlotAxis::defaultBottom(), m_timeAxisProperties_OBSOLETE.v() ); } for ( auto axisProperties : m_axisProperties ) { auto plotAxisProperties = dynamic_cast( axisProperties.p() ); if ( plotAxisProperties ) { connectAxisSignals( plotAxisProperties ); } } for ( auto curve : summaryCurves() ) { connectCurveSignals( curve ); } updateStackedCurveData(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateNameHelperWithCurveData( RimSummaryPlotNameHelper* nameHelper ) const { if ( !nameHelper ) return; nameHelper->clear(); std::vector addresses; std::vector sumCases; std::vector ensembleCases; if ( m_summaryCurveCollection && m_summaryCurveCollection->isCurvesVisible() ) { for ( RimSummaryCurve* curve : m_summaryCurveCollection->curves() ) { if ( curve->summaryAddressY().category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED ) { RiaSummaryTools::getSummaryCasesAndAddressesForCalculation( curve->summaryAddressY().id(), sumCases, addresses ); } else { addresses.push_back( curve->summaryAddressY() ); sumCases.push_back( curve->summaryCaseY() ); if ( curve->summaryCaseX() ) { sumCases.push_back( curve->summaryCaseX() ); if ( curve->summaryAddressX().category() != RifEclipseSummaryAddress::SUMMARY_INVALID ) { addresses.push_back( curve->summaryAddressX() ); } } } } } for ( auto curveSet : m_ensembleCurveSetCollection->curveSets() ) { addresses.push_back( curveSet->summaryAddress() ); ensembleCases.push_back( curveSet->summaryCaseCollection() ); } nameHelper->clear(); nameHelper->appendAddresses( addresses ); nameHelper->setSummaryCases( sumCases ); nameHelper->setEnsembleCases( ensembleCases ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::doUpdateLayout() { updateFonts(); this->loadDataAndUpdate(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::detachAllPlotItems() { if ( m_summaryCurveCollection ) { m_summaryCurveCollection->detachPlotCurves(); } if ( m_ensembleCurveSetCollection ) { m_ensembleCurveSetCollection->detachPlotCurves(); } for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) { curve->detach(); } for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) { curve->detach(); } m_plotInfoLabel->detach(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateCurveNames() { if ( m_summaryCurveCollection->isCurvesVisible() ) { for ( auto c : summaryCurves() ) { if ( c->isCurveVisible() ) c->updateCurveNameNoLegendUpdate(); } } for ( auto curveSet : m_ensembleCurveSetCollection->curveSets() ) { curveSet->updateEnsembleLegendItem(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::detachAllCurves() { detachAllPlotItems(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::reattachAllCurves() { if ( m_summaryCurveCollection ) { m_summaryCurveCollection->reattachPlotCurves(); } m_ensembleCurveSetCollection->reattachPlotCurves(); for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) { curve->reattach(); } for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) { curve->reattach(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::handleKeyPressEvent( QKeyEvent* keyEvent ) { if ( !keyEvent ) return; if ( RiuTreeViewEventFilter::activateFeatureFromKeyEvent( keyEvent ) ) { return; } RimSummaryPlotSourceStepping* sourceStepping = sourceSteppingObjectForKeyEventHandling(); if ( !sourceStepping ) return; if ( keyEvent->key() == Qt::Key_PageUp ) { if ( keyEvent->modifiers() & Qt::ShiftModifier ) { sourceStepping->applyPrevCase(); keyEvent->accept(); } else if ( keyEvent->modifiers() & Qt::ControlModifier ) { sourceStepping->applyPrevOtherIdentifier(); keyEvent->accept(); } else { sourceStepping->applyPrevQuantity(); keyEvent->accept(); } } else if ( keyEvent->key() == Qt::Key_PageDown ) { if ( keyEvent->modifiers() & Qt::ShiftModifier ) { sourceStepping->applyNextCase(); keyEvent->accept(); } else if ( keyEvent->modifiers() & Qt::ControlModifier ) { sourceStepping->applyNextOtherIdentifier(); keyEvent->accept(); } else { sourceStepping->applyNextQuantity(); keyEvent->accept(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::onCurveCollectionChanged( const SignalEmitter* emitter ) { updateStackedCurveData(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimSummaryPlotSourceStepping* RimSummaryPlot::sourceSteppingObjectForKeyEventHandling() const { return m_sourceStepping; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::fieldsToShowInToolbar() { std::vector toolBarFields; { auto fields = m_textCurveSetEditor->fieldsToShowInToolbar(); toolBarFields.insert( std::end( toolBarFields ), std::begin( fields ), std::end( fields ) ); } bool anyFieldsAvailableForSummary = false; auto sourceObject = sourceSteppingObjectForKeyEventHandling(); if ( sourceObject ) { auto fields = sourceObject->fieldsToShowInToolbar(); toolBarFields.insert( std::end( toolBarFields ), std::begin( fields ), std::end( fields ) ); anyFieldsAvailableForSummary = !fields.empty(); } if ( !anyFieldsAvailableForSummary ) { // Show ensemble stepping if no fields are available from summary stepping auto fields = ensembleCurveSetCollection()->fieldsToShowInToolbar(); toolBarFields.insert( std::end( toolBarFields ), std::begin( fields ), std::end( fields ) ); } return toolBarFields; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::setAutoScaleXEnabled( bool enabled ) { for ( auto ap : m_axisProperties ) { if ( ap->plotAxisType().axis() == RiaDefines::PlotAxis::PLOT_AXIS_TOP || ap->plotAxisType().axis() == RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM ) { ap->setAutoZoom( enabled ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::setAutoScaleYEnabled( bool enabled ) { for ( auto ap : m_axisProperties ) { if ( ap->plotAxisType().axis() == RiaDefines::PlotAxis::PLOT_AXIS_LEFT || ap->plotAxisType().axis() == RiaDefines::PlotAxis::PLOT_AXIS_RIGHT ) { ap->setAutoZoom( enabled ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RimSummaryPlot::curveCount() const { return m_summaryCurveCollection->curves().size() + m_gridTimeHistoryCurves.size() + m_asciiDataCurves.size(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimSummaryPlot::isDeletable() const { RimMultiPlot* plotWindow = nullptr; firstAncestorOrThisOfType( plotWindow ); return plotWindow == nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::plotAxes() const { std::vector axisProps; for ( auto ap : m_axisProperties ) { axisProps.push_back( ap ); } return axisProps; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::assignPlotAxis( RimSummaryCurve* curve ) { enum class AxisAssignmentStrategy { ALL_TO_LEFT, ALL_TO_RIGHT, ALTERNATING }; RiaDefines::PlotAxis plotAxis = RiaDefines::PlotAxis::PLOT_AXIS_LEFT; auto strategy = AxisAssignmentStrategy::ALTERNATING; if ( strategy == AxisAssignmentStrategy::ALTERNATING ) { size_t axisCountLeft = 0; size_t axisCountRight = 0; for ( const auto& ap : m_axisProperties ) { if ( ap->plotAxisType().axis() == RiaDefines::PlotAxis::PLOT_AXIS_LEFT ) axisCountLeft++; else if ( ap->plotAxisType().axis() == RiaDefines::PlotAxis::PLOT_AXIS_RIGHT ) axisCountRight++; } if ( axisCountLeft > axisCountRight ) plotAxis = RiaDefines::PlotAxis::PLOT_AXIS_RIGHT; } else if ( strategy == AxisAssignmentStrategy::ALL_TO_LEFT ) { plotAxis = RiaDefines::PlotAxis::PLOT_AXIS_LEFT; } else if ( strategy == AxisAssignmentStrategy::ALL_TO_RIGHT ) { plotAxis = RiaDefines::PlotAxis::PLOT_AXIS_RIGHT; } RiuPlotAxis newPlotAxis = RiuPlotAxis::defaultLeft(); if ( plotWidget() && plotWidget()->isMultiAxisSupported() ) { newPlotAxis = plotWidget()->createNextPlotAxis( plotAxis ); QString axisObjectName = "New Axis"; if ( !curve->summaryAddressY().uiText().empty() ) axisObjectName = QString::fromStdString( curve->summaryAddressY().uiText() ); auto* newAxisProperties = new RimPlotAxisProperties; newAxisProperties->setNameAndAxis( axisObjectName, newPlotAxis.axis(), newPlotAxis.index() ); m_axisProperties.push_back( newAxisProperties ); connectAxisSignals( newAxisProperties ); } curve->setLeftOrRightAxisY( newPlotAxis ); }