mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
#5706 Make Analysis plot filtering start working
This commit is contained in:
@@ -308,9 +308,8 @@ void RimAnalysisPlot::maxMinValueFromAddress( const RifEclipseSummaryAddress&
|
||||
double* minVal,
|
||||
double* maxVal )
|
||||
{
|
||||
std::vector<time_t> selectedTimesteps;
|
||||
double min = std::numeric_limits<double>::infinity();
|
||||
double max = useAbsValue ? 0.0 : -std::numeric_limits<double>::infinity();
|
||||
double min = std::numeric_limits<double>::infinity();
|
||||
double max = useAbsValue ? 0.0 : -std::numeric_limits<double>::infinity();
|
||||
|
||||
std::function<double( double, double )> minOrAbsMin;
|
||||
std::function<double( double, double )> maxOrAbsMax;
|
||||
@@ -326,6 +325,7 @@ void RimAnalysisPlot::maxMinValueFromAddress( const RifEclipseSummaryAddress&
|
||||
maxOrAbsMax = []( double v1, double v2 ) { return std::max( v1, v2 ); };
|
||||
}
|
||||
|
||||
std::vector<time_t> selectedTimesteps;
|
||||
if ( timeStepSourceType == RimPlotDataFilterItem::SELECT_TIMESTEPS )
|
||||
{
|
||||
for ( const QDateTime& dateTime : timeRangeOrSelection )
|
||||
@@ -335,10 +335,7 @@ void RimAnalysisPlot::maxMinValueFromAddress( const RifEclipseSummaryAddress&
|
||||
}
|
||||
else if ( timeStepSourceType == RimPlotDataFilterItem::PLOT_SOURCE_TIMESTEPS )
|
||||
{
|
||||
for ( const QDateTime& dateTime : m_selectedTimeSteps.v() )
|
||||
{
|
||||
selectedTimesteps.push_back( dateTime.toTime_t() );
|
||||
}
|
||||
selectedTimesteps = selectedTimeSteps();
|
||||
}
|
||||
|
||||
std::set<RimSummaryCase*> allSumCases = allSourceCases();
|
||||
@@ -355,7 +352,7 @@ void RimAnalysisPlot::maxMinValueFromAddress( const RifEclipseSummaryAddress&
|
||||
|
||||
const std::vector<time_t>& timesteps = reader->timeSteps( address );
|
||||
|
||||
if ( timesteps.size() )
|
||||
if ( timesteps.size() && values.size() )
|
||||
{
|
||||
if ( timeStepSourceType == RimPlotDataFilterItem::LAST_TIMESTEP )
|
||||
{
|
||||
@@ -409,21 +406,10 @@ void RimAnalysisPlot::maxMinValueFromAddress( const RifEclipseSummaryAddress&
|
||||
}
|
||||
else if ( selectedTimesteps.size() )
|
||||
{
|
||||
std::vector<int> selectedTimestepIndices;
|
||||
std::vector<size_t> selectedTimestepIndices =
|
||||
RimAnalysisPlot::findTimestepIndices( selectedTimesteps, timesteps );
|
||||
|
||||
for ( time_t tt : selectedTimesteps )
|
||||
{
|
||||
for ( int timestepIdx = 0; static_cast<unsigned>( timestepIdx ) < timesteps.size(); ++timestepIdx )
|
||||
{
|
||||
if ( timesteps[timestepIdx] == tt )
|
||||
{
|
||||
selectedTimestepIndices.push_back( timestepIdx );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( int tsIdx : selectedTimestepIndices )
|
||||
for ( size_t tsIdx : selectedTimestepIndices )
|
||||
{
|
||||
min = minOrAbsMin( min, values[tsIdx] );
|
||||
max = maxOrAbsMax( max, values[tsIdx] );
|
||||
@@ -442,6 +428,21 @@ void RimAnalysisPlot::maxMinValueFromAddress( const RifEclipseSummaryAddress&
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimAnalysisPlot::onFiltersChanged()
|
||||
{
|
||||
this->loadDataAndUpdate();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<time_t> RimAnalysisPlot::selectedTimeSteps()
|
||||
{
|
||||
std::vector<time_t> selectedTimeTTimeSteps;
|
||||
for ( const QDateTime& dateTime : m_selectedTimeSteps.v() )
|
||||
{
|
||||
selectedTimeTTimeSteps.push_back( dateTime.toTime_t() );
|
||||
}
|
||||
|
||||
return selectedTimeTTimeSteps;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -461,7 +462,7 @@ void RimAnalysisPlot::fieldChangedByUi( const caf::PdmFieldHandle* changedField,
|
||||
dlg.enableMultiSelect( true );
|
||||
dlg.enableIndividualEnsembleCaseSelection( true );
|
||||
|
||||
dlg.setCurveSelection( this->curveDefinitions() );
|
||||
dlg.setCurveSelection( this->curveDefinitionsWithCollapsedEnsembleCurves() );
|
||||
dlg.setCaseAndAddress( nullptr, RifEclipseSummaryAddress() );
|
||||
|
||||
if ( dlg.exec() == QDialog::Accepted )
|
||||
@@ -595,8 +596,8 @@ QList<caf::PdmOptionItemInfo> RimAnalysisPlot::calculateValueOptions( const caf:
|
||||
|
||||
if ( !m_analyserOfSelectedCurveDefs )
|
||||
{
|
||||
m_analyserOfSelectedCurveDefs =
|
||||
std::unique_ptr<RimCurveDefinitionAnalyser>( new RimCurveDefinitionAnalyser( this->curveDefinitions() ) );
|
||||
m_analyserOfSelectedCurveDefs = std::unique_ptr<RimCurveDefinitionAnalyser>(
|
||||
new RimCurveDefinitionAnalyser( this->curveDefinitionsWithCollapsedEnsembleCurves() ) );
|
||||
}
|
||||
|
||||
if ( fieldNeedingOptions == &m_addTimestepUiField )
|
||||
@@ -729,8 +730,8 @@ void RimAnalysisPlot::onLoadDataAndUpdate()
|
||||
{
|
||||
updateMdiWindowVisibility();
|
||||
|
||||
m_analyserOfSelectedCurveDefs =
|
||||
std::unique_ptr<RimCurveDefinitionAnalyser>( new RimCurveDefinitionAnalyser( this->curveDefinitions() ) );
|
||||
m_analyserOfSelectedCurveDefs = std::unique_ptr<RimCurveDefinitionAnalyser>(
|
||||
new RimCurveDefinitionAnalyser( this->curveDefinitionsWithCollapsedEnsembleCurves() ) );
|
||||
|
||||
if ( m_plotWidget )
|
||||
{
|
||||
@@ -884,7 +885,7 @@ void RimAnalysisPlot::updateAxes()
|
||||
|
||||
std::set<QString> timeHistoryQuantities;
|
||||
|
||||
RimSummaryPlotAxisFormatter calc( valAxisProperties, {}, curveDefinitions(), {}, {} );
|
||||
RimSummaryPlotAxisFormatter calc( valAxisProperties, {}, curveDefinitionsWithCollapsedEnsembleCurves(), {}, {} );
|
||||
calc.applyAxisPropertiesToPlot( m_plotWidget );
|
||||
}
|
||||
else
|
||||
@@ -1004,6 +1005,430 @@ QString assignGroupingText( RimAnalysisPlot::SortGroupType sortGroup,
|
||||
return groupingText;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<size_t> RimAnalysisPlot::findTimestepIndices( std::vector<time_t> selectedTimesteps,
|
||||
const std::vector<time_t>& timesteps )
|
||||
{
|
||||
std::vector<size_t> selectedTimestepIndices;
|
||||
|
||||
for ( time_t tt : selectedTimesteps )
|
||||
{
|
||||
for ( size_t timestepIdx = 0; timestepIdx < timesteps.size(); ++timestepIdx )
|
||||
{
|
||||
if ( timesteps[timestepIdx] == tt )
|
||||
{
|
||||
selectedTimestepIndices.push_back( timestepIdx );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return selectedTimestepIndices;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RiaSummaryCurveDefinition> RimAnalysisPlot::filteredCurveDefs()
|
||||
{
|
||||
std::vector<RiaSummaryCurveDefinition> dataDefinitions = curveDefinitionsWitExpandedEnsembleCurves();
|
||||
|
||||
// Split out the filter targets
|
||||
|
||||
std::set<RimSummaryCase*> filteredSumCases;
|
||||
std::set<RifEclipseSummaryAddress> filteredSummaryItems; // Stores only the unique summary items
|
||||
|
||||
for ( const auto& curveDef : dataDefinitions )
|
||||
{
|
||||
filteredSumCases.insert( curveDef.summaryCase() );
|
||||
|
||||
RifEclipseSummaryAddress address = curveDef.summaryAddress();
|
||||
|
||||
address.setQuantityName( "" ); // Quantity name set to "" in order to store only unique summary items
|
||||
filteredSummaryItems.insert( address );
|
||||
}
|
||||
|
||||
std::vector<RimPlotDataFilterItem*> filters = m_plotDataFilterCollection->filters();
|
||||
|
||||
for ( RimPlotDataFilterItem* filter : filters )
|
||||
{
|
||||
applyFilter( filter, &filteredSumCases, &filteredSummaryItems );
|
||||
}
|
||||
|
||||
// Remove all
|
||||
|
||||
std::vector<RiaSummaryCurveDefinition> filteredDataDefinitions;
|
||||
|
||||
for ( const RiaSummaryCurveDefinition& curveDefCandidate : dataDefinitions )
|
||||
{
|
||||
RimSummaryCase* sumCase = curveDefCandidate.summaryCase();
|
||||
RifEclipseSummaryAddress addr = curveDefCandidate.summaryAddress();
|
||||
addr.setQuantityName( "" );
|
||||
|
||||
if ( filteredSumCases.count( sumCase ) && filteredSummaryItems.count( addr ) )
|
||||
{
|
||||
filteredDataDefinitions.push_back( curveDefCandidate );
|
||||
}
|
||||
}
|
||||
|
||||
return filteredDataDefinitions;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
void RimAnalysisPlot::applyFilter( const RimPlotDataFilterItem* filter,
|
||||
std::set<RimSummaryCase*>* filteredSumCases,
|
||||
std::set<RifEclipseSummaryAddress>* filteredSummaryItems )
|
||||
{
|
||||
const std::vector<RiaSummaryCurveDefinition> curveDefsToFilter;
|
||||
|
||||
if ( !filter->isActive() ) return;
|
||||
|
||||
std::vector<RiaSummaryCurveDefinition> filteredCurveDefs;
|
||||
|
||||
std::set<RimSummaryCase*> casesToKeep;
|
||||
std::set<RifEclipseSummaryAddress> sumItemsToKeep;
|
||||
|
||||
std::map<RimSummaryCase*, double> casesToKeepWithValue;
|
||||
std::map<RifEclipseSummaryAddress, double> sumItemsToKeepWithValue;
|
||||
|
||||
if ( filter->filterTarget() == RimPlotDataFilterItem::ENSEMBLE_CASE )
|
||||
{
|
||||
sumItemsToKeep = ( *filteredSummaryItems ); // Not filtering items
|
||||
|
||||
EnsembleParameter eParam = this->ensembleParameter( filter->ensembleParameterName() );
|
||||
|
||||
std::set<RimSummaryCase*> casesToRemove;
|
||||
for ( auto sumCase : ( *filteredSumCases ) )
|
||||
{
|
||||
if ( !eParam.isValid() ) continue;
|
||||
if ( !sumCase->caseRealizationParameters() ) continue;
|
||||
|
||||
RigCaseRealizationParameters::Value crpValue =
|
||||
sumCase->caseRealizationParameters()->parameterValue( filter->ensembleParameterName() );
|
||||
|
||||
if ( eParam.isNumeric() && crpValue.isNumeric() )
|
||||
{
|
||||
double value = crpValue.numericValue();
|
||||
|
||||
if ( filter->filterOperation() == RimPlotDataFilterItem::RANGE )
|
||||
{
|
||||
std::pair<double, double> minMax = filter->filterRangeMinMax();
|
||||
|
||||
if ( filter->useAbsoluteValues() ) value = fabs( value );
|
||||
|
||||
if ( minMax.first < value && value < minMax.second )
|
||||
{
|
||||
casesToKeep.insert( sumCase );
|
||||
}
|
||||
}
|
||||
else if ( filter->filterOperation() == RimPlotDataFilterItem::TOP_N ||
|
||||
filter->filterOperation() == RimPlotDataFilterItem::BOTTOM_N )
|
||||
{
|
||||
if ( filter->useAbsoluteValues() ) value = fabs( value );
|
||||
bool useLargest = filter->filterOperation() == RimPlotDataFilterItem::TOP_N;
|
||||
|
||||
auto itIsInsertedPair = casesToKeepWithValue.insert( {sumCase, value} );
|
||||
if ( !itIsInsertedPair.second ) // Already exists in map
|
||||
{
|
||||
double& insertedValue = itIsInsertedPair.first->second;
|
||||
if ( ( useLargest && ( insertedValue < value ) ) || ( !useLargest && ( value < insertedValue ) ) )
|
||||
{
|
||||
insertedValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( eParam.isText() && crpValue.isText() )
|
||||
{
|
||||
const auto& filterCategories = filter->selectedEnsembleParameterCategories();
|
||||
|
||||
if ( crpValue.isText() &&
|
||||
std::count( filterCategories.begin(), filterCategories.end(), crpValue.textValue() ) == 0 )
|
||||
{
|
||||
casesToKeep.insert( sumCase );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<time_t> selectedTimesteps;
|
||||
|
||||
if ( filter->consideredTimeStepsType() == RimPlotDataFilterItem::SELECT_TIMESTEPS )
|
||||
{
|
||||
selectedTimesteps = filter->explicitlySelectedTimeSteps();
|
||||
}
|
||||
else if ( filter->consideredTimeStepsType() == RimPlotDataFilterItem::PLOT_SOURCE_TIMESTEPS )
|
||||
{
|
||||
selectedTimesteps = this->selectedTimeSteps();
|
||||
}
|
||||
|
||||
std::function<void( double )> storeResultCoreLambda;
|
||||
|
||||
RimSummaryCase* sumCaseInEvaluation = nullptr;
|
||||
|
||||
// clang-format off
|
||||
std::function<void( RifEclipseSummaryAddress )> evaluateFilterForAllCases =
|
||||
[&]( RifEclipseSummaryAddress addrToFilterValue ) // clang-format on
|
||||
{
|
||||
for ( auto sumCase : *filteredSumCases )
|
||||
{
|
||||
sumCaseInEvaluation = sumCase;
|
||||
|
||||
RifSummaryReaderInterface* reader = sumCase->summaryReader();
|
||||
if ( !reader ) continue;
|
||||
|
||||
if ( reader->hasAddress( addrToFilterValue ) )
|
||||
{
|
||||
std::vector<double> values;
|
||||
reader->values( addrToFilterValue, &values );
|
||||
const std::vector<time_t>& timesteps = reader->timeSteps( addrToFilterValue );
|
||||
|
||||
if ( filter->consideredTimeStepsType() == RimPlotDataFilterItem::ALL_TIMESTEPS )
|
||||
{
|
||||
for ( int tIdx = 0; tIdx < timesteps.size(); ++tIdx )
|
||||
{
|
||||
double value = values[tIdx];
|
||||
|
||||
storeResultCoreLambda( value );
|
||||
}
|
||||
}
|
||||
else if ( timesteps.size() )
|
||||
{
|
||||
std::vector<size_t> selectedTimestepIndices;
|
||||
|
||||
if ( filter->consideredTimeStepsType() == RimPlotDataFilterItem::FIRST_TIMESTEP )
|
||||
{
|
||||
selectedTimestepIndices.push_back( 0 );
|
||||
}
|
||||
else if ( filter->consideredTimeStepsType() == RimPlotDataFilterItem::LAST_TIMESTEP )
|
||||
{
|
||||
size_t timeStepIdx = timesteps.size() - 1;
|
||||
selectedTimestepIndices.push_back( timeStepIdx );
|
||||
}
|
||||
else if ( selectedTimesteps.size() )
|
||||
{
|
||||
selectedTimestepIndices = RimAnalysisPlot::findTimestepIndices( selectedTimesteps, timesteps );
|
||||
}
|
||||
else if ( filter->consideredTimeStepsType() == RimPlotDataFilterItem::LAST_TIMESTEP_WITH_HISTORY )
|
||||
{
|
||||
RifEclipseSummaryAddress historyAddr = addrToFilterValue;
|
||||
|
||||
if ( !historyAddr.isHistoryQuantity() )
|
||||
historyAddr.setQuantityName( addrToFilterValue.quantityName() + "H" );
|
||||
|
||||
const std::vector<time_t>& historyTimesteps = reader->timeSteps( historyAddr );
|
||||
if ( historyTimesteps.size() )
|
||||
{
|
||||
selectedTimestepIndices =
|
||||
RimAnalysisPlot::findTimestepIndices( {historyTimesteps.back()}, timesteps );
|
||||
}
|
||||
}
|
||||
else if ( filter->consideredTimeStepsType() == RimPlotDataFilterItem::SELECT_TIMESTEP_RANGE )
|
||||
{
|
||||
std::pair<time_t, time_t> timeMinMax = filter->timeRangeMinMax();
|
||||
|
||||
for ( size_t tIdx = 0; tIdx < timesteps.size(); ++tIdx )
|
||||
{
|
||||
time_t dateTime = timesteps[tIdx];
|
||||
|
||||
if ( timeMinMax.first <= dateTime && dateTime <= timeMinMax.second )
|
||||
{
|
||||
selectedTimestepIndices.push_back( tIdx );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t timeStepIdx : selectedTimestepIndices )
|
||||
{
|
||||
double value = values[timeStepIdx];
|
||||
storeResultCoreLambda( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if ( filter->filterTarget() == RimPlotDataFilterItem::SUMMARY_CASE )
|
||||
{
|
||||
sumItemsToKeep = ( *filteredSummaryItems ); // Not filtering items
|
||||
|
||||
RifEclipseSummaryAddress addrToFilterValue = filter->summaryAddress();
|
||||
|
||||
if ( filter->filterOperation() == RimPlotDataFilterItem::RANGE )
|
||||
{
|
||||
std::pair<double, double> minMax = filter->filterRangeMinMax();
|
||||
|
||||
// clang-format off
|
||||
storeResultCoreLambda = [&]( double value ) // clang-format on
|
||||
{
|
||||
if ( filter->useAbsoluteValues() ) value = fabs( value );
|
||||
|
||||
if ( minMax.first <= value && value <= minMax.second )
|
||||
{
|
||||
casesToKeep.insert( sumCaseInEvaluation );
|
||||
}
|
||||
};
|
||||
}
|
||||
else if ( filter->filterOperation() == RimPlotDataFilterItem::TOP_N ||
|
||||
filter->filterOperation() == RimPlotDataFilterItem::BOTTOM_N )
|
||||
{
|
||||
// clang-format off
|
||||
storeResultCoreLambda = [&]( double value ) // clang-format on
|
||||
{
|
||||
if ( filter->useAbsoluteValues() ) value = fabs( value );
|
||||
bool useLargest = filter->filterOperation() == RimPlotDataFilterItem::TOP_N;
|
||||
|
||||
auto itIsInsertedPair = casesToKeepWithValue.insert( {sumCaseInEvaluation, value} );
|
||||
if ( !itIsInsertedPair.second ) // Already exists in map
|
||||
{
|
||||
double& insertedValue = itIsInsertedPair.first->second;
|
||||
if ( ( useLargest && ( insertedValue < value ) ) || ( !useLargest && ( value < insertedValue ) ) )
|
||||
{
|
||||
insertedValue = value;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
evaluateFilterForAllCases( addrToFilterValue );
|
||||
}
|
||||
else if ( filter->filterTarget() == RimPlotDataFilterItem::SUMMARY_ITEM )
|
||||
{
|
||||
casesToKeep = ( *filteredSumCases ); // Not filtering cases
|
||||
|
||||
std::string quantityName;
|
||||
{
|
||||
RifEclipseSummaryAddress addrToFilterValue = filter->summaryAddress();
|
||||
|
||||
quantityName = addrToFilterValue.quantityName();
|
||||
}
|
||||
|
||||
for ( auto sumItem : *filteredSummaryItems )
|
||||
{
|
||||
RifEclipseSummaryAddress addrToFilterValue = sumItem;
|
||||
addrToFilterValue.setQuantityName( quantityName );
|
||||
|
||||
if ( filter->filterOperation() == RimPlotDataFilterItem::RANGE )
|
||||
{
|
||||
std::pair<double, double> minMax = filter->filterRangeMinMax();
|
||||
|
||||
// clang-format off
|
||||
storeResultCoreLambda = [&]( double value ) // clang-format on
|
||||
{
|
||||
if ( filter->useAbsoluteValues() ) value = fabs( value );
|
||||
|
||||
if ( minMax.first <= value && value <= minMax.second )
|
||||
{
|
||||
sumItemsToKeep.insert( sumItem );
|
||||
}
|
||||
};
|
||||
}
|
||||
else if ( filter->filterOperation() == RimPlotDataFilterItem::TOP_N ||
|
||||
filter->filterOperation() == RimPlotDataFilterItem::BOTTOM_N )
|
||||
{
|
||||
// clang-format off
|
||||
storeResultCoreLambda = [&]( double value ) // clang-format on
|
||||
{
|
||||
if ( filter->useAbsoluteValues() ) value = fabs( value );
|
||||
bool useLargest = filter->filterOperation() == RimPlotDataFilterItem::TOP_N;
|
||||
|
||||
auto itIsInsertedPair = sumItemsToKeepWithValue.insert( {sumItem, value} );
|
||||
if ( !itIsInsertedPair.second ) // Already exists in map
|
||||
{
|
||||
double& insertedValue = itIsInsertedPair.first->second;
|
||||
if ( ( useLargest && ( insertedValue < value ) ) ||
|
||||
( !useLargest && ( value < insertedValue ) ) )
|
||||
{
|
||||
insertedValue = value;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
evaluateFilterForAllCases( addrToFilterValue );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle top/bottom n filter
|
||||
|
||||
if ( filter->filterOperation() == RimPlotDataFilterItem::TOP_N ||
|
||||
filter->filterOperation() == RimPlotDataFilterItem::BOTTOM_N )
|
||||
{
|
||||
if ( filter->filterTarget() == RimPlotDataFilterItem::SUMMARY_ITEM )
|
||||
{
|
||||
std::multimap<double, RifEclipseSummaryAddress> valueSortedSumItems;
|
||||
for ( const auto& itemValPair : sumItemsToKeepWithValue )
|
||||
{
|
||||
valueSortedSumItems.insert( {itemValPair.second, itemValPair.first} );
|
||||
}
|
||||
|
||||
if ( filter->filterOperation() == RimPlotDataFilterItem::TOP_N )
|
||||
{
|
||||
size_t count = 0;
|
||||
for ( auto it = valueSortedSumItems.rbegin();
|
||||
count < filter->topBottomN() && it != valueSortedSumItems.rend();
|
||||
++it )
|
||||
{
|
||||
sumItemsToKeep.insert( it->second );
|
||||
++count;
|
||||
}
|
||||
}
|
||||
else if ( filter->filterOperation() == RimPlotDataFilterItem::BOTTOM_N )
|
||||
{
|
||||
size_t count = 0;
|
||||
for ( auto it = valueSortedSumItems.begin();
|
||||
count < filter->topBottomN() && it != valueSortedSumItems.end();
|
||||
++it )
|
||||
{
|
||||
sumItemsToKeep.insert( it->second );
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::multimap<double, RimSummaryCase*> valueSortedSumCases;
|
||||
for ( const auto& caseValPair : casesToKeepWithValue )
|
||||
{
|
||||
valueSortedSumCases.insert( {caseValPair.second, caseValPair.first} );
|
||||
}
|
||||
|
||||
if ( filter->filterOperation() == RimPlotDataFilterItem::TOP_N )
|
||||
{
|
||||
size_t count = 0;
|
||||
for ( auto it = valueSortedSumCases.rbegin();
|
||||
count < filter->topBottomN() && it != valueSortedSumCases.rend();
|
||||
++it )
|
||||
{
|
||||
casesToKeep.insert( it->second );
|
||||
++count;
|
||||
}
|
||||
}
|
||||
else if ( filter->filterOperation() == RimPlotDataFilterItem::BOTTOM_N )
|
||||
{
|
||||
size_t count = 0;
|
||||
for ( auto it = valueSortedSumCases.begin();
|
||||
count < filter->topBottomN() && it != valueSortedSumCases.end();
|
||||
++it )
|
||||
{
|
||||
casesToKeep.insert( it->second );
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
( *filteredSumCases ) = casesToKeep;
|
||||
( *filteredSummaryItems ) = sumItemsToKeep;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -1019,147 +1444,121 @@ void RimAnalysisPlot::addDataToChartBuilder( RiuGroupedBarChartBuilder& chartBui
|
||||
|
||||
if ( m_referenceCase ) referenceCaseReader = m_referenceCase->summaryReader();
|
||||
|
||||
for ( const RimAnalysisPlotDataEntry* dataEntry : m_analysisPlotDataSelection )
|
||||
// Unpack ensemble curves and make one curve definition for each individual curve.
|
||||
// Store both ensemble and summary case in the definition
|
||||
|
||||
std::vector<RiaSummaryCurveDefinition> barDataDefinitions = filteredCurveDefs();
|
||||
|
||||
for ( const RiaSummaryCurveDefinition& curveDef : barDataDefinitions )
|
||||
{
|
||||
RiaSummaryCurveDefinition orgBarDataEntry = dataEntry->curveDefinition();
|
||||
RifSummaryReaderInterface* reader = curveDef.summaryCase()->summaryReader();
|
||||
|
||||
// Unpack ensemble curves and make one curve definition for each individual curve.
|
||||
// Store both ensemble and summary case in the definition
|
||||
if ( !reader ) continue;
|
||||
|
||||
std::vector<RiaSummaryCurveDefinition> barDataDefinitions;
|
||||
// Todo:
|
||||
// If curveDef.summaryCase() is a RimGridSummaryCase and we are using summary item as legend and the summary
|
||||
// items are wells, then:
|
||||
/// use color from eclCase->defaultWellColor( wellName );
|
||||
|
||||
if ( orgBarDataEntry.isEnsembleCurve() )
|
||||
std::vector<time_t> timeStepStorage;
|
||||
const std::vector<time_t>* timeStepsPtr = &timeStepStorage;
|
||||
std::vector<double> values;
|
||||
|
||||
if ( referenceCaseReader )
|
||||
{
|
||||
std::vector<RimSummaryCase*> sumCases = orgBarDataEntry.ensemble()->allSummaryCases();
|
||||
for ( auto sumCase : sumCases )
|
||||
{
|
||||
barDataDefinitions.push_back(
|
||||
RiaSummaryCurveDefinition( sumCase, orgBarDataEntry.summaryAddress(), orgBarDataEntry.ensemble() ) );
|
||||
}
|
||||
std::pair<std::vector<time_t>, std::vector<double>> timeAndValues =
|
||||
RimDerivedSummaryCase::calculateDerivedValues( reader,
|
||||
referenceCaseReader,
|
||||
DerivedSummaryOperator::DERIVED_OPERATOR_SUB,
|
||||
curveDef.summaryAddress() );
|
||||
timeStepStorage.swap( timeAndValues.first );
|
||||
values.swap( timeAndValues.second );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( orgBarDataEntry.summaryCase() && orgBarDataEntry.summaryCase()->ensemble() )
|
||||
timeStepsPtr = &( reader->timeSteps( curveDef.summaryAddress() ) );
|
||||
|
||||
reader->values( curveDef.summaryAddress(), &values );
|
||||
}
|
||||
|
||||
const std::vector<time_t>& timesteps = *timeStepsPtr;
|
||||
|
||||
if ( !( timesteps.size() && values.size() ) ) continue;
|
||||
|
||||
// Find selected timestep indices
|
||||
|
||||
std::vector<int> selectedTimestepIndices;
|
||||
|
||||
for ( time_t tt : selectedTimesteps )
|
||||
{
|
||||
for ( int timestepIdx = 0; static_cast<unsigned>( timestepIdx ) < timesteps.size(); ++timestepIdx )
|
||||
{
|
||||
barDataDefinitions.push_back( RiaSummaryCurveDefinition( orgBarDataEntry.summaryCase(),
|
||||
orgBarDataEntry.summaryAddress(),
|
||||
orgBarDataEntry.summaryCase()->ensemble() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
barDataDefinitions.push_back( orgBarDataEntry );
|
||||
if ( timesteps[timestepIdx] == tt )
|
||||
{
|
||||
selectedTimestepIndices.push_back( timestepIdx );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( const RiaSummaryCurveDefinition& curveDef : barDataDefinitions )
|
||||
for ( int timestepIdx : selectedTimestepIndices )
|
||||
{
|
||||
RifSummaryReaderInterface* reader = curveDef.summaryCase()->summaryReader();
|
||||
double sortValue = std::numeric_limits<double>::infinity();
|
||||
|
||||
if ( !reader ) continue;
|
||||
QDateTime dateTime = RiaQDateTimeTools::fromTime_t( timesteps[timestepIdx] );
|
||||
QString formatString = RiaQDateTimeTools::createTimeFormatStringFromDates( {dateTime} );
|
||||
|
||||
// Todo:
|
||||
// If curveDef.summaryCase() is a RimGridSummaryCase and we are using summary item as legend and the summary
|
||||
// items are wells, then:
|
||||
/// use color from eclCase->defaultWellColor( wellName );
|
||||
QString timestepString = dateTime.toString( formatString );
|
||||
|
||||
std::vector<time_t> timeStepStorage;
|
||||
const std::vector<time_t>* timeStepsPtr = &timeStepStorage;
|
||||
std::vector<double> values;
|
||||
QString majorText = assignGroupingText( m_majorGroupType(), curveDef, timestepString );
|
||||
QString medText = assignGroupingText( m_mediumGroupType(), curveDef, timestepString );
|
||||
QString minText = assignGroupingText( m_minorGroupType(), curveDef, timestepString );
|
||||
QString legendText = assignGroupingText( m_sortGroupForLegend(), curveDef, timestepString );
|
||||
|
||||
if ( referenceCaseReader )
|
||||
double value = values[timestepIdx];
|
||||
|
||||
switch ( m_valueSortOperation() )
|
||||
{
|
||||
std::pair<std::vector<time_t>, std::vector<double>> timeAndValues =
|
||||
RimDerivedSummaryCase::calculateDerivedValues( reader,
|
||||
referenceCaseReader,
|
||||
DerivedSummaryOperator::DERIVED_OPERATOR_SUB,
|
||||
curveDef.summaryAddress() );
|
||||
timeStepStorage.swap( timeAndValues.first );
|
||||
values.swap( timeAndValues.second );
|
||||
}
|
||||
else
|
||||
{
|
||||
timeStepsPtr = &( reader->timeSteps( curveDef.summaryAddress() ) );
|
||||
|
||||
reader->values( curveDef.summaryAddress(), &values );
|
||||
case VALUE:
|
||||
sortValue = value;
|
||||
break;
|
||||
case ABS_VALUE:
|
||||
sortValue = fabs( value );
|
||||
break;
|
||||
}
|
||||
|
||||
const std::vector<time_t>& timesteps = *timeStepsPtr;
|
||||
QString barText;
|
||||
QString separator = " ";
|
||||
|
||||
// Find selected timestep indices
|
||||
|
||||
std::vector<int> selectedTimestepIndices;
|
||||
|
||||
for ( time_t tt : selectedTimesteps )
|
||||
if ( m_useBarText() )
|
||||
{
|
||||
for ( int timestepIdx = 0; static_cast<unsigned>( timestepIdx ) < timesteps.size(); ++timestepIdx )
|
||||
if ( m_useQuantityInBarText )
|
||||
{
|
||||
if ( timesteps[timestepIdx] == tt )
|
||||
{
|
||||
selectedTimestepIndices.push_back( timestepIdx );
|
||||
break;
|
||||
}
|
||||
barText += QString::fromStdString( curveDef.summaryAddress().quantityName() ) + separator;
|
||||
}
|
||||
|
||||
if ( m_useSummaryItemInBarText )
|
||||
{
|
||||
barText += QString::fromStdString( curveDef.summaryAddress().itemUiText() ) + separator;
|
||||
}
|
||||
|
||||
if ( m_useCaseInBarText && curveDef.summaryCase() )
|
||||
{
|
||||
barText += curveDef.summaryCase()->displayCaseName() + separator;
|
||||
}
|
||||
|
||||
if ( m_useEnsembleInBarText && curveDef.ensemble() )
|
||||
{
|
||||
barText += curveDef.ensemble()->name() + separator;
|
||||
}
|
||||
|
||||
if ( m_useTimeStepInBarText )
|
||||
{
|
||||
barText += timestepString + separator;
|
||||
}
|
||||
}
|
||||
|
||||
for ( int timestepIdx : selectedTimestepIndices )
|
||||
{
|
||||
double sortValue = std::numeric_limits<double>::infinity();
|
||||
|
||||
QDateTime dateTime = RiaQDateTimeTools::fromTime_t( timesteps[timestepIdx] );
|
||||
QString formatString = RiaQDateTimeTools::createTimeFormatStringFromDates( {dateTime} );
|
||||
|
||||
QString timestepString = dateTime.toString( formatString );
|
||||
|
||||
QString majorText = assignGroupingText( m_majorGroupType(), curveDef, timestepString );
|
||||
QString medText = assignGroupingText( m_mediumGroupType(), curveDef, timestepString );
|
||||
QString minText = assignGroupingText( m_minorGroupType(), curveDef, timestepString );
|
||||
QString legendText = assignGroupingText( m_sortGroupForLegend(), curveDef, timestepString );
|
||||
|
||||
double value = values[timestepIdx];
|
||||
|
||||
switch ( m_valueSortOperation() )
|
||||
{
|
||||
case VALUE:
|
||||
sortValue = value;
|
||||
break;
|
||||
case ABS_VALUE:
|
||||
sortValue = fabs( value );
|
||||
break;
|
||||
}
|
||||
|
||||
QString barText;
|
||||
QString separator = " ";
|
||||
|
||||
if ( m_useBarText() )
|
||||
{
|
||||
if ( m_useQuantityInBarText )
|
||||
{
|
||||
barText += QString::fromStdString( curveDef.summaryAddress().quantityName() ) + separator;
|
||||
}
|
||||
|
||||
if ( m_useSummaryItemInBarText )
|
||||
{
|
||||
barText += QString::fromStdString( curveDef.summaryAddress().itemUiText() ) + separator;
|
||||
}
|
||||
|
||||
if ( m_useCaseInBarText && curveDef.summaryCase() )
|
||||
{
|
||||
barText += curveDef.summaryCase()->displayCaseName() + separator;
|
||||
}
|
||||
|
||||
if ( m_useEnsembleInBarText && curveDef.ensemble() )
|
||||
{
|
||||
barText += curveDef.ensemble()->name() + separator;
|
||||
}
|
||||
|
||||
if ( m_useTimeStepInBarText )
|
||||
{
|
||||
barText += timestepString + separator;
|
||||
}
|
||||
}
|
||||
|
||||
chartBuilder.addBarEntry( majorText, medText, minText, sortValue, legendText, barText, value );
|
||||
}
|
||||
chartBuilder.addBarEntry( majorText, medText, minText, sortValue, legendText, barText, value );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1236,8 +1635,8 @@ RimCurveDefinitionAnalyser* RimAnalysisPlot::getOrCreateSelectedCurveDefAnalyser
|
||||
{
|
||||
if ( !m_analyserOfSelectedCurveDefs )
|
||||
{
|
||||
m_analyserOfSelectedCurveDefs =
|
||||
std::unique_ptr<RimCurveDefinitionAnalyser>( new RimCurveDefinitionAnalyser( this->curveDefinitions() ) );
|
||||
m_analyserOfSelectedCurveDefs = std::unique_ptr<RimCurveDefinitionAnalyser>(
|
||||
new RimCurveDefinitionAnalyser( this->curveDefinitionsWithCollapsedEnsembleCurves() ) );
|
||||
}
|
||||
|
||||
return m_analyserOfSelectedCurveDefs.get();
|
||||
@@ -1246,7 +1645,7 @@ RimCurveDefinitionAnalyser* RimAnalysisPlot::getOrCreateSelectedCurveDefAnalyser
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RiaSummaryCurveDefinition> RimAnalysisPlot::curveDefinitions() const
|
||||
std::vector<RiaSummaryCurveDefinition> RimAnalysisPlot::curveDefinitionsWithCollapsedEnsembleCurves() const
|
||||
{
|
||||
std::vector<RiaSummaryCurveDefinition> curveDefs;
|
||||
for ( auto dataEntry : m_analysisPlotDataSelection )
|
||||
@@ -1257,6 +1656,47 @@ std::vector<RiaSummaryCurveDefinition> RimAnalysisPlot::curveDefinitions() const
|
||||
return curveDefs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// The curve definitions returned contain both the case AND the ensemble from which it has been spawned
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<RiaSummaryCurveDefinition> RimAnalysisPlot::curveDefinitionsWitExpandedEnsembleCurves()
|
||||
{
|
||||
std::vector<RiaSummaryCurveDefinition> barDataDefinitions;
|
||||
|
||||
for ( const RimAnalysisPlotDataEntry* dataEntry : m_analysisPlotDataSelection )
|
||||
{
|
||||
RiaSummaryCurveDefinition orgBarDataEntry = dataEntry->curveDefinition();
|
||||
|
||||
// Unpack ensemble curves and make one curve definition for each individual curve.
|
||||
// Store both ensemble and summary case in the definition
|
||||
|
||||
if ( orgBarDataEntry.isEnsembleCurve() )
|
||||
{
|
||||
std::vector<RimSummaryCase*> sumCases = orgBarDataEntry.ensemble()->allSummaryCases();
|
||||
for ( auto sumCase : sumCases )
|
||||
{
|
||||
barDataDefinitions.push_back(
|
||||
RiaSummaryCurveDefinition( sumCase, orgBarDataEntry.summaryAddress(), orgBarDataEntry.ensemble() ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( orgBarDataEntry.summaryCase() && orgBarDataEntry.summaryCase()->ensemble() )
|
||||
{
|
||||
barDataDefinitions.push_back( RiaSummaryCurveDefinition( orgBarDataEntry.summaryCase(),
|
||||
orgBarDataEntry.summaryAddress(),
|
||||
orgBarDataEntry.summaryCase()->ensemble() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
barDataDefinitions.push_back( orgBarDataEntry );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return barDataDefinitions;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -66,6 +66,8 @@ public:
|
||||
|
||||
void onFiltersChanged();
|
||||
|
||||
std::vector<time_t> selectedTimeSteps();
|
||||
|
||||
public: // Internal. Public needed for AppEnum setup
|
||||
enum BarOrientation
|
||||
{
|
||||
@@ -149,8 +151,17 @@ private:
|
||||
void addDataToChartBuilder( RiuGroupedBarChartBuilder& chartBuilder );
|
||||
void updatePlotTitle();
|
||||
|
||||
RimCurveDefinitionAnalyser* getOrCreateSelectedCurveDefAnalyser();
|
||||
std::vector<RiaSummaryCurveDefinition> curveDefinitions() const;
|
||||
RimCurveDefinitionAnalyser* getOrCreateSelectedCurveDefAnalyser();
|
||||
std::vector<RiaSummaryCurveDefinition> curveDefinitionsWithCollapsedEnsembleCurves() const;
|
||||
std::vector<RiaSummaryCurveDefinition> curveDefinitionsWitExpandedEnsembleCurves();
|
||||
std::vector<RiaSummaryCurveDefinition> filteredCurveDefs();
|
||||
void applyFilter( const RimPlotDataFilterItem* filter,
|
||||
std::set<RimSummaryCase*>* filteredSumCases,
|
||||
std::set<RifEclipseSummaryAddress>* filteredSummaryItems );
|
||||
|
||||
static std::vector<size_t> findTimestepIndices( std::vector<time_t> selectedTimesteps,
|
||||
const std::vector<time_t>& timesteps );
|
||||
|
||||
std::set<RimPlotAxisPropertiesInterface*> allPlotAxes() const;
|
||||
|
||||
void buildTestPlot( RiuGroupedBarChartBuilder& chartBuilder );
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#include "RimSummaryAddress.h"
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
|
||||
#include "RifSummaryReaderInterface.h"
|
||||
#include "RimSummaryCase.h"
|
||||
|
||||
#include "cafPdmUiActionPushButtonEditor.h"
|
||||
#include "cafPdmUiDoubleSliderEditor.h"
|
||||
#include "cafPdmUiLineEditor.h"
|
||||
@@ -44,7 +47,7 @@ void caf::AppEnum<RimPlotDataFilterItem::FilterOperation>::setUp()
|
||||
{
|
||||
addItem( RimPlotDataFilterItem::RANGE, "RANGE", "Range" );
|
||||
addItem( RimPlotDataFilterItem::TOP_N, "TOP_N", "Top N" );
|
||||
addItem( RimPlotDataFilterItem::MIN_N, "MIN_N", "Min N" );
|
||||
addItem( RimPlotDataFilterItem::BOTTOM_N, "BOTTOM_N", "Bottom N" );
|
||||
|
||||
setDefault( RimPlotDataFilterItem::RANGE );
|
||||
}
|
||||
@@ -83,6 +86,7 @@ RimPlotDataFilterItem::RimPlotDataFilterItem()
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_filterAddress, "FilterAddressField", "Filter Address", "", "", "" );
|
||||
m_filterAddress.uiCapability()->setUiTreeHidden( true );
|
||||
m_filterAddress = new RimSummaryAddress();
|
||||
|
||||
CAF_PDM_InitField( &m_filterEnsembleParameter, "QuantityText", QString( "" ), "Quantity", "", "", "" );
|
||||
|
||||
@@ -95,7 +99,7 @@ RimPlotDataFilterItem::RimPlotDataFilterItem()
|
||||
|
||||
CAF_PDM_InitFieldNoDefault( &m_filterOperation, "FilterOperation", "Operation", "", "", "" );
|
||||
CAF_PDM_InitField( &m_useAbsoluteValue, "UseAbsoluteValue", true, "Use Abs(value)", "", "", "" );
|
||||
CAF_PDM_InitField( &m_minTopN, "MinTopN", 20, "N", "", "", "" );
|
||||
CAF_PDM_InitField( &m_topBottomN, "MinTopN", 20, "N", "", "", "" );
|
||||
CAF_PDM_InitField( &m_max, "Max", 0.0, "Max", "", "", "" );
|
||||
m_max.uiCapability()->setUiEditorTypeName( caf::PdmUiDoubleSliderEditor::uiEditorTypeName() );
|
||||
CAF_PDM_InitField( &m_min, "Min", 0.0, "Min", "", "", "" );
|
||||
@@ -120,6 +124,95 @@ RimPlotDataFilterItem::~RimPlotDataFilterItem()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RifEclipseSummaryAddress RimPlotDataFilterItem::summaryAddress() const
|
||||
{
|
||||
CVF_ASSERT( m_filterTarget() == SUMMARY_CASE || m_filterTarget() == SUMMARY_ITEM );
|
||||
return m_filterAddress->address();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimPlotDataFilterItem::ensembleParameterName() const
|
||||
{
|
||||
CVF_ASSERT( m_filterTarget() == ENSEMBLE_CASE );
|
||||
return m_filterEnsembleParameter();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<double, double> RimPlotDataFilterItem::filterRangeMinMax() const
|
||||
{
|
||||
CVF_ASSERT( m_filterOperation() == RANGE );
|
||||
return std::make_pair( m_min(), m_max() );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
int RimPlotDataFilterItem::topBottomN() const
|
||||
{
|
||||
CVF_ASSERT( m_filterOperation() != RANGE );
|
||||
return m_topBottomN;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<QString> RimPlotDataFilterItem::selectedEnsembleParameterCategories() const
|
||||
{
|
||||
CVF_ASSERT( m_filterTarget() == ENSEMBLE_CASE );
|
||||
return m_ensembleParameterValueCategories;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RimPlotDataFilterItem::TimeStepSourceType RimPlotDataFilterItem::consideredTimeStepsType() const
|
||||
{
|
||||
CVF_ASSERT( m_filterTarget() != ENSEMBLE_CASE );
|
||||
return m_consideredTimestepsType();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::pair<time_t, time_t> RimPlotDataFilterItem::timeRangeMinMax() const
|
||||
{
|
||||
CVF_ASSERT( m_consideredTimestepsType() == RANGE );
|
||||
|
||||
if ( m_explicitlySelectedTimeSteps().size() >= 2 )
|
||||
{
|
||||
time_t minTime = m_explicitlySelectedTimeSteps().front().toTime_t();
|
||||
time_t maxTime = m_explicitlySelectedTimeSteps().back().toTime_t();
|
||||
|
||||
return std::make_pair( minTime, maxTime );
|
||||
}
|
||||
return std::make_pair( time_t( 0 ), time_t( 0 ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
std::vector<time_t> RimPlotDataFilterItem::explicitlySelectedTimeSteps() const
|
||||
{
|
||||
CVF_ASSERT( m_consideredTimestepsType == RimPlotDataFilterItem::SELECT_TIMESTEPS );
|
||||
|
||||
std::vector<time_t> selectedTimesteps;
|
||||
{
|
||||
for ( const QDateTime& dateTime : m_explicitlySelectedTimeSteps() )
|
||||
{
|
||||
selectedTimesteps.push_back( dateTime.toTime_t() );
|
||||
}
|
||||
}
|
||||
|
||||
return selectedTimesteps;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@@ -135,8 +228,9 @@ void RimPlotDataFilterItem::fieldChangedByUi( const caf::PdmFieldHandle* changed
|
||||
this->updateMaxMinAndDefaultValues( true );
|
||||
parentPlot->onFiltersChanged();
|
||||
}
|
||||
else if ( changedField == &m_filterAddress )
|
||||
else if ( changedField == &m_filterQuantityUiField )
|
||||
{
|
||||
m_filterAddress->setAddress( m_filterQuantityUiField );
|
||||
this->updateMaxMinAndDefaultValues( true );
|
||||
parentPlot->onFiltersChanged();
|
||||
}
|
||||
@@ -232,6 +326,11 @@ caf::PdmFieldHandle* RimPlotDataFilterItem::objectToggleField()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RimPlotDataFilterItem::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
|
||||
{
|
||||
if ( m_filterAddress )
|
||||
{
|
||||
m_filterQuantityUiField = m_filterAddress->address();
|
||||
}
|
||||
|
||||
updateMaxMinAndDefaultValues( false );
|
||||
|
||||
uiOrdering.add( &m_filterTarget, {true, 4, 1} );
|
||||
@@ -265,9 +364,9 @@ void RimPlotDataFilterItem::defineUiOrdering( QString uiConfigName, caf::PdmUiOr
|
||||
uiOrdering.add( &m_max, {true, 4, 1} );
|
||||
uiOrdering.add( &m_min, {true, 4, 1} );
|
||||
}
|
||||
else if ( m_filterOperation == TOP_N || m_filterOperation == MIN_N )
|
||||
else if ( m_filterOperation == TOP_N || m_filterOperation == BOTTOM_N )
|
||||
{
|
||||
uiOrdering.add( &m_minTopN, {true, 4, 1} );
|
||||
uiOrdering.add( &m_topBottomN, {true, 4, 1} );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,8 +424,19 @@ void RimPlotDataFilterItem::updateMaxMinAndDefaultValues( bool forceDefault )
|
||||
EnsembleParameter eParam = selectedEnsembleParameter();
|
||||
if ( eParam.isValid() && eParam.isNumeric() )
|
||||
{
|
||||
if ( RiaCurveDataTools::isValidValue( eParam.minValue, false ) ) m_lowerLimit = eParam.minValue;
|
||||
if ( RiaCurveDataTools::isValidValue( eParam.maxValue, false ) ) m_upperLimit = eParam.maxValue;
|
||||
if ( RiaCurveDataTools::isValidValue( eParam.minValue, false ) )
|
||||
{
|
||||
m_lowerLimit = eParam.minValue;
|
||||
if ( m_useAbsoluteValue ) m_lowerLimit = fabs( eParam.minValue );
|
||||
}
|
||||
if ( RiaCurveDataTools::isValidValue( eParam.maxValue, false ) )
|
||||
{
|
||||
m_upperLimit = eParam.maxValue;
|
||||
if ( m_useAbsoluteValue ) m_upperLimit = fabs( eParam.maxValue );
|
||||
}
|
||||
|
||||
// Make sure max is > min after doing abs
|
||||
if ( m_upperLimit < m_lowerLimit ) std::swap( m_upperLimit, m_lowerLimit );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include "RimSummaryCaseCollection.h"
|
||||
|
||||
#include "RiaSummaryCurveDefinition.h"
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
class RiuSummaryQwtPlot;
|
||||
@@ -64,6 +66,41 @@ public:
|
||||
SELECT_TIMESTEP_RANGE
|
||||
};
|
||||
|
||||
// Filter target
|
||||
enum FilterTarget
|
||||
{
|
||||
SUMMARY_ITEM,
|
||||
SUMMARY_CASE,
|
||||
ENSEMBLE_CASE
|
||||
};
|
||||
|
||||
enum FilterOperation
|
||||
{
|
||||
TOP_N,
|
||||
BOTTOM_N,
|
||||
RANGE
|
||||
};
|
||||
|
||||
std::vector<RiaSummaryCurveDefinition> applyFilter( const std::vector<RiaSummaryCurveDefinition>& curveDefsToFilter );
|
||||
|
||||
bool isActive() const { return m_isActive(); }
|
||||
FilterTarget filterTarget() const { return m_filterTarget(); }
|
||||
|
||||
RifEclipseSummaryAddress summaryAddress() const;
|
||||
|
||||
QString ensembleParameterName() const;
|
||||
|
||||
FilterOperation filterOperation() const { return m_filterOperation(); }
|
||||
bool useAbsoluteValues() const { return m_useAbsoluteValue(); }
|
||||
std::pair<double, double> filterRangeMinMax() const;
|
||||
int topBottomN() const;
|
||||
|
||||
std::vector<QString> selectedEnsembleParameterCategories() const;
|
||||
|
||||
TimeStepSourceType consideredTimeStepsType() const;
|
||||
std::pair<time_t, time_t> timeRangeMinMax() const;
|
||||
std::vector<time_t> explicitlySelectedTimeSteps() const;
|
||||
|
||||
private:
|
||||
void fieldChangedByUi( const caf::PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue ) override;
|
||||
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
|
||||
@@ -80,14 +117,6 @@ private:
|
||||
|
||||
caf::PdmField<bool> m_isActive;
|
||||
|
||||
// Filter target
|
||||
enum FilterTarget
|
||||
{
|
||||
SUMMARY_ITEM,
|
||||
SUMMARY_CASE,
|
||||
ENSEMBLE_CASE
|
||||
};
|
||||
friend caf::AppEnum<FilterTarget>;
|
||||
caf::PdmField<caf::AppEnum<FilterTarget>> m_filterTarget;
|
||||
|
||||
// Quantity
|
||||
@@ -100,17 +129,9 @@ private:
|
||||
|
||||
// Operation and parameters
|
||||
|
||||
enum FilterOperation
|
||||
{
|
||||
TOP_N,
|
||||
MIN_N,
|
||||
RANGE
|
||||
};
|
||||
friend caf::AppEnum<FilterOperation>;
|
||||
|
||||
caf::PdmField<caf::AppEnum<FilterOperation>> m_filterOperation;
|
||||
caf::PdmField<bool> m_useAbsoluteValue;
|
||||
caf::PdmField<int> m_minTopN;
|
||||
caf::PdmField<int> m_topBottomN;
|
||||
caf::PdmField<double> m_max;
|
||||
caf::PdmField<double> m_min;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user