# Custom labels in colorbar

Here comes a sample data set

data = {{1.03971, 0.00617284, 12.11, 0.227037, 1},
{1.0231, 0.0216931, 27.23, 1.40703, 1},
{1.02864, -0.0294533, 1450, 0.0821789, 1},
{1.01636, -0.0149912, 16.89, 1.02227, 1},
{0.938865, -0.00899471, 68.94, 0.0000322202, 1},
{0.955953, 0.0199295, 1.89, 0.00448189, 9},
{1.03321, 0.0329806, 84.23, 0.094761, 1},
{1.02406, 0.0393298, 13.21, 0.099565, 1},
{0.9728, -0.00194004, 1000, 0.000845306, 0},
{1.00649, -0.00582011, 62.1, 0.0286736, 1}};


The first two columns correspond to the coordinates $(x,y)$, while the other three are some indicators. Now we want to plot those $(x,y)$ coordinates for which the fifth column is equal to 1, while the color of each point should be according to the value of the third column.

First we define a custom color function

valrange = {0, 100};
data[[All, 3]] = Rescale[data[[All, 3]] // N, valrange];
colfunc[x_, cf_] :=
If[x[[5]] == -2 || x[[5]] == -1 || x[[5]] == 0 || x[[5]] == 2 ||
x[[5]] == 9 || x[[5]] == 99, White, ColorData[cf][1 - x[[3]]]];


Then the graphics of the points

S0 = Graphics[{PointSize[0.01], Point[#[[1 ;; 2]], VertexColors -> colfunc[#, "Rainbow"]] & /@
data}];


and a custom colorbar

Clear[colorbar]
colorbar[{min_, max_}, colorFunction_: Automatic, divs_: 150] :=
DensityPlot[y, {x, 0, 0.1}, {y, min, max}, AspectRatio -> 10,
PlotRangePadding -> 0, PlotPoints -> {2, divs}, MaxRecursion -> 0,
Frame -> True, FrameLabel -> {{None, Row[{Subscript["t", "esc"]}]}, {None, None}},
LabelStyle -> Directive[FontFamily -> "Helvetica", 20],
FrameTicks -> {{None, All}, {None, None}},
FrameTicksStyle -> Directive[FontFamily -> "Helvetica", 20, Plain],
ColorFunction -> colorFunction]


Finally we merge together the graphics with the colorbar

With[{opts = {ImageSize -> {Automatic, 400}}, cf = "Rainbow"},
Row[{Show[{S0}, Axes -> False, Frame -> True,
FrameLabel -> {"x", "y"}, RotateLabel -> False,
LabelStyle -> Directive[FontFamily -> "Helvetica", 20],
AspectRatio -> 3/4, ImagePadding -> {{90, 10}, {60, 40}}, opts],
Show[colorbar[valrange, ColorData[cf][1 - #] &],
ImagePadding -> {{10, 80}, {60, 40}}, opts]}]]


which produces the following

The range of the colorbar is between 0 and 100, according to valrange. However in the real data set there are some few initial conditions which have $(x,y)$ coordinates with fifth column equal to 1, while the value of the third column is higher than 100 (see e.g., the third element of data list).

My question: Is there an elegant way to set automatically the higher label of the color bar "> 100", instead of simply "100"?

EDIT

If I set FrameTicks -> {{None, {0, 20, 40, 60, 80, "> 100"}}, {None, None}}, it does not work.

• You're misusing the syntax of FrameTicks. When you provide it with a simple list, you need to give it numeric values of where the ticks will appear, it obviously can't interpret ">100" properly. In this case you need to provide it with a list of the form {{value, label}, {value, label}, ...}. For a "nice" range like {0, 100} it's quite easy to handle this, but what if you feed it a range like {5, 98}? Commented Mar 6, 2017 at 10:38

This is hopefully sufficiently general to handle most cases.

First roll a little helper function:

ticksHelper[min_, max_] :=
Module[
{
out =
ChartingScaledTicks[{Identity, Identity}][min, max]
// #[[;; , {1, 2}]] &
// Cases[#, {_, _?NumberQ}] &
},
If[
First@Last@out < max,
AppendTo[out, {max, "> " <> ToString@max}],
out[[-1, -1]] = "> " <> ToString@max
];
out
]


Then modify the definition of your colorbar to include the helper:

colorbar[{min_, max_}, colorFunction_: Automatic, divs_: 150] :=
DensityPlot[y, {x, 0, 0.1}, {y, min, max}, AspectRatio -> 10,
PlotRangePadding -> 0, PlotPoints -> {2, divs}, MaxRecursion -> 0,
Frame -> True, FrameLabel -> {{None, Row[{Subscript["t", "esc"]}]}, {None, None}},
LabelStyle -> Directive[FontFamily -> "Helvetica", 20],
FrameTicks -> {{None, ticksHelper[min, max]}, {None, None}},
FrameTicksStyle -> Directive[FontFamily -> "Helvetica", 20, Plain],
ColorFunction -> colorFunction]


It might be slightly problematic for a range like {0., 101.} though (you'll get a label at 100 and then a > 101 label at 101` and they'll overlap). It should be quite easy to fix, the exact manner depending on your needs.

• Nice! It works fine because always I use range with round limits. Commented Mar 6, 2017 at 11:37