[/
  Copyright Nick Thompson, Matt Borland, 2022
  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE_1_0.txt or copy at
  http://www.boost.org/LICENSE_1_0.txt).
]

[section:color_maps Color Maps]

[h4 Synopsis]

``
#include <boost/math/tools/color_maps.hpp>

namespace boost::math::tools {

template<typename Real>
std::array<Real, 3> viridis(Real x);
      
template<typename Real>
std::array<Real, 3> plasma(Real x);

template<typename Real>
std::array<Real, 3> black_body(Real x);

template<typename Real>
std::array<Real, 3> inferno(Real x);

template<typename Real>
std::array<Real, 3> smooth_cool_warm(Real x);

template<typename Real>
std::array<Real, 3> kindlmann(Real x);

template<typename Real>
std::array<Real, 3> extended_kindlmann(Real x);

template<typename Real>
std::array<uint8_t, 4> to_8bit_rgba(std::array<Real, 3> const & color);

} // namespaces
``

[heading Description]

Abstractly, a color map is any function which maps [0, 1] -> [0, 1]^3.
As stated, this definition is too broad to be useful, so in Boost, we restrict our attention to the subset of color maps which are useful for the understanding of scientific data.
[@https://www.kennethmoreland.com/color-advice/BadColorMaps.pdf Much research] has demonstrated that color maps differ wildly in their usefulness for interpreting quantitative data; see [@https://www.kennethmoreland.com/color-advice/ here] for details.
In addition, different color maps are useful in different contexts.
For example, the `smooth_cool_warm` color map is useful for examining surfaces embedded in 3-space which have scalar fields defined on them, whereas the `inferno` color map is better for understanding 2D data.

Despite the fact that a color map, per our definition, has a domain of [0, 1], we nonetheless do not throw an exception if the value provided falls outside this range.
This is for two reasons: First, visualizations are themselves amazing debuggers, and if we threw an exception the calculation would not complete and visual debugging would be inaccessible.
Second, often small changes in floating point rounding cause the value provided to be only slightly below zero, or just slightly above 1.
Hence, we make a call to `std::clamp` before interpolating into the color table. 

For an example of how to use these facilites please refer to [@../../example/color_maps_example.cpp `example/color_maps_example.cpp`] 
and [@../../example/color_maps_sf_example.cpp `example/color_maps_sf_example.cpp`]
Note: To compile the examples directly you will need to have [@https://github.com/lvandeve/lodepng lodepng].
An example of the viridis color map using [@https://en.wikipedia.org/wiki/Newton_fractal the newton fractal] is shown below:

[$../images/viridis_newton_fractal.png]

An example from [@../../example/color_maps_example.cpp `example/color_maps_example.cpp`] plots [sub 1]F[sub 1] on a logarithmic scale:

[$../images/extended_kindlmann_1F1.png]

Swatches of each are listed below:

[$../images/smooth_cool_warm_swatch.png]

*Smooth cool warm*

[$../images/viridis_swatch.png]

*Viridis*

[$../images/plasma_swatch.png]

*Plasma*

[$../images/black_body_swatch.png]

*Black body*

[$../images/inferno_swatch.png]

*Inferno*

[$../images/kindlmann_swatch.png]

*Kindlmann*

[$../images/extended_kindlmann_swatch.png]

*Extended Kindlmann*

[heading References]

* Ken Moreland. ['Why We Use Bad Color Maps and What You Can Do About it] .

[endsect]
[/section:color_maps Color Maps]