mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
Realizations whose calculated summary vector value is NaN or Inf at the selected timestep are now excluded from the Pearson correlation computation instead of propagating NaN through the whole result, which corrupted the correlation tornado plot. Also guard the final correlation value against NaN, since the previous check only compared against +Infinity. RigEnsembleParameter::stdDeviation() sums squared parameter values, which can overflow to +Inf for extreme (but finite) magnitudes, turning normalizedStdDeviation() into NaN. Since NaN compares false against the variation epsilon, such parameters were silently treated as having no variation and dropped from parameterCorrelations(), producing an empty tornado plot for that parameter and calculated vector combination. Fall back to a range-based variation estimate when the standard deviation calculation overflows, so the parameter is retained and the Pearson correlation guard above can take over instead.
118 lines
4.1 KiB
C++
118 lines
4.1 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 "RigEnsembleParameter.h"
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
double RigEnsembleParameter::stdDeviation() const
|
|
{
|
|
double N = static_cast<double>( values.size() );
|
|
if ( N > 1 && isNumeric() )
|
|
{
|
|
double sumValues = 0.0;
|
|
double sumValuesSquared = 0.0;
|
|
for ( const QVariant& variant : values )
|
|
{
|
|
double value = variant.toDouble();
|
|
sumValues += value;
|
|
sumValuesSquared += value * value;
|
|
}
|
|
|
|
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 RigEnsembleParameter::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 ( !std::isfinite( normalisedStdDev ) )
|
|
{
|
|
// stdDeviation() sums squared values, which can overflow to NaN/Inf for parameter values with
|
|
// extreme (but finite) magnitudes. Fall back to a range-based variation estimate so the
|
|
// parameter is not silently treated as having no variation and dropped from correlation
|
|
// analysis.
|
|
normalisedStdDev = ( maxValue - minValue ) / maxAbs;
|
|
}
|
|
|
|
if ( !std::isfinite( normalisedStdDev ) || normalisedStdDev < eps )
|
|
{
|
|
return 0.0;
|
|
}
|
|
return normalisedStdDev;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool RigEnsembleParameter::operator<( const RigEnsembleParameter& other ) const
|
|
{
|
|
if ( variationBin != other.variationBin )
|
|
{
|
|
return variationBin > other.variationBin; // Larger first
|
|
}
|
|
|
|
return name < other.name;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
QString RigEnsembleParameter::uiName() const
|
|
{
|
|
QString stem = name;
|
|
QString variationString;
|
|
if ( isNumeric() )
|
|
{
|
|
switch ( variationBin )
|
|
{
|
|
case NO_VARIATION:
|
|
variationString = QString( " (No variation)" );
|
|
break;
|
|
case LOW_VARIATION:
|
|
variationString = QString( " (Low variation)" );
|
|
break;
|
|
case MEDIUM_VARIATION:
|
|
variationString = QString( " (Medium variation)" );
|
|
break;
|
|
case HIGH_VARIATION:
|
|
variationString = QString( " (High variation)" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return QString( "%1%2" ).arg( stem ).arg( variationString );
|
|
}
|