mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Merge TableView and SelectionManager changes for #2609 Well Path
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
#include "RimRftPlotCollection.h"
|
||||
#include "RimStimPlanColors.h"
|
||||
#include "RimSummaryCase.h"
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
#include "RimSummaryCaseMainCollection.h"
|
||||
#include "RimSummaryCrossPlotCollection.h"
|
||||
#include "RimSummaryPlot.h"
|
||||
@@ -597,6 +598,17 @@ bool RiaApplication::loadProject(const QString& projectFileName, ProjectLoadActi
|
||||
cas->intersectionViewCollection()->syncFromExistingIntersections(false);
|
||||
}
|
||||
|
||||
// Init summary case groups
|
||||
for (RimOilField* oilField : m_project->oilFields)
|
||||
{
|
||||
auto sumMainCollection = oilField->summaryCaseMainCollection();
|
||||
if(!sumMainCollection) continue;
|
||||
|
||||
for (auto sumCaseGroup : sumMainCollection->summaryCaseCollections())
|
||||
{
|
||||
sumCaseGroup->loadDataAndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
loadAndUpdatePlotData();
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaFilePathTools.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaTimeHistoryCurveMerger.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaCurveDataTools.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaTimeHistoryCurveResampler.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaStatisticsTools.h
|
||||
)
|
||||
|
||||
set (SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -57,6 +58,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaFilePathTools.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaTimeHistoryCurveMerger.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaCurveDataTools.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaTimeHistoryCurveResampler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RiaStatisticsTools.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES
|
||||
|
||||
49
ApplicationCode/Application/Tools/RiaStatisticsTools.cpp
Normal file
49
ApplicationCode/Application/Tools/RiaStatisticsTools.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2011- Statoil ASA
|
||||
// Copyright (C) 2013- Ceetron Solutions AS
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// 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 "RiaStatisticsTools.h"
|
||||
|
||||
#include "RifEclipseSummaryAddress.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const QString RiaStatisticsTools::replacePercentileByPValueText(const QString& percentile)
|
||||
{
|
||||
QString result = percentile;
|
||||
|
||||
if (result == ENSEMBLE_STAT_P10_QUANTITY_NAME)
|
||||
{
|
||||
result = ENSEMBLE_STAT_P90_QUANTITY_NAME;
|
||||
}
|
||||
else if (result == ENSEMBLE_STAT_P90_QUANTITY_NAME)
|
||||
{
|
||||
result = ENSEMBLE_STAT_P10_QUANTITY_NAME;
|
||||
}
|
||||
else if (percentile.contains(QString("%1:").arg(ENSEMBLE_STAT_P10_QUANTITY_NAME)))
|
||||
{
|
||||
result.replace(ENSEMBLE_STAT_P10_QUANTITY_NAME, ENSEMBLE_STAT_P90_QUANTITY_NAME);
|
||||
}
|
||||
else if (percentile.contains(QString("%1:").arg(ENSEMBLE_STAT_P90_QUANTITY_NAME)))
|
||||
{
|
||||
result.replace(ENSEMBLE_STAT_P90_QUANTITY_NAME, ENSEMBLE_STAT_P10_QUANTITY_NAME);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
36
ApplicationCode/Application/Tools/RiaStatisticsTools.h
Normal file
36
ApplicationCode/Application/Tools/RiaStatisticsTools.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2011- Statoil ASA
|
||||
// Copyright (C) 2013- Ceetron Solutions AS
|
||||
// Copyright (C) 2011-2012 Ceetron AS
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <string>
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
class RiaStatisticsTools
|
||||
{
|
||||
public:
|
||||
static const QString replacePercentileByPValueText(const QString& percentile);
|
||||
};
|
||||
@@ -130,7 +130,7 @@ std::vector<QString> RiaSummaryCurveAnalyzer::identifierTexts(RifEclipseSummaryA
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RifEclipseSummaryAddress>
|
||||
RiaSummaryCurveAnalyzer::addressesForCategory(const std::vector<RifEclipseSummaryAddress>& addresses,
|
||||
RiaSummaryCurveAnalyzer::addressesForCategory(const std::set<RifEclipseSummaryAddress>& addresses,
|
||||
RifEclipseSummaryAddress::SummaryVarCategory category)
|
||||
{
|
||||
std::vector<RifEclipseSummaryAddress> filteredAddresses;
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
|
||||
std::vector<QString> identifierTexts(RifEclipseSummaryAddress::SummaryVarCategory category) const;
|
||||
|
||||
static std::vector<RifEclipseSummaryAddress> addressesForCategory(const std::vector<RifEclipseSummaryAddress>& addresses,
|
||||
static std::vector<RifEclipseSummaryAddress> addressesForCategory(const std::set<RifEclipseSummaryAddress>& addresses,
|
||||
RifEclipseSummaryAddress::SummaryVarCategory category);
|
||||
|
||||
private:
|
||||
|
||||
@@ -85,6 +85,27 @@ const std::vector<double>& RiaTimeHistoryCurveResampler::resampledValues() const
|
||||
return m_values;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<time_t> RiaTimeHistoryCurveResampler::timeStepsFromTimeRange(DateTimePeriod period, time_t minTime, time_t maxTime)
|
||||
{
|
||||
CVF_ASSERT(minTime <= maxTime);
|
||||
|
||||
auto firstOriginalTimeStep = QDT::fromTime_t(minTime);
|
||||
auto lastOriginalTimeStep = QDT::fromTime_t(maxTime);
|
||||
|
||||
auto currTimeStep = firstResampledTimeStep(firstOriginalTimeStep, period);
|
||||
|
||||
std::vector<time_t> timeSteps;
|
||||
while (QDT::lessThanOrEqualTo(currTimeStep, lastOriginalTimeStep))
|
||||
{
|
||||
timeSteps.push_back(currTimeStep.toTime_t());
|
||||
currTimeStep = QDT::addPeriod(currTimeStep, period);
|
||||
}
|
||||
return timeSteps;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -42,13 +42,15 @@ public:
|
||||
const std::vector<time_t>& resampledTimeSteps() const;
|
||||
const std::vector<double>& resampledValues() const;
|
||||
|
||||
static std::vector<time_t> timeStepsFromTimeRange(DateTimePeriod period, time_t minTime, time_t maxTime);
|
||||
|
||||
private:
|
||||
void computeWeightedMeanValues(DateTimePeriod period);
|
||||
void computePeriodEndValues(DateTimePeriod period);
|
||||
|
||||
void clearData();
|
||||
void computeResampledTimeSteps(DateTimePeriod period);
|
||||
QDateTime firstResampledTimeStep(const QDateTime& firstTimestep, DateTimePeriod period);
|
||||
static QDateTime firstResampledTimeStep(const QDateTime& firstTimestep, DateTimePeriod period);
|
||||
inline double interpolatedValue(time_t t, time_t t1, double v1, time_t t2, double v2);
|
||||
|
||||
private:
|
||||
|
||||
@@ -36,19 +36,20 @@ CAF_CMD_SOURCE_INIT(RicCreateSummaryCaseCollectionFeature, "RicCreateSummaryCase
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicCreateSummaryCaseCollectionFeature::groupSummaryCases(std::vector<RimSummaryCase*> cases, const QString& groupName, bool isEnsemble)
|
||||
RimSummaryCaseCollection* RicCreateSummaryCaseCollectionFeature::groupSummaryCases(std::vector<RimSummaryCase*> cases, const QString& groupName, bool isEnsemble)
|
||||
{
|
||||
RimSummaryCaseMainCollection* summaryCaseMainCollection = nullptr;
|
||||
if (!cases.empty())
|
||||
{
|
||||
cases[0]->firstAncestorOrThisOfTypeAsserted(summaryCaseMainCollection);
|
||||
|
||||
summaryCaseMainCollection->addCaseCollection(cases, groupName, isEnsemble);
|
||||
auto newGroup = summaryCaseMainCollection->addCaseCollection(cases, groupName, isEnsemble);
|
||||
summaryCaseMainCollection->updateConnectedEditors();
|
||||
|
||||
RiuPlotMainWindowTools::showPlotMainWindow();
|
||||
RiuPlotMainWindowTools::selectAsCurrentItem(summaryCaseMainCollection->summaryCaseCollections().back()->allSummaryCases().front());
|
||||
return newGroup;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <vector>
|
||||
|
||||
class RimSummaryCase;
|
||||
class RimSummaryCaseCollection;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
@@ -31,7 +32,7 @@ class RicCreateSummaryCaseCollectionFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
static void groupSummaryCases(std::vector<RimSummaryCase*> cases, const QString& groupName, bool isEnsemble = false);
|
||||
static RimSummaryCaseCollection* groupSummaryCases(std::vector<RimSummaryCase*> cases, const QString& groupName, bool isEnsemble = false);
|
||||
|
||||
private:
|
||||
virtual bool isCommandEnabled() override;
|
||||
|
||||
@@ -130,13 +130,12 @@ void RicImportEnsembleFeature::onActionTriggered(bool isChecked)
|
||||
validateEnsembleCases(cases);
|
||||
|
||||
RicImportSummaryCasesFeature::addSummaryCases(cases);
|
||||
RicCreateSummaryCaseCollectionFeature::groupSummaryCases(cases, ensembleName, true);
|
||||
auto newGroup = RicCreateSummaryCaseCollectionFeature::groupSummaryCases(cases, ensembleName, true);
|
||||
|
||||
RiuPlotMainWindow* mainPlotWindow = app->getOrCreateAndShowMainPlotWindow();
|
||||
if (mainPlotWindow && !cases.empty())
|
||||
if (mainPlotWindow && newGroup)
|
||||
{
|
||||
mainPlotWindow->selectAsCurrentItem(cases.back());
|
||||
|
||||
mainPlotWindow->selectAsCurrentItem(newGroup);
|
||||
mainPlotWindow->updateSummaryPlotToolBar();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCrossPlotCurveFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryEnsembleCurveSetFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicPasteEnsembleCurveSetFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewEnsembleCurveFilterFeature.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewDerivedEnsembleFeature.h
|
||||
)
|
||||
|
||||
set (SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -73,6 +74,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryCrossPlotCurveFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewSummaryEnsembleCurveSetFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicPasteEnsembleCurveSetFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewEnsembleCurveFilterFeature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RicNewDerivedEnsembleFeature.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RicNewDerivedEnsembleFeature.h"
|
||||
|
||||
#include "RiaApplication.h"
|
||||
|
||||
#include "RimDerivedEnsembleCaseCollection.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimSummaryCaseMainCollection.h"
|
||||
|
||||
#include "RiuPlotMainWindowTools.h"
|
||||
|
||||
#include "cafSelectionManagerTools.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
CAF_CMD_SOURCE_INIT(RicNewDerivedEnsembleFeature, "RicNewDerivedEnsembleFeature");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RicNewDerivedEnsembleFeature::isCommandEnabled()
|
||||
{
|
||||
std::vector<RimSummaryCaseMainCollection*> mainColls = caf::selectedObjectsByTypeStrict<RimSummaryCaseMainCollection*>();
|
||||
std::vector<RimSummaryCaseCollection*> ensembles = caf::selectedObjectsByTypeStrict<RimSummaryCaseCollection*>();
|
||||
|
||||
return mainColls.size() == 1 || ensembles.size() == 1 || ensembles.size() == 2;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewDerivedEnsembleFeature::onActionTriggered(bool isChecked)
|
||||
{
|
||||
if (isCommandEnabled())
|
||||
{
|
||||
auto project = RiaApplication::instance()->project();
|
||||
auto mainColl = project->firstSummaryCaseMainCollection();
|
||||
|
||||
auto newColl = mainColl->addCaseCollection({}, "", true, []() {return new RimDerivedEnsembleCaseCollection(); });
|
||||
auto newEnsemble = dynamic_cast<RimDerivedEnsembleCaseCollection*>(newColl);
|
||||
|
||||
{
|
||||
std::vector<RimSummaryCaseCollection*> ensembles = caf::selectedObjectsByType<RimSummaryCaseCollection*>();
|
||||
|
||||
if (ensembles.size() >= 1) newEnsemble->setEnsemble1(ensembles[0]);
|
||||
if (ensembles.size() == 2)
|
||||
{
|
||||
newEnsemble->setEnsemble2(ensembles[1]);
|
||||
newEnsemble->updateDerivedEnsembleCases();
|
||||
}
|
||||
}
|
||||
|
||||
mainColl->updateConnectedEditors();
|
||||
RiuPlotMainWindowTools::selectAsCurrentItem(newEnsemble);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RicNewDerivedEnsembleFeature::setupActionLook(QAction* actionToSetup)
|
||||
{
|
||||
actionToSetup->setText("New Derived Ensemble");
|
||||
actionToSetup->setIcon(QIcon(":/SummaryEnsemble16x16.png"));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cafCmdFeature.h"
|
||||
|
||||
class RimSummaryPlotCollection;
|
||||
class RimSummaryCase;
|
||||
class RimSummaryPlot;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RicNewDerivedEnsembleFeature : public caf::CmdFeature
|
||||
{
|
||||
CAF_CMD_HEADER_INIT;
|
||||
|
||||
protected:
|
||||
// Overrides
|
||||
virtual bool isCommandEnabled();
|
||||
virtual void onActionTriggered( bool isChecked );
|
||||
virtual void setupActionLook(QAction* actionToSetup);
|
||||
};
|
||||
@@ -197,7 +197,7 @@ std::vector<RimAsciiDataCurve*> RicPasteAsciiDataToSummaryPlotFeature::parseCurv
|
||||
// Appearance
|
||||
curve->setSymbol(parseOptions.curveSymbol);
|
||||
curve->setLineStyle(parseOptions.curveLineStyle);
|
||||
curve->setSymbolSkipDinstance(parseOptions.curveSymbolSkipDistance);
|
||||
curve->setSymbolSkipDistance(parseOptions.curveSymbolSkipDistance);
|
||||
curveToTypeMap[guessCurveType(QString::fromStdString(col->columnName()))].push_back(curve);
|
||||
curves.push_back(curve);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "RifReaderEclipseSummary.h"
|
||||
|
||||
#include "RimDerivedEnsembleCaseCollection.h"
|
||||
#include "RimEnsembleCurveSet.h"
|
||||
#include "RimEnsembleCurveSetCollection.h"
|
||||
#include "RimEnsembleCurveSetColorManager.h"
|
||||
@@ -416,7 +417,7 @@ void RicSummaryCurveCreator::updatePreviewCurvesFromCurveDefinitions(
|
||||
curve->setSummaryCaseY(currentCase);
|
||||
curve->setSummaryAddressY(curveDef.summaryAddress());
|
||||
curve->applyCurveAutoNameSettings(*m_curveNameConfig());
|
||||
if(currentCase->isObservedData()) curve->setSymbolSkipDinstance(0);
|
||||
if(currentCase->isObservedData()) curve->setSymbolSkipDistance(0);
|
||||
|
||||
if (curveDef.isEnsembleCurve())
|
||||
{
|
||||
@@ -509,13 +510,13 @@ std::set<std::string> RicSummaryCurveCreator::getAllSummaryWellNames()
|
||||
|
||||
if (reader)
|
||||
{
|
||||
const std::vector<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses();
|
||||
const std::set<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses();
|
||||
|
||||
for (size_t i = 0; i < allAddresses.size(); i++)
|
||||
for(auto& address : allAddresses)
|
||||
{
|
||||
if (allAddresses[i].category() == RifEclipseSummaryAddress::SUMMARY_WELL)
|
||||
if (address.category() == RifEclipseSummaryAddress::SUMMARY_WELL)
|
||||
{
|
||||
summaryWellNames.insert(allAddresses[i].wellName());
|
||||
summaryWellNames.insert(address.wellName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleParametersReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.h
|
||||
|
||||
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
|
||||
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.h
|
||||
@@ -90,6 +91,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleParametersReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.cpp
|
||||
|
||||
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
|
||||
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <QStringList>
|
||||
#include <QDir>
|
||||
|
||||
#include <functional>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Constants
|
||||
@@ -166,8 +167,6 @@ void RifCaseRealizationParametersReader::openFile()
|
||||
if (!m_file->open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
closeFile();
|
||||
//delete m_file;
|
||||
//m_file = nullptr;
|
||||
throw FileParseException(QString("Failed to open %1").arg(m_fileName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ private:
|
||||
void closeDataStream();
|
||||
void openFile();
|
||||
void closeFile();
|
||||
|
||||
private:
|
||||
std::shared_ptr<RigCaseRealizationParameters> m_parameters;
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ void RifColumnBasedUserData::buildTimeStepsAndMappings()
|
||||
{
|
||||
RifEclipseSummaryAddress sumAddress = ci.summaryAddress;
|
||||
|
||||
m_allResultAddresses.push_back(sumAddress);
|
||||
m_allResultAddresses.insert(sumAddress);
|
||||
|
||||
m_mapFromAddressToTimeStepIndex[sumAddress] = m_timeSteps.size() - 1;
|
||||
m_mapFromAddressToResultIndex[sumAddress] = std::make_pair(tableIndex, columIndex);
|
||||
|
||||
@@ -158,7 +158,7 @@ void RifCsvUserData::buildTimeStepsAndMappings()
|
||||
{
|
||||
RifEclipseSummaryAddress sumAddress = ci.summaryAddress;
|
||||
|
||||
m_allResultAddresses.push_back(sumAddress);
|
||||
m_allResultAddresses.insert(sumAddress);
|
||||
if (sumAddress.isErrorResult()) m_allErrorAddresses.insert(sumAddress);
|
||||
|
||||
m_mapFromAddressToTimeStepIndex[sumAddress] = m_timeSteps.size() - 1;
|
||||
|
||||
75
ApplicationCode/FileInterface/RifDerivedEnsembleReader.cpp
Normal file
75
ApplicationCode/FileInterface/RifDerivedEnsembleReader.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RifDerivedEnsembleReader.h"
|
||||
|
||||
#include "RimDerivedEnsembleCase.h"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<time_t> RifDerivedEnsembleReader::EMPTY_TIME_STEPS_VECTOR;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifDerivedEnsembleReader::RifDerivedEnsembleReader(RimDerivedEnsembleCase* derivedCase)
|
||||
{
|
||||
CVF_ASSERT(derivedCase);
|
||||
|
||||
m_derivedCase = derivedCase;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<time_t>& RifDerivedEnsembleReader::timeSteps(const RifEclipseSummaryAddress& resultAddress) const
|
||||
{
|
||||
if (!resultAddress.isValid()) return EMPTY_TIME_STEPS_VECTOR;
|
||||
if (m_derivedCase->needsCalculation(resultAddress))
|
||||
{
|
||||
m_derivedCase->calculate(resultAddress);
|
||||
}
|
||||
return m_derivedCase->timeSteps(resultAddress);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifDerivedEnsembleReader::values(const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values) const
|
||||
{
|
||||
if (!resultAddress.isValid()) return false;
|
||||
|
||||
if (m_derivedCase->needsCalculation(resultAddress))
|
||||
{
|
||||
m_derivedCase->calculate(resultAddress);
|
||||
}
|
||||
auto dataValues = m_derivedCase->values(resultAddress);
|
||||
values->clear();
|
||||
values->reserve(dataValues.size());
|
||||
for (auto val : dataValues) values->push_back(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RifDerivedEnsembleReader::unitName(const RifEclipseSummaryAddress& resultAddress) const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
44
ApplicationCode/FileInterface/RifDerivedEnsembleReader.h
Normal file
44
ApplicationCode/FileInterface/RifDerivedEnsembleReader.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RifEclipseSummaryAddress.h"
|
||||
#include "RifSummaryReaderInterface.h"
|
||||
|
||||
class RimDerivedEnsembleCase;
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RifDerivedEnsembleReader : public RifSummaryReaderInterface
|
||||
{
|
||||
static const std::vector<time_t> EMPTY_TIME_STEPS_VECTOR;
|
||||
|
||||
public:
|
||||
RifDerivedEnsembleReader(RimDerivedEnsembleCase* derivedCase);
|
||||
|
||||
virtual const std::vector<time_t>& timeSteps(const RifEclipseSummaryAddress& resultAddress) const override;
|
||||
virtual bool values(const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values) const override;
|
||||
virtual std::string unitName(const RifEclipseSummaryAddress& resultAddress) const override;
|
||||
|
||||
private:
|
||||
RimDerivedEnsembleCase* m_derivedCase;
|
||||
};
|
||||
@@ -674,7 +674,8 @@ bool RifEclipseSummaryAddress::isValid() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RifEclipseSummaryAddress::hasAccumulatedData() const
|
||||
{
|
||||
return QString::fromStdString(m_quantityName).endsWith("T");
|
||||
return QString::fromStdString(m_quantityName).endsWith("T") ||
|
||||
QString::fromStdString(m_quantityName).endsWith("TH");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -167,7 +167,7 @@ QString RifEclipseSummaryTools::findGridCaseFileFromSummaryHeaderFile(const QStr
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RifEclipseSummaryTools::dumpMetaData(RifSummaryReaderInterface* readerEclipseSummary)
|
||||
{
|
||||
std::vector<RifEclipseSummaryAddress> addresses = readerEclipseSummary->allResultAddresses();
|
||||
std::set<RifEclipseSummaryAddress> addresses = readerEclipseSummary->allResultAddresses();
|
||||
|
||||
for (int category = 0; category < RifEclipseSummaryAddress::SUMMARY_BLOCK_LGR; category++)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ RifEnsembleStatisticsReader::RifEnsembleStatisticsReader(RimEnsembleStatisticsCa
|
||||
|
||||
m_ensembleStatCase = ensStatCase;
|
||||
|
||||
m_allResultAddresses = std::vector<RifEclipseSummaryAddress>(
|
||||
m_allResultAddresses = std::set<RifEclipseSummaryAddress>(
|
||||
{
|
||||
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P10_QUANTITY_NAME, ""),
|
||||
RifEclipseSummaryAddress::ensembleStatisticsAddress(ENSEMBLE_STAT_P50_QUANTITY_NAME, ""),
|
||||
@@ -46,7 +46,7 @@ RifEnsembleStatisticsReader::RifEnsembleStatisticsReader(RimEnsembleStatisticsCa
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<time_t>& RifEnsembleStatisticsReader::timeSteps(const RifEclipseSummaryAddress& resultAddress) const
|
||||
{
|
||||
if (!resultAddress.isValid()) return EMPTY_TIME_STEPS_VECTOR;
|
||||
if (!validateAddress(resultAddress)) return EMPTY_TIME_STEPS_VECTOR;
|
||||
return m_ensembleStatCase->timeSteps();
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ bool RifEnsembleStatisticsReader::values(const RifEclipseSummaryAddress& resultA
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::string RifEnsembleStatisticsReader::unitName(const RifEclipseSummaryAddress& resultAddress) const
|
||||
{
|
||||
return "(RifEnsembleStatisticsReader::unitName)";
|
||||
return "";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -179,7 +179,7 @@ bool RifKeywordVectorUserData::parse(const QString& data, const QString& customW
|
||||
-1,
|
||||
false);
|
||||
|
||||
m_allResultAddresses.push_back(addr);
|
||||
m_allResultAddresses.insert(addr);
|
||||
|
||||
m_mapFromAddressToTimeIndex[addr] = timeStepIndexIterator->second;
|
||||
m_mapFromAddressToVectorIndex[addr] = i;
|
||||
|
||||
@@ -441,7 +441,7 @@ void RifReaderEclipseSummary::buildMetaData()
|
||||
{
|
||||
const smspec_node_type * ertSumVarNode = ecl_smspec_iget_node(m_ecl_SmSpec, i);
|
||||
RifEclipseSummaryAddress addr = addressFromErtSmSpecNode(ertSumVarNode);
|
||||
m_allResultAddresses.push_back(addr);
|
||||
m_allResultAddresses.insert(addr);
|
||||
m_resultAddressToErtNodeIdx[addr] = i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ bool RifReaderObservedData::open(const QString& headerFileName,
|
||||
m_allResultAddresses.clear();
|
||||
for (auto s : m_asciiParser->tableData().columnInfos())
|
||||
{
|
||||
m_allResultAddresses.push_back(s.summaryAddress);
|
||||
m_allResultAddresses.insert(s.summaryAddress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,12 +95,14 @@ bool RifReaderObservedData::values(const RifEclipseSummaryAddress& resultAddress
|
||||
{
|
||||
size_t columnIndex = m_allResultAddresses.size();
|
||||
|
||||
for (size_t i = 0; i < m_allResultAddresses.size(); i++)
|
||||
int i = 0;
|
||||
for(auto& address : m_allResultAddresses)
|
||||
{
|
||||
if (resultAddress == m_allResultAddresses[i])
|
||||
if (address == resultAddress)
|
||||
{
|
||||
columnIndex = i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (columnIndex != m_allResultAddresses.size())
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<RifEclipseSummaryAddress>& RifSummaryReaderInterface::allResultAddresses() const
|
||||
const std::set<RifEclipseSummaryAddress>& RifSummaryReaderInterface::allResultAddresses() const
|
||||
{
|
||||
return m_allResultAddresses;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
|
||||
class QDateTime;
|
||||
@@ -37,7 +38,7 @@ class RifSummaryReaderInterface : public cvf::Object
|
||||
{
|
||||
public:
|
||||
bool hasAddress(const RifEclipseSummaryAddress& resultAddress) const;
|
||||
const std::vector<RifEclipseSummaryAddress>& allResultAddresses() const;
|
||||
const std::set<RifEclipseSummaryAddress>& allResultAddresses() const;
|
||||
RifEclipseSummaryAddress errorAddress(const RifEclipseSummaryAddress& resultAddress) const;
|
||||
|
||||
virtual const std::vector<time_t>& timeSteps(const RifEclipseSummaryAddress& resultAddress) const = 0;
|
||||
@@ -51,6 +52,6 @@ public:
|
||||
static std::vector<QDateTime> fromTimeT(const std::vector<time_t>& timeSteps);
|
||||
|
||||
protected:
|
||||
std::vector<RifEclipseSummaryAddress> m_allResultAddresses; // Result and error addresses
|
||||
std::set<RifEclipseSummaryAddress> m_allResultAddresses; // Result and error addresses
|
||||
std::set<RifEclipseSummaryAddress> m_allErrorAddresses; // Error addresses
|
||||
};
|
||||
|
||||
@@ -733,7 +733,7 @@ void RimWellPltPlot::addStackedCurve(const QString& curveName,
|
||||
curve->setSymbol(RimSummaryCurveAppearanceCalculator::cycledSymbol(curveGroupId));
|
||||
}
|
||||
|
||||
curve->setSymbolSkipDinstance(10);
|
||||
curve->setSymbolSkipDistance(10);
|
||||
plotTrack->addCurve(curve);
|
||||
}
|
||||
|
||||
@@ -1018,11 +1018,11 @@ void RimWellPltPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
|
||||
caf::PdmUiGroup* legendAndAxisGroup = uiOrdering.addNewGroup("Legend and Axis");
|
||||
legendAndAxisGroup->setCollapsedByDefault(true);
|
||||
|
||||
m_wellLogPlot->uiOrderingForPlot(*legendAndAxisGroup);
|
||||
m_wellLogPlot->uiOrderingForPlotSettings(*legendAndAxisGroup);
|
||||
|
||||
track->uiOrderingForVisibleXRange(*legendAndAxisGroup);
|
||||
|
||||
m_wellLogPlot->uiOrderingForVisibleDepthRange(*legendAndAxisGroup);
|
||||
m_wellLogPlot->uiOrderingForDepthAxis(*legendAndAxisGroup);
|
||||
}
|
||||
|
||||
uiOrdering.skipRemainingFields(true);
|
||||
|
||||
@@ -781,11 +781,11 @@ void RimWellRftPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
|
||||
caf::PdmUiGroup* legendAndAxisGroup = uiOrdering.addNewGroup("Legend and Axis");
|
||||
legendAndAxisGroup->setCollapsedByDefault(true);
|
||||
|
||||
m_wellLogPlot->uiOrderingForPlot(*legendAndAxisGroup);
|
||||
m_wellLogPlot->uiOrderingForPlotSettings(*legendAndAxisGroup);
|
||||
|
||||
track->uiOrderingForVisibleXRange(*legendAndAxisGroup);
|
||||
|
||||
m_wellLogPlot->uiOrderingForVisibleDepthRange(*legendAndAxisGroup);
|
||||
m_wellLogPlot->uiOrderingForDepthAxis(*legendAndAxisGroup);
|
||||
}
|
||||
|
||||
uiOrdering.skipRemainingFields(true);
|
||||
|
||||
@@ -547,7 +547,7 @@ QString Rim3dOverlayInfoConfig::resultInfoText(const HistogramData& histData, Ri
|
||||
infoText += QString("<b>Cell Property:</b> %1 ").arg(propName);
|
||||
infoText += QString("<br><b>Statistics:</b> ") + timeRangeText + " and " + m_statisticsCellRange().uiText();
|
||||
infoText += QString("<table border=0 cellspacing=5 >"
|
||||
"<tr> <td>Min</td> <td>P10</td> <td>Mean</td> <td>P90</td> <td>Max</td> <td>Sum</td> </tr>"
|
||||
"<tr> <td>Min</td> <td>P90</td> <td>Mean</td> <td>P10</td> <td>Max</td> <td>Sum</td> </tr>"
|
||||
"<tr> <td>%1</td> <td> %2</td> <td> %3</td> <td> %4</td> <td> %5</td> <td> %6</td> </tr>"
|
||||
"</table>").arg(histData.min).arg(histData.p10).arg(histData.mean).arg(histData.p90).arg(histData.max).arg(histData.sum);
|
||||
|
||||
@@ -650,7 +650,7 @@ QString Rim3dOverlayInfoConfig::resultInfoText(const HistogramData& histData, Ri
|
||||
|
||||
infoText += QString("<br><b>Statistics:</b> ") + m_statisticsTimeRange().uiText() + " and " + m_statisticsCellRange().uiText();
|
||||
infoText += QString("<table border=0 cellspacing=5 >"
|
||||
"<tr> <td>Min</td> <td>P10</td> <td>Mean</td> <td>P90</td> <td>Max</td> <td>Sum</td> </tr>"
|
||||
"<tr> <td>Min</td> <td>P90</td> <td>Mean</td> <td>P10</td> <td>Max</td> <td>Sum</td> </tr>"
|
||||
"<tr> <td>%1</td> <td> %2</td> <td> %3</td> <td> %4</td> <td> %5</td> <td> %6</td> </tr>"
|
||||
"</table>").arg(histData.min).arg(histData.p10).arg(histData.mean).arg(histData.p90).arg(histData.max).arg(histData.sum);
|
||||
}
|
||||
|
||||
@@ -488,6 +488,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
|
||||
menuBuilder << "RicImportSummaryCasesFeature";
|
||||
menuBuilder << "RicImportSummaryGroupFeature";
|
||||
menuBuilder << "RicImportEnsembleFeature";
|
||||
menuBuilder << "RicNewDerivedEnsembleFeature";
|
||||
}
|
||||
else if (dynamic_cast<RimSummaryCaseCollection*>(uiItem))
|
||||
{
|
||||
@@ -498,6 +499,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
|
||||
menuBuilder << "RicImportEnsembleFeature";
|
||||
menuBuilder.subMenuEnd();
|
||||
menuBuilder.addSeparator();
|
||||
menuBuilder << "RicNewDerivedEnsembleFeature";
|
||||
menuBuilder << "RicNewSummaryPlotFeature";
|
||||
menuBuilder << "RicNewSummaryCrossPlotFeature";
|
||||
menuBuilder.addSeparator();
|
||||
@@ -677,6 +679,7 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
|
||||
menuBuilder << "RicShowPlotDataFeature";
|
||||
menuBuilder << "RicShowTotalAllocationDataFeature";
|
||||
|
||||
menuBuilder << "RicNewDerivedEnsembleFeature";
|
||||
menuBuilder << "RicNewSummaryPlotFeature";
|
||||
menuBuilder << "RicNewSummaryCrossPlotFeature";
|
||||
menuBuilder << "RicSummaryCurveSwitchAxisFeature";
|
||||
|
||||
@@ -112,6 +112,8 @@ RimPlotCurve::RimPlotCurve()
|
||||
|
||||
CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Contribute To Legend", "", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_symbolSize, "SymbolSize", 6, "Symbol Size", "", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_showErrorBars, "ShowErrorBars", true, "Show Error Bars", "", "", "");
|
||||
|
||||
m_qwtPlotCurve = new RiuRimQwtPlotCurve(this);
|
||||
@@ -416,6 +418,9 @@ void RimPlotCurve::updateCurveAppearance()
|
||||
case SYMBOL_XCROSS:
|
||||
style = QwtSymbol::XCross;
|
||||
break;
|
||||
case SYMBOL_DOWN_TRIANGLE:
|
||||
style = QwtSymbol::DTriangle;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -424,7 +429,7 @@ void RimPlotCurve::updateCurveAppearance()
|
||||
// QwtPlotCurve will take ownership of the symbol
|
||||
symbol = new RiuCurveQwtSymbol(style, m_symbolLabel);
|
||||
|
||||
symbol->setSize(6, 6);
|
||||
symbol->setSize(m_symbolSize, m_symbolSize);
|
||||
symbol->setColor(curveColor);
|
||||
}
|
||||
|
||||
@@ -541,7 +546,7 @@ RimPlotCurve::PointSymbolEnum RimPlotCurve::symbol()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimPlotCurve::setSymbolSkipDinstance(float distance)
|
||||
void RimPlotCurve::setSymbolSkipDistance(float distance)
|
||||
{
|
||||
m_symbolSkipPixelDistance = distance;
|
||||
}
|
||||
@@ -554,6 +559,14 @@ void RimPlotCurve::setSymbolLabel(const QString& label)
|
||||
m_symbolLabel = label;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimPlotCurve::setSymbolSize(int sizeInPixels)
|
||||
{
|
||||
m_symbolSize = sizeInPixels;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -571,7 +584,7 @@ void RimPlotCurve::resetAppearance()
|
||||
setLineThickness(2);
|
||||
setLineStyle(STYLE_SOLID);
|
||||
setSymbol(SYMBOL_NONE);
|
||||
setSymbolSkipDinstance(10);
|
||||
setSymbolSkipDistance(10);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -53,7 +53,8 @@ public:
|
||||
SYMBOL_DIAMOND,
|
||||
SYMBOL_TRIANGLE,
|
||||
SYMBOL_CROSS,
|
||||
SYMBOL_XCROSS
|
||||
SYMBOL_XCROSS,
|
||||
SYMBOL_DOWN_TRIANGLE
|
||||
};
|
||||
|
||||
enum CurveInterpolationEnum
|
||||
@@ -80,8 +81,9 @@ public:
|
||||
void setLineStyle(LineStyleEnum lineStyle);
|
||||
void setSymbol(PointSymbolEnum symbolStyle);
|
||||
PointSymbolEnum symbol();
|
||||
void setSymbolSkipDinstance(float distance);
|
||||
void setSymbolSkipDistance(float distance);
|
||||
void setSymbolLabel(const QString& label);
|
||||
void setSymbolSize(int sizeInPixels);
|
||||
void setLineThickness(int thickness);
|
||||
void resetAppearance();
|
||||
|
||||
@@ -133,6 +135,7 @@ protected:
|
||||
caf::PdmField<QString> m_customCurveName;
|
||||
caf::PdmField<bool> m_showLegend;
|
||||
QString m_symbolLabel;
|
||||
caf::PdmField<int> m_symbolSize;
|
||||
|
||||
caf::PdmField<bool> m_isUsingAutoName;
|
||||
caf::PdmField<cvf::Color3f> m_curveColor;
|
||||
|
||||
@@ -624,6 +624,15 @@ std::vector<RimSummaryCaseCollection*> RimProject::summaryGroups() const
|
||||
return groups;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimSummaryCaseMainCollection* RimProject::firstSummaryCaseMainCollection() const
|
||||
{
|
||||
if (oilFields.empty()) return nullptr;
|
||||
return oilFields[0]->summaryCaseMainCollection;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -48,6 +48,7 @@ class RimOilField;
|
||||
class RimScriptCollection;
|
||||
class RimSummaryCase;
|
||||
class RimSummaryCaseCollection;
|
||||
class RimSummaryCaseMainCollection;
|
||||
class Rim3dView;
|
||||
class RimGridView;
|
||||
class RimViewLinker;
|
||||
@@ -108,7 +109,8 @@ public:
|
||||
|
||||
std::vector<RimSummaryCase*> allSummaryCases() const;
|
||||
std::vector<RimSummaryCaseCollection*> summaryGroups() const;
|
||||
|
||||
RimSummaryCaseMainCollection* firstSummaryCaseMainCollection() const;
|
||||
|
||||
void allVisibleViews(std::vector<Rim3dView*>& views);
|
||||
void allVisibleGridViews(std::vector<RimGridView*>& views);
|
||||
void allNotLinkedViews(std::vector<RimGridView*>& views);
|
||||
|
||||
@@ -65,6 +65,23 @@ void RimViewWindow::removeMdiWindowFromMdiArea()
|
||||
if ( m_windowController() ) m_windowController->removeWindowFromMDI();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimViewWindow::windowTitle()
|
||||
{
|
||||
if (this->userDescriptionField())
|
||||
{
|
||||
caf::PdmUiFieldHandle* uiFieldHandle = this->userDescriptionField()->uiCapability();
|
||||
if (uiFieldHandle)
|
||||
{
|
||||
QVariant v = uiFieldHandle->uiValue();
|
||||
return v.toString();
|
||||
}
|
||||
}
|
||||
return QString("");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -168,15 +185,7 @@ void RimViewWindow::updateMdiWindowTitle()
|
||||
{
|
||||
if ( viewWidget() )
|
||||
{
|
||||
if ( this->userDescriptionField() )
|
||||
{
|
||||
caf::PdmUiFieldHandle* uiFieldHandle = this->userDescriptionField()->uiCapability();
|
||||
if ( uiFieldHandle )
|
||||
{
|
||||
QVariant v = uiFieldHandle->uiValue();
|
||||
viewWidget()->setWindowTitle(v.toString());
|
||||
}
|
||||
}
|
||||
viewWidget()->setWindowTitle(windowTitle());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ protected:
|
||||
///////// Interface for the Window controller
|
||||
friend class RimMdiWindowController;
|
||||
|
||||
QString windowTitle();
|
||||
virtual QWidget* createViewWidget(QWidget* mainWindowParent) = 0;
|
||||
virtual void updateViewWidgetAfterCreation() {};
|
||||
virtual void updateMdiWindowTitle(); // Has real default implementation
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "RiuWellLogPlot.h"
|
||||
#include "RiuWellLogTrack.h"
|
||||
|
||||
#include "cafPdmUiComboBoxEditor.h"
|
||||
#include "cvfAssert.h"
|
||||
|
||||
#include <math.h>
|
||||
@@ -70,16 +71,19 @@ RimWellLogPlot::RimWellLogPlot()
|
||||
CAF_PDM_InitField(&m_userName, "PlotDescription", QString("Well Log Plot"),"Name", "", "", "");
|
||||
|
||||
caf::AppEnum< RimWellLogPlot::DepthTypeEnum > depthType = MEASURED_DEPTH;
|
||||
CAF_PDM_InitField(&m_depthType, "DepthType", depthType, "Depth type", "", "", "");
|
||||
CAF_PDM_InitField(&m_depthType, "DepthType", depthType, "Type", "", "", "");
|
||||
|
||||
caf::AppEnum< RiaDefines::DepthUnitType > depthUnit = RiaDefines::UNIT_METER;
|
||||
CAF_PDM_InitField(&m_depthUnit, "DepthUnit", depthUnit, "Depth unit", "", "", "");
|
||||
CAF_PDM_InitField(&m_depthUnit, "DepthUnit", depthUnit, "Unit", "", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_minVisibleDepth, "MinimumDepth", 0.0, "Min", "", "", "");
|
||||
CAF_PDM_InitField(&m_maxVisibleDepth, "MaximumDepth", 1000.0, "Max", "", "", "");
|
||||
CAF_PDM_InitField(&m_isAutoScaleDepthEnabled, "AutoScaleDepthEnabled", true, "Auto Scale", "", "", "");
|
||||
m_isAutoScaleDepthEnabled.uiCapability()->setUiHidden(true);
|
||||
CAF_PDM_InitField(&m_showTitleInPlot, "ShowTitleInPlot", false, "Show Title", "", "", "");
|
||||
CAF_PDM_InitField(&m_showTrackLegends, "ShowTrackLegends", true, "Show Legends", "", "", "");
|
||||
CAF_PDM_InitField(&m_trackLegendsHorizontal, "TrackLegendsHorizontal", false, "Legend Orientation", "", "", "");
|
||||
m_trackLegendsHorizontal.uiCapability()->setUiEditorTypeName(caf::PdmUiComboBoxEditor::uiEditorTypeName());
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_tracks, "Tracks", "", "", "", "");
|
||||
m_tracks.uiCapability()->setUiHidden(true);
|
||||
@@ -113,6 +117,13 @@ void RimWellLogPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c
|
||||
|
||||
m_isAutoScaleDepthEnabled = false;
|
||||
}
|
||||
else if (changedField == &m_showTitleInPlot ||
|
||||
changedField == &m_showTrackLegends ||
|
||||
changedField == &m_trackLegendsHorizontal)
|
||||
{
|
||||
updateTracks();
|
||||
if (m_viewer) m_viewer->updateChildrenLayout();
|
||||
}
|
||||
else if (changedField == &m_isAutoScaleDepthEnabled)
|
||||
{
|
||||
updateDepthZoom();
|
||||
@@ -121,8 +132,7 @@ void RimWellLogPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c
|
||||
{
|
||||
updateMdiWindowTitle();
|
||||
}
|
||||
|
||||
if ( changedField == &m_depthType )
|
||||
else if ( changedField == &m_depthType )
|
||||
{
|
||||
RimWellAllocationPlot* wellAllocPlot;
|
||||
firstAncestorOrThisOfType(wellAllocPlot);
|
||||
@@ -134,18 +144,12 @@ void RimWellLogPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c
|
||||
updateDepthZoom();
|
||||
}
|
||||
}
|
||||
if ( changedField == &m_depthUnit)
|
||||
else if ( changedField == &m_depthUnit)
|
||||
{
|
||||
updateTracks();
|
||||
updateDepthZoom();
|
||||
}
|
||||
|
||||
if ( changedField == &m_showTrackLegends)
|
||||
{
|
||||
updateTracks();
|
||||
if (m_viewer) m_viewer->updateChildrenLayout();
|
||||
}
|
||||
|
||||
RimWellRftPlot* rftPlot(nullptr);
|
||||
this->firstAncestorOrThisOfType(rftPlot);
|
||||
|
||||
@@ -189,6 +193,11 @@ QList<caf::PdmOptionItemInfo> RimWellLogPlot::calculateValueOptions(const caf::P
|
||||
options.push_back(caf::PdmOptionItemInfo(UnitAppEnum::uiText(RiaDefines::UNIT_METER), RiaDefines::UNIT_METER));
|
||||
options.push_back(caf::PdmOptionItemInfo(UnitAppEnum::uiText(RiaDefines::UNIT_FEET), RiaDefines::UNIT_FEET));
|
||||
}
|
||||
else if (fieldNeedingOptions == &m_trackLegendsHorizontal)
|
||||
{
|
||||
options.push_back(caf::PdmOptionItemInfo("Vertical", false));
|
||||
options.push_back(caf::PdmOptionItemInfo("Horizontal", true));
|
||||
}
|
||||
|
||||
(*useOptionsOnly) = true;
|
||||
return options;
|
||||
@@ -556,23 +565,14 @@ bool RimWellLogPlot::isPltPlotChild() const
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogPlot::uiOrderingForVisibleDepthRange(caf::PdmUiOrdering& uiOrdering)
|
||||
{
|
||||
caf::PdmUiGroup* gridGroup = uiOrdering.addNewGroup("Visible Depth Range");
|
||||
gridGroup->add(&m_minVisibleDepth);
|
||||
gridGroup->add(&m_maxVisibleDepth);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogPlot::uiOrderingForPlot(caf::PdmUiOrdering& uiOrdering)
|
||||
void RimWellLogPlot::uiOrderingForDepthAxis(caf::PdmUiOrdering& uiOrdering)
|
||||
{
|
||||
caf::PdmUiGroup* gridGroup = uiOrdering.addNewGroup("Depth Axis");
|
||||
|
||||
RimWellRftPlot* rftp = rftPlot();
|
||||
|
||||
if (!(rftp || pltPlot()))
|
||||
{
|
||||
uiOrdering.add(&m_depthType);
|
||||
gridGroup->add(&m_depthType);
|
||||
}
|
||||
|
||||
RimWellAllocationPlot* wap;
|
||||
@@ -580,10 +580,22 @@ void RimWellLogPlot::uiOrderingForPlot(caf::PdmUiOrdering& uiOrdering)
|
||||
|
||||
if (!(wap || rftp))
|
||||
{
|
||||
uiOrdering.add(&m_depthUnit);
|
||||
gridGroup->add(&m_depthUnit);
|
||||
}
|
||||
gridGroup->add(&m_minVisibleDepth);
|
||||
gridGroup->add(&m_maxVisibleDepth);
|
||||
}
|
||||
|
||||
uiOrdering.add(&m_showTrackLegends);
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogPlot::uiOrderingForPlotSettings(caf::PdmUiOrdering& uiOrdering)
|
||||
{
|
||||
caf::PdmUiGroup* titleAndLegendsGroup = uiOrdering.addNewGroup("Title and Legends");
|
||||
titleAndLegendsGroup->add(&m_showTitleInPlot);
|
||||
titleAndLegendsGroup->add(&m_showTrackLegends);
|
||||
titleAndLegendsGroup->add(&m_trackLegendsHorizontal);
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -602,8 +614,8 @@ void RimWellLogPlot::depthZoomMinMax(double* minimumDepth, double* maximumDepth)
|
||||
void RimWellLogPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
|
||||
{
|
||||
uiOrdering.add(&m_userName);
|
||||
uiOrderingForPlot(uiOrdering);
|
||||
uiOrderingForVisibleDepthRange(uiOrdering);
|
||||
uiOrderingForDepthAxis(uiOrdering);
|
||||
uiOrderingForPlotSettings(uiOrdering);
|
||||
|
||||
uiOrdering.skipRemainingFields(true);
|
||||
}
|
||||
@@ -615,8 +627,8 @@ void RimWellLogPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
|
||||
void RimWellLogPlot::onLoadDataAndUpdate()
|
||||
{
|
||||
updateMdiWindowVisibility();
|
||||
|
||||
updateTracks();
|
||||
updatePlotTitle();
|
||||
updateTracks();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -834,10 +846,18 @@ QString RimWellLogPlot::depthPlotTitle() const
|
||||
return depthTitle;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellLogPlot::isPlotTitleVisible() const
|
||||
{
|
||||
return m_showTitleInPlot();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellLogPlot::isTrackLegendsVisible() const
|
||||
bool RimWellLogPlot::areTrackLegendsVisible() const
|
||||
{
|
||||
return m_showTrackLegends();
|
||||
}
|
||||
@@ -850,6 +870,14 @@ void RimWellLogPlot::setTrackLegendsVisible(bool doShow)
|
||||
m_showTrackLegends = doShow;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimWellLogPlot::areTrackLegendsHorizontal() const
|
||||
{
|
||||
return m_trackLegendsHorizontal;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -903,3 +931,14 @@ void RimWellLogPlot::updateDisabledDepthTypes()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogPlot::updatePlotTitle()
|
||||
{
|
||||
if (m_viewer)
|
||||
{
|
||||
m_viewer->setPlotTitle(this->windowTitle());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,8 +70,10 @@ public:
|
||||
|
||||
|
||||
QString depthPlotTitle() const;
|
||||
bool isTrackLegendsVisible() const;
|
||||
bool isPlotTitleVisible() const;
|
||||
bool areTrackLegendsVisible() const;
|
||||
void setTrackLegendsVisible(bool doShow);
|
||||
bool areTrackLegendsHorizontal() const;
|
||||
|
||||
void addTrack(RimWellLogTrack* track);
|
||||
void insertTrack(RimWellLogTrack* track, size_t index);
|
||||
@@ -109,8 +111,8 @@ public:
|
||||
RimWellPltPlot* pltPlot() const;
|
||||
bool isPltPlotChild() const;
|
||||
|
||||
void uiOrderingForVisibleDepthRange(caf::PdmUiOrdering& uiOrdering);
|
||||
void uiOrderingForPlot(caf::PdmUiOrdering& uiOrdering);
|
||||
void uiOrderingForDepthAxis(caf::PdmUiOrdering& uiOrdering);
|
||||
void uiOrderingForPlotSettings(caf::PdmUiOrdering& uiOrdering);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -131,7 +133,7 @@ private:
|
||||
void detachAllCurves();
|
||||
|
||||
void updateDisabledDepthTypes();
|
||||
|
||||
void updatePlotTitle();
|
||||
public: // Needed by RiuWellAllocation Plot
|
||||
// RimViewWindow overrides
|
||||
|
||||
@@ -150,7 +152,9 @@ private:
|
||||
caf::PdmField<double> m_minVisibleDepth;
|
||||
caf::PdmField<double> m_maxVisibleDepth;
|
||||
caf::PdmField<bool> m_isAutoScaleDepthEnabled;
|
||||
caf::PdmField<bool> m_showTitleInPlot;
|
||||
caf::PdmField<bool> m_showTrackLegends;
|
||||
caf::PdmField<bool> m_trackLegendsHorizontal;
|
||||
|
||||
double m_minAvailableDepth;
|
||||
double m_maxAvailableDepth;
|
||||
|
||||
@@ -104,6 +104,17 @@ namespace caf
|
||||
addItem(RigWellPathFormations::LEVEL10, "LEVEL10", "Formation 10");
|
||||
setDefault(RigWellPathFormations::ALL);
|
||||
}
|
||||
|
||||
template<>
|
||||
void AppEnum< RimWellLogTrack::WidthScaleFactor >::setUp()
|
||||
{
|
||||
addItem(RimWellLogTrack::EXTRA_NARROW_TRACK, "EXTRA_NARROW_TRACK", "Extra Narrow");
|
||||
addItem(RimWellLogTrack::NARROW_TRACK, "NARROW_TRACK", "Narrow");
|
||||
addItem(RimWellLogTrack::NORMAL_TRACK, "NORMAL_TRACK", "Normal");
|
||||
addItem(RimWellLogTrack::WIDE_TRACK, "WIDE_TRACK", "Wide");
|
||||
addItem(RimWellLogTrack::EXTRA_WIDE_TRACK, "EXTRA_WIDE_TRACK", "Extra wide");
|
||||
setDefault(RimWellLogTrack::NORMAL_TRACK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -155,6 +166,8 @@ RimWellLogTrack::RimWellLogTrack()
|
||||
|
||||
CAF_PDM_InitField(&m_showformationFluids, "ShowFormationFluids", false, "Show Fluids", "", "", "");
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_widthScaleFactor, "Width", "Track Width", "", "Set width of track. ", "");
|
||||
|
||||
m_formationsForCaseWithSimWellOnly = false;
|
||||
}
|
||||
|
||||
@@ -221,19 +234,12 @@ void RimWellLogTrack::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
|
||||
m_wellLogTrackPlotWidget->setVisible(m_show());
|
||||
}
|
||||
|
||||
RimWellLogPlot* wellLogPlot;
|
||||
this->firstAncestorOrThisOfType(wellLogPlot);
|
||||
if (wellLogPlot)
|
||||
{
|
||||
wellLogPlot->calculateAvailableDepthRange();
|
||||
wellLogPlot->updateDepthZoom();
|
||||
|
||||
RiuWellLogPlot* wellLogPlotViewer = dynamic_cast<RiuWellLogPlot*>(wellLogPlot->viewWidget());
|
||||
if (wellLogPlotViewer)
|
||||
{
|
||||
wellLogPlotViewer->updateChildrenLayout();
|
||||
}
|
||||
}
|
||||
updateParentPlotLayout();
|
||||
}
|
||||
else if (changedField == &m_widthScaleFactor)
|
||||
{
|
||||
updateParentPlotLayout();
|
||||
|
||||
}
|
||||
else if (changedField == &m_visibleXRangeMin || changedField == &m_visibleXRangeMax)
|
||||
{
|
||||
@@ -241,6 +247,7 @@ void RimWellLogTrack::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
|
||||
m_wellLogTrackPlotWidget->replot();
|
||||
m_isAutoScaleXEnabled = false;
|
||||
updateEditors();
|
||||
updateParentPlotLayout();
|
||||
}
|
||||
else if (changedField == &m_isAutoScaleXEnabled)
|
||||
{
|
||||
@@ -357,6 +364,23 @@ void RimWellLogTrack::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogTrack::updateParentPlotLayout()
|
||||
{
|
||||
RimWellLogPlot* wellLogPlot;
|
||||
this->firstAncestorOrThisOfType(wellLogPlot);
|
||||
if (wellLogPlot)
|
||||
{
|
||||
RiuWellLogPlot* wellLogPlotViewer = dynamic_cast<RiuWellLogPlot*>(wellLogPlot->viewWidget());
|
||||
if (wellLogPlotViewer)
|
||||
{
|
||||
wellLogPlotViewer->updateChildrenLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -627,6 +651,33 @@ void RimWellLogTrack::setXAxisTitle(const QString& text)
|
||||
m_xAxisTitle = text;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWellLogTrack::depthPlotTitle() const
|
||||
{
|
||||
RimWellLogPlot* parent;
|
||||
this->firstAncestorOrThisOfTypeAsserted(parent);
|
||||
|
||||
return parent->depthPlotTitle();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RimWellLogTrack::widthScaleFactor() const
|
||||
{
|
||||
return static_cast<int>(m_widthScaleFactor());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogTrack::setWidthScaleFactor(WidthScaleFactor scaleFactor)
|
||||
{
|
||||
m_widthScaleFactor = scaleFactor;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -735,6 +786,8 @@ void RimWellLogTrack::calculateXZoomRangeAndUpdateQwt()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimWellLogTrack::applyXZoomFromVisibleRange()
|
||||
{
|
||||
if (!m_wellLogTrackPlotWidget) return;
|
||||
|
||||
m_wellLogTrackPlotWidget->setXRange(m_visibleXRangeMin, m_visibleXRangeMax);
|
||||
m_wellLogTrackPlotWidget->replot();
|
||||
}
|
||||
@@ -851,7 +904,6 @@ RimWellLogCurve* RimWellLogTrack::curveDefinitionFromCurve(const QwtPlotCurve* c
|
||||
void RimWellLogTrack::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
|
||||
{
|
||||
uiOrdering.add(&m_userName);
|
||||
|
||||
caf::PdmUiGroup* formationGroup = uiOrdering.addNewGroup("Zonation/Formation Names");
|
||||
|
||||
formationGroup->add(&m_showFormations);
|
||||
@@ -901,6 +953,9 @@ void RimWellLogTrack::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
|
||||
|
||||
uiOrderingForVisibleXRange(uiOrdering);
|
||||
|
||||
caf::PdmUiGroup* trackSettingsGroup = uiOrdering.addNewGroup("Track Settings");
|
||||
trackSettingsGroup->add(&m_widthScaleFactor);
|
||||
|
||||
uiOrdering.skipRemainingFields(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
|
||||
enum TrajectoryType { WELL_PATH, SIMULATION_WELL };
|
||||
enum FormationSource { CASE, WELL_PICK_FILTER };
|
||||
enum WidthScaleFactor { EXTRA_NARROW_TRACK = 2, NARROW_TRACK = 3, NORMAL_TRACK = 4, WIDE_TRACK = 6, EXTRA_WIDE_TRACK = 8};
|
||||
|
||||
void setDescription(const QString& description);
|
||||
bool isVisible();
|
||||
@@ -78,9 +79,12 @@ public:
|
||||
void takeOutCurve(RimWellLogCurve* curve);
|
||||
void deleteAllCurves();
|
||||
|
||||
size_t curveIndex(RimWellLogCurve* curve);
|
||||
size_t curveCount() { return curves.size(); }
|
||||
void setXAxisTitle(const QString& text);
|
||||
size_t curveIndex(RimWellLogCurve* curve);
|
||||
size_t curveCount() { return curves.size(); }
|
||||
void setXAxisTitle(const QString& text);
|
||||
QString depthPlotTitle() const;
|
||||
int widthScaleFactor() const;
|
||||
void setWidthScaleFactor(WidthScaleFactor scaleFactor);
|
||||
|
||||
void setFormationWellPath(RimWellPath* wellPath);
|
||||
void setFormationSimWellName(const QString& simWellName);
|
||||
@@ -127,6 +131,7 @@ public:
|
||||
|
||||
private:
|
||||
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
|
||||
void updateParentPlotLayout();
|
||||
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override;
|
||||
|
||||
virtual caf::PdmFieldHandle* objectToggleField() override;
|
||||
@@ -179,7 +184,7 @@ private:
|
||||
caf::PdmField<int> m_formationBranchIndex;
|
||||
caf::PdmField<caf::AppEnum<RigWellPathFormations::FormationLevel>> m_formationLevel;
|
||||
caf::PdmField<bool> m_showformationFluids;
|
||||
|
||||
caf::PdmField<caf::AppEnum<WidthScaleFactor>> m_widthScaleFactor;
|
||||
caf::PdmField<bool> m_formationBranchDetection;
|
||||
|
||||
bool m_formationsForCaseWithSimWellOnly;
|
||||
|
||||
@@ -36,6 +36,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilter.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilterCollection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatistics.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatisticsCase.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCase.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCaseCollection.h
|
||||
)
|
||||
|
||||
set (SOURCE_GROUP_SOURCE_FILES
|
||||
@@ -75,6 +77,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilter.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleCurveFilterCollection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatistics.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimEnsembleStatisticsCase.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCase.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/RimDerivedEnsembleCaseCollection.cpp
|
||||
)
|
||||
|
||||
list(APPEND CODE_HEADER_FILES
|
||||
|
||||
@@ -86,7 +86,7 @@ void RifCalculatedSummaryCurveReader::buildMetaData()
|
||||
|
||||
for (RimSummaryCalculation* calc : m_calculationCollection->calculations())
|
||||
{
|
||||
m_allResultAddresses.push_back(RifEclipseSummaryAddress::calculatedAddress(calc->description().toStdString()));
|
||||
m_allResultAddresses.insert(RifEclipseSummaryAddress::calculatedAddress(calc->description().toStdString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RimDerivedEnsembleCase.h"
|
||||
|
||||
#include "RiaSummaryTools.h"
|
||||
#include "RiaTimeHistoryCurveMerger.h"
|
||||
|
||||
#include "RifDerivedEnsembleReader.h"
|
||||
|
||||
#include "RimDerivedEnsembleCaseCollection.h"
|
||||
#include "RimMainPlotCollection.h"
|
||||
#include "RimOilField.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimSummaryCaseMainCollection.h"
|
||||
#include "RimSummaryPlotCollection.h"
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
|
||||
#include "cvfAssert.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
CAF_PDM_ABSTRACT_SOURCE_INIT(RimDerivedEnsembleCase, "RimDerivedEnsembleCase");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<time_t> RimDerivedEnsembleCase::EMPTY_TIME_STEPS_VECTOR;
|
||||
const std::vector<double> RimDerivedEnsembleCase::EMPTY_VALUES_VECTOR;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDerivedEnsembleCase::RimDerivedEnsembleCase() : m_summaryCase1(nullptr), m_summaryCase2(nullptr)
|
||||
{
|
||||
CAF_PDM_InitObject("Summary Case",":/SummaryCase16x16.png","","");
|
||||
CAF_PDM_InitFieldNoDefault(&m_summaryCase1, "SummaryCase1", "SummaryCase1", "", "", "");
|
||||
CAF_PDM_InitFieldNoDefault(&m_summaryCase2, "SummaryCase2", "SummaryCase2", "", "", "");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDerivedEnsembleCase::~RimDerivedEnsembleCase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCase::setInUse(bool inUse)
|
||||
{
|
||||
m_inUse = inUse;
|
||||
|
||||
if (!m_inUse)
|
||||
{
|
||||
m_summaryCase1 = nullptr;
|
||||
m_summaryCase2 = nullptr;
|
||||
m_data.clear();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDerivedEnsembleCase::isInUse() const
|
||||
{
|
||||
return m_inUse;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCase::setSummaryCases(RimSummaryCase* sumCase1, RimSummaryCase* sumCase2)
|
||||
{
|
||||
if (!sumCase1 || !sumCase2) return;
|
||||
m_summaryCase1 = sumCase1;
|
||||
m_summaryCase2 = sumCase2;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDerivedEnsembleCase::needsCalculation(const RifEclipseSummaryAddress& address) const
|
||||
{
|
||||
return m_data.count(address) == 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<time_t>& RimDerivedEnsembleCase::timeSteps(const RifEclipseSummaryAddress& address) const
|
||||
{
|
||||
if (m_data.count(address) == 0) return EMPTY_TIME_STEPS_VECTOR;
|
||||
return m_data.at(address).first;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
const std::vector<double>& RimDerivedEnsembleCase::values(const RifEclipseSummaryAddress& address) const
|
||||
{
|
||||
if (m_data.count(address) == 0) return EMPTY_VALUES_VECTOR;
|
||||
return m_data.at(address).second;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCase::calculate(const RifEclipseSummaryAddress& address)
|
||||
{
|
||||
clearData(address);
|
||||
|
||||
RifSummaryReaderInterface* reader1 = m_summaryCase1 ? m_summaryCase1->summaryReader() : nullptr;
|
||||
RifSummaryReaderInterface* reader2 = m_summaryCase2 ? m_summaryCase2->summaryReader() : nullptr;
|
||||
if (!reader1 || !reader2 || !parentEnsemble()) return;
|
||||
|
||||
RiaTimeHistoryCurveMerger merger;
|
||||
std::vector<double> values1;
|
||||
std::vector<double> values2;
|
||||
DerivedEnsembleOperator op = parentEnsemble()->op();
|
||||
|
||||
reader1->values(address, &values1);
|
||||
reader2->values(address, &values2);
|
||||
|
||||
merger.addCurveData(values1, reader1->timeSteps(address));
|
||||
merger.addCurveData(values2, reader2->timeSteps(address));
|
||||
merger.computeInterpolatedValues();
|
||||
|
||||
std::vector<double>& allValues1 = merger.interpolatedCurveValuesForAllTimeSteps(0);
|
||||
std::vector<double>& allValues2 = merger.interpolatedCurveValuesForAllTimeSteps(1);
|
||||
|
||||
size_t sampleCount = merger.allTimeSteps().size();
|
||||
std::vector<double> calculatedValues;
|
||||
calculatedValues.reserve(sampleCount);
|
||||
for (size_t i = 0; i < sampleCount; i++)
|
||||
{
|
||||
if (op == DERIVED_ENSEMBLE_SUB)
|
||||
{
|
||||
calculatedValues.push_back(allValues1[i] - allValues2[i]);
|
||||
}
|
||||
else if (op == DERIVED_ENSEMBLE_ADD)
|
||||
{
|
||||
calculatedValues.push_back(allValues1[i] + allValues2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
auto& dataItem = m_data[address];
|
||||
dataItem.first = merger.allTimeSteps();
|
||||
dataItem.second = calculatedValues;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimDerivedEnsembleCase::caseName()
|
||||
{
|
||||
auto case1Name = m_summaryCase1->caseName();
|
||||
auto case2Name = m_summaryCase2->caseName();
|
||||
|
||||
if (case1Name == case2Name) return case1Name;
|
||||
else return QString("%1/%2").arg(case1Name).arg(case2Name);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCase::createSummaryReaderInterface()
|
||||
{
|
||||
m_reader.reset(new RifDerivedEnsembleReader(this));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifSummaryReaderInterface* RimDerivedEnsembleCase::summaryReader()
|
||||
{
|
||||
return m_reader.get();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCase::updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath)
|
||||
{
|
||||
// NOP
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDerivedEnsembleCaseCollection * RimDerivedEnsembleCase::parentEnsemble() const
|
||||
{
|
||||
RimDerivedEnsembleCaseCollection* ensemble;
|
||||
firstAncestorOrThisOfType(ensemble);
|
||||
return ensemble;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<std::vector<time_t>, std::vector<double>> RimDerivedEnsembleCase::lookupCachedData(const RifEclipseSummaryAddress& address)
|
||||
{
|
||||
auto itr = m_data.find(address);
|
||||
if (itr == m_data.end()) return std::make_pair(std::vector<time_t>(), std::vector<double>());
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCase::clearData(const RifEclipseSummaryAddress& address)
|
||||
{
|
||||
m_data.erase(address);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "RimSummaryCase.h"
|
||||
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class RifEclipseSummaryAddress;
|
||||
class RifSummaryReaderInterface;
|
||||
class RifDerivedEnsembleReader;
|
||||
class RimDerivedEnsembleCaseCollection;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
enum DerivedEnsembleOperator
|
||||
{
|
||||
DERIVED_ENSEMBLE_SUB,
|
||||
DERIVED_ENSEMBLE_ADD
|
||||
};
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//==================================================================================================
|
||||
|
||||
class RimDerivedEnsembleCase : public RimSummaryCase
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
static const std::vector<time_t> EMPTY_TIME_STEPS_VECTOR;
|
||||
static const std::vector<double> EMPTY_VALUES_VECTOR;
|
||||
|
||||
public:
|
||||
RimDerivedEnsembleCase();
|
||||
~RimDerivedEnsembleCase();
|
||||
|
||||
void setInUse(bool inUse);
|
||||
bool isInUse() const;
|
||||
void setSummaryCases(RimSummaryCase* sumCase1, RimSummaryCase* sumCase2);
|
||||
bool needsCalculation(const RifEclipseSummaryAddress& address) const;
|
||||
const std::vector<time_t>& timeSteps(const RifEclipseSummaryAddress& address) const;
|
||||
const std::vector<double>& values(const RifEclipseSummaryAddress& address) const;
|
||||
|
||||
void calculate(const RifEclipseSummaryAddress& address);
|
||||
|
||||
virtual QString caseName() override;
|
||||
virtual void createSummaryReaderInterface() override;
|
||||
virtual RifSummaryReaderInterface* summaryReader() override;
|
||||
virtual void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath) override;
|
||||
|
||||
RimDerivedEnsembleCaseCollection* parentEnsemble() const;
|
||||
|
||||
private:
|
||||
std::pair<std::vector<time_t>, std::vector<double>> lookupCachedData(const RifEclipseSummaryAddress& address);
|
||||
void clearData(const RifEclipseSummaryAddress& address);
|
||||
|
||||
std::unique_ptr<RifDerivedEnsembleReader> m_reader;
|
||||
|
||||
bool m_inUse;
|
||||
caf::PdmPtrField<RimSummaryCase*> m_summaryCase1;
|
||||
caf::PdmPtrField<RimSummaryCase*> m_summaryCase2;
|
||||
std::map<RifEclipseSummaryAddress, std::pair<std::vector<time_t>, std::vector<double>>> m_data;
|
||||
};
|
||||
@@ -0,0 +1,440 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RiaApplication.h"
|
||||
#include "RiaTimeHistoryCurveMerger.h"
|
||||
|
||||
#include "RimDerivedEnsembleCaseCollection.h"
|
||||
#include "RimDerivedEnsembleCase.h"
|
||||
#include "RimProject.h"
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
#include "RimSummaryCaseMainCollection.h"
|
||||
|
||||
#include "RifSummaryReaderInterface.h"
|
||||
|
||||
#include <cafPdmUiPushButtonEditor.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace caf
|
||||
{
|
||||
template<>
|
||||
void caf::AppEnum<DerivedEnsembleOperator>::setUp()
|
||||
{
|
||||
addItem(DERIVED_ENSEMBLE_SUB, "Sub", "-");
|
||||
addItem(DERIVED_ENSEMBLE_ADD, "Add", "+");
|
||||
setDefault(DERIVED_ENSEMBLE_SUB);
|
||||
}
|
||||
}
|
||||
|
||||
CAF_PDM_SOURCE_INIT(RimDerivedEnsembleCaseCollection, "RimDerivedEnsembleCaseCollection");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDerivedEnsembleCaseCollection::RimDerivedEnsembleCaseCollection()
|
||||
{
|
||||
CAF_PDM_InitObject("Derived Ensemble", ":/SummaryEnsemble16x16.png", "", "");
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_ensemble1, "Ensemble1", "Ensemble 1", "", "", "");
|
||||
m_ensemble1.uiCapability()->setUiTreeChildrenHidden(true);
|
||||
m_ensemble1.uiCapability()->setAutoAddingOptionFromValue(false);
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_ensemble2, "Ensemble2", "Ensemble 2", "", "", "");
|
||||
m_ensemble1.uiCapability()->setUiTreeChildrenHidden(true);
|
||||
m_ensemble2.uiCapability()->setAutoAddingOptionFromValue(false);
|
||||
|
||||
CAF_PDM_InitFieldNoDefault(&m_operator, "Operator", "Operator", "", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_swapEnsemblesButton, "SwapEnsembles", false, "SwapEnsembles", "", "", "");
|
||||
m_swapEnsemblesButton.uiCapability()->setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName());
|
||||
m_swapEnsemblesButton.uiCapability()->setUiLabelPosition(caf::PdmUiItemInfo::HIDDEN);
|
||||
m_swapEnsemblesButton.xmlCapability()->disableIO();
|
||||
|
||||
CAF_PDM_InitField(&m_caseCount, "CaseCount", 0, "Number of Cases", "", "", "");
|
||||
m_caseCount.uiCapability()->setUiReadOnly(true);
|
||||
|
||||
// Do not show child cases
|
||||
uiCapability()->setUiTreeChildrenHidden(true);
|
||||
|
||||
// Do not store child cases to project file
|
||||
m_cases.xmlCapability()->disableIO();
|
||||
|
||||
setNameAsReadOnly();
|
||||
setName("Derived Ensemble");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDerivedEnsembleCaseCollection::~RimDerivedEnsembleCaseCollection()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCaseCollection::setEnsemble1(RimSummaryCaseCollection* ensemble)
|
||||
{
|
||||
m_ensemble1 = ensemble;
|
||||
updateAutoName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCaseCollection::setEnsemble2(RimSummaryCaseCollection* ensemble)
|
||||
{
|
||||
m_ensemble2 = ensemble;
|
||||
updateAutoName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimSummaryCase*> RimDerivedEnsembleCaseCollection::allSummaryCases() const
|
||||
{
|
||||
std::vector<RimSummaryCase*> cases;
|
||||
for (auto sumCase : allDerivedCases(true)) cases.push_back(sumCase);
|
||||
return cases;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::set<RifEclipseSummaryAddress> RimDerivedEnsembleCaseCollection::calculateUnionOfSummaryAddresses() const
|
||||
{
|
||||
std::set<RifEclipseSummaryAddress> addresses;
|
||||
if (!m_ensemble1 || !m_ensemble2) return addresses;
|
||||
|
||||
addresses = m_ensemble1->calculateUnionOfSummaryAddresses();
|
||||
auto addrs2 = m_ensemble2->calculateUnionOfSummaryAddresses();
|
||||
addresses.insert(addrs2.begin(), addrs2.end());
|
||||
return addresses;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCaseCollection::updateDerivedEnsembleCases()
|
||||
{
|
||||
if (!m_ensemble1 || !m_ensemble2) return;
|
||||
|
||||
setAllCasesNotInUse();
|
||||
|
||||
const auto cases1 = m_ensemble1->allSummaryCases();
|
||||
const auto cases2 = m_ensemble2->allSummaryCases();
|
||||
|
||||
for (auto& sumCase1 : cases1)
|
||||
{
|
||||
auto crp = sumCase1->caseRealizationParameters();
|
||||
if (!crp) continue;
|
||||
|
||||
const auto& sumCase2 = findCaseByParametersHash(cases2, crp->parametersHash());
|
||||
if (!sumCase2) continue;
|
||||
|
||||
auto derivedCase = firstCaseNotInUse();
|
||||
derivedCase->createSummaryReaderInterface();
|
||||
derivedCase->setSummaryCases(sumCase1, sumCase2);
|
||||
derivedCase->setCaseRealizationParameters(crp);
|
||||
derivedCase->setInUse(true);
|
||||
}
|
||||
|
||||
// If other derived ensembles are referring to this ensemble, update their cases as well
|
||||
for (auto referring : findReferringEnsembles())
|
||||
{
|
||||
referring->updateDerivedEnsembleCases();
|
||||
}
|
||||
|
||||
deleteCasesNoInUse();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimDerivedEnsembleCaseCollection::hasCaseReference(const RimSummaryCase* sumCase) const
|
||||
{
|
||||
for (auto currCase : m_ensemble1->allSummaryCases())
|
||||
{
|
||||
if (currCase == sumCase) return true;
|
||||
}
|
||||
for (auto currCase : m_ensemble2->allSummaryCases())
|
||||
{
|
||||
if (currCase == sumCase) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCaseCollection::onLoadDataAndUpdate()
|
||||
{
|
||||
updateDerivedEnsembleCases();
|
||||
updateReferringCurveSets();
|
||||
updateConnectedEditors();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QList<caf::PdmOptionItemInfo> RimDerivedEnsembleCaseCollection::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly)
|
||||
{
|
||||
QList<caf::PdmOptionItemInfo> options;
|
||||
|
||||
if (fieldNeedingOptions == &m_ensemble1 || fieldNeedingOptions == &m_ensemble2)
|
||||
{
|
||||
for (auto ensemble : allEnsembles())
|
||||
{
|
||||
if(ensemble != this) options.push_back(caf::PdmOptionItemInfo(ensemble->name(), ensemble));
|
||||
}
|
||||
}
|
||||
else if (fieldNeedingOptions == &m_caseCount)
|
||||
{
|
||||
m_caseCount = (int)m_cases.size();
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCaseCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
|
||||
{
|
||||
RimSummaryCaseCollection::defineUiOrdering(uiConfigName, uiOrdering);
|
||||
|
||||
uiOrdering.add(&m_caseCount);
|
||||
uiOrdering.add(&m_ensemble1);
|
||||
uiOrdering.add(&m_operator);
|
||||
uiOrdering.add(&m_ensemble2);
|
||||
uiOrdering.add(&m_swapEnsemblesButton);
|
||||
|
||||
uiOrdering.skipRemainingFields(true);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCaseCollection::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
|
||||
{
|
||||
bool doUpdate = false;
|
||||
bool doUpdateCases = false;
|
||||
bool doClearAllData = false;
|
||||
|
||||
if (changedField == &m_ensemble1 || changedField == &m_ensemble2)
|
||||
{
|
||||
doUpdate = true;
|
||||
doUpdateCases = true;
|
||||
}
|
||||
else if (changedField == &m_operator)
|
||||
{
|
||||
doUpdate = true;
|
||||
doUpdateCases = true;
|
||||
}
|
||||
else if (changedField == &m_swapEnsemblesButton)
|
||||
{
|
||||
m_swapEnsemblesButton = false;
|
||||
auto temp = m_ensemble1();
|
||||
m_ensemble1 = m_ensemble2();
|
||||
m_ensemble2 = temp;
|
||||
|
||||
doUpdate = true;
|
||||
doUpdateCases = true;
|
||||
}
|
||||
|
||||
if (doUpdate)
|
||||
{
|
||||
updateAutoName();
|
||||
//if (doClearAllData) clearAllData();
|
||||
|
||||
if (doUpdateCases)
|
||||
{
|
||||
updateDerivedEnsembleCases();
|
||||
updateConnectedEditors();
|
||||
}
|
||||
|
||||
updateReferringCurveSets();
|
||||
|
||||
// If other derived ensembles are referring to this ensemble, update their cases as well
|
||||
for (auto refering : findReferringEnsembles())
|
||||
{
|
||||
refering->updateReferringCurveSets();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCaseCollection::defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute)
|
||||
{
|
||||
if (field == &m_swapEnsemblesButton)
|
||||
{
|
||||
caf::PdmUiPushButtonEditorAttribute* attrib = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>(attribute);
|
||||
if (attrib)
|
||||
{
|
||||
attrib->m_buttonText = "Swap Ensembles";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCaseCollection::setAllCasesNotInUse()
|
||||
{
|
||||
for (auto derCase : allDerivedCases(true)) derCase->setInUse(false);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCaseCollection::deleteCasesNoInUse()
|
||||
{
|
||||
std::vector<RimDerivedEnsembleCase*> inactiveCases;
|
||||
auto allCases = allDerivedCases(false);
|
||||
std::copy_if(allCases.begin(), allCases.end(), std::back_inserter(inactiveCases), [](RimDerivedEnsembleCase* derCase) { return !derCase->isInUse(); });
|
||||
|
||||
for (auto derCase : inactiveCases)
|
||||
{
|
||||
removeCase(derCase);
|
||||
delete derCase;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimDerivedEnsembleCase* RimDerivedEnsembleCaseCollection::firstCaseNotInUse()
|
||||
{
|
||||
auto allCases = allDerivedCases(false);
|
||||
auto itr = std::find_if(allCases.begin(), allCases.end(), [](RimDerivedEnsembleCase* derCase) { return !derCase->isInUse(); });
|
||||
if (itr != allCases.end())
|
||||
{
|
||||
return *itr;
|
||||
}
|
||||
|
||||
// If no active case was found, add a new case to the collection
|
||||
auto newCase = new RimDerivedEnsembleCase();
|
||||
m_cases.push_back(newCase);
|
||||
return newCase;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimDerivedEnsembleCase*> RimDerivedEnsembleCaseCollection::allDerivedCases(bool activeOnly) const
|
||||
{
|
||||
std::vector<RimDerivedEnsembleCase*> activeCases;
|
||||
for (auto sumCase : RimSummaryCaseCollection::allSummaryCases())
|
||||
{
|
||||
auto derivedCase = dynamic_cast<RimDerivedEnsembleCase*>(sumCase);
|
||||
if (derivedCase && (!activeOnly || derivedCase->isInUse()))
|
||||
{
|
||||
activeCases.push_back(derivedCase);
|
||||
}
|
||||
}
|
||||
return activeCases;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimDerivedEnsembleCaseCollection::updateAutoName()
|
||||
{
|
||||
QString op = caf::AppEnum<DerivedEnsembleOperator>::uiText(m_operator());
|
||||
|
||||
auto derivedEnsemble1 = dynamic_cast<RimDerivedEnsembleCaseCollection*>(m_ensemble1());
|
||||
auto derivedEnsemble2 = dynamic_cast<RimDerivedEnsembleCaseCollection*>(m_ensemble2());
|
||||
bool isDerived1 = derivedEnsemble1 != nullptr;
|
||||
bool isDerived2 = derivedEnsemble2 != nullptr;
|
||||
|
||||
QString name =
|
||||
(isDerived1 ? "(" : "") +
|
||||
(m_ensemble1 ? m_ensemble1->name() : "") +
|
||||
(isDerived1 ? ")" : "") +
|
||||
" " + op + " " +
|
||||
(isDerived2 ? "(" : "") +
|
||||
(m_ensemble2 ? m_ensemble2->name() : "") +
|
||||
(isDerived2 ? ")" : "");
|
||||
setName(name);
|
||||
|
||||
// If other derived ensembles are referring to this ensemble, update theirs name as well
|
||||
for (auto refering : findReferringEnsembles())
|
||||
{
|
||||
refering->updateAutoName();
|
||||
refering->updateConnectedEditors();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimSummaryCase* RimDerivedEnsembleCaseCollection::findCaseByParametersHash(const std::vector<RimSummaryCase*>& cases, size_t hash) const
|
||||
{
|
||||
for (auto sumCase : cases)
|
||||
{
|
||||
auto ensembleParameters = sumCase->caseRealizationParameters();
|
||||
if (ensembleParameters && ensembleParameters->parametersHash() == hash) return sumCase;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimDerivedEnsembleCaseCollection*> RimDerivedEnsembleCaseCollection::findReferringEnsembles() const
|
||||
{
|
||||
std::vector<RimDerivedEnsembleCaseCollection*> referringEnsembles;
|
||||
RimSummaryCaseMainCollection* mainColl;
|
||||
|
||||
firstAncestorOrThisOfType(mainColl);
|
||||
if (mainColl)
|
||||
{
|
||||
for (auto group : mainColl->summaryCaseCollections())
|
||||
{
|
||||
auto derivedEnsemble = dynamic_cast<RimDerivedEnsembleCaseCollection*>(group);
|
||||
if (derivedEnsemble)
|
||||
{
|
||||
if (derivedEnsemble->m_ensemble1() == this || derivedEnsemble->m_ensemble2() == this)
|
||||
{
|
||||
referringEnsembles.push_back(derivedEnsemble);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return referringEnsembles;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RimSummaryCaseCollection*> RimDerivedEnsembleCaseCollection::allEnsembles() const
|
||||
{
|
||||
std::vector<RimSummaryCaseCollection*> ensembles;
|
||||
|
||||
auto project = RiaApplication::instance()->project();
|
||||
|
||||
for (auto group : project->summaryGroups())
|
||||
{
|
||||
if (group->isEnsemble()) ensembles.push_back(group);
|
||||
}
|
||||
return ensembles;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RifEclipseSummaryAddress.h"
|
||||
|
||||
#include "RimDerivedEnsembleCase.h"
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
|
||||
#include "cafPdmChildArrayField.h"
|
||||
#include "cafPdmField.h"
|
||||
#include "cafPdmPtrField.h"
|
||||
#include "cafPdmObject.h"
|
||||
#include "cafPdmProxyValueField.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class RimSummaryCase;
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
//==================================================================================================
|
||||
class RimDerivedEnsembleCaseCollection : public RimSummaryCaseCollection
|
||||
{
|
||||
CAF_PDM_HEADER_INIT;
|
||||
|
||||
public:
|
||||
RimDerivedEnsembleCaseCollection();
|
||||
virtual ~RimDerivedEnsembleCaseCollection();
|
||||
|
||||
RimSummaryCaseCollection* ensemble1() const { return m_ensemble1; }
|
||||
RimSummaryCaseCollection* ensemble2() const { return m_ensemble2; }
|
||||
DerivedEnsembleOperator op() const { return m_operator(); }
|
||||
|
||||
void setEnsemble1(RimSummaryCaseCollection* ensemble);
|
||||
void setEnsemble2(RimSummaryCaseCollection* ensemble);
|
||||
|
||||
virtual std::vector<RimSummaryCase*> allSummaryCases() const override;
|
||||
virtual std::set<RifEclipseSummaryAddress> calculateUnionOfSummaryAddresses() const override;
|
||||
void updateDerivedEnsembleCases();
|
||||
bool hasCaseReference(const RimSummaryCase* sumCase) const;
|
||||
|
||||
virtual void onLoadDataAndUpdate() override;
|
||||
|
||||
private:
|
||||
virtual QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
|
||||
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
|
||||
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
|
||||
virtual void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName,
|
||||
caf::PdmUiEditorAttribute* attribute) override;
|
||||
|
||||
void setAllCasesNotInUse();
|
||||
void deleteCasesNoInUse();
|
||||
RimDerivedEnsembleCase* firstCaseNotInUse();
|
||||
std::vector<RimDerivedEnsembleCase*> allDerivedCases(bool activeOnly) const;
|
||||
void updateAutoName();
|
||||
RimSummaryCase* findCaseByParametersHash(const std::vector<RimSummaryCase*>& cases, size_t hash) const;
|
||||
std::vector<RimDerivedEnsembleCaseCollection*> findReferringEnsembles() const;
|
||||
|
||||
private:
|
||||
std::vector<RimSummaryCaseCollection*> allEnsembles() const;
|
||||
|
||||
private:
|
||||
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble1;
|
||||
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble2;
|
||||
caf::PdmField<caf::AppEnum<DerivedEnsembleOperator>> m_operator;
|
||||
caf::PdmField<bool> m_swapEnsemblesButton;
|
||||
caf::PdmField<int> m_caseCount;
|
||||
};
|
||||
@@ -25,6 +25,7 @@
|
||||
class EnsembleParameter;
|
||||
class RimEnsembleCurveSet;
|
||||
class RimSummaryCase;
|
||||
class RimSummaryPlot;
|
||||
class RimEnsembleCurveFilterCollection;
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
@@ -148,26 +148,42 @@ void RimEnsembleCurveFilterCollection::defineUiOrdering(QString uiConfigName, ca
|
||||
auto selEnsembleParam = filter->selectedEnsembleParameter();
|
||||
if (selEnsembleParam.isNumeric())
|
||||
{
|
||||
if (!filter->isActive()) groupTitle = "DISABLED - ";
|
||||
groupTitle += QString("%1. Min: %2, Max: %3")
|
||||
.arg(filter->ensembleParameterName())
|
||||
.arg(QString::number(filter->minValue()))
|
||||
.arg(QString::number(filter->maxValue()));
|
||||
groupTitle = filter->ensembleParameterName();
|
||||
|
||||
if (!filter->isActive())
|
||||
{
|
||||
groupTitle += " - [Disabled]";
|
||||
}
|
||||
else
|
||||
{
|
||||
groupTitle += QString(" [%2 .. %3]")
|
||||
.arg(QString::number(filter->minValue()))
|
||||
.arg(QString::number(filter->maxValue()));
|
||||
}
|
||||
}
|
||||
else if (selEnsembleParam.isText())
|
||||
{
|
||||
if (!filter->isActive()) groupTitle = "DISABLED - ";
|
||||
groupTitle += QString("%1. Categories: ")
|
||||
.arg(filter->ensembleParameterName());
|
||||
groupTitle = filter->ensembleParameterName();
|
||||
|
||||
bool first = true;
|
||||
for (auto cat : filter->categories())
|
||||
if (!filter->isActive())
|
||||
{
|
||||
if (!first) groupTitle += ", ";
|
||||
groupTitle += cat;
|
||||
first = false;
|
||||
groupTitle += " - [Disabled]";
|
||||
}
|
||||
else
|
||||
{
|
||||
groupTitle += " { ";
|
||||
|
||||
bool first = true;
|
||||
for (auto cat : filter->categories())
|
||||
{
|
||||
if (!first) groupTitle += ", ";
|
||||
groupTitle += cat;
|
||||
first = false;
|
||||
}
|
||||
groupTitle += " }";
|
||||
}
|
||||
}
|
||||
|
||||
caf::PdmUiGroup* filterGroup = uiOrdering.addNewGroupWithKeyword(groupTitle, QString("EnsembleFilter_") + filter->filterId());
|
||||
filter->defineUiOrdering(uiConfigName, *filterGroup);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "RiaApplication.h"
|
||||
#include "RiaColorTables.h"
|
||||
#include "RiaStatisticsTools.h"
|
||||
|
||||
#include "SummaryPlotCommands/RicSummaryCurveCreator.h"
|
||||
|
||||
@@ -29,6 +30,7 @@
|
||||
#include "RigStatisticsMath.h"
|
||||
#include "RiaTimeHistoryCurveMerger.h"
|
||||
|
||||
#include "RimDerivedEnsembleCaseCollection.h"
|
||||
#include "RimEnsembleCurveFilter.h"
|
||||
#include "RimEnsembleCurveFilterCollection.h"
|
||||
#include "RimEnsembleCurveSetCollection.h"
|
||||
@@ -66,6 +68,12 @@
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
#define DOUBLE_INF std::numeric_limits<double>::infinity()
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Internal functions
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimPlotCurve::PointSymbolEnum statisticsCurveSymbolFromAddress(const RifEclipseSummaryAddress& address);
|
||||
int statisticsCurveSymbolSize(RimPlotCurve::PointSymbolEnum symbol);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -168,6 +176,7 @@ RimEnsembleCurveSet::RimEnsembleCurveSet()
|
||||
m_ensembleStatCase->createSummaryReaderInterface();
|
||||
|
||||
m_disableStatisticCurves = false;
|
||||
m_isCurveSetFiltered = false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -735,7 +744,7 @@ void RimEnsembleCurveSet::appendOptionItemsForSummaryAddresses(QList<caf::PdmOpt
|
||||
for (RimSummaryCase* summaryCase : summaryCaseGroup->allSummaryCases())
|
||||
{
|
||||
RifSummaryReaderInterface* reader = summaryCase->summaryReader();
|
||||
const std::vector<RifEclipseSummaryAddress>& addrs = reader ? reader->allResultAddresses() : std::vector<RifEclipseSummaryAddress>();
|
||||
const std::set<RifEclipseSummaryAddress>& addrs = reader ? reader->allResultAddresses() : std::set<RifEclipseSummaryAddress>();
|
||||
|
||||
for (auto& addr : addrs)
|
||||
{
|
||||
@@ -930,6 +939,8 @@ void RimEnsembleCurveSet::updateEnsembleCurves()
|
||||
m_yValuesSummaryFilter->updateFromAddress(addr->address());
|
||||
|
||||
if (plot->qwtPlot()) m_qwtPlotCurveForLegendText->attach(plot->qwtPlot());
|
||||
|
||||
m_isCurveSetFiltered = filteredCases.size() < group->allSummaryCases().size();
|
||||
}
|
||||
|
||||
RimSummaryPlot* plot;
|
||||
@@ -939,6 +950,7 @@ void RimEnsembleCurveSet::updateEnsembleCurves()
|
||||
plot->qwtPlot()->updateLegend();
|
||||
plot->qwtPlot()->replot();
|
||||
plot->updateAxes();
|
||||
plot->updatePlotInfoLabel();
|
||||
}
|
||||
}
|
||||
updateCurveColors();
|
||||
@@ -987,9 +999,17 @@ void RimEnsembleCurveSet::updateStatisticsCurves(bool calculate = true)
|
||||
curve->setParentQwtPlotNoReplot(plot->qwtPlot());
|
||||
m_curves.push_back(curve);
|
||||
curve->setColor(m_statistics->color());
|
||||
curve->setSymbol(RimPlotCurve::SYMBOL_ELLIPSE);
|
||||
curve->setSymbolSkipDinstance(50);
|
||||
curve->setSymbolLabel(QString::fromStdString(address.ensembleStatisticsQuantityName()));
|
||||
curve->setColor(m_statistics->color());
|
||||
|
||||
auto symbol = statisticsCurveSymbolFromAddress(address);
|
||||
curve->setSymbol(symbol);
|
||||
curve->setSymbolSize(statisticsCurveSymbolSize(symbol));
|
||||
curve->setSymbolSkipDistance(150);
|
||||
if (m_statistics->showCurveLabels())
|
||||
{
|
||||
curve->setSymbolLabel(RiaStatisticsTools::replacePercentileByPValueText(
|
||||
QString::fromStdString(address.ensembleStatisticsQuantityName())));
|
||||
}
|
||||
curve->setLineStyle(RimPlotCurve::STYLE_SOLID);
|
||||
curve->setSummaryCaseY(m_ensembleStatCase.get());
|
||||
curve->setSummaryAddressY(address);
|
||||
@@ -1093,6 +1113,14 @@ void RimEnsembleCurveSet::disableStatisticCurves()
|
||||
m_disableStatisticCurves = true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RimEnsembleCurveSet::isFiltered() const
|
||||
{
|
||||
return m_isCurveSetFiltered;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -1212,3 +1240,27 @@ void RimEnsembleCurveSet::updateLegendMappingMode()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimPlotCurve::PointSymbolEnum statisticsCurveSymbolFromAddress(const RifEclipseSummaryAddress& address)
|
||||
{
|
||||
auto qName = QString::fromStdString(address.quantityName());
|
||||
|
||||
if (qName.contains(ENSEMBLE_STAT_P10_QUANTITY_NAME)) return RimPlotCurve::SYMBOL_TRIANGLE;
|
||||
if (qName.contains(ENSEMBLE_STAT_P90_QUANTITY_NAME)) return RimPlotCurve::SYMBOL_DOWN_TRIANGLE;
|
||||
if (qName.contains(ENSEMBLE_STAT_P50_QUANTITY_NAME)) return RimPlotCurve::SYMBOL_DIAMOND;
|
||||
return RimPlotCurve::SYMBOL_ELLIPSE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int statisticsCurveSymbolSize(RimPlotCurve::PointSymbolEnum symbol)
|
||||
{
|
||||
if (symbol == RimPlotCurve::SYMBOL_DIAMOND) return 8;
|
||||
if (symbol == RimPlotCurve::SYMBOL_TRIANGLE) return 7;
|
||||
if (symbol == RimPlotCurve::SYMBOL_DOWN_TRIANGLE) return 7;
|
||||
return 6;
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ public:
|
||||
|
||||
std::vector<RimSummaryCase*> filterEnsembleCases(const RimSummaryCaseCollection* ensemble);
|
||||
void disableStatisticCurves();
|
||||
bool isFiltered() const;
|
||||
|
||||
bool hasP10Data() const;
|
||||
bool hasP50Data() const;
|
||||
@@ -174,5 +175,6 @@ private:
|
||||
std::unique_ptr<RimEnsembleStatisticsCase> m_ensembleStatCase;
|
||||
|
||||
bool m_disableStatisticCurves;
|
||||
bool m_isCurveSetFiltered;
|
||||
};
|
||||
|
||||
|
||||
@@ -38,10 +38,11 @@ RimEnsembleStatistics::RimEnsembleStatistics()
|
||||
CAF_PDM_InitObject("Ensemble Curve Filter", ":/EnsembleCurveSet16x16.png", "", "");
|
||||
|
||||
CAF_PDM_InitField(&m_active, "Active", true, "Show statistics curves", "", "", "");
|
||||
CAF_PDM_InitField(&m_showP10Curve, "ShowP10Curve", true, "P10", "", "", "");
|
||||
CAF_PDM_InitField(&m_showP10Curve, "ShowP10Curve", true, "P90", "", "", ""); // Yes, P90
|
||||
CAF_PDM_InitField(&m_showP50Curve, "ShowP50Curve", true, "P50", "", "", "");
|
||||
CAF_PDM_InitField(&m_showP90Curve, "ShowP90Curve", true, "P90", "", "", "");
|
||||
CAF_PDM_InitField(&m_showP90Curve, "ShowP90Curve", true, "P10", "", "", ""); // Yes, P10
|
||||
CAF_PDM_InitField(&m_showMeanCurve, "ShowMeanCurve", true, "Mean", "", "", "");
|
||||
CAF_PDM_InitField(&m_showCurveLabels, "ShowCurveLabels", true, "Show Curve Labels", "", "", "");
|
||||
CAF_PDM_InitField(&m_color, "Color", cvf::Color3f(cvf::Color3::BLACK), "Color", "", "", "");
|
||||
}
|
||||
|
||||
@@ -106,6 +107,7 @@ void RimEnsembleStatistics::fieldChangedByUi(const caf::PdmFieldHandle* changedF
|
||||
changedField == &m_showP50Curve ||
|
||||
changedField == &m_showP90Curve ||
|
||||
changedField == &m_showMeanCurve ||
|
||||
changedField == &m_showCurveLabels ||
|
||||
changedField == &m_color)
|
||||
{
|
||||
auto curveSet = parentCurveSet();
|
||||
@@ -125,20 +127,25 @@ void RimEnsembleStatistics::defineUiOrdering(QString uiConfigName, caf::PdmUiOrd
|
||||
auto curveSet = parentCurveSet();
|
||||
|
||||
uiOrdering.add(&m_active);
|
||||
uiOrdering.add(&m_showCurveLabels);
|
||||
uiOrdering.add(&m_color);
|
||||
|
||||
auto group = uiOrdering.addNewGroup("Curves");
|
||||
group->add(&m_showP10Curve);
|
||||
group->add(&m_showP50Curve);
|
||||
group->add(&m_showP90Curve);
|
||||
group->add(&m_showP50Curve);
|
||||
group->add(&m_showMeanCurve);
|
||||
group->add(&m_color);
|
||||
group->add(&m_showP10Curve);
|
||||
|
||||
disableP10Curve(!m_active || !curveSet->hasP10Data());
|
||||
disableP50Curve(!m_active || !curveSet->hasP50Data());
|
||||
disableP90Curve(!m_active || !curveSet->hasP90Data());
|
||||
disableMeanCurve(!m_active);
|
||||
m_showCurveLabels.uiCapability()->setUiReadOnly(!m_active);
|
||||
m_color.uiCapability()->setUiReadOnly(!m_active);
|
||||
|
||||
m_showP10Curve.uiCapability()->setUiName(curveSet->hasP10Data() ? "P90" : "P90 (Needs > 8 curves)");
|
||||
m_showP90Curve.uiCapability()->setUiName(curveSet->hasP90Data() ? "P10" : "P10 (Needs > 8 curves)");
|
||||
|
||||
uiOrdering.skipRemainingFields(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
bool showP50Curve() const { return m_showP50Curve; }
|
||||
bool showP90Curve() const { return m_showP90Curve; }
|
||||
bool showMeanCurve() const { return m_showMeanCurve; }
|
||||
bool showCurveLabels() const { return m_showCurveLabels; }
|
||||
cvf::Color3f color() const { return m_color; }
|
||||
|
||||
void disableP10Curve(bool disable);
|
||||
@@ -64,6 +65,7 @@ private:
|
||||
caf::PdmField<bool> m_showP50Curve;
|
||||
caf::PdmField<bool> m_showP90Curve;
|
||||
caf::PdmField<bool> m_showMeanCurve;
|
||||
caf::PdmField<bool> m_showCurveLabels;
|
||||
|
||||
caf::PdmField<cvf::Color3f> m_color;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
|
||||
#include "RimDerivedEnsembleCaseCollection.h"
|
||||
#include "RimEnsembleCurveSet.h"
|
||||
#include "RimGridSummaryCase.h"
|
||||
#include "RimProject.h"
|
||||
@@ -68,13 +69,34 @@ void RimSummaryCaseCollection::removeCase(RimSummaryCase* summaryCase)
|
||||
updateReferringCurveSets();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryCaseCollection::deleteAllCases()
|
||||
{
|
||||
m_cases.deleteAllChildObjects();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryCaseCollection::addCase(RimSummaryCase* summaryCase)
|
||||
void RimSummaryCaseCollection::addCase(RimSummaryCase* summaryCase, bool updateCurveSets)
|
||||
{
|
||||
m_cases.push_back(summaryCase);
|
||||
updateReferringCurveSets();
|
||||
|
||||
// Update derived ensemble cases (if any)
|
||||
std::vector<caf::PdmObjectHandle*> referringObjects;
|
||||
objectsWithReferringPtrFields(referringObjects);
|
||||
for (auto refObj : referringObjects)
|
||||
{
|
||||
auto derEnsemble = dynamic_cast<RimDerivedEnsembleCaseCollection*>(refObj);
|
||||
if (!derEnsemble) continue;
|
||||
|
||||
derEnsemble->updateDerivedEnsembleCases();
|
||||
if (updateCurveSets) derEnsemble->updateReferringCurveSets();
|
||||
}
|
||||
|
||||
if(updateCurveSets) updateReferringCurveSets();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -133,11 +155,9 @@ std::set<RifEclipseSummaryAddress> RimSummaryCaseCollection::calculateUnionOfSum
|
||||
|
||||
if ( !reader ) continue;
|
||||
|
||||
const std::vector<RifEclipseSummaryAddress>& readerAddresses = reader->allResultAddresses();
|
||||
const std::set<RifEclipseSummaryAddress>& readerAddresses = reader->allResultAddresses();
|
||||
addressUnion.insert(readerAddresses.begin(), readerAddresses.end());
|
||||
|
||||
}
|
||||
|
||||
return addressUnion;
|
||||
}
|
||||
|
||||
@@ -234,6 +254,14 @@ EnsembleParameter RimSummaryCaseCollection::ensembleParameter(const QString& par
|
||||
return eParam;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryCaseCollection::loadDataAndUpdate()
|
||||
{
|
||||
onLoadDataAndUpdate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -242,10 +270,18 @@ caf::PdmFieldHandle* RimSummaryCaseCollection::userDescriptionField()
|
||||
return &m_name;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryCaseCollection::onLoadDataAndUpdate()
|
||||
{
|
||||
// NOP
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryCaseCollection::updateReferringCurveSets() const
|
||||
void RimSummaryCaseCollection::updateReferringCurveSets()
|
||||
{
|
||||
// Update curve set referring to this group
|
||||
std::vector<PdmObjectHandle*> referringObjects;
|
||||
@@ -299,3 +335,20 @@ void RimSummaryCaseCollection::fieldChangedByUi(const caf::PdmFieldHandle* chang
|
||||
updateIcon();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryCaseCollection::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
|
||||
{
|
||||
uiOrdering.add(&m_name);
|
||||
uiOrdering.skipRemainingFields(true);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryCaseCollection::setNameAsReadOnly()
|
||||
{
|
||||
m_name.uiCapability()->setUiReadOnly(true);
|
||||
}
|
||||
|
||||
@@ -65,26 +65,35 @@ public:
|
||||
virtual ~RimSummaryCaseCollection();
|
||||
|
||||
void removeCase(RimSummaryCase* summaryCase);
|
||||
void addCase(RimSummaryCase* summaryCase);
|
||||
std::vector<RimSummaryCase*> allSummaryCases() const;
|
||||
void deleteAllCases();
|
||||
void addCase(RimSummaryCase* summaryCase, bool updateCurveSets = true);
|
||||
virtual std::vector<RimSummaryCase*> allSummaryCases() const;
|
||||
void setName(const QString& name);
|
||||
QString name() const;
|
||||
bool isEnsemble() const;
|
||||
void setAsEnsemble(bool isEnsemble);
|
||||
std::set<RifEclipseSummaryAddress> calculateUnionOfSummaryAddresses() const;
|
||||
virtual std::set<RifEclipseSummaryAddress> calculateUnionOfSummaryAddresses() const;
|
||||
EnsembleParameter ensembleParameter(const QString& paramName) const;
|
||||
|
||||
void loadDataAndUpdate();
|
||||
|
||||
private:
|
||||
caf::PdmFieldHandle* userDescriptionField() override;
|
||||
void updateReferringCurveSets() const;
|
||||
QString nameAndItemCount() const;
|
||||
void updateIcon();
|
||||
|
||||
virtual void initAfterRead() override;
|
||||
virtual void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
virtual void onLoadDataAndUpdate();
|
||||
void updateReferringCurveSets();
|
||||
virtual void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
|
||||
void setNameAsReadOnly();
|
||||
|
||||
caf::PdmChildArrayField<RimSummaryCase*> m_cases;
|
||||
|
||||
private:
|
||||
caf::PdmField<QString> m_name;
|
||||
caf::PdmProxyValueField<QString> m_nameAndItemCount;
|
||||
caf::PdmField<bool> m_isEnsemble;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "RifSummaryCaseRestartSelector.h"
|
||||
#include "RifCaseRealizationParametersReader.h"
|
||||
|
||||
#include "RimDerivedEnsembleCaseCollection.h"
|
||||
#include "RimEclipseResultCase.h"
|
||||
#include "RimFileSummaryCase.h"
|
||||
#include "RimGridSummaryCase.h"
|
||||
@@ -201,19 +202,43 @@ void RimSummaryCaseMainCollection::addCase(RimSummaryCase* summaryCase)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryCaseMainCollection::removeCase(RimSummaryCase* summaryCase)
|
||||
{
|
||||
std::vector<RimDerivedEnsembleCaseCollection*> derivedEnsembles;
|
||||
|
||||
// Build a list of derived ensembles that must be updated after delete
|
||||
for (auto group : summaryCaseCollections())
|
||||
{
|
||||
auto derEnsemble = dynamic_cast<RimDerivedEnsembleCaseCollection*>(group);
|
||||
if (derEnsemble)
|
||||
{
|
||||
if (derEnsemble->hasCaseReference(summaryCase))
|
||||
{
|
||||
derivedEnsembles.push_back(derEnsemble);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_cases.removeChildObject(summaryCase);
|
||||
for (RimSummaryCaseCollection* summaryCaseCollection : m_caseCollections)
|
||||
{
|
||||
summaryCaseCollection->removeCase(summaryCase);
|
||||
}
|
||||
|
||||
// Update derived ensemble cases (if any)
|
||||
for (auto derEnsemble : derivedEnsembles)
|
||||
{
|
||||
derEnsemble->updateDerivedEnsembleCases();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryCaseMainCollection::addCaseCollection(std::vector<RimSummaryCase*> summaryCases, const QString& collectionName, bool isEnsemble)
|
||||
RimSummaryCaseCollection* RimSummaryCaseMainCollection::addCaseCollection(std::vector<RimSummaryCase*> summaryCases,
|
||||
const QString& collectionName,
|
||||
bool isEnsemble,
|
||||
std::function<RimSummaryCaseCollection* ()> allocator)
|
||||
{
|
||||
RimSummaryCaseCollection* summaryCaseCollection = new RimSummaryCaseCollection();
|
||||
RimSummaryCaseCollection* summaryCaseCollection = allocator();
|
||||
if(!collectionName.isEmpty()) summaryCaseCollection->setName(collectionName);
|
||||
summaryCaseCollection->setAsEnsemble(isEnsemble);
|
||||
|
||||
@@ -235,6 +260,8 @@ void RimSummaryCaseMainCollection::addCaseCollection(std::vector<RimSummaryCase*
|
||||
}
|
||||
|
||||
m_caseCollections.push_back(summaryCaseCollection);
|
||||
|
||||
return summaryCaseCollection;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -330,6 +357,14 @@ void RimSummaryCaseMainCollection::loadSummaryCaseData(std::vector<RimSummaryCas
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimSummaryCaseCollection* RimSummaryCaseMainCollection::defaultAllocator()
|
||||
{
|
||||
return new RimSummaryCaseCollection();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "cafPdmObject.h"
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
class RimGridSummaryCase;
|
||||
class RimSummaryCase;
|
||||
@@ -56,7 +57,10 @@ public:
|
||||
void addCase(RimSummaryCase* summaryCase);
|
||||
void removeCase(RimSummaryCase* summaryCase);
|
||||
|
||||
void addCaseCollection(std::vector<RimSummaryCase*> summaryCases, const QString& coolectionName, bool isEnsemble);
|
||||
RimSummaryCaseCollection* addCaseCollection(std::vector<RimSummaryCase*> summaryCases,
|
||||
const QString& coolectionName,
|
||||
bool isEnsemble,
|
||||
std::function<RimSummaryCaseCollection* ()> allocator = defaultAllocator);
|
||||
void removeCaseCollection(RimSummaryCaseCollection* caseCollection);
|
||||
|
||||
void loadAllSummaryCaseData();
|
||||
@@ -67,6 +71,7 @@ public:
|
||||
|
||||
private:
|
||||
static void loadSummaryCaseData(std::vector<RimSummaryCase*> summaryCases);
|
||||
static RimSummaryCaseCollection* defaultAllocator();
|
||||
|
||||
private:
|
||||
caf::PdmChildArrayField<RimSummaryCase*> m_cases;
|
||||
|
||||
@@ -593,7 +593,7 @@ void RimSummaryCurve::appendOptionItemsForSummaryAddresses(QList<caf::PdmOptionI
|
||||
RifSummaryReaderInterface* reader = summaryCase->summaryReader();
|
||||
if (reader)
|
||||
{
|
||||
const std::vector<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses();
|
||||
const std::set<RifEclipseSummaryAddress> allAddresses = reader->allResultAddresses();
|
||||
|
||||
for (auto& address : allAddresses)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include "RimSummaryCurveAutoName.h"
|
||||
|
||||
#include "RiaStatisticsTools.h"
|
||||
|
||||
#include "RifEclipseSummaryAddress.h"
|
||||
|
||||
#include "RimEnsembleCurveSet.h"
|
||||
@@ -73,6 +75,11 @@ QString RimSummaryCurveAutoName::curveNameY(const RifEclipseSummaryAddress& summ
|
||||
{
|
||||
text += summaryAddress.quantityName();
|
||||
|
||||
if (summaryAddress.category() == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS)
|
||||
{
|
||||
text = RiaStatisticsTools::replacePercentileByPValueText(QString::fromStdString(text)).toStdString();
|
||||
}
|
||||
|
||||
if (m_unit && summaryCurve && !summaryCurve->unitNameY().empty())
|
||||
{
|
||||
text += "[" + summaryCurve->unitNameY() + "]";
|
||||
|
||||
@@ -208,7 +208,11 @@ QString RimSummaryPlotYAxisFormatter::autoAxisTitle() const
|
||||
RifEclipseSummaryAddress sumAddress;
|
||||
std::string unitText;
|
||||
|
||||
if (m_axisProperties->plotAxisType() == RiaDefines::PLOT_AXIS_BOTTOM)
|
||||
if (rimCurve->summaryAddressY().category() == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (m_axisProperties->plotAxisType() == RiaDefines::PLOT_AXIS_BOTTOM)
|
||||
{
|
||||
sumAddress = rimCurve->summaryAddressX();
|
||||
unitText = rimCurve->unitNameX();
|
||||
|
||||
@@ -52,16 +52,23 @@
|
||||
#include "qwt_legend.h"
|
||||
#include "qwt_plot_curve.h"
|
||||
#include "qwt_plot_renderer.h"
|
||||
#include "qwt_plot_textlabel.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
#include <QRectF>
|
||||
|
||||
#include <set>
|
||||
#include <limits>
|
||||
|
||||
|
||||
CAF_PDM_SOURCE_INIT(RimSummaryPlot, "SummaryPlot");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Internal constants
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
#define DOUBLE_INF std::numeric_limits<double>::infinity()
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Internal types
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -79,14 +86,39 @@ struct CurveData
|
||||
std::vector<double> values;
|
||||
};
|
||||
|
||||
class CurvesData
|
||||
{
|
||||
public:
|
||||
CurvesData() : resamplePeriod(DateTimePeriod::NONE) {}
|
||||
void clear()
|
||||
{
|
||||
resamplePeriod = DateTimePeriod::NONE;
|
||||
caseNames.clear();
|
||||
timeSteps.clear();
|
||||
allCurveData.clear();
|
||||
}
|
||||
|
||||
DateTimePeriod resamplePeriod;
|
||||
std::vector<QString> caseNames;
|
||||
std::vector<std::vector<time_t> > timeSteps;
|
||||
std::vector<std::vector<CurveData>> allCurveData;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Internal functions
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
|
||||
const std::vector<time_t> &timeSteps, const std::vector<CurveData>& curveData,
|
||||
std::vector<time_t>* exportTimeSteps, std::vector<CurveData>* exportValues);
|
||||
void populateSummaryCurvesData(std::vector<RimSummaryCurve*> curves, CurvesData* curvesData);
|
||||
void populateTimeHistoryCurvesData(std::vector<RimGridTimeHistoryCurve*> curves, CurvesData* curvesData);
|
||||
void populateAsciiDataCurvesData(std::vector<RimAsciiDataCurve*> curves, CurvesData* curvesData);
|
||||
|
||||
void appendToExportData(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData);
|
||||
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
|
||||
const CurvesData& inputCurvesData,
|
||||
CurvesData* resultCurvesData);
|
||||
|
||||
void appendToExportDataForCase(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData);
|
||||
void appendToExportData(QString& out, const std::vector<CurvesData>& curvesData);
|
||||
CurvesData concatCurvesData(const std::vector<CurvesData>& curvesData);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
@@ -154,6 +186,8 @@ RimSummaryPlot::RimSummaryPlot()
|
||||
m_isCrossPlot = false;
|
||||
|
||||
m_nameHelperAllCurves.reset(new RimSummaryPlotNameHelper);
|
||||
|
||||
setPlotInfoLabel("Filters Active");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -275,140 +309,44 @@ QString RimSummaryPlot::asciiDataForPlotExport(DateTimePeriod resamplingPeriod)
|
||||
QString out;
|
||||
RiaTimeHistoryCurveResampler resampler;
|
||||
|
||||
out += description();
|
||||
|
||||
// Summary curves
|
||||
// Summary and time history (from grid) curves
|
||||
{
|
||||
std::vector<RimSummaryCurve*> curves;
|
||||
this->descendantsIncludingThisOfType(curves);
|
||||
|
||||
std::vector<QString> caseNames;
|
||||
std::vector<std::vector<time_t> > timeSteps;
|
||||
std::vector<std::vector<CurveData>> allCurveData;
|
||||
// Vector containing cases - curves
|
||||
CurvesData summaryCurvesData;
|
||||
populateSummaryCurvesData(curves, &summaryCurvesData);
|
||||
|
||||
for (RimSummaryCurve* curve : curves)
|
||||
{
|
||||
if (!curve->isCurveVisible()) continue;
|
||||
QString curveCaseName = curve->summaryCaseY()->caseName();
|
||||
|
||||
size_t casePosInList = cvf::UNDEFINED_SIZE_T;
|
||||
for (size_t i = 0; i < caseNames.size(); i++)
|
||||
{
|
||||
if (curveCaseName == caseNames[i]) casePosInList = i;
|
||||
}
|
||||
CurvesData timeHistoryCurvesData;
|
||||
populateTimeHistoryCurvesData(m_gridTimeHistoryCurves.childObjects(), &timeHistoryCurvesData);
|
||||
|
||||
CurveData curveData = { curve->curveName(), curve->summaryAddressY(), curve->valuesY() };
|
||||
std::vector<CurvesData> exportData(2);
|
||||
|
||||
if (casePosInList == cvf::UNDEFINED_SIZE_T)
|
||||
{
|
||||
caseNames.push_back(curveCaseName);
|
||||
timeSteps.push_back(curve->timeStepsY());
|
||||
allCurveData.push_back(std::vector<CurveData>({ curveData }));
|
||||
}
|
||||
else
|
||||
{
|
||||
allCurveData[casePosInList].push_back(curveData);
|
||||
}
|
||||
}
|
||||
// Summary data for export
|
||||
prepareCaseCurvesForExport(resamplingPeriod,
|
||||
ResampleAlgorithm::DATA_DECIDES,
|
||||
summaryCurvesData,
|
||||
&exportData[0]);
|
||||
|
||||
for (size_t i = 0; i < timeSteps.size(); i++) //cases
|
||||
{
|
||||
// Data for export
|
||||
std::vector<time_t> expTimeSteps;
|
||||
std::vector<CurveData> expCurveData;
|
||||
// Time history data for export
|
||||
prepareCaseCurvesForExport(resamplingPeriod,
|
||||
ResampleAlgorithm::PERIOD_END,
|
||||
timeHistoryCurvesData,
|
||||
&exportData[1]);
|
||||
|
||||
out += "\n\n";
|
||||
out += "Case: " + caseNames[i];
|
||||
out += "\n";
|
||||
|
||||
prepareCaseCurvesForExport(resamplingPeriod, ResampleAlgorithm::DATA_DECIDES, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
|
||||
appendToExportData(out, expTimeSteps, expCurveData);
|
||||
}
|
||||
}
|
||||
|
||||
// Time history curves (from grid)
|
||||
{
|
||||
std::vector<QString> caseNames;
|
||||
std::vector<std::vector<time_t> > timeSteps;
|
||||
std::vector<std::vector<CurveData>> allCurveData;
|
||||
// Vector containing cases - curves
|
||||
|
||||
for (RimGridTimeHistoryCurve* curve : m_gridTimeHistoryCurves)
|
||||
{
|
||||
if (!curve->isCurveVisible()) continue;
|
||||
QString curveCaseName = curve->caseName();
|
||||
|
||||
size_t casePosInList = cvf::UNDEFINED_SIZE_T;
|
||||
for (size_t i = 0; i < caseNames.size(); i++)
|
||||
{
|
||||
if (curveCaseName == caseNames[i]) casePosInList = i;
|
||||
}
|
||||
|
||||
CurveData curveData = { curve->curveName(), RifEclipseSummaryAddress(), curve->yValues() };
|
||||
|
||||
if (casePosInList == cvf::UNDEFINED_SIZE_T)
|
||||
{
|
||||
caseNames.push_back(curveCaseName);
|
||||
timeSteps.push_back(curve->timeStepValues());
|
||||
allCurveData.push_back(std::vector<CurveData>({ curveData }));
|
||||
}
|
||||
else
|
||||
{
|
||||
allCurveData[casePosInList].push_back(curveData);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < timeSteps.size(); i++) //cases
|
||||
{
|
||||
// Data for export
|
||||
std::vector<time_t> expTimeSteps;
|
||||
std::vector<CurveData> expCurveData;
|
||||
|
||||
out += "\n\n";
|
||||
out += "Case: " + caseNames[i];
|
||||
out += "\n";
|
||||
|
||||
prepareCaseCurvesForExport(resamplingPeriod, ResampleAlgorithm::PERIOD_END, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
|
||||
appendToExportData(out, expTimeSteps, expCurveData);
|
||||
}
|
||||
appendToExportData(out, exportData);
|
||||
}
|
||||
|
||||
// Pasted observed data
|
||||
{
|
||||
std::vector<std::vector<time_t> > timeSteps;
|
||||
std::vector<std::vector<CurveData>> allCurveData;
|
||||
// Vector containing cases - curves
|
||||
CurvesData asciiCurvesData;
|
||||
populateAsciiDataCurvesData(m_asciiDataCurves.childObjects(), &asciiCurvesData);
|
||||
|
||||
for (RimAsciiDataCurve* curve : m_asciiDataCurves)
|
||||
for (size_t i = 0; i < asciiCurvesData.timeSteps.size(); i++)
|
||||
{
|
||||
if (!curve->isCurveVisible()) continue;
|
||||
|
||||
size_t casePosInList = cvf::UNDEFINED_SIZE_T;
|
||||
|
||||
CurveData curveData = { curve->curveName(), RifEclipseSummaryAddress(), curve->yValues() };
|
||||
|
||||
if (casePosInList == cvf::UNDEFINED_SIZE_T)
|
||||
{
|
||||
timeSteps.push_back(curve->timeSteps());
|
||||
allCurveData.push_back(std::vector<CurveData>({ curveData }));
|
||||
}
|
||||
else
|
||||
{
|
||||
allCurveData[casePosInList].push_back(curveData);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < timeSteps.size(); i++) //cases
|
||||
{
|
||||
// Data for export
|
||||
std::vector<time_t> expTimeSteps;
|
||||
std::vector<CurveData> expCurveData;
|
||||
|
||||
out += "\n\n";
|
||||
|
||||
prepareCaseCurvesForExport(DateTimePeriod::NONE, ResampleAlgorithm::NONE, timeSteps[i], allCurveData[i], &expTimeSteps, &expCurveData);
|
||||
appendToExportData(out, expTimeSteps, expCurveData);
|
||||
appendToExportDataForCase(out, asciiCurvesData.timeSteps[i], asciiCurvesData.allCurveData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,6 +473,49 @@ void RimSummaryPlot::updateAll()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
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(30);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryPlot::showPlotInfoLabel(bool show)
|
||||
{
|
||||
if (show) m_plotInfoLabel->attach(m_qwtPlot);
|
||||
else m_plotInfoLabel->detach();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimSummaryPlot::updatePlotInfoLabel()
|
||||
{
|
||||
bool anyCurveSetFiltered = false;
|
||||
for (auto group : m_ensembleCurveSetCollection->curveSets())
|
||||
{
|
||||
if (group->isFiltered())
|
||||
{
|
||||
anyCurveSetFiltered = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
showPlotInfoLabel(anyCurveSetFiltered);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -1647,48 +1628,167 @@ void RimSummaryPlot::defineEditorAttribute(const caf::PdmFieldHandle* field, QSt
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
|
||||
const std::vector<time_t> &timeSteps, const std::vector<CurveData>& curveData,
|
||||
std::vector<time_t>* exportTimeSteps, std::vector<CurveData>* exportCurveData)
|
||||
void populateTimeHistoryCurvesData(std::vector<RimGridTimeHistoryCurve*> curves, CurvesData* curvesData)
|
||||
{
|
||||
RiaTimeHistoryCurveResampler resampler;
|
||||
CVF_ASSERT(curvesData);
|
||||
|
||||
exportTimeSteps->clear();
|
||||
exportCurveData->clear();
|
||||
curvesData->caseNames.clear();
|
||||
curvesData->timeSteps.clear();
|
||||
curvesData->allCurveData.clear();
|
||||
|
||||
if (period != DateTimePeriod::NONE)
|
||||
for (RimGridTimeHistoryCurve* curve : curves)
|
||||
{
|
||||
for (auto& curveDataItem : curveData)
|
||||
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++)
|
||||
{
|
||||
resampler.setCurveData(curveDataItem.values, timeSteps);
|
||||
|
||||
if (curveDataItem.address.hasAccumulatedData() || algorithm == ResampleAlgorithm::PERIOD_END)
|
||||
{
|
||||
resampler.resampleAndComputePeriodEndValues(period);
|
||||
}
|
||||
else
|
||||
{
|
||||
resampler.resampleAndComputeWeightedMeanValues(period);
|
||||
}
|
||||
|
||||
auto cd = curveDataItem;
|
||||
cd.values = resampler.resampledValues();
|
||||
exportCurveData->push_back(cd);
|
||||
if (curveCaseName == curvesData->caseNames[i]) casePosInList = i;
|
||||
}
|
||||
|
||||
*exportTimeSteps = resampler.resampledTimeSteps();
|
||||
}
|
||||
else
|
||||
{
|
||||
*exportTimeSteps = timeSteps;
|
||||
*exportCurveData = curveData;
|
||||
CurveData curveData = { curve->curveName(), 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>({ curveData }));
|
||||
}
|
||||
else
|
||||
{
|
||||
curvesData->allCurveData[casePosInList].push_back(curveData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void appendToExportData(QString& out, const std::vector<time_t>& timeSteps, const std::vector<CurveData>& curveData)
|
||||
void populateAsciiDataCurvesData(std::vector<RimAsciiDataCurve*> 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->curveName(), 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>({ curveData }));
|
||||
}
|
||||
else
|
||||
{
|
||||
curvesData->allCurveData[casePosInList].push_back(curveData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void populateSummaryCurvesData(std::vector<RimSummaryCurve*> curves, CurvesData* curvesData)
|
||||
{
|
||||
CVF_ASSERT(curvesData);
|
||||
|
||||
curvesData->caseNames.clear();
|
||||
curvesData->timeSteps.clear();
|
||||
curvesData->allCurveData.clear();
|
||||
|
||||
for (RimSummaryCurve* curve : curves)
|
||||
{
|
||||
if (!curve->isCurveVisible()) continue;
|
||||
QString curveCaseName = curve->summaryCaseY()->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->curveName(), curve->summaryAddressY(), curve->valuesY() };
|
||||
|
||||
if (casePosInList == cvf::UNDEFINED_SIZE_T)
|
||||
{
|
||||
curvesData->caseNames.push_back(curveCaseName);
|
||||
curvesData->timeSteps.push_back(curve->timeStepsY());
|
||||
curvesData->allCurveData.push_back(std::vector<CurveData>({ curveData }));
|
||||
}
|
||||
else
|
||||
{
|
||||
curvesData->allCurveData[casePosInList].push_back(curveData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void prepareCaseCurvesForExport(DateTimePeriod period, ResampleAlgorithm algorithm,
|
||||
const CurvesData& inputCurvesData,
|
||||
CurvesData* resultCurvesData)
|
||||
{
|
||||
RiaTimeHistoryCurveResampler resampler;
|
||||
|
||||
resultCurvesData->clear();
|
||||
|
||||
if (period != DateTimePeriod::NONE)
|
||||
{
|
||||
for (int 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->resamplePeriod = period;
|
||||
//resultCurvesData->resampleAlgorithm = algorithm;
|
||||
resultCurvesData->caseNames.push_back(caseName);
|
||||
resultCurvesData->allCurveData.push_back(std::vector<CurveData>());
|
||||
|
||||
for (auto& curveDataItem : caseCurveData)
|
||||
{
|
||||
resampler.setCurveData(curveDataItem.values, caseTimeSteps);
|
||||
|
||||
if (curveDataItem.address.hasAccumulatedData() || 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<time_t>& timeSteps, const std::vector<CurveData>& curveData)
|
||||
{
|
||||
for (size_t j = 0; j < timeSteps.size(); j++) //time steps & data points
|
||||
{
|
||||
@@ -1714,3 +1814,108 @@ void appendToExportData(QString& out, const std::vector<time_t>& timeSteps, cons
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void appendToExportData(QString& out, const std::vector<CurvesData>& curvesData)
|
||||
{
|
||||
CurvesData data = concatCurvesData(curvesData);
|
||||
|
||||
if (data.resamplePeriod != DateTimePeriod::NONE)
|
||||
{
|
||||
time_t minTimeStep = std::numeric_limits<time_t>::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 + " (" + data.caseNames[i] + ")";
|
||||
}
|
||||
}
|
||||
out += "\n";
|
||||
|
||||
std::vector<int> currIndexes(data.caseNames.size());
|
||||
for (auto& i : currIndexes) i = 0;
|
||||
|
||||
for (auto timeStep : allTimeSteps)
|
||||
{
|
||||
QString tt = QDateTime::fromTime_t(timeStep).toUTC().toString("yyyy-MM-dd hh:mm:ss ");
|
||||
out += QDateTime::fromTime_t(timeStep).toUTC().toString("yyyy-MM-dd hh:mm:ss ");
|
||||
|
||||
for (size_t i = 0; i < data.caseNames.size(); i++) // cases
|
||||
{
|
||||
// Check is time step exists in curr case
|
||||
int& 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', 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
valueText = QString::number(DOUBLE_INF);
|
||||
}
|
||||
out += "\t" + valueText;
|
||||
}
|
||||
|
||||
if (timeStepExists && currIndex < data.timeSteps[i].size()) currIndex++;
|
||||
}
|
||||
out += "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < data.caseNames.size(); i++)
|
||||
{
|
||||
out += "\n\n";
|
||||
out += "Case: " + data.caseNames[i];
|
||||
out += "\n";
|
||||
|
||||
appendToExportDataForCase(out, data.timeSteps[i], data.allCurveData[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
CurvesData concatCurvesData(const std::vector<CurvesData>& curvesData)
|
||||
{
|
||||
CVF_ASSERT(!curvesData.empty());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "RimViewWindow.h"
|
||||
|
||||
#include "qwt_plot_textlabel.h"
|
||||
#include <QPointer>
|
||||
|
||||
#include <set>
|
||||
@@ -121,6 +122,10 @@ public:
|
||||
|
||||
void updateAll();
|
||||
|
||||
void setPlotInfoLabel(const QString& label);
|
||||
void showPlotInfoLabel(bool show);
|
||||
void updatePlotInfoLabel();
|
||||
|
||||
// RimViewWindow overrides
|
||||
public:
|
||||
virtual QWidget* createViewWidget(QWidget* mainWindowParent) override;
|
||||
@@ -183,7 +188,7 @@ private:
|
||||
caf::PdmChildField<RimSummaryTimeAxisProperties*> m_timeAxisProperties;
|
||||
|
||||
QPointer<RiuSummaryQwtPlot> m_qwtPlot;
|
||||
|
||||
std::unique_ptr<QwtPlotTextLabel> m_plotInfoLabel;
|
||||
|
||||
bool m_isCrossPlot;
|
||||
|
||||
|
||||
@@ -17,7 +17,12 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RigCaseRealizationParameters.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include <limits>
|
||||
#include <functional>
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
@@ -109,3 +114,45 @@ std::map<QString, RigCaseRealizationParameters::Value> RigCaseRealizationParamet
|
||||
{
|
||||
return m_parameters;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RigCaseRealizationParameters::parameterHash(const QString& name) const
|
||||
{
|
||||
auto itr = m_parameters.find(name);
|
||||
if (itr == m_parameters.end() || !itr->second.isValid()) return 0;
|
||||
|
||||
std::hash<std::string> stringHasher;
|
||||
std::hash<double> doubleHasher;
|
||||
size_t nameHash;
|
||||
size_t valueHash;
|
||||
|
||||
nameHash = stringHasher(name.toStdString());
|
||||
|
||||
auto value = itr->second;
|
||||
if (value.isNumeric()) valueHash = doubleHasher(value.numericValue());
|
||||
else if (value.isText()) valueHash = stringHasher(value.textValue().toStdString());
|
||||
|
||||
QString s = QString::number(nameHash) + QString::number(valueHash);
|
||||
return stringHasher((QString::number(nameHash) + QString::number(valueHash)).toStdString());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
size_t RigCaseRealizationParameters::parametersHash()
|
||||
{
|
||||
if (m_parametersHash == 0)
|
||||
{
|
||||
QStringList hashes;
|
||||
for (auto param : m_parameters)
|
||||
{
|
||||
hashes.push_back(QString::number(parameterHash(param.first)));
|
||||
}
|
||||
|
||||
std::hash<std::string> stringHasher;
|
||||
m_parametersHash = stringHasher(hashes.join("").toStdString());
|
||||
}
|
||||
return m_parametersHash;
|
||||
}
|
||||
|
||||
@@ -59,12 +59,18 @@ public:
|
||||
QString m_textValue;
|
||||
};
|
||||
|
||||
RigCaseRealizationParameters() : m_parametersHash(0) { }
|
||||
|
||||
void addParameter(const QString& name, double value);
|
||||
void addParameter(const QString& name, const QString& value);
|
||||
Value parameterValue(const QString& name);
|
||||
|
||||
std::map<QString, Value> parameters() const;
|
||||
|
||||
size_t parameterHash(const QString& name) const;
|
||||
size_t parametersHash();
|
||||
|
||||
private:
|
||||
std::map<QString, Value> m_parameters;
|
||||
size_t m_parametersHash;
|
||||
};
|
||||
|
||||
@@ -255,42 +255,42 @@ std::vector<RiaSummaryCurveDefinition> RiuSummaryCurveDefSelection::allCurveDefi
|
||||
|
||||
{
|
||||
std::set<RiaSummaryCurveDefinition> curveDefinitions;
|
||||
|
||||
std::set<RifEclipseSummaryAddress> selectedAddressesFromUi = buildAddressListFromSelections();
|
||||
|
||||
for (SummarySource* currSource : selectedSummarySources())
|
||||
{
|
||||
std::vector<RimSummaryCase*> sourceCases;
|
||||
std::vector<SummarySource*> sourceSources;
|
||||
RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>(currSource);
|
||||
RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>(currSource);
|
||||
|
||||
std::set<RifEclipseSummaryAddress> addressesFromSource;
|
||||
std::vector<RimSummaryCase*> casesFromSource;
|
||||
|
||||
// Build case list
|
||||
if (ensemble)
|
||||
{
|
||||
auto sumCases = ensemble->allSummaryCases();
|
||||
sourceCases.insert(sourceCases.end(), sumCases.begin(), sumCases.end());
|
||||
auto addresses = ensemble->calculateUnionOfSummaryAddresses();
|
||||
addressesFromSource.insert(addresses.begin(), addresses.end());
|
||||
auto ensembleCases = ensemble->allSummaryCases();
|
||||
casesFromSource.insert(casesFromSource.end(), ensembleCases.begin(), ensembleCases.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
RimSummaryCase* sourceCase = dynamic_cast<RimSummaryCase*>(currSource);
|
||||
if (sourceCase)
|
||||
RifSummaryReaderInterface* reader = sumCase ? sumCase->summaryReader() : nullptr;
|
||||
if (reader)
|
||||
{
|
||||
sourceCases.push_back(sourceCase);
|
||||
addressesFromSource.insert(reader->allResultAddresses().begin(), reader->allResultAddresses().end());
|
||||
casesFromSource.push_back(sumCase);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& currCase : sourceCases)
|
||||
for (auto caseFromSource : casesFromSource)
|
||||
{
|
||||
if (currCase && currCase->summaryReader())
|
||||
for (const auto& addressFromSource : addressesFromSource)
|
||||
{
|
||||
RifSummaryReaderInterface* reader = currCase->summaryReader();
|
||||
|
||||
const std::vector<RifEclipseSummaryAddress>& readerAddresses = reader->allResultAddresses();
|
||||
for (const auto& readerAddress : readerAddresses)
|
||||
if (selectedAddressesFromUi.count(addressFromSource) > 0)
|
||||
{
|
||||
if (selectedAddressesFromUi.count(readerAddress) > 0)
|
||||
{
|
||||
curveDefinitions.insert(RiaSummaryCurveDefinition(currCase, readerAddress, ensemble));
|
||||
}
|
||||
curveDefinitions.insert(RiaSummaryCurveDefinition(caseFromSource, addressFromSource, ensemble));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,6 +313,7 @@ std::vector<RiaSummaryCurveDefinition> RiuSummaryCurveDefSelection::selection()
|
||||
{
|
||||
RimSummaryCaseCollection* ensemble = dynamic_cast<RimSummaryCaseCollection*>(currSource);
|
||||
RimSummaryCase* sourceCase = dynamic_cast<RimSummaryCase*>(currSource);
|
||||
|
||||
if (ensemble)
|
||||
{
|
||||
std::set<RifEclipseSummaryAddress> addressUnion = ensemble->calculateUnionOfSummaryAddresses();
|
||||
@@ -328,10 +329,10 @@ std::vector<RiaSummaryCurveDefinition> RiuSummaryCurveDefSelection::selection()
|
||||
{
|
||||
if (!(sourceCase && sourceCase->summaryReader())) continue;
|
||||
|
||||
const std::vector<RifEclipseSummaryAddress>& readerAddresses = sourceCase->summaryReader()->allResultAddresses();
|
||||
for ( const auto& addr : readerAddresses)
|
||||
const std::set<RifEclipseSummaryAddress>& readerAddresses = sourceCase->summaryReader()->allResultAddresses();
|
||||
for ( const auto& addr : selectedAddressesFromUi)
|
||||
{
|
||||
if (selectedAddressesFromUi.count(addr))
|
||||
if (readerAddresses.count(addr))
|
||||
{
|
||||
curveDefSelection.push_back(RiaSummaryCurveDefinition(sourceCase, addr, nullptr));
|
||||
}
|
||||
@@ -481,7 +482,7 @@ std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSumm
|
||||
{
|
||||
RimSummaryCase* calcSumCase = calculatedSummaryCase();
|
||||
|
||||
const std::vector<RifEclipseSummaryAddress> allAddresses = calcSumCase->summaryReader()->allResultAddresses();
|
||||
const std::set<RifEclipseSummaryAddress> allAddresses = calcSumCase->summaryReader()->allResultAddresses();
|
||||
for (const auto& adr : allAddresses)
|
||||
{
|
||||
addressSet.insert(adr);
|
||||
@@ -868,7 +869,7 @@ void RiuSummaryCurveDefSelection::defineUiOrdering(QString uiConfigName, caf::Pd
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSummaryAddressesFromSelectedCases(const SummaryIdentifierAndField *identifierAndField)
|
||||
{
|
||||
std::vector<RimSummaryCase*> cases;
|
||||
std::vector<SummarySource*> sources;
|
||||
for (const auto& source : m_selectedSources())
|
||||
{
|
||||
RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>(source.p());
|
||||
@@ -876,15 +877,14 @@ std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSumm
|
||||
|
||||
if (sumCase)
|
||||
{
|
||||
if(!isObservedData(sumCase)) cases.push_back(sumCase);
|
||||
if(!isObservedData(sumCase)) sources.push_back(sumCase);
|
||||
}
|
||||
else if (ensemble)
|
||||
{
|
||||
const auto& ensembleCases = ensemble->allSummaryCases();
|
||||
cases.insert(cases.end(), ensembleCases.begin(), ensembleCases.end());
|
||||
sources.push_back(ensemble);
|
||||
}
|
||||
}
|
||||
return findPossibleSummaryAddresses(cases, identifierAndField);
|
||||
return findPossibleSummaryAddresses(sources, identifierAndField);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -892,7 +892,7 @@ std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSumm
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSummaryAddressesFromSelectedObservedData(const SummaryIdentifierAndField *identifierAndField)
|
||||
{
|
||||
std::vector<RimSummaryCase*> obsData;
|
||||
std::vector<SummarySource*> obsData;
|
||||
for (const auto& source : m_selectedSources())
|
||||
{
|
||||
RimSummaryCase* sumCase = dynamic_cast<RimSummaryCase*>(source.p());
|
||||
@@ -908,7 +908,7 @@ std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSumm
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Returns the summary addresses that match the selected item type and input selections made in GUI
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSummaryAddresses(const std::vector<RimSummaryCase*> &selectedCases,
|
||||
std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSummaryAddresses(const std::vector<SummarySource*> &selectedSources,
|
||||
const SummaryIdentifierAndField *identifierAndField)
|
||||
{
|
||||
std::set<RifEclipseSummaryAddress> addrUnion;
|
||||
@@ -920,32 +920,42 @@ std::set<RifEclipseSummaryAddress> RiuSummaryCurveDefSelection::findPossibleSumm
|
||||
return addrUnion;
|
||||
}
|
||||
|
||||
for (RimSummaryCase* currCase : selectedCases)
|
||||
for (SummarySource* currSource : selectedSources)
|
||||
{
|
||||
RifSummaryReaderInterface* reader = nullptr;
|
||||
if (currCase) reader = currCase->summaryReader();
|
||||
if (reader)
|
||||
std::set<RifEclipseSummaryAddress> allAddresses;
|
||||
|
||||
RimSummaryCase* currCase = dynamic_cast<RimSummaryCase*>(currSource);
|
||||
RimSummaryCaseCollection* currEnsemble = dynamic_cast<RimSummaryCaseCollection*>(currSource);
|
||||
|
||||
if (currCase)
|
||||
{
|
||||
const std::vector<RifEclipseSummaryAddress>& allAddresses = reader->allResultAddresses();
|
||||
int addressCount = static_cast<int>(allAddresses.size());
|
||||
RifSummaryReaderInterface* reader = nullptr;
|
||||
if (currCase) reader = currCase->summaryReader();
|
||||
if (reader) allAddresses = reader->allResultAddresses();
|
||||
}
|
||||
else if (currEnsemble)
|
||||
{
|
||||
allAddresses = currEnsemble->calculateUnionOfSummaryAddresses();
|
||||
}
|
||||
|
||||
bool applySelections = identifierAndField == nullptr || (!isVectorField && controllingIdentifierAndField != nullptr);
|
||||
std::vector<SummaryIdentifierAndField*> controllingFields;
|
||||
if (applySelections)
|
||||
{
|
||||
// Build selections vector
|
||||
controllingFields = buildControllingFieldList(identifierAndField);
|
||||
}
|
||||
int addressCount = static_cast<int>(allAddresses.size());
|
||||
|
||||
for (int i = 0; i < addressCount; i++)
|
||||
bool applySelections = identifierAndField == nullptr || (!isVectorField && controllingIdentifierAndField != nullptr);
|
||||
std::vector<SummaryIdentifierAndField*> controllingFields;
|
||||
if (applySelections)
|
||||
{
|
||||
// Build selections vector
|
||||
controllingFields = buildControllingFieldList(identifierAndField);
|
||||
}
|
||||
|
||||
for(auto& address : allAddresses)
|
||||
{
|
||||
if (address.category() == m_currentSummaryCategory())
|
||||
{
|
||||
if (allAddresses[i].category() == m_currentSummaryCategory())
|
||||
bool addressSelected = applySelections ? isAddressCompatibleWithControllingFieldSelection(address, controllingFields) : true;
|
||||
if (addressSelected)
|
||||
{
|
||||
bool addressSelected = applySelections ? isAddressCompatibleWithControllingFieldSelection(allAddresses[i], controllingFields) : true;
|
||||
if (addressSelected)
|
||||
{
|
||||
addrUnion.insert(allAddresses[i]);
|
||||
}
|
||||
addrUnion.insert(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ private:
|
||||
caf::PdmUiEditorAttribute* attribute) override;
|
||||
|
||||
|
||||
std::set<RifEclipseSummaryAddress> findPossibleSummaryAddresses(const std::vector<RimSummaryCase*> &selectedCases,
|
||||
std::set<RifEclipseSummaryAddress> findPossibleSummaryAddresses(const std::vector<SummarySource*> &selectedSources,
|
||||
const SummaryIdentifierAndField *identifierAndField);
|
||||
std::set<RifEclipseSummaryAddress> findPossibleSummaryAddressesFromSelectedCases(const SummaryIdentifierAndField *identifierAndField);
|
||||
std::set<RifEclipseSummaryAddress> findPossibleSummaryAddressesFromSelectedObservedData(const SummaryIdentifierAndField *identifierAndField);
|
||||
|
||||
@@ -32,13 +32,14 @@
|
||||
#include "cvfAssert.h"
|
||||
|
||||
#include "qwt_legend.h"
|
||||
#include "qwt_plot_layout.h"
|
||||
|
||||
#include <QFocusEvent>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMdiSubWindow>
|
||||
#include <QMenu>
|
||||
#include <QScrollBar>
|
||||
#include <QTimer>
|
||||
#include <QMenu>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -57,6 +58,12 @@ RiuWellLogPlot::RiuWellLogPlot(RimWellLogPlot* plotDefinition, QWidget* parent)
|
||||
|
||||
setAutoFillBackground(true);
|
||||
|
||||
m_plotTitle = new QLabel("PLOT TITLE HERE", this);
|
||||
QFont font = m_plotTitle->font();
|
||||
font.setPointSize(14);
|
||||
font.setBold(true);
|
||||
m_plotTitle->setFont(font);
|
||||
m_plotTitle->hide();
|
||||
m_scrollBar = new QScrollBar(this);
|
||||
m_scrollBar->setOrientation(Qt::Vertical);
|
||||
m_scrollBar->setVisible(true);
|
||||
@@ -97,14 +104,19 @@ void RiuWellLogPlot::insertTrackPlot(RiuWellLogTrack* trackPlot, size_t index)
|
||||
m_trackPlots.insert(static_cast<int>(index), trackPlot);
|
||||
|
||||
QwtLegend* legend = new QwtLegend(this);
|
||||
legend->setMaxColumns(1);
|
||||
int legendColumns = 1;
|
||||
if (m_plotDefinition->areTrackLegendsHorizontal())
|
||||
{
|
||||
legendColumns = 0; // unlimited
|
||||
}
|
||||
legend->setMaxColumns(legendColumns);
|
||||
legend->connect(trackPlot, SIGNAL(legendDataChanged(const QVariant &, const QList< QwtLegendData > &)), SLOT(updateLegend(const QVariant &, const QList< QwtLegendData > &)));
|
||||
legend->contentsWidget()->layout()->setAlignment(Qt::AlignBottom | Qt::AlignHCenter);
|
||||
m_legends.insert(static_cast<int>(index), legend);
|
||||
|
||||
this->connect(trackPlot, SIGNAL(legendDataChanged(const QVariant &, const QList< QwtLegendData > &)), SLOT(scheduleUpdateChildrenLayout()));
|
||||
|
||||
if (!m_plotDefinition->isTrackLegendsVisible())
|
||||
if (!m_plotDefinition->areTrackLegendsVisible())
|
||||
{
|
||||
legend->hide();
|
||||
}
|
||||
@@ -201,6 +213,15 @@ void RiuWellLogPlot::setDepthZoomAndReplot(double minDepth, double maxDepth)
|
||||
updateScrollBar(minDepth, maxDepth);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuWellLogPlot::setPlotTitle(const QString& plotTitle)
|
||||
{
|
||||
m_plotTitle->setText(plotTitle);
|
||||
this->updateChildrenLayout();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -296,77 +317,196 @@ void RiuWellLogPlot::resizeEvent(QResizeEvent *event)
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuWellLogPlot::placeChildWidgets(int height, int width)
|
||||
std::map<int, int> RiuWellLogPlot::calculateTrackWidths(int frameWidth)
|
||||
{
|
||||
int trackCount = m_trackPlots.size();
|
||||
CVF_ASSERT(m_legends.size() == trackCount);
|
||||
|
||||
|
||||
int visibleTrackCount = 0;
|
||||
int firstTrackAxisOffset = 0; // Account for first track having the y-axis labels and markers
|
||||
for (int tIdx = 0; tIdx < trackCount; ++tIdx)
|
||||
{
|
||||
if (m_trackPlots[tIdx]->isVisible()) ++visibleTrackCount;
|
||||
if (m_trackPlots[tIdx]->isVisible())
|
||||
{
|
||||
if (visibleTrackCount == 0)
|
||||
{
|
||||
firstTrackAxisOffset = static_cast<int>(m_trackPlots[tIdx]->plotLayout()->canvasRect().left());
|
||||
}
|
||||
++visibleTrackCount;
|
||||
}
|
||||
}
|
||||
|
||||
int scrollBarWidth = 0;
|
||||
if (m_scrollBar->isVisible()) scrollBarWidth = m_scrollBar->sizeHint().width();
|
||||
|
||||
int maxLegendHeight = 0;
|
||||
|
||||
if (m_plotDefinition && m_plotDefinition->isTrackLegendsVisible())
|
||||
{
|
||||
for ( int tIdx = 0; tIdx < trackCount; ++tIdx )
|
||||
{
|
||||
if ( m_trackPlots[tIdx]->isVisible() )
|
||||
{
|
||||
int legendHeight = m_legends[tIdx]->sizeHint().height();
|
||||
if ( legendHeight > maxLegendHeight ) maxLegendHeight = legendHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int trackHeight = height - maxLegendHeight;
|
||||
int trackX = 0;
|
||||
|
||||
std::map<int, int> trackWidths;
|
||||
|
||||
if (visibleTrackCount)
|
||||
{
|
||||
int trackWidth = (width - scrollBarWidth)/visibleTrackCount;
|
||||
int trackWidthExtra = (width-scrollBarWidth)%visibleTrackCount;
|
||||
int totalTrackWidth = (frameWidth - firstTrackAxisOffset - scrollBarWidth);
|
||||
int trackWidthExtra = (frameWidth - firstTrackAxisOffset - scrollBarWidth) % visibleTrackCount;
|
||||
|
||||
int totalWidthWeights = 0;
|
||||
for (int tIdx = 0; tIdx < trackCount; ++tIdx)
|
||||
{
|
||||
if (m_trackPlots[tIdx]->isVisible())
|
||||
{
|
||||
int realTrackWidth = trackWidth;
|
||||
totalWidthWeights += m_trackPlots[tIdx]->widthScaleFactor();
|
||||
}
|
||||
}
|
||||
|
||||
bool firstVisible = true;
|
||||
for (int tIdx = 0; tIdx < trackCount; ++tIdx)
|
||||
{
|
||||
if (m_trackPlots[tIdx]->isVisible())
|
||||
{
|
||||
int realTrackWidth = (totalTrackWidth * m_trackPlots[tIdx]->widthScaleFactor()) / totalWidthWeights;
|
||||
|
||||
if (firstVisible)
|
||||
{
|
||||
realTrackWidth += firstTrackAxisOffset;
|
||||
firstVisible = false;
|
||||
}
|
||||
|
||||
if (trackWidthExtra > 0)
|
||||
{
|
||||
realTrackWidth += 1;
|
||||
--trackWidthExtra;
|
||||
}
|
||||
int realLegendWidth = std::max(realTrackWidth, m_legends[tIdx]->sizeHint().width());
|
||||
m_legends[tIdx]->setGeometry(trackX, 0, realLegendWidth, maxLegendHeight);
|
||||
m_trackPlots[tIdx]->setGeometry(trackX, maxLegendHeight, realTrackWidth, trackHeight);
|
||||
|
||||
trackWidths[tIdx] = realTrackWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return trackWidths;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuWellLogPlot::placeChildWidgets(int frameHeight, int frameWidth)
|
||||
{
|
||||
CVF_ASSERT(m_legends.size() == m_trackPlots.size());
|
||||
|
||||
positionTitle(frameWidth);
|
||||
|
||||
const int trackPadding = 4;
|
||||
|
||||
std::map<int, int> trackWidths = calculateTrackWidths(frameWidth);
|
||||
size_t visibleTrackCount = trackWidths.size();
|
||||
|
||||
int maxLegendHeight = 0;
|
||||
|
||||
if (m_plotDefinition && m_plotDefinition->areTrackLegendsVisible())
|
||||
{
|
||||
for ( int tIdx = 0; tIdx < m_trackPlots.size(); ++tIdx )
|
||||
{
|
||||
if ( m_trackPlots[tIdx]->isVisible() )
|
||||
{
|
||||
int legendHeight = m_legends[tIdx]->heightForWidth(trackWidths[tIdx] - 2 * trackPadding);
|
||||
if ( legendHeight > maxLegendHeight ) maxLegendHeight = legendHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int titleHeight = 0;
|
||||
if (m_plotTitle && m_plotTitle->isVisible())
|
||||
{
|
||||
titleHeight = m_plotTitle->height() + 10;
|
||||
}
|
||||
|
||||
int trackHeight = frameHeight - maxLegendHeight;
|
||||
int trackX = 0;
|
||||
|
||||
if (visibleTrackCount)
|
||||
{
|
||||
|
||||
int maxCanvasOffset = 0;
|
||||
for (int tIdx = 0; tIdx < m_trackPlots.size(); ++tIdx)
|
||||
{
|
||||
if (m_trackPlots[tIdx]->isVisible())
|
||||
{
|
||||
// Hack to align QWT plots. See below.
|
||||
QRectF canvasRect = m_trackPlots[tIdx]->plotLayout()->canvasRect();
|
||||
maxCanvasOffset = std::max(maxCanvasOffset, static_cast<int>(canvasRect.top()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int tIdx = 0; tIdx < m_trackPlots.size(); ++tIdx)
|
||||
{
|
||||
if (m_trackPlots[tIdx]->isVisible())
|
||||
{
|
||||
int adjustedVerticalPosition = titleHeight + maxLegendHeight + 10;
|
||||
int adjustedTrackHeight = trackHeight;
|
||||
{
|
||||
// Hack to align QWT plots which doesn't have an x-axis with the other tracks.
|
||||
// Since they are missing the axis, QWT will shift them upwards.
|
||||
// So we shift the plot downwards and resize to match the others.
|
||||
// TODO: Look into subclassing QwtPlotLayout instead.
|
||||
QRectF canvasRect = m_trackPlots[tIdx]->plotLayout()->canvasRect();
|
||||
int myCanvasOffset = static_cast<int>(canvasRect.top());
|
||||
int myMargins = m_trackPlots[tIdx]->plotLayout()->canvasMargin(QwtPlot::xTop);
|
||||
int canvasShift = std::max(0, maxCanvasOffset - myCanvasOffset);
|
||||
adjustedVerticalPosition += canvasShift - myMargins;
|
||||
adjustedTrackHeight -= canvasShift;
|
||||
}
|
||||
|
||||
int realTrackWidth = trackWidths[tIdx];
|
||||
m_legends[tIdx]->setGeometry(trackX + trackPadding, titleHeight, realTrackWidth - 2 * trackPadding, maxLegendHeight);
|
||||
m_trackPlots[tIdx]->setGeometry(trackX + trackPadding, adjustedVerticalPosition, realTrackWidth - 2 * trackPadding, adjustedTrackHeight);
|
||||
|
||||
trackX += realTrackWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_scrollBar->isVisible()) m_scrollBar->setGeometry(trackX, maxLegendHeight, scrollBarWidth, trackHeight);
|
||||
if (m_scrollBar->isVisible())
|
||||
{
|
||||
m_scrollBar->setGeometry(trackX, titleHeight + maxLegendHeight, m_scrollBar->sizeHint().width(), trackHeight);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuWellLogPlot::positionTitle(int frameWidth)
|
||||
{
|
||||
if (m_plotDefinition && m_plotDefinition->isPlotTitleVisible())
|
||||
{
|
||||
int textWidth = m_plotTitle->sizeHint().width();
|
||||
m_plotTitle->setGeometry(frameWidth/2 - textWidth/2, 0, textWidth, m_plotTitle->sizeHint().height());
|
||||
m_plotTitle->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_plotTitle->hide();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuWellLogPlot::updateChildrenLayout()
|
||||
{
|
||||
{
|
||||
int trackCount = m_trackPlots.size();
|
||||
int numTracksAlreadyShown = 0;
|
||||
for (int tIdx = 0; tIdx < trackCount; ++tIdx)
|
||||
{
|
||||
if (m_trackPlots[tIdx]->isVisible())
|
||||
{
|
||||
m_legends[tIdx]->show();
|
||||
int legendColumns = 1;
|
||||
if (m_plotDefinition->areTrackLegendsHorizontal())
|
||||
{
|
||||
legendColumns = 0; // unlimited
|
||||
}
|
||||
m_legends[tIdx]->setMaxColumns(legendColumns);
|
||||
m_legends[tIdx]->show();
|
||||
|
||||
m_trackPlots[tIdx]->enableVerticalAxisLabelsAndTitle(numTracksAlreadyShown == 0);
|
||||
numTracksAlreadyShown++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -19,20 +19,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RiuInterfaceToViewWindow.h"
|
||||
|
||||
#include "cafPdmPointer.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QPointer>
|
||||
#include <QWidget>
|
||||
|
||||
#include "RiuInterfaceToViewWindow.h"
|
||||
#include <map>
|
||||
|
||||
class RimWellLogPlot;
|
||||
class RiuWellLogTrack;
|
||||
|
||||
class QHBoxLayout;
|
||||
class QScrollBar;
|
||||
class QFocusEvent;
|
||||
class QLabel;
|
||||
class QScrollBar;
|
||||
class QwtLegend;
|
||||
|
||||
//==================================================================================================
|
||||
@@ -56,8 +58,9 @@ public:
|
||||
void removeTrackPlot(RiuWellLogTrack* trackPlot);
|
||||
|
||||
void setDepthZoomAndReplot(double minDepth, double maxDepth);
|
||||
void setPlotTitle(const QString& plotTitle);
|
||||
|
||||
public slots:
|
||||
public slots:
|
||||
void updateChildrenLayout();
|
||||
|
||||
protected:
|
||||
@@ -70,18 +73,20 @@ protected:
|
||||
private:
|
||||
void updateScrollBar(double minDepth, double maxDepth);
|
||||
void modifyWidthOfContainingMdiWindow(int widthChange);
|
||||
void placeChildWidgets(int height, int width);
|
||||
std::map<int, int> calculateTrackWidths(int frameWidth);
|
||||
void placeChildWidgets(int frameHeight, int frameWidth);
|
||||
void positionTitle(int frameWidth);
|
||||
|
||||
private slots:
|
||||
void slotSetMinDepth(int value);
|
||||
void scheduleUpdateChildrenLayout();
|
||||
|
||||
private:
|
||||
QHBoxLayout* m_layout;
|
||||
QScrollBar* m_scrollBar;
|
||||
QList<QPointer<QwtLegend> > m_legends;
|
||||
QLabel* m_plotTitle;
|
||||
QScrollBar* m_scrollBar;
|
||||
QList<QPointer<QwtLegend> > m_legends;
|
||||
QList<QPointer<RiuWellLogTrack> > m_trackPlots;
|
||||
caf::PdmPointer<RimWellLogPlot> m_plotDefinition;
|
||||
QTimer* m_scheduleUpdateChildrenLayoutTimer;
|
||||
caf::PdmPointer<RimWellLogPlot> m_plotDefinition;
|
||||
QTimer* m_scheduleUpdateChildrenLayoutTimer;
|
||||
};
|
||||
|
||||
|
||||
@@ -261,3 +261,30 @@ bool RiuWellLogTrack::isRimTrackVisible()
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuWellLogTrack::enableVerticalAxisLabelsAndTitle(bool enable)
|
||||
{
|
||||
QString depthAxisTitle("");
|
||||
if (enable && m_plotTrackDefinition)
|
||||
{
|
||||
depthAxisTitle = m_plotTrackDefinition->depthPlotTitle();
|
||||
}
|
||||
this->setAxisTitle(QwtPlot::yLeft, depthAxisTitle);
|
||||
this->axisScaleDraw(QwtPlot::yLeft)->enableComponent(
|
||||
QwtAbstractScaleDraw::Labels, enable);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RiuWellLogTrack::widthScaleFactor() const
|
||||
{
|
||||
if (m_plotTrackDefinition)
|
||||
{
|
||||
return m_plotTrackDefinition->widthScaleFactor();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ public:
|
||||
void setXRange(double min, double max);
|
||||
|
||||
bool isRimTrackVisible();
|
||||
void enableVerticalAxisLabelsAndTitle(bool enable);
|
||||
int widthScaleFactor() const;
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject* watched, QEvent* event);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
@startuml
|
||||
left to right direction
|
||||
|
||||
|
||||
RifSummaryReaderInterface <|-- RifCalculatedSummaryCurveReader
|
||||
RifSummaryReaderInterface <|-- RifColumnBasedUserData
|
||||
RifSummaryReaderInterface <|-- RifCsvUserData
|
||||
@@ -9,17 +8,24 @@ RifSummaryReaderInterface <|-- RifKeywordVectorUserData
|
||||
RifSummaryReaderInterface <|-- RifReaderEclipseSummary
|
||||
RifSummaryReaderInterface <|-- RifReaderObservedData
|
||||
RifSummaryReaderInterface <|-- RifEnsembleStatisticsReader
|
||||
RifSummaryReaderInterface <|-- RifDerivedEnsembleReader
|
||||
|
||||
RifColumnBasedUserData *-- "1" RifColumnBasedUserDataParser
|
||||
RifKeywordVectorUserData *-- "1" RifKeywordVectorUserDataParser
|
||||
RifReaderObservedData --> RifCsvUserDataParser
|
||||
|
||||
RimSummaryCaseCollection -> "*" RimSummaryCase
|
||||
RimSummaryCaseCollection --> "*" RimSummaryCase
|
||||
|
||||
RimSummaryCaseCollection <|-- RimDerivedEnsembleCaseCollection
|
||||
|
||||
RimDerivedEnsembleCaseCollection --> "*" RimDerivedEnsembleCase
|
||||
|
||||
RimSummaryCase <|-- RimCalculatedSummaryCase
|
||||
RimSummaryCase <|-- RimFileSummaryCase
|
||||
RimSummaryCase <|-- RimGridSummaryCase
|
||||
RimSummaryCase <|-- RimObservedData
|
||||
RimSummaryCase <|-- RimEnsembleStatisticsCase
|
||||
RimSummaryCase <|-- RimDerivedEnsembleCase
|
||||
|
||||
RimObservedData <|-- RimObservedEclipseUserData
|
||||
RimObservedData <|-- RimCsvUserData
|
||||
@@ -27,6 +33,8 @@ RimObservedData <|-- RimSummaryObservedDataFile
|
||||
|
||||
RimCalculatedSummaryCase --> RifCalculatedSummaryCurveReader
|
||||
|
||||
RimDerivedEnsembleCase --> RifDerivedEnsembleReader
|
||||
|
||||
RimSummaryObservedDataFile --> RifReaderObservedData
|
||||
|
||||
RimObservedEclipseUserData *--> RifSummaryReaderInterface
|
||||
@@ -44,4 +52,7 @@ RimEnsembleCurveSet -> "1" RimSummaryCaseCollection
|
||||
RimEnsembleCurveSet --> "1" RimEnsembleStatisticsCase
|
||||
RimEnsembleStatisticsCase --> RifEnsembleStatisticsReader
|
||||
|
||||
RimSummaryCaseMainCollection -> "*" RimSummaryCase
|
||||
RimSummaryCaseMainCollection -> "*" RimSummaryCaseCollection
|
||||
|
||||
@enduml
|
||||
|
||||
Reference in New Issue
Block a user