APPENDIX B: Examples Here are a few simple SPP applications. They illustrate a range of tasks including image I/O, cl I/O, dynamic memory, and graphics, including cursor interaction. They are complete, including a task statement to implement cl tasks. More examples are provided in Rob Seaman's An Introductory User's Guide to IRAF SPP Programming [Seaman92]. "Hello World" One useful way to get started with a language is to build and run a simple program, before attempting to learn all the details. It often provides an introduction to the flavor of the language and its syntax and can provide a template for developing useful applications. Here is the SPP version of the common "hello world" program. It prints the text "hello world" on the user's terminal. Example B.1: Hello World Example. The text of this program would be placed in a file with the extension ".x" and compiled with the command xc (X Compiler) in the host system or in the IRAF cl as follows: xc hello.x The xc compiler will translate the program into Fortran, call the Fortran compiler to generate the object file (hello.o), and call the loader to link the object file with modules from the IRAF system libraries to produce the executable program. xc may be used to compile C and Fortran programs as well as SPP programs, and in general behaves very much like cc or f77 (note that the -o flag is not required; by default the name of the output module is the base name of the first file name on the command line). The -f flag may be used to inspect the Fortran created by the preprocessor; this is sometimes necessary to interpret error messages from the F77 compiler. Finally, to run the program, you may define it as a task in the cl by using the task statement: task $hello = hello.e Then run it by typing hello. cl Interaction Example B.2 demonstrates simple use of clio, reading and writing cl parameters and simple imio, reading an image. While the application does little significant, it illustrates a task that analyzes an image and extracts information from it. The procedure called by the above procedure to perform the operation on the images is shown in Example B.3. Example B.2: Simple Use of clio. Example B.3: Procedure Called by Bones. A Simple Filter This example (Example B.4) illustrates a simple filter. That is, a task that takes a file as input and produces a similar but changed file on output. In this case the input and output are IRAF images and the operation is the absolute value. Note particularly the use of dynamic memory allocation and basic image I/O. Example B.4: Sample Filter. Image I/O The following is a complete example that demonstrates line by line image I/O by copying an existing image to a new image. Note that the procedure works the same regardless of the dimensionality and data type of the images. This is the code for the IRAF imcopy task in the images package which is in images$imutil/imcopy.x. There are comments scattered interspersed with the code to clarify it. IM_MAXDIM and other constants used for image I/O are defined in . Other constants such as ARB and SZ_FNAME are defined in iraf.h which needs not be included explicitly. Example B.5: Image I/O. imgsection() returns only the image section from an image file name. If image2 = mosaic.imh[100:200,150:350], then the image section is [100:200,150:350] and we want to overwrite this space with the same space from the input image, i.e., pixels 100 to 200 inclusive in the first axis, and rows 150 to 350 in the second axis. If the output image already exists, the access mode is READ_WRITE. If it does not exist open it as a NEW_COPY of an existing image, passing the open image descriptor, im1, to immap(). All necessary header information will be copied. The array v1 keeps track of the current line to read from image1 by imgnl() and v2 keeps track of the line written to image2 using impnl(). amovkl() initializes the vectors with the long integer constant 1. The macro defined constant IM_LEN contains the size of the image. It is defined in . It is a vector storing the size of each dimension up to the maximum number of dimensions supported by imio (seven). There is a case for each data type to preserve the precision of the pixels. Example B.5 (Continued): Image I/O. The pixel type unsigned short (TY_USHORT) will be copied to a buffer of type long. The routine imgnll() (the last letter denote the pixel type) returns a pointer in buf1 that points to the beginning of the current line in the input image. The routine impnll() returns a pointer buf2 that points to the beginning of the next line in the output image. amovl() copies npix pixel values from the input buffer to the output one. The input and output buffers in Meml[] have already been allocated in memory by imgnll() and impnll(). The loops will be repeated until all the lines have been copied, in which case an EOF is returned. Example B.5 (Continued): Image I/O. Basic Graphics Example B.7, below, demonstrate a very simple gio (IRAF graphics) application. It draws a box in graphics and writes a text string. It follows the conventions of most IRAF graphics applications. The graphics device is specified in the task parameter device and the graphics stream is STDGRAPH. Note that gopen() returns a pointer and this value is passed to all subsequent graphics procedures. In addition, the include file is specified. This contains defines for gio macros such as G_TXSIZE. Example B.6: Basic Graphics. Interactive Graphics This example builds somewhat on the previous example. In addition to simply writing graphics, it uses the clgcur() procedure to return cursor coordinates to the application. Depending upon how the task is run, this is resolved in various ways. The usual situation is for the task to be run from the cl with the interactive graphics cursor activated. The user would then move the cursor and pressing a keyboard key would result in the coordinates of the cursor being returned to the task. The clgcur() procedure is a clio function that returns a value that is EOF upon the end of cursor interaction. Note that the function call is within a while loop that terminates on the value EOF. Note also that several cursor keys have been defined for the task. That is, when the user types that key with the graphics cursor active, the task performs some function. These functions are in addition to the built-in functions of the IRAF graphics cursor. The implementation of the cursor keys is also an example of the switch ... case syntax. Example B.7: Interactive Graphics. Example B.7 (Continued): Interactive Graphics Example B.7 (Continued): Interactive Graphics: the Arrow Procedure. Task The following code is a task statement that creates a task for the above procedures. task arrows, bones, filter, hello To compile the code, use xc directly or use mkpkg, which also uses xc. If you extract the SPP code in the previous sections in files named bones.x, filter.x, hello.x, arrows.x, and x_tutor.x, respectively, the following command will compile and link them: xc x_tutor.x bones.x filter.x hello.x arrows.x producing x_tutor.e as the executable. You can either run this directly or define tasks in the cl: task arrows, bones, filter, hello = x_tutor.e B.12.1 mkpkg The following is a sample mkpkg file to make the package comprising the above examples. It creates a library (tutor.a) containing the procedures and links a single executable (physical task) containing several logical tasks. Example B.8: Sample mkpkg File.