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!

3 Ways to Make OpenTelemetry Even Better

My role as an Observability Specialist at Splunk provides me with the opportunity to work with customers of ...

What's New in Splunk Cloud Platform 9.2.2406?

Hi Splunky people! We are excited to share the newest updates in Splunk Cloud Platform 9.2.2406 with many ...

Enterprise Security Content Update (ESCU) | New Releases

In August, the Splunk Threat Research Team had 3 releases of new security content via the Enterprise Security ...