# Create a discrete legend

**URL:** <https://discourse.vtk.org/t/create-a-discrete-legend/7787>\
**Category:** Web\
**Created:** [February 7, 2022, 3:30pm UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787 "2022-02-07T15:30:37Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kevin\_Sweeney](https://discourse.vtk.org/user_avatar/discourse.vtk.org/kevin_sweeney/32/3935_2.png) [@Kevin\_Sweeney](https://discourse.vtk.org/u/Kevin_Sweeney)\
**Post date:** [February 7, 2022, 3:30pm UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/1 "2022-02-07T15:30:37Z")

</div>

I have a continuous legend created for my plot using the vtkScalarBarActor but I cannot see how to create one for discrete values.

I previously have used `vtkLegendBoxActor` when implementing in Python but I do not believe this is available in VTK.js?  
Are there any examples online showing how this could be done?

Thanks

---

<div class="post-metadata">

**Author:** ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)\
**Post date:** [February 8, 2022, 2:13pm UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/2 "2022-02-08T14:13:09Z")

</div>

Hi, Kevin,

I guess you need what is termed an annotaded lookup table. Here is how I do it in C++:

```cpp
    //table color indexes must go from 0 to greatest category code, without skipping values
    size_t tableSize = greatestCategoryCode + 1;
    vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
    lut->SetNumberOfTableValues(tableSize);

    //assign only the codes defined in the category definition
    //which may be less than the total number of entries in the color table
    //this is a requirement by the way VTK's LUT work for categorical color tables
    for(size_t i = 0; i < tableSize; ++i)
    {
        if( cd->codeExists( i ) ){ //cd is a category definition table object of the application's domain
            double rgb[3];
            QColor color = cd->getCategoryColor( i );
            rgb[0] = color.redF();
            rgb[1] = color.greenF();
            rgb[2] = color.blueF();
            lut->SetTableValue(i, rgb[0], rgb[1], rgb[2], 1.0);
            lut->SetAnnotation(i, cd->getCategoryName( i ) );
        } else { //we can't skip values, so add some default annotation for non-existing codes
            lut->SetTableValue(i, 1.0, 0.0, 1.0, 0.3); //ilegal color codes are rendered as pink transparent.
            lut->SetAnnotation(i, "UNKNOWN CATEGORY" );
        }
    }
    lut->SetNanColor( 1.0, 0.0, 1.0, 0.3 ); //unvalued samples are likewise rendered as pink transparent.
    lut->IndexedLookupOn();
    lut->Build();

```

I think this is not difficult to port to JavaScript.

I hope this helps,

Paulo

---

<div class="post-metadata">

**Author:** ![Kevin\_Sweeney](https://discourse.vtk.org/user_avatar/discourse.vtk.org/kevin_sweeney/32/3935_2.png) [@Kevin\_Sweeney](https://discourse.vtk.org/u/Kevin_Sweeney)\
**Post date:** [February 9, 2022, 9:10am UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/3 "2022-02-09T09:10:43Z")

</div>

Thank you, I will give that a try.

---

<div class="post-metadata">

**Author:** ![amaclean](https://discourse.vtk.org/user_avatar/discourse.vtk.org/amaclean/32/224_2.png) [@amaclean](https://discourse.vtk.org/u/amaclean)\
**Post date:** [February 9, 2022, 10:00am UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/4 "2022-02-09T10:00:15Z")

</div>

Not sure but this may help: [CurvatureBandsWithGlyphs](https://kitware.github.io/vtk-examples/site/Python/Visualization/CurvatureBandsWithGlyphs/)

---

<div class="post-metadata">

**Author:** ![Kevin\_Sweeney](https://discourse.vtk.org/user_avatar/discourse.vtk.org/kevin_sweeney/32/3935_2.png) [@Kevin\_Sweeney](https://discourse.vtk.org/u/Kevin_Sweeney)\
**Post date:** [March 2, 2022, 11:21am UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/5 "2022-03-02T11:21:38Z")

</div>

Thanks for the replies thus far but I could not yet get it functioning.

Ideally I would like my code to work for both continuous and categorical variables (depending on what scalars the user wants to colour by) and so would like to, if possible, use the same modules etc.

Is there some way to change the `scalarBarActor` to not show a full bar but only the colours at the selected points?

 ![Screenshot 2022-03-02 at 11.05.12](https://discourse.vtk.org/uploads/default/original/2X/5/545d7bad6b64589f01f16416c3f08ce8ca6aa25a.png)

For the discrete instance, I am currently creating a `vtkColorTransferFunction` and `setNumberOfValues` to the number of unique points in the data. Then, for each unique value I am using `addRGBPoint` to add the colour to the current value in the table.

Below is snippits of the code being used:  
**Note:** Only code between /\* DISCRETE CHANGES \*/ has been changed for discrete variables.

```auto
var lookupTable = vtk.Rendering.Core.vtkColorTransferFunction.newInstance();

const scalarArray = this.vtkData.getPointData().getArrayByName(colorByArrayName.toLowerCase());

/* DISCRETE CHANGES */
// Get unique values from the data
let unique = scalarArray.getData().filter(this.onlyUnique).sort()
// Set the number of values
lookupTable.setNumberOfValues(unique.length)

for (let index = 0; index < unique.length; index++) {

    lookupTable.addRGBPoint(unique[index], 
                            rgb[0][index], // 2D array of RGB values
                            rgb[1][index],
                            rgb[2][index]); 
}
/* DISCRETE CHANGES */

this.mapper = vtk.Rendering.Core.vtkGlyph3DMapper.newInstance({
            colorByArrayName,
            colorMode: 1, // vtk.Rendering.Core.Mapper.ColorMode.MAP_SCALARS;,
            interpolateScalarsBeforeMapping: true,
            scalarMode: 3, // vtk.Rendering.Core.Mapper.Constants.ScalarMode.USE_POINT_FIELD_DATA
            scalarVisibility: true,
            useLookupTableScalarRange: true,
            lookupTable,
        });

this.actor.setMapper(this.mapper);
this.mapper.setInputData(this.vtkData, 0)
this.mapper.setInputConnection(this.source.getOutputPort(), 1)

this.lutActor = vtk.Rendering.Core.vtkScalarBarActor.newInstance()
this.lutActor.setAxisLabel(colorByArrayName);
this.lutActor.setVisibility(true);
this.lutActor.setDrawNanAnnotation(false);
this.lutActor.setScalarsToColors(this.mapper.getLookupTable());

...

```

Ideally I am looking for something like this:  
 ![Screenshot 2022-03-02 at 11.20.37](https://discourse.vtk.org/uploads/default/original/2X/7/7dc3f3bc7c952fdea6721448220ea49c66e9bb20.png)

@Sebastien_Jourdain (only adding you as you have been very helpful in the past)

---

<div class="post-metadata">

**Author:** ![Sebastien\_Jourdain](https://discourse.vtk.org/user_avatar/discourse.vtk.org/sebastien_jourdain/32/100_2.png) [@Sebastien\_Jourdain](https://discourse.vtk.org/u/Sebastien_Jourdain)\
**Post date:** [March 2, 2022, 3:57pm UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/6 "2022-03-02T15:57:44Z")

</div>

I don’t think it has been implemented on the JS side. But @ken-martin should know as he created the scalar bar for vtk.js.

---

<div class="post-metadata">

**Author:** ![Kevin\_Sweeney](https://discourse.vtk.org/user_avatar/discourse.vtk.org/kevin_sweeney/32/3935_2.png) [@Kevin\_Sweeney](https://discourse.vtk.org/u/Kevin_Sweeney)\
**Post date:** [March 9, 2022, 8:32pm UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/7 "2022-03-09T20:32:10Z")

</div>

I have hacked something together here (by just automatically “blacking” out parts of the colour map for the legend based on the number of unique discrete values that are to be shown.  
Is there any way to specify to the scalar bar to show more “ticks”, i.e. in this case all digits from 0-9? I cannot find anything in the documentation.

 ![Screenshot 2022-03-09 at 20.30.51](https://discourse.vtk.org/uploads/default/original/2X/a/a71963c7e59764903ff9f05b20102722322fcd4b.png)

---

<div class="post-metadata">

**Author:** ![Sebastien\_Jourdain](https://discourse.vtk.org/user_avatar/discourse.vtk.org/sebastien_jourdain/32/100_2.png) [@Sebastien\_Jourdain](https://discourse.vtk.org/u/Sebastien_Jourdain)\
**Post date:** [March 9, 2022, 8:33pm UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/8 "2022-03-09T20:33:50Z")

</div>

Another approach is to do it in plain HTML as those blocks will be easy to do.

---

<div class="post-metadata">

**Author:** ![Kevin\_Sweeney](https://discourse.vtk.org/user_avatar/discourse.vtk.org/kevin_sweeney/32/3935_2.png) [@Kevin\_Sweeney](https://discourse.vtk.org/u/Kevin_Sweeney)\
**Post date:** [March 10, 2022, 9:07am UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/9 "2022-03-10T09:07:10Z")

</div>

True, but as the number of bars and labels could be anything (as defined by the data ingested by the user) I would rather use VTK, if possible

---

<div class="post-metadata">

**Author:** ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)\
**Post date:** [March 10, 2022, 11:58am UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/10 "2022-03-10T11:58:37Z")

</div>

That’s nice, but often the discrete values are not necessarily ordinary. I mean, the categorical variable can have random values such as 1,7,8,33,51, etc. That is quite common in geosciences applications for the rock type code in a geologic model.

---

<div class="post-metadata">

**Author:** ![Kevin\_Sweeney](https://discourse.vtk.org/user_avatar/discourse.vtk.org/kevin_sweeney/32/3935_2.png) [@Kevin\_Sweeney](https://discourse.vtk.org/u/Kevin_Sweeney)\
**Post date:** [March 10, 2022, 4:23pm UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/11 "2022-03-10T16:23:40Z")

</div>

Thanks @Sebastien_Jourdain and @Paulo_Carvalho, I decided to go ahead and create the dynamic legend using JS and HTML.

 ![Screenshot 2022-03-10 at 16.20.38](https://discourse.vtk.org/uploads/default/original/2X/9/9644a144e0ec0ac70a22ccf267c3f119b82c09c2.jpeg) ![Screenshot 2022-03-10 at 16.22.29](https://discourse.vtk.org/uploads/default/original/2X/d/d8a0addba93914a1482f2e66e3f0a01f4eca8dda.jpeg)

It will indeed allow for categorical data now too which is nice.

---

<div class="post-metadata">

**Author:** ![Sebastien\_Jourdain](https://discourse.vtk.org/user_avatar/discourse.vtk.org/sebastien_jourdain/32/100_2.png) [@Sebastien\_Jourdain](https://discourse.vtk.org/u/Sebastien_Jourdain)\
**Post date:** [March 10, 2022, 4:44pm UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/12 "2022-03-10T16:44:27Z")

</div>

VTK will eventually support it, but I’m sure your JS/HTML code was actually not that bad to do… 😉

---

<div class="post-metadata">

**Author:** ![Rafael\_Scatena](https://discourse.vtk.org/user_avatar/discourse.vtk.org/rafael_scatena/32/7820_2.png) [@Rafael\_Scatena](https://discourse.vtk.org/u/Rafael_Scatena)\
**Post date:** [February 13, 2024, 11:52pm UTC](https://discourse.vtk.org/t/create-a-discrete-legend/7787/13 "2024-02-13T23:52:10Z")

</div>

Hey!

 ![image](https://discourse.vtk.org/uploads/default/original/2X/3/369b3e58b15e6d0d1a6be6bb41f75be068833203.jpeg)

> [@Mapping Scalars into colors](https://discourse.vtk.org/t/mapping-scalars-into-colors/13306):
>
> Hello, I am trying to color the connected components in the image according to their cell scalar value array. The scalarbar renders ok, with the correct labels, but the image renders only with one color. Thank you selectCells-\>Update(); vtkNew\<vtkGeometryFilter\> geometry; geometry-\>SetInputConnection(selectCells-\>GetOutputPort()); geometry-\>Update(); vtkSmartPointer\<vtkPolyData\> geometry\_mesh; geometry\_mesh = geometry-\>GetOutput(); if(geometry\_mesh){ vtkCellData…
