mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#4013 Create variation bins for ensemble parameters based on current data
* Rather than having a fixed index. * This way the variation is more or less always normal distributed.
This commit is contained in:
parent
7518a1880a
commit
54b5dc33f4
@ -453,16 +453,13 @@ QString RimEnsembleCurveSet::ensembleParameterUiName(const RimEnsembleCurveSet::
|
|||||||
QString variationString;
|
QString variationString;
|
||||||
if (paramPair.second.isNumeric())
|
if (paramPair.second.isNumeric())
|
||||||
{
|
{
|
||||||
switch (paramPair.second.logarithmicVariationIndex())
|
switch (paramPair.second.variationBin)
|
||||||
{
|
{
|
||||||
case -1:
|
case EnsembleParameter::LOW_VARIATION:
|
||||||
variationString = QString(" (No variation)");
|
|
||||||
case 0:
|
|
||||||
variationString = QString(" (Low variation)");
|
variationString = QString(" (Low variation)");
|
||||||
|
case EnsembleParameter::MEDIUM_VARIATION:
|
||||||
break;
|
break;
|
||||||
case 1:
|
case EnsembleParameter::HIGH_VARIATION:
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
variationString = QString(" (High variation)");
|
variationString = QString(" (High variation)");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1170,13 +1167,7 @@ std::vector<RimEnsembleCurveSet::NameParameterPair> RimEnsembleCurveSet::ensembl
|
|||||||
{
|
{
|
||||||
parameterVector.push_back(std::make_pair(parameterName, group->ensembleParameter(parameterName)));
|
parameterVector.push_back(std::make_pair(parameterName, group->ensembleParameter(parameterName)));
|
||||||
}
|
}
|
||||||
|
EnsembleParameter::sortByBinnedVariation(parameterVector);
|
||||||
// Sort by variation index (highest first) but keep name as sorting parameter when parameters have the same variation index
|
|
||||||
std::stable_sort(parameterVector.begin(), parameterVector.end(), [](const NameParameterPair& lhs, const NameParameterPair& rhs)
|
|
||||||
{
|
|
||||||
return lhs.second.logarithmicVariationIndex() > rhs.second.logarithmicVariationIndex();
|
|
||||||
});
|
|
||||||
|
|
||||||
return parameterVector;
|
return parameterVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,26 +127,27 @@ private:
|
|||||||
|
|
||||||
caf::PdmFieldHandle* userDescriptionField() override;
|
caf::PdmFieldHandle* userDescriptionField() override;
|
||||||
caf::PdmFieldHandle* objectToggleField() override;
|
caf::PdmFieldHandle* objectToggleField() override;
|
||||||
void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override;
|
void defineEditorAttribute(const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute) override;
|
||||||
|
|
||||||
QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
|
QList<caf::PdmOptionItemInfo> calculateValueOptions(const caf::PdmFieldHandle* fieldNeedingOptions, bool* useOptionsOnly) override;
|
||||||
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
|
void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override;
|
||||||
void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override;
|
void defineUiTreeOrdering(caf::PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") override;
|
||||||
|
|
||||||
void fieldChangedByUi(const caf::PdmFieldHandle* changedField,
|
void fieldChangedByUi(const caf::PdmFieldHandle* changedField,
|
||||||
const QVariant& oldValue, const QVariant& newValue) override;
|
const QVariant& oldValue, const QVariant& newValue) override;
|
||||||
|
|
||||||
void appendOptionItemsForSummaryAddresses(QList<caf::PdmOptionItemInfo>* options,
|
void appendOptionItemsForSummaryAddresses(QList<caf::PdmOptionItemInfo>* options,
|
||||||
RimSummaryCaseCollection* summaryCaseGroup,
|
RimSummaryCaseCollection* summaryCaseGroup,
|
||||||
RimSummaryFilter* summaryFilter);
|
RimSummaryFilter* summaryFilter);
|
||||||
|
|
||||||
void updateCurveColors();
|
void updateCurveColors();
|
||||||
void updateQwtPlotAxis();
|
void updateQwtPlotAxis();
|
||||||
|
|
||||||
QString name() const;
|
QString name() const;
|
||||||
QString createAutoName() const;
|
QString createAutoName() const;
|
||||||
|
|
||||||
void updateLegendMappingMode();
|
void updateLegendMappingMode();
|
||||||
|
void sortParameterVectorByBinnedVariation(std::vector<NameParameterPair>& parameterVector) const;
|
||||||
private:
|
private:
|
||||||
caf::PdmField<bool> m_showCurves;
|
caf::PdmField<bool> m_showCurves;
|
||||||
caf::PdmChildArrayField<RimSummaryCurve*> m_curves;
|
caf::PdmChildArrayField<RimSummaryCurve*> m_curves;
|
||||||
|
@ -36,44 +36,11 @@
|
|||||||
|
|
||||||
CAF_PDM_SOURCE_INIT(RimSummaryCaseCollection, "SummaryCaseSubCollection");
|
CAF_PDM_SOURCE_INIT(RimSummaryCaseCollection, "SummaryCaseSubCollection");
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
/// Return an integer derived from the logarithm of the range.
|
|
||||||
/// -1 if there is practically no variation and a rising positive integer for non-zero range.
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
|
||||||
int EnsembleParameter::logarithmicVariationIndex() const
|
|
||||||
{
|
|
||||||
const double eps = 1.0e-4;
|
|
||||||
|
|
||||||
double maxAbs = std::max(std::fabs(maxValue), std::fabs(minValue));
|
|
||||||
if (maxAbs < eps)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double normalisedStdDevPercent = 2.0 * m_stdDeviation / maxAbs * 100.0;
|
|
||||||
if (normalisedStdDevPercent < eps)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should always yield an index from and including -1 to and including 2
|
|
||||||
// As the maximum normalisedStdDevPercent is ~282
|
|
||||||
// Found with two values symmetric around 0 so min = -X and max = +X
|
|
||||||
// normalisedStdDevPercent is then 2 * sqrt(2X^2) / X * 100 = sqrt(2) * 100 = ~282.
|
|
||||||
// And log10 value is ~2.45.
|
|
||||||
int variationIndex = std::max(-1, (int) std::round(std::log10(normalisedStdDevPercent)));
|
|
||||||
//CVF_ASSERT(variationIndex >= -1 && variationIndex <= 2);
|
|
||||||
return variationIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
void EnsembleParameter::calculateStdDeviation()
|
double EnsembleParameter::stdDeviation() const
|
||||||
{
|
{
|
||||||
m_stdDeviation = 0.0;
|
|
||||||
|
|
||||||
double N = static_cast<double>(values.size());
|
double N = static_cast<double>(values.size());
|
||||||
if (N > 1 && isNumeric())
|
if (N > 1 && isNumeric())
|
||||||
{
|
{
|
||||||
@ -86,10 +53,80 @@ void EnsembleParameter::calculateStdDeviation()
|
|||||||
sumValuesSquared += value * value;
|
sumValuesSquared += value * value;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_stdDeviation = std::sqrt((N * sumValuesSquared - sumValues * sumValues) / (N * (N - 1.0)));
|
return std::sqrt((N * sumValuesSquared - sumValues * sumValues) / (N * (N - 1.0)));
|
||||||
}
|
}
|
||||||
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
/// Standard deviation normalized by max absolute value of min/max values.
|
||||||
|
/// Produces values between 0.0 and sqrt(2.0).
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
double EnsembleParameter::normalizedStdDeviation() const
|
||||||
|
{
|
||||||
|
const double eps = 1.0e-4;
|
||||||
|
|
||||||
|
double maxAbs = std::max(std::fabs(maxValue), std::fabs(minValue));
|
||||||
|
if (maxAbs < eps)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double normalisedStdDev = stdDeviation() / maxAbs;
|
||||||
|
if (normalisedStdDev < eps)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
return normalisedStdDev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
///
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
void EnsembleParameter::sortByBinnedVariation(std::vector<NameParameterPair>& parameterVector)
|
||||||
|
{
|
||||||
|
double minStdDev = std::numeric_limits<double>::infinity();
|
||||||
|
double maxStdDev = 0.0;
|
||||||
|
for (const auto& paramPair : parameterVector)
|
||||||
|
{
|
||||||
|
minStdDev = std::min(minStdDev, paramPair.second.normalizedStdDeviation());
|
||||||
|
maxStdDev = std::max(maxStdDev, paramPair.second.normalizedStdDeviation());
|
||||||
|
}
|
||||||
|
if ((maxStdDev - minStdDev) < 1.0e-8)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double delta = (maxStdDev - minStdDev) / NR_OF_VARIATION_BINS;
|
||||||
|
|
||||||
|
std::vector<double> bins;
|
||||||
|
for (int i = 0; i < NR_OF_VARIATION_BINS - 1; ++i)
|
||||||
|
{
|
||||||
|
bins.push_back(minStdDev + (i + 1) * delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (NameParameterPair& nameParamPair : parameterVector)
|
||||||
|
{
|
||||||
|
int binNumber = 0;
|
||||||
|
for (double bin : bins)
|
||||||
|
{
|
||||||
|
if (nameParamPair.second.normalizedStdDeviation() >= bin)
|
||||||
|
{
|
||||||
|
binNumber++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nameParamPair.second.variationBin = binNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by variation bin (highest first) but keep name as sorting parameter when parameters have the same variation index
|
||||||
|
std::stable_sort(parameterVector.begin(), parameterVector.end(),
|
||||||
|
[&bins](const NameParameterPair& lhs, const NameParameterPair& rhs)
|
||||||
|
{
|
||||||
|
return lhs.second.variationBin > rhs.second.variationBin;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
///
|
///
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
@ -338,8 +375,6 @@ EnsembleParameter RimSummaryCaseCollection::ensembleParameter(const QString& par
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eParam.calculateStdDeviation();
|
|
||||||
|
|
||||||
return eParam;
|
return eParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
#include "cafPdmObject.h"
|
#include "cafPdmObject.h"
|
||||||
#include "cafPdmProxyValueField.h"
|
#include "cafPdmProxyValueField.h"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class RimSummaryCase;
|
class RimSummaryCase;
|
||||||
@ -35,31 +38,35 @@ class RimSummaryCase;
|
|||||||
class EnsembleParameter
|
class EnsembleParameter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type { TYPE_NONE, TYPE_NUMERIC, TYPE_TEXT };
|
typedef std::pair<QString, EnsembleParameter> NameParameterPair;
|
||||||
|
|
||||||
|
enum Type { TYPE_NONE, TYPE_NUMERIC, TYPE_TEXT };
|
||||||
|
enum Bins { LOW_VARIATION, MEDIUM_VARIATION, HIGH_VARIATION, NR_OF_VARIATION_BINS };
|
||||||
QString name;
|
QString name;
|
||||||
Type type;
|
Type type;
|
||||||
std::vector<QVariant> values;
|
std::vector<QVariant> values;
|
||||||
double minValue;
|
double minValue;
|
||||||
double maxValue;
|
double maxValue;
|
||||||
|
int variationBin;
|
||||||
|
|
||||||
EnsembleParameter() :
|
EnsembleParameter() :
|
||||||
type(TYPE_NONE),
|
type(TYPE_NONE),
|
||||||
minValue(std::numeric_limits<double>::infinity()),
|
minValue(std::numeric_limits<double>::infinity()),
|
||||||
maxValue(-std::numeric_limits<double>::infinity()),
|
maxValue(-std::numeric_limits<double>::infinity()),
|
||||||
m_stdDeviation(0.0)
|
variationBin(static_cast<int>(MEDIUM_VARIATION))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool isValid() const { return !name.isEmpty() && type != TYPE_NONE; }
|
bool isValid() const { return !name.isEmpty() && type != TYPE_NONE; }
|
||||||
bool isNumeric() const { return type == TYPE_NUMERIC; }
|
bool isNumeric() const { return type == TYPE_NUMERIC; }
|
||||||
bool isText() const { return type == TYPE_TEXT; }
|
bool isText() const { return type == TYPE_TEXT; }
|
||||||
double range() const { return std::abs(maxValue - minValue); }
|
double range() const { return std::abs(maxValue - minValue); }
|
||||||
void calculateStdDeviation();
|
double normalizedStdDeviation() const;
|
||||||
|
|
||||||
int logarithmicVariationIndex() const;
|
static void sortByBinnedVariation(std::vector<NameParameterPair>& parameterVector);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double m_stdDeviation;
|
double stdDeviation() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
TEST(RimSummaryCaseCollection, logarithmicVariationIndex)
|
TEST(RimSummaryCaseCollection, EnsembleParameter)
|
||||||
{
|
{
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
std::mt19937 gen(rd());
|
std::mt19937 gen(rd());
|
||||||
@ -14,7 +14,8 @@ TEST(RimSummaryCaseCollection, logarithmicVariationIndex)
|
|||||||
std::uniform_real_distribution<double> variationDistribution(0.0, 5000.0);
|
std::uniform_real_distribution<double> variationDistribution(0.0, 5000.0);
|
||||||
std::uniform_int_distribution<size_t> countDistribution(1u, 1000u);
|
std::uniform_int_distribution<size_t> countDistribution(1u, 1000u);
|
||||||
size_t N = 1000;
|
size_t N = 1000;
|
||||||
std::map<int, size_t> indexCounts;
|
|
||||||
|
std::vector<EnsembleParameter::NameParameterPair> parameters;
|
||||||
for (size_t i = 0; i < N; ++i)
|
for (size_t i = 0; i < N; ++i)
|
||||||
{
|
{
|
||||||
EnsembleParameter param;
|
EnsembleParameter param;
|
||||||
@ -34,17 +35,25 @@ TEST(RimSummaryCaseCollection, logarithmicVariationIndex)
|
|||||||
param.values.push_back(QVariant(value));
|
param.values.push_back(QVariant(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
param.calculateStdDeviation();
|
|
||||||
param.minValue = minValue;
|
param.minValue = minValue;
|
||||||
param.maxValue = maxValue;
|
param.maxValue = maxValue;
|
||||||
int variationIndex = param.logarithmicVariationIndex();
|
|
||||||
EXPECT_GE(variationIndex, -1);
|
double normStdDev = param.normalizedStdDeviation();
|
||||||
EXPECT_LE(variationIndex, 2);
|
EXPECT_GE(normStdDev, 0.0);
|
||||||
indexCounts[variationIndex]++;
|
EXPECT_LE(normStdDev, std::sqrt(2.0));
|
||||||
|
parameters.push_back(std::make_pair(QString("%1").arg(i), param));
|
||||||
}
|
}
|
||||||
|
size_t previousSize = parameters.size();
|
||||||
for (auto countPair : indexCounts)
|
EnsembleParameter::sortByBinnedVariation(parameters);
|
||||||
|
size_t currentSize = parameters.size();
|
||||||
|
EXPECT_EQ(previousSize, currentSize);
|
||||||
|
|
||||||
|
int currentVariation = (int)EnsembleParameter::HIGH_VARIATION;
|
||||||
|
for (const EnsembleParameter::NameParameterPair& nameParamPair : parameters)
|
||||||
{
|
{
|
||||||
qDebug() << "Variation index " << countPair.first << " count = " << countPair.second;
|
EXPECT_GE(nameParamPair.second.variationBin, (int) EnsembleParameter::LOW_VARIATION);
|
||||||
|
EXPECT_LE(nameParamPair.second.variationBin, (int) EnsembleParameter::HIGH_VARIATION);
|
||||||
|
EXPECT_LE(nameParamPair.second.variationBin, currentVariation);
|
||||||
|
currentVariation = nameParamPair.second.variationBin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user