///////////////////////////////////////////////////////////////////////////////// // // 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 "RiaFieldHandleTools.h" #include "RiaSummaryCurveAnalyzer.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 "RimPlotAxisProperties.h" #include "RimProject.h" #include "RimSummaryCase.h" #include "RimSummaryCurve.h" #include "RimSummaryCurveCollection.h" #include "RimSummaryCurveFilter.h" #include "RimSummaryPlotAxisFormatter.h" #include "RimSummaryPlotCollection.h" #include "RimSummaryPlotFilterTextCurveSetEditor.h" #include "RimSummaryPlotNameHelper.h" #include "RimSummaryTimeAxisProperties.h" #include "RiuPlotMainWindowTools.h" #include "RiuSummaryQwtPlot.h" #include "RiuTreeViewEventFilter.h" #include "cvfColor3.h" #include "cafPdmFieldScriptingCapability.h" #include "cafPdmUiCheckBoxEditor.h" #include "cafPdmUiTreeOrdering.h" #include "cafSelectionManager.h" #include "qwt_abstract_legend.h" #include "qwt_legend.h" #include "qwt_plot_curve.h" #include "qwt_plot_renderer.h" #include "qwt_plot_textlabel.h" #include "qwt_scale_engine.h" #include #include #include #include #include #include #include #include #include CAF_PDM_SOURCE_INIT( RimSummaryPlot, "SummaryPlot" ); //-------------------------------------------------------------------------------------------------- /// Internal types //-------------------------------------------------------------------------------------------------- enum class ResampleAlgorithm { NONE, DATA_DECIDES, PERIOD_END }; struct CurveData { QString name; RifEclipseSummaryAddress address; std::vector values; }; class CurvesData { public: CurvesData() : resamplePeriod( RiaQDateTimeTools::DateTimePeriod::NONE ) { } void clear() { resamplePeriod = RiaQDateTimeTools::DateTimePeriod::NONE; caseNames.clear(); timeSteps.clear(); allCurveData.clear(); } RiaQDateTimeTools::DateTimePeriod resamplePeriod; std::vector caseNames; std::vector> timeSteps; std::vector> allCurveData; }; //-------------------------------------------------------------------------------------------------- /// Internal functions //-------------------------------------------------------------------------------------------------- enum SummaryCurveType { CURVE_TYPE_GRID = 0x1, CURVE_TYPE_OBSERVED = 0x2 }; void populateSummaryCurvesData( std::vector curves, SummaryCurveType curveType, CurvesData* curvesData ); void populateTimeHistoryCurvesData( std::vector curves, CurvesData* curvesData ); void populateAsciiDataCurvesData( std::vector curves, CurvesData* curvesData ); void prepareCaseCurvesForExport( RiaQDateTimeTools::DateTimePeriod period, ResampleAlgorithm algorithm, const CurvesData& inputCurvesData, CurvesData* resultCurvesData ); void appendToExportDataForCase( QString& out, const std::vector& timeSteps, const std::vector& curveData ); void appendToExportData( QString& out, const std::vector& curvesData, bool showTimeAsLongString ); CurvesData concatCurvesData( const std::vector& curvesData ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimSummaryPlot::RimSummaryPlot() : RimPlot() { 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", "", "", "" ); 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.uiCapability()->setUiHidden( 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_leftYAxisProperties, "LeftYAxisProperties", "Left Y Axis", "", "", "" ); m_leftYAxisProperties.uiCapability()->setUiTreeHidden( true ); m_leftYAxisProperties = new RimPlotAxisProperties; m_leftYAxisProperties->setNameAndAxis( "Left Y-Axis", QwtPlot::yLeft ); CAF_PDM_InitFieldNoDefault( &m_rightYAxisProperties, "RightYAxisProperties", "Right Y Axis", "", "", "" ); m_rightYAxisProperties.uiCapability()->setUiTreeHidden( true ); m_rightYAxisProperties = new RimPlotAxisProperties; m_rightYAxisProperties->setNameAndAxis( "Right Y-Axis", QwtPlot::yRight ); CAF_PDM_InitFieldNoDefault( &m_bottomAxisProperties, "BottomAxisProperties", "Bottom X Axis", "", "", "" ); m_bottomAxisProperties.uiCapability()->setUiTreeHidden( true ); m_bottomAxisProperties = new RimPlotAxisProperties; m_bottomAxisProperties->setNameAndAxis( "Bottom X-Axis", QwtPlot::xBottom ); connectAxisSignals( m_leftYAxisProperties() ); connectAxisSignals( m_rightYAxisProperties() ); connectAxisSignals( m_bottomAxisProperties() ); CAF_PDM_InitFieldNoDefault( &m_timeAxisProperties, "TimeAxisProperties", "Time Axis", "", "", "" ); m_timeAxisProperties.uiCapability()->setUiTreeHidden( true ); m_timeAxisProperties = new RimSummaryTimeAxisProperties; CAF_PDM_InitFieldNoDefault( &m_textCurveSetEditor, "SummaryPlotFilterTextCurveSetEditor", "Text Filter Curve Creator", "", "", "" ); m_textCurveSetEditor.uiCapability()->setUiTreeHidden( true ); m_textCurveSetEditor = new RimSummaryPlotFilterTextCurveSetEditor; m_isCrossPlot = false; m_nameHelperAllCurves.reset( new RimSummaryPlotNameHelper ); setPlotInfoLabel( "Filters Active" ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimSummaryPlot::~RimSummaryPlot() { removeMdiWindowFromMdiArea(); cleanupBeforeClose(); delete m_summaryCurveCollection; delete m_ensembleCurveSetCollection; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateAxes() { updateYAxis( RiaDefines::PlotAxis::PLOT_AXIS_LEFT ); updateYAxis( RiaDefines::PlotAxis::PLOT_AXIS_RIGHT ); if ( m_timeAxisProperties() && m_plotWidget ) { m_plotWidget->updateAnnotationObjects( m_timeAxisProperties() ); } if ( m_leftYAxisProperties() && m_plotWidget ) { m_plotWidget->updateAnnotationObjects( m_leftYAxisProperties() ); } if ( m_isCrossPlot ) { updateBottomXAxis(); } else { updateTimeAxis(); } m_plotWidget->scheduleReplot(); updateZoomInQwt(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimSummaryPlot::isLogarithmicScaleEnabled( RiaDefines::PlotAxis plotAxis ) const { return yAxisPropertiesLeftOrRight( plotAxis )->isLogarithmicScaleEnabled(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimSummaryTimeAxisProperties* RimSummaryPlot::timeAxisProperties() { return m_timeAxisProperties(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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 m_plotWidget; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuQwtPlotWidget* RimSummaryPlot::viewer() { return m_plotWidget; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimSummaryPlot::asciiDataForPlotExport() const { return asciiDataForSummaryPlotExport( RiaQDateTimeTools::DateTimePeriod::YEAR, false ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimSummaryPlot::asciiDataForSummaryPlotExport( RiaQDateTimeTools::DateTimePeriod resamplingPeriod, bool showTimeAsLongString ) const { QString out; // Summary and time history (from grid) curves { std::vector curves; this->descendantsIncludingThisOfType( curves ); CurvesData summaryCurvesGridData; CurvesData summaryCurvesObsData; populateSummaryCurvesData( curves, CURVE_TYPE_GRID, &summaryCurvesGridData ); populateSummaryCurvesData( curves, CURVE_TYPE_OBSERVED, &summaryCurvesObsData ); CurvesData timeHistoryCurvesData; populateTimeHistoryCurvesData( m_gridTimeHistoryCurves.childObjects(), &timeHistoryCurvesData ); // Export observed data appendToExportData( out, { summaryCurvesObsData }, showTimeAsLongString ); std::vector exportData( 2 ); // Summary grid data for export prepareCaseCurvesForExport( resamplingPeriod, ResampleAlgorithm::DATA_DECIDES, summaryCurvesGridData, &exportData[0] ); // Time history data for export prepareCaseCurvesForExport( resamplingPeriod, ResampleAlgorithm::PERIOD_END, timeHistoryCurvesData, &exportData[1] ); // Export resampled summary and time history data appendToExportData( out, exportData, showTimeAsLongString ); } // Pasted observed data { CurvesData asciiCurvesData; populateAsciiDataCurvesData( m_asciiDataCurves.childObjects(), &asciiCurvesData ); appendToExportData( out, { asciiCurvesData }, showTimeAsLongString ); } return out; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- caf::PdmObject* RimSummaryPlot::findPdmObjectFromQwtCurve( const QwtPlotCurve* qwtCurve ) const { for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) { if ( curve->qwtPlotCurve() == qwtCurve ) { return curve; } } for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) { if ( curve->qwtPlotCurve() == qwtCurve ) { return curve; } } if ( m_summaryCurveCollection ) { RimSummaryCurve* foundCurve = m_summaryCurveCollection->findRimCurveFromQwtCurve( qwtCurve ); if ( foundCurve ) { m_summaryCurveCollection->setCurrentSummaryCurve( foundCurve ); return foundCurve; } } if ( m_ensembleCurveSetCollection ) { RimSummaryCurve* foundCurve = m_ensembleCurveSetCollection->findRimCurveFromQwtCurve( qwtCurve ); 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; } else if ( axis == QwtPlot::yRight ) { itemToSelect = m_rightYAxisProperties; } else if ( axis == QwtPlot::xBottom ) { if ( m_isCrossPlot ) { itemToSelect = m_bottomAxisProperties; } else { itemToSelect = m_timeAxisProperties; } } 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::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( RiaDefines::PlotAxis 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; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::curveSets() const { return ensembleCurveSetCollection()->curveSets(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updatePlotTitle() { updateNameHelperWithCurveData( m_nameHelperAllCurves.get() ); if ( m_useAutoPlotTitle ) { m_description = m_nameHelperAllCurves->plotTitle(); } updateCurveNames(); updateMdiWindowTitle(); if ( m_plotWidget ) { QString plotTitle = description(); m_plotWidget->setPlotTitle( plotTitle ); m_plotWidget->setPlotTitleEnabled( m_showPlotTitle && !isSubPlot() ); m_plotWidget->scheduleReplot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const RimSummaryPlotNameHelper* RimSummaryPlot::activePlotTitleHelperAllCurves() const { if ( m_useAutoPlotTitle() ) { return m_nameHelperAllCurves.get(); } return nullptr; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimSummaryPlot::generatedPlotTitleFromAllCurves() const { RimSummaryPlotNameHelper nameHelper; updateNameHelperWithCurveData( &nameHelper ); return nameHelper.plotTitle(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::copyAxisPropertiesFromOther( const RimSummaryPlot& sourceSummaryPlot ) { { QString data = sourceSummaryPlot.yAxisPropertiesLeftOrRight( RiaDefines::PlotAxis::PLOT_AXIS_LEFT )->writeObjectToXmlString(); yAxisPropertiesLeftOrRight( RiaDefines::PlotAxis::PLOT_AXIS_LEFT ) ->readObjectFromXmlString( data, caf::PdmDefaultObjectFactory::instance() ); } { QString data = sourceSummaryPlot.yAxisPropertiesLeftOrRight( RiaDefines::PlotAxis::PLOT_AXIS_RIGHT )->writeObjectToXmlString(); yAxisPropertiesLeftOrRight( RiaDefines::PlotAxis::PLOT_AXIS_RIGHT ) ->readObjectFromXmlString( data, caf::PdmDefaultObjectFactory::instance() ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateAll() { if ( m_plotWidget ) { updatePlotTitle(); m_plotWidget->updateLegend(); updateAxes(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateLegend() { if ( m_plotWidget ) { m_plotWidget->setInternalLegendVisible( m_showPlotLegends && !isSubPlot() ); } reattachAllCurves(); if ( m_plotWidget ) { m_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 ) { if ( show ) m_plotInfoLabel->attach( m_plotWidget ); 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::updateYAxis( RiaDefines::PlotAxis plotAxis ) { if ( !m_plotWidget ) return; QwtPlot::Axis qwtAxis = QwtPlot::yLeft; if ( plotAxis == RiaDefines::PlotAxis::PLOT_AXIS_LEFT ) { qwtAxis = QwtPlot::yLeft; } else { qwtAxis = QwtPlot::yRight; } RimPlotAxisProperties* yAxisProperties = yAxisPropertiesLeftOrRight( plotAxis ); if ( yAxisProperties->isActive() && hasVisibleCurvesForAxis( plotAxis ) ) { m_plotWidget->enableAxis( qwtAxis, true ); std::set timeHistoryQuantities; for ( auto c : visibleTimeHistoryCurvesForAxis( plotAxis ) ) { timeHistoryQuantities.insert( c->quantityName() ); } RimSummaryPlotAxisFormatter calc( yAxisProperties, visibleSummaryCurvesForAxis( plotAxis ), {}, visibleAsciiDataCurvesForAxis( plotAxis ), timeHistoryQuantities ); calc.applyAxisPropertiesToPlot( m_plotWidget ); } else { m_plotWidget->enableAxis( qwtAxis, false ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateZoomForAxis( RiaDefines::PlotAxis plotAxis ) { if ( plotAxis == RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM ) { if ( m_isCrossPlot ) { if ( m_bottomAxisProperties->isAutoZoom() ) { m_plotWidget->setAxisAutoScale( QwtPlot::xBottom, true ); } else { m_plotWidget->setAxisScale( QwtPlot::xBottom, m_bottomAxisProperties->visibleRangeMin(), m_bottomAxisProperties->visibleRangeMax() ); } } else { if ( m_timeAxisProperties->isAutoZoom() ) { m_plotWidget->setAxisAutoScale( QwtPlot::xBottom, true ); } else { m_plotWidget->setAxisScale( QwtPlot::xBottom, m_timeAxisProperties->visibleRangeMin(), m_timeAxisProperties->visibleRangeMax() ); } } } else { RimPlotAxisProperties* yAxisProps = yAxisPropertiesLeftOrRight( plotAxis ); if ( yAxisProps->isAutoZoom() ) { m_plotWidget->setAxisIsLogarithmic( yAxisProps->qwtPlotAxisType(), yAxisProps->isLogarithmicScaleEnabled ); if ( yAxisProps->isLogarithmicScaleEnabled ) { std::vector plotCurves; for ( RimSummaryCurve* c : visibleSummaryCurvesForAxis( plotAxis ) ) { plotCurves.push_back( c->qwtPlotCurve() ); } for ( RimGridTimeHistoryCurve* c : visibleTimeHistoryCurvesForAxis( plotAxis ) ) { plotCurves.push_back( c->qwtPlotCurve() ); } for ( RimAsciiDataCurve* c : visibleAsciiDataCurvesForAxis( plotAxis ) ) { plotCurves.push_back( c->qwtPlotCurve() ); } double min, max; RimPlotAxisLogRangeCalculator calc( QwtPlot::yLeft, plotCurves ); calc.computeAxisRange( &min, &max ); if ( yAxisProps->isAxisInverted() ) { std::swap( min, max ); } m_plotWidget->setAxisScale( yAxisProps->qwtPlotAxisType(), min, max ); } else { m_plotWidget->setAxisAutoScale( yAxisProps->qwtPlotAxisType(), true ); } } else { m_plotWidget->setAxisScale( yAxisProps->qwtPlotAxisType(), yAxisProps->visibleRangeMin(), yAxisProps->visibleRangeMax() ); } m_plotWidget->axisScaleEngine( yAxisProps->qwtPlotAxisType() ) ->setAttribute( QwtScaleEngine::Inverted, yAxisProps->isAxisInverted() ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::visibleSummaryCurvesForAxis( RiaDefines::PlotAxis plotAxis ) const { std::vector curves; if ( plotAxis == 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( RiaDefines::PlotAxis 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; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimPlotAxisProperties* RimSummaryPlot::yAxisPropertiesLeftOrRight( RiaDefines::PlotAxis leftOrRightPlotAxis ) const { RimPlotAxisProperties* yAxisProps = nullptr; if ( leftOrRightPlotAxis == RiaDefines::PlotAxis::PLOT_AXIS_LEFT ) { yAxisProps = m_leftYAxisProperties(); } else { yAxisProps = m_rightYAxisProperties(); } CVF_ASSERT( yAxisProps ); return yAxisProps; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::visibleTimeHistoryCurvesForAxis( RiaDefines::PlotAxis plotAxis ) const { std::vector curves; for ( auto c : m_gridTimeHistoryCurves ) { if ( c->isCurveVisible() ) { if ( c->yAxis() == plotAxis || plotAxis == RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM ) { curves.push_back( c ); } } } return curves; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::visibleAsciiDataCurvesForAxis( RiaDefines::PlotAxis plotAxis ) const { std::vector curves; for ( auto c : m_asciiDataCurves ) { if ( c->isCurveVisible() ) { if ( c->yAxis() == plotAxis || plotAxis == RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM ) { curves.push_back( c ); } } } return curves; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateTimeAxis() { if ( !m_plotWidget ) return; if ( !m_timeAxisProperties->isActive() ) { m_plotWidget->enableAxis( QwtPlot::xBottom, false ); return; } if ( m_timeAxisProperties->timeMode() == RimSummaryTimeAxisProperties::DATE ) { RiaQDateTimeTools::DateFormatComponents dateComponents = m_timeAxisProperties->dateComponents(); RiaQDateTimeTools::TimeFormatComponents timeComponents = m_timeAxisProperties->timeComponents(); QString dateFormat = m_timeAxisProperties->dateFormat(); QString timeFormat = m_timeAxisProperties->timeFormat(); m_plotWidget->useDateBasedTimeAxis( dateFormat, timeFormat, dateComponents, timeComponents ); } else { m_plotWidget->useTimeBasedTimeAxis(); } m_plotWidget->enableAxis( QwtPlot::xBottom, true ); { Qt::AlignmentFlag alignment = Qt::AlignCenter; if ( m_timeAxisProperties->titlePosition() == RimPlotAxisPropertiesInterface::AXIS_TITLE_END ) { alignment = Qt::AlignRight; } m_plotWidget->setAxisFontsAndAlignment( QwtPlot::xBottom, m_timeAxisProperties->titleFontSize(), m_timeAxisProperties->valuesFontSize(), true, alignment ); m_plotWidget->setAxisTitleText( QwtPlot::xBottom, m_timeAxisProperties->title() ); m_plotWidget->setAxisTitleEnabled( QwtPlot::xBottom, m_timeAxisProperties->showTitle ); { RimSummaryTimeAxisProperties::LegendTickmarkCount tickmarkCountEnum = m_timeAxisProperties->majorTickmarkCount(); int maxTickmarkCount = 8; switch ( tickmarkCountEnum ) { 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; } m_plotWidget->setAxisMaxMajor( QwtPlot::xBottom, maxTickmarkCount ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateBottomXAxis() { if ( !m_plotWidget ) return; QwtPlot::Axis qwtAxis = QwtPlot::xBottom; RimPlotAxisProperties* bottomAxisProperties = m_bottomAxisProperties(); if ( bottomAxisProperties->isActive() ) { m_plotWidget->enableAxis( qwtAxis, true ); std::set timeHistoryQuantities; RimSummaryPlotAxisFormatter calc( bottomAxisProperties, visibleSummaryCurvesForAxis( RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM ), {}, visibleAsciiDataCurvesForAxis( RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM ), timeHistoryQuantities ); calc.applyAxisPropertiesToPlot( m_plotWidget ); } else { m_plotWidget->enableAxis( qwtAxis, false ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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 ); updateZoomInQwt(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::addCurveAndUpdate( RimSummaryCurve* curve ) { if ( curve ) { m_summaryCurveCollection->addCurve( curve ); connectCurveSignals( curve ); if ( m_plotWidget ) { curve->setParentQwtPlotAndReplot( m_plotWidget ); this->updateAxes(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::addCurveNoUpdate( RimSummaryCurve* curve ) { if ( curve ) { m_summaryCurveCollection->addCurve( curve ); connectCurveSignals( curve ); if ( m_plotWidget ) { curve->setParentQwtPlotNoReplot( m_plotWidget ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::insertCurve( RimSummaryCurve* curve, size_t insertAtPosition ) { if ( curve ) { m_summaryCurveCollection->insertCurve( curve, insertAtPosition ); connectCurveSignals( curve ); if ( m_plotWidget ) { curve->setParentQwtPlotNoReplot( m_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 && m_plotWidget && curveSet->legendFrame() ) { m_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 ( m_plotWidget ) { curve->setParentQwtPlotAndReplot( m_plotWidget ); this->updateAxes(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::addGridTimeHistoryCurveNoUpdate( RimGridTimeHistoryCurve* curve ) { CVF_ASSERT( curve ); m_gridTimeHistoryCurves.push_back( curve ); if ( m_plotWidget ) { curve->setParentQwtPlotNoReplot( m_plotWidget ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RimSummaryPlot::gridTimeHistoryCurves() const { return m_gridTimeHistoryCurves.childObjects(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::addAsciiDataCruve( RimAsciiDataCurve* curve ) { CVF_ASSERT( curve ); m_asciiDataCurves.push_back( curve ); if ( m_plotWidget ) { curve->setParentQwtPlotAndReplot( m_plotWidget ); this->updateAxes(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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_normalizeCurveYValues ) { this->loadDataAndUpdate(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::childFieldChangedByUi( const caf::PdmFieldHandle* changedChildField ) { updateStackedCurveData(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateStackedCurveData() { updateStackedCurveDataForAxis( RiaDefines::PlotAxis::PLOT_AXIS_LEFT ); updateStackedCurveDataForAxis( RiaDefines::PlotAxis::PLOT_AXIS_RIGHT ); if ( m_plotWidget ) { reattachAllCurves(); m_plotWidget->scheduleReplot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateStackedCurveDataForAxis( RiaDefines::PlotAxis 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 ( m_plotWidget ) { QPixmap pix = m_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 { caf::PdmUiTreeOrdering* axisFolder = uiTreeOrdering.add( "Axes", ":/Axes16x16.png" ); if ( m_isCrossPlot ) { axisFolder->add( &m_bottomAxisProperties ); } else { axisFolder->add( &m_timeAxisProperties ); } axisFolder->add( &m_leftYAxisProperties ); axisFolder->add( &m_rightYAxisProperties ); 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 ( m_plotWidget ) { m_plotWidget->setInternalLegendVisible( m_showPlotLegends && !isSubPlot() ); m_plotWidget->setLegendFontSize( legendFontSize() ); m_plotWidget->updateLegend(); } this->updateAxes(); m_textCurveSetEditor->updateTextFilter(); updateStackedCurveData(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateZoomInQwt() { if ( m_plotWidget ) { updateZoomForAxis( RiaDefines::PlotAxis::PLOT_AXIS_BOTTOM ); updateZoomForAxis( RiaDefines::PlotAxis::PLOT_AXIS_LEFT ); updateZoomForAxis( RiaDefines::PlotAxis::PLOT_AXIS_RIGHT ); m_plotWidget->updateAxes(); updateZoomFromQwt(); m_plotWidget->scheduleReplot(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateZoomFromQwt() { if ( !m_plotWidget ) return; QwtInterval leftAxis = m_plotWidget->axisRange( QwtPlot::yLeft ); QwtInterval rightAxis = m_plotWidget->axisRange( QwtPlot::yRight ); QwtInterval timeAxis = m_plotWidget->axisRange( QwtPlot::xBottom ); m_leftYAxisProperties->visibleRangeMax = leftAxis.maxValue(); m_leftYAxisProperties->visibleRangeMin = leftAxis.minValue(); m_leftYAxisProperties->updateConnectedEditors(); m_rightYAxisProperties->visibleRangeMax = rightAxis.maxValue(); m_rightYAxisProperties->visibleRangeMin = rightAxis.minValue(); m_rightYAxisProperties->updateConnectedEditors(); if ( m_isCrossPlot ) { m_bottomAxisProperties->visibleRangeMax = timeAxis.maxValue(); m_bottomAxisProperties->visibleRangeMin = timeAxis.minValue(); m_bottomAxisProperties->updateConnectedEditors(); } else { m_timeAxisProperties->setVisibleRangeMin( timeAxis.minValue() ); m_timeAxisProperties->setVisibleRangeMax( timeAxis.maxValue() ); m_timeAxisProperties->updateConnectedEditors(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::set RimSummaryPlot::allPlotAxes() const { return { m_timeAxisProperties, m_bottomAxisProperties, m_leftYAxisProperties, m_rightYAxisProperties }; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::cleanupBeforeClose() { detachAllPlotItems(); if ( m_plotWidget ) { m_plotWidget->setParent( nullptr ); delete m_plotWidget; m_plotWidget = nullptr; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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 ( m_plotWidget ) { m_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::setAsCrossPlot() { m_isCrossPlot = true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::onPlotZoomed() { setAutoScaleXEnabled( false ); setAutoScaleYEnabled( false ); updateZoomFromQwt(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) { if ( !m_isCrossPlot ) { caf::PdmUiGroup* textCurveFilterGroup = uiOrdering.addNewGroup( "Text-Based Curve Creation" ); m_textCurveSetEditor->uiOrdering( uiConfigName, *textCurveFilterGroup ); } caf::PdmUiGroup* mainOptions = uiOrdering.addNewGroup( "General Plot Options" ); mainOptions->setCollapsedByDefault( true ); 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 ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiuQwtPlotWidget* RimSummaryPlot::doCreatePlotViewWidget( QWidget* mainWindowParent ) { if ( !m_plotWidget ) { m_plotWidget = new RiuSummaryQwtPlot( this, mainWindowParent ); for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) { curve->setParentQwtPlotNoReplot( m_plotWidget ); } for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) { curve->setParentQwtPlotNoReplot( m_plotWidget ); } if ( m_summaryCurveCollection ) { m_summaryCurveCollection->setParentQwtPlotAndReplot( m_plotWidget ); } if ( m_ensembleCurveSetCollection ) { m_ensembleCurveSetCollection->setParentQwtPlotAndReplot( m_plotWidget ); } this->connect( m_plotWidget, SIGNAL( plotZoomed() ), SLOT( onPlotZoomed() ) ); updatePlotTitle(); } return m_plotWidget; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::deleteViewWidget() { cleanupBeforeClose(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::initAfterRead() { RimViewWindow::initAfterRead(); 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->detachQwtCurves(); } m_ensembleCurveSetCollection->detachQwtCurves(); for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) { curve->detachQwtCurve(); } for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) { curve->detachQwtCurve(); } m_plotInfoLabel->detach(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::updateCurveNames() { if ( m_summaryCurveCollection->isCurvesVisible() ) { for ( auto c : summaryCurves() ) { c->updateCurveNameNoLegendUpdate(); } } for ( auto curveSet : m_ensembleCurveSetCollection->curveSets() ) { curveSet->updateEnsembleLegendItem(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::detachAllCurves() { detachAllPlotItems(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::reattachAllCurves() { if ( m_summaryCurveCollection ) { m_summaryCurveCollection->reattachQwtCurves(); } m_ensembleCurveSetCollection->reattachQwtCurves(); for ( RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves ) { curve->reattachQwtCurve(); } for ( RimAsciiDataCurve* curve : m_asciiDataCurves ) { curve->reattachQwtCurve(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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 { caf::PdmObjectHandle* selectedObj = dynamic_cast( caf::SelectionManager::instance()->selectedItem() ); if ( selectedObj ) { RimEnsembleCurveSetCollection* ensembleCurveSetColl = nullptr; selectedObj->firstAncestorOrThisOfType( ensembleCurveSetColl ); if ( ensembleCurveSetColl ) { return ensembleCurveSetCollection()->sourceSteppingObject(); } } return summaryCurveCollection()->sourceSteppingObject( RimSummaryPlotSourceStepping::Y_AXIS ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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 ) { if ( m_isCrossPlot ) { m_bottomAxisProperties->setAutoZoom( enabled ); } else { m_timeAxisProperties->setAutoZoom( enabled ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimSummaryPlot::setAutoScaleYEnabled( bool enabled ) { m_leftYAxisProperties->setAutoZoom( enabled ); m_rightYAxisProperties->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; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void populateTimeHistoryCurvesData( std::vector curves, CurvesData* curvesData ) { CVF_ASSERT( curvesData ); curvesData->caseNames.clear(); curvesData->timeSteps.clear(); curvesData->allCurveData.clear(); for ( RimGridTimeHistoryCurve* curve : curves ) { if ( !curve->isCurveVisible() ) continue; QString curveCaseName = curve->caseName(); size_t casePosInList = cvf::UNDEFINED_SIZE_T; for ( size_t i = 0; i < curvesData->caseNames.size(); i++ ) { if ( curveCaseName == curvesData->caseNames[i] ) casePosInList = i; } CurveData curveData = { curve->curveExportDescription(), RifEclipseSummaryAddress(), curve->yValues() }; if ( casePosInList == cvf::UNDEFINED_SIZE_T ) { curvesData->caseNames.push_back( curveCaseName ); curvesData->timeSteps.push_back( curve->timeStepValues() ); curvesData->allCurveData.push_back( std::vector( { curveData } ) ); } else { curvesData->allCurveData[casePosInList].push_back( curveData ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void populateAsciiDataCurvesData( std::vector curves, CurvesData* curvesData ) { CVF_ASSERT( curvesData ); curvesData->caseNames.clear(); curvesData->timeSteps.clear(); curvesData->allCurveData.clear(); for ( RimAsciiDataCurve* curve : curves ) { if ( !curve->isCurveVisible() ) continue; size_t casePosInList = cvf::UNDEFINED_SIZE_T; CurveData curveData = { curve->curveExportDescription(), RifEclipseSummaryAddress(), curve->yValues() }; if ( casePosInList == cvf::UNDEFINED_SIZE_T ) { curvesData->caseNames.push_back( "" ); curvesData->timeSteps.push_back( curve->timeSteps() ); curvesData->allCurveData.push_back( std::vector( { curveData } ) ); } else { curvesData->allCurveData[casePosInList].push_back( curveData ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void populateSummaryCurvesData( std::vector curves, SummaryCurveType curveType, CurvesData* curvesData ) { CVF_ASSERT( curvesData ); curvesData->caseNames.clear(); curvesData->timeSteps.clear(); curvesData->allCurveData.clear(); for ( RimSummaryCurve* curve : curves ) { bool isObservedCurve = curve->summaryCaseY() ? curve->summaryCaseY()->isObservedData() : false; if ( !curve->isCurveVisible() ) continue; if ( isObservedCurve && ( curveType & CURVE_TYPE_OBSERVED ) == 0 ) continue; if ( !isObservedCurve && ( curveType & CURVE_TYPE_GRID ) == 0 ) continue; if ( !curve->summaryCaseY() ) continue; QString curveCaseName = curve->summaryCaseY()->displayCaseName(); size_t casePosInList = cvf::UNDEFINED_SIZE_T; for ( size_t i = 0; i < curvesData->caseNames.size(); i++ ) { if ( curveCaseName == curvesData->caseNames[i] ) casePosInList = i; } CurveData curveData = { curve->curveExportDescription(), curve->summaryAddressY(), curve->valuesY() }; CurveData errorCurveData; // Error data auto errorValues = curve->errorValuesY(); bool hasErrorData = !errorValues.empty(); if ( hasErrorData ) { errorCurveData.name = curve->curveExportDescription( curve->errorSummaryAddressY() ); errorCurveData.address = curve->errorSummaryAddressY(); errorCurveData.values = errorValues; } if ( casePosInList == cvf::UNDEFINED_SIZE_T || curve->summaryAddressY().category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED ) { // Create a section with separate time axis data if // 1. Case is not referenced before, or // 2. We have calculated data, and it we cannot assume identical time axis auto curveDataList = std::vector( { curveData } ); if ( hasErrorData ) curveDataList.push_back( errorCurveData ); curvesData->caseNames.push_back( curveCaseName ); curvesData->timeSteps.push_back( curve->timeStepsY() ); curvesData->allCurveData.push_back( curveDataList ); } else { // Append curve data to previously created curvesdata object curvesData->allCurveData[casePosInList].push_back( curveData ); if ( hasErrorData ) curvesData->allCurveData[casePosInList].push_back( errorCurveData ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void prepareCaseCurvesForExport( RiaQDateTimeTools::DateTimePeriod period, ResampleAlgorithm algorithm, const CurvesData& inputCurvesData, CurvesData* resultCurvesData ) { RiaTimeHistoryCurveResampler resampler; resultCurvesData->clear(); if ( period != RiaQDateTimeTools::DateTimePeriod::NONE ) { // Prepare result data resultCurvesData->resamplePeriod = period; for ( size_t i = 0; i < inputCurvesData.caseNames.size(); i++ ) { // Shortcuts to input data auto& caseName = inputCurvesData.caseNames[i]; auto& caseTimeSteps = inputCurvesData.timeSteps[i]; auto& caseCurveData = inputCurvesData.allCurveData[i]; // Prepare result data resultCurvesData->caseNames.push_back( caseName ); resultCurvesData->allCurveData.push_back( std::vector() ); for ( auto& curveDataItem : caseCurveData ) { resampler.setCurveData( curveDataItem.values, caseTimeSteps ); if ( RiaSummaryTools::hasAccumulatedData( curveDataItem.address ) || algorithm == ResampleAlgorithm::PERIOD_END ) { resampler.resampleAndComputePeriodEndValues( period ); } else { resampler.resampleAndComputeWeightedMeanValues( period ); } auto cd = curveDataItem; cd.values = resampler.resampledValues(); auto& currResultCurveDataList = resultCurvesData->allCurveData[i]; currResultCurveDataList.push_back( cd ); } resultCurvesData->timeSteps.push_back( resampler.resampledTimeSteps() ); } } else { *resultCurvesData = inputCurvesData; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void appendToExportDataForCase( QString& out, const std::vector& timeSteps, const std::vector& curveData ) { for ( size_t j = 0; j < timeSteps.size(); j++ ) // time steps & data points { if ( j == 0 ) { out += "Date and time"; for ( size_t k = 0; k < curveData.size(); k++ ) // curves { out += "\t" + ( curveData[k].name ); } } out += "\n"; out += QDateTime::fromSecsSinceEpoch( timeSteps[j] ).toUTC().toString( "yyyy-MM-dd hh:mm:ss " ); for ( size_t k = 0; k < curveData.size(); k++ ) // curves { QString valueText; if ( j < curveData[k].values.size() ) { valueText = QString::number( curveData[k].values[j], 'g', RimSummaryPlot::precision() ); } out += "\t" + valueText.rightJustified( 13 ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void appendToExportData( QString& out, const std::vector& curvesData, bool showTimeAsLongString ) { CurvesData data = concatCurvesData( curvesData ); if ( data.resamplePeriod != RiaQDateTimeTools::DateTimePeriod::NONE ) { time_t minTimeStep = std::numeric_limits::max(); time_t maxTimeStep = 0; for ( auto& timeSteps : data.timeSteps ) { if ( !timeSteps.empty() ) { if ( timeSteps.front() < minTimeStep ) minTimeStep = timeSteps.front(); if ( timeSteps.back() > maxTimeStep ) maxTimeStep = timeSteps.back(); } } auto allTimeSteps = RiaTimeHistoryCurveResampler::timeStepsFromTimeRange( data.resamplePeriod, minTimeStep, maxTimeStep ); out += "\n\n"; out += "Date and time"; for ( size_t i = 0; i < data.caseNames.size(); i++ ) { for ( size_t j = 0; j < data.allCurveData[i].size(); j++ ) { out += "\t" + data.allCurveData[i][j].name; } } out += "\n"; std::vector currIndexes( data.caseNames.size() ); for ( auto& i : currIndexes ) i = 0; for ( auto timeStep : allTimeSteps ) { QDateTime timseStepUtc = QDateTime::fromSecsSinceEpoch( timeStep ).toUTC(); QString timeText; if ( showTimeAsLongString ) { timeText = timseStepUtc.toString( "yyyy-MM-dd hh:mm:ss " ); } else { // Subtract one day to make sure the period is reported using the previous period as label QDateTime oneDayEarlier = timseStepUtc.addDays( -1 ); QChar zeroChar( 48 ); switch ( data.resamplePeriod ) { default: // Fall through to NONE case RiaQDateTimeTools::DateTimePeriod::NONE: timeText = timseStepUtc.toString( "yyyy-MM-dd hh:mm:ss " ); break; case RiaQDateTimeTools::DateTimePeriod::DAY: timeText = oneDayEarlier.toString( "yyyy-MM-dd " ); break; case RiaQDateTimeTools::DateTimePeriod::WEEK: { timeText = oneDayEarlier.toString( "yyyy" ); int weekNumber = oneDayEarlier.date().weekNumber(); timeText += QString( "-W%1" ).arg( weekNumber, 2, 10, zeroChar ); break; } case RiaQDateTimeTools::DateTimePeriod::MONTH: timeText = oneDayEarlier.toString( "yyyy-MM" ); break; case RiaQDateTimeTools::DateTimePeriod::QUARTER: { int quarterNumber = oneDayEarlier.date().month() / 3; timeText = oneDayEarlier.toString( "yyyy" ); timeText += QString( "-Q%1" ).arg( quarterNumber ); break; } case RiaQDateTimeTools::DateTimePeriod::HALFYEAR: { int halfYearNumber = oneDayEarlier.date().month() / 6; timeText = oneDayEarlier.toString( "yyyy" ); timeText += QString( "-H%1" ).arg( halfYearNumber ); break; } case RiaQDateTimeTools::DateTimePeriod::YEAR: timeText = oneDayEarlier.toString( "yyyy" ); break; case RiaQDateTimeTools::DateTimePeriod::DECADE: timeText = oneDayEarlier.toString( "yyyy" ); break; } } out += timeText; for ( size_t i = 0; i < data.caseNames.size(); i++ ) // cases { // Check is time step exists in curr case size_t& currIndex = currIndexes[i]; bool timeStepExists = currIndex < data.timeSteps[i].size() && timeStep == data.timeSteps[i][currIndex]; for ( size_t j = 0; j < data.allCurveData[i].size(); j++ ) // vectors { QString valueText; if ( timeStepExists ) { valueText = QString::number( data.allCurveData[i][j].values[currIndex], 'g', RimSummaryPlot::precision() ); } else { valueText = "NULL"; } out += "\t" + valueText.rightJustified( 13 ); } if ( timeStepExists && currIndex < data.timeSteps[i].size() ) currIndex++; } out += "\n"; } } else { for ( size_t i = 0; i < data.caseNames.size(); i++ ) { out += "\n\n"; if ( !data.caseNames[i].isEmpty() ) { out += "Case: " + data.caseNames[i]; out += "\n"; } appendToExportDataForCase( out, data.timeSteps[i], data.allCurveData[i] ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- CurvesData concatCurvesData( const std::vector& curvesData ) { CVF_ASSERT( !curvesData.empty() ); RiaQDateTimeTools::DateTimePeriod period = curvesData.front().resamplePeriod; CurvesData resultCurvesData; resultCurvesData.resamplePeriod = period; for ( auto curvesDataItem : curvesData ) { if ( curvesDataItem.caseNames.empty() ) continue; CVF_ASSERT( curvesDataItem.resamplePeriod == period ); resultCurvesData.caseNames.insert( resultCurvesData.caseNames.end(), curvesDataItem.caseNames.begin(), curvesDataItem.caseNames.end() ); resultCurvesData.timeSteps.insert( resultCurvesData.timeSteps.end(), curvesDataItem.timeSteps.begin(), curvesDataItem.timeSteps.end() ); resultCurvesData.allCurveData.insert( resultCurvesData.allCurveData.end(), curvesDataItem.allCurveData.begin(), curvesDataItem.allCurveData.end() ); } return resultCurvesData; }