Changing Colors in cgWindow
All was well until I wanted to change the colors in the contour plot. I found I could easily change the colors for the contour plot itself with cgLoadCT, simply by setting the Window keyword. But, I could not find a way to change the out-of-bounds colors. Here is my code. Can you help?
data = cgDemoData(2) nlevels = 12 oob_low = 0 oob_high = nlevels levels = Indgen(nlevels)*100 + 100 range = [Min(levels), Max(levels)] TVLCT, cgColor('Hot Pink', /Triple), oob_low cgLoadCT, 33, NColors=nlevels-1, Bottom=1 TVLCT, cgColor('Tan', /Triple), oob_high cgContour, data, Levels=[Min(data),levels], /Fill, C_Colors=Indgen(nlevels+1), $ /Outline, Position=[0.1, 0.1, 0.9, 0.8], /Window cgColorbar, NColors=nlevels-1, Bottom=1, OOB_High=Fix(oob_high), $ OOB_Low=Fix(oob_Low), /Discrete, /Fit, Range=range , /AddCmd
|A filled contour plot with out-of-bounds colors.|
ANSWER: Yes, this can be a little confusing. The way cgWindow works is that when the window is first created it loads whatever colors are in the color table into its internal color vectors. Then, whenever it needs to draw the graphics commands that have been loaded into it, it first loads the IDL color table with these internal color vectors. In this way, the window can protect its own colors.
As you have discovered, one way to update the color vectors that are stored internally is to use the cgLoadCT command with the Window keyword, like this.
cgLoadCT, 5, NColors=nlevels-1, Bottom=1, /Window
Those colors are immediately changed in the cgWindow graphics plot.
|The contour colors have changed, but not the out-of-bounds colors.|
Unfortunately, the Window keyword may give you a false sense of what is happening. Normally, when you use a Window or AddCmd keyword on a Coyote Graphics command, that command is added to the command list in the cgWindow. But, that is not what is actually happening here.
Instead, what is happening is that colors are being loaded into the IDL hardware color table table, and then the color vectors of that color table are being sent directly to the "command object" that is at the heart of cgWindow. The cgLoadCT command itself is not being loaded in cgWindow. (This kind of communication with IDL objects has been a feature of Coyote Library color routines from the very beginning, and is one of the features that have always separated them from normal IDL color handling routines.)
Knowing this, you might be tempted to look for the Coyote Graphics equivalent of TVLCT. It would be possible to write such a thing, no doubt, but that is generally not what is done with cgWindow.
Instead, what is done is to load the hardware color table in IDL normally, then copy it into a 3-by-256 byte array, and pass this directly to the cgWindow with the cgControl command and the Palette keyword. The code looks something like this.
TVLCT, cgColor('Red', /Triple), oob_low cgLoadCT, 4, NColors=nlevels-1, Bottom=1, /Brewer, /Reverse TVLCT, cgColor('Yellow', /Triple), oob_high TVLCT, rgb, /Get cgControl, Palette=rgb
The output now looks like the figure below, with both the contour colors and the out-of-bounds colors changed.
|All contour colors have changed when the palette is passed to cgWindow.|
If you prefer not to load the hardware color table, you can get the color palette out of the cgWindow, manipulate it, and put it back. The commands to do so would look like this. Again, the window will update itself when you are finished and you will see the new colors on the display.
void = cgQuery(/Current, ObjectRef=thisWindow) thisWindow -> GetProperty, Palette=theseColors theseColors[oob_low,*] = cgColor('Purple', /Triple) theseColors[oob_high,*] = cgColor('Cyan', /Triple) thisWindow -> SetProperty, Palette=theseColors, /Update
Version of IDL used to prepare this article: IDL 7.1.2.