Impacks

K-band line+continuum emission (2166 nm) in the star-formation region AFGL 437. Data reduction by Peter Allen.

program names, file names
variable names
prompts, commands, program code


Contents:

Overview

Image data (as we tend to deal with it) generally consists of (at least) three main components: (1) the image plane itself, which is a 2-D array of the intensity values for each of the detector array's individual light-sensitive elements (pixels); (2) the weight plane (also a 2-D array) which indicates the "goodness" of the image plane pixels (eg., a zero in the weight plane means that that pixel's counterpart in the image plane is somehow not usable); and (3) the header file, an array of character strings which provides a description of the image (here's an example of an image header).

Near the end of 1997 I got really sick of having several different variables associated with the same image data file (one for the image plane, one for the weight plane, another for the header file, etc). So I developed a way of keeping all that stuff together with a single variable name. The solution I came up with is a structure with pointers to the image (which may or may not have a weight plane) and to the header file, as well as fields which give information about the size of the image and the date and time at which the structure was created. I have taken to calling the structures "impacks" (image packages). It is basically a poor attempt at dealing with the data in an object-oriented fashion. If I had it to do again, I'd redevelop all this software with a more strict adherence to the concepts of object-oriented programming, with constructors, destructors, methods, inheritance, and all that jazz. But at this point, I'd just like to get on with my life.


Creating, using, and deleting impacks

Images are read into memory from FITS data files. FITS is a file storage format, as GIF and JPEG are file storage formats. The rfits function is used to read FITS files into impacks:
IDLprompt> newimpack = rfits('dirname/filename.fits')
This reads in the FITS file filename in the directory dirname and creates an impack called newimpack. The image, header file, and weight plane (if there is a weight plane) associated with the file dirname/filename.fits may now be accessed via the variable newimpack.

Impacks can also be made from scratch. If you want to store an image, a header, and (maybe) a weight plane in a newly-created impack, you can do so with the imcre procedure. The following two commands create two impacks, impack1 and impack2, each of which contains the image imname and the FITS header hdrname:
IDLprompt> imcre, impack1, imname, hdrname IDLprompt> imcre, impack2, imname, hdrname, wt = wtname
The image portion of impack1 will be a 2-D image which is a copy of imname. The image portion of impack2 will be a 3-D image array, the top plane being a copy of imname, the lower plane being a copy of the weight plane wtname. When using the second form of imcre, if the dimensions of the image and weight planes do not match, imcre will complain and refuse to create the image package.

Incidentally, impacks, as IDL structures, have a rather funny-looking description in the symbol table (eg., when you press F1): STRUCT -> ANONYMOUS ARRAY[1]. This just means that the impack is a single (ARRAY[1]) structure (STRUCT) which has the label of ANONYMOUS. Structures can actually be labelled, but this imposes certain restrictions about changing the elements of that structure, and so impacks are not labelled (not important).

The different elements in an impack may be accessed using the filter function by setting any of four mutually exclusive keywords, as illustrated by the following examples:
IDLprompt> im1 = filter( impackname , /im ) IDLprompt> im2 = filter( impackname ) IDLprompt> h = filter( impackname , /hdr ) IDLprompt> weight = filter( impackname , /wt ) IDLprompt> stack = filter( impackname , /cube )
The first two examples produce the same result, as setting the keyword im in filter is the default mode of operation: im1 and im2 will be identical, and each will be equal to the 2-D image plane in impackname. The second example assigns a copy of impackname's header file to h. The fourth command assigns the 2-D weight plane in impackname, if there is one, to weight. Finally, if there is a weight plane, the fifth command assigns to stack a 3-D array which contains the image and weight planes of impackname. If filter is ever unable to derive from impackname the requested element (if, for example, cube or wt was set, but impackname has no weight plane), an integer of value -1 is assigned as the result.

filter can also be used to check the validity of an impack or an array of several impacks (as mentioned above, a single impack is actually an array, with one element, of structures -- you could also have an array of several impacks, such as the output of the load_list procedure). The following command will return information about the image(s) in impackthingy, where impackthingy is a single impack or an array of several impacks:
IDLprompt> info = filter( impackthingy , /diag )
If there is some major problem with impackthingy (eg., impackthingy isn't an IDL structure, some of the pointers are broken, etc.), then info will be a scalar with a value of 0., no matter how many elements in impackthingy. If impackthingy passes the preliminary diagnostic checks, then info will be a floating-point array whose length is the number of elements (impacks) in impackthingy. Each element of info should be a 1. or 2., indicating that the corresponding impack in impackthingy has only an image plane or an image plane and a weight plane, respectively.

Impacks may be saved (ie., written to disk) with the wfits procedure:
IDLprompt> wfits, 'filename', impackname
where filename (and the single quotes ARE necessary) is the pathname---relative to the current working directory---of the file to which impackname is to be written.

As mentioned previously, it's a good idea to delete variables after you've finished with with, especially big variables like images. However, AND THIS IS DAMN IMPORTANT, you mustn't use delvar to delete an image package until you've first run imdel. The reason for this is that the elements of an impack are pointers to images and headers, rather than the images and headers themselves. So if you run delvar on an impack, you'll delete the references to the data, but the data will still be locked up in memory. That data will then be unaccessable, and those memory addresses cannot become available again in that IDL session. If you want to delete an impack, make sure you do it in the following sequence:
IDLprompt> imdel, impackname IDLprompt> delvar, impackname
(Unfortunately, unlike delvar, imdel can have only one argument at a time.) Deleting an impack in the above sequence will first free up the memory referenced by the pointers in impackname, and then impackname itself will be deleted.


Annotative and arithmetic manipulation of impacks

Returning, for a moment, to the point of creating impacks, it's important for a FITS header to indicate any changes made to the image associated with that header. Most of the data reduction routines to be discussed in upcoming sections automatically alter the FITS headers of the images they alter, so that there is a record of everything that's been done to an image. But it's sometimes necessary to have fine control over the content of a FITS header. The head_edit procedure can be used to add lines of text to a FITS header file:
IDLprompt> head_edit, oldheader, newheader, $ IDLprompt> add_message = 'blah, blah, blah'
The above command will leave oldheader unchanged, copy it to oldheader, add the following line of text to oldheader:

HISTORY  3 aug 00: blah, blah, blah
The nohist and nodate Boolean keywords may be used to suppress printing of the HISTORY tag or the date. The default length of a line in a FITS header file is 80 characters, so if the message is shorter than this length, it is padded with whitespace at the end to give the proper length. If the message is longer than the line length, head_edit attempts to break the entry into several lines of text. If a line length other than 80 characters is desired, this may be specified with the linelen keyword.

If you need to perform some arithmetic operation on either plane in an impack after the impack has been created, you can do that with the imarith procedure. imarith can be used to add, subtract, multiply, or divide a scalar number or a 2-D plane to, from, against, or into (respectively) either plane in an impack. If the operand is a 2-D plane, it must have the same dimensions as the image(s) in the impack. imarith automatically annotates the header to indicate the type of arithmetic function performed. The following command adds the scalar value 2. to every pixel in the image plane of impack (thus changing impack) and alters its header accordingly:
IDLprompt> imarith, impack, 2., /add
The following command multiplies the weight plane of impack by im2D, assigns the result to the weight plane of impack, and alters the header via head_edit:
IDLprompt> imarith, impack, im2D, /multiply, /wt, $ IDLprompt> headermessage = 'ANDed weight plane with bad pixel mask'


Viewing impacks

Viewing images in IDL can be done with the v procedure. The first argument of v (a positional parameter) is the object you want to display. This can be a 2-D image, a 3-D image, an impack, or even (if the h keyword is set) a header file. v runs filter on the first argument to strip out the image.

The second parameter is optional; it's the magnification, which defaults to 2 (if no value is supplied as a second positional parameter in the call to v). The display window created at startup (by newwin) is approximately 550 screen pixels by 550 screen pixels, and is therefore large enough to display a 256x256 image array at a magnification of 2.

In displaying an image, it is necessary to set two parameters which will specify the display range. If, for example, you are running IDL with a black/white-linear color map, then the smallest pixel values (in the image array) appear on the screen as black, the largest pixel values look white, and intermediate values are linearly interpolated to various shades of gray. You need to tell IDL what two image values (ie., pixel values in the image array) correspond to the lower and upper ends of the display range. All image pixels with values lower than or equal to this minimum will appear black (in the black/white-linear color map), all image pixels with values larger than or equal to the maximum will appear white, and everything in between will be at an appropriate greyscale.

(If you try any of the following examples, you'll probably want to set the c keyword, as indicated. This will suppress a feature of v which we'll discuss in a moment.)

There are three ways to specify the display parameters in v. One way is to use the min and max keywords. If the minimum and maximum values you wanted mapped to the screen are 1000 and 5000, respectively, use the following command:
IDLprompt> v, impackname, 2, min=1000, max=5000, /c
The magnification was explicitly set to 2 in this example, even though that is the default value.

The second way to specify the display range is with the mm keyword. This effectively sets min= -|mm| and max= |mm|, where the vertical bars indicate absolute value. The following command sets the display parameters to -300 and +300 (this time we'll omit the magnification, but it'll default to 2):
IDLprompt> v, impackname, mm=300, /c

The third way of setting the display parameters depends on the statistics of the image. By setting sig=5, you tell IDL to set the display parameters to five standard deviations above and below the mean, where the mean and standard deviation are the first and second moments of all the pixel values in the input image:
IDLprompt> v, impackname, sig=5, /c

Now we'll discuss a few of the other features of the viewing program v. The first was alluded to above in the parenthetical note reganrding the c keyword. If this keyword is not set, v remains active even after the image appears in the display window (ie., the IDL prompt won't return):
IDLprompt> v, impackname, sig=5
As you move the cursor over the display window, the pixel coordinates and values are printed to the screen. During this time, you can reverse the color map by clicking the middle mouse key. This will continue until you press the third mouse button (ring finger on a right-handed mouse), at which time the v program is terminated. These features are suppressed by setting the c keyword in the call to v---control returns to the user as soon as the image is displayed.

v can also be run without giving an image or impack as the first positional parameter:
IDLprompt> v
In this case, it is as though the user never terminated v the last time it was used to display an image, and moving the cursor over the display window causes the pixel locations and values to appear as before. Again, this is terminated by clicking the third mouse button.

Setting the h keyword tells v to run filter on the first positional parameter to look for a FITS header. If h is set, then the first positional parameter may be an impack or a direct reference to an array of character strings. v will then display the header in a GUI.

If a named variable is given as a third positional parameter (and in this case, the magnification must be explicitly given as the second positional parameter, even if the desired magnification is the default value of 2), v allows the user to draw a box over the image:
IDLprompt> v, impackname, 2, box, sig=5
This is done by clicking the second mouse button to start drawing the box, and then clicking the second mouse button again after the box is the right size and shape. At this point, another box may be drawn in the same way, or the box may be moved around by clicking the first mouse button. Clicking the third mouse button ends the box-drawing rigmarole and terminates v. After runtime, the named variable (appearing as the third positional parameter, box in this case) is a 2-D array corresponding to the pixels within the box drawn on the image. This is useful for picking out interesting regions of an image, and we'll see other applications for this feature later on.

Setting the rec keyword lets you record the positions and values of individual pixels by clicking on them with the first mouse button. The coordinates and values will be written to the file ~/idlpro/disp.rec. This will continue until you click the third mouse button. Those pixel values and coordinates will remain in the file until the next time you run v with the rec keyword set. Setting the p keyword also prints these pixel coordinates and values to the command window (but only if rec is also set).

Setting the sam runs a bilinear interpolation routine to smoothe the image. This can make images (particularly if the magnification is more than 3 or so) look less pixelated.

See the documentation for v and view for more information.


Carl Welch