IDL plot objects


This document gives some notes about using IDL plot objects. Particular focus is given on how to reproduce features from IDL direct graphics.

Multiple plots on one page

IDL> p1=plot(findgen(5),layout=[2,1,1])
IDL> p2=plot(findgen(5),layout=[2,1,2],/current)

The POSITION= keyword is also available to directly position a plot within a window.

When annotating multiple plots with the 'text' object (the equivalent of xyouts in direct graphics), make sure to specify which of the existing plot objects is being annotated by using the target= input:

IDL> p1_text=text(1,1,/data,'Hello',target=p1)
IDL> p2_text=text(1,1,/data,'Goodbye',target=p2)

Creating an output file with fixed size

When creating a .eps file with direct graphics, the X-size and Y-size are set with a call to DEVICE. With object graphics, the plot window that is displayed to the screen can be manually adjusted using the mouse, and there's a button in the plot window that allows it to be saved in various formats. For figures for journals, however, you want to have an IDL routine that generates a plot with a fixed size without any manual intervention.

The following shows how a plot can be written to an eps file without manual intervention:

IDL> p=plot(findgen(5),dimension=[600,450],/buffer)
IDL> p.save,'idl.eps'
IDL> p.close

The /buffer keyword sends the plot to a buffer rather than the screen.

The dimension is set in pixel units. I notice the size of the output .eps file is larger than the IDL plot window, although the aspect ratio is correct.

Making png/jpeg images

These can be made simply with, e.g.,

IDL> p.save,'idl.png'

However, you'll notice that the image ends up huge, much bigger than the dimensions specified with dimension=. To fix this, do:

IDL> p.save,'idl.png',resolution=96

96 is the magic number that makes the png the same size as the IDL window dimension.

Images with axes

With direct graphics there wasn't a built-in routine to plot 2D images with X and Y axes, so many people used the Solarsoft routine 'plot_image'. Using the object function image.pro it's easy to produce image plots with axes. One point to note is that plot_image plotted images such that the coordinates corresponded to the center of the pixels. With image.pro, they correspond to the bottom-left corners of the pixels so care has to be taken when comparing the two routines.

The functionality of plot_image can be reproduced using the IMAGE object. The following example assumes that 'a' has size 256x256:

IDL> x=findgen(256)-128
IDL> y=findgen(256)-128
IDL> p=image(a,x,y,axis_style=2)

The equivalent of the SCALE= input to plot_image is achieved by simply multiplying X and Y by the scale factors. For example:

IDL> x=(findgen(256)-256)*2
IDL> y=findgen(256)-128
IDL> p=image(a,x,y,axis_style=2)

will stretch the image in the X-direction by a factor 2.

By default, image() will plot the image at its exact size - in this case 256x256 pixels. To make the image fill the display window better, the best option seems to be with the MARGIN= keyword. For example:

IDL> p=image(a,x,y,axis_style,margin=0.10)

Problem with scaling

Even after using the margin keyword, you may want to stretch the image in one direction in order to make a better plot. You can do this with, e.g.,

IDL> p.scale, 1, 1.5

which applies a 1.5 scaling in the Y-direction.

This works fine if the x and y arrays that define the axes are uniformly spaced. If they're not uniformly spaced, then the software seems to apply an interpolation to the data when doing the scaling. You will notice this by the fact that the pixels will not be stretched. I find that the interpolation often introduces ugly artifacts.

If your axes are close to being uniformly spaced, then I suggest re-defining them to make them uniformly-space and then using these new axes.

One example where I've seen this effect is when time is one axis of an image and (typically with space image data) the time difference between each frameis not exactly the same.

Colors

For line and symbol plots, specifying colors is much easier than with direct graphics. For example:

IDL> p=plot(findgen(5), color='red')

Note that only the data will be colored red, with the axes left with their default colors (use xcolor and ycolor to change the axis colors). See the IDL user guide for a complete set of IDL color names, and alternative ways of specifying the color.

For images, you can specify the standard IDL color tables as follows:

IDL> p=image(data, rgb_table=n)

where n is the number of table (e.g., 3 for the standard red table).

Spectrum plot (histogram)

Spectra are usually displayed with a histogram plot, and with direct graphics one uses PSYM=10. With the plot object command, the correct option is /stairstep:

IDL> p=plot(x,y,/stairstep)

Make sure that you don't use the /histogram option as this offsets the spectrum by half a pixel compared to the old psym=10 option.

Object-equivalent for UTPLOT

The SSW routine UTPLOT is widely used for plotting light curves, giving time in a nice format on the X-axis. IDL has its own capability for plotting times, but the times must be in Julian Day format.

Suppose we have a 1D array called TT containing times in any of the standard SSW formats, and an array LC containing the light curve data points. We can plot this with:

IDL> tt_jd=tim2jd(tt)
IDL> p=plot(tt_jd, lc, xtickunits='time')

where IDL will choose which time unit (seconds, minutes, hours, etc.) is best to use based on the data range. You can force it to use hours by using xtickunits='hours'.

The above would give the tick marks as, e.g., '0', '1', etc., for hours. If you'd prefer to have '00:00', '01:00', then you have to specify a format with XTICKFORMAT='(C(CHI2.2,":",CMI2.2))'. Here C() tells IDL to interpret the input as time, then CHI extracts the hour portion, CMI the minute portion, and 2.2 gives the format for the number string. Check the IDL help page for TICKFORMAT for more details.

If you want to set the X-range, you have to set it in Julian Days. So use TIM2JD again to convert your times, and then use XRANGE=.

IDL Maps

Dominc Zarro created a suite of software for displaying solar images based around "maps", which are IDL structures containing an image with metadata. I've created a routine called plot_map_obj (available in Solarsoft) that allows a map to be plotted as an object:

IDL> p=plot_map_obj(map)

I've tried to re-create the functionality of plot_map.pro, so some of the keywords are the same:

/log  - plot logarithm of the image
dmin - specify a minimum intensity value to display
dmax - specify a maximum intensity value to display

One new keyword is /velocity which tells the routine that it's displaying a velocity map and so it uses the familiar red/blue color table. Note that the keyword dmax= specifies the maximum absolute velocity to display.

For over-plotting a map as a contour on another map, do:

IDL> p=plot_map_obj(map1)
IDL> q=plot_map_obj(map2, /overplot [, levels=levels])

where the keyword levels allows the intensity levels of the contour to be plotted.

Color bars for image plots

These are straightforward to add, as illustrated below using a map image:

IDL> p=plot_map_obj(map,/log)
IDL> pcb=colorbar(target=p,orientation=1,title='Log!d10!n Intensity',/border_on)

By specifying the target as the image object, then colorbar automatically picks up the range of intensity values in the image. The orientation keyword determines whether the colorbar appears above the image (0) or to the right side (1). The position keyword can be used to place the colorbar at any location.

Destroying a plot object

Simply use the 'close' method:

IDL> p=plot(findgen(5))
IDL> p.close


Page maintained by Dr Peter R Young.