Fix zone colors to honor LYR-file specification (#13658)

* #12974 Fix zone colors to honor LYR-file specification

- Map formation colors by name instead of palette index in updateFormationNamesOnPlot()
- Map formation colors by categoryValue lookup in updateCellResultLegend(), fixing
  incorrect colors when showOnlyVisibleCategoriesInLegend filters the active set
- Add RimColorLegendCollection::createColorLegendFromFormationNames() and call it
  from readAllFormationNames() so LYR colors are available after project load
- Auto-assign formation color legend when a formation case is set on a well log track
- Rename fileNameWoPath() to shortName() and switch to baseName() (no extension)
- Remove addCustomColorLegend() from RicImportFormationNamesFeature; logic now lives
  in RimColorLegendCollection
- Set formation legend when creating new Well Log Extraction Curve track
This commit is contained in:
Magne Sjaastad
2026-02-25 18:16:03 +01:00
committed by GitHub
parent 3d1abec870
commit 1cd3cf3b67
13 changed files with 157 additions and 92 deletions
@@ -70,26 +70,12 @@ RimFormationNames* RicImportFormationNamesFeature::importFormationFiles( const Q
std::vector<RimFormationNames*> formationNames = fomNameColl->importFiles( fileNames );
fomNameColl->updateConnectedEditors();
for ( int i = 0; i < fileNames.size(); i++ )
RimColorLegendCollection* colorLegendCollection = proj->colorLegendCollection;
for ( auto* fmNames : formationNames )
{
auto colors = formationNames[i]->formationNamesData()->formationColors();
bool anyValidColor = false;
for ( const auto& color : colors )
{
if ( color.isValid() )
{
anyValidColor = true;
break;
}
}
if ( anyValidColor )
{
QString baseName = QFileInfo( fileNames[i] ).baseName();
RicImportFormationNamesFeature::addCustomColorLegend( baseName, formationNames[i] );
}
colorLegendCollection->createColorLegendFromFormationNames( fmNames );
}
colorLegendCollection->updateConnectedEditors();
if ( !formationNames.empty() ) return formationNames.back();
@@ -165,40 +151,6 @@ void RicImportFormationNamesFeature::setupActionLook( QAction* actionToSetup )
actionToSetup->setText( "Import Formations" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicImportFormationNamesFeature::addCustomColorLegend( QString& name, RimFormationNames* rimFormationNames )
{
RigFormationNames* rigFormationNames = rimFormationNames->formationNamesData();
if ( !rigFormationNames ) return;
const std::vector<QString>& formationNames = rigFormationNames->formationNames();
const std::vector<cvf::Color3f>& formationColors = rigFormationNames->formationColors();
// return if no formation names or colors (latter e.g. in case of FMU input or LYR without colors)
if ( formationNames.empty() || formationColors.empty() ) return;
auto* colorLegend = new RimColorLegend;
colorLegend->setColorLegendName( name );
for ( size_t i = 0; i < formationColors.size(); i++ )
{
auto* colorLegendItem = new RimColorLegendItem;
colorLegendItem->setValues( formationNames[i], (int)i, formationColors[i] );
colorLegend->appendColorLegendItem( colorLegendItem );
}
RimProject* proj = RimProject::current();
RimColorLegendCollection* colorLegendCollection = proj->colorLegendCollection;
colorLegendCollection->appendCustomColorLegend( colorLegend );
colorLegendCollection->updateConnectedEditors();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -37,7 +37,5 @@ protected:
void setupActionLook( QAction* actionToSetup ) override;
private:
static void addCustomColorLegend( QString& name, RimFormationNames* formationNames );
void setFormationCellResultAndLegend( Rim3dView* activeView, QString& legendName );
};
@@ -19,7 +19,12 @@
#include "RicNewWellLogPlotFeatureImpl.h"
#include "RiaGuiApplication.h"
#include "Formations/RimFormationNames.h"
#include "RimCase.h"
#include "RimColorLegend.h"
#include "RimColorLegendCollection.h"
#include "RimEclipseCase.h"
#include "RimMainPlotCollection.h"
#include "RimProject.h"
@@ -34,8 +39,6 @@
#include "RimWellLogTrack.h"
#include "RimWellPath.h"
#include "RiaGuiApplication.h"
#include "cvfAssert.h"
#include <QString>
@@ -218,6 +221,14 @@ RimWellLogTrack*
if ( caseToApply )
{
plotTrack->setFormationCase( caseToApply );
if ( auto* formationNames = caseToApply->activeFormationNames() )
{
if ( auto* legend = RimProject::current()->colorLegendCollection->findByName( formationNames->shortName() ) )
{
plotTrack->setColorShadingLegend( legend );
}
}
}
if ( wellPathToApply )
@@ -105,10 +105,10 @@ QString RimFormationNames::fileName()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RimFormationNames::fileNameWoPath()
QString RimFormationNames::shortName()
{
QFileInfo fnameFileInfo( m_formationNamesFileName().path() );
return fnameFileInfo.fileName();
return fnameFileInfo.baseName();
}
//--------------------------------------------------------------------------------------------------
@@ -159,5 +159,5 @@ QString RimFormationNames::layerZoneTableFileName()
//--------------------------------------------------------------------------------------------------
void RimFormationNames::updateUiTreeName()
{
uiCapability()->setUiName( fileNameWoPath() );
uiCapability()->setUiName( shortName() );
}
@@ -38,7 +38,7 @@ public:
void setFileName( const QString& fileName );
QString fileName();
QString fileNameWoPath();
QString shortName();
RigFormationNames* formationNamesData() { return m_formationNamesData.p(); }
void updateConnectedViews();
@@ -20,7 +20,9 @@
#include "RiaLogging.h"
#include "RimCase.h"
#include "RimColorLegendCollection.h"
#include "RimFormationNames.h"
#include "RimProject.h"
CAF_PDM_SOURCE_INIT( RimFormationNamesCollection, "FormationNamesCollectionObject" );
@@ -44,6 +46,7 @@ void RimFormationNamesCollection::readAllFormationNames()
for ( RimFormationNames* fmNames : m_formationNamesList )
{
fmNames->readFormationNamesFile( nullptr );
RimProject::current()->colorLegendCollection->createColorLegendFromFormationNames( fmNames );
}
}
@@ -272,7 +272,7 @@ QList<caf::PdmOptionItemInfo> RimCase::calculateValueOptions( const caf::PdmFiel
{
for ( RimFormationNames* fnames : proj->activeOilField()->formationNamesCollection()->formationNamesList() )
{
options.push_back( caf::PdmOptionItemInfo( fnames->fileNameWoPath(), fnames, false, fnames->uiCapability()->uiIconProvider() ) );
options.push_back( caf::PdmOptionItemInfo( fnames->shortName(), fnames, false, fnames->uiCapability()->uiIconProvider() ) );
}
}
@@ -21,6 +21,9 @@
#include "RiaColorTables.h"
#include "RiaFractureDefines.h"
#include "RigFormationNames.h"
#include "Formations/RimFormationNames.h"
#include "RimColorLegend.h"
#include "RimColorLegendItem.h"
#include "RimProject.h"
@@ -206,6 +209,43 @@ std::vector<RimColorLegend*> RimColorLegendCollection::allColorLegends() const
return allLegends;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimColorLegendCollection::createColorLegendFromFormationNames( RimFormationNames* rimFormationNames )
{
if ( !rimFormationNames ) return;
RigFormationNames* rigFormationNames = rimFormationNames->formationNamesData();
if ( !rigFormationNames ) return;
const std::vector<QString>& formationNames = rigFormationNames->formationNames();
const std::vector<cvf::Color3f>& formationColors = rigFormationNames->formationColors();
if ( formationNames.empty() || formationColors.empty() ) return;
if ( formationNames.size() != formationColors.size() ) return;
bool anyValidColor = std::any_of( formationColors.begin(), formationColors.end(), []( const auto& color ) { return color.isValid(); } );
if ( !anyValidColor ) return;
QString legendName = rimFormationNames->shortName();
// Do not create duplicate legends
if ( findByName( legendName ) != nullptr ) return;
auto* colorLegend = new RimColorLegend;
colorLegend->setColorLegendName( legendName );
for ( size_t i = 0; i < formationColors.size(); i++ )
{
auto* item = new RimColorLegendItem;
item->setValues( formationNames[i], (int)i, formationColors[i] );
colorLegend->appendColorLegendItem( item );
}
appendCustomColorLegend( colorLegend );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -24,6 +24,7 @@
class RimColorLegend;
class RimColorLegendItem;
class RimFormationNames;
namespace caf
{
@@ -48,6 +49,7 @@ public:
void deleteCustomColorLegends();
RimColorLegend* createColorLegend( const QString& colorLegendName, const std::map<int, QString>& valuesAndNames );
void createColorLegendFromFormationNames( RimFormationNames* rimFormationNames );
void deleteColorLegend( int caseId, const QString& resultName );
void setDefaultColorLegendForResult( int caseId, const QString& resultName, RimColorLegend* colorLegend );
@@ -784,7 +784,7 @@ QList<caf::PdmOptionItemInfo> RimEclipseResultCase::calculateValueOptions( const
QList<caf::PdmOptionItemInfo> options;
if ( m_activeFormationNames() )
{
options.push_back( caf::PdmOptionItemInfo( m_activeFormationNames->fileNameWoPath(), m_activeFormationNames(), false ) );
options.push_back( caf::PdmOptionItemInfo( m_activeFormationNames->shortName(), m_activeFormationNames(), false ) );
}
else
{
@@ -49,6 +49,8 @@
#include <QString>
#include <map>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -675,11 +677,29 @@ void RimEclipseResultDefinitionTools::updateCellResultLegend( const RimEclipseRe
categoryMapper->setCategories( visibleCategoryValues );
categoryMapper->setInterpolateColors( legendBaseColors );
// Build a direct value-to-color map from legend items so that LYR-file specified
// colors are honored regardless of which categories are visible.
// Related to https://github.com/OPM/ResInsight/issues/12974
std::map<int, cvf::Color3ub> legendItemColors;
for ( auto* item : legendConfigToUpdate->colorLegend()->colorLegendItems() )
{
legendItemColors[item->categoryValue()] = cvf::Color3ub( item->color() );
}
std::vector<std::tuple<QString, int, cvf::Color3ub>> categoryVector;
for ( auto value : visibleCategoryValues )
{
cvf::Color3ub categoryColor = categoryMapper->mapToColor( value );
cvf::Color3ub categoryColor;
auto colorIt = legendItemColors.find( value );
if ( colorIt != legendItemColors.end() )
{
categoryColor = colorIt->second;
}
else
{
categoryColor = categoryMapper->mapToColor( value );
}
QString valueTxt;
if ( resultDefinition->resultType() == RiaDefines::ResultCatType::FORMATION_NAMES )
@@ -166,20 +166,24 @@ bool RimWellLogRegionAnnotationSettings::showFormations() const
void RimWellLogRegionAnnotationSettings::uiOrdering( const QString& uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.add( &m_regionAnnotationType );
uiOrdering.add( &m_regionAnnotationDisplay );
uiOrdering.add( &m_showRegionLabels );
if ( m_regionAnnotationType() == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
if ( m_regionAnnotationType() != RiaDefines::RegionAnnotationType::NO_ANNOTATIONS )
{
uiOrdering.add( &m_regionLabelFontSize );
}
uiOrdering.add( &m_regionAnnotationDisplay );
uiOrdering.add( &m_showRegionLabels );
if ( m_regionAnnotationDisplay() & RiaDefines::COLOR_SHADING || m_regionAnnotationDisplay() & RiaDefines::COLORED_LINES )
{
uiOrdering.add( &m_colorShadingLegend );
if ( m_regionAnnotationDisplay() & RiaDefines::COLOR_SHADING )
if ( m_regionAnnotationType() == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
{
uiOrdering.add( &m_colorShadingTransparency );
uiOrdering.add( &m_regionLabelFontSize );
}
if ( m_regionAnnotationDisplay() & RiaDefines::COLOR_SHADING || m_regionAnnotationDisplay() & RiaDefines::COLORED_LINES )
{
uiOrdering.add( &m_colorShadingLegend );
if ( m_regionAnnotationDisplay() & RiaDefines::COLOR_SHADING )
{
uiOrdering.add( &m_colorShadingTransparency );
}
}
}
}
@@ -46,6 +46,7 @@
#include "Well/RigWellPath.h"
#include "Well/RigWellPathFormations.h"
#include "Formations/RimFormationNames.h"
#include "RimCase.h"
#include "RimColorLegend.h"
#include "RimColorLegendCollection.h"
@@ -107,6 +108,7 @@
#include <QWheelEvent>
#include <algorithm>
#include <map>
#include <memory>
#include <set>
@@ -117,6 +119,21 @@
CAF_PDM_SOURCE_INIT( RimWellLogTrack, "WellLogPlotTrack" );
namespace internal
{
void setColorShadingLegendFromFormationCase( RimWellLogRegionAnnotationSettings* settings, RimCase* rimCase )
{
if ( !settings || !rimCase ) return;
auto* formationNames = rimCase->activeFormationNames();
if ( !formationNames ) return;
QString legendName = formationNames->shortName();
auto* legend = RimProject::current()->colorLegendCollection->findByName( legendName );
if ( legend ) settings->setColorShadingLegend( legend );
}
} // namespace internal
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -1227,6 +1244,7 @@ void RimWellLogTrack::setAndUpdateWellPathFormationNamesData( RimCase* rimCase,
m_formationSettings->setSimWellName( "" );
m_formationSettings->setBranchIndex( -1 );
internal::setColorShadingLegendFromFormationCase( m_regionAnnotationSettings, rimCase );
updateConnectedEditors();
if ( m_regionAnnotationSettings->annotationType() != RiaDefines::RegionAnnotationType::NO_ANNOTATIONS )
@@ -1259,6 +1277,7 @@ void RimWellLogTrack::setAndUpdateSimWellFormationNamesData( RimCase* rimCase, c
m_formationSettings->setWellPathForSourceCase( nullptr );
m_formationSettings->setSimWellName( simWellName );
internal::setColorShadingLegendFromFormationCase( m_regionAnnotationSettings, rimCase );
updateConnectedEditors();
if ( m_regionAnnotationSettings->annotationType() != RiaDefines::RegionAnnotationType::NO_ANNOTATIONS )
@@ -1775,13 +1794,12 @@ void RimWellLogTrack::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering
automationGroup->add( &m_autoCheckStateBasedOnCurveData );
caf::PdmUiGroup* annotationGroup = uiOrdering.addNewGroup( "Regions/Annotations" );
annotationGroup->setCollapsedByDefault();
// Region annotation settings UI ordering
m_regionAnnotationSettings->uiOrdering( uiConfigName, *annotationGroup );
// Formation settings UI ordering
m_formationSettings->uiOrdering( uiConfigName, *annotationGroup, m_formationsForCaseWithSimWellOnly );
if ( m_regionAnnotationSettings->annotationType() == RiaDefines::RegionAnnotationType::FORMATION_ANNOTATIONS )
{
m_formationSettings->uiOrdering( uiConfigName, *annotationGroup, m_formationsForCaseWithSimWellOnly );
}
if ( m_regionAnnotationSettings->annotationType() == RiaDefines::RegionAnnotationType::RESULT_PROPERTY_ANNOTATIONS )
{
@@ -2701,23 +2719,40 @@ void RimWellLogTrack::updateFormationNamesOnPlot()
std::vector<std::pair<double, double>> convertedYValues =
RiaWellLogUnitTools<double>::convertDepths( yValues, fromDepthUnit, toDepthUnit );
// TODO: This is not working as expected, and the colors used are always using the regular legend colors.
// The recent refactoring in 93bd0b9c9d768f55c1994385ba431fbbc7a9606f ended up with a nullptr for the color legend in
// RimWellLogTrack, which is why we need to fall back to the regular legend colors.
// Build color table ordered by formation name to ensure correct color mapping
// when using a legend based on a LYR-file. Falls back to palette index for
// formations not found in the legend (e.g., when using a generic color palette).
// Related to https://github.com/OPM/ResInsight/issues/12974
cvf::Color3ubArray colors;
if ( m_regionAnnotationSettings->colorShadingLegend() )
{
colors = m_regionAnnotationSettings->colorShadingLegend()->colorArray();
}
else if ( auto defaultLegend = RimRegularLegendConfig::mapToColorLegend( RimRegularLegendConfig::ColorRangesType::NORMAL ) )
{
colors = defaultLegend->colorArray();
}
RimColorLegend* legend = m_regionAnnotationSettings->colorShadingLegend();
if ( !legend ) legend = RimRegularLegendConfig::mapToColorLegend( RimRegularLegendConfig::ColorRangesType::NORMAL );
if ( colors.size() > 0 )
if ( legend && !formationNamesToPlot.empty() )
{
caf::ColorTable colorTable( colors );
std::map<QString, cvf::Color3ub> nameToColor;
for ( auto* item : legend->colorLegendItems() )
{
nameToColor[item->categoryName()] = cvf::Color3ub( item->color() );
}
cvf::Color3ubArray paletteColors = legend->colorArray();
size_t colorCount = std::max( size_t( 2 ), formationNamesToPlot.size() );
cvf::Color3ubArray orderedColors( colorCount );
orderedColors.setAll( cvf::Color3ub::GRAY );
for ( size_t i = 0; i < formationNamesToPlot.size(); i++ )
{
auto it = nameToColor.find( formationNamesToPlot[i] );
if ( it != nameToColor.end() )
{
orderedColors.set( i, it->second );
}
else if ( paletteColors.size() > 0 )
{
orderedColors.set( i, paletteColors[i % paletteColors.size()] );
}
}
caf::ColorTable colorTable( orderedColors );
m_annotationTool->attachNamedRegions( m_plotWidget->qwtPlot(),
formationNamesToPlot,