Fanning Software Consulting

Correct Colors in Legends

QUESTION: I have updated to the latest version of the IDL NASA Astronomy Library legend routine, AL_LEGEND, but when I use it in my programs it no longer produces the correct colors. Is this program broken, or am I doing something wrong?

ANSWER: The program is not broken, but if by "wrong" you mean "living in the last century", then the answer is probably yes. :-)

This NASA legend program, AL_LEGEND, was renamed and updated to use Coyote Graphics System routines when IDL 8 was introduced and appropriated the LEGEND name for itself. A tenet of the Coyote Graphics System is that drawing colors are more easily understood in code if they are expressed as color names rather than as some esoteric number (e.g, "green" as opposed to 187 or '34FC53'xL). Thus, the best way to express drawing colors in AL_LEGEND is by specifying the color names directly, like this.

   cgPlot, cgDemoData(17), PSym=-15, Color='red', YRange=[0,120], $
      LineStyle=0, YStyle=1, /Window
   cgPlot, cgDemoData(17), PSym=-16, Color='dodger blue', /Overplot, $
      LineStyle=2, /AddCmd
   AL_Legend, ['Experiment 1', 'Experiment 2'], PSym=[-15,-16], $
      LineStyle=[0,2], Color=['red','dodger blue'], Position=[5,115], /Window

You see the result in the figure below.

Using color names to express legend colors.
Using color names to express legend colors.

Nevertheless, a great deal of IDL code was written in the last century and still uses index numbers into the current color table to assign colors for the legend. The Coyote Graphics System programmers are mindful of the fact that astronomers move slowly (nowhere near the speed of light!), so they have written their routines to allow for indexed color. This is true even though all Coyote Graphics routines display their output in decomposed color, when possible, so they can avoid loading, and thereby contaminating, the colors in the one physical color table.

All Coyote Graphics routines, including AL_LEGEND, allow colors to be expressed as indices as long as the index is a string, a byte value, or a short integer value. For example, suppose you loaded the color dodger blue at color index 200, like this.

    IDL> TVLCT, 30, 144, 255, 200 ; Load "dodger blue" at color index 200.

Then you could create a legend using any of these three commands to express the color as an index into the current color table.

   cgDisplay, 300, 200
   AL_Legend, 'Color as string', PSym=15, Position=[0.2, 0.8], /Normal, Color='200'
   AL_Legend, 'Color as byte', PSym=15, Position=[0.2, 0.6], /Normal, Color=200B
   AL_Legend, 'Color as short integer', PSym=15, Position=[0.2, 0.4], /Normal, Color=200S

What does not work, however, is using a long integer to express the color index. This command will show up as a red symbol.

   AL_Legend, 'Color as long integer', PSym=15, Position=[0.2, 0.2], /Normal, Color=200L
Indexed color works as long as the index
        is a string, a byte, or a short integer.
Indexed color works as long as the index is a string, a byte, or a short integer.

This is because all Coyote Graphics routines treat a long integer as a number that can be decomposed into a specific color, in this case, because only red bits are set, a red color. This really becomes a problem when users have the compiler option DEFINT32 turned on for their program module, and they use a command like this.

   AL_Legend, 'Color', PSym=15, Position=[0.2, 0.2], /Normal, Color=200

While most of the time this would be interpreted correctly, in this case it is interpreted incorrectly because the default integer is now a long integer! The "fix," of course, is to just make sure this index number is expressed as a string, a byte, or a short integer. Then, things will work in exactly the same way they have always worked.

Version of IDL used to prepare this article: IDL 8.1.

Written: 7 October 2011