From 7879fe186d9a93814d08f1ed38e675748ac8145e Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sun, 23 Jun 2019 15:18:17 +0200 Subject: [PATCH] #4136 Export of Flow Characteristics : Create text for export and add context menu --- .../RicShowPlotDataFeature.cpp | 46 ++++-- .../Flow/RimFlowCharacteristicsPlot.cpp | 145 ++++++++++++++++-- .../Flow/RimFlowCharacteristicsPlot.h | 3 + .../RiuFlowCharacteristicsPlot.cpp | 31 +++- .../RiuFlowCharacteristicsPlot.h | 1 + 5 files changed, 200 insertions(+), 26 deletions(-) diff --git a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp index eafbaca629..3da8d88955 100644 --- a/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp +++ b/ApplicationCode/Commands/ApplicationCommands/RicShowPlotDataFeature.cpp @@ -1,23 +1,24 @@ ///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017 Statoil ASA -// +// // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License at +// +// See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RicShowPlotDataFeature.h" +#include "RiaFeatureCommandContext.h" #include "RiaGuiApplication.h" #include "RimGridCrossPlot.h" @@ -36,7 +37,6 @@ #include - CAF_CMD_SOURCE_INIT(RicShowPlotDataFeature, "RicShowPlotDataFeature"); //-------------------------------------------------------------------------------------------------- @@ -166,11 +166,17 @@ private: /// /// /// RicShowPlotDataFeature -/// -/// +/// +/// //-------------------------------------------------------------------------------------------------- bool RicShowPlotDataFeature::isCommandEnabled() { + QString content = RiaFeatureCommandContext::instance()->contentString(); + if (!content.isEmpty()) + { + return true; + } + auto selectedSummaryPlots = caf::selectedObjectsByType(); if (selectedSummaryPlots.size() > 0) { @@ -195,15 +201,29 @@ bool RicShowPlotDataFeature::isCommandEnabled() } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RicShowPlotDataFeature::onActionTriggered(bool isChecked) { + QString content = RiaFeatureCommandContext::instance()->contentString(); + if (!content.isEmpty()) + { + QString title = "Data Content"; + { + QString titleCandidate = RiaFeatureCommandContext::instance()->titleString(); + if (!titleCandidate.isEmpty()) titleCandidate = titleCandidate; + } + + RicShowPlotDataFeature::showTextWindow(title, content); + + return; + } + this->disableModelChangeContribution(); std::vector selectedSummaryPlots = caf::selectedObjectsByType(); - std::vector wellLogPlots = caf::selectedObjectsByType(); - std::vector crossPlots = caf::selectedObjectsByType(); + std::vector wellLogPlots = caf::selectedObjectsByType(); + std::vector crossPlots = caf::selectedObjectsByType(); if (selectedSummaryPlots.size() == 0 && wellLogPlots.size() == 0 && crossPlots.size() == 0) { CVF_ASSERT(false); @@ -223,7 +243,7 @@ void RicShowPlotDataFeature::onActionTriggered(bool isChecked) for (RimWellLogPlot* wellLogPlot : wellLogPlots) { QString title = wellLogPlot->description(); - QString text = wellLogPlot->asciiDataForPlotExport(); + QString text = wellLogPlot->asciiDataForPlotExport(); RicShowPlotDataFeature::showTextWindow(title, text); } @@ -235,7 +255,7 @@ void RicShowPlotDataFeature::onActionTriggered(bool isChecked) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RicShowPlotDataFeature::setupActionLook(QAction* actionToSetup) { @@ -244,7 +264,7 @@ void RicShowPlotDataFeature::setupActionLook(QAction* actionToSetup) } //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- void RicShowPlotDataFeature::showTabbedTextWindow(RiuTabbedTextProvider* textProvider) { diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp index f1229faefb..7d005f00b6 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.cpp @@ -18,6 +18,8 @@ #include "RimFlowCharacteristicsPlot.h" +#include "RifEclipseDataTableFormatter.h" + #include "RigActiveCellInfo.h" #include "RigEclipseCaseData.h" #include "RigFlowDiagResults.h" @@ -555,19 +557,22 @@ void RimFlowCharacteristicsPlot::onLoadDataAndUpdate() if (m_flowDiagSolution && m_flowCharPlotWidget) { - RigFlowDiagResults* flowResult = m_flowDiagSolution->flowDiagResults(); - std::vector calculatedTimesteps = flowResult->calculatedTimeSteps(RigFlowDiagResultAddress::PHASE_ALL); + RigFlowDiagResults* flowResult = m_flowDiagSolution->flowDiagResults(); - if (m_timeStepSelectionType == SELECTED) { - for (int tsIdx : m_selectedTimeSteps()) - { - m_flowDiagSolution()->flowDiagResults()->maxAbsPairFlux(tsIdx); - } - calculatedTimesteps = m_selectedTimeSteps(); - } + std::vector calculatedTimesteps = flowResult->calculatedTimeSteps(RigFlowDiagResultAddress::PHASE_ALL); - m_currentlyPlottedTimeSteps = calculatedTimesteps; + if (m_timeStepSelectionType == SELECTED) + { + for (int tsIdx : m_selectedTimeSteps()) + { + m_flowDiagSolution()->flowDiagResults()->maxAbsPairFlux(tsIdx); + } + calculatedTimesteps = m_selectedTimeSteps(); + } + + m_currentlyPlottedTimeSteps = calculatedTimesteps; + } std::vector timeStepDates = m_case->timeStepDates(); QStringList timeStepStrings = m_case->timeStepStrings(); @@ -586,7 +591,7 @@ void RimFlowCharacteristicsPlot::onLoadDataAndUpdate() std::map timeStepToFlowResultMap; - for (int timeStepIdx : calculatedTimesteps) + for (int timeStepIdx : m_currentlyPlottedTimeSteps) { if (m_cellFilter() == RigFlowDiagResults::CELLS_VISIBLE) { @@ -622,9 +627,11 @@ void RimFlowCharacteristicsPlot::onLoadDataAndUpdate() lorenzVals[timeStepIdx] = timeStepToFlowResultMap[timeStepIdx].m_lorenzCoefficient; } + m_timeStepToFlowResultMap = timeStepToFlowResultMap; + m_flowCharPlotWidget->setLorenzCurve(timeStepStrings, timeStepDates, lorenzVals); - for (int timeStepIdx : calculatedTimesteps) + for (int timeStepIdx : m_currentlyPlottedTimeSteps) { const auto& flowCharResults = timeStepToFlowResultMap[timeStepIdx]; @@ -652,6 +659,120 @@ void RimFlowCharacteristicsPlot::viewGeometryUpdated() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +double interpolate(std::vector& xData, std::vector& yData, double x, bool extrapolate) +{ + size_t itemCount = xData.size(); + + size_t index = 0; + if (x >= xData[itemCount - 2]) + { + index = itemCount - 2; + } + else + { + while (x > xData[index + 1]) + index++; + } + double xLeft = xData[index]; + double yLeft = yData[index]; + double xRight = xData[index + 1]; + double yRight = yData[index + 1]; + + if (!extrapolate) + { + if (x < xLeft) yRight = yLeft; + if (x > xRight) yLeft = yRight; + } + + double dydx = (yRight - yLeft) / (xRight - xLeft); + + return yLeft + dydx * (x - xLeft); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString RimFlowCharacteristicsPlot::curveDataAsText() const +{ + QString tableText; + + QTextStream stream(&tableText); + RifEclipseDataTableFormatter formatter(stream); + + std::vector header = { + RifEclipseOutputTableColumn("Date"), + RifEclipseOutputTableColumn("Storage Capacity"), + RifEclipseOutputTableColumn("Flow Capacity"), + RifEclipseOutputTableColumn("Sweep Efficiency"), + RifEclipseOutputTableColumn("Dimensionless Time"), + RifEclipseOutputTableColumn("Lorentz Coefficient"), + }; + + formatter.header(header); + + std::vector timeStepDates = m_case->timeStepDates(); + + std::vector storageCapacitySamplingValues = {0.08, 0.1, 0.2, 0.3, 0.4}; + size_t sampleCount = storageCapacitySamplingValues.size(); + + for (const auto& timeIndex : m_currentlyPlottedTimeSteps) + { + QString dateString = timeStepDates[timeIndex].toString("yyyy-MM-DD"); + + auto a = m_timeStepToFlowResultMap.find(timeIndex); + if (a != m_timeStepToFlowResultMap.end()) + { + auto storageCapacityValues = a->second.m_storageCapFlowCapCurve.first; + auto flowCapacityValues = a->second.m_storageCapFlowCapCurve.second; + + bool extrapolate = false; + std::vector flowCapacitySamplingValues; + for (const auto storageCapacity : storageCapacitySamplingValues) + { + { + double flowCapacity = interpolate(storageCapacityValues, flowCapacityValues, storageCapacity, extrapolate); + flowCapacitySamplingValues.push_back(flowCapacity); + } + } + + auto dimensionLessTimeValues = a->second.m_dimensionlessTimeSweepEfficiencyCurve.first; + auto sweepEffValues = a->second.m_dimensionlessTimeSweepEfficiencyCurve.second; + + std::vector dimensionLessTimeSamplingValues; + std::vector sweepEffSamplingValues; + double range = dimensionLessTimeValues.back() - dimensionLessTimeValues[0]; + double step = range / sampleCount; + for (size_t i = 0; i < sampleCount; i++) + { + double dimensionLessTimeValue = i * step; + dimensionLessTimeSamplingValues.push_back(dimensionLessTimeValue); + double sweepEffValue = interpolate(dimensionLessTimeValues, sweepEffValues, dimensionLessTimeValue, extrapolate); + sweepEffSamplingValues.push_back(sweepEffValue); + } + + auto lorentz = a->second.m_lorenzCoefficient; + + for (size_t i = 0; i < sampleCount; i++) + { + formatter.add(dateString); + formatter.add(storageCapacitySamplingValues[i]); + formatter.add(flowCapacitySamplingValues[i]); + formatter.add(sweepEffSamplingValues[i]); + formatter.add(dimensionLessTimeSamplingValues[i]); + formatter.add(lorentz); + formatter.rowCompleted(); + } + } + } + + formatter.tableCompleted(); + + return tableText; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h index e5a1df6dcd..78fc196a87 100644 --- a/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h +++ b/ApplicationCode/ProjectDataModel/Flow/RimFlowCharacteristicsPlot.h @@ -67,6 +67,8 @@ public: void deleteViewWidget() override; void viewGeometryUpdated(); + QString curveDataAsText() const; + enum TimeSelectionType { ALL_AVAILABLE, @@ -107,6 +109,7 @@ private: caf::PdmField m_maxTof; std::vector m_currentlyPlottedTimeSteps; + std::map m_timeStepToFlowResultMap; QPointer m_flowCharPlotWidget; }; diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp index 80bff9f85b..e47ea231b8 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.cpp @@ -20,6 +20,7 @@ #include "RiaApplication.h" #include "RiaColorTables.h" +#include "RiaFeatureCommandContext.h" #include "RiaFontCache.h" #include "RiaPreferences.h" @@ -34,6 +35,8 @@ #include "cvfBase.h" #include "cvfColor3.h" +#include "cafCmdFeatureMenuBuilder.h" + #include "qwt_date.h" #include "qwt_legend.h" #include "qwt_plot.h" @@ -316,7 +319,33 @@ QSize RiuFlowCharacteristicsPlot::minimumSizeHint() const } //-------------------------------------------------------------------------------------------------- -/// +/// +//-------------------------------------------------------------------------------------------------- +void RiuFlowCharacteristicsPlot::contextMenuEvent(QContextMenuEvent* event) +{ + if (m_plotDefinition) + { + QString curveDataAsText = m_plotDefinition->curveDataAsText(); + + QString dialogTitle = "Flow Characteristics"; + + RiaFeatureCommandContextTextHelper helper(dialogTitle, curveDataAsText); + + caf::CmdFeatureMenuBuilder menuBuilder; + menuBuilder << "RicShowPlotDataFeature"; + + QMenu menu; + menuBuilder.appendToMenu(&menu); + + if (menu.actions().size() > 0) + { + menu.exec(event->globalPos()); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// //-------------------------------------------------------------------------------------------------- QSize RiuFlowCharacteristicsPlot::sizeHint() const { diff --git a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h index 13d2b05bce..3b3aa8e62a 100644 --- a/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h +++ b/ApplicationCode/UserInterface/RiuFlowCharacteristicsPlot.h @@ -68,6 +68,7 @@ public: protected: QSize sizeHint() const override; QSize minimumSizeHint() const override; + void contextMenuEvent(QContextMenuEvent* event) override; private: void setDefaults();