# What algorithms are there for picking colors for plot lines on graphs?

I'm interested in what algorithms or rules I can programmatically implement to generate RGB or HSV colors for plotlines to keep them visually distinct from the neighbors.

I know that in professional mapmaking, there are algorithms or rules that make sure that no two adjacent countries on a map are the same color. I can also think of Microsoft office Excel as picking good tints/shades for plot lines (red, then blue, then purple/orange).

Here's an example of what I'm talking about - I need to generate colors for 12 lines on a black background. The colors here I've hardcoded by hand using web-safe RGB color codes. The problem arises when these lines overlap - it's hard to tell if one is looking at purple, slighly darker purple or violet. I'm looking for a better algorithm to produce colors for plotlines like these.

Here's an example using Flot plotting library for jQuery, it has nice succession of colors for graphs:

• two relevant questions here: programmers.stackexchange.com/questions/44929/… and stackoverflow.com/questions/470690/… Commented May 14, 2013 at 14:19
• It seems they just chose the base colors. And you have only five lines in this chart while your other example has twelve. If you would let Flot have more graphs you would most likely run into similar problems. There are only that many different colors and from there you have to repeat shades and can only try to have some "distance" between them. Commented May 14, 2013 at 14:35
• While there is a very interesting (and good) problem here, from a practical implementation side, I would strognly suggest looking at identifying the color set for a theme (greyscale, high contrast, pastels, color blind, etc...) with a reasonable maximum number (before it becomes unreadable) - 32 or 128 or so colors (depending on the application) and use that array index rather than trying to calculate a next color.
– user40980
Commented May 14, 2013 at 15:50

I recommend using the HSV or HSL color spaces, not the RGB color space, because HSV and HSL are better structured for generating colors that look different to humans. You'll have more work in RGB (though conversions back and forth exist, should you need them).

This is what HSV / HSL look like:

When using the HSV or HSL color space you can assume (very roughly) that the difference between the H (hue) components of two colors are a good approximation of the perceptual distance between the colors - i.e. the bigger the change in hue, the more different the colors will look to humans. You can try playing with S (saturation) and L/V (lightness/value) as well to eke out a few more very different colors, but they will not look as different for the same value change as varying the hue.

Depending on the number of distinct colors that you need, you can divide the hue-space into that number of different colors. If for example you have a hue-range of 256 values and you require 16 distinct colors, then your first color might be (0, 128, 128), your second (16, 128, 128) and so on. I somewhat arbitrarily picked S/L values smack in the middle here as that will usually be light and saturated enough to clearly see the color differences. This system is simple, and assumes you need to know nothing about adjacency of colors in your graph/map.

If you do not know in advance how many distinct colors you need but you know the upper limit, and dividing the hue range into colors with that upper limit in mind as above still gives you good perceptually different colors then you can use the same system with the upper limit.

If you (could) need very many distinct colors, you could still get away with using very similar or even the same colors, as long as they do not appear near the other elements of the graph that have the similar color. This requires knowing your adjacency situation in the graph you're rendering and may not always be straightforward, and even then it may not be a good idea as Dukeling points out in the comments: it may be confusing to viewers that the same color is used twice in the graph for two different concepts.

• Regardless of whether or not there is intersection, you do not want the same colours representing different things on a single graph (if this is what you imply), there's too much room for confusion and you may not be able to figure out which is which, so graph colouring is unrelated. In case you didn't notice, each line only has a single colour and consists of a sequence of connected points. Commented May 14, 2013 at 16:54
• @Dukeling - you misunderstand my point. At some point, no matter how carefully you choose, if you need many different colors you will start having colors that look similar (e.g. the purples in the first image in the question). At that point a naïve but simple implementation like I suggested may put those colors close together, making it hard to see what's going on. That's when you can use graph coloring to ensure that you are using distant colors for "close" lines on the graph. Commented May 15, 2013 at 5:53
• @Dukeling - I've edited my answer to include your remark about why reusing the same color may be bad. Commented May 15, 2013 at 9:59

For the case where you don't know in advance how many distinct colors you will be needing another interesting algorithm is the golden ratio algorithm.

Simply start at your favorite color and then go around the color wheel in steps of the golden angle (137.5°). With this angle you'll ensure that after every convolution around the color wheel your new colors fall between the colors you already created.

(Image from wikipedia)

I have experimented a bit and found out that even with HSL/HSV it's not quite easy to get a decent algorithm for nice, undisturbing, calming (all quite subjective, but...), yet contrasty colors. Some parts of the specter are visually similar - esp. the green-blue section. So I had to add some lightness variation.

Here is what I ended up with:

``````\$.plot(\$('#application_pie'), data_application_pie, {
series: { pie: { show: true,  innerRadius: 0.55, offset: { top: 0, left: -120 } } },
colors: \$.map( data_application_pie, function (item, index) {
return jQuery.Color({
hue: (index*0.95*360/data_application_pie.length),
saturation: 0.95,
//lightness: (index%2/-4)+0.55, alpha: 1
lightness: ((index%4 == 3 ? 1:0)/-4)+0.55, alpha: 1
}).toHexString();
})
});
``````