diff --git a/ApplicationCode/Application/RiaGuiApplication.cpp b/ApplicationCode/Application/RiaGuiApplication.cpp index 21c9441b5b..909f24d720 100644 --- a/ApplicationCode/Application/RiaGuiApplication.cpp +++ b/ApplicationCode/Application/RiaGuiApplication.cpp @@ -660,7 +660,7 @@ RiaApplication::ApplicationStatus RiaGuiApplication::handleArguments(cvf::Progra if (cvf::Option o = progOpt->option("summaryplot")) { - RicSummaryPlotFeatureImpl::createSummaryPlotFromArgumentLine( cvfqt::Utils::toQStringList(o.values())); + RicSummaryPlotFeatureImpl::createSummaryPlotsFromArgumentLine( cvfqt::Utils::toQStringList(o.values())); } QString projectFileName; diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp index 2e3e0c898f..2c1c65e99f 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.cpp @@ -24,21 +24,25 @@ #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 "RiaPreferences.h" #include "RiaEclipseFileNameTools.h" +#include "RiaDefines.h" #include "RifSummaryReaderInterface.h" #include "RicImportGeneralDataFeature.h" +#include "RicCreateSummaryCaseCollectionFeature.h" +#include "RicImportSummaryCasesFeature.h" #include -#include "RicImportSummaryCasesFeature.h" -#include "RiaDefines.h" #include //-------------------------------------------------------------------------------------------------- @@ -143,26 +147,34 @@ void RicSummaryPlotFeatureImpl::createDefaultSummaryPlot( RimSummaryCase* summar } } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -RimSummaryPlot* RicSummaryPlotFeatureImpl::createSummaryPlotFromCommandLine(const QStringList & arguments) +RimSummaryCurve* createHistoryCurve(const RifEclipseSummaryAddress& addr, RimSummaryCase* summaryCasesToUse) { - RimSummaryPlot* plot = RicSummaryPlotFeatureImpl::createSummaryPlotFromArgumentLine(arguments); - return plot; + 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; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimSummaryPlot* RicSummaryPlotFeatureImpl::createSummaryPlotFromArgumentLine(const QStringList & arguments) +void RicSummaryPlotFeatureImpl::createSummaryPlotsFromArgumentLine(const QStringList & arguments) { // Split arguments in options, vectors and filenames QStringList options; QStringList summaryAddressFilters; QStringList summaryFiles; + QString ensembleColoringParameter; + std::set validOptions = {"-help", "-h", "-nl", "-s", "-n", "-e", "-c", "-cl"}; for (int optionIdx = 0; optionIdx < arguments.size(); ++optionIdx) { @@ -175,7 +187,7 @@ RimSummaryPlot* RicSummaryPlotFeatureImpl::createSummaryPlotFromArgumentLine(con "\n" "[] []\n" "\n" - "It Creates one summary plot using all the for each of the the summary vectors matched by the .\n" + "It Creates one summary plot for each of the the summary vectors matched by the using all the in each plot.\n" "The has the syntax [:[:[: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 can be written with or without extension. Only the corresponding SMSPEC file will be opened for each case.\n" @@ -185,12 +197,30 @@ RimSummaryPlot* RicSummaryPlotFeatureImpl::createSummaryPlotFromArgumentLine(con " -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\t Scale all curves into the range 0.0-1.0. Useful when using -s" + " -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 \t Same as -e, but colors the curves by the ensemble parameter . \n" + " -cl \t Same as -c, but uses logarithmic legend.\n" ); - return nullptr; + + 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."); } - options.push_back(arguments[optionIdx]); } else { @@ -211,34 +241,90 @@ RimSummaryPlot* RicSummaryPlotFeatureImpl::createSummaryPlotFromArgumentLine(con { RiaLogging::error("Needs at least one summary vector to create a plot."); } - - std::vector summaryCasesToUse; - - if ( summaryFiles.size() ) - { - RicImportSummaryCasesFeature::createAndAddSummaryCasesFromFiles(summaryFiles, false, &summaryCasesToUse); - RiaApplication::instance()->setLastUsedDialogDirectory(RiaDefines::defaultDirectoryLabel(RiaDefines::ECLIPSE_SUMMARY_FILE), QFileInfo(summaryFiles[0]).absolutePath()); - } 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 summaryCasesToUse; + + if ( summaryFiles.size() ) + { + RicImportSummaryCasesFeature::createSummaryCasesFromFiles(summaryFiles, &summaryCasesToUse, isEnsembleMode); + RicImportSummaryCasesFeature::addSummaryCases(summaryCasesToUse); + RiaApplication::instance()->setLastUsedDialogDirectory(RiaDefines::defaultDirectoryLabel(RiaDefines::ECLIPSE_SUMMARY_FILE), + QFileInfo(summaryFiles[0]).absolutePath()); + } + if ( summaryCasesToUse.size() ) { + RimSummaryPlot* lastPlotCreated = nullptr; RimSummaryPlotCollection* sumPlotColl = RiaApplication::instance()->project()->mainPlotCollection()->summaryPlotCollection(); + RimSummaryCaseCollection* ensemble = nullptr; + if (isEnsembleMode) ensemble = RicCreateSummaryCaseCollectionFeature::groupSummaryCases(summaryCasesToUse, "Ensemble", true); + if ( isSinglePlot ) { RimSummaryPlot* newPlot = sumPlotColl->createSummaryPlotWithAutoTitle(); - for ( RimSummaryCase* sumCase : summaryCasesToUse ) + if ( isEnsembleMode ) { - RicSummaryPlotFeatureImpl::addCurvesFromAddressFiltersToPlot(summaryAddressFilters, newPlot, sumCase, addHistoryCurves); - addHistoryCurves = false; + std::set 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); @@ -253,64 +339,66 @@ RimSummaryPlot* RicSummaryPlotFeatureImpl::createSummaryPlotFromArgumentLine(con } else // Multiplot, one for each separate summary address { - std::set filteredAdressesFromCases; - RimSummaryPlot* lastPlotCreated = nullptr; - for ( RimSummaryCase* sumCase : summaryCasesToUse ) - { - const std::set& addrs = sumCase->summaryReader()->allResultAddresses(); - std::vector usedFilters; + std::set filteredAdressesFromCases = applySummaryAddressFiltersToCases(summaryCasesToUse, + summaryAddressFilters); - 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() + "\""); - } - } - } - - for (const auto & addr : filteredAdressesFromCases) + for ( const auto & addr : filteredAdressesFromCases ) { std::vector createdCurves; - bool isFirstCase = true; - for ( RimSummaryCase* sumCase : summaryCasesToUse ) + std::vector createdEnsembleCurveSets; + if ( isEnsembleMode ) { - const std::set& addrs = sumCase->summaryReader()->allResultAddresses(); - if (addrs.count(addr)) - { - RimSummaryCurve* newCurve = new RimSummaryCurve(); - newCurve->setSummaryCaseY(sumCase); - newCurve->setSummaryAddressYAndApplyInterpolation(addr); - createdCurves.push_back(newCurve); + RimEnsembleCurveSet* curveSet = new RimEnsembleCurveSet(); - if ( addHistoryCurves && isFirstCase) + 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 ) { - RifEclipseSummaryAddress historyAddr = addr; - historyAddr.setQuantityName(historyAddr.quantityName() + "H"); - if ( addrs.count(historyAddr) ) - { - RimSummaryCurve* historyCurve = new RimSummaryCurve(); - historyCurve->setSummaryCaseY(sumCase); - historyCurve->setSummaryAddressYAndApplyInterpolation(historyAddr); - createdCurves.push_back(historyCurve); - } + curveSet->legendConfig()->setMappingMode(RimRegularLegendConfig::LOG10_CONTINUOUS); + } + } + createdEnsembleCurveSets.push_back(curveSet); + } + else + { + for ( RimSummaryCase* sumCase : summaryCasesToUse ) + { + const std::set& allAddrsInCase = sumCase->summaryReader()->allResultAddresses(); + if ( allAddrsInCase.count(addr) ) + { + RimSummaryCurve* newCurve = new RimSummaryCurve(); + newCurve->setSummaryCaseY(sumCase); + newCurve->setSummaryAddressYAndApplyInterpolation(addr); + createdCurves.push_back(newCurve); } } - - isFirstCase = false; } - if ( createdCurves.size() ) + 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); @@ -319,22 +407,46 @@ RimSummaryPlot* RicSummaryPlotFeatureImpl::createSummaryPlotFromArgumentLine(con lastPlotCreated = newPlot; } } + } + sumPlotColl->updateConnectedEditors(); - sumPlotColl->updateConnectedEditors(); - if ( lastPlotCreated ) - { - RiuPlotMainWindowTools::setExpanded(lastPlotCreated); - RiuPlotMainWindowTools::selectAsCurrentItem(lastPlotCreated); - } + if ( lastPlotCreated ) + { + RiuPlotMainWindowTools::setExpanded(lastPlotCreated); + RiuPlotMainWindowTools::selectAsCurrentItem(lastPlotCreated); + RiuPlotMainWindowTools::showPlotMainWindow(); + RiuMainWindow::instance()->close(); } } else { RiaLogging::error("Needs at least one summary case to create a plot."); } +} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::set RicSummaryPlotFeatureImpl::applySummaryAddressFiltersToCases(const std::vector& summaryCasesToUse, + const QStringList& summaryAddressFilters) +{ + std::set filteredAdressesFromCases; + for ( RimSummaryCase* sumCase : summaryCasesToUse ) + { + const std::set& addrs = sumCase->summaryReader()->allResultAddresses(); + std::vector usedFilters; - return nullptr; + 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; } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h index 157efe29eb..19d76bcc39 100644 --- a/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h +++ b/ApplicationCode/Commands/SummaryPlotCommands/RicSummaryPlotFeatureImpl.h @@ -33,19 +33,23 @@ class RicSummaryPlotFeatureImpl { public: static RimSummaryCurve* addDefaultCurveToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase); - static std::vector addCurvesFromAddressFiltersToPlot(const QStringList& curveFilters, - RimSummaryPlot* plot, - RimSummaryCase* summaryCase, - bool addHistoryCurves); - static void filteredSummaryAdressesFromCase(const QStringList& curveFilters, - const std::set& allAddressesInCase, - std::set* setToInsertFilteredAddressesIn, - std::vector* usedFilters); static std::vector addDefaultCurvesToPlot(RimSummaryPlot* plot, RimSummaryCase* summaryCase); static void ensureAtLeastOnePlot(RimSummaryPlotCollection* summaryPlotCollection, RimSummaryCase* summaryCase); static void createDefaultSummaryPlot(RimSummaryCase* summaryCase); - static RimSummaryPlot* createSummaryPlotFromCommandLine(const QStringList & arguments); - static RimSummaryPlot* createSummaryPlotFromArgumentLine(const QStringList & arguments); + static void createSummaryPlotsFromArgumentLine(const QStringList & arguments); + +private: + static std::vector addCurvesFromAddressFiltersToPlot(const QStringList& curveFilters, + RimSummaryPlot* plot, + RimSummaryCase* summaryCase, + bool addHistoryCurves); + static std::set applySummaryAddressFiltersToCases(const std::vector& summaryCasesToUse, + const QStringList& summaryAddressFilters); + static void filteredSummaryAdressesFromCase(const QStringList& curveFilters, + const std::set& allAddressesInCase, + std::set* setToInsertFilteredAddressesIn, + std::vector* usedFilters); + }; diff --git a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp index 3e67f0314c..f05001ac11 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp +++ b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.cpp @@ -426,6 +426,22 @@ RimEnsembleCurveSet::ColorMode RimEnsembleCurveSet::colorMode() const return m_colorMode(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleCurveSet::setColorMode(ColorMode mode) +{ + m_colorMode = mode; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimEnsembleCurveSet::setEnsembleParameter(const QString& parameterName) +{ + m_ensembleParameter = parameterName; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h index 3f6af71fa7..3a91968503 100644 --- a/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h +++ b/ApplicationCode/ProjectDataModel/Summary/RimEnsembleCurveSet.h @@ -97,6 +97,8 @@ public: RimEnsembleCurveFilterCollection* filterCollection() const; ColorMode colorMode() const; + void setColorMode(ColorMode mode); + void setEnsembleParameter(const QString& parameterName); void updateEnsembleLegendItem(); EnsembleParameter::Type currentEnsembleParameterType() const; static QString ensembleParameterUiName(const NameParameterPair& paramPair);