mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
810 lines
34 KiB
C++
810 lines
34 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2019- Equinor ASA
|
|
//
|
|
// ResInsight is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
|
// for more details.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "RicSummaryPlotFeatureImpl.h"
|
|
|
|
#include "RimSummaryCurve.h"
|
|
#include "RimSummaryPlot.h"
|
|
#include "RimSummaryPlotCollection.h"
|
|
#include "RimProject.h"
|
|
#include "RimMainPlotCollection.h"
|
|
#include "RimSummaryCase.h"
|
|
#include "RimEnsembleCurveSet.h"
|
|
#include "RimEnsembleCurveSetCollection.h"
|
|
|
|
#include "RiuPlotMainWindowTools.h"
|
|
#include "RiuMainWindow.h"
|
|
|
|
#include "RiaApplication.h"
|
|
#include "RiaColorTables.h"
|
|
#include "RiaLogging.h"
|
|
#include "RiaPreferences.h"
|
|
#include "RiaEclipseFileNameTools.h"
|
|
#include "RiaDefines.h"
|
|
|
|
#include "RifSummaryReaderInterface.h"
|
|
|
|
#include "RicImportGeneralDataFeature.h"
|
|
#include "RicCreateSummaryCaseCollectionFeature.h"
|
|
#include "RicImportSummaryCasesFeature.h"
|
|
|
|
#include <QStringList>
|
|
#include <QFileInfo>
|
|
#include <QRegularExpression>
|
|
#include "RiaImportEclipseCaseTools.h"
|
|
#include "RimEclipseCase.h"
|
|
#include "RimGridTimeHistoryCurve.h"
|
|
#include "WellLogCommands/RicWellLogPlotCurveFeatureImpl.h"
|
|
#include "RimEclipseResultCase.h"
|
|
#include "RimOilField.h"
|
|
#include "RimEclipseCaseCollection.h"
|
|
#include "RigEclipseResultAddress.h"
|
|
#include "RigEclipseCaseData.h"
|
|
#include "RigCaseCellResultsData.h"
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RimSummaryCurve* RicSummaryPlotFeatureImpl::addDefaultCurveToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase)
|
|
{
|
|
if (plot)
|
|
{
|
|
RifEclipseSummaryAddress defaultAddressToUse;
|
|
|
|
QString curvesTextFilter = RiaApplication::instance()->preferences()->defaultSummaryCurvesTextFilter;
|
|
QStringList curveFilters = curvesTextFilter.split(";", QString::SkipEmptyParts);
|
|
|
|
if ( curveFilters.size() )
|
|
{
|
|
const std::set<RifEclipseSummaryAddress>& addrs = summaryCase->summaryReader()->allResultAddresses();
|
|
|
|
for ( const auto & addr : addrs )
|
|
{
|
|
const QString& filter = curveFilters[0];
|
|
{
|
|
if ( addr.isUiTextMatchingFilterText(filter) )
|
|
{
|
|
defaultAddressToUse = addr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RimSummaryCurve* newCurve = new RimSummaryCurve();
|
|
|
|
// Use same counting as RicNewSummaryEnsembleCurveSetFeature::onActionTriggered
|
|
cvf::Color3f curveColor = RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f(plot->singleColorCurveCount());
|
|
newCurve->setColor(curveColor);
|
|
|
|
plot->addCurveNoUpdate(newCurve);
|
|
|
|
if (summaryCase)
|
|
{
|
|
newCurve->setSummaryCaseY(summaryCase);
|
|
}
|
|
|
|
newCurve->setSummaryAddressYAndApplyInterpolation(defaultAddressToUse);
|
|
|
|
return newCurve;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<RimSummaryCurve*> RicSummaryPlotFeatureImpl::addDefaultCurvesToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase)
|
|
{
|
|
std::vector<RimSummaryCurve*> defaultCurves;
|
|
|
|
QString curvesTextFilter = RiaApplication::instance()->preferences()->defaultSummaryCurvesTextFilter;
|
|
QStringList curveFilters = curvesTextFilter.split(";", QString::SkipEmptyParts);
|
|
|
|
return addCurvesFromAddressFiltersToPlot(curveFilters, plot, summaryCase, false);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RicSummaryPlotFeatureImpl::ensureAtLeastOnePlot(RimSummaryPlotCollection* summaryPlotCollection, RimSummaryCase* summaryCase)
|
|
{
|
|
if (summaryPlotCollection && summaryCase)
|
|
{
|
|
if (summaryPlotCollection->summaryPlots.empty())
|
|
{
|
|
createDefaultSummaryPlot(summaryCase);
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RicSummaryPlotFeatureImpl::createDefaultSummaryPlot( RimSummaryCase* summaryCase)
|
|
{
|
|
RimSummaryPlotCollection* summaryPlotCollection = RiaApplication::instance()->project()->mainPlotCollection->summaryPlotCollection();
|
|
|
|
if (summaryPlotCollection && summaryCase && !RiaApplication::instance()->preferences()->defaultSummaryCurvesTextFilter().isEmpty())
|
|
{
|
|
auto plot = summaryPlotCollection->createSummaryPlotWithAutoTitle();
|
|
|
|
std::vector<RimSummaryCurve*> curves = RicSummaryPlotFeatureImpl::addDefaultCurvesToPlot(plot, summaryCase);
|
|
|
|
plot->applyDefaultCurveAppearances();
|
|
plot->loadDataAndUpdate();
|
|
|
|
summaryPlotCollection->updateConnectedEditors();
|
|
|
|
caf::PdmObject* itemToSelect = plot;
|
|
if (curves.size()) itemToSelect = curves[0];
|
|
|
|
RiuPlotMainWindowTools::setExpanded(itemToSelect);
|
|
RiuPlotMainWindowTools::selectAsCurrentItem(itemToSelect);
|
|
}
|
|
}
|
|
|
|
RimSummaryCurve* createHistoryCurve(const RifEclipseSummaryAddress& addr, RimSummaryCase* summaryCasesToUse)
|
|
{
|
|
RifEclipseSummaryAddress historyAddr = addr;
|
|
historyAddr.setQuantityName(historyAddr.quantityName() + "H");
|
|
if ( summaryCasesToUse->summaryReader()->allResultAddresses().count(historyAddr) )
|
|
{
|
|
RimSummaryCurve* historyCurve = new RimSummaryCurve();
|
|
historyCurve->setSummaryCaseY(summaryCasesToUse);
|
|
historyCurve->setSummaryAddressYAndApplyInterpolation(historyAddr);
|
|
return historyCurve;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
class RigGridCellResultAddress
|
|
{
|
|
public:
|
|
RigGridCellResultAddress()
|
|
: gridIndex(-1)
|
|
, i(-1)
|
|
, j(-1)
|
|
, k(-1)
|
|
{}
|
|
|
|
RigGridCellResultAddress(size_t gridIndex,
|
|
size_t i,
|
|
size_t j,
|
|
size_t k,
|
|
const RigEclipseResultAddress & eclipseResultAddress)
|
|
: gridIndex(gridIndex)
|
|
, i(i)
|
|
, j(j)
|
|
, k(k)
|
|
, eclipseResultAddress(eclipseResultAddress)
|
|
{}
|
|
|
|
// Using zero based ijk
|
|
|
|
size_t gridIndex;
|
|
size_t i;
|
|
size_t j;
|
|
size_t k;
|
|
RigEclipseResultAddress eclipseResultAddress;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<RigGridCellResultAddress> createGridCellAddressesFromFilter(const QString& text)
|
|
{
|
|
std::vector<RigGridCellResultAddress> addresses;
|
|
QStringList addressParts = text.split(":");
|
|
|
|
if (addressParts.size() > 1)
|
|
{
|
|
QString resultVarName = addressParts[0];
|
|
size_t gridIdx = 0;
|
|
if (addressParts.size() > 2)
|
|
{
|
|
gridIdx = addressParts[1].toULong();
|
|
}
|
|
|
|
QString ijkText = addressParts.back();
|
|
QStringList ijkTextParts = ijkText.split(",");
|
|
if (ijkTextParts.size() == 3)
|
|
{
|
|
bool isOk = true;
|
|
bool allOk = true;
|
|
size_t i = ijkTextParts[0].toULong(&isOk);
|
|
allOk &= isOk;
|
|
size_t j = ijkTextParts[1].toULong(&isOk);
|
|
allOk &= isOk;
|
|
size_t k = ijkTextParts[2].toULong(&isOk);
|
|
allOk &= isOk;
|
|
|
|
if (allOk)
|
|
{
|
|
addresses.emplace_back(RigGridCellResultAddress(gridIdx, i-1, j-1, k-1, RigEclipseResultAddress(resultVarName )));
|
|
}
|
|
}
|
|
}
|
|
|
|
return addresses;
|
|
}
|
|
|
|
std::vector<RimEclipseCase*> openEclipseCasesForCellPlotting(QStringList gridFileNames)
|
|
{
|
|
std::vector<RimEclipseCase*> openedCases;
|
|
|
|
RiaApplication* app = RiaApplication::instance();
|
|
RimProject* project = app->project();
|
|
RimEclipseCaseCollection* analysisModels = project->activeOilField()->analysisModels();
|
|
for ( const QString& fileName: gridFileNames )
|
|
{
|
|
QFileInfo gridFileInfo(fileName);
|
|
|
|
if (!gridFileInfo.exists()) continue;
|
|
|
|
QString caseName = gridFileInfo.completeBaseName();
|
|
|
|
RimEclipseResultCase* rimResultReservoir = new RimEclipseResultCase();
|
|
rimResultReservoir->setCaseInfo(caseName, fileName);
|
|
|
|
analysisModels->cases.push_back(rimResultReservoir);
|
|
|
|
if ( !rimResultReservoir->openReserviorCase() )
|
|
{
|
|
analysisModels->removeCaseFromAllGroups(rimResultReservoir);
|
|
|
|
delete rimResultReservoir;
|
|
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
openedCases.push_back(rimResultReservoir);
|
|
}
|
|
}
|
|
|
|
analysisModels->updateConnectedEditors();
|
|
|
|
return openedCases;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RicSummaryPlotFeatureImpl::createSummaryPlotsFromArgumentLine(const QStringList & arguments)
|
|
{
|
|
// Split arguments in options, vectors and filenames
|
|
|
|
QStringList options;
|
|
QStringList allCurveAddressFilters;
|
|
QStringList summaryFileNames;
|
|
QStringList gridFileNames;
|
|
QString ensembleColoringParameter;
|
|
|
|
std::set<QString> validOptions = {"-help", "-h", "-nl", "-s", "-n", "-e", "-c", "-cl"};
|
|
|
|
for (int optionIdx = 0; optionIdx < arguments.size(); ++optionIdx)
|
|
{
|
|
if (arguments[optionIdx].startsWith("-"))
|
|
{
|
|
if (arguments[optionIdx] == "-help")
|
|
{
|
|
RiaApplication::instance()->showFormattedTextInMessageBoxOrConsole(
|
|
"The --summaryplot option has the following syntax:\n"
|
|
"\n"
|
|
"[<plotOptions>] <eclipsesummaryvectorfilters> [<eclipsedatafiles>]\n"
|
|
"\n"
|
|
"It Creates one summary plot for each of the the summary vectors matched by the <eclipsesummaryvectorfilters> using all the <eclipsedatafiles> in each plot.\n"
|
|
"The <eclipsesummaryvectorfilters> has the syntax <vectorname>[:<item>[:<subitem>[:i,j,k]]] and can be repeated.\n"
|
|
"Wildcards can also be used, eg. \"WOPT:*\" to select the total oil production from all the wells.\n"
|
|
"The <eclipsedatafiles> can be written with or without extension. Only the corresponding SMSPEC file will be opened for each case.\n"
|
|
"\n"
|
|
"The summary plot options are: \n"
|
|
" -help\t Show this help text and ignore the rest of the options.\n"
|
|
" -h\t Include history vectors. Will be read from the summary file if the vectors exist.\n"
|
|
" \t Only history vectors from the first summary case in the project will be included.\n"
|
|
" -nl\t Omit legend in plot.\n"
|
|
" -s\t Create only one plot including all the defined vectors and cases.\n"
|
|
" -n\t Scale all curves into the range 0.0-1.0. Useful when using -s.\n"
|
|
" -e\t Import all the cases as an ensemble, and create ensemble curves sets instead of single curves.\n"
|
|
" -c <parametername>\t Same as -e, but colors the curves by the ensemble parameter <parametername> . \n"
|
|
" -cl <parametername>\t Same as -c, but uses logarithmic legend.\n"
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
if ( validOptions.count(arguments[optionIdx]) )
|
|
{
|
|
options.push_back(arguments[optionIdx]);
|
|
|
|
if ( arguments[optionIdx] == "-c" || arguments[optionIdx] == "-cl" )
|
|
{
|
|
optionIdx++;
|
|
if ( optionIdx < arguments.size() ) ensembleColoringParameter = arguments[optionIdx];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RiaLogging::error("The summaryplot option: \"" + arguments[optionIdx] + "\" is unknown.");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RiaEclipseFileNameTools nameTool(arguments[optionIdx]);
|
|
QString smSpecFileName = nameTool.findRelatedSummarySpecFile();
|
|
QString gridFileName = nameTool.findRelatedGridFile();
|
|
|
|
if (smSpecFileName != "" || gridFileName != "")
|
|
{
|
|
if (smSpecFileName != "") summaryFileNames.push_back(smSpecFileName);
|
|
if (gridFileName != "") gridFileNames.push_back(gridFileName);
|
|
}
|
|
else
|
|
{
|
|
allCurveAddressFilters.push_back(arguments[optionIdx]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( allCurveAddressFilters.empty() )
|
|
{
|
|
RiaLogging::error("Needs at least one vector to create a plot.");
|
|
}
|
|
|
|
bool hideLegend = options.contains("-nl");
|
|
bool addHistoryCurves = options.contains("-h");
|
|
bool isNormalizedY = options.contains("-n");
|
|
bool isSinglePlot = options.contains("-s");
|
|
|
|
enum EnsembleColoringType { SINGLE_COLOR, PARAMETER, LOG_PARAMETER, NONE };
|
|
EnsembleColoringType ensembleColoringStyle = NONE;
|
|
{
|
|
int e_pos = options.lastIndexOf("-e");
|
|
int c_pos = options.lastIndexOf("-c");
|
|
int cl_pos = options.lastIndexOf("-cl");
|
|
|
|
|
|
int lastEnsembleOptionPos = -1;
|
|
if ( e_pos > lastEnsembleOptionPos ) { lastEnsembleOptionPos = e_pos ; ensembleColoringStyle = SINGLE_COLOR; }
|
|
if ( c_pos > lastEnsembleOptionPos ) { lastEnsembleOptionPos = c_pos ; ensembleColoringStyle = PARAMETER; }
|
|
if ( cl_pos > lastEnsembleOptionPos ) { lastEnsembleOptionPos = cl_pos ; ensembleColoringStyle = LOG_PARAMETER; }
|
|
}
|
|
|
|
bool isEnsembleMode = ensembleColoringStyle != NONE;
|
|
|
|
std::vector<RimSummaryCase*> summaryCasesToUse;
|
|
|
|
if ( summaryFileNames.size() )
|
|
{
|
|
RicImportSummaryCasesFeature::createSummaryCasesFromFiles(summaryFileNames, &summaryCasesToUse, isEnsembleMode);
|
|
RicImportSummaryCasesFeature::addSummaryCases(summaryCasesToUse);
|
|
RiaApplication::instance()->setLastUsedDialogDirectory(RiaDefines::defaultDirectoryLabel(RiaDefines::ECLIPSE_SUMMARY_FILE),
|
|
QFileInfo(summaryFileNames[0]).absolutePath());
|
|
}
|
|
|
|
// Sort in summary and grid curve addresses
|
|
|
|
QStringList gridResultAddressFilters;
|
|
QStringList summaryAddressFilters;
|
|
if ( summaryCasesToUse.size() )
|
|
{
|
|
const std::set<RifEclipseSummaryAddress>& addrs = summaryCasesToUse[0]->summaryReader()->allResultAddresses();
|
|
std::vector<bool> usedFilters;
|
|
std::set<RifEclipseSummaryAddress> setToInsertFilteredAddressesIn;
|
|
filteredSummaryAdressesFromCase(allCurveAddressFilters, addrs, &setToInsertFilteredAddressesIn, &usedFilters);
|
|
|
|
QRegularExpression gridAddressPattern("^[A-Z]+:[0-9]+,[0-9]+,[0-9]+$");
|
|
|
|
for ( int filterIdx = 0; filterIdx < allCurveAddressFilters.size(); ++filterIdx )
|
|
{
|
|
const QString& address = allCurveAddressFilters[filterIdx];
|
|
if ( usedFilters[filterIdx] )
|
|
{
|
|
summaryAddressFilters.push_back(address);
|
|
}
|
|
else
|
|
{
|
|
if ( gridAddressPattern.match(address).hasMatch() )
|
|
{
|
|
gridResultAddressFilters.push_back(address);
|
|
}
|
|
else
|
|
{
|
|
RiaLogging::warning("No summary or restart vectors matched \"" + address + "\"");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( summaryCasesToUse.size() )
|
|
{
|
|
if ( summaryAddressFilters.size() )
|
|
{
|
|
RimSummaryPlotCollection* sumPlotColl = RiaApplication::instance()->project()->mainPlotCollection()->summaryPlotCollection();
|
|
RimSummaryPlot* lastPlotCreated = nullptr;
|
|
RimSummaryCaseCollection* ensemble = nullptr;
|
|
if ( isEnsembleMode ) ensemble = RicCreateSummaryCaseCollectionFeature::groupSummaryCases(summaryCasesToUse, "Ensemble", true);
|
|
|
|
if ( isSinglePlot )
|
|
{
|
|
RimSummaryPlot* newPlot = sumPlotColl->createSummaryPlotWithAutoTitle();
|
|
|
|
if ( isEnsembleMode )
|
|
{
|
|
std::set<RifEclipseSummaryAddress> filteredAdressesFromCases = applySummaryAddressFiltersToCases(summaryCasesToUse,
|
|
summaryAddressFilters);
|
|
for ( const auto & addr : filteredAdressesFromCases )
|
|
{
|
|
RimEnsembleCurveSet* curveSet = new RimEnsembleCurveSet();
|
|
|
|
curveSet->setSummaryCaseCollection(ensemble);
|
|
curveSet->setSummaryAddress(addr);
|
|
|
|
if ( ensembleColoringStyle == PARAMETER || ensembleColoringStyle == LOG_PARAMETER )
|
|
{
|
|
curveSet->setColorMode(RimEnsembleCurveSet::BY_ENSEMBLE_PARAM);
|
|
curveSet->setEnsembleParameter(ensembleColoringParameter);
|
|
if ( ensembleColoringStyle == LOG_PARAMETER )
|
|
{
|
|
curveSet->legendConfig()->setMappingMode(RimRegularLegendConfig::LOG10_CONTINUOUS);
|
|
}
|
|
}
|
|
newPlot->ensembleCurveSetCollection()->addCurveSet(curveSet);
|
|
|
|
|
|
if ( addHistoryCurves )
|
|
{
|
|
RimSummaryCurve* historyCurve = createHistoryCurve(addr, summaryCasesToUse[0]);
|
|
if ( historyCurve ) newPlot->addCurveNoUpdate(historyCurve);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( RimSummaryCase* sumCase : summaryCasesToUse )
|
|
{
|
|
RicSummaryPlotFeatureImpl::addCurvesFromAddressFiltersToPlot(summaryAddressFilters, newPlot, sumCase, addHistoryCurves);
|
|
addHistoryCurves = false;
|
|
}
|
|
}
|
|
|
|
lastPlotCreated = newPlot;
|
|
|
|
newPlot->showLegend(!hideLegend);
|
|
newPlot->setNormalizationEnabled(isNormalizedY);
|
|
|
|
newPlot->applyDefaultCurveAppearances();
|
|
newPlot->loadDataAndUpdate();
|
|
|
|
sumPlotColl->updateConnectedEditors();
|
|
|
|
RiuPlotMainWindowTools::setExpanded(newPlot);
|
|
RiuPlotMainWindowTools::selectAsCurrentItem(newPlot);
|
|
}
|
|
else // Multiplot, one for each separate summary address
|
|
{
|
|
|
|
std::set<RifEclipseSummaryAddress> filteredAdressesFromCases = applySummaryAddressFiltersToCases(summaryCasesToUse,
|
|
summaryAddressFilters);
|
|
|
|
for ( const auto & addr : filteredAdressesFromCases )
|
|
{
|
|
std::vector<RimSummaryCurve*> createdCurves;
|
|
std::vector<RimEnsembleCurveSet*> createdEnsembleCurveSets;
|
|
if ( isEnsembleMode )
|
|
{
|
|
RimEnsembleCurveSet* curveSet = new RimEnsembleCurveSet();
|
|
|
|
curveSet->setSummaryCaseCollection(ensemble);
|
|
curveSet->setSummaryAddress(addr);
|
|
if ( ensembleColoringStyle == PARAMETER || ensembleColoringStyle == LOG_PARAMETER )
|
|
{
|
|
curveSet->setColorMode(RimEnsembleCurveSet::BY_ENSEMBLE_PARAM);
|
|
curveSet->setEnsembleParameter(ensembleColoringParameter);
|
|
if ( ensembleColoringStyle == LOG_PARAMETER )
|
|
{
|
|
curveSet->legendConfig()->setMappingMode(RimRegularLegendConfig::LOG10_CONTINUOUS);
|
|
}
|
|
}
|
|
createdEnsembleCurveSets.push_back(curveSet);
|
|
}
|
|
else
|
|
{
|
|
for ( RimSummaryCase* sumCase : summaryCasesToUse )
|
|
{
|
|
const std::set<RifEclipseSummaryAddress>& allAddrsInCase = sumCase->summaryReader()->allResultAddresses();
|
|
if ( allAddrsInCase.count(addr) )
|
|
{
|
|
RimSummaryCurve* newCurve = new RimSummaryCurve();
|
|
newCurve->setSummaryCaseY(sumCase);
|
|
newCurve->setSummaryAddressYAndApplyInterpolation(addr);
|
|
createdCurves.push_back(newCurve);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( addHistoryCurves )
|
|
{
|
|
RimSummaryCurve* historyCurve = createHistoryCurve(addr, summaryCasesToUse[0]);
|
|
if ( historyCurve ) createdCurves.push_back(historyCurve);
|
|
}
|
|
|
|
if ( createdCurves.size() || createdEnsembleCurveSets.size() )
|
|
{
|
|
RimSummaryPlot* newPlot = sumPlotColl->createSummaryPlotWithAutoTitle();
|
|
|
|
for ( auto curve : createdCurves )
|
|
{
|
|
newPlot->addCurveNoUpdate(curve);
|
|
}
|
|
|
|
for ( auto curveSet: createdEnsembleCurveSets )
|
|
{
|
|
newPlot->ensembleCurveSetCollection()->addCurveSet(curveSet);
|
|
}
|
|
|
|
newPlot->showLegend(!hideLegend);
|
|
newPlot->setNormalizationEnabled(isNormalizedY);
|
|
|
|
newPlot->applyDefaultCurveAppearances();
|
|
newPlot->loadDataAndUpdate();
|
|
lastPlotCreated = newPlot;
|
|
}
|
|
}
|
|
}
|
|
sumPlotColl->updateConnectedEditors();
|
|
|
|
if ( lastPlotCreated )
|
|
{
|
|
RiuPlotMainWindowTools::setExpanded(lastPlotCreated);
|
|
RiuPlotMainWindowTools::selectAsCurrentItem(lastPlotCreated);
|
|
RiuPlotMainWindowTools::showPlotMainWindow();
|
|
RiuMainWindow::instance()->close();
|
|
}
|
|
}
|
|
|
|
// Grid Cell Result vectors
|
|
|
|
if ( gridResultAddressFilters.size() )
|
|
{
|
|
// Todo: Use identical grid case import if -e -c or -cl
|
|
|
|
std::vector<RimEclipseCase*> gridCasesToPlotFrom = openEclipseCasesForCellPlotting(gridFileNames);
|
|
|
|
RimSummaryPlotCollection* sumPlotColl = RiaApplication::instance()->project()->mainPlotCollection()->summaryPlotCollection();
|
|
|
|
if ( isSinglePlot )
|
|
{
|
|
std::vector<RimGridTimeHistoryCurve*> createdCurves;
|
|
int curveColorIndex = 0;
|
|
for ( const QString& gridAddressFilter : gridResultAddressFilters )
|
|
{
|
|
std::vector<RigGridCellResultAddress> cellResAddrs = createGridCellAddressesFromFilter(gridAddressFilter);
|
|
for ( RigGridCellResultAddress cellResAddr : cellResAddrs )
|
|
{
|
|
for ( RimEclipseCase* eclCase: gridCasesToPlotFrom )
|
|
{
|
|
if (!(eclCase->eclipseCaseData()->results(RiaDefines::MATRIX_MODEL) &&
|
|
eclCase->eclipseCaseData()->results(RiaDefines::MATRIX_MODEL)->resultInfo(cellResAddr.eclipseResultAddress)) )
|
|
{
|
|
RiaLogging::warning("Could not find a restart result property with name: \"" + cellResAddr.eclipseResultAddress.m_resultName + "\"");
|
|
continue;
|
|
}
|
|
|
|
RimGridTimeHistoryCurve* newCurve = new RimGridTimeHistoryCurve();
|
|
newCurve->setFromEclipseCellAndResult(eclCase,
|
|
cellResAddr.gridIndex,
|
|
cellResAddr.i,
|
|
cellResAddr.j,
|
|
cellResAddr.k,
|
|
cellResAddr.eclipseResultAddress);
|
|
newCurve->setLineThickness(2);
|
|
cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable(curveColorIndex);
|
|
newCurve->setColor(curveColor);
|
|
if (!isEnsembleMode) ++curveColorIndex;
|
|
|
|
createdCurves.push_back(newCurve);
|
|
}
|
|
if (isEnsembleMode) ++curveColorIndex;
|
|
}
|
|
}
|
|
|
|
if ( createdCurves.size() )
|
|
{
|
|
RimSummaryPlot* newPlot = sumPlotColl->createSummaryPlotWithAutoTitle();
|
|
for ( auto curve: createdCurves )
|
|
{
|
|
newPlot->addGridTimeHistoryCurve(curve);
|
|
}
|
|
|
|
newPlot->showLegend(!hideLegend);
|
|
newPlot->setNormalizationEnabled(isNormalizedY);
|
|
newPlot->loadDataAndUpdate();
|
|
}
|
|
}
|
|
else // Multiplot
|
|
{
|
|
int curveColorIndex = 0;
|
|
|
|
for ( const QString& gridAddressFilter : gridResultAddressFilters )
|
|
{
|
|
std::vector<RigGridCellResultAddress> cellResAddrs = createGridCellAddressesFromFilter(gridAddressFilter);
|
|
for ( RigGridCellResultAddress cellResAddr : cellResAddrs )
|
|
{
|
|
std::vector<RimGridTimeHistoryCurve*> createdCurves;
|
|
for ( RimEclipseCase* eclCase: gridCasesToPlotFrom )
|
|
{
|
|
if (!(eclCase->eclipseCaseData()->results(RiaDefines::MATRIX_MODEL) &&
|
|
eclCase->eclipseCaseData()->results(RiaDefines::MATRIX_MODEL)->resultInfo(cellResAddr.eclipseResultAddress)) )
|
|
{
|
|
RiaLogging::warning("Could not find a restart result property with name: \"" + cellResAddr.eclipseResultAddress.m_resultName + "\"");
|
|
continue;
|
|
}
|
|
RimGridTimeHistoryCurve* newCurve = new RimGridTimeHistoryCurve();
|
|
newCurve->setFromEclipseCellAndResult(eclCase,
|
|
cellResAddr.gridIndex,
|
|
cellResAddr.i,
|
|
cellResAddr.j,
|
|
cellResAddr.k,
|
|
cellResAddr.eclipseResultAddress);
|
|
newCurve->setLineThickness(2);
|
|
cvf::Color3f curveColor = RicWellLogPlotCurveFeatureImpl::curveColorFromTable(curveColorIndex);
|
|
newCurve->setColor(curveColor);
|
|
if (!isEnsembleMode) ++curveColorIndex;
|
|
createdCurves.push_back(newCurve);
|
|
}
|
|
|
|
if (isEnsembleMode) ++curveColorIndex;
|
|
|
|
if ( createdCurves.size() )
|
|
{
|
|
RimSummaryPlot* newPlot = sumPlotColl->createSummaryPlotWithAutoTitle();
|
|
for (auto newCurve : createdCurves)
|
|
{
|
|
newPlot->addGridTimeHistoryCurve(newCurve);
|
|
}
|
|
newPlot->showLegend(!hideLegend);
|
|
newPlot->setNormalizationEnabled(isNormalizedY);
|
|
newPlot->loadDataAndUpdate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sumPlotColl->updateConnectedEditors();
|
|
|
|
RiuPlotMainWindowTools::showPlotMainWindow();
|
|
RiuMainWindow::instance()->close();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RiaLogging::error("Needs at least one summary case to create a plot.");
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::set<RifEclipseSummaryAddress> RicSummaryPlotFeatureImpl::applySummaryAddressFiltersToCases(const std::vector<RimSummaryCase *>& summaryCasesToUse,
|
|
const QStringList& summaryAddressFilters)
|
|
{
|
|
std::set<RifEclipseSummaryAddress> filteredAdressesFromCases;
|
|
for ( RimSummaryCase* sumCase : summaryCasesToUse )
|
|
{
|
|
const std::set<RifEclipseSummaryAddress>& addrs = sumCase->summaryReader()->allResultAddresses();
|
|
std::vector<bool> usedFilters;
|
|
|
|
filteredSummaryAdressesFromCase(summaryAddressFilters, addrs, &filteredAdressesFromCases, &usedFilters);
|
|
|
|
for ( int cfIdx = 0 ; cfIdx < usedFilters.size() ; ++cfIdx )
|
|
{
|
|
if ( !usedFilters[cfIdx] )
|
|
{
|
|
RiaLogging::warning("Vector filter \"" + summaryAddressFilters[cfIdx] + "\" did not match anything in case: \"" + sumCase->caseName() + "\"");
|
|
}
|
|
}
|
|
}
|
|
return filteredAdressesFromCases;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
std::vector<RimSummaryCurve*> RicSummaryPlotFeatureImpl::addCurvesFromAddressFiltersToPlot(const QStringList& curveFilters,
|
|
RimSummaryPlot* plot,
|
|
RimSummaryCase* summaryCase,
|
|
bool addHistoryCurves)
|
|
{
|
|
std::vector<RimSummaryCurve*> createdCurves;
|
|
|
|
std::set<RifEclipseSummaryAddress> curveAddressesToUse;
|
|
|
|
const std::set<RifEclipseSummaryAddress>& addrs = summaryCase->summaryReader()->allResultAddresses();
|
|
std::vector<bool> usedFilters;
|
|
|
|
filteredSummaryAdressesFromCase(curveFilters, addrs, &curveAddressesToUse, &usedFilters);
|
|
|
|
for (int cfIdx = 0 ; cfIdx < usedFilters.size() ; ++cfIdx)
|
|
{
|
|
if (!usedFilters[cfIdx])
|
|
{
|
|
RiaLogging::warning("Vector filter \"" + curveFilters[cfIdx] + "\" did not match anything in case: \"" + summaryCase->caseName() + "\"");
|
|
}
|
|
}
|
|
|
|
if (addHistoryCurves)
|
|
{
|
|
std::vector<RifEclipseSummaryAddress> historyAddressesToUse;
|
|
for (RifEclipseSummaryAddress historyAddr : curveAddressesToUse)
|
|
{
|
|
historyAddr.setQuantityName(historyAddr.quantityName() + "H");
|
|
if (addrs.count(historyAddr))
|
|
{
|
|
historyAddressesToUse.push_back(historyAddr);
|
|
}
|
|
}
|
|
curveAddressesToUse.insert( historyAddressesToUse.begin(), historyAddressesToUse.end() );
|
|
}
|
|
|
|
|
|
for (const auto & addr : curveAddressesToUse)
|
|
{
|
|
RimSummaryCurve* newCurve = new RimSummaryCurve();
|
|
plot->addCurveNoUpdate(newCurve);
|
|
if (summaryCase)
|
|
{
|
|
newCurve->setSummaryCaseY(summaryCase);
|
|
}
|
|
newCurve->setSummaryAddressYAndApplyInterpolation(addr);
|
|
createdCurves.push_back(newCurve);
|
|
}
|
|
|
|
return createdCurves;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RicSummaryPlotFeatureImpl::filteredSummaryAdressesFromCase(const QStringList& curveFilters,
|
|
const std::set<RifEclipseSummaryAddress>& allAddressesInCase,
|
|
std::set<RifEclipseSummaryAddress>* setToInsertFilteredAddressesIn,
|
|
std::vector<bool>* usedFilters)
|
|
{
|
|
int curveFilterCount = curveFilters.size();
|
|
|
|
usedFilters->clear();
|
|
usedFilters->resize(curveFilterCount, false);
|
|
|
|
for (const auto & addr : allAddressesInCase)
|
|
{
|
|
for (int cfIdx = 0 ; cfIdx < curveFilterCount ; ++cfIdx)
|
|
{
|
|
if ( addr.isUiTextMatchingFilterText( curveFilters[cfIdx]) )
|
|
{
|
|
setToInsertFilteredAddressesIn->insert(addr);
|
|
(*usedFilters)[cfIdx] = true;
|
|
}
|
|
}
|
|
}
|
|
} |