Creating Unique value colorizer for raster

2511
13
Jump to solution
07-16-2019 06:51 AM
GKmieliauskas
Esri Regular Contributor

Hi,

I am trying to create raster layer from grid and apply unique value colorizer on the same button click. I have tried different techniques from samples with feature layers, from geonet question https://community.esri.com/thread/235510-applysymbologyfromlayer-geoprocessing-tool (part about Classify colorizer) but can't get results as I expected. Sometimes I see correct legend but no raster on map, otherwise bad legend and bad colorized raster on map. I modified ChangeColorizerForRasterLayer project from sdk samples to load my raster and added color ramp to

SetToUniqueValueColorizer method. My code:

public static async Task SetToUniqueValueColorizer(BasicRasterLayer basicRasterLayer)

{

// Creates a new UV Colorizer Definition using the default constructor.

string fieldName = "Value";

string colorRampName = "Muted pastels";

string colorRampStyle = "ArcGIS Colors";

// Sets the newly created colorizer on the layer.

await QueuedTask.Run(async() =>

{

IList<ColorRampStyleItem> rampList = GetColorRampsFromStyleAsync(Project.Current, colorRampStyle, colorRampName);

CIMColorRamp colorRamp = rampList[0].ColorRamp;

UniqueValueColorizerDefinition UVColorizerDef = new UniqueValueColorizerDefinition(fieldName, colorRamp);

// Creates a new UV colorizer using the colorizer definition created above.

CIMRasterUniqueValueColorizer newColorizer = await basicRasterLayer.CreateColorizerAsync(UVColorizerDef) as CIMRasterUniqueValueColorizer;

basicRasterLayer.SetColorizer(newColorizer);

});

}

@Uma Harano could you please help me again. I can attach my raster.

0 Kudos
13 Replies
GKmieliauskas
Esri Regular Contributor

Hi Uma,

The only one difference in our code is obtaining RasterLayer. You take it from map, in my add-in I create it from LayerFactory. I will check is it work by taking from map.

0 Kudos
LesleyBross1
New Contributor III

Uma,

I am experiencing the same issue as Gintautas when adding a UniqueValueColorizer to a new raster layer. I am developing on ArcGIS Pro 2.4.2. If I use the VALUE field for the unique values, Pro changes the field name in the TOC to the only text field on the attribute table (NAME) and cannot display the layer. Image of incorrect TOC: 

If I use the NAME field for the unique values, everything works fine. The code you provided to initialize the colorizer results in the color ramp that I am expecting.

It seems that this may have something to do with using the LayerFactory to create the raster layer shortly before symbolizing it. I also tried getting the layer from the map instead of directly from the LayerFactory but this did not change my results. Let me know if I can provide any additional information to help with troubleshooting.

Also, for anyone migrating code from ArcObjects, I found that some of the color ramps that were formerly found in the "Default Ramps" style category can be found in the "ArcGIS Colors" style category in Pro. I am working with the "Elevation #2" color ramp.

0 Kudos
UmaHarano
Esri Regular Contributor

Hi Lesley

I was able to see the same behavior you are seeing. I narrowed down the issue to the CreateColorizer method - it is using the "NAME" field to create the CIMRasterUniqueValueGroup groups. There is a mismatch in the output. I have informed the Raster development about this issue. I will post back to this thread when there is a solution or workaround for this.

Thank you reporting this!

Uma

0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Like Uma mentioned above the CreateColorizer method appears to have some issues.  I looked at the colorizer result and the values[0] property in the group / classes appears to have the wrong value.  I wrote a workaround to 'hand-correct' those values (i also overwrite the label - but that's extra) by using the raster's attribute table to look up the correct values - needless to say you have to adapt this code to use your raster fields:

protected async override void OnClick()
{
    var raster = MapView.Active.Map.GetLayersAsFlattenedList().OfType<RasterLayer>().FirstOrDefault();
    if (raster == null)
        return;

    await QueuedTask.Run(() =>
    {
        string fieldName = "ericlookup";  // Landuse or value or ericLookup

        var style = Project.Current.GetItems<StyleProjectItem>().First(s => s.Name == "ArcGIS Colors");
        var ramps = style.SearchColorRamps("Green Blues");
        var colorizerDef = new UniqueValueColorizerDefinition(fieldName, ramps[0].ColorRamp);
        var colorizer = raster.CreateColorizer(colorizerDef);

        // fix up colorizer ... turns out the values are wrong ... the landuse value is always inserted
        // we use the Raster's attribute table to collect a dictionary with the correct replacement values
        Dictionary<string, Tuple<string, string>> landuseToFieldValue = new Dictionary<string, Tuple<string, string>>(); ;
        if (colorizer is CIMRasterUniqueValueColorizer uvrColorizer)
        {
            var rasterTbl = raster.GetRaster().GetAttributeTable();
            var cursor = rasterTbl.Search();
            while (cursor.MoveNext())
            {
                var row = cursor.Current;
                var correctVal = row[fieldName].ToString();
                var correctCnt = row["count_"].ToString();
                var key = row[uvrColorizer.Groups[0].Heading].ToString();
                landuseToFieldValue.Add(key, new Tuple<string, string>(correctVal, correctCnt));
            }
            uvrColorizer.Groups[0].Heading = fieldName;
            for (var idxGrp = 0; idxGrp < uvrColorizer.Groups[0].Classes.Length; idxGrp++)
            {
                var grpClass = uvrColorizer.Groups[0].Classes[idxGrp];
                var oldValue = grpClass.Values[0];
                var correctValue = landuseToFieldValue[oldValue];
                grpClass.Values[0] = correctValue.Item1;
                grpClass.Label = $@"{correctValue.Item1} ({correctValue.Item2})";
            }
        }
        raster.SetColorizer(colorizer);
    });
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

With the workaround i was able to code against any of the fields in the raster's attribute table:

Here is the default symbology after i added the raster to my map:

and here are some tests using different field names:

0 Kudos