Fanning Software Consulting

Evaluating Keyword and Parameters Expressions in cgWindow

QUESTION: I am used to writing programs in which keyword values and even parameters are determined at run-time. For example, I might use the THICK keyword to set the plot thickness to 4.0 if I am outputing to a PostScript file and to 1.0 otherwise, like this.

   IDL> cgPlot, cgDemoData(1), THICK=(!D.Name EQ 'PS') ? 4.0 : 1.0

This works fine when I am simply creating plots in normal IDL graphics windows or in the PostScript device. But, it doesn't work properly if I display the plot in the resizeable graphics window cgWindow. When I create a PostScript file from the resizeable graphics window, the plot thickness is always set to 1. Is there a way I can evaluate the value of the THICK keyword at run-time, so the keyword is set to the proper value in the PostScript file?

ANSWER: You are correct. Because of the way cgWindow "stores" the command to be replayed or executed when the current device is switched to produce the PostScript file, it is not possible to re-evaluate the keyword value later. The value of the keyword when the command is added to cgWindow is "hardcoded" by default as the keyword value.

This is almost always a problem of wanting to do something different in the PostScript device, as opposed to what happens on the display. To address this problem, I have added two keywords to cgWindow as of September 1, 2011. The keywords are named AltPS_Keywords and AltPS_Params. Both keywords accept a structure of alternate values to be used in place of the normal keyword or parameter values when the code is executed in the PostScript device.

To use your example of a different thickness of line in your PostScript file, you would add your command to cgWindow like this.

   IDL> cgPlot, cgDemoData(1), THICK=1.0, ALTPS_KEYWORDS={THICK:4.0}, /WINDOW

The alternate PostScript keyword values must be in a structure with fields spelled exactly as the actual keyword that they will replace. When this command is exectuted in a display window, the THICK keyword will be set to 1.0. When this command is executed in the PostScript device, the THICK keyword will be set to 4.0. The alternative keyword structure can contain as many fields as you like.

A similar strategy is used for positional parameters, although here the fields are restricted to the names P1, P2, and P3, corresponding to the three positional parameters that can be passed to cgWindow. For example, suppose we wanted to display a different plot in the PostScript file when the command above is executed. We could write the command like this.

   IDL> cgPlot, cgDemoData(1), ALTPS_PARAMS={P1:Findgen(11)}, /WINDOW

Practical Examples

Suppose you want to use a Greek symbol in the X title of a plot. You could write your code like this.

Note: The rather clunky method of writing a Greek character or other symbol described in this article has been changed in a July 2012 update of the Coyote Library. It is now possible to directly embed these types of symbols into your text string.

   IDL> cgPlot, cgDemoData(1), /WINDOW, $
           THICK=1.0, XTITLE='Distance (' + cgSymbol('mu') + 'm)', $
           ALTPS_KEYWORDS={THICK:4.0, XTITLE:'Distance (' + cgSymbol('mu', /PS) + 'm)'}

Suppose you want to add a line of text to the current plot window, but you want to display the line in a different location in the PostScript file as opposed to the display, and you want to right align it at its new position.

   IDL> cgText, 0.20, 0.85, /Normal, 'Line of Text', ALIGNMENT=0.0, $

Here is how the plot looks on the display and in a PostScript file.

The plot on the display.
The plot as seen on the display.
The plot saved as a PostScript file.
The plot saved as a PostScript file.

If you use the popular TeXtoIDL program, it can be used in a similar fashion to the Coyote Library cgSymbol program demonstrated above, although here you will have to find the proper PostScript form of the string before you enter the program in the cgWindow. (Please note, it is now possible to embed TeXtoIDL control sequences directly into graphical text, making the method shown here obsolete.)

   IDL> cgPS_Open
   IDL> ps_text = TeXtoIDL('sin(x/\alpha) e^{-x/\beta}')
   IDL> cgPS_Close, /NoFix
   IDL> cgWindow, WXSize=800, WYSize=400
   IDL> cgText, 0.5, 0.5, /Normal, TeXtoIDL('sin(x/\alpha) e^{-x/\beta}'), $
           Charsize=3.0, Alignment=0.5, Color='red', $
           ALTPS_PARAMS={P3:ps_text}, /Window

If the TeXtoIDL control sequences are embedded directly, the code will look like this, instead.

   IDL> cgWindow, WXSIZE=800, WYSize=400
   IDL> cgText, 0.5, 0.5, /Normal, TeXtoIDL('sin(x/$\tex\alpha$) e^{-x/$\tex\beta$}'), $
           Charsize=3.0, Alignment=0.5, Color='red', /Window
   IDL> cgControl, Output=''

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

Written: 1 September 2011
Updated: 24 November 2012