All Apps and Add-ons

Is it possible to map value to color/color code using a bilinear color gradient for visualization?

Olli1919
Path Finder

(Disclaimer: May be a little nuts. Meaning you do not necessarily need to be sane to enjoy this question/answer)

Many custom visualizations can work with a colorcode in the event data to further enrich a chart.
Is it possible to map a numerical value to a color / colorcode? E.g. 42.4 -> #FFA500
Furthermore, is it possible to map a value range to a color range? E.g. 0.0-1.0 -> green-red?

Labels (2)
0 Karma
1 Solution

Olli1919
Path Finder

A nice usage scenario for chart annotation (e.g. heatmap) is to merge two values (e.g. local riskscore, global riskscore) into a single color. Of course the same could be achieved in coming up with an overall score first and mapping this into a colorcode.

But since splunk can do, let's take the more colorful approach of "mapping two values into a 2D color space" ("Bilinear Interpolate Color Gradient").

As referenced in slide 26 of conf19's: SEC1374 - Augment Your Security Monitoring Use Cases with Splunk's Machine Learning Toolkit (@time 41:04)
Colorize Graph using two riskscores
bilinearInterpolateColorGradient(inputVal1, inputVal2, colorspaceCol00, colorspaceColX0, colorspaceCol0Y, colorspaceColXY, "outcolor")

Goal:
- Input two values in the range of 0..1
- Map into a 2D colorspace defined by the four colorcodes in the corners
- Output a single colorcode in the format "#AABBCC"

Result:
The two input values will get mapped into a 2D colorspace like this one:
2DColorspace at HarmonicCode: harmoniccode.blogspot.com
For a great explanation, refer to this article:
Bilinear color interpolation at HarmonicCode: harmoniccode.blogspot.com

Code: (4 Macros)

bilinearInterpolateColorGradient(7)

`comment("
    Maps two values into a color space with four colors.
    Outputs a final color, smoothly interpolated between these four color, 
    on basis of the two input values.
    https://harmoniccode.blogspot.com/2011/04/bilinear-color-interpolation.html
    x: Input value 1 (x axis in color space. left->right)
    y: Input value 2 (y axis in color space. bottom->top)    
    col00: color in the bottom left corner of the color space.
    colX0: color in the bottom right corner of the color space.
    col0Y: color in the top left corner of the color space.
    colXY: color in the top right corner of the color space.
    outcolorfieldname: name of field in which the final color is written.
")`

| eval _x = $x$
| eval _y = $y$
| eval _col00 = $col00$
| eval _colX0 = $colX0$
| eval _col0Y = $col0Y$
| eval _colXY = $colXY$
`interpolateColor(_col00, _colX0, _x, "_outcolorB")`
`interpolateColor(_col0Y, _colXY, _x, "_outcolorT")`
`interpolateColor(_outcolorB, _outcolorT, _y, "_outcolor")`
| eval $outcolorfieldname$ = _outcolor

interpolateColor(4)

| eval _col1 = $col1$
| eval _col2 = $col2$
| eval _lerpt = $lerpt$
| eval _outcolor = "#ZZZZZZ"

| eval _lerpt = if(_lerpt > 1, 1.0, _lerpt)
| eval _lerpt = if(_lerpt < 0.0, 0.0, _lerpt)

`splitColorIntoComponents(_col1, "_col1r", "_col1g", "_col1b")`
`splitColorIntoComponents(_col2, "_col2r", "_col2g", "_col2b")`
| eval _deltaRed = _col2r - _col1r, _deltaGreen = _col2g - _col1g, _deltaBlue = _col2b - _col1b
| eval _outRed = _col1r + _lerpt * _deltaRed, _outGreen = _col1g + _lerpt * _deltaGreen, _outBlue = _col1b + _lerpt * _deltaBlue
`genColorFromComponents(_outRed, _outGreen, _outBlue, "_outcolor")`

| eval $outcolorfieldname$ = _outcolor

splitColorIntoComponents(4)

| eval _color = $color$
| rex field=_color "^#(?<_red>[0-9a-zA-Z]{2,2})(?<_green>[0-9a-zA-Z]{2,2})(?<_blue>[0-9a-zA-Z]{2,2})$"
| eval _red = tonumber(_red, 16), _green = tonumber(_green, 16), _blue = tonumber(_blue, 16)
| eval $oufieldname_red$ = _red
| eval $oufieldname_green$ = _green
| eval $oufieldname_blue$ = _blue

genColorFromComponents(4)

| eval _red = $red$
| eval _green = $green$
| eval _blue = $blue$
| eval _outcolor = "#" + upper(printf("%02x", _red)) + upper(printf("%02x", _green)) + upper(printf("%02x", _blue))
| eval $outcolorfieldname$ = _outcolor

Testbed / Usage example

| makeresults count=484
| eval count = 22
| streamstats count as id
| eval id = id - 1
| eval x = floor(id / count) / count, y = (id % count) / count, z = 0

| eval col00 = "#00AA00"
| eval colX0 = "#FFA500"
| eval col0Y = "#FFFF00"
| eval colXY = "#FF0000"

`bilinearInterpolateColorGradient(x, y, col00, colX0, col0Y, colXY, "outcolor")`
| eval clusterId=outcolor, clusterColor=outcolor, z=0
| table clusterId, x, y, z, clusterColor

**-> Render the generated events into MLTK's 3D Scatterplot**

View solution in original post

Olli1919
Path Finder

A nice usage scenario for chart annotation (e.g. heatmap) is to merge two values (e.g. local riskscore, global riskscore) into a single color. Of course the same could be achieved in coming up with an overall score first and mapping this into a colorcode.

But since splunk can do, let's take the more colorful approach of "mapping two values into a 2D color space" ("Bilinear Interpolate Color Gradient").

As referenced in slide 26 of conf19's: SEC1374 - Augment Your Security Monitoring Use Cases with Splunk's Machine Learning Toolkit (@time 41:04)
Colorize Graph using two riskscores
bilinearInterpolateColorGradient(inputVal1, inputVal2, colorspaceCol00, colorspaceColX0, colorspaceCol0Y, colorspaceColXY, "outcolor")

Goal:
- Input two values in the range of 0..1
- Map into a 2D colorspace defined by the four colorcodes in the corners
- Output a single colorcode in the format "#AABBCC"

Result:
The two input values will get mapped into a 2D colorspace like this one:
2DColorspace at HarmonicCode: harmoniccode.blogspot.com
For a great explanation, refer to this article:
Bilinear color interpolation at HarmonicCode: harmoniccode.blogspot.com

Code: (4 Macros)

bilinearInterpolateColorGradient(7)

`comment("
    Maps two values into a color space with four colors.
    Outputs a final color, smoothly interpolated between these four color, 
    on basis of the two input values.
    https://harmoniccode.blogspot.com/2011/04/bilinear-color-interpolation.html
    x: Input value 1 (x axis in color space. left->right)
    y: Input value 2 (y axis in color space. bottom->top)    
    col00: color in the bottom left corner of the color space.
    colX0: color in the bottom right corner of the color space.
    col0Y: color in the top left corner of the color space.
    colXY: color in the top right corner of the color space.
    outcolorfieldname: name of field in which the final color is written.
")`

| eval _x = $x$
| eval _y = $y$
| eval _col00 = $col00$
| eval _colX0 = $colX0$
| eval _col0Y = $col0Y$
| eval _colXY = $colXY$
`interpolateColor(_col00, _colX0, _x, "_outcolorB")`
`interpolateColor(_col0Y, _colXY, _x, "_outcolorT")`
`interpolateColor(_outcolorB, _outcolorT, _y, "_outcolor")`
| eval $outcolorfieldname$ = _outcolor

interpolateColor(4)

| eval _col1 = $col1$
| eval _col2 = $col2$
| eval _lerpt = $lerpt$
| eval _outcolor = "#ZZZZZZ"

| eval _lerpt = if(_lerpt > 1, 1.0, _lerpt)
| eval _lerpt = if(_lerpt < 0.0, 0.0, _lerpt)

`splitColorIntoComponents(_col1, "_col1r", "_col1g", "_col1b")`
`splitColorIntoComponents(_col2, "_col2r", "_col2g", "_col2b")`
| eval _deltaRed = _col2r - _col1r, _deltaGreen = _col2g - _col1g, _deltaBlue = _col2b - _col1b
| eval _outRed = _col1r + _lerpt * _deltaRed, _outGreen = _col1g + _lerpt * _deltaGreen, _outBlue = _col1b + _lerpt * _deltaBlue
`genColorFromComponents(_outRed, _outGreen, _outBlue, "_outcolor")`

| eval $outcolorfieldname$ = _outcolor

splitColorIntoComponents(4)

| eval _color = $color$
| rex field=_color "^#(?<_red>[0-9a-zA-Z]{2,2})(?<_green>[0-9a-zA-Z]{2,2})(?<_blue>[0-9a-zA-Z]{2,2})$"
| eval _red = tonumber(_red, 16), _green = tonumber(_green, 16), _blue = tonumber(_blue, 16)
| eval $oufieldname_red$ = _red
| eval $oufieldname_green$ = _green
| eval $oufieldname_blue$ = _blue

genColorFromComponents(4)

| eval _red = $red$
| eval _green = $green$
| eval _blue = $blue$
| eval _outcolor = "#" + upper(printf("%02x", _red)) + upper(printf("%02x", _green)) + upper(printf("%02x", _blue))
| eval $outcolorfieldname$ = _outcolor

Testbed / Usage example

| makeresults count=484
| eval count = 22
| streamstats count as id
| eval id = id - 1
| eval x = floor(id / count) / count, y = (id % count) / count, z = 0

| eval col00 = "#00AA00"
| eval colX0 = "#FFA500"
| eval col0Y = "#FFFF00"
| eval colXY = "#FF0000"

`bilinearInterpolateColorGradient(x, y, col00, colX0, col0Y, colXY, "outcolor")`
| eval clusterId=outcolor, clusterColor=outcolor, z=0
| table clusterId, x, y, z, clusterColor

**-> Render the generated events into MLTK's 3D Scatterplot**
Get Updates on the Splunk Community!

Index This | I am a number, but when you add ‘G’ to me, I go away. What number am I?

March 2024 Edition Hayyy Splunk Education Enthusiasts and the Eternally Curious!  We’re back with another ...

What’s New in Splunk App for PCI Compliance 5.3.1?

The Splunk App for PCI Compliance allows customers to extend the power of their existing Splunk solution with ...

Extending Observability Content to Splunk Cloud

Register to join us !   In this Extending Observability Content to Splunk Cloud Tech Talk, you'll see how to ...