Make P10/P90 calculation style more explicit

This commit is contained in:
Kristian Bendiksen 2021-09-16 10:38:27 +02:00 committed by GitHub
parent 0bfa6ae2d1
commit 1e83254e9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 149 additions and 116 deletions

View File

@ -20,39 +20,8 @@
#include "RiaStatisticsTools.h"
#include "RifEclipseSummaryAddress.h"
#include "RigStatisticsMath.h"
#include "cafAssert.h"
#include <QString>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QString RiaStatisticsTools::replacePercentileByPValueText( const QString& percentile )
{
QString result = percentile;
if ( result == ENSEMBLE_STAT_P10_QUANTITY_NAME )
{
result = ENSEMBLE_STAT_P90_QUANTITY_NAME;
}
else if ( result == ENSEMBLE_STAT_P90_QUANTITY_NAME )
{
result = ENSEMBLE_STAT_P10_QUANTITY_NAME;
}
else if ( percentile.contains( QString( "%1:" ).arg( ENSEMBLE_STAT_P10_QUANTITY_NAME ) ) )
{
result.replace( ENSEMBLE_STAT_P10_QUANTITY_NAME, ENSEMBLE_STAT_P90_QUANTITY_NAME );
}
else if ( percentile.contains( QString( "%1:" ).arg( ENSEMBLE_STAT_P90_QUANTITY_NAME ) ) )
{
result.replace( ENSEMBLE_STAT_P90_QUANTITY_NAME, ENSEMBLE_STAT_P10_QUANTITY_NAME );
}
return result;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -24,8 +24,6 @@
#include <numeric>
#include <vector>
class QString;
//==================================================================================================
//
//
@ -34,8 +32,6 @@ class QString;
class RiaStatisticsTools
{
public:
static const QString replacePercentileByPValueText( const QString& percentile );
template <class NumberType>
static bool isInvalidNumber( NumberType value )
{

View File

@ -240,7 +240,12 @@ void RifReaderEnsembleStatisticsRft::calculateStatistics( const RifEclipseRftAdd
pressuresAtDepth.push_back( curvePressures[depthIdx] );
}
double p10, p50, p90, mean;
RigStatisticsMath::calculateStatisticsCurves( pressuresAtDepth, &p10, &p50, &p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( pressuresAtDepth,
&p10,
&p50,
&p90,
&mean,
RigStatisticsMath::PercentileStyle::SWITCHED );
m_cachedValues[depthAddress].push_back( allDepths[depthIdx] );

View File

@ -1131,7 +1131,12 @@ void RimEnsembleFractureStatistics::generateStatisticsGrids(
double p50;
double p90;
double mean;
RigStatisticsMath::calculateStatisticsCurves( samples[idx], &p10, &p50, &p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( samples[idx],
&p10,
&p50,
&p90,
&mean,
RigStatisticsMath::PercentileStyle::SWITCHED );
if ( calculateP10 )
setValueNoInf( statisticsGrids[RimEnsembleFractureStatistics::StatisticsType::P10], x, y, p10 );

View File

@ -20,7 +20,6 @@
#include "RiaPreferences.h"
#include "RiaQDateTimeTools.h"
#include "RiaStatisticsTools.h"
#include "RiuGroupedBarChartBuilder.h"
#include "RiuPlotMainWindowTools.h"
#include "RiuQwtPlotWidget.h"

View File

@ -21,7 +21,6 @@
#include "RiaColorTables.h"
#include "RiaPreferences.h"
#include "RiaQDateTimeTools.h"
#include "RiaStatisticsTools.h"
#include "RiaTextStringTools.h"
#include "RifSummaryReaderInterface.h"

View File

@ -22,7 +22,6 @@
#include "RiaColorTools.h"
#include "RiaDateStringParser.h"
#include "RiaSimWellBranchTools.h"
#include "RiaStatisticsTools.h"
#include "RifReaderEclipseRft.h"
@ -582,7 +581,6 @@ void RimWellRftPlot::updateCurvesInPlot( const std::set<RiaRftPltCurveDefinition
QString uiText =
caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::uiText( rftAddress.wellLogChannel() );
QString label = uiText.replace( ": Pressure", "" );
label = RiaStatisticsTools::replacePercentileByPValueText( label );
curve->setSymbolLabel( label );
curve->setLineThickness( 3 );
}

View File

@ -481,9 +481,9 @@ QString Rim3dOverlayInfoConfig::resultInfoText( const RigHistogramData& histData
"<tr> <td>%1</td> <td> %2</td> <td> %3</td> <td> %4</td> <td> %5</td> <td> %6</td> </tr>"
"</table>" )
.arg( histData.min )
.arg( histData.p10 )
.arg( histData.mean )
.arg( histData.p90 )
.arg( histData.mean )
.arg( histData.p10 )
.arg( histData.max )
.arg( histData.sum );
}
@ -652,9 +652,9 @@ QString Rim3dOverlayInfoConfig::resultInfoText( const RigHistogramData& histData
"<tr> <td>%1</td> <td> %2</td> <td> %3</td> <td> %4</td> <td> %5</td> <td> %6</td> </tr>"
"</table>" )
.arg( histData.min )
.arg( histData.p10 )
.arg( histData.mean )
.arg( histData.p90 )
.arg( histData.mean )
.arg( histData.p10 )
.arg( histData.max )
.arg( histData.sum );
}
@ -863,7 +863,7 @@ void Rim3dOverlayInfoConfig::updateEclipse3DInfo( RimEclipseView* eclipseView )
{
eclipseView->viewer()->showHistogram( true );
eclipseView->viewer()->setHistogram( histData.min, histData.max, histData.histogram );
eclipseView->viewer()->setHistogramPercentiles( histData.p10, histData.p90, histData.mean );
eclipseView->viewer()->setHistogramPercentiles( histData.p90, histData.p10, histData.mean );
}
}
}
@ -912,7 +912,7 @@ void Rim3dOverlayInfoConfig::updateGeoMech3DInfo( RimGeoMechView* geoMechView )
{
geoMechView->viewer()->showHistogram( true );
geoMechView->viewer()->setHistogram( histData.min, histData.max, histData.histogram );
geoMechView->viewer()->setHistogramPercentiles( histData.p10, histData.p90, histData.mean );
geoMechView->viewer()->setHistogramPercentiles( histData.p90, histData.p10, histData.mean );
}
}
}

View File

@ -97,10 +97,7 @@ QString createResultNameRange( const QString& resultName )
}
QString createResultNamePVal( const QString& resultName, double pValPos )
{
// Invert the number for display text
double valueForDisplay = 100.0 - pValPos;
return resultName + "_P" + QString::number( valueForDisplay );
return resultName + "_P" + QString::number( pValPos );
}
//--------------------------------------------------------------------------------------------------
@ -296,7 +293,9 @@ void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList<ResSpec>
pValPoss.push_back( m_statisticsConfig.m_pMidPos );
pValPoss.push_back( m_statisticsConfig.m_pMaxPos );
std::vector<double> pVals =
RigStatisticsMath::calculateNearestRankPercentiles( values, pValPoss );
RigStatisticsMath::calculateNearestRankPercentiles( values,
pValPoss,
RigStatisticsMath::PercentileStyle::SWITCHED );
statParams[PMIN] = pVals[0];
statParams[PMID] = pVals[1];
statParams[PMAX] = pVals[2];
@ -306,9 +305,15 @@ void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList<ResSpec>
std::vector<size_t> histogram;
RigHistogramCalculator histCalc( statParams[MIN], statParams[MAX], 100, &histogram );
histCalc.addData( values );
statParams[PMIN] = histCalc.calculatePercentil( m_statisticsConfig.m_pMinPos / 100.0 );
statParams[PMID] = histCalc.calculatePercentil( m_statisticsConfig.m_pMidPos / 100.0 );
statParams[PMAX] = histCalc.calculatePercentil( m_statisticsConfig.m_pMaxPos / 100.0 );
statParams[PMIN] =
histCalc.calculatePercentil( m_statisticsConfig.m_pMinPos / 100.0,
RigStatisticsMath::PercentileStyle::SWITCHED );
statParams[PMID] =
histCalc.calculatePercentil( m_statisticsConfig.m_pMidPos / 100.0,
RigStatisticsMath::PercentileStyle::SWITCHED );
statParams[PMAX] =
histCalc.calculatePercentil( m_statisticsConfig.m_pMaxPos / 100.0,
RigStatisticsMath::PercentileStyle::SWITCHED );
}
else if ( m_statisticsConfig.m_pValMethod ==
RimEclipseStatisticsCase::INTERPOLATED_OBSERVATION )
@ -318,7 +323,9 @@ void RimEclipseStatisticsCaseEvaluator::evaluateForResults( const QList<ResSpec>
pValPoss.push_back( m_statisticsConfig.m_pMidPos );
pValPoss.push_back( m_statisticsConfig.m_pMaxPos );
std::vector<double> pVals =
RigStatisticsMath::calculateInterpolatedPercentiles( values, pValPoss );
RigStatisticsMath::calculateInterpolatedPercentiles( values,
pValPoss,
RigStatisticsMath::PercentileStyle::SWITCHED );
statParams[PMIN] = pVals[0];
statParams[PMID] = pVals[1];
statParams[PMAX] = pVals[2];

View File

@ -365,7 +365,7 @@ void RimStatisticsPlot::updatePlots()
p10series->attachAxis( axisY );
}
if ( !std::isinf( histogramData.p10 ) )
if ( !std::isinf( histogramData.p90 ) )
{
QLineSeries* p90series = new QLineSeries();
chart->addSeries( p90series );

View File

@ -22,7 +22,6 @@
#include "RiaGuiApplication.h"
#include "RiaPreferences.h"
#include "RiaResultNames.h"
#include "RiaStatisticsTools.h"
#include "RiaSummaryCurveAnalyzer.h"
#include "RiaSummaryCurveDefinition.h"
#include "RiaTimeTTools.h"
@ -31,8 +30,6 @@
#include "RifEnsembleStatisticsReader.h"
#include "RigStatisticsMath.h"
#include "RimCustomObjectiveFunction.h"
#include "RimCustomObjectiveFunctionCollection.h"
#include "RimDerivedEnsembleCaseCollection.h"
@ -1804,8 +1801,7 @@ void RimEnsembleCurveSet::updateStatisticsCurves( const std::vector<RimSummaryCa
curve->setSymbolSkipDistance( 150 );
if ( m_statistics->showCurveLabels() )
{
curve->setSymbolLabel( RiaStatisticsTools::replacePercentileByPValueText(
QString::fromStdString( address.ensembleStatisticsQuantityName() ) ) );
curve->setSymbolLabel( QString::fromStdString( address.ensembleStatisticsQuantityName() ) );
}
curve->setLineStyle( RiuQwtPlotCurveDefines::LineStyleEnum::STYLE_SOLID );
curve->setSummaryCaseY( m_ensembleStatCase.get() );

View File

@ -37,9 +37,9 @@ RimEnsembleStatistics::RimEnsembleStatistics( RimEnsembleCurveSetInterface* pare
CAF_PDM_InitField( &m_active, "Active", true, "Show Statistics Curves", "", "", "" );
CAF_PDM_InitField( &m_hideEnsembleCurves, "HideEnsembleCurves", false, "Hide Ensemble Curves", "", "", "" );
CAF_PDM_InitField( &m_basedOnFilteredCases, "BasedOnFilteredCases", false, "Based on Filtered Cases", "", "", "" );
CAF_PDM_InitField( &m_showP10Curve, "ShowP10Curve", true, "P90", "", "", "" ); // Yes, P90
CAF_PDM_InitField( &m_showP10Curve, "ShowP10Curve", true, "P10", "", "", "" );
CAF_PDM_InitField( &m_showP50Curve, "ShowP50Curve", false, "P50", "", "", "" );
CAF_PDM_InitField( &m_showP90Curve, "ShowP90Curve", true, "P10", "", "", "" ); // Yes, P10
CAF_PDM_InitField( &m_showP90Curve, "ShowP90Curve", true, "P90", "", "", "" );
CAF_PDM_InitField( &m_showMeanCurve, "ShowMeanCurve", true, "Mean", "", "", "" );
CAF_PDM_InitField( &m_showCurveLabels, "ShowCurveLabels", true, "Show Curve Labels", "", "", "" );
CAF_PDM_InitField( &m_includeIncompleteCurves, "IncludeIncompleteCurves", false, "Include Incomplete Curves", "", "", "" );
@ -149,8 +149,8 @@ void RimEnsembleStatistics::defineUiOrdering( QString uiConfigName, caf::PdmUiOr
m_showCurveLabels.uiCapability()->setUiReadOnly( !m_active );
m_color.uiCapability()->setUiReadOnly( !m_active );
m_showP10Curve.uiCapability()->setUiName( curveSet->hasP10Data() ? "P90" : "P90 (Needs > 8 curves)" );
m_showP90Curve.uiCapability()->setUiName( curveSet->hasP90Data() ? "P10" : "P10 (Needs > 8 curves)" );
m_showP10Curve.uiCapability()->setUiName( curveSet->hasP10Data() ? "P10" : "P10 (Needs > 8 curves)" );
m_showP90Curve.uiCapability()->setUiName( curveSet->hasP90Data() ? "P90" : "P90 (Needs > 8 curves)" );
uiOrdering.skipRemainingFields( true );
}

View File

@ -188,8 +188,12 @@ void RimEnsembleStatisticsCase::calculate( const std::vector<RimSummaryCase*> su
}
double p10, p50, p90, mean;
RigStatisticsMath::calculateStatisticsCurves( valuesAtTimeStep, &p10, &p50, &p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( valuesAtTimeStep,
&p10,
&p50,
&p90,
&mean,
RigStatisticsMath::PercentileStyle::SWITCHED );
m_p10Data.push_back( p10 );
m_p50Data.push_back( p50 );
m_p90Data.push_back( p90 );

View File

@ -24,7 +24,6 @@
#include "RiaLogging.h"
#include "RiaPreferencesSummary.h"
#include "RiaResultNames.h"
#include "RiaStatisticsTools.h"
#include "RiaSummaryCurveDefinition.h"
#include "RiaSummaryTools.h"
@ -941,11 +940,6 @@ QString RimSummaryCurve::curveExportDescription( const RifEclipseSummaryAddress&
auto group = curveSet ? curveSet->summaryCaseCollection() : nullptr;
auto addressUiText = addr.uiText();
if ( addr.category() == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS )
{
addressUiText =
RiaStatisticsTools::replacePercentileByPValueText( QString::fromStdString( addressUiText ) ).toStdString();
}
if ( group && group->isEnsemble() )
{

View File

@ -18,8 +18,6 @@
#include "RimSummaryCurveAutoName.h"
#include "RiaStatisticsTools.h"
#include "RifEclipseSummaryAddress.h"
#include "RimEnsembleCurveSet.h"
@ -196,9 +194,7 @@ QString RimSummaryCurveAutoName::buildCurveName( const RifEclipseSummaryAddress&
if ( summaryAddress.category() == RifEclipseSummaryAddress::SUMMARY_ENSEMBLE_STATISTICS )
{
text = RiaStatisticsTools::replacePercentileByPValueText(
QString::fromStdString( summaryAddress.quantityName() ) )
.toStdString();
text = summaryAddress.quantityName();
}
else if ( summaryAddress.category() == RifEclipseSummaryAddress::SUMMARY_CALCULATED )
{

View File

@ -145,7 +145,12 @@ void RimEnsembleWellLogStatistics::calculate( const std::vector<RimWellLogFile*>
valuesAtDepth.push_back( curveValues[depthIdx] );
}
double p10, p50, p90, mean;
RigStatisticsMath::calculateStatisticsCurves( valuesAtDepth, &p10, &p50, &p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( valuesAtDepth,
&p10,
&p50,
&p90,
&mean,
RigStatisticsMath::PercentileStyle::SWITCHED );
m_measuredDepths.push_back( allDepths[depthIdx] );
m_p10Data.push_back( p10 );
@ -216,7 +221,12 @@ void RimEnsembleWellLogStatistics::calculateByKLayer( const std::vector<RimWellL
{
std::vector<double> valuesAtDepth = topValues[kIndex];
double p10, p50, p90, mean;
RigStatisticsMath::calculateStatisticsCurves( valuesAtDepth, &p10, &p50, &p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( valuesAtDepth,
&p10,
&p50,
&p90,
&mean,
RigStatisticsMath::PercentileStyle::SWITCHED );
m_measuredDepths.push_back( offsets->getTopDepth( kIndex ) );
m_p10Data.push_back( p10 );
m_p50Data.push_back( p50 );
@ -230,7 +240,12 @@ void RimEnsembleWellLogStatistics::calculateByKLayer( const std::vector<RimWellL
{
std::vector<double> valuesAtDepth = bottomValues[kIndex];
double p10, p50, p90, mean;
RigStatisticsMath::calculateStatisticsCurves( valuesAtDepth, &p10, &p50, &p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( valuesAtDepth,
&p10,
&p50,
&p90,
&mean,
RigStatisticsMath::PercentileStyle::SWITCHED );
m_measuredDepths.push_back( offsets->getBottomDepth( kIndex ) );
m_p10Data.push_back( p10 );
m_p50Data.push_back( p50 );

View File

@ -22,7 +22,6 @@
#include "RiaEclipseUnitTools.h"
#include "RiaQDateTimeTools.h"
#include "RiaSimWellBranchTools.h"
#include "RiaStatisticsTools.h"
#include "RifEclipseRftAddress.h"
#include "RifReaderEclipseRft.h"
@ -359,7 +358,6 @@ QString RimWellLogRftCurve::createCurveAutoName()
RifEclipseRftAddress::RftWellLogChannelType channelNameEnum =
caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::fromText( wellLogChannelUiName() );
QString channelName = caf::AppEnum<RifEclipseRftAddress::RftWellLogChannelType>::uiText( channelNameEnum );
channelName = RiaStatisticsTools::replacePercentileByPValueText( channelName );
name.push_back( channelName );
}
if ( !m_timeStep().isNull() )

View File

@ -127,7 +127,12 @@ RigHistogramData RigEnsembleFractureStatisticsCalculator::createStatisticsData(
double p50;
double mean;
RigStatisticsMath::calculateStatisticsCurves( samples, &histogramData.p10, &p50, &histogramData.p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( samples,
&histogramData.p10,
&p50,
&histogramData.p90,
&mean,
RigStatisticsMath::PercentileStyle::SWITCHED );
std::vector<size_t> histogram;
RigHistogramCalculator histogramCalculator( histogramData.min, histogramData.max, numBins, &histogram );

View File

@ -82,7 +82,12 @@ cvf::ref<RigSurface> RigSurfaceStatisticsCalculator::computeStatistics( const st
double p10;
double p50;
double p90;
RigStatisticsMath::calculateStatisticsCurves( samples, &p10, &p50, &p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( samples,
&p10,
&p50,
&p90,
&mean,
RigStatisticsMath::PercentileStyle::SWITCHED );
// TODO: improve handling of these cases
auto makeValid = []( double val ) {

View File

@ -343,8 +343,8 @@ void RigStatisticsDataCache::computeHistogramStatisticsIfNeeded()
m_statisticsCalculator->addDataToHistogramCalculator( histCalc );
m_statsAllTimesteps.m_p10 = histCalc.calculatePercentil( 0.1 );
m_statsAllTimesteps.m_p90 = histCalc.calculatePercentil( 0.9 );
m_statsAllTimesteps.m_p10 = histCalc.calculatePercentil( 0.1, RigStatisticsMath::PercentileStyle::SWITCHED );
m_statsAllTimesteps.m_p90 = histCalc.calculatePercentil( 0.9, RigStatisticsMath::PercentileStyle::SWITCHED );
}
}
@ -364,8 +364,8 @@ void RigStatisticsDataCache::computeHistogramStatisticsIfNeeded( size_t timeStep
m_statisticsCalculator->addDataToHistogramCalculator( timeStepIndex, histCalc );
m_statsPrTs[timeStepIndex].m_p10 = histCalc.calculatePercentil( 0.1 );
m_statsPrTs[timeStepIndex].m_p90 = histCalc.calculatePercentil( 0.9 );
m_statsPrTs[timeStepIndex].m_p10 = histCalc.calculatePercentil( 0.1, RigStatisticsMath::PercentileStyle::SWITCHED );
m_statsPrTs[timeStepIndex].m_p90 = histCalc.calculatePercentil( 0.9, RigStatisticsMath::PercentileStyle::SWITCHED );
}
}

View File

@ -91,7 +91,8 @@ void RigStatisticsMath::calculateStatisticsCurves( const std::vector<double>& va
double* p10,
double* p50,
double* p90,
double* mean )
double* mean,
PercentileStyle percentileStyle )
{
CVF_ASSERT( p10 && p50 && p90 && mean );
@ -145,9 +146,20 @@ void RigStatisticsMath::calculateStatisticsCurves( const std::vector<double>& va
}
}
*p10 = pValues[P10];
*p50 = pValues[P50];
*p90 = pValues[P90];
*p50 = pValues[P50];
if ( percentileStyle == PercentileStyle::REGULAR )
{
*p10 = pValues[P10];
*p90 = pValues[P90];
}
else
{
CVF_ASSERT( percentileStyle == PercentileStyle::SWITCHED );
*p10 = pValues[P90];
*p90 = pValues[P10];
}
*mean = valueSum / valueCount;
}
@ -158,7 +170,8 @@ void RigStatisticsMath::calculateStatisticsCurves( const std::vector<double>& va
//--------------------------------------------------------------------------------------------------
std::vector<double> RigStatisticsMath::calculateNearestRankPercentiles( const std::vector<double>& inputValues,
const std::vector<double>& pValPositions )
const std::vector<double>& pValPositions,
RigStatisticsMath::PercentileStyle percentileStyle )
{
std::vector<double> sortedValues;
sortedValues.reserve( inputValues.size() );
@ -180,7 +193,10 @@ std::vector<double> RigStatisticsMath::calculateNearestRankPercentiles( const st
{
double pVal = HUGE_VAL;
size_t pValIndex = static_cast<size_t>( sortedValues.size() * cvf::Math::abs( pValPositions[i] ) / 100 );
double pValPosition = cvf::Math::abs( pValPositions[i] ) / 100;
if ( percentileStyle == RigStatisticsMath::PercentileStyle::SWITCHED ) pValPosition = 1.0 - pValPosition;
size_t pValIndex = static_cast<size_t>( sortedValues.size() * pValPosition );
if ( pValIndex >= sortedValues.size() ) pValIndex = sortedValues.size() - 1;
@ -198,7 +214,8 @@ std::vector<double> RigStatisticsMath::calculateNearestRankPercentiles( const st
/// the inputValues does not contain any valid values
//--------------------------------------------------------------------------------------------------
std::vector<double> RigStatisticsMath::calculateInterpolatedPercentiles( const std::vector<double>& inputValues,
const std::vector<double>& pValPositions )
const std::vector<double>& pValPositions,
RigStatisticsMath::PercentileStyle percentileStyle )
{
std::vector<double> sortedValues;
sortedValues.reserve( inputValues.size() );
@ -220,7 +237,10 @@ std::vector<double> RigStatisticsMath::calculateInterpolatedPercentiles( const s
{
double pVal = HUGE_VAL;
double doubleIndex = ( sortedValues.size() - 1 ) * cvf::Math::abs( pValPositions[i] ) / 100.0;
double pValPosition = cvf::Math::abs( pValPositions[i] ) / 100.0;
if ( percentileStyle == RigStatisticsMath::PercentileStyle::SWITCHED ) pValPosition = 1.0 - pValPosition;
double doubleIndex = ( sortedValues.size() - 1 ) * pValPosition;
size_t lowerValueIndex = static_cast<size_t>( floor( doubleIndex ) );
size_t upperValueIndex = lowerValueIndex + 1;
@ -315,12 +335,16 @@ void RigHistogramCalculator::addData( const std::vector<float>& data )
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
double RigHistogramCalculator::calculatePercentil( double pVal )
double RigHistogramCalculator::calculatePercentil( double pVal, RigStatisticsMath::PercentileStyle percentileStyle )
{
assert( m_histogram );
assert( m_histogram->size() );
auto pValClamped = cvf::Math::clamp( pVal, 0.0, 1.0 );
assert( 0.0 <= pValClamped && pValClamped <= 1.0 );
if ( percentileStyle == RigStatisticsMath::PercentileStyle::SWITCHED )
{
pValClamped = 1.0 - pValClamped;
}
double pValObservationCount = pValClamped * m_observationCount;
if ( pValObservationCount == 0.0 ) return m_min;

View File

@ -27,6 +27,12 @@
class RigStatisticsMath
{
public:
enum class PercentileStyle
{
REGULAR,
SWITCHED
};
static void calculateBasicStatistics( const std::vector<double>& values,
double* min,
double* max,
@ -34,13 +40,21 @@ public:
double* range,
double* mean,
double* dev );
static void
calculateStatisticsCurves( const std::vector<double>& values, double* p10, double* p50, double* p90, double* mean );
static void calculateStatisticsCurves( const std::vector<double>& values,
double* p10,
double* p50,
double* p90,
double* mean,
PercentileStyle percentileStyle );
static std::vector<double> calculateNearestRankPercentiles( const std::vector<double>& inputValues,
const std::vector<double>& pValPositions );
const std::vector<double>& pValPositions,
PercentileStyle percentileStyle );
static std::vector<double> calculateInterpolatedPercentiles( const std::vector<double>& inputValues,
const std::vector<double>& pValPositions );
const std::vector<double>& pValPositions,
PercentileStyle percentileStyle );
};
//==================================================================================================
@ -61,7 +75,7 @@ public:
/// the percentile is the domain value at which pVal of the observations are below it.
/// Will only consider observed values between min and max, as all other values are discarded from the histogram
double calculatePercentil( double pVal );
double calculatePercentil( double pVal, RigStatisticsMath::PercentileStyle percentileStyle );
private:
size_t m_maxIndex;

View File

@ -86,7 +86,8 @@ TEST( RigStatisticsMath, RankPercentiles )
pValPos.push_back( 40 );
pValPos.push_back( 50 );
pValPos.push_back( 90 );
std::vector<double> pVals = RigStatisticsMath::calculateNearestRankPercentiles( values, pValPos );
std::vector<double> pVals =
RigStatisticsMath::calculateNearestRankPercentiles( values, pValPos, RigStatisticsMath::PercentileStyle::REGULAR );
EXPECT_DOUBLE_EQ( -76092.8157632591000, pVals[0] );
EXPECT_DOUBLE_EQ( 2788.2723335651900, pVals[1] );
@ -126,9 +127,9 @@ TEST( RigStatisticsMath, HistogramPercentiles )
histCalc.addData( values );
double p10, p50, p90;
p10 = histCalc.calculatePercentil( 0.1 );
p50 = histCalc.calculatePercentil( 0.5 );
p90 = histCalc.calculatePercentil( 0.9 );
p10 = histCalc.calculatePercentil( 0.1, RigStatisticsMath::PercentileStyle::REGULAR );
p50 = histCalc.calculatePercentil( 0.5, RigStatisticsMath::PercentileStyle::REGULAR );
p90 = histCalc.calculatePercentil( 0.9, RigStatisticsMath::PercentileStyle::REGULAR );
EXPECT_DOUBLE_EQ( -76273.240559989776, p10 );
EXPECT_DOUBLE_EQ( 5312.1312871307755, p50 );
@ -164,10 +165,11 @@ TEST( RigStatisticsMath, InterpolatedPercentiles )
pValPos.push_back( 40 );
pValPos.push_back( 50 );
pValPos.push_back( 90 );
std::vector<double> pVals = RigStatisticsMath::calculateInterpolatedPercentiles( values, pValPos );
std::vector<double> pVals =
RigStatisticsMath::calculateInterpolatedPercentiles( values, pValPos, RigStatisticsMath::PercentileStyle::REGULAR );
EXPECT_DOUBLE_EQ( -72278.340409937548, pVals[0] );
EXPECT_DOUBLE_EQ( -2265.6006907818719, pVals[1] );
EXPECT_DOUBLE_EQ( -2265.6006907818496, pVals[1] );
EXPECT_DOUBLE_EQ( 6391.9799990972897, pVals[2] );
EXPECT_DOUBLE_EQ( 93073.49128098879, pVals[3] );
}
@ -226,6 +228,8 @@ TEST( RigStatisticsMath, Accumulators )
//--------------------------------------------------------------------------------------------------
TEST( RigStatisticsMath, calculateStatisticsCurves )
{
RigStatisticsMath::PercentileStyle percentileStyle = RigStatisticsMath::PercentileStyle::REGULAR;
{
std::vector<double> values;
@ -234,7 +238,7 @@ TEST( RigStatisticsMath, calculateStatisticsCurves )
double p50 = HUGE_VAL;
double p90 = HUGE_VAL;
RigStatisticsMath::calculateStatisticsCurves( values, &p10, &p50, &p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( values, &p10, &p50, &p90, &mean, percentileStyle );
EXPECT_TRUE( std::isinf( p10 ) );
EXPECT_TRUE( std::isinf( p50 ) );
EXPECT_TRUE( std::isinf( p90 ) );
@ -254,7 +258,7 @@ TEST( RigStatisticsMath, calculateStatisticsCurves )
double p90 = HUGE_VAL;
// If we have few samples, P10 and P90 cannot be computed
RigStatisticsMath::calculateStatisticsCurves( values, &p10, &p50, &p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( values, &p10, &p50, &p90, &mean, percentileStyle );
EXPECT_TRUE( std::isinf( p10 ) );
EXPECT_TRUE( std::isinf( p90 ) );
EXPECT_DOUBLE_EQ( 1.0, p50 );
@ -269,7 +273,7 @@ TEST( RigStatisticsMath, calculateStatisticsCurves )
double p50 = HUGE_VAL;
double p90 = HUGE_VAL;
RigStatisticsMath::calculateStatisticsCurves( values, &p10, &p50, &p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( values, &p10, &p50, &p90, &mean, percentileStyle );
EXPECT_DOUBLE_EQ( 1.0, p10 );
EXPECT_DOUBLE_EQ( 1.0, p50 );
EXPECT_FALSE( std::isinf( p90 ) );
@ -284,7 +288,7 @@ TEST( RigStatisticsMath, calculateStatisticsCurves )
double p50 = HUGE_VAL;
double p90 = HUGE_VAL;
RigStatisticsMath::calculateStatisticsCurves( values, &p10, &p50, &p90, &mean );
RigStatisticsMath::calculateStatisticsCurves( values, &p10, &p50, &p90, &mean, percentileStyle );
EXPECT_DOUBLE_EQ( 1.0, p10 );
EXPECT_DOUBLE_EQ( 1.0, p50 );
EXPECT_DOUBLE_EQ( 1.0, p90 );

View File

@ -74,8 +74,8 @@ TEST( RigSurfaceStatisticsTests, computeStatistics )
ASSERT_EQ( 49.5, meanValues[i] );
ASSERT_EQ( 0, minValues[i] );
ASSERT_EQ( 99, maxValues[i] );
ASSERT_NEAR( 9.1, p10Values[i], 0.0001 );
ASSERT_NEAR( 9.1, p90Values[i], 0.0001 );
ASSERT_NEAR( 49.5, p50Values[i], 0.0001 );
ASSERT_NEAR( 89.9, p90Values[i], 0.0001 );
ASSERT_NEAR( 89.9, p10Values[i], 0.0001 );
}
}