#9126 Improve plot and curve handling for ensembles

Add append plots and append curves to context menu of ensembles
Make sure we create an unique color when adding multiple ensembles
This commit is contained in:
Magne Sjaastad 2022-07-08 14:54:48 +02:00
parent ee715a86e0
commit f80fde85ca
11 changed files with 221 additions and 71 deletions

View File

@ -196,8 +196,10 @@ cvf::Color3f RiaColorTools::makeLighter( const cvf::Color3f& color, float normal
double l = 0.0;
qColor.getHslF( &h, &s, &l );
// A negative value will make the color darker
l = l + ( 1.0 - l ) * normalizedScalingFactor;
l = std::min( 1.0, l );
l = std::clamp( l, 0.0, 1.0 );
qColor.setHslF( h, s, l );

View File

@ -24,6 +24,7 @@
#include "RimSummaryAddressCollection.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryMultiPlot.h"
#include "RimSummaryPlot.h"
@ -77,12 +78,21 @@ void RicAppendSummaryCurvesForSummaryCasesFeature::setupActionLook( QAction* act
//--------------------------------------------------------------------------------------------------
std::vector<caf::PdmObjectHandle*> RicAppendSummaryCurvesForSummaryCasesFeature::selectedCases()
{
std::vector<RimSummaryCase*> objects;
caf::SelectionManager::instance()->objectsByType( &objects );
// Make the object type general to match the expected type for handleDroppedObjects();
std::vector<caf::PdmObjectHandle*> generalObjects;
generalObjects.insert( generalObjects.begin(), objects.begin(), objects.end() );
{
std::vector<RimSummaryCase*> objects;
caf::SelectionManager::instance()->objectsByType( &objects );
generalObjects.insert( generalObjects.begin(), objects.begin(), objects.end() );
}
{
std::vector<RimSummaryCaseCollection*> objects;
caf::SelectionManager::instance()->objectsByType( &objects );
generalObjects.insert( generalObjects.begin(), objects.begin(), objects.end() );
}
return generalObjects;
}

View File

@ -77,9 +77,21 @@ void RicAppendSummaryPlotsForObjectsFeature::appendPlots( RimSummaryMultiPlot* s
summaryMultiPlot->addPlot( duplicatedPlot );
auto summaryCase = RiaSummaryTools::summaryCaseById( summaryAdrCollection->caseId() );
for ( auto c : duplicatedPlot->summaryCurves() )
if ( summaryCase )
{
c->setSummaryCaseY( summaryCase );
for ( auto c : duplicatedPlot->summaryCurves() )
{
c->setSummaryCaseY( summaryCase );
}
}
auto ensemble = RiaSummaryTools::ensembleById( summaryAdrCollection->ensembleId() );
if ( ensemble )
{
for ( auto c : duplicatedPlot->curveSets() )
{
c->setSummaryCaseCollection( ensemble );
}
}
}
else
@ -102,6 +114,51 @@ void RicAppendSummaryPlotsForObjectsFeature::appendPlots( RimSummaryMultiPlot* s
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicAppendSummaryPlotsForObjectsFeature::appendPlots( RimSummaryMultiPlot* summaryMultiPlot,
const std::vector<RimSummaryCase*>& cases,
const std::vector<RimSummaryCaseCollection*>& ensembles )
{
auto addressCollectionsToBeDeleted =
RicAppendSummaryPlotsForObjectsFeature::createAddressCollections( cases, ensembles );
RicAppendSummaryPlotsForObjectsFeature::appendPlots( summaryMultiPlot, addressCollectionsToBeDeleted );
for ( auto obj : addressCollectionsToBeDeleted )
{
delete obj;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryAddressCollection*>
RicAppendSummaryPlotsForObjectsFeature::createAddressCollections( const std::vector<RimSummaryCase*>& cases,
const std::vector<RimSummaryCaseCollection*>& ensembles )
{
std::vector<RimSummaryAddressCollection*> addresses;
for ( auto c : cases )
{
auto myColl = new RimSummaryAddressCollection;
myColl->setContentType( RimSummaryAddressCollection::CollectionContentType::SUMMARY_CASE );
myColl->setCaseId( c->caseId() );
addresses.push_back( myColl );
}
for ( auto c : ensembles )
{
auto myColl = new RimSummaryAddressCollection;
myColl->setContentType( RimSummaryAddressCollection::CollectionContentType::SUMMARY_CASE );
myColl->setEnsembleId( c->ensembleId() );
addresses.push_back( myColl );
}
return addresses;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -276,8 +333,9 @@ std::vector<RimSummaryPlot*> RicAppendSummaryPlotsForObjectsFeature::plotsForOne
std::string wellNameToMatch;
std::string groupNameToMatch;
int regionToMatch = -1;
int caseIdToMatch = -1;
int regionToMatch = -1;
int caseIdToMatch = -1;
int ensembleIdToMatch = -1;
RiaSummaryAddressAnalyzer myAnalyser;
for ( auto sourcePlot : sourcePlots )
@ -307,6 +365,11 @@ std::vector<RimSummaryPlot*> RicAppendSummaryPlotsForObjectsFeature::plotsForOne
{
caseIdToMatch = curves.front()->summaryCaseY()->caseId();
}
auto curveSets = sourcePlots.back()->curveSets();
if ( !curveSets.empty() )
{
ensembleIdToMatch = curveSets.front()->ensembleId();
}
}
}
@ -322,6 +385,14 @@ std::vector<RimSummaryPlot*> RicAppendSummaryPlotsForObjectsFeature::plotsForOne
if ( c->summaryCaseY()->caseId() == caseIdToMatch ) isMatching = true;
}
}
else if ( ensembleIdToMatch != -1 )
{
auto curveSets = sourcePlot->curveSets();
for ( auto c : curveSets )
{
if ( c->summaryCaseCollection()->ensembleId() == ensembleIdToMatch ) isMatching = true;
}
}
else
{
auto addresses = RimSummaryAddressModifier::createEclipseSummaryAddress( sourcePlot );

View File

@ -29,6 +29,8 @@ class RimSummaryAddressCollection;
class RimSummaryMultiPlot;
class RifEclipseSummaryAddress;
class RimSummaryPlot;
class RimSummaryCase;
class RimSummaryCaseCollection;
//==================================================================================================
///
@ -39,21 +41,31 @@ class RicAppendSummaryPlotsForObjectsFeature : public caf::CmdFeature
public:
static std::vector<RimSummaryAddressCollection*> selectedCollections();
static std::vector<RimSummaryPlot*>
plotsForOneInstanceOfObjectType( const std::vector<RimSummaryPlot*>& sourcePlots,
RimSummaryAddressCollection::CollectionContentType objectType );
plotsForOneInstanceOfObjectType( const std::vector<RimSummaryPlot*>& sourcePlots,
RimSummaryAddressCollection::CollectionContentType objectType );
static bool isSelectionCompatibleWithPlot( const std::vector<RimSummaryAddressCollection*>& selection,
RimSummaryMultiPlot* summaryMultiPlot );
static void appendPlots( RimSummaryMultiPlot* summaryMultiPlot,
const std::vector<RimSummaryAddressCollection*>& selection );
static void appendPlots( RimSummaryMultiPlot* summaryMultiPlot,
const std::vector<RimSummaryCase*>& cases,
const std::vector<RimSummaryCaseCollection*>& ensembles );
protected:
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
private:
static std::vector<RimSummaryAddressCollection*>
createAddressCollections( const std::vector<RimSummaryCase*>& cases,
const std::vector<RimSummaryCaseCollection*>& ensembles );
static RifEclipseSummaryAddress modifyAddress( const RifEclipseSummaryAddress& sourceAddress,
RimSummaryAddressCollection* summaryAddressCollection );
};

View File

@ -24,6 +24,7 @@
#include "RimSummaryAddressCollection.h"
#include "RimSummaryCase.h"
#include "RimSummaryCaseCollection.h"
#include "RimSummaryMultiPlot.h"
#include "cafSelectionManager.h"
@ -32,39 +33,17 @@
CAF_CMD_SOURCE_INIT( RicAppendSummaryPlotsForSummaryCasesFeature, "RicAppendSummaryPlotsForSummaryCasesFeature" );
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicAppendSummaryPlotsForSummaryCasesFeature::appendPlotsForCases( RimSummaryMultiPlot* summaryMultiPlot,
const std::vector<RimSummaryCase*>& cases )
{
if ( !summaryMultiPlot ) return;
if ( cases.empty() ) return;
std::vector<RimSummaryAddressCollection*> tmp;
for ( auto c : cases )
{
auto myColl = new RimSummaryAddressCollection;
myColl->setContentType( RimSummaryAddressCollection::CollectionContentType::SUMMARY_CASE );
myColl->setCaseId( c->caseId() );
tmp.push_back( myColl );
}
RicAppendSummaryPlotsForObjectsFeature::appendPlots( summaryMultiPlot, tmp );
for ( auto obj : tmp )
{
delete obj;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicAppendSummaryPlotsForSummaryCasesFeature::isCommandEnabled()
{
return !selectedCases().empty();
auto cases = selectedCases();
auto ensembles = selectedEnsembles();
if ( cases.empty() && ensembles.empty() ) return false;
return true;
}
//--------------------------------------------------------------------------------------------------
@ -77,10 +56,10 @@ void RicAppendSummaryPlotsForSummaryCasesFeature::onActionTriggered( bool isChec
auto summaryMultiPlot = dynamic_cast<RimSummaryMultiPlot*>( app->activePlotWindow() );
if ( !summaryMultiPlot ) return;
auto cases = selectedCases();
if ( cases.empty() ) return;
auto cases = selectedCases();
auto ensembles = selectedEnsembles();
appendPlotsForCases( summaryMultiPlot, cases );
RicAppendSummaryPlotsForObjectsFeature::appendPlots( summaryMultiPlot, cases, ensembles );
}
//--------------------------------------------------------------------------------------------------
@ -105,3 +84,14 @@ std::vector<RimSummaryCase*> RicAppendSummaryPlotsForSummaryCasesFeature::select
return objects;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<RimSummaryCaseCollection*> RicAppendSummaryPlotsForSummaryCasesFeature::selectedEnsembles()
{
std::vector<RimSummaryCaseCollection*> objects;
caf::SelectionManager::instance()->objectsByType( &objects );
return objects;
}

View File

@ -24,6 +24,7 @@
class RimSummaryCase;
class RimSummaryMultiPlot;
class RimSummaryCaseCollection;
//==================================================================================================
///
@ -32,14 +33,12 @@ class RicAppendSummaryPlotsForSummaryCasesFeature : public caf::CmdFeature
{
CAF_CMD_HEADER_INIT;
public:
static void appendPlotsForCases( RimSummaryMultiPlot* summaryMultiPlot, const std::vector<RimSummaryCase*>& cases );
protected:
bool isCommandEnabled() override;
void onActionTriggered( bool isChecked ) override;
void setupActionLook( QAction* actionToSetup ) override;
private:
static std::vector<RimSummaryCase*> selectedCases();
static std::vector<RimSummaryCase*> selectedCases();
static std::vector<RimSummaryCaseCollection*> selectedEnsembles();
};

View File

@ -777,6 +777,8 @@ caf::CmdFeatureMenuBuilder RimContextCommandBuilder::commandsFromSelection()
menuBuilder << "RicNewDerivedEnsembleFeature";
menuBuilder << "RicOpenSummaryPlotEditorFeature";
menuBuilder << "RicNewSummaryCrossPlotFeature";
menuBuilder << "RicAppendSummaryCurvesForSummaryCasesFeature";
menuBuilder << "RicAppendSummaryPlotsForSummaryCasesFeature";
menuBuilder.addSeparator();
menuBuilder << "RicConvertGroupToEnsembleFeature";
menuBuilder.addSeparator();

View File

@ -396,18 +396,21 @@ cvf::Color3f RimSummaryCurveAppearanceCalculator::computeTintedCurveColorForAddr
{
bool usePhaseColor = RiaPreferencesSummary::current()->colorCurvesByPhase();
float scalingFactor = 0.25;
cvf::Color3f curveColor;
if ( usePhaseColor )
{
curveColor = RimSummaryCurveAppearanceCalculator::assignColorByPhase( address );
// A negative scaling factor will make the color darker
scalingFactor = -0.1 * colorIndex;
curveColor = RimSummaryCurveAppearanceCalculator::assignColorByPhase( address );
}
else
{
curveColor = RiaColorTables::summaryCurveDefaultPaletteColors().cycledColor3f( colorIndex );
}
float scalingFactor = 0.25;
curveColor = RiaColorTools::makeLighter( curveColor, scalingFactor );
curveColor = RiaColorTools::makeLighter( curveColor, scalingFactor );
return curveColor;
}

View File

@ -222,6 +222,7 @@ void RimSummaryMultiPlot::handleDroppedObjects( const std::vector<caf::PdmObject
std::vector<RimSummaryAddress*> addresses;
std::vector<RimSummaryAddressCollection*> addressCollections;
std::vector<RimSummaryCase*> cases;
std::vector<RimSummaryCaseCollection*> ensembles;
for ( auto o : objects )
{
@ -243,11 +244,13 @@ void RimSummaryMultiPlot::handleDroppedObjects( const std::vector<caf::PdmObject
auto summaryCase = dynamic_cast<RimSummaryCase*>( o );
if ( summaryCase ) cases.push_back( summaryCase );
auto ensemble = dynamic_cast<RimSummaryCaseCollection*>( o );
if ( ensemble ) ensembles.push_back( ensemble );
}
RicAppendSummaryPlotsForSummaryAddressesFeature::appendPlotsForAddresses( this, addresses );
RicAppendSummaryPlotsForObjectsFeature::appendPlots( this, addressCollections );
RicAppendSummaryPlotsForSummaryCasesFeature::appendPlotsForCases( this, cases );
RicAppendSummaryPlotsForObjectsFeature::appendPlots( this, cases, ensembles );
}
//--------------------------------------------------------------------------------------------------

View File

@ -770,22 +770,7 @@ size_t RimSummaryPlot::singleColorCurveCount() const
void RimSummaryPlot::applyDefaultCurveAppearances()
{
applyDefaultCurveAppearances( summaryCurves() );
// Ensemble curve sets
int colorIndex = 0;
for ( auto& curveSet : this->ensembleCurveSetCollection()->curveSets() )
{
if ( curveSet->colorMode() != RimEnsembleCurveSet::ColorMode::SINGLE_COLOR ) continue;
cvf::Color3f curveColor =
RimSummaryCurveAppearanceCalculator::computeTintedCurveColorForAddress( curveSet->summaryAddress(),
colorIndex++ );
auto adr = curveSet->summaryAddress();
if ( adr.isHistoryVector() ) curveColor = RiaPreferencesSummary::current()->historyCurveContrastColor();
curveSet->setColor( curveColor );
}
applyDefaultCurveAppearances( ensembleCurveSetCollection()->curveSets() );
}
//--------------------------------------------------------------------------------------------------
@ -803,6 +788,36 @@ void RimSummaryPlot::applyDefaultCurveAppearances( std::vector<RimSummaryCurve*>
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::applyDefaultCurveAppearances( std::vector<RimEnsembleCurveSet*> ensembleCurvesToUpdate )
{
auto allCurveSets = ensembleCurveSetCollection()->curveSets();
for ( auto curveSet : ensembleCurvesToUpdate )
{
size_t colorIndex = 0;
auto it = std::find( allCurveSets.begin(), allCurveSets.end(), curveSet );
if ( it != allCurveSets.end() )
{
colorIndex = std::distance( allCurveSets.begin(), it );
}
if ( curveSet->colorMode() != RimEnsembleCurveSet::ColorMode::SINGLE_COLOR ) continue;
cvf::Color3f curveColor =
RimSummaryCurveAppearanceCalculator::computeTintedCurveColorForAddress( curveSet->summaryAddress(),
static_cast<int>( colorIndex ) );
auto adr = curveSet->summaryAddress();
if ( adr.isHistoryVector() ) curveColor = RiaPreferencesSummary::current()->historyCurveContrastColor();
curveSet->setColor( curveColor );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -1997,6 +2012,34 @@ std::pair<int, std::vector<RimSummaryCurve*>> RimSummaryPlot::handleSummaryCaseD
return { newCurves, curves };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<int, std::vector<RimEnsembleCurveSet*>> RimSummaryPlot::handleEnsembleDrop( RimSummaryCaseCollection* ensemble )
{
int newCurves = 0;
std::vector<RimEnsembleCurveSet*> curveSetsToUpdate;
std::map<RifEclipseSummaryAddress, std::set<RimSummaryCaseCollection*>> dataVectorMap;
for ( auto& curve : curveSets() )
{
const auto addr = curve->summaryAddress();
dataVectorMap[addr].insert( curve->summaryCaseCollection() );
}
for ( const auto& [addr, ensembles] : dataVectorMap )
{
if ( ensembles.count( ensemble ) > 0 ) continue;
auto curveSet = addNewEnsembleCurveY( addr, ensemble );
curveSetsToUpdate.push_back( curveSet );
newCurves++;
}
return { newCurves, curveSetsToUpdate };
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -2195,8 +2238,9 @@ std::pair<int, std::vector<RimSummaryCurve*>> RimSummaryPlot::handleSummaryAddre
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::handleDroppedObjects( const std::vector<caf::PdmObjectHandle*>& objects )
{
int accumulatedCurveCount = 0;
std::vector<RimSummaryCurve*> curvesToUpdate;
int accumulatedCurveCount = 0;
std::vector<RimSummaryCurve*> curvesToUpdate;
std::vector<RimEnsembleCurveSet*> curveSetsToUpdate;
for ( auto obj : objects )
{
@ -2208,6 +2252,14 @@ void RimSummaryPlot::handleDroppedObjects( const std::vector<caf::PdmObjectHandl
curvesToUpdate.insert( curvesToUpdate.end(), curvesCreated.begin(), curvesCreated.end() );
continue;
}
auto ensemble = dynamic_cast<RimSummaryCaseCollection*>( obj );
if ( ensemble )
{
auto [curveCount, curvesCreated] = handleEnsembleDrop( ensemble );
accumulatedCurveCount += curveCount;
curveSetsToUpdate.insert( curveSetsToUpdate.end(), curvesCreated.begin(), curvesCreated.end() );
continue;
}
auto summaryAddr = dynamic_cast<RimSummaryAddress*>( obj );
if ( summaryAddr )
@ -2244,6 +2296,7 @@ void RimSummaryPlot::handleDroppedObjects( const std::vector<caf::PdmObjectHandl
if ( accumulatedCurveCount > 0 )
{
applyDefaultCurveAppearances( curvesToUpdate );
applyDefaultCurveAppearances( curveSetsToUpdate );
loadDataAndUpdate();
@ -2269,7 +2322,8 @@ RimSummaryCurve* RimSummaryPlot::addNewCurveY( const RifEclipseSummaryAddress& a
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimSummaryPlot::addNewEnsembleCurveY( const RifEclipseSummaryAddress& address, RimSummaryCaseCollection* ensemble )
RimEnsembleCurveSet* RimSummaryPlot::addNewEnsembleCurveY( const RifEclipseSummaryAddress& address,
RimSummaryCaseCollection* ensemble )
{
auto* curveSet = new RimEnsembleCurveSet();
@ -2288,6 +2342,8 @@ void RimSummaryPlot::addNewEnsembleCurveY( const RifEclipseSummaryAddress& addre
curveSet->setColor( curveColor );
ensembleCurveSetCollection()->addCurveSet( curveSet );
return curveSet;
}
//--------------------------------------------------------------------------------------------------

View File

@ -165,6 +165,7 @@ public:
size_t singleColorCurveCount() const;
void applyDefaultCurveAppearances();
void applyDefaultCurveAppearances( std::vector<RimSummaryCurve*> curvesToUpdate );
void applyDefaultCurveAppearances( std::vector<RimEnsembleCurveSet*> ensembleCurvesToUpdate );
void setNormalizationEnabled( bool enable );
bool isNormalizationEnabled();
@ -288,13 +289,14 @@ private:
void assignPlotAxis( RimSummaryCurve* curve );
RimSummaryCurve* addNewCurveY( const RifEclipseSummaryAddress& address, RimSummaryCase* summaryCase );
void addNewEnsembleCurveY( const RifEclipseSummaryAddress& address, RimSummaryCaseCollection* ensemble );
RimEnsembleCurveSet* addNewEnsembleCurveY( const RifEclipseSummaryAddress& address, RimSummaryCaseCollection* ensemble );
void updateStackedCurveData();
bool updateStackedCurveDataForAxis( RiuPlotAxis plotAxis );
bool updateStackedCurveDataForRelevantAxes();
std::pair<int, std::vector<RimSummaryCurve*>> handleSummaryCaseDrop( RimSummaryCase* summaryCase );
std::pair<int, std::vector<RimSummaryCurve*>> handleSummaryCaseDrop( RimSummaryCase* summaryCase );
std::pair<int, std::vector<RimEnsembleCurveSet*>> handleEnsembleDrop( RimSummaryCaseCollection* ensemble );
std::pair<int, std::vector<RimSummaryCurve*>> handleAddressCollectionDrop( RimSummaryAddressCollection* addrColl );
std::pair<int, std::vector<RimSummaryCurve*>> handleSummaryAddressDrop( RimSummaryAddress* summaryAddr );