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
If you want to test your plot object expertise, then try my exercises.
I also have a list of IDL
plot object quirks that you should be careful of.
What is a plot object made of?
When you create a plot object with, for example,
it's worth noting that 'p' is really just the straight line
corresponding to the data. In putting this on the screen, however, IDL
has had to first create a window that contains the straight line plot,
and create four axes. Each of these is a plot object in its own right.
The objects can be accessed by doing:
So if you'd like to change the background color from white to pink, and change the plot dimensions to 700x400, you can do:
Similarly you can modify the axis properties - see "Suppressing or replacing plot axes" further down.
If you now overplot a new object:
then 'q' inherits the window and axes objects (thus q.window
and q.axes are the same as p.window and p.axes). One consequence is
that if you try to close 'q', thinking that it will only remove the
over-plotted line, you find that the entire window gets destroyed. This
is because 'close' actually tells IDL to close the window that the object is plotted in, not just the object.
This behavior also helps explain what happens when you do:
Why does IDL not get confused by having three objects of the same name?
Because each new 'p' inherits the window and axes from the previous
'p'. You can no longer modify the first 'p' once you've created the
second one, but you can modify 'window' and 'axes' since they've just
been copied into the new 'p'.
Multiple plots on one page
The POSITION= keyword is also available to directly position a
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:
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
The /buffer keyword sends the plot to a buffer rather than the
The dimension is set in pixel units. I notice the size of the
.eps file is larger than the IDL plot window, although the aspect ratio
Making png/jpeg images
These can be made simply with, e.g.,
you'll notice that the image ends up huge, much
the dimensions specified with dimension=. This is because the default
is to write the image with 600 dpi (dots per inch). To get an image
that is (almost) the same size as the IDL window, do:
This sets the dpi to 97.
Images with axes
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
object. The following example assumes that 'a' has size 256x256:
The equivalent of the SCALE= input to plot_image is achieved
simply multiplying X and Y by the scale factors. For example:
will stretch the image in the X-direction by a factor 2.
By default, image() will plot the image at its exact size - in
case 256x256 pixels. To make the image fill the display window better,
the best option seems to be with the MARGIN= keyword. For example:
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.
Suppressing or replacing plot axes (the axis object)
When you create a plot, it's worth noting that IDL
creates the plot (a line plot, symbol plot, image, etc.) and a set of
axes. Each axis is it's own object. Thus if you do:
is really just the straight line representing the data, but IDL has had
to create a set of four axis objects representing each of four
displayed axes. You can access these axes by doing
'ax' is an object array that specifes each of the four axes. ax is
the bottom X-axis, ax is the left Y-axis, ax is the top X-axis
and ax is the right Y-axis. You can make any of the axes disappear
by using the 'hide' property. For example:
gets rid of the right Y-axis. Set hide to 0 to make it reappear.
You can also modify the individual axes separately. For example:
You can also perform a coordinate transform to the axis, which is
useful if you're using the two Y-axes to represent two different
curves. Suppose the left axis represents degrees centigrade, then the
right axis can represent by Fahrenheit by doing
(You may have to do ax.showtext=1 to show the axis numbers.)
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
IDL> p=image(data, rgb_table=n)
where n is the number of table (e.g., 3 for the standard red
Spectrum plot (histogram)
Spectra are usually displayed with a histogram plot, and with
graphics one uses PSYM=10. With the plot object command, the correct
option is /stairstep:
Make sure that you don't use the /histogram option as this
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
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> p=plot(tt_jd, lc, xtickunits='time')
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
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=.
Application to GOES data
There is object-based software for plotting GOES data - see
at GSFC. If you want to take the GOES data and plot it with the IDL
object software, then follow the method below.
First extract the GOES data for the required time period
Create the time array in JD format:
Extract the light curve for the low energy channel, and then
Dominc Zarro created a suite
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:
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> 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
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.
Creating a multi-page postscript/pdf file
you have a lot of data that you'd like to browse quickly,
it's useful to send the plots to a single postscript or pdf file, such
that single (or multiple) plots appear on each page. You can then
quickly flick through the pages (either with an electronic or
This can be done using the /APPEND keyword when you save a plot. I give
an example below of making a 6-page pdf document with 2x3 plots per
page. Note that object "w" gets destroyed and recreated on each "i"
loop, but the channel that sends w to the pdf file remains open,
irrespective of this.
FOR i=0,5 DO BEGIN
FOR j=0,5 DO BEGIN
Destroying a plot object
Simply use the 'close' method:
Page maintained by Dr Peter R Young.