#4580 Import Eclipse RFT data as part of ensemble import

This commit is contained in:
Gaute Lindkvist
2019-07-25 07:38:46 +02:00
parent 222f230687
commit 71da659506
77 changed files with 2960 additions and 848 deletions

View File

@@ -1,52 +1,69 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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>
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaRftPltCurveDefinition.h"
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RiaRftPltCurveDefinition::RiaRftPltCurveDefinition(RifDataSourceForRftPlt address, const QDateTime timeStep)
RiaRftPltCurveDefinition::RiaRftPltCurveDefinition(const RifDataSourceForRftPlt& address, const QString& wellName, const QDateTime& timeStep)
: m_curveAddress(address)
, m_wellName(wellName)
, m_timeStep(timeStep)
{
m_curveDefinition = std::make_pair(address, timeStep);
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RifDataSourceForRftPlt RiaRftPltCurveDefinition::address() const
const RifDataSourceForRftPlt& RiaRftPltCurveDefinition::address() const
{
return m_curveDefinition.first;
return m_curveAddress;
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
QDateTime RiaRftPltCurveDefinition::timeStep() const
const QString& RiaRftPltCurveDefinition::wellName() const
{
return m_curveDefinition.second;
return m_wellName;
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
const QDateTime& RiaRftPltCurveDefinition::timeStep() const
{
return m_timeStep;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RiaRftPltCurveDefinition::operator<(const RiaRftPltCurveDefinition& other) const
{
return m_curveDefinition < other.m_curveDefinition;
if (m_curveAddress == other.m_curveAddress)
{
if (m_wellName == other.m_wellName)
{
return m_timeStep < other.m_timeStep;
}
return m_wellName < other.m_wellName;
}
return m_curveAddress < other.m_curveAddress;
}

View File

@@ -33,13 +33,16 @@ class RimSummaryCase;
class RiaRftPltCurveDefinition
{
public:
explicit RiaRftPltCurveDefinition(RifDataSourceForRftPlt address, const QDateTime timeStep);
explicit RiaRftPltCurveDefinition(const RifDataSourceForRftPlt& address, const QString& wellName, const QDateTime& timeStep);
RifDataSourceForRftPlt address() const;
QDateTime timeStep() const;
const RifDataSourceForRftPlt& address() const;
const QString& wellName() const;
const QDateTime& timeStep() const;
bool operator < (const RiaRftPltCurveDefinition& other) const;
private:
std::pair<RifDataSourceForRftPlt, QDateTime> m_curveDefinition;
RifDataSourceForRftPlt m_curveAddress;
QString m_wellName;
QDateTime m_timeStep;
};

View File

@@ -25,7 +25,8 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaTextFileCompare.h
${CMAKE_CURRENT_LIST_DIR}/RiaRegressionTestRunner.h
${CMAKE_CURRENT_LIST_DIR}/RiaExtractionTools.h
${CMAKE_CURRENT_LIST_DIR}/RiaFilePathTools.h
${CMAKE_CURRENT_LIST_DIR}/RiaTimeHistoryCurveMerger.h
${CMAKE_CURRENT_LIST_DIR}/RiaCurveMerger.h
${CMAKE_CURRENT_LIST_DIR}/RiaCurveMerger.inl
${CMAKE_CURRENT_LIST_DIR}/RiaCurveDataTools.h
${CMAKE_CURRENT_LIST_DIR}/RiaTimeHistoryCurveResampler.h
${CMAKE_CURRENT_LIST_DIR}/RiaStatisticsTools.h
@@ -67,7 +68,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RiaTextFileCompare.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaRegressionTestRunner.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaExtractionTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaFilePathTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaTimeHistoryCurveMerger.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaCurveMerger.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaCurveDataTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaTimeHistoryCurveResampler.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaStatisticsTools.cpp

View File

@@ -142,6 +142,21 @@ cvf::Color3f RiaColorTools::fromQColorTo3f(QColor color)
return cvf::Color3f(color.redF(), color.greenF(), color.blueF());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
cvf::Color3f RiaColorTools::blendCvfColors(const cvf::Color3f& color1,
const cvf::Color3f& color2,
int weight1 /*= 1*/,
int weight2 /*= 1*/)
{
CVF_ASSERT(weight1 > 0 && weight2 > 0);
int weightsum = weight1 + weight2;
return cvf::Color3f((color1.r() * weight1 + color2.r() * weight2) / weightsum,
(color1.g() * weight1 + color2.g() * weight2) / weightsum,
(color1.b() * weight1 + color2.b() * weight2) / weightsum);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -43,7 +43,8 @@ public:
static QColor toQColor(cvf::Color4f color);
static cvf::Color3f fromQColorTo3f(QColor);
static QColor blendQColors(const QColor& color1, const QColor& color2, int weight1 = 1, int weight2 = 1);
static cvf::Color3f blendCvfColors(const cvf::Color3f& color1, const cvf::Color3f& color2, int weight1 = 1, int weight2 = 1);
static QColor blendQColors(const QColor& color1, const QColor& color2, int weight1 = 1, int weight2 = 1);
private:
static float relativeLuminance(cvf::Color3f backgroundColor);

View File

@@ -0,0 +1,20 @@
#include "RiaCurveMerger.h"
#include <algorithm>
#include <time.h>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<>
bool XValueComparator<double>::equals(const double& lhs, const double& rhs)
{
double eps = 1.0e-12 * std::max(std::fabs(lhs), std::fabs(rhs));
return std::fabs(lhs - rhs) < eps;
}
template<>
double XValueComparator<time_t>::diff(const time_t& lhs, const time_t& rhs)
{
return difftime(lhs, rhs);
}

View File

@@ -0,0 +1,87 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaCurveDataTools.h"
#include <ctime>
template<typename XValueType>
class XValueComparator
{
public:
bool operator()(const XValueType& lhs, const XValueType& rhs) const;
static bool equals(const XValueType& lhs, const XValueType& rhs);
static double diff(const XValueType& lhs, const XValueType& rhs);
};
//==================================================================================================
///
//==================================================================================================
template<typename XValueType>
class RiaCurveMerger
{
public:
typedef XValueComparator<XValueType> XComparator;
RiaCurveMerger();
void addCurveData(const std::vector<XValueType>& xValues, const std::vector<double>& yValues);
size_t curveCount() const;
void computeInterpolatedValues(bool includeValuesFromPartialCurves = true);
RiaCurveDataTools::CurveIntervals validIntervalsForAllXValues() const;
const std::vector<XValueType>& allXValues() const;
const std::vector<double>& interpolatedYValuesForAllXValues(size_t curveIdx) const;
// Non-const access is not required by any clients, but the expression parser has no available const interface
// for specifying a data source for an expression variable. Allow non-const access to avoid copy of the contained
// values, interpolated for all time steps
//
// See ExpressionParserImpl::assignVector()
std::vector<double>& interpolatedYValuesForAllXValues(size_t curveIdx);
public:
// Helper methods, available as public to be able to access from unit tests
static double interpolatedYValue(const XValueType& xValue,
const std::vector<XValueType>& curveXValues,
const std::vector<double>& curveYValues);
private:
void computeUnionOfXValues(bool includeValuesFromPartialCurves);
private:
std::vector<std::pair<std::vector<XValueType>, std::vector<double>>> m_originalValues;
RiaCurveDataTools::CurveIntervals m_validIntervalsForAllXValues;
std::vector<XValueType> m_allXValues;
std::vector<std::vector<double>> m_interpolatedValuesForAllCurves;
};
typedef RiaCurveMerger<time_t> RiaTimeHistoryCurveMerger;
template<>
bool XValueComparator<double>::equals(const double& lhs, const double& rhs);
template<>
double XValueComparator<time_t>::diff(const time_t& lhs, const time_t& rhs);
#include "RiaCurveMerger.inl"

View File

@@ -0,0 +1,286 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 <algorithm>
#include <cmath> // Needed for HUGE_VAL on Linux
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
bool XValueComparator<XValueType>::operator()(const XValueType& lhs, const XValueType& rhs) const
{
if (XValueComparator<XValueType>::equals(lhs, rhs))
{
return false;
}
return lhs < rhs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
double XValueComparator<XValueType>::diff(const XValueType& lhs, const XValueType& rhs)
{
return lhs - rhs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
bool XValueComparator<XValueType>::equals(const XValueType& lhs, const XValueType& rhs)
{
return lhs == rhs;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
RiaCurveMerger<XValueType>::RiaCurveMerger()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
void RiaCurveMerger<XValueType>::addCurveData(const std::vector<XValueType>& xValues, const std::vector<double>& yValues)
{
CVF_ASSERT(xValues.size() == yValues.size());
m_originalValues.push_back(std::make_pair(xValues, yValues));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
size_t RiaCurveMerger<XValueType>::curveCount() const
{
return m_interpolatedValuesForAllCurves.size();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
RiaCurveDataTools::CurveIntervals RiaCurveMerger<XValueType>::validIntervalsForAllXValues() const
{
return m_validIntervalsForAllXValues;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
const std::vector<XValueType>& RiaCurveMerger<XValueType>::allXValues() const
{
return m_allXValues;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
const std::vector<double>& RiaCurveMerger<XValueType>::interpolatedYValuesForAllXValues(size_t curveIdx) const
{
CVF_ASSERT(curveIdx < m_interpolatedValuesForAllCurves.size());
return m_interpolatedValuesForAllCurves[curveIdx];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
std::vector<double>& RiaCurveMerger<XValueType>::interpolatedYValuesForAllXValues(size_t curveIdx)
{
CVF_ASSERT(curveIdx < m_interpolatedValuesForAllCurves.size());
return m_interpolatedValuesForAllCurves[curveIdx];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
void RiaCurveMerger<XValueType>::computeInterpolatedValues(bool includeValuesFromPartialCurves)
{
m_validIntervalsForAllXValues.clear();
m_allXValues.clear();
m_interpolatedValuesForAllCurves.clear();
computeUnionOfXValues(includeValuesFromPartialCurves);
const size_t curveCount = m_originalValues.size();
if (curveCount == 0)
{
return;
}
const size_t dataValueCount = m_allXValues.size();
if (dataValueCount == 0)
{
return;
}
m_interpolatedValuesForAllCurves.resize(curveCount);
std::vector<double> accumulatedValidValues(dataValueCount, 1.0);
for (size_t curveIdx = 0; curveIdx < curveCount; curveIdx++)
{
std::vector<double>& curveValues = m_interpolatedValuesForAllCurves[curveIdx];
curveValues.resize(dataValueCount);
for (size_t valueIndex = 0; valueIndex < dataValueCount; valueIndex++)
{
double interpolValue = interpolatedYValue(m_allXValues[valueIndex], m_originalValues[curveIdx].first, m_originalValues[curveIdx].second);
if (!RiaCurveDataTools::isValidValue(interpolValue, false))
{
accumulatedValidValues[valueIndex] = HUGE_VAL;
}
curveValues[valueIndex] = interpolValue;
}
}
m_validIntervalsForAllXValues = RiaCurveDataTools::calculateIntervalsOfValidValues(accumulatedValidValues, false);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
void RiaCurveMerger<XValueType>::computeUnionOfXValues(bool includeValuesForPartialCurves)
{
m_allXValues.clear();
std::set<XValueType, XComparator> unionOfXValues;
for (const auto& curveData : m_originalValues)
{
for (const auto& x : curveData.first)
{
unionOfXValues.insert(x);
}
}
if (!includeValuesForPartialCurves)
{
for (auto it = unionOfXValues.begin(); it != unionOfXValues.end();)
{
bool outsideBounds = false;
for (const auto& curveData : m_originalValues)
{
if (curveData.first.empty()) continue;
if (*it < curveData.first.front() || *it > curveData.first.back())
{
outsideBounds = true;
break;
}
}
if (outsideBounds)
{
it = unionOfXValues.erase(it);
}
else
{
++it;
}
}
}
m_allXValues = std::vector<XValueType>(unionOfXValues.begin(), unionOfXValues.end());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename XValueType>
double RiaCurveMerger<XValueType>::interpolatedYValue(const XValueType& interpolationXValue,
const std::vector<XValueType>& xValues,
const std::vector<double>& yValues)
{
if (yValues.size() != xValues.size()) return HUGE_VAL;
const bool removeInterpolatedValues = false;
for (size_t firstI = 0; firstI < xValues.size(); firstI++)
{
if (XComparator::equals(xValues.at(firstI), interpolationXValue))
{
const double& firstValue = yValues.at(firstI);
if (!RiaCurveDataTools::isValidValue(firstValue, removeInterpolatedValues))
{
return HUGE_VAL;
}
return firstValue;
}
size_t secondI = firstI + 1;
if (secondI < xValues.size())
{
if (XComparator::equals(xValues.at(secondI), interpolationXValue))
{
const double& secondValue = yValues.at(secondI);
if (!RiaCurveDataTools::isValidValue(secondValue, removeInterpolatedValues))
{
return HUGE_VAL;
}
return secondValue;
}
if (xValues.at(firstI) < interpolationXValue && xValues.at(secondI) > interpolationXValue)
{
const double& firstValue = yValues.at(firstI);
const double& secondValue = yValues.at(secondI);
bool isFirstValid = RiaCurveDataTools::isValidValue(firstValue, removeInterpolatedValues);
if (!isFirstValid) return HUGE_VAL;
bool isSecondValid = RiaCurveDataTools::isValidValue(secondValue, removeInterpolatedValues);
if (!isSecondValid) return HUGE_VAL;
double firstDiff = fabs(XComparator::diff(interpolationXValue, xValues.at(firstI)));
double secondDiff = fabs(XComparator::diff(xValues.at(secondI), interpolationXValue));
double firstWeight = secondDiff / (firstDiff + secondDiff);
double secondWeight = firstDiff / (firstDiff + secondDiff);
double val = (firstValue * firstWeight) + (secondValue * secondWeight);
CVF_ASSERT(RiaCurveDataTools::isValidValue(val, removeInterpolatedValues));
return val;
}
}
}
return HUGE_VAL;
}

View File

@@ -1,215 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaTimeHistoryCurveMerger.h"
#include <cmath> // Needed for HUGE_VAL on Linux
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaTimeHistoryCurveMerger::RiaTimeHistoryCurveMerger()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaTimeHistoryCurveMerger::addCurveData(const std::vector<double>& values, const std::vector<time_t>& timeSteps)
{
CVF_ASSERT(values.size() == timeSteps.size());
m_originalValues.push_back(std::make_pair(values, timeSteps));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaCurveDataTools::CurveIntervals RiaTimeHistoryCurveMerger::validIntervalsForAllTimeSteps() const
{
return m_validIntervalsForAllTimeSteps;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<time_t>& RiaTimeHistoryCurveMerger::allTimeSteps() const
{
return m_allTimeSteps;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<double>& RiaTimeHistoryCurveMerger::interpolatedCurveValuesForAllTimeSteps(size_t curveIdx) const
{
CVF_ASSERT(curveIdx < m_interpolatedValuesForAllCurves.size());
return m_interpolatedValuesForAllCurves[curveIdx];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<double>& RiaTimeHistoryCurveMerger::interpolatedCurveValuesForAllTimeSteps(size_t curveIdx)
{
CVF_ASSERT(curveIdx < m_interpolatedValuesForAllCurves.size());
return m_interpolatedValuesForAllCurves[curveIdx];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaTimeHistoryCurveMerger::computeInterpolatedValues()
{
m_validIntervalsForAllTimeSteps.clear();
m_allTimeSteps.clear();
m_interpolatedValuesForAllCurves.clear();
computeUnionOfTimeSteps();
const size_t curveCount = m_originalValues.size();
if (curveCount == 0)
{
return;
}
const size_t dataValueCount = m_allTimeSteps.size();
if (dataValueCount == 0)
{
return;
}
m_interpolatedValuesForAllCurves.resize(curveCount);
std::vector<double> accumulatedValidValues(dataValueCount, 1.0);
for (size_t curveIdx = 0; curveIdx < curveCount; curveIdx++)
{
std::vector<double>& curveValues = m_interpolatedValuesForAllCurves[curveIdx];
curveValues.resize(dataValueCount);
for (size_t valueIndex = 0; valueIndex < dataValueCount; valueIndex++)
{
double interpolValue = interpolationValue(m_allTimeSteps[valueIndex], m_originalValues[curveIdx].first, m_originalValues[curveIdx].second);
if (!RiaCurveDataTools::isValidValue(interpolValue, false))
{
accumulatedValidValues[valueIndex] = HUGE_VAL;
}
curveValues[valueIndex] = interpolValue;
}
}
m_validIntervalsForAllTimeSteps = RiaCurveDataTools::calculateIntervalsOfValidValues(accumulatedValidValues, false);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaTimeHistoryCurveMerger::computeUnionOfTimeSteps()
{
m_allTimeSteps.clear();
std::set<time_t> unionOfTimeSteps;
for (const auto& curveData : m_originalValues)
{
for (const auto& dt : curveData.second)
{
unionOfTimeSteps.insert(dt);
}
}
for (const auto& dt : unionOfTimeSteps)
{
m_allTimeSteps.push_back(dt);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RiaTimeHistoryCurveMerger::interpolationValue(const time_t& interpolationTimeStep,
const std::vector<double>& curveValues,
const std::vector<time_t>& curveTimeSteps)
{
if (curveValues.size() != curveTimeSteps.size()) return HUGE_VAL;
const bool removeInterpolatedValues = false;
for (size_t firstI = 0; firstI < curveTimeSteps.size(); firstI++)
{
if (curveTimeSteps.at(firstI) == interpolationTimeStep)
{
const double& firstValue = curveValues.at(firstI);
if (!RiaCurveDataTools::isValidValue(firstValue, removeInterpolatedValues))
{
return HUGE_VAL;
}
return firstValue;
}
size_t secondI = firstI + 1;
if (secondI < curveTimeSteps.size() &&
curveTimeSteps.at(firstI) <= interpolationTimeStep &&
curveTimeSteps.at(secondI) > interpolationTimeStep)
{
if (curveTimeSteps.at(secondI) == interpolationTimeStep)
{
const double& secondValue = curveValues.at(secondI);
if (!RiaCurveDataTools::isValidValue(secondValue, removeInterpolatedValues))
{
return HUGE_VAL;
}
return secondValue;
}
const double& firstValue = curveValues.at(firstI);
const double& secondValue = curveValues.at(secondI);
bool isFirstValid = RiaCurveDataTools::isValidValue(firstValue, removeInterpolatedValues);
if (!isFirstValid) return HUGE_VAL;
bool isSecondValid = RiaCurveDataTools::isValidValue(secondValue, removeInterpolatedValues);
if (!isSecondValid) return HUGE_VAL;
double firstDiff = fabs(difftime(interpolationTimeStep, curveTimeSteps.at(firstI)));
double secondDiff = fabs(difftime(curveTimeSteps.at(secondI), interpolationTimeStep));
double firstWeight = secondDiff / (firstDiff + secondDiff);
double secondWeight = firstDiff / (firstDiff + secondDiff);
double val = (firstValue * firstWeight) + (secondValue * secondWeight);
CVF_ASSERT(RiaCurveDataTools::isValidValue(val, removeInterpolatedValues));
return val;
}
}
return HUGE_VAL;
}

View File

@@ -1,68 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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 "RiaCurveDataTools.h"
#include <ctime>
//==================================================================================================
///
//==================================================================================================
class RiaTimeHistoryCurveMerger
{
public:
RiaTimeHistoryCurveMerger();
void addCurveData(const std::vector<double>& values,
const std::vector<time_t>& timeSteps);
void computeInterpolatedValues();
RiaCurveDataTools::CurveIntervals validIntervalsForAllTimeSteps() const;
const std::vector<time_t>& allTimeSteps() const;
const std::vector<double>& interpolatedCurveValuesForAllTimeSteps(size_t curveIdx) const;
// Non-const access is not required by any clients, but the expression parser has no available const interface
// for specifying a data source for an expression variable. Allow non-const access to avoid copy of the contained
// values, interpolated for all time steps
//
// See ExpressionParserImpl::assignVector()
std::vector<double>& interpolatedCurveValuesForAllTimeSteps(size_t curveIdx);
public:
// Helper methods, available as public to be able to access from unit tests
static double interpolationValue(const time_t& interpolationTimeStep,
const std::vector<double>& curveValues,
const std::vector<time_t>& curveTimeSteps);
private:
void computeUnionOfTimeSteps();
private:
std::vector<std::pair<std::vector<double>, std::vector<time_t>>> m_originalValues;
RiaCurveDataTools::CurveIntervals m_validIntervalsForAllTimeSteps;
std::vector<time_t> m_allTimeSteps;
std::vector<std::vector<double>> m_interpolatedValuesForAllCurves;
};

View File

@@ -41,6 +41,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicImportGeoMechCaseTimeStepFilterFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryCaseFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryCasesFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicImportObservedDataFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicImportFmuObservedDataFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicImportObservedDataInMenuFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicImportGeneralDataFeature.h
${CMAKE_CURRENT_LIST_DIR}/RicExportFeatureImpl.h
@@ -121,6 +122,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicImportGeoMechCaseTimeStepFilterFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryCaseFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicImportSummaryCasesFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicImportObservedDataFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicImportFmuObservedDataFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicImportObservedDataInMenuFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicImportGeneralDataFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/RicExportFeatureImpl.cpp

View File

@@ -234,7 +234,7 @@ void RicGridStatisticsDialog::createAndConnectToolbarActions()
//--------------------------------------------------------------------------------------------------
void RicGridStatisticsDialog::deletePlotItems(QwtPlot* plot)
{
auto itemList = plot->itemList();
QwtPlotItemList itemList = plot->itemList();
for (auto item : itemList)
{
if (dynamic_cast<QwtPlotMarker*>(item)

View File

@@ -0,0 +1,70 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RicImportFmuObservedDataFeature.h"
#include "RiaApplication.h"
#include "RifReaderFmuRft.h"
#include "RimObservedData.h"
#include "RimObservedDataCollection.h"
#include "RimProject.h"
#include "RiuPlotMainWindowTools.h"
#include "cafSelectionManager.h"
#include <QAction>
#include <QFileDialog>
#include <QMessageBox>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicImportFmuObservedDataFeature::selectObservedDataPathInDialog()
{
RiaApplication* app = RiaApplication::instance();
QString defaultDir = app->lastUsedDialogDirectory("SUMMARY_CASE_DIR");
QString directory = QFileDialog::getExistingDirectory(
nullptr, "Import Fmu Observed Data Recursively from Directory", defaultDir, QFileDialog::ShowDirsOnly);
QStringList subDirsWithFmuData = RifReaderFmuRft::findSubDirectoriesWithFmuRftData(directory);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicImportFmuObservedDataFeature::isCommandEnabled()
{
std::vector<RimObservedDataCollection*> selectionObservedDataCollection;
caf::SelectionManager::instance()->objectsByType(&selectionObservedDataCollection);
std::vector<RimObservedData*> selectionObservedData;
caf::SelectionManager::instance()->objectsByType(&selectionObservedData);
return (selectionObservedDataCollection.size() > 0 || selectionObservedData.size() > 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicImportFmuObservedDataFeature::onActionTriggered(bool isChecked) {}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicImportFmuObservedDataFeature::setupActionLook(QAction* actionToSetup) {}

View File

@@ -0,0 +1,40 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafCmdFeature.h"
#include "cafPdmField.h"
//==================================================================================================
//
//
//
//==================================================================================================
class RicImportFmuObservedDataFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
public:
static void selectObservedDataPathInDialog();
private:
bool isCommandEnabled() override;
void onActionTriggered(bool isChecked) override;
void setupActionLook(QAction* actionToSetup) override;
};

View File

@@ -37,13 +37,6 @@
CAF_CMD_SOURCE_INIT(RicImportObservedDataFeature, "RicImportObservedDataFeature");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RicImportObservedDataFeature::RicImportObservedDataFeature()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -32,7 +32,6 @@ class RicImportObservedDataFeature : public caf::CmdFeature
CAF_CMD_HEADER_INIT;
public:
RicImportObservedDataFeature();
static void selectObservedDataFileInDialog();
private:

View File

@@ -16,7 +16,9 @@ ${CMAKE_CURRENT_LIST_DIR}/RifColumnBasedUserDataParser.h
${CMAKE_CURRENT_LIST_DIR}/RifKeywordVectorParser.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderObservedData.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseSummary.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderRftInterface.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseRft.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderFmuRft.h
${CMAKE_CURRENT_LIST_DIR}/RifJsonEncodeDecode.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderInterface.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderMockModel.h
@@ -42,6 +44,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifSummaryCaseRestartSelector.h
${CMAKE_CURRENT_LIST_DIR}/RifCaseRealizationParametersReader.h
${CMAKE_CURRENT_LIST_DIR}/RifFileParseTools.h
${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.h
${CMAKE_CURRENT_LIST_DIR}/RifReaderEnsembleStatisticsRft.h
${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.h
${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader.h
${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter.h
@@ -68,7 +71,9 @@ ${CMAKE_CURRENT_LIST_DIR}/RifColumnBasedUserDataParser.cpp
${CMAKE_CURRENT_LIST_DIR}/RifKeywordVectorParser.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderObservedData.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseSummary.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderRftInterface.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderEclipseRft.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderFmuRft.cpp
${CMAKE_CURRENT_LIST_DIR}/RifJsonEncodeDecode.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderInterface.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderMockModel.cpp
@@ -95,6 +100,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RifEnsembleStatisticsReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifDerivedEnsembleReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifActiveCellsReader.cpp
${CMAKE_CURRENT_LIST_DIR}/RifCsvDataTableFormatter.cpp
${CMAKE_CURRENT_LIST_DIR}/RifReaderEnsembleStatisticsRft.cpp
# HDF5 file reader is directly included in ResInsight main CmakeList.txt
#${CMAKE_CURRENT_LIST_DIR}/RifHdf5Reader.cpp

View File

@@ -135,6 +135,14 @@ std::string RifColumnBasedUserData::unitName(const RifEclipseSummaryAddress& res
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RifColumnBasedUserData::unitSystem() const
{
return RiaEclipseUnitTools::UNITS_UNKNOWN;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -48,7 +48,8 @@ public:
bool values(const RifEclipseSummaryAddress& resultAddress,
std::vector<double>* values) const override;
std::string unitName(const RifEclipseSummaryAddress& resultAddress) const override;
std::string unitName(const RifEclipseSummaryAddress& resultAddress) const override;
RiaEclipseUnitTools::UnitSystem unitSystem() const override;
private:
void buildTimeStepsAndMappings();

View File

@@ -140,6 +140,14 @@ std::string RifCsvUserData::unitName(const RifEclipseSummaryAddress& resultAddre
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RifCsvUserData::unitSystem() const
{
return RiaEclipseUnitTools::UNITS_UNKNOWN;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -52,6 +52,9 @@ public:
std::string unitName(const RifEclipseSummaryAddress& resultAddress) const override;
RiaEclipseUnitTools::UnitSystem unitSystem() const override;
private:
void buildTimeStepsAndMappings();

View File

@@ -1,41 +1,43 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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>
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RifDataSourceForRftPlt.h"
#include "RimEclipseCase.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimWellLogFile.h"
#include "RimEclipseResultCase.h"
#include "cafAppEnum.h"
#include "cvfAssert.h"
#include <QString>
#include <QTextStream>
#include "RimEclipseResultCase.h"
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RifDataSourceForRftPlt::RifDataSourceForRftPlt() : m_sourceType(SourceType::NONE)
RifDataSourceForRftPlt::RifDataSourceForRftPlt()
: m_sourceType(SourceType::NONE)
{
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RifDataSourceForRftPlt::RifDataSourceForRftPlt(SourceType sourceType, RimEclipseCase* eclCase)
{
@@ -43,22 +45,47 @@ RifDataSourceForRftPlt::RifDataSourceForRftPlt(SourceType sourceType, RimEclipse
CVF_ASSERT(eclCase != nullptr);
m_sourceType = sourceType;
m_eclCase = eclCase;
m_eclCase = eclCase;
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RifDataSourceForRftPlt::RifDataSourceForRftPlt(SourceType sourceType, RimWellLogFile* wellLogFile)
{
CVF_ASSERT(sourceType == SourceType::OBSERVED);
m_sourceType = sourceType;
m_sourceType = sourceType;
m_wellLogFile = wellLogFile;
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RifDataSourceForRftPlt::RifDataSourceForRftPlt(SourceType sourceType, RimSummaryCaseCollection* ensemble)
{
CVF_ASSERT(sourceType == SourceType::ENSEMBLE_RFT);
m_sourceType = sourceType;
m_ensemble = ensemble;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifDataSourceForRftPlt::RifDataSourceForRftPlt(SourceType sourceType,
RimSummaryCase* summaryCase,
RimSummaryCaseCollection* ensemble)
{
CVF_ASSERT(sourceType == SourceType::SUMMARY_RFT);
m_sourceType = sourceType;
m_summaryCase = summaryCase;
m_ensemble = ensemble;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifDataSourceForRftPlt::SourceType RifDataSourceForRftPlt::sourceType() const
{
@@ -66,7 +93,7 @@ RifDataSourceForRftPlt::SourceType RifDataSourceForRftPlt::sourceType() const
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RimEclipseCase* RifDataSourceForRftPlt::eclCase() const
{
@@ -74,22 +101,45 @@ RimEclipseCase* RifDataSourceForRftPlt::eclCase() const
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RifReaderEclipseRft* RifDataSourceForRftPlt::rftReader() const
RifReaderRftInterface* RifDataSourceForRftPlt::rftReader() const
{
if (m_sourceType == RFT)
{
auto eclResCase = dynamic_cast<RimEclipseResultCase*>(m_eclCase.p());
if (eclResCase ) return eclResCase->rftReader();
if (eclResCase) return eclResCase->rftReader();
}
return nullptr;
else if (m_sourceType == SUMMARY_RFT)
{
if (m_summaryCase) return m_summaryCase->rftReader();
}
else if (m_sourceType == ENSEMBLE_RFT)
{
if (m_ensemble) return m_ensemble->rftStatisticsReader();
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RimSummaryCaseCollection* RifDataSourceForRftPlt::ensemble() const
{
return m_ensemble;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RifDataSourceForRftPlt::summaryCase() const
{
return m_summaryCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimWellLogFile* RifDataSourceForRftPlt::wellLogFile() const
{
@@ -97,33 +147,40 @@ RimWellLogFile* RifDataSourceForRftPlt::wellLogFile() const
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
QString RifDataSourceForRftPlt::sourceTypeUiText(SourceType sourceType)
{
switch (sourceType)
{
case SourceType::RFT: return QString("RFT File Cases");
case SourceType::GRID: return QString("Grid Cases");
case SourceType::OBSERVED: return QString("Observed Data");
case SourceType::RFT:
return QString("RFT File Cases");
case SourceType::GRID:
return QString("Grid Cases");
case SourceType::OBSERVED:
return QString("Observed Data");
case SourceType::ENSEMBLE_RFT:
return QString("Ensembles with RFT Data");
case SourceType::SUMMARY_RFT:
return QString("Summary case with RFT Data");
}
return QString();
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
bool operator==(const RifDataSourceForRftPlt& addr1, const RifDataSourceForRftPlt& addr2)
{
return addr1.sourceType() == addr2.sourceType()
&& addr1.eclCase() == addr2.eclCase()
&& addr1.wellLogFile() == addr2.wellLogFile();
return addr1.sourceType() == addr2.sourceType() && addr1.eclCase() == addr2.eclCase() &&
addr1.wellLogFile() == addr2.wellLogFile() && addr1.summaryCase() == addr2.summaryCase() &&
addr1.ensemble() == addr2.ensemble();
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
QTextStream& operator << (QTextStream& str, const RifDataSourceForRftPlt& addr)
QTextStream& operator<<(QTextStream& str, const RifDataSourceForRftPlt& addr)
{
// Not implemented
CVF_ASSERT(false);
@@ -131,9 +188,9 @@ QTextStream& operator << (QTextStream& str, const RifDataSourceForRftPlt& addr)
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
QTextStream& operator >> (QTextStream& str, RifDataSourceForRftPlt& source)
QTextStream& operator>>(QTextStream& str, RifDataSourceForRftPlt& source)
{
// Not implemented
CVF_ASSERT(false);
@@ -146,16 +203,16 @@ QTextStream& operator >> (QTextStream& str, RifDataSourceForRftPlt& source)
//--------------------------------------------------------------------------------------------------
bool operator<(const RifDataSourceForRftPlt& addr1, const RifDataSourceForRftPlt& addr2)
{
if ( addr1.m_sourceType != addr2.m_sourceType )
if (addr1.m_sourceType != addr2.m_sourceType)
{
return addr1.m_sourceType < addr2.m_sourceType;
}
if ( addr1.m_sourceType == RifDataSourceForRftPlt::NONE ) return false; //
if (addr1.m_sourceType == RifDataSourceForRftPlt::OBSERVED)
{
if(addr1.wellLogFile() && addr2.wellLogFile())
if (addr1.m_sourceType == RifDataSourceForRftPlt::NONE) return false; //
if (addr1.m_sourceType == RifDataSourceForRftPlt::OBSERVED)
{
if (addr1.wellLogFile() && addr2.wellLogFile())
{
return addr1.wellLogFile()->fileName() < addr2.wellLogFile()->fileName();
}
@@ -164,9 +221,31 @@ bool operator<(const RifDataSourceForRftPlt& addr1, const RifDataSourceForRftPlt
return addr1.wellLogFile() < addr2.wellLogFile();
}
}
else
else if (addr1.m_sourceType == RifDataSourceForRftPlt::SUMMARY_RFT)
{
if ( addr1.eclCase() && addr2.eclCase() )
if (addr1.summaryCase() && addr2.summaryCase())
{
return addr1.summaryCase()->caseName() < addr2.summaryCase()->caseName();
}
else
{
return addr1.summaryCase() < addr2.summaryCase();
}
}
else if (addr1.m_sourceType == RifDataSourceForRftPlt::ENSEMBLE_RFT)
{
if (addr1.ensemble() && addr2.ensemble())
{
return addr1.ensemble()->name() < addr2.ensemble()->name();
}
else
{
return addr1.ensemble() < addr2.ensemble();
}
}
else
{
if (addr1.eclCase() && addr2.eclCase())
{
return addr1.eclCase()->caseId() < addr2.eclCase()->caseId();
}

View File

@@ -32,7 +32,9 @@
class RimWellLogFile;
class RimEclipseCase;
class RifReaderEclipseRft;
class RifReaderRftInterface;
class RimSummaryCase;
class RimSummaryCaseCollection;
//==================================================================================================
///
@@ -46,16 +48,22 @@ public:
NONE,
OBSERVED,
RFT,
GRID
GRID,
ENSEMBLE_RFT,
SUMMARY_RFT
};
RifDataSourceForRftPlt();
RifDataSourceForRftPlt(SourceType sourceType, RimEclipseCase* eclCase);
RifDataSourceForRftPlt(SourceType sourceType, RimSummaryCaseCollection* ensemble);
RifDataSourceForRftPlt(SourceType sourceType, RimSummaryCase* summaryCase, RimSummaryCaseCollection* ensemble);
RifDataSourceForRftPlt(SourceType sourceType, RimWellLogFile* wellLogFile = nullptr);
SourceType sourceType() const;
RimEclipseCase* eclCase() const;
RifReaderEclipseRft* rftReader() const;
RifReaderRftInterface* rftReader() const;
RimSummaryCaseCollection* ensemble() const;
RimSummaryCase* summaryCase() const;
RimWellLogFile* wellLogFile() const;
static QString sourceTypeUiText(SourceType sourceType);
@@ -64,9 +72,11 @@ public:
friend bool operator<(const RifDataSourceForRftPlt& addr1, const RifDataSourceForRftPlt& addr2);
private:
SourceType m_sourceType;
caf::PdmPointer<RimEclipseCase> m_eclCase;
caf::PdmPointer<RimWellLogFile> m_wellLogFile;
SourceType m_sourceType;
caf::PdmPointer<RimEclipseCase> m_eclCase;
caf::PdmPointer<RimSummaryCase> m_summaryCase;
caf::PdmPointer<RimSummaryCaseCollection> m_ensemble;
caf::PdmPointer<RimWellLogFile> m_wellLogFile;
};
bool operator==(const RifDataSourceForRftPlt& addr1, const RifDataSourceForRftPlt& addr2);

View File

@@ -82,3 +82,11 @@ std::string RifDerivedEnsembleReader::unitName(const RifEclipseSummaryAddress& r
{
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RifDerivedEnsembleReader::unitSystem() const
{
return RiaEclipseUnitTools::UNITS_UNKNOWN;
}

View File

@@ -38,6 +38,7 @@ public:
const std::vector<time_t>& timeSteps(const RifEclipseSummaryAddress& resultAddress) const override;
bool values(const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values) const override;
std::string unitName(const RifEclipseSummaryAddress& resultAddress) const override;
RiaEclipseUnitTools::UnitSystem unitSystem() const override;
private:
RimDerivedEnsembleCase* m_derivedCase;

View File

@@ -36,14 +36,19 @@ public:
enum RftWellLogChannelType
{
NONE,
DEPTH,
TVD,
PRESSURE,
SWAT,
SOIL,
SGAS,
WRAT,
ORAT,
GRAT
GRAT,
MD,
PRESSURE_P10,
PRESSURE_P50,
PRESSURE_P90,
PRESSURE_MEAN
};
public:

View File

@@ -83,6 +83,14 @@ std::string RifEnsembleStatisticsReader::unitName(const RifEclipseSummaryAddress
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RifEnsembleStatisticsReader::unitSystem() const
{
return m_ensembleStatCase->unitSystem();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -37,6 +37,9 @@ public:
bool values(const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values) const override;
std::string unitName(const RifEclipseSummaryAddress& resultAddress) const override;
RiaEclipseUnitTools::UnitSystem unitSystem() const override;
private:
bool validateAddress(const RifEclipseSummaryAddress& address) const;

View File

@@ -231,6 +231,14 @@ std::string RifKeywordVectorUserData::unitName(const RifEclipseSummaryAddress& r
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RifKeywordVectorUserData::unitSystem() const
{
return RiaEclipseUnitTools::UNITS_UNKNOWN;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -49,7 +49,8 @@ public:
bool values(const RifEclipseSummaryAddress& resultAddress,
std::vector<double>* values) const override;
std::string unitName(const RifEclipseSummaryAddress& resultAddress) const override;
std::string unitName(const RifEclipseSummaryAddress& resultAddress) const override;
RiaEclipseUnitTools::UnitSystem unitSystem() const override;
private:
static bool isTimeHeader(const std::map<QString, QString>& header);

View File

@@ -81,39 +81,39 @@ void RifReaderEclipseRft::open()
timeStep.setTime_t(timeStepTime_t);
RifEclipseRftAddress addressPressure(wellName, timeStep, RifEclipseRftAddress::PRESSURE);
m_eclipseRftAddresses.push_back(addressPressure);
m_eclipseRftAddresses.insert(addressPressure);
m_rftAddressToLibeclNodeIdx[addressPressure] = i;
RifEclipseRftAddress addressDepth(wellName, timeStep, RifEclipseRftAddress::DEPTH);
m_eclipseRftAddresses.push_back(addressDepth);
RifEclipseRftAddress addressDepth(wellName, timeStep, RifEclipseRftAddress::TVD);
m_eclipseRftAddresses.insert(addressDepth);
m_rftAddressToLibeclNodeIdx[addressDepth] = i;
if (ecl_rft_node_is_RFT(node))
{
RifEclipseRftAddress addressSwat(wellName, timeStep, RifEclipseRftAddress::SWAT);
m_eclipseRftAddresses.push_back(addressSwat);
m_eclipseRftAddresses.insert(addressSwat);
m_rftAddressToLibeclNodeIdx[addressSwat] = i;
RifEclipseRftAddress addressSoil(wellName, timeStep, RifEclipseRftAddress::SOIL);
m_eclipseRftAddresses.push_back(addressSoil);
m_eclipseRftAddresses.insert(addressSoil);
m_rftAddressToLibeclNodeIdx[addressSoil] = i;
RifEclipseRftAddress addressSgas(wellName, timeStep, RifEclipseRftAddress::SGAS);
m_eclipseRftAddresses.push_back(addressSgas);
m_eclipseRftAddresses.insert(addressSgas);
m_rftAddressToLibeclNodeIdx[addressSgas] = i;
}
else if (ecl_rft_node_is_PLT(node))
{
RifEclipseRftAddress addressWrat(wellName, timeStep, RifEclipseRftAddress::WRAT);
m_eclipseRftAddresses.push_back(addressWrat);
m_eclipseRftAddresses.insert(addressWrat);
m_rftAddressToLibeclNodeIdx[addressWrat] = i;
RifEclipseRftAddress addressOrat(wellName, timeStep, RifEclipseRftAddress::ORAT);
m_eclipseRftAddresses.push_back(addressOrat);
m_eclipseRftAddresses.insert(addressOrat);
m_rftAddressToLibeclNodeIdx[addressOrat] = i;
RifEclipseRftAddress addressGrat(wellName, timeStep, RifEclipseRftAddress::GRAT);
m_eclipseRftAddresses.push_back(addressGrat);
m_eclipseRftAddresses.insert(addressGrat);
m_rftAddressToLibeclNodeIdx[addressGrat] = i;
}
}
@@ -124,7 +124,7 @@ void RifReaderEclipseRft::open()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::vector<RifEclipseRftAddress>& RifReaderEclipseRft::eclipseRftAddresses()
std::set<RifEclipseRftAddress> RifReaderEclipseRft::eclipseRftAddresses()
{
if (!m_ecl_rft_file)
{
@@ -157,7 +157,7 @@ void RifReaderEclipseRft::values(const RifEclipseRftAddress& rftAddress, std::ve
switch (wellLogChannelName)
{
case RifEclipseRftAddress::DEPTH:
case RifEclipseRftAddress::TVD:
{
for (int i = 0; i < ecl_rft_node_get_size(node); i++)
{
@@ -258,14 +258,14 @@ void RifReaderEclipseRft::cellIndices(const RifEclipseRftAddress& rftAddress, st
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<QDateTime> RifReaderEclipseRft::availableTimeSteps(const QString& wellName, const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName)
std::set<QDateTime> RifReaderEclipseRft::availableTimeSteps(const QString& wellName, const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName)
{
if (!m_ecl_rft_file)
{
open();
}
std::vector<QDateTime> timeSteps;
std::set<QDateTime> timeSteps;
if (wellName == "") return timeSteps;
@@ -273,7 +273,7 @@ std::vector<QDateTime> RifReaderEclipseRft::availableTimeSteps(const QString& we
{
if (address.wellName() == wellName && address.wellLogChannel() == wellLogChannelName)
{
timeSteps.push_back(address.timeStep());
timeSteps.insert(address.timeStep());
}
}
return timeSteps;
@@ -303,17 +303,26 @@ std::set<QDateTime> RifReaderEclipseRft::availableTimeSteps(const QString& wellN
return timeSteps;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QDateTime> RifReaderEclipseRft::availableTimeSteps(const QString& wellName)
{
auto wellLogChannels = availableWellLogChannels(wellName);
return availableTimeSteps(wellName, wellLogChannels);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RifEclipseRftAddress::RftWellLogChannelType> RifReaderEclipseRft::availableWellLogChannels(const QString& wellName)
std::set<RifEclipseRftAddress::RftWellLogChannelType> RifReaderEclipseRft::availableWellLogChannels(const QString& wellName)
{
if (!m_ecl_rft_file)
{
open();
}
std::vector<RifEclipseRftAddress::RftWellLogChannelType> wellLogChannelNames;
std::set<RifEclipseRftAddress::RftWellLogChannelType> wellLogChannelNames;
if (wellName == "") return wellLogChannelNames;
@@ -359,19 +368,19 @@ std::vector<RifEclipseRftAddress::RftWellLogChannelType> RifReaderEclipseRft::av
if (pressureFound)
{
wellLogChannelNames.push_back(RifEclipseRftAddress::PRESSURE);
wellLogChannelNames.insert(RifEclipseRftAddress::PRESSURE);
}
if (rftFound)
{
wellLogChannelNames.push_back(RifEclipseRftAddress::RftWellLogChannelType::SWAT);
wellLogChannelNames.push_back(RifEclipseRftAddress::RftWellLogChannelType::SOIL);
wellLogChannelNames.push_back(RifEclipseRftAddress::RftWellLogChannelType::SGAS);
wellLogChannelNames.insert(RifEclipseRftAddress::RftWellLogChannelType::SWAT);
wellLogChannelNames.insert(RifEclipseRftAddress::RftWellLogChannelType::SOIL);
wellLogChannelNames.insert(RifEclipseRftAddress::RftWellLogChannelType::SGAS);
}
if (pltFound)
{
wellLogChannelNames.push_back(RifEclipseRftAddress::RftWellLogChannelType::WRAT);
wellLogChannelNames.push_back(RifEclipseRftAddress::RftWellLogChannelType::ORAT);
wellLogChannelNames.push_back(RifEclipseRftAddress::RftWellLogChannelType::GRAT);
wellLogChannelNames.insert(RifEclipseRftAddress::RftWellLogChannelType::WRAT);
wellLogChannelNames.insert(RifEclipseRftAddress::RftWellLogChannelType::ORAT);
wellLogChannelNames.insert(RifEclipseRftAddress::RftWellLogChannelType::GRAT);
}
return wellLogChannelNames;
@@ -380,7 +389,7 @@ std::vector<RifEclipseRftAddress::RftWellLogChannelType> RifReaderEclipseRft::av
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const std::set<QString>& RifReaderEclipseRft::wellNames()
std::set<QString> RifReaderEclipseRft::wellNames()
{
if (!m_ecl_rft_file)
{

View File

@@ -18,7 +18,7 @@
#pragma once
#include "RifEclipseRftAddress.h"
#include "RifReaderRftInterface.h"
#include <map>
#include <string>
@@ -38,26 +38,27 @@ namespace caf
//
//
//==================================================================================================
class RifReaderEclipseRft : public cvf::Object
class RifReaderEclipseRft : public RifReaderRftInterface, public cvf::Object
{
public:
RifReaderEclipseRft(const QString& fileName);
~RifReaderEclipseRft() override;
const std::vector<RifEclipseRftAddress>& eclipseRftAddresses();
void values(const RifEclipseRftAddress& rftAddress, std::vector<double>* values);
void cellIndices(const RifEclipseRftAddress& rftAddress, std::vector<caf::VecIjk>* indices);
std::set<RifEclipseRftAddress> eclipseRftAddresses() override;
void values(const RifEclipseRftAddress& rftAddress, std::vector<double>* values) override;
void cellIndices(const RifEclipseRftAddress& rftAddress, std::vector<caf::VecIjk>* indices);
std::set<QDateTime> availableTimeSteps(const QString& wellName, const std::set<RifEclipseRftAddress::RftWellLogChannelType> relevantChannels);
std::set<QDateTime> availableTimeSteps(const QString& wellName) override;
std::set<QDateTime> availableTimeSteps(const QString& wellName, const std::set<RifEclipseRftAddress::RftWellLogChannelType> relevantChannels) override;
std::vector<QDateTime> availableTimeSteps(const QString& wellName, const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName);
std::vector<RifEclipseRftAddress::RftWellLogChannelType> availableWellLogChannels(const QString& wellName);
const std::set<QString>& wellNames();
bool wellHasRftData(QString wellName);
std::set<QDateTime> availableTimeSteps(const QString& wellName, const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName) override;
std::set<RifEclipseRftAddress::RftWellLogChannelType> availableWellLogChannels(const QString& wellName) override;
std::set<QString> wellNames() override;
bool wellHasRftData(QString wellName);
private:
void open();
int indexFromAddress(const RifEclipseRftAddress& rftAddress) const;
void open();
int indexFromAddress(const RifEclipseRftAddress& rftAddress) const;
private:
// Taken from ecl_rft_file.h and ecl_rft_node.h
@@ -65,7 +66,7 @@ private:
QString m_fileName;
ecl_rft_file_type* m_ecl_rft_file;
std::vector<RifEclipseRftAddress> m_eclipseRftAddresses;
std::set<RifEclipseRftAddress> m_eclipseRftAddresses;
std::set<QString> m_wellNames;
std::map<RifEclipseRftAddress, int> m_rftAddressToLibeclNodeIdx;
};

View File

@@ -57,6 +57,22 @@ std::vector<time_t> getTimeSteps(ecl_sum_type* ecl_sum)
return timeSteps;
}
RiaEclipseUnitTools::UnitSystem readUnitSystem(ecl_sum_type* ecl_sum)
{
ert_ecl_unit_enum eclUnitEnum = ecl_sum_get_unit_system(ecl_sum);
switch (eclUnitEnum)
{
case ECL_METRIC_UNITS:
return RiaEclipseUnitTools::UNITS_METRIC;
case ECL_FIELD_UNITS:
return RiaEclipseUnitTools::UNITS_FIELD;
case ECL_LAB_UNITS:
return RiaEclipseUnitTools::UNITS_LAB;
default:
return RiaEclipseUnitTools::UNITS_UNKNOWN;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -105,6 +121,7 @@ void closeEclSum(ecl_sum_type* ecl_sum)
RifReaderEclipseSummary::RifReaderEclipseSummary()
: m_ecl_sum(nullptr)
, m_ecl_SmSpec(nullptr)
, m_unitSystem(RiaEclipseUnitTools::UNITS_METRIC)
{
m_valuesCache.reset(new ValuesCache());
}
@@ -135,7 +152,7 @@ bool RifReaderEclipseSummary::open(const QString& headerFileName, bool includeRe
m_timeSteps.clear();
m_ecl_SmSpec = ecl_sum_get_smspec(m_ecl_sum);
m_timeSteps = getTimeSteps(m_ecl_sum);
m_unitSystem = readUnitSystem(m_ecl_sum);
buildMetaData();
return true;
@@ -515,6 +532,14 @@ std::string RifReaderEclipseSummary::unitName(const RifEclipseSummaryAddress& re
return ertSumVarNode.get_unit();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RifReaderEclipseSummary::unitSystem() const
{
return m_unitSystem;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -18,6 +18,7 @@
#pragma once
#include "RiaEclipseUnitTools.h"
#include "RifEclipseSummaryAddress.h"
#include "RifSummaryReaderInterface.h"
@@ -67,7 +68,7 @@ public:
bool values(const RifEclipseSummaryAddress& resultAddress, std::vector<double>* values) const override;
std::string unitName(const RifEclipseSummaryAddress& resultAddress) const override;
RiaEclipseUnitTools::UnitSystem unitSystem() const override;
QStringList warnings() const { return m_warnings; }
void markForCachePurge(const RifEclipseSummaryAddress& address) override;
@@ -88,6 +89,8 @@ private:
const ecl_smspec_type * m_ecl_SmSpec;
std::vector<time_t> m_timeSteps;
RiaEclipseUnitTools::UnitSystem m_unitSystem;
std::map<RifEclipseSummaryAddress, int> m_resultAddressToErtNodeIdx;
QStringList m_warnings;

View File

@@ -0,0 +1,258 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RifReaderEnsembleStatisticsRft.h"
#include "RiaCurveMerger.h"
#include "RigStatisticsMath.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "cafAssert.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderEnsembleStatisticsRft::RifReaderEnsembleStatisticsRft(const RimSummaryCaseCollection* summaryCaseCollection)
: m_summaryCaseCollection(summaryCaseCollection)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseRftAddress> RifReaderEnsembleStatisticsRft::eclipseRftAddresses()
{
std::set<RifEclipseRftAddress> allAddresses;
for (auto summaryCase : m_summaryCaseCollection->allSummaryCases())
{
if (summaryCase->rftReader())
{
std::set<RifEclipseRftAddress> addresses = summaryCase->rftReader()->eclipseRftAddresses();
allAddresses.insert(addresses.begin(), addresses.end());
}
}
std::set<RifEclipseRftAddress> statisticsAddresses;
for (const RifEclipseRftAddress& regularAddress : allAddresses)
{
if (regularAddress.wellLogChannel() == RifEclipseRftAddress::TVD)
{
statisticsAddresses.insert(regularAddress);
}
else if (regularAddress.wellLogChannel() == RifEclipseRftAddress::PRESSURE)
{
std::set<RifEclipseRftAddress::RftWellLogChannelType> statChannels = {RifEclipseRftAddress::PRESSURE_P10,
RifEclipseRftAddress::PRESSURE_P50,
RifEclipseRftAddress::PRESSURE_P90,
RifEclipseRftAddress::PRESSURE_MEAN};
for (auto channel : statChannels)
{
statisticsAddresses.insert(RifEclipseRftAddress(regularAddress.wellName(), regularAddress.timeStep(), channel));
}
}
}
return statisticsAddresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderEnsembleStatisticsRft::values(const RifEclipseRftAddress& rftAddress, std::vector<double>* values)
{
CAF_ASSERT(rftAddress.wellLogChannel() == RifEclipseRftAddress::TVD ||
rftAddress.wellLogChannel() == RifEclipseRftAddress::PRESSURE_MEAN ||
rftAddress.wellLogChannel() == RifEclipseRftAddress::PRESSURE_P10 ||
rftAddress.wellLogChannel() == RifEclipseRftAddress::PRESSURE_P50 ||
rftAddress.wellLogChannel() == RifEclipseRftAddress::PRESSURE_P90);
auto it = m_cachedValues.find(rftAddress);
if (it == m_cachedValues.end())
{
calculateStatistics(rftAddress);
}
*values = m_cachedValues[rftAddress];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QDateTime> RifReaderEnsembleStatisticsRft::availableTimeSteps(const QString& wellName)
{
std::set<QDateTime> allTimeSteps;
for (auto summaryCase : m_summaryCaseCollection->allSummaryCases())
{
if (summaryCase->rftReader())
{
std::set<QDateTime> timeSteps = summaryCase->rftReader()->availableTimeSteps(wellName);
allTimeSteps.insert(timeSteps.begin(), timeSteps.end());
}
}
return allTimeSteps;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QDateTime>
RifReaderEnsembleStatisticsRft::availableTimeSteps(const QString& wellName,
const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName)
{
std::set<QDateTime> allTimeSteps;
for (auto summaryCase : m_summaryCaseCollection->allSummaryCases())
{
if (summaryCase->rftReader())
{
std::set<QDateTime> timeSteps = summaryCase->rftReader()->availableTimeSteps(wellName, wellLogChannelName);
allTimeSteps.insert(timeSteps.begin(), timeSteps.end());
}
}
return allTimeSteps;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QDateTime> RifReaderEnsembleStatisticsRft::availableTimeSteps(
const QString& wellName,
const std::set<RifEclipseRftAddress::RftWellLogChannelType> relevantChannels)
{
std::set<QDateTime> allTimeSteps;
for (auto summaryCase : m_summaryCaseCollection->allSummaryCases())
{
if (summaryCase->rftReader())
{
std::set<QDateTime> timeSteps = summaryCase->rftReader()->availableTimeSteps(wellName, relevantChannels);
allTimeSteps.insert(timeSteps.begin(), timeSteps.end());
}
}
return allTimeSteps;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseRftAddress::RftWellLogChannelType>
RifReaderEnsembleStatisticsRft::availableWellLogChannels(const QString& wellName)
{
std::set<RifEclipseRftAddress::RftWellLogChannelType> allWellLogChannels;
for (auto summaryCase : m_summaryCaseCollection->allSummaryCases())
{
if (summaryCase->rftReader())
{
std::set<RifEclipseRftAddress::RftWellLogChannelType> wellLogChannels =
summaryCase->rftReader()->availableWellLogChannels(wellName);
allWellLogChannels.insert(wellLogChannels.begin(), wellLogChannels.end());
}
}
return allWellLogChannels;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QString> RifReaderEnsembleStatisticsRft::wellNames()
{
std::set<QString> allWellNames;
for (auto summaryCase : m_summaryCaseCollection->allSummaryCases())
{
if (summaryCase->rftReader())
{
std::set<QString> wellNames = summaryCase->rftReader()->wellNames();
allWellNames.insert(wellNames.begin(), wellNames.end());
}
}
return allWellNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderEnsembleStatisticsRft::calculateStatistics(const RifEclipseRftAddress& rftAddress)
{
const QString& wellName = rftAddress.wellName();
const QDateTime& timeStep = rftAddress.timeStep();
RifEclipseRftAddress depthAddress(wellName, timeStep, RifEclipseRftAddress::TVD);
RifEclipseRftAddress pressAddress(wellName, timeStep, RifEclipseRftAddress::PRESSURE);
RifEclipseRftAddress p10Address(wellName, timeStep, RifEclipseRftAddress::PRESSURE_P10);
RifEclipseRftAddress p50Address(wellName, timeStep, RifEclipseRftAddress::PRESSURE_P50);
RifEclipseRftAddress p90Address(wellName, timeStep, RifEclipseRftAddress::PRESSURE_P90);
RifEclipseRftAddress meanAddress(wellName, timeStep, RifEclipseRftAddress::PRESSURE_MEAN);
RiaCurveMerger<double> curveMerger;
for (RimSummaryCase* summaryCase : m_summaryCaseCollection->allSummaryCases())
{
RifReaderRftInterface* reader = summaryCase->rftReader();
if (reader)
{
std::vector<double> depths;
std::vector<double> pressures;
reader->values(depthAddress, &depths);
reader->values(pressAddress, &pressures);
curveMerger.addCurveData(depths, pressures);
}
}
curveMerger.computeInterpolatedValues(false);
clearData(wellName, timeStep);
const std::vector<double>& allDepths = curveMerger.allXValues();
if (!allDepths.empty())
{
m_cachedValues[depthAddress] = allDepths;
for (size_t depthIdx = 0; depthIdx < allDepths.size(); ++depthIdx)
{
std::vector<double> pressuresAtDepth;
pressuresAtDepth.reserve(curveMerger.curveCount());
for (size_t curveIdx = 0; curveIdx < curveMerger.curveCount(); ++curveIdx)
{
const std::vector<double>& curvePressures = curveMerger.interpolatedYValuesForAllXValues(curveIdx);
pressuresAtDepth.push_back(curvePressures[depthIdx]);
}
double p10, p50, p90, mean;
RigStatisticsMath::calculateStatisticsCurves(pressuresAtDepth, &p10, &p50, &p90, &mean);
if (p10 != HUGE_VAL) m_cachedValues[p10Address].push_back(p10);
if (p50 != HUGE_VAL) m_cachedValues[p50Address].push_back(p50);
if (p90 != HUGE_VAL) m_cachedValues[p90Address].push_back(p90);
m_cachedValues[meanAddress].push_back(mean);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderEnsembleStatisticsRft::clearData(const QString& wellName, const QDateTime& timeStep)
{
for (auto it = m_cachedValues.begin(); it != m_cachedValues.end(); )
{
if (it->first.wellName() == wellName && it->first.timeStep() == timeStep)
{
it = m_cachedValues.erase(it);
}
else
{
++it;
}
}
}

View File

@@ -0,0 +1,51 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RifReaderEclipseRft.h"
#include "cvfObject.h"
class RimSummaryCaseCollection;
class RifReaderEnsembleStatisticsRft : public RifReaderRftInterface, public cvf::Object
{
public:
RifReaderEnsembleStatisticsRft(const RimSummaryCaseCollection* summaryCaseCollection);
std::set<RifEclipseRftAddress> eclipseRftAddresses() override;
void values(const RifEclipseRftAddress& rftAddress, std::vector<double>* values) override;
std::set<QDateTime> availableTimeSteps(const QString& wellName) override;
std::set<QDateTime> availableTimeSteps(const QString& wellName,
const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName) override;
std::set<QDateTime> availableTimeSteps(const QString& wellName,
const std::set<RifEclipseRftAddress::RftWellLogChannelType> relevantChannels) override;
std::set<RifEclipseRftAddress::RftWellLogChannelType> availableWellLogChannels(const QString& wellName) override;
std::set<QString> wellNames() override;
private:
void calculateStatistics(const RifEclipseRftAddress& rftAddress);
void clearData(const QString& wellName, const QDateTime& timeStep);
private:
const RimSummaryCaseCollection* m_summaryCaseCollection;
std::map<RifEclipseRftAddress, std::vector<double>> m_cachedValues;
};

View File

@@ -0,0 +1,506 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RifReaderFmuRft.h"
#include "RiaLogging.h"
#include "cafAssert.h"
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QTextStream>
#include <limits>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderFmuRft::Observation::Observation()
: utmx(-std::numeric_limits<double>::infinity())
, utmy(-std::numeric_limits<double>::infinity())
, mdrkb(-std::numeric_limits<double>::infinity())
, tvdmsl(-std::numeric_limits<double>::infinity())
, pressure(-std::numeric_limits<double>::infinity())
, pressureError(-std::numeric_limits<double>::infinity())
, formation()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifReaderFmuRft::Observation::valid() const
{
return utmx != std::numeric_limits<double>::infinity() && utmy != std::numeric_limits<double>::infinity() &&
mdrkb != std::numeric_limits<double>::infinity() && tvdmsl != std::numeric_limits<double>::infinity() &&
pressure != std::numeric_limits<double>::infinity() && pressureError != std::numeric_limits<double>::infinity();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderFmuRft::WellObservationSet::WellObservationSet(const QDateTime& dateTime, int measurementIndex)
: dateTime(dateTime)
, measurementIndex(measurementIndex)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderFmuRft::RifReaderFmuRft(const QString& filePath)
: m_filePath(filePath)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList RifReaderFmuRft::findSubDirectoriesWithFmuRftData(const QString& filePath)
{
QStringList subDirsContainingFmuRftData;
QFileInfo fileInfo(filePath);
if (!(fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable()))
{
return subDirsContainingFmuRftData;
}
if (directoryContainsFmuRftData(filePath))
{
subDirsContainingFmuRftData.push_back(filePath);
}
QDir dir(filePath);
QStringList subDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Readable, QDir::Name);
for (QString subDir : subDirs)
{
QString absDir = dir.absoluteFilePath(subDir);
subDirsContainingFmuRftData.append(findSubDirectoriesWithFmuRftData(absDir));
}
return subDirsContainingFmuRftData;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifReaderFmuRft::directoryContainsFmuRftData(const QString& filePath)
{
QFileInfo baseFileInfo(filePath);
if (!(baseFileInfo.exists() && baseFileInfo.isDir() && baseFileInfo.isReadable()))
{
return false;
}
QDir dir(filePath);
if (!dir.exists("well_date_rft.txt"))
{
return false;
}
QStringList obsFiles;
obsFiles << "*.obs"
<< "*.txt";
QFileInfoList fileInfos = dir.entryInfoList(obsFiles, QDir::Files, QDir::Name);
std::map<QString, int> fileStemCounts;
for (QFileInfo fileInfo : fileInfos)
{
// TODO:
// Uses completeBaseName() to support wells with a dot in the name.
// Not sure if this is necessary or desired
fileStemCounts[fileInfo.completeBaseName()]++;
if (fileStemCounts[fileInfo.completeBaseName()] == 2)
{
// At least one matching obs and txt file.
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseRftAddress> RifReaderFmuRft::eclipseRftAddresses()
{
if (m_allWellObservations.empty())
{
load();
}
std::set<RifEclipseRftAddress> allAddresses;
for (const WellObservationPair& wellObservationPair : m_allWellObservations)
{
const QString& wellName = wellObservationPair.first;
const QDateTime& dateTime = wellObservationPair.second.dateTime;
const std::vector<Observation>& observations = wellObservationPair.second.observations;
for (const Observation& observation : observations)
{
if (observation.valid())
{
RifEclipseRftAddress tvdAddress(wellName, dateTime, RifEclipseRftAddress::TVD);
RifEclipseRftAddress mdAddress(wellName, dateTime, RifEclipseRftAddress::MD);
RifEclipseRftAddress pressureAddress(wellName, dateTime, RifEclipseRftAddress::PRESSURE);
allAddresses.insert(tvdAddress);
allAddresses.insert(mdAddress);
allAddresses.insert(pressureAddress);
}
}
}
return allAddresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderFmuRft::values(const RifEclipseRftAddress& rftAddress, std::vector<double>* values)
{
CAF_ASSERT(values);
if (m_allWellObservations.empty())
{
load();
}
auto it = m_allWellObservations.find(rftAddress.wellName());
if (it != m_allWellObservations.end())
{
const std::vector<Observation>& observations = it->second.observations;
values->clear();
values->reserve(observations.size());
for (const Observation& observation : observations)
{
switch (rftAddress.wellLogChannel())
{
case RifEclipseRftAddress::TVD:
values->push_back(observation.tvdmsl);
break;
case RifEclipseRftAddress::MD:
values->push_back(observation.mdrkb);
break;
case RifEclipseRftAddress::PRESSURE:
values->push_back(observation.pressure);
break;
default:
CAF_ASSERT(false && "Wrong channel type sent to Fmu RFT reader");
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifReaderFmuRft::load()
{
QString errorMsg;
QFileInfo fileInfo(m_filePath);
if (!(fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable()))
{
errorMsg = QString("Directory '%s' does not exist or isn't readable").arg(m_filePath);
RiaLogging::error(errorMsg);
return;
}
QDir dir(m_filePath);
WellObservationMap wellObservations = loadWellDates(dir, &errorMsg);
if (wellObservations.empty())
{
if (errorMsg.isEmpty())
{
errorMsg = QString("'%1' contains no valid FMU RFT data").arg(m_filePath);
}
RiaLogging::error(errorMsg);
return;
}
for (auto it = wellObservations.begin(); it != wellObservations.end(); ++it)
{
const QString& wellName = it->first;
WellObservationSet& wellObservationSet = it->second;
QString txtFile = QString("%1.txt").arg(wellName);
QString obsFile = QString("%1.obs").arg(wellName);
QFileInfo txtFileInfo(dir.absoluteFilePath(txtFile));
QFileInfo obsFileInfo(dir.absoluteFilePath(obsFile));
if (!readTxtFile(txtFile, &errorMsg, &wellObservationSet))
{
RiaLogging::error(errorMsg);
return;
}
if (!readObsFile(obsFile, &errorMsg, &wellObservationSet))
{
RiaLogging::error(errorMsg);
return;
}
}
m_allWellObservations.swap(wellObservations);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QDateTime> RifReaderFmuRft::availableTimeSteps(const QString& wellName,
const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName)
{
if (wellLogChannelName == RifEclipseRftAddress::TVD || wellLogChannelName == RifEclipseRftAddress::MD ||
wellLogChannelName == RifEclipseRftAddress::PRESSURE)
{
return availableTimeSteps(wellName);
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QDateTime> RifReaderFmuRft::availableTimeSteps(const QString& wellName)
{
if (m_allWellObservations.empty())
{
load();
}
auto it = m_allWellObservations.find(wellName);
if (it != m_allWellObservations.end())
{
return {it->second.dateTime};
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QDateTime>
RifReaderFmuRft::availableTimeSteps(const QString& wellName,
const std::set<RifEclipseRftAddress::RftWellLogChannelType> relevantChannels)
{
if (relevantChannels.count(RifEclipseRftAddress::TVD) || relevantChannels.count(RifEclipseRftAddress::MD) ||
relevantChannels.count(RifEclipseRftAddress::PRESSURE))
{
return availableTimeSteps(wellName);
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseRftAddress::RftWellLogChannelType> RifReaderFmuRft::availableWellLogChannels(const QString& wellName)
{
if (m_allWellObservations.empty())
{
load();
}
if (!m_allWellObservations.empty())
{
return {RifEclipseRftAddress::TVD, RifEclipseRftAddress::MD, RifEclipseRftAddress::PRESSURE};
}
return {};
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QString> RifReaderFmuRft::wellNames()
{
if (m_allWellObservations.empty())
{
load();
}
std::set<QString> wellNames;
for (auto it = m_allWellObservations.begin(); it != m_allWellObservations.end(); ++it)
{
wellNames.insert(it->first);
}
return wellNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderFmuRft::WellObservationMap RifReaderFmuRft::loadWellDates(QDir& dir, QString* errorMsg)
{
CAF_ASSERT(errorMsg);
WellObservationMap validObservations;
QFileInfo wellDateFileInfo(dir.absoluteFilePath("well_date_rft.txt"));
if (!(wellDateFileInfo.exists() && wellDateFileInfo.isFile() && wellDateFileInfo.isReadable()))
{
*errorMsg = QString("well_date_rft.txt cannot be found at '%s'").arg(m_filePath);
return WellObservationMap();
}
{
QFile wellDateFile(wellDateFileInfo.absoluteFilePath());
if (!wellDateFile.open(QIODevice::Text | QIODevice::ReadOnly))
{
*errorMsg = QString("Could not read '%1'").arg(wellDateFileInfo.absoluteFilePath());
return WellObservationMap();
}
QTextStream fileStream(&wellDateFile);
while (true)
{
QString line = fileStream.readLine();
if (line.isNull())
{
break;
}
else
{
QTextStream lineStream(&line);
QString wellName;
int day, month, year, measurementIndex;
lineStream >> wellName >> day >> month >> year >> measurementIndex;
if (lineStream.status() != QTextStream::Ok)
{
*errorMsg = QString("Failed to parse '%1'").arg(wellDateFileInfo.absoluteFilePath());
return WellObservationMap();
}
QDateTime dateTime(QDate(year, month, day));
WellObservationSet observationSet(dateTime, measurementIndex);
validObservations.insert(std::make_pair(wellName, observationSet));
}
}
}
return validObservations;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifReaderFmuRft::readTxtFile(const QString& fileName, QString* errorMsg, WellObservationSet* wellObservationSet)
{
CAF_ASSERT(wellObservationSet);
QFile file(fileName);
if (!(file.open(QIODevice::Text | QIODevice::ReadOnly)))
{
*errorMsg = QString("Could not open '%1'").arg(fileName);
return false;
}
QTextStream stream(&file);
while (true)
{
QString line = stream.readLine();
if (line.isNull())
{
break;
}
else
{
QTextStream lineStream(&line);
double utmx, utmy, mdrkb, tvdmsl;
QString formationName;
lineStream >> utmx >> utmy >> mdrkb >> tvdmsl >> formationName;
if (lineStream.status() != QTextStream::Ok)
{
*errorMsg = QString("Failed to parse '%1'").arg(fileName);
return false;
}
Observation observation;
observation.utmx = utmx;
observation.utmy = utmy;
observation.mdrkb = mdrkb;
observation.tvdmsl = tvdmsl;
observation.formation = formationName;
wellObservationSet->observations.push_back(observation);
}
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RifReaderFmuRft::readObsFile(const QString& fileName, QString* errorMsg, WellObservationSet* wellObservationSet)
{
QFile file(fileName);
if (!(file.open(QIODevice::Text | QIODevice::ReadOnly)))
{
*errorMsg = QString("Could not open '%1'").arg(fileName);
return false;
}
size_t lineNumber = 0u;
QTextStream stream(&file);
while (true)
{
if (lineNumber >= wellObservationSet->observations.size())
{
*errorMsg = QString("'%1' has more lines than corresponding txt file").arg(fileName);
return false;
}
QString line = stream.readLine();
if (line.isNull())
{
break;
}
else
{
QTextStream lineStream(&line);
double pressure, pressureError;
lineStream >> pressure >> pressureError;
if (lineStream.status() != QTextStream::Ok)
{
*errorMsg = QString("Failed to parse line %1 of '%2'").arg(lineNumber + 1).arg(fileName);
return false;
}
Observation& observation = wellObservationSet->observations[lineNumber];
observation.pressure = pressure;
observation.pressureError = pressureError;
}
lineNumber++;
}
if (lineNumber != wellObservationSet->observations.size())
{
*errorMsg = QString("'%1' has less lines than corresponding txt file").arg(fileName);
return false;
}
return true;
}

View File

@@ -0,0 +1,98 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RifEclipseRftAddress.h"
#include "RifReaderRftInterface.h"
#include <map>
#include <string>
#include <vector>
#include "cvfBase.h"
#include "cvfObject.h"
#include <QDateTime>
#include <QDir>
//==================================================================================================
//
//
//==================================================================================================
class RifReaderFmuRft : public RifReaderRftInterface, public cvf::Object
{
public:
struct Observation
{
double utmx;
double utmy;
double mdrkb;
double tvdmsl;
double pressure;
double pressureError;
QString formation;
Observation();
bool valid() const;
};
struct WellObservationSet
{
QDateTime dateTime;
int measurementIndex;
std::vector<Observation> observations;
WellObservationSet(const QDateTime& dateTime, int measurementIndex);
};
public:
RifReaderFmuRft(const QString& filePath);
~RifReaderFmuRft() = default;
static QStringList findSubDirectoriesWithFmuRftData(const QString& filePath);
static bool directoryContainsFmuRftData(const QString& filePath);
std::set<RifEclipseRftAddress> eclipseRftAddresses() override;
void values(const RifEclipseRftAddress& rftAddress, std::vector<double>* values) override;
std::set<QDateTime> availableTimeSteps(const QString& wellName,
const std::set<RifEclipseRftAddress::RftWellLogChannelType> relevantChannels) override;
std::set<QDateTime> availableTimeSteps(const QString& wellName) override;
std::set<QDateTime> availableTimeSteps(const QString& wellName,
const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName) override;
std::set<RifEclipseRftAddress::RftWellLogChannelType> availableWellLogChannels(const QString& wellName) override;
std::set<QString> wellNames() override;
public:
void load();
private:
typedef std::pair<QString, WellObservationSet> WellObservationPair;
typedef std::map<QString, WellObservationSet> WellObservationMap;
WellObservationMap loadWellDates(QDir& dir, QString* errorMsg);
static bool readTxtFile(const QString& txtFileName, QString* errorMsg, WellObservationSet* wellObservationSet);
static bool readObsFile(const QString& obsFileName, QString* errorMsg, WellObservationSet* wellObservationSet);
private:
QString m_filePath;
WellObservationMap m_allWellObservations;
};

View File

@@ -183,3 +183,11 @@ std::string RifReaderObservedData::unitName(const RifEclipseSummaryAddress& resu
std::string str = "";
return str;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RifReaderObservedData::unitSystem() const
{
return RiaEclipseUnitTools::UNITS_UNKNOWN;
}

View File

@@ -53,6 +53,9 @@ public:
std::string unitName(const RifEclipseSummaryAddress& resultAddress) const override;
RiaEclipseUnitTools::UnitSystem unitSystem() const override;
private:
RifEclipseSummaryAddress address(const QString& quantity,
const QString& identifierName,

View File

@@ -0,0 +1,37 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RifReaderRftInterface.h"
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<RifEclipseRftAddress> RifReaderRftInterface::eclipseRftAddresses(const QString& wellName, const QDateTime& timeStep)
{
std::set<RifEclipseRftAddress> matchingAddresses;
std::set<RifEclipseRftAddress> allAddresses = this->eclipseRftAddresses();
for (const RifEclipseRftAddress& address : allAddresses)
{
if (address.wellName() == wellName && address.timeStep() == timeStep)
{
matchingAddresses.insert(address);
}
}
return matchingAddresses;
}

View File

@@ -0,0 +1,44 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- Equinor ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RifEclipseRftAddress.h"
#include <QDateTime>
#include <QString>
#include <set>
#include <vector>
class RifReaderRftInterface
{
public:
std::set<RifEclipseRftAddress> eclipseRftAddresses(const QString& wellName, const QDateTime& timeStep);
virtual std::set<RifEclipseRftAddress> eclipseRftAddresses() = 0;
virtual void values(const RifEclipseRftAddress& rftAddress, std::vector<double>* values) = 0;
virtual std::set<QDateTime>
availableTimeSteps(const QString& wellName,
const std::set<RifEclipseRftAddress::RftWellLogChannelType> relevantChannels) = 0;
virtual std::set<QDateTime> availableTimeSteps(const QString& wellName) = 0;
virtual std::set<QDateTime> availableTimeSteps(const QString& wellName,
const RifEclipseRftAddress::RftWellLogChannelType& wellLogChannelName) = 0;
virtual std::set<RifEclipseRftAddress::RftWellLogChannelType> availableWellLogChannels(const QString& wellName) = 0;
virtual std::set<QString> wellNames() = 0;
};

View File

@@ -18,6 +18,7 @@
#pragma once
#include "RiaEclipseUnitTools.h"
#include "RifEclipseSummaryAddress.h"
#include "cvfObject.h"
@@ -50,7 +51,7 @@ public:
std::vector<double>* values) const = 0;
virtual std::string unitName(const RifEclipseSummaryAddress& resultAddress) const = 0;
virtual RiaEclipseUnitTools::UnitSystem unitSystem() const = 0;
virtual void markForCachePurge(const RifEclipseSummaryAddress& address) {}

View File

@@ -34,6 +34,7 @@ namespace caf
addItem(RifDataSourceForRftPlt::SourceType::RFT, "RFT", "RFT Cases");
addItem(RifDataSourceForRftPlt::SourceType::GRID, "GRID", "Grid Cases");
addItem(RifDataSourceForRftPlt::SourceType::OBSERVED, "OBSERVED", "Observed Data");
addItem(RifDataSourceForRftPlt::SourceType::ENSEMBLE_RFT, "ENSEMBLE", "Ensembles with RFT Data");
setDefault(RifDataSourceForRftPlt::SourceType::NONE);
}
}

View File

@@ -32,6 +32,8 @@
#include "RimEclipseResultCase.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimWellLogExtractionCurve.h"
#include "RimWellLogFile.h"
#include "RimWellLogFileChannel.h"
@@ -406,6 +408,48 @@ std::vector<RimEclipseResultCase*> RimWellPlotTools::rftCasesForWell(const QStri
return cases;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCaseCollection*> RimWellPlotTools::rftEnsemblesForWell(const QString& simWellName)
{
const RimProject* project = RiaApplication::instance()->project();
std::vector<RimSummaryCaseCollection*> allSummaryCaseCollections = project->summaryGroups();
std::vector<RimSummaryCaseCollection*> rftEnsembles;
for (RimSummaryCaseCollection* summaryCaseColl : allSummaryCaseCollections)
{
if (summaryCaseColl && summaryCaseColl->isEnsemble() && !summaryCaseColl->rftTimeStepsForWell(simWellName).empty())
{
rftEnsembles.push_back(summaryCaseColl);
}
}
return rftEnsembles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCaseCollection*> RimWellPlotTools::rftEnsembles()
{
const RimProject* project = RiaApplication::instance()->project();
std::vector<RimSummaryCaseCollection*> allSummaryCaseCollections = project->summaryGroups();
std::vector<RimSummaryCaseCollection*> rftEnsembles;
for (RimSummaryCaseCollection* summaryCaseColl : allSummaryCaseCollections)
{
if (summaryCaseColl && summaryCaseColl->isEnsemble() && !summaryCaseColl->wellsWithRftData().empty())
{
rftEnsembles.push_back(summaryCaseColl);
}
}
return rftEnsembles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -495,12 +539,28 @@ RiaRftPltCurveDefinition RimWellPlotTools::curveDefFromCurve(const RimWellLogCur
if (rftCurve != nullptr)
{
RimEclipseResultCase* rftCase = dynamic_cast<RimEclipseResultCase*>(rftCurve->eclipseResultCase());
RimEclipseResultCase* rftCase = dynamic_cast<RimEclipseResultCase*>(rftCurve->eclipseResultCase());
RimSummaryCase* rftSummaryCase = rftCurve->summaryCase();
RimSummaryCaseCollection* rftEnsemble = rftCurve->ensemble();
const RifEclipseRftAddress rftAddress = rftCurve->rftAddress();
const QString& wellName = rftAddress.wellName();
const QDateTime& timeStep = rftAddress.timeStep();
if (rftCase != nullptr)
{
const RifEclipseRftAddress rftAddress = rftCurve->rftAddress();
const QDateTime timeStep = rftAddress.timeStep();
return RiaRftPltCurveDefinition(RifDataSourceForRftPlt(RifDataSourceForRftPlt::RFT, rftCase), timeStep);
return RiaRftPltCurveDefinition(RifDataSourceForRftPlt(RifDataSourceForRftPlt::RFT, rftCase), wellName, timeStep);
}
else if (rftSummaryCase != nullptr)
{
rftSummaryCase->firstAncestorOrThisOfTypeAsserted(rftEnsemble);
return RiaRftPltCurveDefinition(
RifDataSourceForRftPlt(RifDataSourceForRftPlt::SUMMARY_RFT, rftSummaryCase, rftEnsemble), wellName, timeStep);
}
else if (rftEnsemble != nullptr)
{
return RiaRftPltCurveDefinition(
RifDataSourceForRftPlt(RifDataSourceForRftPlt::ENSEMBLE_RFT, rftEnsemble), wellName, timeStep);
}
}
else if (gridCurve != nullptr)
@@ -515,6 +575,7 @@ RiaRftPltCurveDefinition RimWellPlotTools::curveDefFromCurve(const RimWellLogCur
if (timeStepIndex < timeStepsMap.size())
{
return RiaRftPltCurveDefinition(RifDataSourceForRftPlt(RifDataSourceForRftPlt::GRID, gridCase),
gridCurve->wellName(),
timeStepsVector[timeStepIndex].first);
}
}
@@ -529,11 +590,12 @@ RiaRftPltCurveDefinition RimWellPlotTools::curveDefFromCurve(const RimWellLogCur
if (date.isValid())
{
return RiaRftPltCurveDefinition(RifDataSourceForRftPlt(RifDataSourceForRftPlt::OBSERVED, wellLogFile), date);
return RiaRftPltCurveDefinition(
RifDataSourceForRftPlt(RifDataSourceForRftPlt::OBSERVED, wellLogFile), wellLogFile->wellName(), date);
}
}
}
return RiaRftPltCurveDefinition(RifDataSourceForRftPlt(), QDateTime());
return RiaRftPltCurveDefinition(RifDataSourceForRftPlt(), QString(), QDateTime());
}
//--------------------------------------------------------------------------------------------------
@@ -591,14 +653,14 @@ std::set<RiaRftPltCurveDefinition>
for (const RifDataSourceForRftPlt& addr : selectedSourcesExpanded)
{
if (addr.rftReader())
if (addr.sourceType() == RifDataSourceForRftPlt::RFT && addr.rftReader())
{
std::set<QDateTime> rftTimes = addr.rftReader()->availableTimeSteps(simWellName, interestingRFTResults);
for (const QDateTime& time : rftTimes)
{
if (selectedTimeStepSet.count(time))
{
curveDefs.insert(RiaRftPltCurveDefinition(addr, time));
curveDefs.insert(RiaRftPltCurveDefinition(addr, simWellName, time));
}
}
}
@@ -611,7 +673,7 @@ std::set<RiaRftPltCurveDefinition>
{
if (selectedTimeStepSet.count(time))
{
curveDefs.insert(RiaRftPltCurveDefinition(addr, time));
curveDefs.insert(RiaRftPltCurveDefinition(addr, simWellName, time));
}
}
}
@@ -621,7 +683,37 @@ std::set<RiaRftPltCurveDefinition>
{
if (selectedTimeStepSet.count(addr.wellLogFile()->date()))
{
curveDefs.insert(RiaRftPltCurveDefinition(addr, addr.wellLogFile()->date()));
curveDefs.insert(RiaRftPltCurveDefinition(addr, simWellName, addr.wellLogFile()->date()));
}
}
}
else if (addr.sourceType() == RifDataSourceForRftPlt::ENSEMBLE_RFT)
{
if (addr.ensemble())
{
for (RimSummaryCase* summaryCase : addr.ensemble()->allSummaryCases())
{
if (summaryCase && summaryCase->rftReader())
{
RifDataSourceForRftPlt summaryAddr(RifDataSourceForRftPlt::SUMMARY_RFT, summaryCase, addr.ensemble());
std::set<QDateTime> timeSteps = summaryCase->rftReader()->availableTimeSteps(simWellName);
for (const QDateTime& time : timeSteps)
{
if (selectedTimeStepSet.count(time))
{
curveDefs.insert(RiaRftPltCurveDefinition(summaryAddr, simWellName, time));
}
}
}
}
std::set<QDateTime> statTimeSteps = addr.ensemble()->rftTimeStepsForWell(simWellName);
for (const QDateTime& time : statTimeSteps)
{
if (selectedTimeStepSet.count(time))
{
curveDefs.insert(RiaRftPltCurveDefinition(addr, simWellName, time));
}
}
}
}
@@ -780,9 +872,11 @@ std::map<QDateTime, std::set<RifDataSourceForRftPlt>> RimWellPlotTools::calculat
{
bool addFirstTimestep = (interestingRFTResults.count(RifEclipseRftAddress::PRESSURE) == 1);
bool hasObservedData = false;
bool hasRftData = false;
bool hasGridData = false;
bool hasObservedData = false;
bool hasRftData = false;
bool hasGridData = false;
bool hasEnsembleData = false;
bool hasSummaryRftData = false;
for (const auto& source : selSources)
{
@@ -797,12 +891,20 @@ std::map<QDateTime, std::set<RifDataSourceForRftPlt>> RimWellPlotTools::calculat
case RifDataSourceForRftPlt::OBSERVED:
hasObservedData = true;
break;
case RifDataSourceForRftPlt::SUMMARY_RFT:
hasSummaryRftData = true;
break;
case RifDataSourceForRftPlt::ENSEMBLE_RFT:
hasEnsembleData = true;
break;
}
}
std::map<QDateTime, std::set<RifDataSourceForRftPlt>> observedTimeStepsWithSources;
std::map<QDateTime, std::set<RifDataSourceForRftPlt>> rftTimeStepsWithSources;
std::map<QDateTime, std::set<RifDataSourceForRftPlt>> gridTimestepsWithSources;
std::map<QDateTime, std::set<RifDataSourceForRftPlt>> summaryRftTimeStepsWithSources;
std::map<QDateTime, std::set<RifDataSourceForRftPlt>> ensembleTimeStepsWithSources;
if (hasObservedData)
{
@@ -848,6 +950,39 @@ std::map<QDateTime, std::set<RifDataSourceForRftPlt>> RimWellPlotTools::calculat
}
}
if (hasSummaryRftData)
{
for (const auto& source : selSources)
{
if (source.sourceType() == RifDataSourceForRftPlt::SUMMARY_RFT && source.summaryCase())
{
std::set<QDateTime> wellTimeSteps =
source.summaryCase()->rftReader()->availableTimeSteps(wellPathNameOrSimWellName);
for (const QDateTime& date : wellTimeSteps)
{
summaryRftTimeStepsWithSources[date].insert(source);
}
}
}
}
if (hasEnsembleData)
{
for (const auto& source : selSources)
{
if (source.sourceType() == RifDataSourceForRftPlt::ENSEMBLE_RFT && source.ensemble())
{
std::set<QDateTime> wellTimeSteps = source.ensemble()->rftTimeStepsForWell(wellPathNameOrSimWellName);
for (const QDateTime& date : wellTimeSteps)
{
ensembleTimeStepsWithSources[date].insert(source);
}
}
}
}
// If we have a time baseline add the equal or adjacent grid timesteps
std::map<QDateTime, std::set<RifDataSourceForRftPlt>> timestepsToShowWithSources;
@@ -861,6 +996,14 @@ std::map<QDateTime, std::set<RifDataSourceForRftPlt>> RimWellPlotTools::calculat
{
timeBaseline = &rftTimeStepsWithSources;
}
else if (hasSummaryRftData)
{
timeBaseline = &summaryRftTimeStepsWithSources;
}
else if (hasEnsembleData)
{
timeBaseline = &ensembleTimeStepsWithSources;
}
if (timeBaseline)
{
@@ -876,9 +1019,21 @@ std::map<QDateTime, std::set<RifDataSourceForRftPlt>> RimWellPlotTools::calculat
for (const auto& dateSourceSetPair : gridTimestepsWithSources)
gridTimeSteps.insert(dateSourceSetPair.first);
std::set<QDateTime> summaryRftTimeSteps;
for (const auto& dateSourceSetPair : summaryRftTimeStepsWithSources)
summaryRftTimeSteps.insert(dateSourceSetPair.first);
std::set<QDateTime> ensembleRftTimeSteps;
for (const auto& dateSourceSetPair : ensembleTimeStepsWithSources)
ensembleRftTimeSteps.insert(dateSourceSetPair.first);
std::set<QDateTime> filteredRftTimeSteps = RimWellPlotTools::findMatchingOrAdjacentTimeSteps(baseTimeSteps, rftTimeSteps);
std::set<QDateTime> filteredGridTimeSteps =
RimWellPlotTools::findMatchingOrAdjacentTimeSteps(baseTimeSteps, gridTimeSteps);
std::set<QDateTime> filteredSummaryRftTimeSteps =
RimWellPlotTools::findMatchingOrAdjacentTimeSteps(baseTimeSteps, summaryRftTimeSteps);
std::set<QDateTime> filteredEnsembleRftTimeSteps =
RimWellPlotTools::findMatchingOrAdjacentTimeSteps(baseTimeSteps, ensembleRftTimeSteps);
if (addFirstTimestep && gridTimeSteps.size())
{
@@ -889,6 +1044,7 @@ std::map<QDateTime, std::set<RifDataSourceForRftPlt>> RimWellPlotTools::calculat
timestepsToShowWithSources = observedTimeStepsWithSources;
std::set<QDateTime>& allFilteredTimesteps = filteredRftTimeSteps;
allFilteredTimesteps.insert(filteredEnsembleRftTimeSteps.begin(), filteredEnsembleRftTimeSteps.end());
allFilteredTimesteps.insert(filteredGridTimeSteps.begin(), filteredGridTimeSteps.end());
for (const QDateTime& time : allFilteredTimesteps)
@@ -900,11 +1056,25 @@ std::map<QDateTime, std::set<RifDataSourceForRftPlt>> RimWellPlotTools::calculat
timestepsToShowWithSources[time].insert(sourceSet.begin(), sourceSet.end());
}
auto gridTimeSourceSetIt = gridTimestepsWithSources.find(time);
auto gridTimeSourceSetIt = gridTimestepsWithSources.find(time);
if (gridTimeSourceSetIt != gridTimestepsWithSources.end())
{
std::set<RifDataSourceForRftPlt>& sourceSet = gridTimeSourceSetIt->second;
timestepsToShowWithSources[time].insert(sourceSet.begin(), sourceSet.end());
}
auto summaryRftTimeSourceSetIt = summaryRftTimeStepsWithSources.find(time);
if (summaryRftTimeSourceSetIt != summaryRftTimeStepsWithSources.end())
{
std::set<RifDataSourceForRftPlt>& sourceSet = summaryRftTimeSourceSetIt->second;
timestepsToShowWithSources[time].insert(sourceSet.begin(), sourceSet.end());
}
auto ensembleRftTimeSourceSetIt = ensembleTimeStepsWithSources.find(time);
if (ensembleRftTimeSourceSetIt != ensembleTimeStepsWithSources.end())
{
std::set<RifDataSourceForRftPlt>& sourceSet = ensembleRftTimeSourceSetIt->second;
timestepsToShowWithSources[time].insert(sourceSet.begin(), sourceSet.end());
}
}
}
@@ -943,9 +1113,10 @@ void RimWellPlotTools::calculateValueOptionsForTimeSteps(
{
QString optionText = RiaQDateTimeTools::toStringUsingApplicationLocale(timeStepPair.first, dateFormatString);
bool hasObs = false;
bool hasRft = false;
bool hasGrid = false;
bool hasObs = false;
bool hasRft = false;
bool hasGrid = false;
bool hasEnsemble = false;
for (const auto& source : timeStepPair.second)
{
@@ -960,15 +1131,19 @@ void RimWellPlotTools::calculateValueOptionsForTimeSteps(
case RifDataSourceForRftPlt::GRID:
hasGrid = true;
break;
case RifDataSourceForRftPlt::ENSEMBLE_RFT:
hasEnsemble = true;
break;
}
}
optionText += " \t[ ";
if (hasObs) optionText += "O ";
if (hasRft) optionText += "R ";
if (hasGrid) optionText += "G";
optionText += " ]";
QStringList optionTags;
if (hasObs) optionTags << "O";
if (hasRft) optionTags << "R";
if (hasGrid) optionTags << "G";
if (hasEnsemble) optionTags << "E";
optionText += QString(" \t[%1]").arg(optionTags.join(", "));
options.push_back(caf::PdmOptionItemInfo(optionText, timeStepPair.first));
}
}

View File

@@ -33,6 +33,7 @@
class RimEclipseCase;
class RimEclipseResultCase;
class RimSummaryCaseCollection;
class RimWellLogCurve;
class RimWellLogFileChannel;
class RimWellLogPlot;
@@ -82,6 +83,8 @@ public:
// Both
static std::vector<RimEclipseResultCase*> gridCasesForWell(const QString& simWellName);
static std::vector<RimEclipseResultCase*> rftCasesForWell(const QString& simWellName);
static std::vector<RimSummaryCaseCollection*> rftEnsemblesForWell(const QString& simWellName);
static std::vector<RimSummaryCaseCollection*> rftEnsembles();
static QString simWellName(const QString& wellPathNameOrSimWellName);
static std::map<QDateTime, std::set<RifDataSourceForRftPlt>>

View File

@@ -19,6 +19,7 @@
#include "RimWellRftPlot.h"
#include "RiaApplication.h"
#include "RiaColorTools.h"
#include "RiaColorTables.h"
#include "RiaDateStringParser.h"
#include "RiaSimWellBranchTools.h"
@@ -36,6 +37,7 @@
#include "RimEclipseResultDefinition.h"
#include "RimOilField.h"
#include "RimProject.h"
#include "RimSummaryCaseCollection.h"
#include "RimTools.h"
#include "RimWellLogExtractionCurve.h"
#include "RimWellLogFile.h"
@@ -49,6 +51,7 @@
#include "RimWellPlotTools.h"
#include "RimWellPltPlot.h"
#include "RiuWellLogTrack.h"
#include "RiuWellRftPlot.h"
#include "cafPdmUiTreeOrdering.h"
@@ -76,6 +79,8 @@ RimWellRftPlot::RimWellRftPlot()
m_userName.uiCapability()->setUiReadOnly(true);
CAF_PDM_InitField(&m_showPlotTitle, "ShowPlotTitle", true, "Show Plot Title", "", "", "");
CAF_PDM_InitField(&m_showStatisticsCurves, "ShowStatisticsCurves", true, "Show Statistics Curves", "", "", "");
CAF_PDM_InitField(&m_showEnsembleCurves, "ShowEnsembleCurves", true, "Show Ensemble Curves", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_wellLogPlot, "WellLog", "Well Log", "", "", "");
m_wellLogPlot.uiCapability()->setUiHidden(true);
@@ -135,94 +140,39 @@ void RimWellRftPlot::deleteViewWidget()
//--------------------------------------------------------------------------------------------------
void RimWellRftPlot::applyCurveAppearance(RimWellLogCurve* newCurve)
{
const RiaRftPltCurveDefinition& newCurveDef = RimWellPlotTools::curveDefFromCurve(newCurve);
RiaRftPltCurveDefinition newCurveDef = RimWellPlotTools::curveDefFromCurve(newCurve);
std::vector<cvf::Color3f> colorTable;
RiaColorTables::summaryCurveDefaultPaletteColors().color3fArray().toStdVector(&colorTable);
RiuQwtPlotCurve::LineStyleEnum currentLineStyle = RiuQwtPlotCurve::STYLE_SOLID;
std::vector<RiuQwtSymbol::PointSymbolEnum> symbolTable = {RiuQwtSymbol::SYMBOL_ELLIPSE,
RiuQwtSymbol::SYMBOL_RECT,
RiuQwtSymbol::SYMBOL_DIAMOND,
RiuQwtSymbol::SYMBOL_TRIANGLE,
RiuQwtSymbol::SYMBOL_CROSS,
RiuQwtSymbol::SYMBOL_XCROSS};
// State variables
static size_t defaultColorTableIndex = 0;
static size_t defaultSymbolTableIndex = 0;
cvf::Color3f currentColor;
RiuQwtSymbol::PointSymbolEnum currentSymbol = symbolTable.front();
RiuQwtPlotCurve::LineStyleEnum currentLineStyle = RiuQwtPlotCurve::STYLE_SOLID;
bool isCurrentColorSet = false;
bool isCurrentSymbolSet = false;
std::set<cvf::Color3f> assignedColors;
std::set<RiuQwtSymbol::PointSymbolEnum> assignedSymbols;
// Used colors and symbols
for (RimWellLogCurve* const curve : m_wellLogPlot->trackByIndex(0)->curvesVector())
{
if (curve == newCurve) continue;
RiaRftPltCurveDefinition cDef = RimWellPlotTools::curveDefFromCurve(curve);
if (cDef.address() == newCurveDef.address())
{
currentColor = curve->color();
isCurrentColorSet = true;
}
if (cDef.timeStep() == newCurveDef.timeStep())
{
currentSymbol = curve->symbol();
isCurrentSymbolSet = true;
}
assignedColors.insert(curve->color());
assignedSymbols.insert(curve->symbol());
}
// Assign color
if (!isCurrentColorSet)
{
for (const auto& color : colorTable)
{
if (assignedColors.count(color) == 0)
{
currentColor = color;
isCurrentColorSet = true;
break;
}
}
if (!isCurrentColorSet)
{
currentColor = colorTable[defaultColorTableIndex];
if (++defaultColorTableIndex == colorTable.size()) defaultColorTableIndex = 0;
}
}
// Assign symbol
if (!isCurrentSymbolSet)
{
for (const auto& symbol : symbolTable)
{
if (assignedSymbols.count(symbol) == 0)
{
currentSymbol = symbol;
isCurrentSymbolSet = true;
break;
}
}
if (!isCurrentSymbolSet)
{
currentSymbol = symbolTable[defaultSymbolTableIndex];
if (++defaultSymbolTableIndex == symbolTable.size()) defaultSymbolTableIndex = 0;
}
}
cvf::Color3f currentColor;
if (newCurveDef.address().sourceType() == RifDataSourceForRftPlt::SUMMARY_RFT)
{
RifDataSourceForRftPlt sourceAddress(RifDataSourceForRftPlt::ENSEMBLE_RFT, newCurveDef.address().ensemble());
currentColor = m_dataSourceColors[sourceAddress];
if (m_showStatisticsCurves)
{
cvf::Color3f backgroundColor =
RiaColorTools::fromQColorTo3f(m_wellLogPlot->trackByIndex(0)->viewer()->canvasBackground().color());
currentColor = RiaColorTools::blendCvfColors(backgroundColor, currentColor, 2, 1);
}
}
else
{
currentColor = m_dataSourceColors[newCurveDef.address()];
}
RiuQwtSymbol::PointSymbolEnum currentSymbol = RiuQwtSymbol::SYMBOL_NONE;
if (newCurveDef.address().sourceType() != RifDataSourceForRftPlt::ENSEMBLE_RFT)
{
currentSymbol = m_timeStepSymbols[newCurveDef.timeStep()];
}
// Observed data
currentLineStyle = newCurveDef.address().sourceType() == RifDataSourceForRftPlt::OBSERVED ? RiuQwtPlotCurve::STYLE_NONE
: RiuQwtPlotCurve::STYLE_SOLID;
newCurve->setColor(currentColor);
newCurve->setSymbolEdgeColor(currentColor);
newCurve->setSymbol(currentSymbol);
newCurve->setLineStyle(currentLineStyle);
}
@@ -289,6 +239,11 @@ void RimWellRftPlot::applyInitialSelections()
sourcesToSelect.push_back(RifDataSourceForRftPlt(RifDataSourceForRftPlt::GRID, gridCase));
}
for (RimSummaryCaseCollection* const ensemble : RimWellPlotTools::rftEnsemblesForWell(simWellName))
{
sourcesToSelect.push_back(RifDataSourceForRftPlt(RifDataSourceForRftPlt::ENSEMBLE_RFT, ensemble));
}
std::vector<RimWellLogFile*> wellLogFiles = RimWellPlotTools::wellLogFilesContainingPressure(m_wellPathNameOrSimWellName);
if (!wellLogFiles.empty())
{
@@ -447,6 +402,8 @@ void RimWellRftPlot::updateCurvesInPlot(const std::set<RiaRftPltCurveDefinition>
// Delete curves
plotTrack->deleteAllCurves();
defineCurveColorsAndSymbols(allCurveDefs);
// Add new curves
for (const RiaRftPltCurveDefinition& curveDefToAdd : allCurveDefs)
{
@@ -465,6 +422,47 @@ void RimWellRftPlot::updateCurvesInPlot(const std::set<RiaRftPltCurveDefinition>
applyCurveAppearance(curve);
}
else if (m_showEnsembleCurves && curveDefToAdd.address().sourceType() == RifDataSourceForRftPlt::SUMMARY_RFT)
{
auto curve = new RimWellLogRftCurve();
plotTrack->addCurve(curve);
auto rftCase = curveDefToAdd.address().summaryCase();
curve->setSummaryCase(rftCase);
RifEclipseRftAddress address(simWellName, curveDefToAdd.timeStep(), RifEclipseRftAddress::PRESSURE);
curve->setRftAddress(address);
curve->setZOrder(1);
applyCurveAppearance(curve);
}
else if (m_showStatisticsCurves && curveDefToAdd.address().sourceType() == RifDataSourceForRftPlt::ENSEMBLE_RFT)
{
RimSummaryCaseCollection* ensemble = curveDefToAdd.address().ensemble();
std::set<RifEclipseRftAddress> rftAddresses =
ensemble->rftStatisticsReader()->eclipseRftAddresses(simWellName, curveDefToAdd.timeStep());
for (auto rftAddress : rftAddresses)
{
if (rftAddress.wellLogChannel() != RifEclipseRftAddress::TVD)
{
auto curve = new RimWellLogRftCurve();
plotTrack->addCurve(curve);
curve->setEnsemble(ensemble);
curve->setRftAddress(rftAddress);
curve->setZOrder(RiuQwtPlotCurve::Z_ENSEMBLE_STAT_CURVE);
applyCurveAppearance(curve);
auto symbol = statisticsCurveSymbolFromAddress(rftAddress);
RiuQwtSymbol::LabelPosition labelPos = statisticsLabelPosFromAddress(rftAddress);
curve->setSymbol(symbol);
curve->setSymbolLabelPosition(labelPos);
curve->setSymbolSize(curve->symbolSize() + 3);
curve->setSymbolSkipDistance(150);
curve->setLineStyle(RiuQwtPlotCurve::STYLE_SOLID);
QString uiText =
caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::uiText(rftAddress.wellLogChannel());
QString label = uiText.replace("Pressure", "");
curve->setSymbolLabel(label);
}
}
}
else if (curveDefToAdd.address().sourceType() == RifDataSourceForRftPlt::GRID)
{
auto curve = new RimWellLogExtractionCurve();
@@ -580,6 +578,14 @@ RimWellLogPlot* RimWellRftPlot::wellLogPlot() const
return m_wellLogPlot();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QString& RimWellRftPlot::simWellOrWellPathName() const
{
return m_wellPathNameOrSimWellName.v();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -639,6 +645,21 @@ QList<caf::PdmOptionItemInfo> RimWellRftPlot::calculateValueOptions(const caf::P
}
}
const std::vector<RimSummaryCaseCollection*> rftEnsembles = RimWellPlotTools::rftEnsemblesForWell(simWellName);
if (!rftEnsembles.empty())
{
options.push_back(caf::PdmOptionItemInfo::createHeader(
RifDataSourceForRftPlt::sourceTypeUiText(RifDataSourceForRftPlt::ENSEMBLE_RFT), true));
for (RimSummaryCaseCollection* rftEnsemble : rftEnsembles)
{
auto addr = RifDataSourceForRftPlt(RifDataSourceForRftPlt::ENSEMBLE_RFT, rftEnsemble);
auto item = caf::PdmOptionItemInfo(rftEnsemble->name(), QVariant::fromValue(addr));
item.setLevel(1);
options.push_back(item);
}
}
const std::vector<RimEclipseResultCase*> gridCases = RimWellPlotTools::gridCasesForWell(simWellName);
if (!gridCases.empty())
{
@@ -716,7 +737,14 @@ void RimWellRftPlot::fieldChangedByUi(const caf::PdmFieldHandle* changedField, c
{
updateFormationsOnPlot();
syncCurvesFromUiSelection();
this->updateConnectedEditors();
}
else if (changedField == &m_showStatisticsCurves || changedField == &m_showEnsembleCurves)
{
updateFormationsOnPlot();
syncCurvesFromUiSelection();
}
else if (changedField == &m_showPlotTitle)
{
// m_wellLogPlot->setShowDescription(m_showPlotTitle);
@@ -754,6 +782,20 @@ void RimWellRftPlot::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering&
{
uiOrdering.add(&m_userName);
uiOrdering.add(&m_wellPathNameOrSimWellName);
uiOrdering.add(&m_showStatisticsCurves);
uiOrdering.add(&m_showEnsembleCurves);
bool showingEnsembleData = false;
for (const RifDataSourceForRftPlt& dataSource : m_selectedSources())
{
if (dataSource.sourceType() == RifDataSourceForRftPlt::ENSEMBLE_RFT)
{
showingEnsembleData = true;
break;
}
}
m_showStatisticsCurves.uiCapability()->setUiReadOnly(!showingEnsembleData);
m_showEnsembleCurves.uiCapability()->setUiReadOnly(!showingEnsembleData);
RiaSimWellBranchTools::appendSimWellBranchFieldsIfRequiredFromWellName(
&uiOrdering, m_wellPathNameOrSimWellName, m_branchDetection, m_branchIndex);
@@ -818,6 +860,20 @@ void RimWellRftPlot::calculateValueOptionsForWells(QList<caf::PdmOptionItemInfo>
}
}
// Ensemble RFT wells
const std::vector<RimSummaryCaseCollection*> rftEnsembles = RimWellPlotTools::rftEnsembles();
if (!rftEnsembles.empty())
{
for (RimSummaryCaseCollection* summaryCaseColl : rftEnsembles)
{
std::set<QString> wellsWithRftData = summaryCaseColl->wellsWithRftData();
for (QString wellName : wellsWithRftData)
{
wellNames.insert(std::make_pair(wellName, wellName));
}
}
}
for (const auto& wellName : wellNames)
{
options.push_back(caf::PdmOptionItemInfo(wellName.first, wellName.second));
@@ -870,6 +926,8 @@ void RimWellRftPlot::onLoadDataAndUpdate()
updateEditorsFromCurves();
updateWidgetTitleWindowTitle();
// applyInitialSelections();
}
//--------------------------------------------------------------------------------------------------
@@ -903,3 +961,88 @@ QWidget* RimWellRftPlot::createViewWidget(QWidget* mainWindowParent)
return m_wellLogPlotWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuQwtSymbol::PointSymbolEnum RimWellRftPlot::statisticsCurveSymbolFromAddress(const RifEclipseRftAddress& address)
{
switch (address.wellLogChannel())
{
case RifEclipseRftAddress::PRESSURE_P10:
return RiuQwtSymbol::SYMBOL_TRIANGLE;
case RifEclipseRftAddress::PRESSURE_P50:
return RiuQwtSymbol::SYMBOL_DOWN_TRIANGLE;
case RifEclipseRftAddress::PRESSURE_P90:
return RiuQwtSymbol::SYMBOL_LEFT_TRIANGLE;
case RifEclipseRftAddress::PRESSURE_MEAN:
return RiuQwtSymbol::SYMBOL_RIGHT_TRIANGLE;
}
return RiuQwtSymbol::SYMBOL_RIGHT_TRIANGLE;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuQwtSymbol::LabelPosition RimWellRftPlot::statisticsLabelPosFromAddress(const RifEclipseRftAddress& address)
{
switch (address.wellLogChannel())
{
case RifEclipseRftAddress::PRESSURE_P10:
return RiuQwtSymbol::LabelLeftOfSymbol;
case RifEclipseRftAddress::PRESSURE_P50:
return RiuQwtSymbol::LabelAboveSymbol;
case RifEclipseRftAddress::PRESSURE_P90:
return RiuQwtSymbol::LabelRightOfSymbol;
case RifEclipseRftAddress::PRESSURE_MEAN:
return RiuQwtSymbol::LabelBelowSymbol;
}
return RiuQwtSymbol::LabelAboveSymbol;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellRftPlot::defineCurveColorsAndSymbols(const std::set<RiaRftPltCurveDefinition>& allCurveDefs)
{
m_dataSourceColors.clear();
m_timeStepSymbols.clear();
std::vector<cvf::Color3f> colorTable;
RiaColorTables::summaryCurveDefaultPaletteColors().color3fArray().toStdVector(&colorTable);
std::vector<RiuQwtSymbol::PointSymbolEnum> symbolTable = {RiuQwtSymbol::SYMBOL_ELLIPSE,
RiuQwtSymbol::SYMBOL_RECT,
RiuQwtSymbol::SYMBOL_DIAMOND,
RiuQwtSymbol::SYMBOL_CROSS,
RiuQwtSymbol::SYMBOL_XCROSS,
RiuQwtSymbol::SYMBOL_STAR1};
// Add new curves
for (const RiaRftPltCurveDefinition& curveDefToAdd : allCurveDefs)
{
auto colorTableIndex = m_dataSourceColors.size();
auto symbolTableIndex = m_timeStepSymbols.size();
RifDataSourceForRftPlt address = curveDefToAdd.address();
if (address.sourceType() != RifDataSourceForRftPlt::SUMMARY_RFT)
{
if (!m_dataSourceColors.count(curveDefToAdd.address()))
{
colorTableIndex = colorTableIndex % colorTable.size();
m_dataSourceColors[curveDefToAdd.address()] = colorTable[colorTableIndex];
}
}
if (address.sourceType() != RifDataSourceForRftPlt::ENSEMBLE_RFT)
{
if (!m_timeStepSymbols.count(curveDefToAdd.timeStep()))
{
symbolTableIndex = symbolTableIndex % symbolTable.size();
m_timeStepSymbols[curveDefToAdd.timeStep()] = symbolTable[symbolTableIndex];
}
}
}
}

View File

@@ -1,27 +1,27 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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>
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RimViewWindow.h"
#include "RifDataSourceForRftPltQMetaType.h"
#include "RiuQwtSymbol.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
@@ -46,102 +46,118 @@ class RiuWellRftPlot;
class RigEclipseCaseData;
class RiaRftPltCurveDefinition;
class RifDataSourceForRftPlt;
class RifEclipseRftAddress;
namespace cvf {
class Color3f;
namespace cvf
{
class Color3f;
}
namespace caf {
class PdmOptionItemInfo;
namespace caf
{
class PdmOptionItemInfo;
}
//==================================================================================================
///
///
///
///
//==================================================================================================
class RimWellRftPlot : public RimViewWindow
{
CAF_PDM_HEADER_INIT;
static const std::set<QString> PRESSURE_DATA_NAMES;
static const char PLOT_NAME_QFORMAT_STRING[];
static const char PLOT_NAME_QFORMAT_STRING[];
public:
RimWellRftPlot();
~RimWellRftPlot() override;
void setDescription(const QString& description);
QString description() const;
void setDescription(const QString& description);
QString description() const;
QWidget* viewWidget() override;
void zoomAll() override;
QWidget* viewWidget() override;
void zoomAll() override;
RimWellLogPlot* wellLogPlot() const;
RimWellLogPlot* wellLogPlot() const;
void setSimWellOrWellPathName(const QString& currWellName);
const QString& simWellOrWellPathName() const;
void setSimWellOrWellPathName(const QString& currWellName);
int branchIndex() const;
int branchIndex() const;
void applyInitialSelections();
void applyInitialSelections();
static const char* plotNameFormatString();
protected:
// Overridden PDM methods
caf::PdmFieldHandle* userDescriptionField() override { return &m_userName; }
void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName) override;
caf::PdmFieldHandle* userDescriptionField() override
{
return &m_userName;
}
void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) override;
QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly) override;
QImage snapshotWindowContent() override;
QImage snapshotWindowContent() override;
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
void onLoadDataAndUpdate() override;
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
void onLoadDataAndUpdate() override;
private:
void calculateValueOptionsForWells(QList<caf::PdmOptionItemInfo>& options);
void updateEditorsFromCurves();
void updateWidgetTitleWindowTitle();
void syncCurvesFromUiSelection();
void assignWellPathToExtractionCurves();
void calculateValueOptionsForWells(QList<caf::PdmOptionItemInfo>& options);
void updateEditorsFromCurves();
void updateWidgetTitleWindowTitle();
void syncCurvesFromUiSelection();
void assignWellPathToExtractionCurves();
std::set<RiaRftPltCurveDefinition> selectedCurveDefs() const;
std::set<RiaRftPltCurveDefinition> curveDefsFromCurves() const;
std::set<RiaRftPltCurveDefinition> selectedCurveDefs() const;
std::set<RiaRftPltCurveDefinition> curveDefsFromCurves() const;
void updateCurvesInPlot(const std::set<RiaRftPltCurveDefinition>& allCurveDefs,
const std::set<RiaRftPltCurveDefinition>& curveDefsToAdd,
const std::set<RimWellLogCurve*>& curvesToDelete);
void updateCurvesInPlot(const std::set<RiaRftPltCurveDefinition>& allCurveDefs,
const std::set<RiaRftPltCurveDefinition>& curveDefsToAdd,
const std::set<RimWellLogCurve*>& curvesToDelete);
std::vector<RifDataSourceForRftPlt> selectedSourcesExpanded() const;
// RimViewWindow overrides
QWidget* createViewWidget(QWidget* mainWindowParent) override;
void deleteViewWidget() override;
QWidget* createViewWidget(QWidget* mainWindowParent) override;
void deleteViewWidget() override;
void applyCurveAppearance(RimWellLogCurve* newCurve);
void applyCurveAppearance(RimWellLogCurve* newCurve);
void updateFormationsOnPlot() const;
QString associatedSimWellName() const;
void updateFormationsOnPlot() const;
QString associatedSimWellName() const;
static RiuQwtSymbol::PointSymbolEnum statisticsCurveSymbolFromAddress(const RifEclipseRftAddress& address);
static RiuQwtSymbol::LabelPosition statisticsLabelPosFromAddress(const RifEclipseRftAddress& address);
void defineCurveColorsAndSymbols(const std::set<RiaRftPltCurveDefinition>& allCurveDefs);
private:
caf::PdmField<bool> m_showPlotTitle;
caf::PdmField<QString> m_userName;
caf::PdmField<bool> m_showPlotTitle;
caf::PdmField<QString> m_userName;
caf::PdmField<QString> m_wellPathNameOrSimWellName;
caf::PdmField<int> m_branchIndex;
caf::PdmField<bool> m_branchDetection;
caf::PdmField<QString> m_wellPathNameOrSimWellName;
caf::PdmField<int> m_branchIndex;
caf::PdmField<bool> m_branchDetection;
caf::PdmField<bool> m_showStatisticsCurves;
caf::PdmField<bool> m_showEnsembleCurves;
caf::PdmField<std::vector<RifDataSourceForRftPlt>> m_selectedSources;
caf::PdmField<std::vector<QDateTime>> m_selectedTimeSteps;
caf::PdmField<std::vector<RifDataSourceForRftPlt>> m_selectedSources;
caf::PdmChildField<RimWellLogPlot*> m_wellLogPlot;
caf::PdmField<std::vector<QDateTime>> m_selectedTimeSteps;
QPointer<RiuWellRftPlot> m_wellLogPlotWidget;
caf::PdmChildField<RimWellLogPlot*> m_wellLogPlot;
QPointer<RiuWellRftPlot> m_wellLogPlotWidget;
std::map<RifDataSourceForRftPlt, cvf::Color3f> m_dataSourceColors;
std::map<QDateTime, RiuQwtSymbol::PointSymbolEnum> m_timeStepSymbols;
bool m_isOnLoad;
};

View File

@@ -191,7 +191,7 @@ QList<caf::PdmOptionItemInfo> Rim3dWellLogRftCurve::calculateValueOptions(const
if (reader)
{
QString dateFormat = "dd MMM yyyy";
std::vector<QDateTime> timeStamps = reader->availableTimeSteps(wellName(), m_wellLogChannelName());
std::set<QDateTime> timeStamps = reader->availableTimeSteps(wellName(), m_wellLogChannelName());
for (const QDateTime& dt : timeStamps)
{
QString dateString = RiaQDateTimeTools::toStringUsingApplicationLocale(dt, dateFormat);

View File

@@ -73,12 +73,27 @@ void RimPlotCurve::PointSymbol::setUp()
addItem(RiuQwtSymbol::SYMBOL_RECT, "SYMBOL_RECT", "Rect");
addItem(RiuQwtSymbol::SYMBOL_DIAMOND, "SYMBOL_DIAMOND", "Diamond");
addItem(RiuQwtSymbol::SYMBOL_TRIANGLE, "SYMBOL_TRIANGLE", "Triangle");
addItem(RiuQwtSymbol::SYMBOL_DOWN_TRIANGLE, "SYMBOL_DOWN_TRIANGLE", "Down Triangle");
addItem(RiuQwtSymbol::SYMBOL_CROSS, "SYMBOL_CROSS", "Cross");
addItem(RiuQwtSymbol::SYMBOL_XCROSS, "SYMBOL_XCROSS", "X Cross");
addItem(RiuQwtSymbol::SYMBOL_STAR1, "SYMBOL_STAR1", "Star 1");
addItem(RiuQwtSymbol::SYMBOL_STAR2, "SYMBOL_STAR2", "Star 2");
addItem(RiuQwtSymbol::SYMBOL_HEXAGON, "SYMBOL_HEXAGON", "Hexagon");
addItem(RiuQwtSymbol::SYMBOL_LEFT_TRIANGLE, "SYMBOL_LEFT_TRIANGLE", "Left Triangle");
addItem(RiuQwtSymbol::SYMBOL_RIGHT_TRIANGLE, "SYMBOL_RIGHT_TRIANGLE", "Right Triangle");
setDefault(RiuQwtSymbol::SYMBOL_NONE);
}
template<>
void RimPlotCurve::LabelPosition::setUp()
{
addItem(RiuQwtSymbol::LabelAboveSymbol, "LABEL_ABOVE_SYMBOL", "Label above Symbol");
addItem(RiuQwtSymbol::LabelBelowSymbol, "LABEL_BELOW_SYMBOL", "Label below Symbol");
addItem(RiuQwtSymbol::LabelLeftOfSymbol, "LABEL_LEFT_OF_SYMBOL", "Label left of Symbol");
addItem(RiuQwtSymbol::LabelRightOfSymbol, "LABEL_RIGHT_OF_SYMBOL", "Label right of Symbol");
setDefault(RiuQwtSymbol::LabelAboveSymbol);
}
}
@@ -86,7 +101,6 @@ void RimPlotCurve::PointSymbol::setUp()
///
//--------------------------------------------------------------------------------------------------
RimPlotCurve::RimPlotCurve()
: m_symbolLabelPosition(RiuQwtSymbol::LabelAboveSymbol)
{
CAF_PDM_InitObject("Curve", ":/WellLogCurve16x16.png", "", "");
@@ -116,10 +130,13 @@ RimPlotCurve::RimPlotCurve()
CAF_PDM_InitField(&m_showLegend, "ShowLegend", true, "Contribute To Legend", "", "", "");
CAF_PDM_InitField(&m_symbolSize, "SymbolSize", 6, "Symbol Size", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_symbolLabel, "SymbolLabel", "Symbol Label", "", "", "");
CAF_PDM_InitField(&m_symbolSize, "SymbolSize", 6, "Symbol Size", "", "", "");
CAF_PDM_InitField(&m_showErrorBars, "ShowErrorBars", true, "Show Error Bars", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_symbolLabelPosition, "SymbolLabelPosition", "Symbol Label Position", "", "", "");
m_qwtPlotCurve = new RiuRimQwtPlotCurve(this);
m_parentQwtPlot = nullptr;
@@ -548,7 +565,7 @@ void RimPlotCurve::updateCurveAppearance()
if (m_pointSymbol() != RiuQwtSymbol::SYMBOL_NONE)
{
// QwtPlotCurve will take ownership of the symbol
symbol = new RiuQwtSymbol(m_pointSymbol(), m_symbolLabel, m_symbolLabelPosition);
symbol = new RiuQwtSymbol(m_pointSymbol(), m_symbolLabel(), m_symbolLabelPosition());
symbol->setSize(m_symbolSize, m_symbolSize);
symbol->setColor(curveColor);
@@ -683,6 +700,14 @@ RiuQwtSymbol::PointSymbolEnum RimPlotCurve::symbol()
return m_pointSymbol();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int RimPlotCurve::symbolSize() const
{
return m_symbolSize();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -715,6 +740,14 @@ void RimPlotCurve::setSymbolLabel(const QString& label)
m_symbolLabel = label;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimPlotCurve::setSymbolLabelPosition(RiuQwtSymbol::LabelPosition labelPosition)
{
m_symbolLabelPosition = labelPosition;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -41,6 +41,7 @@ public:
typedef caf::AppEnum<RiuQwtPlotCurve::CurveInterpolationEnum> CurveInterpolation;
typedef caf::AppEnum<RiuQwtPlotCurve::LineStyleEnum> LineStyle;
typedef caf::AppEnum<RiuQwtSymbol::PointSymbolEnum> PointSymbol;
typedef caf::AppEnum<RiuQwtSymbol::LabelPosition> LabelPosition;
public:
RimPlotCurve();
@@ -62,10 +63,12 @@ public:
void setLineStyle(RiuQwtPlotCurve::LineStyleEnum lineStyle);
void setSymbol(RiuQwtSymbol::PointSymbolEnum symbolStyle);
RiuQwtSymbol::PointSymbolEnum symbol();
int symbolSize() const;
cvf::Color3f symbolEdgeColor() const;
void setSymbolEdgeColor(const cvf::Color3f& edgeColor);
void setSymbolSkipDistance(float distance);
void setSymbolLabel(const QString& label);
void setSymbolLabelPosition(RiuQwtSymbol::LabelPosition labelPosition);
void setSymbolSize(int sizeInPixels);
void setLineThickness(int thickness);
void resetAppearance();
@@ -128,7 +131,7 @@ protected:
caf::PdmField<QString> m_curveName;
caf::PdmField<QString> m_customCurveName;
caf::PdmField<bool> m_showLegend;
QString m_symbolLabel;
caf::PdmField<QString> m_symbolLabel;
caf::PdmField<int> m_symbolSize;
caf::PdmField<QString> m_legendEntryText;
@@ -141,7 +144,7 @@ protected:
caf::PdmField<PointSymbol> m_pointSymbol;
caf::PdmField<LineStyle> m_lineStyle;
caf::PdmField<CurveInterpolation> m_curveInterpolation;
RiuQwtSymbol::LabelPosition m_symbolLabelPosition;
caf::PdmField<LabelPosition> m_symbolLabelPosition;
caf::PdmField<cvf::Color3f> m_symbolEdgeColor;
};

View File

@@ -23,7 +23,7 @@
#include "RiaSummaryCurveDefinition.h"
#include "RiaSummaryTools.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RiaCurveMerger.h"
#include "RimProject.h"
#include "RimSummaryAddress.h"
@@ -267,7 +267,7 @@ bool RimSummaryCalculation::calculate()
std::vector<time_t> curveTimeSteps = RiaSummaryCurveDefinition::timeSteps(curveDef);
timeHistoryCurveMerger.addCurveData(curveValues, curveTimeSteps);
timeHistoryCurveMerger.addCurveData(curveTimeSteps, curveValues);
}
timeHistoryCurveMerger.computeInterpolatedValues();
@@ -277,11 +277,11 @@ bool RimSummaryCalculation::calculate()
{
RimSummaryCalculationVariable* v = m_variables[i];
parser.assignVector(v->name(), timeHistoryCurveMerger.interpolatedCurveValuesForAllTimeSteps(i));
parser.assignVector(v->name(), timeHistoryCurveMerger.interpolatedYValuesForAllXValues(i));
}
std::vector<double> resultValues;
resultValues.resize(timeHistoryCurveMerger.allTimeSteps().size());
resultValues.resize(timeHistoryCurveMerger.allXValues().size());
parser.assignVector(leftHandSideVariableName, resultValues);
@@ -293,16 +293,16 @@ bool RimSummaryCalculation::calculate()
m_timesteps.v().clear();
m_calculatedValues.v().clear();
if (timeHistoryCurveMerger.validIntervalsForAllTimeSteps().size() > 0)
if (timeHistoryCurveMerger.validIntervalsForAllXValues().size() > 0)
{
size_t firstValidTimeStep = timeHistoryCurveMerger.validIntervalsForAllTimeSteps().front().first;
size_t lastValidTimeStep = timeHistoryCurveMerger.validIntervalsForAllTimeSteps().back().second + 1;
size_t firstValidTimeStep = timeHistoryCurveMerger.validIntervalsForAllXValues().front().first;
size_t lastValidTimeStep = timeHistoryCurveMerger.validIntervalsForAllXValues().back().second + 1;
if (lastValidTimeStep > firstValidTimeStep &&
lastValidTimeStep <= timeHistoryCurveMerger.allTimeSteps().size())
lastValidTimeStep <= timeHistoryCurveMerger.allXValues().size())
{
std::vector<time_t> validTimeSteps(timeHistoryCurveMerger.allTimeSteps().begin() + firstValidTimeStep,
timeHistoryCurveMerger.allTimeSteps().begin() + lastValidTimeStep);
std::vector<time_t> validTimeSteps(timeHistoryCurveMerger.allXValues().begin() + firstValidTimeStep,
timeHistoryCurveMerger.allXValues().begin() + lastValidTimeStep);
std::vector<double> validValues(resultValues.begin() + firstValidTimeStep,

View File

@@ -1,22 +1,21 @@
/////////////////////////////////////////////////////////////////////////////////
//
// 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>
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RimWellLogRftCurve.h"
#include "RiaApplication.h"
@@ -37,6 +36,8 @@
#include "RimEclipseResultCase.h"
#include "RimMainPlotCollection.h"
#include "RimProject.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimTools.h"
#include "RimWellLogPlot.h"
#include "RimWellLogPlotCollection.h"
@@ -60,26 +61,31 @@
namespace caf
{
template<>
void caf::AppEnum< RifEclipseRftAddress::RftWellLogChannelType >::setUp()
{
addItem(RifEclipseRftAddress::NONE, "NONE", "None");
addItem(RifEclipseRftAddress::DEPTH, "DEPTH", "Depth");
addItem(RifEclipseRftAddress::PRESSURE, "PRESSURE", "Pressure");
addItem(RifEclipseRftAddress::SWAT, "SWAT", "Water Saturation");
addItem(RifEclipseRftAddress::SOIL, "SOIL", "Oil Saturation");
addItem(RifEclipseRftAddress::SGAS, "SGAS", "Gas Saturation");
addItem(RifEclipseRftAddress::WRAT, "WRAT", "Water Flow");
addItem(RifEclipseRftAddress::ORAT, "ORAT", "Oil Flow");
addItem(RifEclipseRftAddress::GRAT, "GRAT", "Gas flow");
setDefault(RifEclipseRftAddress::NONE);
}
template<>
void caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::setUp()
{
addItem(RifEclipseRftAddress::NONE, "NONE", "None");
addItem(RifEclipseRftAddress::TVD, "DEPTH", "Depth");
addItem(RifEclipseRftAddress::PRESSURE, "PRESSURE", "Pressure");
addItem(RifEclipseRftAddress::SWAT, "SWAT", "Water Saturation");
addItem(RifEclipseRftAddress::SOIL, "SOIL", "Oil Saturation");
addItem(RifEclipseRftAddress::SGAS, "SGAS", "Gas Saturation");
addItem(RifEclipseRftAddress::WRAT, "WRAT", "Water Flow");
addItem(RifEclipseRftAddress::ORAT, "ORAT", "Oil Flow");
addItem(RifEclipseRftAddress::GRAT, "GRAT", "Gas flow");
addItem(RifEclipseRftAddress::MD, "MD", "Measured Depth");
addItem(RifEclipseRftAddress::PRESSURE_P10, "PRESSURE_P10", "Pressure P10");
addItem(RifEclipseRftAddress::PRESSURE_P50, "PRESSURE_P50", "Pressure P50");
addItem(RifEclipseRftAddress::PRESSURE_P90, "PRESSURE_P90", "Pressure P90");
addItem(RifEclipseRftAddress::PRESSURE_MEAN, "PRESSURE_MEAN", "Pressure Mean");
setDefault(RifEclipseRftAddress::NONE);
}
} // namespace caf
CAF_PDM_SOURCE_INIT(RimWellLogRftCurve, "WellLogRftCurve");
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RimWellLogRftCurve::RimWellLogRftCurve()
{
@@ -88,12 +94,23 @@ RimWellLogRftCurve::RimWellLogRftCurve()
CAF_PDM_InitFieldNoDefault(&m_eclipseResultCase, "CurveEclipseResultCase", "Eclipse Result Case", "", "", "");
m_eclipseResultCase.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_summaryCase, "CurveSummaryCase", "Summary Case", "", "", "");
m_summaryCase.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_ensemble, "CurveEnsemble", "Ensemble", "", "", "");
m_ensemble.uiCapability()->setUiTreeChildrenHidden(true);
CAF_PDM_InitFieldNoDefault(&m_timeStep, "TimeStep", "Time Step", "", "", "");
CAF_PDM_InitFieldNoDefault(&m_wellName, "WellName", "Well Name", "", "", "");
CAF_PDM_InitField(&m_branchIndex, "BranchIndex", 0, "Branch Index", "", "", "");
CAF_PDM_InitField(&m_branchDetection, "BranchDetection", true, "Branch Detection", "",
"Compute branches based on how simulation well cells are organized", "");
CAF_PDM_InitField(&m_branchDetection,
"BranchDetection",
true,
"Branch Detection",
"",
"Compute branches based on how simulation well cells are organized",
"");
CAF_PDM_InitFieldNoDefault(&m_wellLogChannelName, "WellLogChannelName", "Well Property", "", "", "");
@@ -101,14 +118,12 @@ RimWellLogRftCurve::RimWellLogRftCurve()
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RimWellLogRftCurve::~RimWellLogRftCurve()
{
}
RimWellLogRftCurve::~RimWellLogRftCurve() {}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogRftCurve::wellName() const
{
@@ -116,7 +131,7 @@ QString RimWellLogRftCurve::wellName() const
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogRftCurve::wellLogChannelName() const
{
@@ -124,7 +139,7 @@ QString RimWellLogRftCurve::wellLogChannelName() const
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::setEclipseResultCase(RimEclipseResultCase* eclipseResultCase)
{
@@ -132,7 +147,7 @@ void RimWellLogRftCurve::setEclipseResultCase(RimEclipseResultCase* eclipseResul
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RimEclipseResultCase* RimWellLogRftCurve::eclipseResultCase() const
{
@@ -140,12 +155,44 @@ RimEclipseResultCase* RimWellLogRftCurve::eclipseResultCase() const
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::setSummaryCase(RimSummaryCase* summaryCase)
{
m_summaryCase = summaryCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCase* RimWellLogRftCurve::summaryCase() const
{
return m_summaryCase;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::setEnsemble(RimSummaryCaseCollection* ensemble)
{
m_ensemble = ensemble;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RimSummaryCaseCollection* RimWellLogRftCurve::ensemble() const
{
return m_ensemble;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::setRftAddress(RifEclipseRftAddress address)
{
m_timeStep = address.timeStep();
m_wellName = address.wellName();
m_timeStep = address.timeStep();
m_wellName = address.wellName();
m_wellLogChannelName = address.wellLogChannel();
}
@@ -158,21 +205,21 @@ RifEclipseRftAddress RimWellLogRftCurve::rftAddress() const
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::setDefaultAddress(QString wellName)
{
RifReaderEclipseRft* reader = rftReader();
RifReaderRftInterface* reader = rftReader();
if (!reader) return;
bool wellNameHasRftData = false;
std::set<QString> wellNames = reader->wellNames();
bool wellNameHasRftData = false;
std::set<QString> wellNames = reader->wellNames();
for (const QString& wellNameWithRft : wellNames)
{
if (wellName == wellNameWithRft)
{
wellNameHasRftData = true;
m_wellName = wellName;
m_wellName = wellName;
break;
}
}
@@ -180,16 +227,16 @@ void RimWellLogRftCurve::setDefaultAddress(QString wellName)
if (!wellNameHasRftData)
{
m_wellLogChannelName = RifEclipseRftAddress::NONE;
m_timeStep = QDateTime();
m_timeStep = QDateTime();
return;
}
m_wellLogChannelName = RifEclipseRftAddress::PRESSURE;
std::vector<QDateTime> timeSteps = reader->availableTimeSteps(m_wellName, m_wellLogChannelName());
if (timeSteps.size() > 0)
std::set<QDateTime> timeSteps = reader->availableTimeSteps(m_wellName, m_wellLogChannelName());
if (!timeSteps.empty())
{
m_timeStep = timeSteps[0];
m_timeStep = *(timeSteps.begin());
}
else
{
@@ -198,7 +245,7 @@ void RimWellLogRftCurve::setDefaultAddress(QString wellName)
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::updateWellChannelNameAndTimeStep()
{
@@ -208,43 +255,43 @@ void RimWellLogRftCurve::updateWellChannelNameAndTimeStep()
return;
}
RifReaderEclipseRft* reader = rftReader();
RifReaderRftInterface* reader = rftReader();
if (!reader) return;
std::vector<RifEclipseRftAddress::RftWellLogChannelType> channelNames = reader->availableWellLogChannels(m_wellName);
std::set<RifEclipseRftAddress::RftWellLogChannelType> channelNames = reader->availableWellLogChannels(m_wellName);
if (channelNames.empty())
{
m_wellLogChannelName = RifEclipseRftAddress::NONE;
}
else if (std::find(channelNames.begin(), channelNames.end(), m_wellLogChannelName()) == channelNames.end())
else if (!channelNames.count(m_wellLogChannelName()))
{
m_wellLogChannelName = RifEclipseRftAddress::PRESSURE;
}
std::vector<QDateTime> timeSteps = reader->availableTimeSteps(m_wellName, m_wellLogChannelName());
std::set<QDateTime> timeSteps = reader->availableTimeSteps(m_wellName, m_wellLogChannelName());
if (timeSteps.empty())
{
m_timeStep = QDateTime();
}
else if (std::find(timeSteps.begin(), timeSteps.end(), m_timeStep()) == timeSteps.end())
else if (!timeSteps.count(m_timeStep()))
{
m_timeStep = timeSteps[0];
m_timeStep = *(timeSteps.begin());
}
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::setSimWellBranchData(bool branchDetection, int branchIndex)
{
m_branchDetection = branchDetection;
m_branchIndex = branchIndex;
m_branchIndex = branchIndex;
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
QString RimWellLogRftCurve::createCurveAutoName()
{
@@ -261,12 +308,21 @@ QString RimWellLogRftCurve::createCurveAutoName()
{
name.push_back(m_eclipseResultCase->caseUserDescription());
}
else if (m_summaryCase)
{
name.push_back(m_summaryCase->caseName());
}
else if (m_ensemble)
{
name.push_back(m_ensemble->name());
}
if (wellLogChannelName() != caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::text(RifEclipseRftAddress::NONE))
{
RifEclipseRftAddress::RftWellLogChannelType channelNameEnum = caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::fromText(wellLogChannelName());
{
RifEclipseRftAddress::RftWellLogChannelType channelNameEnum =
caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::fromText(wellLogChannelName());
name.push_back(caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::uiText(channelNameEnum));
}
if ( !m_timeStep().isNull())
if (!m_timeStep().isNull())
{
name.push_back(m_timeStep().toString(RiaQDateTimeTools::dateFormatString()));
}
@@ -275,14 +331,14 @@ QString RimWellLogRftCurve::createCurveAutoName()
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::onLoadDataAndUpdate(bool updateParentPlot)
{
this->RimPlotCurve::updateCurvePresentation(updateParentPlot);
m_isUsingPseudoLength = false;
if (isCurveVisible())
{
m_curveData = new RigWellLogCurveData;
@@ -292,18 +348,41 @@ void RimWellLogRftCurve::onLoadDataAndUpdate(bool updateParentPlot)
CVF_ASSERT(wellLogPlot);
std::vector<double> measuredDepthVector = measuredDepthValues();
std::vector<double> tvDepthVector = tvDepthValues();
std::vector<double> values = xValues();
std::vector<double> tvDepthVector = tvDepthValues();
std::vector<double> values = xValues();
if (values.empty() ||
values.size() != tvDepthVector.size() ||
values.size() != measuredDepthVector.size())
if (values.empty() || values.size() != tvDepthVector.size())
{
this->detachQwtCurve();
return;
}
m_curveData->setValuesWithTVD(values, measuredDepthVector, tvDepthVector, RiaEclipseUnitTools::depthUnit(m_eclipseResultCase->eclipseCaseData()->unitsType()), false);
RiaEclipseUnitTools::UnitSystem unitSystem = RiaEclipseUnitTools::UNITS_METRIC;
if (m_eclipseResultCase)
{
unitSystem = m_eclipseResultCase->eclipseCaseData()->unitsType();
}
else if (m_summaryCase)
{
unitSystem = m_summaryCase->unitsSystem();
}
else if (m_ensemble)
{
unitSystem = m_ensemble->unitSystem();
}
else
{
CVF_ASSERT(false && "Need to have either an eclipse result case, a summary case or an ensemble");
}
if (tvDepthVector.size() != measuredDepthVector.size())
{
m_isUsingPseudoLength = true;
measuredDepthVector = tvDepthVector;
}
m_curveData->setValuesWithTVD(
values, measuredDepthVector, tvDepthVector, RiaEclipseUnitTools::depthUnit(unitSystem), false);
RiaDefines::DepthUnitType displayUnit = RiaDefines::UNIT_METER;
if (wellLogPlot)
@@ -313,11 +392,15 @@ void RimWellLogRftCurve::onLoadDataAndUpdate(bool updateParentPlot)
if (wellLogPlot->depthType() == RimWellLogPlot::MEASURED_DEPTH)
{
m_qwtPlotCurve->setSamples(m_curveData->xPlotValues().data(), m_curveData->measuredDepthPlotValues(displayUnit).data(), static_cast<int>(m_curveData->xPlotValues().size()));
m_qwtPlotCurve->setSamples(m_curveData->xPlotValues().data(),
m_curveData->measuredDepthPlotValues(displayUnit).data(),
static_cast<int>(m_curveData->xPlotValues().size()));
}
else
{
m_qwtPlotCurve->setSamples(m_curveData->xPlotValues().data(), m_curveData->trueDepthPlotValues(displayUnit).data(), static_cast<int>(m_curveData->xPlotValues().size()));
m_qwtPlotCurve->setSamples(m_curveData->xPlotValues().data(),
m_curveData->trueDepthPlotValues(displayUnit).data(),
static_cast<int>(m_curveData->xPlotValues().size()));
m_isUsingPseudoLength = false;
}
@@ -349,7 +432,7 @@ void RimWellLogRftCurve::onLoadDataAndUpdate(bool updateParentPlot)
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering)
{
@@ -359,10 +442,8 @@ void RimWellLogRftCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderi
curveDataGroup->add(&m_eclipseResultCase);
curveDataGroup->add(&m_wellName);
RiaSimWellBranchTools::appendSimWellBranchFieldsIfRequiredFromWellName(curveDataGroup,
m_wellName,
m_branchDetection,
m_branchIndex);
RiaSimWellBranchTools::appendSimWellBranchFieldsIfRequiredFromWellName(
curveDataGroup, m_wellName, m_branchDetection, m_branchIndex);
curveDataGroup->add(&m_wellLogChannelName);
curveDataGroup->add(&m_timeStep);
@@ -378,9 +459,10 @@ void RimWellLogRftCurve::defineUiOrdering(QString uiConfigName, caf::PdmUiOrderi
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
QList<caf::PdmOptionItemInfo> RimWellLogRftCurve::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly)
QList<caf::PdmOptionItemInfo> RimWellLogRftCurve::calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions,
bool* useOptionsOnly)
{
QList<caf::PdmOptionItemInfo> options;
@@ -397,7 +479,7 @@ QList<caf::PdmOptionItemInfo> RimWellLogRftCurve::calculateValueOptions(const ca
else if (fieldNeedingOptions == &m_wellName)
{
options.push_back(caf::PdmOptionItemInfo("None", ""));
RifReaderEclipseRft* reader = rftReader();
RifReaderRftInterface* reader = rftReader();
if (reader)
{
std::set<QString> wellNames = reader->wellNames();
@@ -409,26 +491,29 @@ QList<caf::PdmOptionItemInfo> RimWellLogRftCurve::calculateValueOptions(const ca
}
else if (fieldNeedingOptions == &m_wellLogChannelName)
{
RifReaderEclipseRft* reader = rftReader();
RifReaderRftInterface* reader = rftReader();
if (reader)
{
for (const RifEclipseRftAddress::RftWellLogChannelType& channelName : reader->availableWellLogChannels(m_wellName))
{
options.push_back(caf::PdmOptionItemInfo(caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::uiText(channelName), channelName));
options.push_back(caf::PdmOptionItemInfo(
caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::uiText(channelName), channelName));
}
}
if (options.empty())
{
options.push_back(caf::PdmOptionItemInfo(caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::uiText(RifEclipseRftAddress::NONE), RifEclipseRftAddress::NONE));
options.push_back(caf::PdmOptionItemInfo(
caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::uiText(RifEclipseRftAddress::NONE),
RifEclipseRftAddress::NONE));
}
}
else if (fieldNeedingOptions == &m_timeStep)
{
RifReaderEclipseRft* reader = rftReader();
RifReaderRftInterface* reader = rftReader();
if (reader)
{
QString dateFormat = "dd MMM yyyy";
std::vector<QDateTime> timeStamps = reader->availableTimeSteps(m_wellName, m_wellLogChannelName());
QString dateFormat = "dd MMM yyyy";
std::set<QDateTime> timeStamps = reader->availableTimeSteps(m_wellName, m_wellLogChannelName());
for (const QDateTime& dt : timeStamps)
{
QString dateString = RiaQDateTimeTools::toStringUsingApplicationLocale(dt, dateFormat);
@@ -441,7 +526,7 @@ QList<caf::PdmOptionItemInfo> RimWellLogRftCurve::calculateValueOptions(const ca
}
else if (fieldNeedingOptions == &m_branchIndex)
{
auto simulationWellBranches =
auto simulationWellBranches =
RiaSimWellBranchTools::simulationWellBranches(RimWellPlotTools::simWellName(m_wellName), m_branchDetection);
options = RiaSimWellBranchTools::valueOptionsForBranchIndexField(simulationWellBranches);
@@ -451,17 +536,19 @@ QList<caf::PdmOptionItemInfo> RimWellLogRftCurve::calculateValueOptions(const ca
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
void RimWellLogRftCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue)
void RimWellLogRftCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
const QVariant& oldValue,
const QVariant& newValue)
{
m_idxInWellPathToIdxInRftFile.clear();
RimWellLogCurve::fieldChangedByUi(changedField, oldValue, newValue);
if (changedField == &m_eclipseResultCase)
{
m_timeStep = QDateTime();
m_wellName = "";
m_timeStep = QDateTime();
m_wellName = "";
m_wellLogChannelName = RifEclipseRftAddress::NONE;
this->loadDataAndUpdate(true);
@@ -473,8 +560,7 @@ void RimWellLogRftCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedFiel
updateWellChannelNameAndTimeStep();
this->loadDataAndUpdate(true);
}
else if (changedField == &m_branchDetection ||
changedField == &m_branchIndex)
else if (changedField == &m_branchDetection || changedField == &m_branchIndex)
{
QString simWellName = RimWellPlotTools::simWellName(m_wellName);
@@ -498,24 +584,32 @@ void RimWellLogRftCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedFiel
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RifReaderEclipseRft* RimWellLogRftCurve::rftReader() const
RifReaderRftInterface* RimWellLogRftCurve::rftReader() const
{
if (!m_eclipseResultCase()) return nullptr;
return m_eclipseResultCase()->rftReader();
if (m_eclipseResultCase())
{
return m_eclipseResultCase()->rftReader();
}
else if (m_summaryCase())
{
return m_summaryCase()->rftReader();
}
else if (m_ensemble())
{
return m_ensemble()->rftStatisticsReader();
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
RigEclipseWellLogExtractor* RimWellLogRftCurve::extractor()
{
if (!m_eclipseResultCase()) return nullptr;
RifReaderEclipseRft* reader = rftReader();
RifReaderRftInterface* reader = rftReader();
if (!reader) return nullptr;
RimMainPlotCollection* mainPlotCollection;
this->firstAncestorOrThisOfTypeAsserted(mainPlotCollection);
@@ -525,13 +619,13 @@ RigEclipseWellLogExtractor* RimWellLogRftCurve::extractor()
RigEclipseWellLogExtractor* eclExtractor = nullptr;
RimProject* proj = RiaApplication::instance()->project();
RimProject* proj = RiaApplication::instance()->project();
RimWellPath* wellPath = proj->wellPathFromSimWellName(m_wellName());
eclExtractor = wellLogCollection->findOrCreateExtractor(wellPath, m_eclipseResultCase);
eclExtractor = wellLogCollection->findOrCreateExtractor(wellPath, m_eclipseResultCase);
if (!eclExtractor)
{
QString simWellName = RimWellPlotTools::simWellName(m_wellName);
QString simWellName = RimWellPlotTools::simWellName(m_wellName);
std::vector<const RigWellPath*> wellPaths = RiaSimWellBranchTools::simulationWellBranches(simWellName, m_branchDetection);
if (wellPaths.size() == 0) return nullptr;
@@ -539,10 +633,8 @@ RigEclipseWellLogExtractor* RimWellLogRftCurve::extractor()
auto wellPathBranch = wellPaths[m_branchIndex];
eclExtractor = wellLogCollection->findOrCreateSimWellExtractor(simWellName,
QString("Find or create sim well extractor"),
wellPathBranch,
m_eclipseResultCase->eclipseCaseData());
eclExtractor = wellLogCollection->findOrCreateSimWellExtractor(
simWellName, QString("Find or create sim well extractor"), wellPathBranch, m_eclipseResultCase->eclipseCaseData());
m_isUsingPseudoLength = true;
}
@@ -550,7 +642,7 @@ RigEclipseWellLogExtractor* RimWellLogRftCurve::extractor()
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
bool RimWellLogRftCurve::createWellPathIdxToRftFileIdxMapping()
{
@@ -573,16 +665,19 @@ bool RimWellLogRftCurve::createWellPathIdxToRftFileIdxMapping()
globCellIndicesToIndexInWell[intersections[idx].globCellIndex] = idx;
}
RifEclipseRftAddress depthAddress(m_wellName(), m_timeStep, RifEclipseRftAddress::DEPTH);
RifEclipseRftAddress depthAddress(m_wellName(), m_timeStep, RifEclipseRftAddress::TVD);
std::vector<caf::VecIjk> rftIndices;
rftReader()->cellIndices(depthAddress, &rftIndices);
RifReaderEclipseRft* eclipseRftReader = dynamic_cast<RifReaderEclipseRft*>(rftReader());
if (!eclipseRftReader) return false;
eclipseRftReader->cellIndices(depthAddress, &rftIndices);
const RigMainGrid* mainGrid = eclExtractor->caseData()->mainGrid();
for (size_t idx = 0; idx < rftIndices.size(); idx++)
{
caf::VecIjk ijkIndex = rftIndices[idx];
size_t globalCellIndex = mainGrid->cellIndexFromIJK(ijkIndex.i(), ijkIndex.j(), ijkIndex.k());
caf::VecIjk ijkIndex = rftIndices[idx];
size_t globalCellIndex = mainGrid->cellIndexFromIJK(ijkIndex.i(), ijkIndex.j(), ijkIndex.k());
if (globCellIndicesToIndexInWell.find(globalCellIndex) != globCellIndicesToIndexInWell.end())
{
@@ -594,7 +689,7 @@ bool RimWellLogRftCurve::createWellPathIdxToRftFileIdxMapping()
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
size_t RimWellLogRftCurve::rftFileIndex(size_t wellPathIndex)
{
@@ -612,7 +707,7 @@ size_t RimWellLogRftCurve::rftFileIndex(size_t wellPathIndex)
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
std::vector<size_t> RimWellLogRftCurve::sortedIndicesInRftFile()
{
@@ -631,19 +726,19 @@ std::vector<size_t> RimWellLogRftCurve::sortedIndicesInRftFile()
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimWellLogRftCurve::xValues()
{
RifReaderEclipseRft* reader = rftReader();
std::vector<double> values;
RifReaderRftInterface* reader = rftReader();
std::vector<double> values;
if (!reader) return values;
RifEclipseRftAddress address(m_wellName(), m_timeStep, m_wellLogChannelName());
reader->values(address, &values);
bool wellPathExists = createWellPathIdxToRftFileIdxMapping();
if (wellPathExists)
@@ -657,7 +752,7 @@ std::vector<double> RimWellLogRftCurve::xValues()
valuesSorted.push_back((values.at(idx)));
}
}
return valuesSorted;
}
else
@@ -667,16 +762,16 @@ std::vector<double> RimWellLogRftCurve::xValues()
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimWellLogRftCurve::tvDepthValues()
{
RifReaderEclipseRft* reader = rftReader();
std::vector<double> values;
RifReaderRftInterface* reader = rftReader();
std::vector<double> values;
if (!reader) return values;
RifEclipseRftAddress depthAddress(m_wellName(), m_timeStep, RifEclipseRftAddress::DEPTH);
RifEclipseRftAddress depthAddress(m_wellName(), m_timeStep, RifEclipseRftAddress::TVD);
reader->values(depthAddress, &values);
bool wellPathExists = createWellPathIdxToRftFileIdxMapping();
@@ -702,38 +797,37 @@ std::vector<double> RimWellLogRftCurve::tvDepthValues()
}
//--------------------------------------------------------------------------------------------------
///
///
//--------------------------------------------------------------------------------------------------
std::vector<double> RimWellLogRftCurve::measuredDepthValues()
{
std::vector<double> measuredDepthForCells;
RigEclipseWellLogExtractor* eclExtractor = extractor();
if (!eclExtractor) return measuredDepthForCells;
std::vector<double> measuredDepthForIntersections = eclExtractor->cellIntersectionMDs();
if (measuredDepthForIntersections.empty())
{
return measuredDepthForCells;
}
std::vector< size_t> globCellIndices = eclExtractor->intersectedCellsGlobIdx();
std::vector<size_t> globCellIndices = eclExtractor->intersectedCellsGlobIdx();
for (size_t i = 0; i < globCellIndices.size() - 1; i = i + 2)
{
double sum = measuredDepthForIntersections[i] + measuredDepthForIntersections[i + 1];
measuredDepthForCells.push_back( sum / 2.0 );
measuredDepthForCells.push_back(sum / 2.0);
}
std::vector<double> measuredDepthForCellsWhichHasRftData;
for (size_t i = 0; i < measuredDepthForCells.size(); i++)
{
if(rftFileIndex(i) != cvf::UNDEFINED_SIZE_T)
if (rftFileIndex(i) != cvf::UNDEFINED_SIZE_T)
{
measuredDepthForCellsWhichHasRftData.push_back(measuredDepthForCells[i]);
}

View File

@@ -31,9 +31,11 @@
#include <map>
class RifReaderEclipseRft;
class RifReaderRftInterface;
class RigEclipseWellLogExtractor;
class RimEclipseResultCase;
class RimSummaryCase;
class RimSummaryCaseCollection;
class RimWellPath;
//==================================================================================================
@@ -54,6 +56,12 @@ public:
void setEclipseResultCase(RimEclipseResultCase* eclipseResultCase);
RimEclipseResultCase* eclipseResultCase() const;
void setSummaryCase(RimSummaryCase* summaryCase);
RimSummaryCase* summaryCase() const;
void setEnsemble(RimSummaryCaseCollection* ensemble);
RimSummaryCaseCollection* ensemble() const;
void setRftAddress(RifEclipseRftAddress address);
RifEclipseRftAddress rftAddress() const;
@@ -73,7 +81,7 @@ protected:
void fieldChangedByUi(const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) override;
private:
RifReaderEclipseRft* rftReader() const;
RifReaderRftInterface* rftReader() const;
RigEclipseWellLogExtractor* extractor();
@@ -86,11 +94,13 @@ private:
std::vector<double> measuredDepthValues();
private:
caf::PdmPtrField<RimEclipseResultCase*> m_eclipseResultCase;
caf::PdmField<QDateTime> m_timeStep;
caf::PdmField<QString> m_wellName;
caf::PdmField<int> m_branchIndex;
caf::PdmField<bool> m_branchDetection;
caf::PdmPtrField<RimEclipseResultCase*> m_eclipseResultCase;
caf::PdmPtrField<RimSummaryCase*> m_summaryCase;
caf::PdmPtrField<RimSummaryCaseCollection*> m_ensemble;
caf::PdmField<QDateTime> m_timeStep;
caf::PdmField<QString> m_wellName;
caf::PdmField<int> m_branchIndex;
caf::PdmField<bool> m_branchDetection;
std::map<size_t, size_t> m_idxInWellPathToIdxInRftFile;
bool m_isUsingPseudoLength;

View File

@@ -110,3 +110,11 @@ RimSummaryCalculation* RifCalculatedSummaryCurveReader::findCalculationByName(co
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RifCalculatedSummaryCurveReader::unitSystem() const
{
return RiaEclipseUnitTools::UNITS_UNKNOWN;
}

View File

@@ -44,6 +44,9 @@ public:
RimSummaryCalculation* findCalculationByName(const RifEclipseSummaryAddress& resultAddress) const;
RiaEclipseUnitTools::UnitSystem unitSystem() const override;
private:
caf::PdmPointer<RimSummaryCalculationCollection> m_calculationCollection;
};

View File

@@ -20,7 +20,7 @@
#include "RiaLogging.h"
#include "RiaSummaryTools.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RiaCurveMerger.h"
#include "RifDerivedEnsembleReader.h"
@@ -151,14 +151,14 @@ void RimDerivedEnsembleCase::calculate(const RifEclipseSummaryAddress& address)
reader1->values(address, &values1);
reader2->values(address, &values2);
merger.addCurveData(values1, reader1->timeSteps(address));
merger.addCurveData(values2, reader2->timeSteps(address));
merger.addCurveData(reader1->timeSteps(address), values1);
merger.addCurveData(reader2->timeSteps(address), values2);
merger.computeInterpolatedValues();
std::vector<double>& allValues1 = merger.interpolatedCurveValuesForAllTimeSteps(0);
std::vector<double>& allValues2 = merger.interpolatedCurveValuesForAllTimeSteps(1);
std::vector<double>& allValues1 = merger.interpolatedYValuesForAllXValues(0);
std::vector<double>& allValues2 = merger.interpolatedYValuesForAllXValues(1);
size_t sampleCount = merger.allTimeSteps().size();
size_t sampleCount = merger.allXValues().size();
std::vector<double> calculatedValues;
calculatedValues.reserve(sampleCount);
for (size_t i = 0; i < sampleCount; i++)
@@ -174,7 +174,7 @@ void RimDerivedEnsembleCase::calculate(const RifEclipseSummaryAddress& address)
}
auto& dataItem = m_data[address];
dataItem.first = merger.allTimeSteps();
dataItem.first = merger.allXValues();
dataItem.second = calculatedValues;
}

View File

@@ -17,7 +17,6 @@
/////////////////////////////////////////////////////////////////////////////////
#include "RiaApplication.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "SummaryPlotCommands/RicNewDerivedEnsembleFeature.h"

View File

@@ -28,7 +28,6 @@
#include "RifReaderEclipseSummary.h"
#include "RigStatisticsMath.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimEnsembleCurveFilter.h"

View File

@@ -21,7 +21,6 @@
#include "RifSummaryReaderInterface.h"
#include "RigStatisticsMath.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RimEnsembleCurveSet.h"
#include "RimSummaryCase.h"

View File

@@ -21,7 +21,6 @@
#include "RifEnsembleStatisticsReader.h"
#include "RigStatisticsMath.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RiaTimeHistoryCurveResampler.h"
#include "RimEnsembleCurveSet.h"
@@ -173,14 +172,25 @@ void RimEnsembleStatisticsCase::calculate(const std::vector<RimSummaryCase*> sum
}
double p10, p50, p90, mean;
calculateStatistics(valuesAtTimeStep, &p10, &p50, &p90, &mean);
RigStatisticsMath::calculateStatisticsCurves(valuesAtTimeStep, &p10, &p50, &p90, &mean);
if (p10 != DOUBLE_INF) m_p10Data.push_back(p10);
if (p50 != DOUBLE_INF) m_p50Data.push_back(p50);
if (p90 != DOUBLE_INF) m_p90Data.push_back(p90);
if (p10 != HUGE_VAL) m_p10Data.push_back(p10);
if (p50 != HUGE_VAL) m_p50Data.push_back(p50);
if (p90 != HUGE_VAL) m_p90Data.push_back(p90);
m_meanData.push_back(mean);
}
m_addressUsedInLastCalculation = inputAddress;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RimEnsembleStatisticsCase::unitSystem() const
{
if (m_curveSet)
{
return m_curveSet->summaryCaseCollection()->unitSystem();
}
return RiaEclipseUnitTools::UNITS_UNKNOWN;
}
//--------------------------------------------------------------------------------------------------
@@ -193,7 +203,6 @@ void RimEnsembleStatisticsCase::clearData()
m_p50Data.clear();
m_p90Data.clear();
m_meanData.clear();
m_addressUsedInLastCalculation = RifEclipseSummaryAddress();
}
//--------------------------------------------------------------------------------------------------
@@ -239,57 +248,3 @@ std::vector<RimSummaryCase*> RimEnsembleStatisticsCase::validSummaryCases(const
return validCases;
}
//--------------------------------------------------------------------------------------------------
/// Algorithm:
/// https://en.wikipedia.org/wiki/Percentile#Third_variant,_'%22%60UNIQ--postMath-00000052-QINU%60%22'
//--------------------------------------------------------------------------------------------------
void RimEnsembleStatisticsCase::calculateStatistics(const std::vector<double>& values, double* p10, double* p50, double* p90, double* mean)
{
CVF_ASSERT(p10 && p50 && p90 && mean);
enum PValue { P10, P50, P90 };
std::vector<double> sortedValues;
double valueSum = 0;
{
std::multiset<double> vSet(values.begin(), values.end());
for (double v : vSet)
{
if (RiaStatisticsTools::isValidNumber(v))
{
sortedValues.push_back(v);
valueSum += v;
}
}
}
int valueCount = (int)sortedValues.size();
double percentiles[] = { 0.1, 0.5, 0.9 };
double pValues[] = { DOUBLE_INF, DOUBLE_INF, DOUBLE_INF };
for (int i = P10; i <= P90; i++)
{
// Check valid params
if ((percentiles[i] < 1.0 / ((double)valueCount + 1)) || (percentiles[i] > (double)valueCount / ((double)valueCount + 1))) continue;
double rank = percentiles[i] * (valueCount + 1) - 1;
double rankInt;
double rankFrac = std::modf(rank, &rankInt);
if (rankInt < valueCount - 1)
{
pValues[i] = sortedValues[rankInt] + rankFrac * (sortedValues[rankInt + 1] - sortedValues[rankInt]);
}
else
{
pValues[i] = sortedValues[rankInt];
}
}
*p10 = pValues[P10];
*p50 = pValues[P50];
*p90 = pValues[P90];
*mean = valueSum / valueCount;
}

View File

@@ -19,6 +19,7 @@
#pragma once
#include "RiaEclipseUnitTools.h"
#include "RifEclipseSummaryAddress.h"
#include "RimSummaryCase.h"
@@ -55,12 +56,12 @@ public:
const RimEnsembleCurveSet* curveSet() const;
void calculate(const std::vector<RimSummaryCase*>& sumCases);
RiaEclipseUnitTools::UnitSystem unitSystem() const;
private:
void calculate(const std::vector<RimSummaryCase*> sumCases, const RifEclipseSummaryAddress& inputAddress);
void clearData();
void clearData();
std::vector<RimSummaryCase*> validSummaryCases(const std::vector<RimSummaryCase*> allSumCases, const RifEclipseSummaryAddress& inputAddress);
void calculateStatistics(const std::vector<double>& values, double* p10, double* p50, double* p90, double* mean);
private:
std::unique_ptr<RifEnsembleStatisticsReader> m_statisticsReader;
@@ -72,5 +73,4 @@ private:
std::vector<double> m_p90Data;
std::vector<double> m_meanData;
RifEclipseSummaryAddress m_addressUsedInLastCalculation;
};

View File

@@ -22,6 +22,7 @@
#include "RifEclipseSummaryTools.h"
#include "RifReaderEclipseSummary.h"
#include "RifReaderEclipseRft.h"
#include "RimTools.h"
@@ -42,6 +43,7 @@ CAF_PDM_SOURCE_INIT(RimFileSummaryCase,"FileSummaryCase");
RimFileSummaryCase::RimFileSummaryCase()
{
CAF_PDM_InitField(&m_includeRestartFiles, "IncludeRestartFiles", false, "Include Restart Files", "", "", "");
m_includeRestartFiles.uiCapability()->setUiHidden(true);
}
@@ -84,7 +86,12 @@ void RimFileSummaryCase::updateFilePathsFromProjectPath(const QString & newProje
//--------------------------------------------------------------------------------------------------
void RimFileSummaryCase::createSummaryReaderInterface()
{
m_summaryFileReader = RimFileSummaryCase::findRelatedFilesAndCreateReader(this->summaryHeaderFilename(), m_includeRestartFiles);
m_summaryFileReader = RimFileSummaryCase::findRelatedFilesAndCreateReader(this->summaryHeaderFilename(), m_includeRestartFiles);
m_summaryEclipseRftReader = RimFileSummaryCase::findRftDataAndCreateReader(this->summaryHeaderFilename());
if (m_summaryEclipseRftReader.notNull())
{
RiaLogging::info(QString("Found RFT Data for %1").arg(this->summaryHeaderFilename()));
}
}
//--------------------------------------------------------------------------------------------------
@@ -105,6 +112,26 @@ RifReaderEclipseSummary* RimFileSummaryCase::findRelatedFilesAndCreateReader(con
return summaryFileReader;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderEclipseRft* RimFileSummaryCase::findRftDataAndCreateReader(const QString& headerFileName)
{
QFileInfo fileInfo(headerFileName);
QString folder = fileInfo.absolutePath();
QString rftFileName = folder + "/" + fileInfo.completeBaseName() + ".RFT";
QFileInfo rftFileInfo(rftFileName);
if (rftFileInfo.exists())
{
std::unique_ptr<RifReaderEclipseRft> rftReader(new RifReaderEclipseRft(rftFileInfo.filePath()));
return rftReader.release();
}
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -113,6 +140,14 @@ RifSummaryReaderInterface* RimFileSummaryCase::summaryReader()
return m_summaryFileReader.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderRftInterface* RimFileSummaryCase::rftReader()
{
return m_summaryEclipseRftReader.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -22,6 +22,8 @@
#include "cvfObject.h"
#include "cafPdmField.h"
class RifReaderRftInterface;
class RifReaderEclipseRft;
class RifReaderEclipseSummary;
//==================================================================================================
@@ -42,12 +44,15 @@ public:
void createSummaryReaderInterface() override;
RifSummaryReaderInterface* summaryReader() override;
RifReaderRftInterface* rftReader() override;
void setIncludeRestartFiles(bool includeRestartFiles);
static RifReaderEclipseSummary* findRelatedFilesAndCreateReader(const QString& headerFileName, bool includeRestartFiles);
static RifReaderEclipseSummary* findRelatedFilesAndCreateReader(const QString& headerFileName, bool includeRestartFiles);
static RifReaderEclipseRft* findRftDataAndCreateReader(const QString& headerFileName);
private:
cvf::ref<RifReaderEclipseSummary> m_summaryFileReader;
cvf::ref<RifReaderEclipseRft> m_summaryEclipseRftReader;
caf::PdmField<bool> m_includeRestartFiles;
};

View File

@@ -19,6 +19,7 @@
#include "RimSummaryCase.h"
#include "RiaSummaryTools.h"
#include "RifSummaryReaderInterface.h"
#include "RimMainPlotCollection.h"
#include "RimOilField.h"
@@ -168,6 +169,14 @@ void RimSummaryCase::updateOptionSensitivity()
m_shortName.uiCapability()->setUiReadOnly(m_useAutoShortName);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderRftInterface* RimSummaryCase::rftReader()
{
return nullptr;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -187,6 +196,19 @@ QString RimSummaryCase::shortName() const
return m_shortName();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystemType RimSummaryCase::unitsSystem()
{
RifSummaryReaderInterface* reader = summaryReader();
if (reader)
{
return reader->unitSystem();
}
return RiaEclipseUnitTools::UNITS_UNKNOWN;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -17,6 +17,7 @@
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "RiaEclipseUnitTools.h"
#include "RigCaseRealizationParameters.h"
#include "cafPdmField.h"
@@ -24,6 +25,7 @@
#include <memory>
class RifReaderRftInterface;
class RifSummaryReaderInterface;
class RimSummaryCaseCollection;
@@ -43,12 +45,15 @@ public:
virtual QString summaryHeaderFilename() const;
virtual QString caseName() const = 0;
QString shortName() const;
RiaEclipseUnitTools::UnitSystemType unitsSystem();
void updateAutoShortName();
void updateOptionSensitivity();
virtual void createSummaryReaderInterface() = 0;
virtual RifSummaryReaderInterface* summaryReader() = 0;
virtual RifReaderRftInterface* rftReader();
virtual QString errorMessagesFromReader() { return QString(); }
virtual void updateFilePathsFromProjectPath(const QString& newProjectPath, const QString& oldProjectPath) = 0;

View File

@@ -22,10 +22,12 @@
#include "RimDerivedEnsembleCaseCollection.h"
#include "RimEnsembleCurveSet.h"
#include "RifReaderEnsembleStatisticsRft.h"
#include "RimGridSummaryCase.h"
#include "RimProject.h"
#include "RimSummaryCase.h"
#include "RifReaderEclipseRft.h"
#include "RifSummaryReaderInterface.h"
#include <QFileDialog>
@@ -146,6 +148,8 @@ RimSummaryCaseCollection::RimSummaryCaseCollection()
CAF_PDM_InitField(&m_isEnsemble, "IsEnsemble", false, "Is Ensemble", "", "", "");
m_isEnsemble.uiCapability()->setUiHidden(true);
m_statisticsEclipseRftReader = new RifReaderEnsembleStatisticsRft(this);
m_commonAddressCount = 0;
}
@@ -284,6 +288,50 @@ std::set<RifEclipseSummaryAddress> RimSummaryCaseCollection::ensembleSummaryAddr
return addresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QString> RimSummaryCaseCollection::wellsWithRftData() const
{
std::set<QString> allWellNames;
for (RimSummaryCase* summaryCase : m_cases)
{
RifReaderRftInterface* reader = summaryCase->rftReader();
if (reader)
{
std::set<QString> wellNames = reader->wellNames();
allWellNames.insert(wellNames.begin(), wellNames.end());
}
}
return allWellNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::set<QDateTime> RimSummaryCaseCollection::rftTimeStepsForWell(const QString& wellName) const
{
std::set<QDateTime> allTimeSteps;
for (RimSummaryCase* summaryCase : m_cases)
{
RifReaderRftInterface* reader = summaryCase->rftReader();
if (reader)
{
std::set<QDateTime> timeStep = reader->availableTimeSteps(wellName);
allTimeSteps.insert(timeStep.begin(), timeStep.end());
}
}
return allTimeSteps;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifReaderRftInterface* RimSummaryCaseCollection::rftStatisticsReader()
{
return m_statisticsEclipseRftReader.p();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -528,6 +576,18 @@ bool RimSummaryCaseCollection::operator<(const RimSummaryCaseCollection& rhs) co
return name() < rhs.name();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiaEclipseUnitTools::UnitSystem RimSummaryCaseCollection::unitSystem() const
{
if (m_cases.empty())
{
return RiaEclipseUnitTools::UNITS_UNKNOWN;
}
return m_cases[0]->unitsSystem();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@@ -18,7 +18,10 @@
#pragma once
#include "RiaEclipseUnitTools.h"
#include "RifEclipseSummaryAddress.h"
#include "RifEclipseRftAddress.h"
#include "RifReaderEnsembleStatisticsRft.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmField.h"
@@ -30,6 +33,8 @@
#include <utility>
#include <vector>
class RifReaderRftInterface;
class RifReaderEnsembleStatisticsRft;
class RimSummaryCase;
//==================================================================================================
@@ -87,6 +92,10 @@ public:
bool isEnsemble() const;
void setAsEnsemble(bool isEnsemble);
virtual std::set<RifEclipseSummaryAddress> ensembleSummaryAddresses() const;
std::set<QString> wellsWithRftData() const;
std::set<QDateTime> rftTimeStepsForWell(const QString& wellName) const;
RifReaderRftInterface* rftStatisticsReader();
EnsembleParameter ensembleParameter(const QString& paramName) const;
void calculateEnsembleParametersIntersectionHash();
void clearEnsembleParametersHashes();
@@ -95,6 +104,8 @@ public:
static bool validateEnsembleCases(const std::vector<RimSummaryCase*> cases);
bool operator<(const RimSummaryCaseCollection& rhs) const;
RiaEclipseUnitTools::UnitSystem unitSystem() const;
private:
caf::PdmFieldHandle* userDescriptionField() override;
QString nameAndItemCount() const;
@@ -112,9 +123,10 @@ protected:
caf::PdmChildArrayField<RimSummaryCase*> m_cases;
private:
caf::PdmField<QString> m_name;
caf::PdmProxyValueField<QString> m_nameAndItemCount;
caf::PdmField<bool> m_isEnsemble;
caf::PdmField<QString> m_name;
caf::PdmProxyValueField<QString> m_nameAndItemCount;
caf::PdmField<bool> m_isEnsemble;
cvf::ref<RifReaderEnsembleStatisticsRft> m_statisticsEclipseRftReader;
size_t m_commonAddressCount; // if different address count among cases, set to 0
};

View File

@@ -18,10 +18,10 @@
#include "RimSummaryCurve.h"
#include "RiaCurveMerger.h"
#include "RiaDefines.h"
#include "RiaGuiApplication.h"
#include "RiaPreferences.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RifReaderEclipseSummary.h"
@@ -490,14 +490,14 @@ void RimSummaryCurve::onLoadDataAndUpdate(bool updateParentPlot)
else
{
RiaTimeHistoryCurveMerger curveMerger;
curveMerger.addCurveData(curveValuesX, curveTimeStepsX);
curveMerger.addCurveData(curveValuesY, curveTimeStepsY);
curveMerger.addCurveData(curveTimeStepsX, curveValuesX);
curveMerger.addCurveData(curveTimeStepsY, curveValuesY);
curveMerger.computeInterpolatedValues();
if (curveMerger.allTimeSteps().size() > 0)
if (curveMerger.allXValues().size() > 0)
{
m_qwtPlotCurve->setSamplesFromXValuesAndYValues(curveMerger.interpolatedCurveValuesForAllTimeSteps(0),
curveMerger.interpolatedCurveValuesForAllTimeSteps(1),
m_qwtPlotCurve->setSamplesFromXValuesAndYValues(curveMerger.interpolatedYValuesForAllXValues(0),
curveMerger.interpolatedYValuesForAllXValues(1),
isLogCurve);
}
else
@@ -995,11 +995,11 @@ void RimSummaryCurve::fieldChangedByUi(const caf::PdmFieldHandle* changedField,
if (!curveValuesX.empty() && !curveValuesY.empty())
{
RiaTimeHistoryCurveMerger curveMerger;
curveMerger.addCurveData(curveValuesX, curveTimeStepsX);
curveMerger.addCurveData(curveValuesY, curveTimeStepsY);
curveMerger.addCurveData(curveTimeStepsX, curveValuesX);
curveMerger.addCurveData(curveTimeStepsY, curveValuesY);
curveMerger.computeInterpolatedValues();
if (curveMerger.validIntervalsForAllTimeSteps().size() == 0)
if (curveMerger.validIntervalsForAllXValues().size() == 0)
{
QString description;

View File

@@ -79,6 +79,72 @@ void RigStatisticsMath::calculateBasicStatistics(const std::vector<double>& valu
}
//--------------------------------------------------------------------------------------------------
/// Algorithm:
/// https://en.wikipedia.org/wiki/Percentile#Third_variant,_'%22%60UNIQ--postMath-00000052-QINU%60%22'
//--------------------------------------------------------------------------------------------------
void RigStatisticsMath::calculateStatisticsCurves(const std::vector<double>& values,
double* p10,
double* p50,
double* p90,
double* mean)
{
CVF_ASSERT(p10 && p50 && p90 && mean);
enum PValue
{
P10,
P50,
P90
};
std::vector<double> sortedValues;
double valueSum = 0;
{
std::multiset<double> vSet(values.begin(), values.end());
for (double v : vSet)
{
if (RiaStatisticsTools::isValidNumber(v))
{
sortedValues.push_back(v);
valueSum += v;
}
}
}
int valueCount = (int)sortedValues.size();
double percentiles[] = {0.1, 0.5, 0.9};
double pValues[] = {HUGE_VAL, HUGE_VAL, HUGE_VAL};
for (int i = P10; i <= P90; i++)
{
// Check valid params
if ((percentiles[i] < 1.0 / ((double)valueCount + 1)) || (percentiles[i] > (double)valueCount / ((double)valueCount + 1)))
continue;
double rank = percentiles[i] * (valueCount + 1) - 1;
double rankRem;
double rankFrac = std::modf(rank, &rankRem);
int rankInt = static_cast<int>(rankRem);
if (rankInt < valueCount - 1)
{
pValues[i] = sortedValues[rankInt] + rankFrac * (sortedValues[rankInt + 1] - sortedValues[rankInt]);
}
else
{
pValues[i] = sortedValues.back();
}
}
*p10 = pValues[P10];
*p50 = pValues[P50];
*p90 = pValues[P90];
*mean = valueSum / valueCount;
}
//--------------------------------------------------------------------------------------------------
/// Calculate the percentiles of /a inputValues at the pValPosition percentages using the "Nearest Rank"
/// method. This method treats HUGE_VAL as "undefined" values, and ignores these. Will return HUGE_VAL if

View File

@@ -28,6 +28,8 @@ class RigStatisticsMath
{
public:
static void calculateBasicStatistics(const std::vector<double>& values, double* min, double* max, double* sum, double* range, double* mean, double* dev);
static void calculateStatisticsCurves(const std::vector<double>& values, double* p10, double* p50, double* p90, double* mean);
static std::vector<double> calculateNearestRankPercentiles(const std::vector<double> & inputValues, const std::vector<double>& pValPositions);
static std::vector<double> calculateInterpolatedPercentiles(const std::vector<double> & inputValues, const std::vector<double>& pValPositions);
};

View File

@@ -15,7 +15,7 @@ TEST(DISABLED_RifReaderEclipseRftTest, TestRifEclipseRftAddress)
RifReaderEclipseRft reader(filename);
std::vector<RifEclipseRftAddress> addresses = reader.eclipseRftAddresses();
std::set<RifEclipseRftAddress> addresses = reader.eclipseRftAddresses();
/*for (RifEclipseRftAddress address : addresses)
{
@@ -32,7 +32,7 @@ TEST(DISABLED_RifReaderEclipseRftTest, TestRifEclipseRftAddress)
ASSERT_TRUE(addresses.size() > 0);
std::vector<double> values;
reader.values(addresses[0], &values);
reader.values(*addresses.begin(), &values);
ASSERT_TRUE(values.size() > 0);
std::cout << "First value: " << values.front() << ", last value: " << values.back() << std::endl;

View File

@@ -1,6 +1,6 @@
#include "gtest/gtest.h"
#include "RiaTimeHistoryCurveMerger.h"
#include "RiaCurveMerger.h"
#include <cmath> // Needed for HUGE_VAL on Linux
@@ -13,25 +13,25 @@ TEST(RiaTimeHistoryCurveMergerTest, TestDateInterpolation)
std::vector<time_t> timeSteps{ 1, 5, 10, 15};
{
double val = RiaTimeHistoryCurveMerger::interpolationValue(1, values, timeSteps);
double val = RiaTimeHistoryCurveMerger::interpolatedYValue(1, timeSteps, values);
EXPECT_EQ(2.0, val);
}
{
double val = RiaTimeHistoryCurveMerger::interpolationValue(0, values, timeSteps);
double val = RiaTimeHistoryCurveMerger::interpolatedYValue(0, timeSteps, values);
EXPECT_EQ(HUGE_VAL, val);
}
{
double val = RiaTimeHistoryCurveMerger::interpolationValue(20, values, timeSteps);
double val = RiaTimeHistoryCurveMerger::interpolatedYValue(20, timeSteps, values);
EXPECT_EQ(HUGE_VAL, val);
}
{
double val = RiaTimeHistoryCurveMerger::interpolationValue(3, values, timeSteps);
double val = RiaTimeHistoryCurveMerger::interpolatedYValue(3, timeSteps, values);
EXPECT_EQ(2.75, val);
}
@@ -54,12 +54,12 @@ TEST(RiaTimeHistoryCurveMergerTest, ExtractIntervalsWithSameTimeSteps)
}
RiaTimeHistoryCurveMerger interpolate;
interpolate.addCurveData(valuesA, timeSteps);
interpolate.addCurveData(valuesB, timeSteps);
interpolate.addCurveData(timeSteps, valuesA);
interpolate.addCurveData(timeSteps, valuesB);
interpolate.computeInterpolatedValues();
auto interpolatedTimeSteps = interpolate.allTimeSteps();
auto intervals = interpolate.validIntervalsForAllTimeSteps();
auto interpolatedTimeSteps = interpolate.allXValues();
auto intervals = interpolate.validIntervalsForAllXValues();
EXPECT_EQ(10, static_cast<int>(interpolatedTimeSteps.size()));
EXPECT_EQ(3, static_cast<int>(intervals.size()));
@@ -82,12 +82,12 @@ TEST(RiaTimeHistoryCurveMergerTest, ExtractIntervalsWithSameTimeStepsOneComplete
}
RiaTimeHistoryCurveMerger interpolate;
interpolate.addCurveData(valuesA, timeSteps);
interpolate.addCurveData(valuesB, timeSteps);
interpolate.addCurveData(timeSteps, valuesA);
interpolate.addCurveData(timeSteps, valuesB);
interpolate.computeInterpolatedValues();
auto interpolatedTimeSteps = interpolate.allTimeSteps();
auto intervals = interpolate.validIntervalsForAllTimeSteps();
auto interpolatedTimeSteps = interpolate.allXValues();
auto intervals = interpolate.validIntervalsForAllXValues();
EXPECT_EQ(7, static_cast<int>(interpolatedTimeSteps.size()));
EXPECT_EQ(3, static_cast<int>(intervals.size()));
@@ -110,12 +110,12 @@ TEST(RiaTimeHistoryCurveMergerTest, ExtractIntervalsWithSameTimeStepsBothComplet
}
RiaTimeHistoryCurveMerger interpolate;
interpolate.addCurveData(valuesA, timeSteps);
interpolate.addCurveData(valuesB, timeSteps);
interpolate.addCurveData(timeSteps, valuesA);
interpolate.addCurveData(timeSteps, valuesB);
interpolate.computeInterpolatedValues();
auto interpolatedTimeSteps = interpolate.allTimeSteps();
auto intervals = interpolate.validIntervalsForAllTimeSteps();
auto interpolatedTimeSteps = interpolate.allXValues();
auto intervals = interpolate.validIntervalsForAllXValues();
EXPECT_EQ(7, static_cast<int>(interpolatedTimeSteps.size()));
EXPECT_EQ(1, static_cast<int>(intervals.size()));
@@ -135,12 +135,13 @@ TEST(RiaTimeHistoryCurveMergerTest, OverlappintTimes)
std::vector<time_t> timeStepsB{ 1, 2, 3, 5, 7 };
RiaTimeHistoryCurveMerger interpolate;
interpolate.addCurveData(valuesA, timeStepsA);
interpolate.addCurveData(valuesB, timeStepsB);
interpolate.addCurveData(timeStepsA, valuesA);
interpolate.addCurveData(timeStepsB, valuesB);
interpolate.computeInterpolatedValues();
EXPECT_EQ(2, static_cast<int>(interpolate.curveCount()));
auto interpolatedTimeSteps = interpolate.allTimeSteps();
auto intervals = interpolate.validIntervalsForAllTimeSteps();
auto interpolatedTimeSteps = interpolate.allXValues();
auto intervals = interpolate.validIntervalsForAllXValues();
EXPECT_EQ(10, static_cast<int>(interpolatedTimeSteps.size()));
EXPECT_EQ(1, static_cast<int>(intervals.size()));
@@ -154,7 +155,7 @@ TEST(RiaTimeHistoryCurveMergerTest, RobustUse)
{
RiaTimeHistoryCurveMerger curveMerger;
curveMerger.computeInterpolatedValues();
EXPECT_EQ(0, static_cast<int>(curveMerger.allTimeSteps().size()));
EXPECT_EQ(0, static_cast<int>(curveMerger.allXValues().size()));
}
std::vector<double> valuesA{ 1, 2, 3, 4, 5 };
@@ -165,23 +166,23 @@ TEST(RiaTimeHistoryCurveMergerTest, RobustUse)
{
RiaTimeHistoryCurveMerger curveMerger;
curveMerger.addCurveData(valuesA, timeStepsA);
curveMerger.addCurveData(timeStepsA, valuesA);
curveMerger.computeInterpolatedValues();
EXPECT_EQ(timeStepsA.size(), curveMerger.allTimeSteps().size());
EXPECT_EQ(timeStepsA.size(), curveMerger.interpolatedCurveValuesForAllTimeSteps(0).size());
EXPECT_EQ(timeStepsA.size(), curveMerger.allXValues().size());
EXPECT_EQ(timeStepsA.size(), curveMerger.interpolatedYValuesForAllXValues(0).size());
}
{
RiaTimeHistoryCurveMerger curveMerger;
curveMerger.addCurveData(valuesA, timeStepsA);
curveMerger.addCurveData(valuesB, timeStepsB);
curveMerger.addCurveData(timeStepsA, valuesA);
curveMerger.addCurveData(timeStepsB, valuesB);
// Execute interpolation twice is allowed
curveMerger.computeInterpolatedValues();
curveMerger.computeInterpolatedValues();
EXPECT_EQ(8, static_cast<int>(curveMerger.allTimeSteps().size()));
EXPECT_EQ(8, static_cast<int>(curveMerger.interpolatedCurveValuesForAllTimeSteps(0).size()));
EXPECT_EQ(8, static_cast<int>(curveMerger.interpolatedCurveValuesForAllTimeSteps(1).size()));
EXPECT_EQ(8, static_cast<int>(curveMerger.allXValues().size()));
EXPECT_EQ(8, static_cast<int>(curveMerger.interpolatedYValuesForAllXValues(0).size()));
EXPECT_EQ(8, static_cast<int>(curveMerger.interpolatedYValuesForAllXValues(1).size()));
}
}
@@ -198,13 +199,13 @@ TEST(RiaTimeHistoryCurveMergerTest, NoTimeStepOverlap)
{
RiaTimeHistoryCurveMerger curveMerger;
curveMerger.addCurveData(valuesA, timeStepsA);
curveMerger.addCurveData(valuesB, timeStepsB);
curveMerger.addCurveData(timeStepsA, valuesA);
curveMerger.addCurveData(timeStepsB, valuesB);
// Execute interpolation twice is allowed
curveMerger.computeInterpolatedValues();
EXPECT_EQ(8, static_cast<int>(curveMerger.allTimeSteps().size()));
EXPECT_EQ(0, static_cast<int>(curveMerger.validIntervalsForAllTimeSteps().size()));
EXPECT_EQ(8, static_cast<int>(curveMerger.allXValues().size()));
EXPECT_EQ(0, static_cast<int>(curveMerger.validIntervalsForAllXValues().size()));
}
}

View File

@@ -217,7 +217,7 @@ void RiuQwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol,
}
float sqSkipDist = m_symbolSkipPixelDistance * m_symbolSkipPixelDistance;
float sqSkipToLastDiff = m_symbolSkipPixelDistance / 10 * m_symbolSkipPixelDistance / 10;
for (int pIdx = 1; pIdx < pointCount - 1; ++pIdx)
{
QPointF diff = points[pIdx] - lastDrawnSymbolPos;
@@ -225,6 +225,13 @@ void RiuQwtPlotCurve::drawSymbols(QPainter *painter, const QwtSymbol &symbol,
if (sqDistBetweenSymbols > sqSkipDist)
{
if (pIdx == pointCount - 2)
{
QPointF diffToBack = points.back() - points[pIdx];
float sqDistToBack = diffToBack.x() * diffToBack.x() + diffToBack.y() * diffToBack.y();
if (sqDistToBack < sqSkipToLastDiff)
continue;
}
pointsToDisplay.push_back(points[pIdx]);
lastDrawnSymbolPos = points[pIdx];
}

View File

@@ -54,7 +54,7 @@ RiuQwtSymbol::RiuQwtSymbol(PointSymbolEnum riuStyle, const QString& label, Label
case SYMBOL_DOWN_TRIANGLE:
style = QwtSymbol::DTriangle;
break;
case SYMBOL_LEFT_TRIANGLE:
case SYMBOL_LEFT_ALIGNED_TRIANGLE:
style = QwtSymbol::Path;
{
QPainterPath path;
@@ -66,7 +66,7 @@ RiuQwtSymbol::RiuQwtSymbol(PointSymbolEnum riuStyle, const QString& label, Label
setPinPoint(QPointF(0, 0));
}
break;
case SYMBOL_RIGHT_TRIANGLE:
case SYMBOL_RIGHT_ALIGNED_TRIANGLE:
style = QwtSymbol::Path;
{
QPainterPath path;
@@ -114,6 +114,11 @@ RiuQwtSymbol::RiuQwtSymbol(PointSymbolEnum riuStyle, const QString& label, Label
case SYMBOL_HEXAGON:
style = QwtSymbol::Hexagon;
break;
case SYMBOL_LEFT_TRIANGLE:
style = QwtSymbol::LTriangle;
break;
case SYMBOL_RIGHT_TRIANGLE:
style = QwtSymbol::RTriangle;
default:
break;
}
@@ -132,7 +137,7 @@ void RiuQwtSymbol::renderSymbols(QPainter *painter, const QPointF *points, int n
for (int i = 0; i < numPoints; i++)
{
auto position = points[i];
renderSymbolLabel(painter, position);
//renderSymbolLabel(painter, position);
}
}
}
@@ -174,7 +179,6 @@ RiuQwtSymbol::PointSymbolEnum RiuQwtSymbol::cycledSymbolStyle(int indexLevel1, i
{SYMBOL_ELLIPSE, SYMBOL_RECT, SYMBOL_DIAMOND},
{SYMBOL_DOWN_TRIANGLE, SYMBOL_UP_TRIANGLE},
{SYMBOL_LEFT_TRIANGLE, SYMBOL_RIGHT_TRIANGLE},
{SYMBOL_LEFT_ANGLED_TRIANGLE, SYMBOL_RIGHT_ANGLED_TRIANGLE},
{SYMBOL_CROSS, SYMBOL_XCROSS},
{SYMBOL_STAR1, SYMBOL_STAR2},
};
@@ -208,7 +212,8 @@ QRect RiuQwtSymbol::labelBoundingRect(const QPainter* painter, const QRect& symb
QPoint symbolPosition = symbolRect.topLeft();
int symbolWidth = symbolRect.width();
int symbolWidth = symbolRect.width();
int symbolHeight = symbolRect.height();
int labelWidth = painter->fontMetrics().width(m_label);
int labelHeight = painter->fontMetrics().height();
@@ -218,6 +223,10 @@ QRect RiuQwtSymbol::labelBoundingRect(const QPainter* painter, const QRect& symb
{
labelPosition = QPoint(symbolPosition.x() - labelWidth / 2, symbolPosition.y() - 5);
}
else if (m_labelPosition == LabelBelowSymbol)
{
labelPosition = QPoint(symbolPosition.x() - labelWidth / 2, symbolPosition.y() + symbolHeight + 5);
}
else if (m_labelPosition == LabelLeftOfSymbol)
{
labelPosition = QPoint(symbolPosition.x() - labelWidth - symbolWidth, symbolPosition.y());

View File

@@ -34,6 +34,7 @@ public:
enum LabelPosition
{
LabelAboveSymbol,
LabelBelowSymbol,
LabelLeftOfSymbol,
LabelRightOfSymbol
};
@@ -47,14 +48,16 @@ public:
SYMBOL_DOWN_TRIANGLE,
SYMBOL_CROSS,
SYMBOL_XCROSS,
SYMBOL_LEFT_TRIANGLE,
SYMBOL_RIGHT_TRIANGLE,
SYMBOL_LEFT_ALIGNED_TRIANGLE, // Aligned so pin point is at lower right corner
SYMBOL_RIGHT_ALIGNED_TRIANGLE, // Aligned so pin point is at lower left corner
SYMBOL_LEFT_ANGLED_TRIANGLE,
SYMBOL_RIGHT_ANGLED_TRIANGLE,
SYMBOL_UP_TRIANGLE,
SYMBOL_STAR1,
SYMBOL_STAR2,
SYMBOL_HEXAGON
SYMBOL_HEXAGON,
SYMBOL_LEFT_TRIANGLE,
SYMBOL_RIGHT_TRIANGLE
};
RiuQwtSymbol(PointSymbolEnum riuStyle, const QString& label, LabelPosition labelPosition = LabelAboveSymbol);

View File

@@ -201,16 +201,16 @@ void RiuWellPathComponentPlotItem::onLoadDataAndUpdate(bool updateParentPlot)
double markerDepth = startDepth;
while (markerDepth < endDepth - 5)
{
addMarker(-casingTrackEnd, markerDepth, markerSize, RiuQwtSymbol::SYMBOL_LEFT_TRIANGLE, componentColor());
addMarker(casingTrackEnd, markerDepth, markerSize, RiuQwtSymbol::SYMBOL_RIGHT_TRIANGLE, componentColor());
addMarker(-casingTrackEnd, markerDepth, markerSize, RiuQwtSymbol::SYMBOL_LEFT_ALIGNED_TRIANGLE, componentColor());
addMarker(casingTrackEnd, markerDepth, markerSize, RiuQwtSymbol::SYMBOL_RIGHT_ALIGNED_TRIANGLE, componentColor());
markerDepth += markerSpacing;
}
addMarker(casingTrackEnd, midDepth, 10, RiuQwtSymbol::SYMBOL_RIGHT_TRIANGLE, componentColor(0.0), label());
addMarker(casingTrackEnd, midDepth, 10, RiuQwtSymbol::SYMBOL_RIGHT_ALIGNED_TRIANGLE, componentColor(0.0), label());
QwtPlotItem* legendItem1 = createMarker(16.0, 0.0, 6, RiuQwtSymbol::SYMBOL_RIGHT_TRIANGLE, componentColor());
QwtPlotItem* legendItem1 = createMarker(16.0, 0.0, 6, RiuQwtSymbol::SYMBOL_RIGHT_ALIGNED_TRIANGLE, componentColor());
legendItem1->setLegendIconSize(QSize(4, 8));
QwtPlotItem* legendItem2 = createMarker(16.0, 8.0, 6, RiuQwtSymbol::SYMBOL_RIGHT_TRIANGLE, componentColor());
QwtPlotItem* legendItem2 = createMarker(16.0, 8.0, 6, RiuQwtSymbol::SYMBOL_RIGHT_ALIGNED_TRIANGLE, componentColor());
legendItem2->setLegendIconSize(QSize(4, 8));
m_combinedComponentGroup.addLegendItem(legendItem1);
m_combinedComponentGroup.addLegendItem(legendItem2);