CHAPTER 2: Libraries and Packages: The VOS Interface The IRAF Virtual Operating System (VOS) comprises several libraries of procedures that provide the interface to IRAF, permitting an SPP application to access images, cl parameters and so forth. It provides an environment for developing scientific analysis applications. The libraries described here are available to any SPP application without explicitly including the library when linking. Other libraries exist that may be included. In addition, an applications package may create its own library. Several VOS packages have associated include files which may be used for predefined constants, structures, and other macros. These may be included in code with the syntax (see "Include Files" on page 36). Note that here the term package refers to a set of procedures in a library, not a set of applications tasks available in the IRAF cl. The VOS procedures are grouped into library packages of related procedures. Most of them deal with input and output of various forms. o clio - Interaction with the cl o memio - Dynamic memory allocation o imio - Image access o fmtio - Formatted I/O o fio - Basic file I/O o vops - Vector (array) operations o gio - Vector graphics o tty - Terminal I/O o osb - Bit and byte operations o plio - Pixel lists o mwcs - World coordinate system o etc - Miscellaneous The procedures described here represent the normal interface between an SPP program and the IRAF environment. That is, they are the only procedures that should be called. While additional, lower-level, procedures exist in the library, these should not be used. The top-level interface is intended to be stable and well documented. The remainder of the library cannot be guaranteed to remain free of modifications such as changes to the calling sequence. Using lower level procedures in portable, maintainable code represents an interface violation and causes potential maintenance problems. This chapter describes many of the VOS package library procedures. While every attempt has been made to provide comprehensive and up-to-date information on the VOS packages, there are quite a few libraries and the number of individual procedures is quite large. An exhaustive description of each procedure and its calling sequence is beyond the scope of this reference. In particular, it is not practical to describe each procedure in extensive detail. Nor is there room to fully describe every calling argument to every procedure. However, in many cases it should be clear what the data type and meaning are for most of them. In many cases, they are discussed in the text. Examples are used throughout to demonstrate the most commonly used procedures. Ideally, there would be a complete document for every library package describing each procedure and its calling arguments in detail. An example is gio with a quite complete reference. However, not every package has such complete documentation. There is usually a table describing the important procedures in a given library package. If there is a variable and equals sign then the procedure is a function. If there is no variable assignment, the procedure is invoked by a call statement. It should be fairly clear what is the data type of the function by the variable name. In many cases, a given procedure is implemented separately for several different SPP data types. That is, there is a separate procedure for each data type. In that case, there is usually a single entry in the table for that family of procedures with the suffix t indicating to specify the data type with the initial of the data type name. You should refer to the source code for the definitive description of any procedure. The best sources for such information is in the IRAF system itself. Each package resides in a separate directory below the IRAF sys directory, with the same name as the package. This directory contains the source code for the package library procedures. In addition, there is usually a doc directory below this source directory, containing help files or additional documentation. For example, the directory sys$imio contains the source and additional documentation for the imio library. Note also that the IRAF cl defines an environment variable for each library with the same name, imio or fmtio, for example. Therefore, the source to immap() is in imio$immap.x. It is quite instructive to look at the source files as well as the associated documentation. Note however, that these source directories contain all of the library procedures. This includes lower level code, not intended to be called by SPP applications tasks, but by the library procedures themselves. Interaction with the cl - clio The clio package allows an application to interact with the IRAF command language (cl). This includes mostly reading and writing cl parameters. In addition, there is a set of procedures for handling filename templates, lists of input files, as well as satisfying interactive graphics input (cursor position). Parameters in the cl may have a data type attribute as SPP parameters are typed. The SPP data type need not match the cl parameter's data type, however. The data type is silently converted by clio. The typed procedures returning cl parameter values refer to the data type of the SPP variables accepting the value of the cl parameter. Ordinary Parameters There is a separate read (get) and write (put) procedure for each SPP data type. All of the get procedures, except strings, are functions, returning the value of the cl parameter as the function value. Each function takes a single argument of type char, the cl parameter name. When the function is called, the cl will attempt to resolve the value of the parameter from a default in a parameter file or prompt for input from the standard input stream STDIN (see "Formatted I/O - fmtio" on page 78). If the program is not connected to the cl (i.e., if it is run stand-alone), a prompt will be written to STDOUT and the value of the parameter is read from STDIN. In the case of string parameters, there is a get and put procedure, returning the string value in a calling argument. Function Call Purpose --------------------------------------------------------------------------------- value = clgetT (parname) Get the value of a cl parameter clgstr (parname, string, maxch) Get a cl string parameter value = clputT (parname, value) Put the value of a cl parameter clpstr (parname, string) Put a cl string parameter clgwrd (parname, keyword, maxchar, dictionary) Get an enumerated string -------------------------------------------------------------------------------- Table 2.1: Parameter I/O Functions. The procedures to read and write numeric parameters are implemented for each SPP data type: bool, char, short, int, long, real, double, and complex. Use the appropriate procedure by replacing T with the first letter of the corresponding data type, clgetr() for type real or clgeti() for type integer, for example. Note that the data type of the returned value need not match the parameter's data type. Implicit type conversion is done by clio. The parname parameter is a char variable containing the parameter name. This may be a literal string, a predefined string parameter constant, or a character variable containing the desired string (which may also have been read with clgstr()). In the case of clgstr(), the additional parameter maxch specifies the size of the string parameter. The following example illustrates clio by reading several parameters from the cl. Example 2.1: Reading Parameters From the cl. Note the literal string constants for the parameter names and the predefined constant SZ_LINE specifying the size of the returned string. Also, note the distintion between the variable assigned a value in the code and the parameter as defined in the cl. There is no short data type in the cl, only integers. The procedure clgets() reads a cl parameter of any data type into a short variable. The cl parameter shortpar is declared as an integer but the variable sval is declared short. Such a procedure implemented as part of a task may use a parameter file to specify attributes of parameters. This is a text file with a root name the same as the task name and an extension .par. The above example defines a task readcl whose parameter file would be called readcl.par, containing the lines shown in. See "Parameter Files" on page 171 for a more detailed description of .par files. Example 2.2: Parameter File. The clgwrd() procedure returns the value of an enumerated string parameter. This is a string parameter whose value may take on one of a list of possible values. The list of possibilities is specified in the parameter file in the minimum value field as a quoted string with values delimited by a vertical bar. For example the parameter color might permit the selection of several possible values. The definition in the parameter file might be: color,s,h,"black","|black|white|red|green|blue|",,"color" The cl uses minimum matching to determine the desired value from the smallest unique initial characters the user specifies for the string. You must specify the dictionary or the list of possible values to clgwrd() in the dictionary argument returns the full word in the keyword argument. One pitfall is the potential mismatch between the enumeration string in the parameter file and the dictionary in the source. However, it is possible to read the enumeration string using clgstr() since it is possible to read the individual components of the parameter definition in addition to its value. The following would return the dictionary for the color parameter as defined above: call clgstr ("color.p_min", colordict, SZ_LINE) Where colordict is a string variable and would be used in the clg- wrd() call: call clgwrd ("color", color SZ_LINE, colordict,) pset parameters Any cl parameter may be included in a pset. A pset is a set of cl parameters referred to as a group via a single parameter of a task. The pset itself is defined as a task in the cl and is defined by a .par file. In the SPP code, however, pset parameters are accessed identically to any other task parameter. While you may prepend the pset name to the parameter name, this is not necessary and not recommended. List Structured Parameters List structured or list-directed parameters permit a number of values to be accessed by an application from a file specified by name. The following procedures get list structured parameters from the cl. The first two return a status value which is EOF on reading at the end of file on the input. The clglpt() procedures return the value of the appropriate data type as the function value. Procedure Call Purpose ------------------------------------------------------------------------ status = clglpT (param, value) Get a numeric parameter len = clglstr (param, outstr, maxch) Get a string parameter ----------------------------------------------------------------------- Table 2.2: List-Structured Parameter Functions. The procedure represented by clglpT() reads a numeric list structured parameter and is implemented for the usual SPP data types: bool, char, short, int, long, real, double, and complex. It returns the value as the second procedure argument, whose data type should match the procedure. The function return value is an integer status that takes the value EOF upon reading after the last parameter in the list. The other procedure, clglstr() returns the length of the string read as the int function value, or EOF after reading the last string. For example, we may wish to read integer values from a list filename int_file.txt which contains the following: 1 22 333 4444 55555 666666 If we add the following statements to the program readcl in the previous section: . . while (clglpi ("intval", ival) != EOF) { call printf ("integer value: %d\n") call pargi (ival) } . . then the parameter file should have the following line: intval,*i,a,"int_file.txt",,,"> List of integer elements" Notice the additional flexibility to input data to a program; changing the input list filename gives you another set of values. Vector Parameters It is possible to access a group of parameter values using a single root parameter name. This provides the capability of vectors or arrays in cl parameters. The array structure, default values, ranges, etc. may be specified in the .par file as with scalar parameters. However, the syntax is slightly different. For example, the following declares a singly dimensioned real array having three elements. vecreal,ar,a,1,3,1,,,"real vector elements", 0.0,1.2,3 Note that the character a precedes the data type field, the next three fields specify the dimensionality, size, and starting index, and the default values are after the prompt string. The following code (Example 2.3) will read the above values. Example 2.3: Reading Vector Parameters. Note that the element number of the cl parameter vector is enclosed in square brackets following the parameter name and is part of the string passed to the clgetT() and clputT() procedures. Interactive Graphics Cursor The cl treats an interactive graphics input cursor read similarly to a list structured cl parameter query. When the user asks for a cursor position, either through a cl query or through a task, the cl issues a prompt which the user must satisfy with some action. In the case of a normal cl parameter, the user may type in the value of the parameter. For a cursor read (assuming a graphics terminal with cursor capability) the graphics enters graphics input (GIN) mode. The user may then move the cursor on the screen. To terminate graphics mode, the user types a key on the keyboard. This satisfies the query prompt and the cl returns the cursor position. The clgcur() procedure returns the next cursor value from a list structured cursor type parameter. The format of a cursor value is as follows: x y wcs key sval where o x, y - are the x and y cursor coordinates o wcs - is the world coordinate system in which cursor coordinates are given o key - is the key (stroke) value associated with cursor read o sval - is an optional string associated with the given key All of the fields need not be given, and extra fields may be supplied and will be either ignored or returned in sval. The x y, and wcs fields may be omitted, in which case the input is key sval, causing INDEF INDEF 0 key sval to be returned, exactly as if the INDEF INDEF 0 had been typed in. The number of fields read is returned as the function value; EOF is returned when the end of the cursor list is reached. Since the cl treats a cursor query as a parameter, the clio procedure clgcur() is used to perform interactive graphics input from an SPP task. Its calling sequence is: call clgcur (param, wx, wy, wcs, key, strval, maxch) Field Types and Names Contents -------------------------------------------------------------------------- char param cl parameter name real wx, wy World coordinates of cursor int wcs Index of WCS at cursor position int key Keystroke value used to return cursor char strval [maxch] String command if key = `:' int maxch Size of strval ------------------------------------------------------------------------- Table 2.3: Graphics Cursor Parameters. Note that the argument key is an int typed variable, not char as might be expected. There are two flavors of cursor available through the cl: for vector graphics and image display. The cl data type of a cursor parameter may be either *gcur for a graphics cursor parameter or *imcur for an image display cursor parameter. See "Vector Graphics - gio" on page 114 for a brief description of the graphics procedures. See the gio reference manual (Graphics I/O Design [Tody84b]) for a more complete description of cursor interaction. cl Command A quite general method is available to execute any cl command (task) from an SPP application. The procedures clcmd() and clcmdw() send a string as a command line to the cl. The single argument to both procedures is a string containing the command to execute. The only difference between the two procedures is that clcmdw() waits for the completion of the command before returning to the caller. Procedure Call Purpose ------------------------------------------------------------------ clcmd (cmd) Send a command line to the cl clcmdw (cmd) Send a command to the cl and wait for completion ------------------------------------------------------------------ Table 2.4: CL Command Execution Procedures. Sending an explicit command to the cl requires that the task have detailed knowledge of the capabilities of the cl and of the syntax of the command language. This means that the task is very dependent on the cl and may no longer work if the cl is modified, or if there is more than one version of the cl in use in a system. For this reason clcmd() should only be used where it is truly necessary, usually only in system utilities. Memory Allocation - memio Memory may be dynamically allocated within an SPP application. The memory is referenced by a pointer, an int value containing the memory location of the first element of the buffer. The allocated memory may then be accessed as if it were a statically allocated array. The advantages to allocating memory dynamically are to reduce the size of compiled code and to allocate arrays whose size is not known at compile time. The pointer is used in subsequent procedure calls to refer to the allocated memory. The Mem[] construct is used to access the data. When passed to a procedure, the data are treated simply as an SPP array. Pointers are indices into (one indexed) Fortran arrays. A pointer to an object of one data type will in general have a different value than a pointer to an object of a different data type, even if the objects are stored at the same physical address. Pointers have strict alignment requirements, and it is not always possible to coerce the type of a pointer. For this reason, the pointers returned by malloc() and salloc() are always aligned for all data types, regardless of the data type requested. There are two types of dynamically allocated memory: stack and heap. They are treated identically in terms of dealing with the allocated data, but the mechanics of the allocation differ slightly. malloc and relatives Heap memory is used for arbitrarily large buffers and the resulting pointers may be stored and passed to calling and called procedures. Procedure and Variables Purpose ----------------------------------------------------------------------- malloc (memptr, size, datatype) Allocate heap memory calloc (memptr, size, datatype) Allocate cleared heap memory realloc (memptr, size, datatype) Reallocate memory mfree (memptr, datatype) Free heap memory ----------------------------------------------------------------------- Table 2.5: Heap Memory Allocation Procedures. Many VOS library procedures return a pointer allocated by malloc(), the imio procedures, for example. Be sure to free the memory by using the mfree() procedure. Note that the mfree() procedure in addition to the allocation procedures requires the data type of the allocated memory as an argument. These data types are passed as predefined parameter constants, defined by the system, for example, TY_INT, TY_REAL, etc. Parameter Word Size Data Type ---------------------------------------------------------------------- TY_BOOL SZ_BOOL Boolean TY_CHAR SZ_CHAR Character TY_SHORT SZ_SHORT Short integer TY_INT SZ_INT Integer TY_LONG SZ_LONG Long integer TY_REAL SZ_REAL Single precision real TY_DOUBLE SZ_DOUBLE Double precision real TY_COMPLEX SZ_COMPLEX Complex TY_STRUCT SZ_STRUCT Structure ---------------------------------------------------------------------- Table 2.6: Memory Allocation Parameter Data Types. Memory allocated explicitly with malloc() should be freed after use by mfree(). Pointers allocated implicitly, by immap(), etc., for example, should not be freed explicitly. They will be freed by the appropriate close procedure such as imunmap(). The realloc() procedure changes the size of a previously allocated buffer, copying the contents of the buffer if necessary. This is useful when allocating memory of unspecified size. For example, when reading from STDIN, you might allocate a data buffer initially with some default size. After reading all of the data you may wish to use realloc() to insure that the buffer is only as big as the amount of the data read. Note that realloc() will allocate new memory if the passed pointer is NULL, so it may be used in place of malloc(). This may be useful in a loop in which you need not use malloc() the first time you enter the loop. The only difference between malloc() and calloc() is that the latter sets all of the buffer values to zero, while the former retains the contents of the memory locations, which should be considered garbage. The following example illustrates allocating a block of memory using malloc() and calling a procedure to perform some operation on the values. Example 2.4: Allocating and Using a Memory Block. Note that the dostuff() procedure need not have nested loops if the operation is independent of column or row information. In fact, the vector operator (vops) procedures may be used for any dimensionality of arrays. smark and salloc Stack memory is useful for small buffers local to a procedure. Procedure Call Purpose ------------------------------------------------------------------------- smark (stkptr) Mark memory stack salloc (memptr, size, datatype) Allocate stack memory sfree (stkptr) Free memory stack ------------------------------------------------------------------------- Table 2.7: Stack Memory Procedures. The salloc() procedure allocates stack memory. This is a preallocated block of memory, a chunk of which may be used temporarily by a task. This differs from malloc() which allocates the memory at the time it is called. To use salloc(), a stack pointer must be referenced first using the smark() procedure. This marks the beginning of the block of memory to be referenced. It is not necessary (nor possible) to free the individual memory buffers allocated using salloc(). However, the stack pointer should be reset using sfree() at the end of the procedure. The memory pointer returned by salloc() should not be passed back to a calling procedure but may be passed down to a called procedure. Otherwise stack memory is used identically to heap memory allocated by malloc() or calloc(), see Example 2.5. Example 2.5: Using Stack Memory. Data Structures Dynamic memory is often used in creating and using data structures (see "Macro Definitions" on page 16 and "Data Structures" on page 18 for more details and additional examples). The structure is described by macro define statements declaring the components of the structure. These may be based on dynamically allocated memory, in which case the memory must be allocated before the structure is addressed, and the memory pointer passed as an argument to the structure element. Example 2.6 shows some code that may reside in an include file; it declares a structure consisting of integers and strings. Example 2.6: Declaring a Data Structure. The strings (SPOOL_OUTPUT, for example) are in turn declared using dynamically allocated memory, the pointer being saved in another element of the structure. The elements are addressed with the Mem constructs. To use this structure, the memory must first be allocated using malloc() or calloc() with a data type of TY_STRUCT (see Example 2.7). The first line of the macro provides the number of elements to allocate. Elements of the structure are referenced name, with the pointer to the dynamically allocated memory passed as an argument to the macro. Example 2.7: Using the Memory Structure. There may also be substructures, pointed to by an element of the primary structure. Example 2.8 shows a substructure called from the gio structure defined in lib$gset.h. Example 2.8: Substructures of a Data Structure. Example 2.8 defines a structure for storing polyline attributes. GP_PLAP is a member of the top-level gio structure and PL_LTYPE for example is a member of the polyline substructure. These would be used in code as shown in Example 2.9. Example 2.9: Using the Substructures. A more complicated example (Example 2.10) illustrates a two-dimensional array in a substructure, again from gio. Note the use of two arguments to the macro, referred to as $1 and $2 in the definition. Example 2.11 shows how the two-dimensional in the structure could be used. Note the two arguments to the macro GP_WCSPTR, one of which is itself a symbolic definition, GP_WCS, also part of the data structure. The structure defined in Example 2.10 is a fragment of the gio header file gset.h, included in the source example. Example 2.10: Defining a 2-Dimensional Array in a Structure. Example 2.11: Using the Structure. Accessing Images - imio Procedures in the sf imio library allow an SPP application to read and write IRAF images. IRAF supports several different image formats, including old IRAF, (OIF format), GEIS or STSDAS (STF format) and PROS (QPOE format). However, the same imio procedures are used regardless of the specific format of the image so the formats are transparent to the applications program. The details of decoding the image files are buried in the kernels beneath the applications level of imio. The user specifies the format type when specifying the image names as input or output to the task. The imtype cl environment variable also may be used to specify the default image type. A specific image name extension overrides the value of imtype. The imio interface supports images of up to seven dimensions. In a sense, all images are multidimensional, with the higher, unused axis lengths set to one. An n dimensional image may therefore be accessed by a program coded to operate upon an m dimensional image. Open To access an image, you must first open it using the immap() function. Procedure Call Purpose ------------------------------------------------------------------------ imp = immap (filename, mode, template) Open an image file imunmap (imp) Close an image ------------------------------------------------------------------------ Table 2.8: Image I/O Functions. This returns a pointer type variable that is the address of the image descriptor structure. The immap() function has three arguments. The first argument is the image filename, passed as a string, the second is a mode specifying how to access the image. It is an integer usually passed as a symbolic constant parameter. The access mode argument may be one of the following symbolic parameters: Parameter Access Mode ------------------------------------------------------------------------ READ_ONLY Read only READ_WRITE Read and write WRITE_ONLY Write only NEW_FILE New image NEW_COPY New image, header copied from open image NEW_IMAGE Alias for NEW_FILE ------------------------------------------------------------------------ Table 2.9: Access Mode Parameters. The third argument is the pointer to another image, already opened with another immap() call. It is used only if the access mode is NEW_COPY and specifies a template image. The header of the template image will be copied to the header of the new image, but not the pixel values. That is, the structure of the new output image will be similar to the existing image, but the pixels will be different. imunmap() releases any dynamically allocated memory used for file and I/O buffers. Note that imio refers to images by the header filename, regardless of the format of the image. Therefore, if you do specify an extension on the image filename in a call to immap(), use the header file extension, not the pixel file. Extension Image Format ----------------------------------------- .imh OIF, Old IRAF .hhh STF, STScI GEIS .qp QPOE, PROS ----------------------------------------- Table 2.10: Image Formats. For example, im = immap ("taurus.imh", READ_ONLY, 0) You may omit the extension, in which case imio will interpret the filename as an image header. If there is only one image with the specified root name, then it will open that one, regardless of the image format. If there are two images with the same root but different extensions (different image for- mats), imio will open the one in OIF (IRAF) format. Of course, it is usually up to the user to specify a filename. You need not append an extension unless you wish to force a particular format, or if you wish to use a non-standard extension. If the task creates an image from scratch (using NEW_IMAGE, not copying an existing image) there is an additional way to control the image format. The cl environment variable imtype specifies the image format if there is no extension to the output image filename. Image data are passed from imio procedures to the application via pointers in dynamically allocated memory. These imio procedures comprise families of calls to read and write the pixel data. Each pointer typed function returns a pointer to dynamically allocated memory containing the specified part of the image. Arbitrary Line I/O These procedures read image data one line at a time. They allocate a block of memory containing the pixels and return the memory pointer as the function value. Procedure Call Purpose -------------------------------------------------------------------------- bpt = imgl1T (imp) Get a 1-D image bpt = imgl2T (imp, line) Get a line from a 2-D image bpt = imgl3T (imp, line, band) Get a line from a 3-D image bpt = impl1T (imp) Put a 1-D image bpt = impl2T (imp, line) Put a line to a 2-D image bpt = impl3T (imp, line, band) Put a line to a 3-D image -------------------------------------------------------------------------- Table 2.11: Image Line I/O Functions. All of the above procedures are implemented for the usual SPP numeric data types: short, int, long, real, double, and complex. That is, the procedure name represents the data type of the SPP buffer that holds the image pixels, not necessarily the data type of the image file. The returned pointer type function value is a pointer to memory allocated by memio for the line of pixels from the image. This differs from the image file descriptor (imp above), which is a pointer to a structure containing the attributes of the image as a whole. The pixel data may be passed to another procedure via the Mem[] construct. You need not explicitly deallocate memory allocated by any imio procedure. However, you should call imunmap() for any images opened with immap(). This will flush I/O buffers and free allocated memory. Note that the output (imp...()) procedures as well as the input (img...()) procedures return a pointer to dynamic memory. The pixels are written to the file when the output buffer is full; in some cases, not until the image is closed, or when flushed explicitly. When writing to an output image, your procedure fills the buffer associated with the pointer and then calls the imp...() procedure. Example 2.12 is a simple example of copying one image into another using arbitrary line I/O. Example 2.12: Copying Images Using Arbitrary line I/O. Line by Line I/O Another family of procedures returns a pointer to a line of an image, progressing through adjacent lines with each successive call. These differ from the previous family in that those allow a particular line to be read in random order. These procedures return the next line in order. Procedure Call Purpose ---------------------------------------------------------------- status = imgnlT (im, bufptr, v) Get next image line ---------------------------------------------------------------- Table 2.12: Line by Line I/O. This family of procedures is implemented for the usual SPP numeric data types: short, int, long, real, double, and complex. The functions return the buffer pointer in an argument, bufptr, not in the function value as the previous procedures. These procedures return a completion status as the function value which may be tested for EOF. The argument v is a long array containing indexes of the line to read. This should be initialized to ones. After each call to imgnlT() it is updated to contain the index of the next line. See the example below. This family of procedures is useful for operating on an image line by line, without regard for the absolute size or even the dimensionality of the image. Because of the buffering of image input and output and a certain amount of asynchronous I/O, substantially more efficient code can result. Example 2.13 demonstrates line by line image I/O by copying an image to a new image. Note that the procedure works the same regardless of the dimensionality and data type of the images. Another, more complete example, can be found in Appendix B. Example 2.13: Line by Line Image I/O. General Sections These procedures return a pointer to dynamically allocated memory containing the pixels from an arbitrary section of an image. Note the difference from line-by-line I/O, in which the returned memory always represents a single line of an image, regardless of the dimensionality. These procedures may return a multi-dimensional section. Procedure Call Purpose ------------------------------------------------------------------------------ bpt = imgs1T (imp, x1, x2) Get a section of a 1-D image bpt = imgs2T (imp, x1, x2, y1, y2) Get a section of a 2-D image bpt = imgs3T (imp, x1, x2, y1, y2, z1, z2) Get a section of a 3-D image bpt = imps1T (imp, x1, x2) Put a section of a 1-D image bpt = imps2T (imp, x1, x2, y1, y2) Put a section of a 2-D image bpt = imps3T (imp, x1, x2, y1, y2, z1, z2) Put a section of a 3-D image bpt = imggsT (imp, vs, ve, ndim) Get a general section ------------------------------------------------------------------------------ Table 2.13: Image Section Memory I/O Functions. All of the above procedures are implemented for the usual SPP numeric data types: short, int, long, real, double, and complex. imggsT() differs from the other procedures in that the same arguments may be used for images of any dimension. The vectors vs and ve describe the range of elements in the section. Miscellaneous Procedures There are a few additional procedures providing miscellaneous capabilities. Function Call Purpose --------------------------------------------------------------------------- imflush (imp) Flush the output buffer imaccess (image, acmode) Test availability of image imcopy (input, output) Copy images (does not work on OIF files) imdelete (image) Delete the image imrename (oldname, newname) Rename the image imgsection (imagef, section, maxch) Get the image section field imgimage (imspec, image, maxch) Get the image name imgcluster (imspec, cluster, maxch) Get the cluster name --------------------------------------------------------------------------- Table 2.14: Miscellaneous Image I/O Functions. The last three procedures parse a fully qualified image filename into its components. The terms image, section, and cluster refer to separate fragments of a fully qualified image name. The image section is a string enclosed by square brackets specifying some subraster of an image, for example, [100:125,200:450]. The image name is the filename and group member number (applicable to STF images) without the image section, and the cluster is the filename only. Example 2.14 should clarify this nomenclature. Image sections will be explained in greater detail (See "Image Sections" on page 74.) Example 2.14: Using Image Section Syntax. Note that imacces() tests only whether an image name is valid, not if the image exists. However, if the image includes an image section, then imacces() will test for its existence. Header Parameters Image headers describe the format of an image and permit arbitrary parameters to be carried with the pixel data. The image database interface is the imio interface to the database containing the image headers. The first, fixed format, part of the image header contains the standard fields in binary and is fixed in size. This is followed by the user area, a string buffer containing a sequence of variable length, newline delimited FITS format keyword=value header cards. When an image is opened a large user area is allocated to permit the addition of new parameters without filling up the buffer. When the header is subsequently updated on disk only as much disk space is used as is needed to store the actual header. Images comprise keyword parameters in an image header in addition to the pixel values. These header keywords describe the fundamental properties of the image such as its size and data type. In addition, they represent other pertinent information such as the instrument, date, world coordinate transformation, or any other data thought useful by the originator of the data. See "Standard Fields" on page 72 for an explanation of the standard parameters available for every image. Procedure Call Purpose ---------------------------------------------------------------------------- value = imgetT (imp, keyword) Get a header parameter imgstr (imp, keyword, outstr, maxch) Get a string parameter imputT (imp, keyword, value) Put a header parameter impstr (imp, keyword, value) Put a string parameter imaddT (imp, keyword, default) Add a header parameter imastr (imp, keyword, default) Add a string parameter imaddf (imp, keyword, default) Add a keyword with no value imdelf (imp, keyword) Delete a parameter istat = imaccf (imp, keyword) Test if parameter exists itype = imgftype (imp, keyword) Return datatype of parameter ---------------------------------------------------------------------------- Table 2.15: Image Header Parameter Functions. In each procedure, the name of the parameter is specified as a character string (keyword here), sometimes referred to as a field. The procedures imgetT(), imputT(), and imaddT() are implemented for the SPP data types bool, char, short, int, long, real, and double. The argument imp is a pointer type reference to the image returned by immap(). New parameters will typically be added to the image header with either one of the typed imadd() procedures or with the lower level imaddf() procedure. The former procedures permit the parameter to be created and the value initialized all in one call, while the latter only creates the parameter. In addition, the typed imadd() procedures may be used to update the values of existing parameters, i.e., it is not considered an error if the parameter already exists. The principal limitation of the typed procedures is that they may only be used to add or set parameters of a standard data type. The value of any parameter may be fetched with one of the imgetT() functions. Be careful not to confuse imgets() with imgstr() (or imputs() with impstr()) when fetching or storing the string value of a field. Fully automatic type conversion is provided. Any field may be read or written as a string, and the usual type conversions are permitted for the numeric data types. The imaccf() function may be used to determine whether a field exists. Fields are deleted with imdelf(). It is an error to attempt to delete a nonexistent field. The following example (Example 2.15) illustrates handling of image header parameters. The character string field can take the name of any existing keyword in the image header, e.g., DATE_OBS or i_naxis1. Example 2.15: Handling Image Header Parameters. Procedure Call Purpose ----------------------------------------------------------------------------- list = imofnls (imp, template) Open a sorted file template list = imofnlu (imp, template) Open unsorted file template nchars = imgnfn (list, fieldname, maxch) Get next filename imcfnl (list) Close template ----------------------------------------------------------------------------- Table 2.16: Image File I/O Functions Handling Templates. The field name list procedures imofnl[su](), imgnfn(), and imcfnl() procedures are similar to the fio file template facilities, except that the @file notation is not supported. The template is expanded upon an image header rather than a directory. Unsorted lists are the most useful for image header fields. If sorting is enabled each comma delimited pattern in the template is sorted separately, rather than globally sorting the entire template after expansion. Minimum match is permitted when expanding the template, another difference from file templates. Only actual, full length field names are placed in the output list. Standard Fields The imio database interface, described above, may be used to access any field of the image header, including the standard fields shown in Table 2.17, existing for every image. In addition, there may be other parameters unique to the particular image. Keyword Type Declaration ----------------------------------------------------------------------------- i_ctime long Time of image creation i_history string History string buffer i_limtime long Time when limits (minmax) were last updated i_maxpixval real Maximum pixel value i_minpixval real Minimum pixel value i_mtime long Time of last modify i_naxis int Number of axes (dimensionality) i_naxisN long Length of axis n (i_naxis1, etc.) i_pixfile string Pixel storage filename i_pixtype int Pixel datatype (SPP integer code) i_title string Title string ----------------------------------------------------------------------------- Table 2.17: Standard Header Keywords. The names of the standard fields share an i_ prefix to reduce the possibility of collisions with user field names, to identify the standard fields in sorted listings, to allow use of pattern matching to discriminate between the standard fields and user fields, and so on. The i_ prefix may be omitted provided the resultant name does not match the name of a user parameter. It is however recommended that the full name be used in all applications software. You will need to use the include file when dealing with image headers. This defines macros for standard image header parameters dealing with fundamental characteristics of the image such as the size, data type, etc. Several header parameters are available via the imio structure defined by . Others may be accessed through the imio database procedures. Parameters may be read or written. If a parameter does not exist, it must be created. Example 2.16 is a fragment of code that finds the size of the image, the number of pixels per line and the number of lines. Since the keyword values in Table 2.17 are accessible through the structure, they can be used to get keyword values from an image using the hedit task. Example 2.16: Using Header Parameters. Image Sections A fundamental feature of imio is the capability to treat a subset of an image identically to an entire image. The image filename as passed to immap() may include an image section which specifies what part of the image to read. The image section facility greatly increases the flexibility of the imio interface. Image sections are specified as part of the image name input to immap(), and are not visible to the applications program, which sees a somewhat smaller image, or an image of lesser dimensionality. Some examples are shown below. In addition, see "World Coordinates - mwcs" on page 129 describing the mwcs world coordinate system library. Section Refers to... ---------------------------------------------------------------------------- pix[] The whole image pix[i,j] The single pixel value (scalar) at [i,j] pix[*.*] The whole image, two dimensions pix[*,-*] Flip Y-axis pix[*,*,b] B and B of 3-D image pix[*,*:s] Subsample in Y by S pix[*,1] Line l of image pix[c,*] Column c of image pix[i1:i2,j1:j2] Subraster of image pix[i1:i2:sx,j1:j2:sy] Subraster with sampling ---------------------------------------------------------------------------- Table 2.18: Image Section Syntax. Image Name Templates The filename template package of procedures permits the use of wildcards or nested lists of image filenames. The functionality and calling sequences are similar to those of the fio filename template package (see "Filename Templates" on page 101). An image template is expanded into a list of image names or image sections with imtopen(). The list is not globally sorted, however sublists generated by pattern matching are sorted before appending the sublist to the final list. The number of images or image sections in a list is given by imtlen(). Images are read sequentially from the list with imtgetim(), which returns EOF when the end of the list is reached. The list may be rewound with imtrew(). An image template list should be closed with imtclose() to return the buffers used to store the list and its descriptor. Procedure Call Purpose ---------------------------------------------------------------------------- list = imtopen (template) Open image template nimages = imtlen (list) Return number of images imtrew (list) Rewind template list nchars = imtgetim (list, fname, maxch) Get next image name imtclose (list) Close template ---------------------------------------------------------------------------- Table 2.19: Image Template Functions. Note that the int function imgetim() returns EOF upon attempting to read at the end of file. Otherwise, it returns the number of characters in the image name. Example 2.17 is the top level procedure for the IRAF images.imcopy task in images$imutil/t_imcopy.x. It demonstrates handling image name templates. Some comments have been added to clarify the code. Example 2.17: Handling Image Name Templates. Example 2.17 (Continued): Handling Image Name Templates. Formatted I/O - fmtio SPP includes complete facilities for formatting numeric and text data for input, output, and internal use. printf and its relatives Text and binary numbers formatted as text may be directed to the standard output (STDOUT), the standard error stream (STDERR), a text file, or a string. Note that STDOUT may be redirected to a file or piped to another task in the IRAF cl. Binary values may be formatted via a format specification string. The values to format must be passed in separate procedure calls. The printf() family of procedures performs formatted output. These are similar to the C library procedures except that the values to format are not included in the calling sequence because SPP (Fortran) does not handle variable numbers of calling arguments in a portable manner. Procedure Call Purpose ------------------------------------------------------------------------- printf (format) Formatted print to STDOUT eprintf (format) Formatted print to STDERR fprintf (fd, format) Formatted print to any open file sprintf (outstr, maxch, format) Formatted print to a string buffer clprintf (param, format) Formatted print to a cl parameter pargT (value) Pass a numeric argument to a printf() pargstr (value) Pass string argument to a printf() ------------------------------------------------------------------------- Table 2.20: Formatted Output Functions. The values to format and print are passed via pargT() procedures. There is a separate procedure for each of the SPP data types: bool, char, short, int, long, real, double, and complex. For example, for numerical values, pargr() is used for floating point, pargi() for integer, while pargstr() would be used for strings. Note that the data type specified by the name of the procedure represents the data type of the parameter passed to the format, not the format itself. In general, any SPP data type variable may be formatted by any printf() format specification. Format Codes A format specification is a string that describes how values are to be represented in the output. The string may include any text, but fields may be included to format values. These fields have the form %w.dCn. Any text not preceded by a percent character will be written to the output unchanged. The percent character is a required part of the format field and the remainder of the word specifies the form of the output. w is the field width, d is the number of decimal places or the number of digits of precision, C is the format code, and n is radix character (for format code r only). The w and d fields are optional. The string may be a literal, a string variable, or a predefined parameter constant. Therefore, run-time formats are possible. The format codes C are shown in Table 2.21. Code Format ------------------------------------------------------------------------- b Boolean, true or false (yes or no only on output) c Single character, c or \c or \Onnn d Decimal integer e Exponential, d specifies the precision f Fixed format, d specifies the number of decimal places g General format, d specifies the precision h Sexagesimal, hh:mm:ss.ss, d is the number of decimal places m Minutes, seconds (or hours, minutes), mm:ss.ss o Octal integer rn Convert integer in any radix n s String, d field specifies max chars to print t Advance to column given as field w u Unsigned decimal integer w Output the number of spaces given by field w x Hexadecimal integer z Complex format (r,r), d specifies the precision ------------------------------------------------------------------------- Table 2.21: Output Format Codes. The conventions for the w (field width) specification are as follows: Code Effect --------------------------------------------------------------------- n Right justify in field of n characters, blank fill -n Left justify in field of n characters, blank fill On Zero fill at left, only if right justified absent Use as much space as needed, d field sets precision O Use as much space as needed, d field sets precision --------------------------------------------------------------------- Table 2.22: Field Width Specifications. Escape sequences (e.g., \n for newline) are replaced by the appropriate character value on output: Escape Replacement Character --------------------------------------------------------------------- \b Backspace \f Form feed \n Newline (LF) \r Carriage return \t Tab \" String delimiter character \' Character constant delimiter character \\ Backslash character \nnn Octal value of character %% Insert a percent character in the output ------------------------------------------------------------------- Table 2.23: Escape Sequences. Note that a newline is not automatically written for every printf() call, as with a Fortran WRITE. Use \n in the format text to explicitly write a newline. (See Example 2.18). Example 2.18: Writing a Newline. Additional Output Procedures Substituting eprintf() for printf() would write to the standard error stream STDERR instead of standard output. These two streams are treated separately by the cl. To write to an arbitrary text file, use fprintf(), specifying a file descriptor for an open text file, see Example 2.19. Example 2.19: Writing an Arbitrary Text File. Similarly, formatted text may be written to a text string variable using sprintf(). This is particularly useful for error messages or runtime formats, i.e., generating a format string to use in another printf() call. Note that sprintf() includes an argument specifying the maximum size of the output character string. Example 2.20: Writing Output to a Text String Using sprintf(). Formatted Input - scan, et. al. Formatted input may be read from the standard input stream STDIN, a text file, a string variable, or a cl parameter using the scan family of procedures. Each scan procedure returns an integer status as the function value. This status will contain EOF upon reading end of file. Procedure Call Purpose ------------------------------------------------------------------------- scan () Scan from STDIN stat = fscan (fd) Scan from file opened as fd stat = sscan (str) Scan from the string str stat = clscan (param) Scan from the cl parameter param scanc (ch) Get the next character from a scan reset_scan () Rescan same input ------------------------------------------------------------------------- Table 2.24: Formatted Input Functions. Note that as with the output (printf() family) procedures, variables are not changed by the scan() procedures. Values read are placed in variables using the gargT() family of procedures. Procedure Call Purpose ---------------------------------------------------------------------- gargT (value) Get a typed argument gargstr (outstr, maxch) Get rest of line gargwrd (outstr, maxch) Get next "word" gargrad (lval, radix) Non-decimal gargi() gargtok (tok, outstr, maxch) Get next token ---------------------------------------------------------------------- Table 2.25: Input Functions. There is a separate gargT() procedure for each of the SPP data types: bool, char, short, int, long, real, double, and complex. A word, as recognized by gargwrd(), is any string separated by white space. Example 2.21: Formatting Output. Internal Formatting These procedures convert a string representation of a number into its binary value. They perform the same function as the garg...() procedures, but do I/O internally. That is, they read from a character string variable, not an input stream or file. Each function may be called repeatedly to decode a string of values delimited by white space or embedded in non-numeric characters. Procedure Call Purpose ------------------------------------------------------------------------------ nchar = ctoT (str, ip, value) Convert string to binary (there is no ctos() nchar = cctoc (str, ip, char) char constant to char nchar = gctod (str, ip, dval) Convert any number to double nchar = gctox (str, ip, xval) Convert any number to complex nchar = gctol (str, ip, lval, radix) Variable radix nchar = ctowrd (str, ip, outstr, maxch) Word or string token = ctotok (str, ip, outstr, maxch) Extract token ------------------------------------------------------------------------------- Table 2.26: Internal Formatting Functions. There is a separate ctoT() procedure for each of the SPP numeric data types: int, long, real, double, and complex. All of the procedures except ctotok() return the number of non-white input characters converted as the integer function value. ctotok() returns an integer code identifying the type of token returned. Tokens represent the smallest substrings recognized in the string. The values assigned to the token returned by ctotok() are defined in the include file ctotok.h. While ctowrd() nominally recognizes words separated by white space, any string enclosed in quotes is treated as a single word. The dtoc() format (see Table 2.27) is one of the characters e, f, g, h, or m. See "Format Codes" on page 79 for their meaning. Example 2.22: Using Internal Formatting Functions. Procedure Call Purpose --------------------------------------------------------------------------------- nchar = itoc (ival, outstr, maxch) int to char nchar = ltoc (lval, outstr, maxch) long to char nchar = ctocc (char, outstr, maxch) char to char constant nchar = gltoc (lval, outstr, maxch, radix) Generic long nchar = xtoc (xval, outstr, maxch, decpl, format, width) complex to char nchar = dtoc (dval, outstr, maxch, decpl, format, width) double to char --------------------------------------------------------------------------------- Table 2.27: Conversion Functions. Character and String Functions SPP characters are implemented as integers. Character strings are implemented as fixed length arrays of characters (integers) with the element following the last character set to zero to indicate the end of the string. Therefore they cannot be treated simply as scalar variables in assignment statements. There is a family of procedures for assigning and otherwise manipulating strings. The chr...() family of functions convert a single character (type char) to upper or lower case. The converted character is returned as the function value. Procedure Call Purpose ----------------------------------------------------------------------- ch = chrupr (ch) Change character to upper case ch = chrlwr (ch) Change character to lower case ---------------------------------------------------------------------- Table 2.28: Character Case Conversion Functions. Note that there are macro definitions to accomplish the same purpose. The macro TO_UPPER() converts a single character to upper case and TO_LOWER() converts a character to lower case. However, these assume that the character is already the appropriate case. These macros are defined in . The str...() family of procedures deal with character strings (char arrays). Procedure Call Purpose ------------------------------------------------------------------------------ nchar = gstrcat (str, outstr, maxch) Returns length of output string strcat (str, outstr, maxch) Concatenate str to outstr nchar = gstrcpy (from, to, maxch) Returns length of output string strcpy (from, to, maxch) Copy EOS delim string nchar = strlen (str) Length of string (excluding EOS) strlwr (str) Convert string to lower case strupr (str) Convert string to upper case ------------------------------------------------------------------------------ Table 2.29: Basic String Functions. Note that strlen() returns the number of characters actually occupying the string, not including the EOS character but including any blanks, not the declared size. This is different from the Fortran len function, which returns the declared size of a string, implicitly padded with blanks to the declared size. Procedure Call Purpose ----------------------------------------------------------------------------- index = stridx (char, str) First index of character in string index = stridxs (set, str) Return the index of the first occurrence of any of a set of characters in a string index = strldx (char, str) Last index of character in string index = strldxs (set, str) Return the index of the last occurrence of any of a set of characters in a string ----------------------------------------------------------------------------- Table 2.30: String Index Functions. Note that the argument char in stridx() and strldx() is not a string (a double quoted literal or char array) but an integer representing a single character. If it's a literal, it should be in single quotes. Otherwise, it should be a scalar char variable. Procedure Call Purpose ------------------------------------------------------------------------------ index = strdic (instr, outstr, maxch, dict) Search a dictionary string for a match with an input string nchar = strmac (macro, argstr, outstr, maxch) Expand a macro by string substitution int = strsrt (x, sb, nstr) Sort a list of strings strtbl (fd, buf, strp, nstr, first_col,last_col, maxch, ncol) Print a list of strings. ------------------------------------------------------------------------------ Table 2.31: Complex String Functions. Note that macro expansion in strmac() is not recursive. String Comparisons Procedure Call Purpose ----------------------------------------------------------------------------- index = strcmp (str1, str2) Compare two strings. bool = strOP (s1, s2) Is s1 OP s2? (see below) -1,0,1 = strncmp (s1, s2, n) Counted comparison nextch = strsearch (str, patstr) Fast substring search nextch = strmatch (str, patstr) Match strings using metacharacters nextch = gstrmatch (str, patstr, first, last) Generalized pattern matching bool = streq (str1, str2) s1 == s 2 bool = strne (str1, str2) s1 != s 2 bool = strlt (str1, str2) s1< s 2 bool = strgt (str1, str2) s1> s 2 bool = strle (str1, str2) s1 <= s 2 bool = strge (str1, str2) s1 >= s 2 ----------------------------------------------------------------------------- Table 2.32: String Comparison Functions. The strcmp() procedure returns -n if s1 < s2, 0 if s1 = s2, and +n if s1 > s2. The bool procedure strop() determines whether two strings satisfy a logical operation. The function is selected by replacing op with an operator from the list. For example, to test whether strings are equal, use streq(). Pattern matching characters or metacharacters are defined in the include file : Procedure Metacharacter Purpose --------------------------------------------------------------------------- CH_BOL ^ Beginning of line CH_NOT ^ Not, in character classes CH_EOL $ End of line symbol CH_ANY ? Match any single character CH_CLOSURE * Zero or more occurrences CH_CCL [ Begin character class CH_CCLEND ] End character class CH_RANGE - Range, as in [a-z] CH_ESCAPE \\ Escape character CH_WHITESPACE # Match optional white space CH_IGNORECASE { Begin ignoring case CH_MATCHCASE } Begin checking case --------------------------------------------------------------------------- Table 2.33: Pattern Matching Metacharacters. Evaluating Expressions - evexpr The evexpr() procedure is a function which takes an algebraic expression as input, evaluates the expression, and returns the value of the expression as the function value. Procedure Call Purpose ----------------------------------------------------------------------------- opt = evexpr (expr, getop_epa, ufcn_epa) Evaluate expression ----------------------------------------------------------------------------- Table 2.34: Evaluating Expressions. The input expression is a character string. It is parsed and reduced to a single value. The operands to the expression may be either constants or identifiers (strings). If an identifier is encountered the user supplied get operand procedure is called to return the value of the operand. Operands are described by the operand structure, and operands are passed about by a pointer to such a structure. The value of the expression is returned as a pointer to an operand structure containing the function value. Operands of different data types may be mixed in an expression with the usual automatic type coercion rules. All SPP data types are supported including strings (char arrays). All SPP operators and intrinsic functions are recognized. (See "Intrinsic Functions" on page 35). Output is a pointer to an operand structure containing the computed value of the expression. The output operand structure is dynamically allocated by evexpr() and must be freed explicitly by the user with mfree(). Note that the second and third arguments are the int entry point addresses of procedures. The function locpr() is used to return the address of a function. If there is no function supplied, use NULL for the address. A generic example is: op = evexpr (expr, locpr(getop), locpr(ufcn)) with the user-supplied procedures having the calling sequences shown in Table 2.35: Procedure Call Purpose ------------------------------------------------------------------------ getop (identifier, op) Return named operand's value ufcn (fcn, args, nargs, op) Return named function's value ------------------------------------------------------------------------ Table 2.35: Calling User-Supplied Procedures. If a syntax error occurs while parsing the expression evexpr() will take the error action syntax error. The NULL arguments could be replaced by the locpr() addresses of get operand and/or user function procedures if required by the application. The lexical form of the input expression is the same as that of SPP and the cl for all numeric, character, and string constants and operators. Any other sequence of characters is considered an identifier and will be passed to the user supplied get operand function to be turned into an operand. This procedure requires the include file that defines the operand structure. The operand structure is used to represent all operands in expressions and on the parser stack. Operands are passed to and from the outside world by means of a pointer to an operand structure. The caller is responsible for string storage of string operands passed to evexpr(). evexpr() manages string storage for temporary string operands created during expression evaluation, as well as storage for the final string value if the expression is string valued. In the latter case the value string should be used before evexpr() is called again. Calling Procedure Returned Data Type ------------------------------------------------------------------------------ O_TYPE(op) Operand data type O_VALB(op) Boolean value O_VALI(op) Integer value (or string pointer) O_VALR(op) Real value O_VALC(op) String value ------------------------------------------------------------------------------ Table 2.36: Evaluating Procedure Data Types. The following simple example (Example 2.23) evaluates a constant expression and prints the value on the standard output. An only slightly more complicated example (Example 2.24) uses the procedure get_op() to return an operand value. Example 2.23: Evaluating Data Types. Example 2.24: Returning Operand Value. File I/O - fio File I/O takes place using a stream, that is, an I/O channel available to the SPP program. The standard streams, referred to as STDIN, STDOUT, and STDERR (macros for integer values specifying a stream), are always open. That is, you need not call open() to access them. STDIN and STDOUT read from and write to the user terminal when working interactively but may be redirected or piped. STDERR is for warning or error messages. The fio library permits input from and output to binary or text files. Before any I/O can be done on a file, the file must be opened. The open() procedure may be used to access ordinary files containing either text or binary data. To access a file on one of the special devices such as magnetic tape, a special open procedure must be used. To conserve resources (file descriptors, buffer space) a file should be closed when no longer needed. Any file buffers that may have been created and written into will be flushed before being deallocated. close() ignores any attempts to close STDIN. Attempts to close STDOUT, or STDERR cause the respective output byte stream to be flushed, but are otherwise ignored. An error results if one attempts to close a file that is not open. File I/O functions are listed in Table 2.37; if you are working with binary data, Table 2.42, "Binary File I/O Functions.," on page 98 lists additional functions. Procedure Call Purpose ----------------------------------------------------------------------- fd = open (fname, mode, type) Open or create a text or binary file close (fd) Close a file flush (fd) Flush any buffered output to a file seek (fd, loffset) Set the file offset of the next char to be read or written long = note (fd) Note the position in file for later seek ----------------------------------------------------------------------- Table 2.37: File I/O Functions. The access modes (the mode argument to open()) are: Access Mode Definition ----------------------------------------------------------------------- READ_ONLY Read-only from an existing file WRITE_ONLY Write-only to an existing file READ_WRITE Read from or write to an existing file APPEND Write to the end of an existing file NEW_FILE Create a new file TEMP_FILE Temporary file; delete upon task completion ----------------------------------------------------------------------- Table 2.38: File Access Modes. The file types (the type argument to open()) are: File Type Definition ----------------------------------------------------------------------- TEXT_FILE File of lines of text BINARY_FILE Buffered binary byte stream SPOOL_FILE In-memory "file" ----------------------------------------------------------------------- Table 2.39: File Types. Procedure Call Purpose ----------------------------------------------------------------------- fseti (fd, param, value) Set integer fio options value = fstati (fd, param) Get the value of an integer fio parameter value = fstatl (fd, param) Get value of a long integer fio parameter fstats (fd, param, outstr, maxch) Get a string valued fio parameter stat = finfo (fname, ostruct) Get directory information on a file stat = access (fname, mode, type) Determine the type or accessibility of a file delete (fname) Delete a file rename (old_fname, new_fname) Change the name of a file mktemp (root, fname, maxchars) Make a unique temporary filename falloc (fname, nchars) Preallocate file space stat = protect (fname, action) Protect a file from deletion fcopy (from_fname, to_fname) Copy a file fcopyo (from_fd, to_fd) Copy open files ----------------------------------------------------------------------- Table 2.40: File Manipulation Commands In the above procedures, the common calling sequence variables are declared as follows: Variable Name Contents ----------------------------------------------------------------------- int fd File descriptor char fname[SZ_FNAME] Filename string ----------------------------------------------------------------------- Table 2.41: File Variables. Any file may be accessed after specifying only the filename, access mode, and file type parameters using the open() call. Occasionally, however, it is desirable to change the default file control parameters, to optimize I/O to the file. The fset() procedure is used to set the FIO parameters for a particular file, while fget() is used to inspect the values of these parameters. The special value DEFAULT will restore the default value of the indicated parameter. The procedure seek() is used to move the file pointer (offset in a file at which the next data transfer will occur). With text files, one can only seek to the start of a line, the position of which must have been determined by a prior call to note(). For binary files, seek() merely sets the logical offset within the file. The logical offset is the character offset in the file at which the next I/O transfer will occur. In general, there is no simple relationship between the logical offset and the actual physical offset in the file. Binary File I/O The minimum size addressable SPP data item is a character, usually implemented as a short (two byte) integer. Therefore, in binary file I/O, the size of the buffer is specified in units of chars, or shorts. It is possible to pack bit and byte data into chars. See the osb procedures described in "Bit & Byte Operations - osb" on page 123. Procedure call Purpose ----------------------------------------------------------------------- stat = read (fd, buffer, nch) Read a binary block of data from a file write (fd, buffer, nch) Write a binary block of data to a file ----------------------------------------------------------------------- Table 2.42: Binary File I/O Functions. The read() procedure reads a maximum of nch characters from the file with descriptor fd into the user supplied memory buffer. The following example (Example 2.25) illustrates reading a binary file and extracting values. This is a straightforward example because all of the desired values are short integers at the beginning of the file. Example 2.25: Reading Values From a Binary File. The next slightly more complicated example () demonstrates extracting individual bytes from a binary file. The fragment of code reads a single word consisting of four bytes and assigns the individual byte values to separate short integers using the osb bytmov() procedure. Example 2.26: Extracting Bytes From a Binary File. Text Character I/O The procedures getc() and putc() read and write character data, a single character at a time. Procedure Call Purpose ----------------------------------------------------------------------- stat = getc (fd, char) Get a char from a file putc (fd, char) Put char to a file putcc (fd, char) Handles unprintable characters stat = getchar (char) Get char from STDIN putchar (char) Put char to STDOUT stat = getline (fd, linebuf) Get a line of text stat = getlline (fd, linebuf, maxch) Get a line of text putline (fd, linebuf) Output a string to fd ----------------------------------------------------------------------- Table 2.43: Text Character I/O Operations. Note that getchar() and putchar() deal with STDIN and STDOUT respectively so they don't require a file descriptor. The other procedures require a previous call to open() or may specify one of the standard streams STDIN, STDOUT, or STDERR. The newline character is returned as part of a line read by getline(). The maximum size of a line (size of a line buffer) is set at compile time by the system wide constant SZ_LINE. getline() reads at most SZ_LINE characters. To read more in one call, use getlline() which includes an argument specifying how many characters to read. Pushback Characters and strings (and even binary data) may be pushed back into the input stream. ungetc() pushes a single character. Subsequent calls to getc(), getline(), read(), etc. will read out the characters in the order in which they were pushed (first in, first out). When all of the pushback data have been read, reading resumes at the preceding file position, which may either be in one of the primary buffers, or an earlier state in the pushback buffer. Procedure Call Purpose ----------------------------------------------------------------------- ungetc (fd, char) Push back a char ungetline (fd, string) Push back a string unread (fd, buf, nchars) Push back binary data ----------------------------------------------------------------------- Table 2.44: Pushback Text Functions. ungets() differs from ungetc() in that it pushes back whole strings, in a last in, first out fashion. ungets() is used to implement recursive macro expansions. The amount of recursion permitted may be specified after the file is opened, and before any data are pushed back. Recursion is limited by the size of the input pointer stack, and pushback capacity by the size of the pushback buffer. Filename Templates The filename template package contains routines to expand a filename template string into a list of filenames, and to access the individual elements of the list. It is primarily a convenience for users to allow wildcards in filenames and pointers to files containing lists of names. The template is a list of filenames, patterns, or list filenames. The concatenation operator (//) may be used within input list elements to form new output filenames. String substitution may also be used to form new filenames. A sample template string is: alpha, *.x, data* // .pix, [a-m]*, @list_file This template would be expanded as the file alpha, followed in successive calls by all the files in the current directory whose names end in .x, followed by all files whose names begin with data with the extension .pix appended, and so on. The @ character signifies a list file. That is, a file containing regular filenames. String substitution uses the first string given for the template, expands the template, and for each filename generated by the template, substitutes the second string to generate a new filename. Some examples follow. Sample String Performs Function ----------------------------------------------------------------------- *.%x%y Change the extension to y *%%_abc%.imh Append _abc to root nite%1%2%.1024.imh Change nite1 to nite2 ----------------------------------------------------------------------- Table 2.45: String Substitution Characters. The following procedures (with a b suffix) are the highest level and most convenient to use. Procedure Call Purpose ----------------------------------------------------------------------- fntopnb (template, sort) Expand template and open a buffered filename list status = fntgfnb (list, fname, maxch) Get next filename from buffered list (sequential) status = fntrfnb (list, index, fname, maxch) Get next filename from buffered list (random) fntclsb (list) Close buffered list num = fntlenb (list) Get number of filenames in a buffered list fntrewb (list) Rewind the list ----------------------------------------------------------------------- Table 2.46: High-Level Template Functions. The remaining lower level routines expand a template on the fly and do not permit sorting or determination of the length of the list. Procedure Call Purpose ----------------------------------------------------------------------- fntopn (template) Open an unbuffered filename list fntgfn (pp, outstr, maxch) Get next filename from unbuffered list fntcls (pp) Close unbuffered list ----------------------------------------------------------------------- Table 2.47: Low-Level Template Routines. Vector (Array) Operators - vops The vector operator (vops) procedures implement common operators for arrays of most supported SPP data types. They are host-specific in the sense that they may take advantage of specialized hardware and software available on a particular system such as vector processors and vectorizing compilers. This would substantially improve the performance of computationally intensive tasks dealing with large arrays such as images. Nevertheless, the interface to SPP (the calling sequence) is independent of the underlying architecture. Each section below describes a family of vops operators related by functionality. Each operator (procedure) is implemented with the same root name and calling sequence for several data types. However, not all operators are implemented (nor do they make sense) for every data type. The tables list the root procedure name, implemented data types, calling sequence, and description of the operation. All of the functions require an int argument that specifies the number of elements in the passed vector or vectors. If the procedure requires more than one vector, they are assumed to have the same number of elements. In nearly every case, multiple array arguments to vops procedures are also the same data type. A significant exception is achtTT(), which converts a vector of one data type to another vector of a different data type. All vector operations may be performed in place. That is, the same array may be used on input as well as output. An array passed to a vector procedure need not be one-dimensional. In all cases, the vectors are treated simply as contiguous words. Since there is assumed to be no functional relationship among the pixel positions in the vectors, arrays of any dimensionality may be passed. Only the total number of pixels in the array need be passed to the vops procedure. Many procedures are implemented for the case of two vectors or a vector and a scalar. In the latter case, the procedure name has a k inserted before the last character (the initial of the data type) and one argument must be a constant or scalar variable. Arithmetic Operators These procedures implement basic arithmetic operations. The binary operators (add, subtract, multiply, and divide) include operations between two vectors or between a vector and a scalar. In the former case, each element of the output vector is the result of the operation on the corresponding elements of the input vectors. In the second case, each element of the output vector represents the result of the operation between the corresponding element of the input vector and the same scalar. Procedure Call Purpose ----------------------------------------------------------------------- anegT (a, b, npix) Negate a vector aaddT (a, b, c, npix) Add two vectors aaddkT (a, k, c, npix) Add a vector and a scalar asubT (a, b, c, npix) Subtract two vectors asubkT (a, k, c, npix) Subtract a scalar from a vector amulT (a, b, c, npix) Multiply two vectors amulkT (a, k, c, npix) Multiply a vector and a scalar adivT (a, b, c, npix) Divide two vectors adivkT (a, k, c, npix) Divide a vector by a scalar advzT (a, b, c, npix, errfcn) Vector divide, detect divide by zero ----------------------------------------------------------------------- Table 2.48: Arithmetic Functions. Each of these procedures is implemented for the following data types: short, int, long, real, double, and complex. To use the appropriate data type, replace T with the representative of the data type name, amulr() or aaddki(), for example. Most of these are the first character of the data type, except for complex, whose representative character is x. The last procedure, advzT(), implements dividing vectors, but upon dividing by zero it calls errfcn(), supplied by the application as an external function. Bitwise Boolean operators These procedures perform boolean operations on integer arrays, returning the same type result. The resulting vector is the result of the boolean operation on each bit of each element of the arrays. Procedure Call Purpose ----------------------------------------------------------------------- anotT (a, b, npiix) NOT of a vector aandT (a, b, c, npix) AND of two vectors aandkT (a, b, c, npix) AND of a vector and a scalar aborT (a, b, c, npix) OR of two vectors aborkT (a, b, c, npix) OR of a vector and a scalar axorT (a, b, c, npix) XOR (exclusive or) of two vectors axorkT (a, b, c, npix) XOR of a vector and a scalar ----------------------------------------------------------------------- Table 2.49: Bitwise Boolean Operators. All of the above procedures are implemented only for the integer data types: short, int, and long. Logical Comparison These procedures return an int array containing the result of the logical comparison between elements of the input vectors. If the result of the comparison is true, the value in the vector is one, otherwise, it is zero. Procedure Call Purpose ----------------------------------------------------------------------- abeqT (a, b, c, npix) abeqkT (a, k, c, npix) abgeT (a, b, c, npix) abgekT (a, k, c, npix) abgtT (a, b, c, npix) abgtkT (a, k, c, npix) ableT (a, b, c, npix) ablekT (a, k, c, npix) abltT (a, b, c, npix) abltkT (a, k, c, npix) abneT (a, b, c, npix) abnekT (a, k, c, npix) ----------------------------------------------------------------------- Table 2.50: Logical Comparison Functions. All of the above are implemented for the range of SPP data types: char, short, int, long, real, double, and complex. Note, however, that the output vector, c is always an int array. Fundamental Array Operators These procedures implement various basic array operations. The achtTT() procedure is unique in that the input and output vectors are of different data types. It requires two data type specifiers (t) for the input and output vectors. Function Data Type Parameters Purpose ----------------------------------------------------------------------- amovT csilrdx (a, b, npix) Move (copy or shit) a vector amovkT csilrdx (k, b, npix) Move a scalar into a vector aclrT bcsilrdx (a, npix) Clear (zero) a vector achtTT ubcsilrdx (a, b, npix) Change datatype of a vector ----------------------------------------------------------------------- Table 2.51: Fundamental Array Operators. All of the above are implemented for the full range of SPP data types: char, short, int, long, real, double, and complex. In addition, achTT() is implemented for unsigned byte b and unsigned short u types. These are used primarily in low-level image I/O (imio) code. aclrT() is also implemented for byte. Algebraic Operators These procedures implement various functions. The log and square root functions include an external function passed to the procedure that sets the returned value in the case of an invalid function result such as -1. Procedure Call Definition ----------------------------------------------------------------------- aabsT (a, b, npix) Absolute value bi = |ai| amodT (a, b, c, npix) Modulus of two vectors amodkT (a, k, c, npix) Modulus of a vector and a scalar apowT (a, b, c, npix) Vector to an integer vector power apowkT (a, k, c, npix) Vector to an integer scalar power aexpTt (a, b, c, npix) Vector to a real vector exponent aexpkT (a, k, c, npix) Vector to a real scalar exponent arcpT (a, k, c, npix) Reciprocal of a scalar and a vector arczT (a, k, c, npix, errfcn) Reciprocal, detect divide by zero allnT (a, b, npix, errfcn) Natural logarithm alogT (a, b, npix, errfcn) Common logarithm asqrT (a, b, npix, errfcn) Square root amagT (a, b, c, npix) Magnitude of vectors amgsT (a, b, c, npix) Magnitude squared of vectors ----------------------------------------------------------------------- Table 2.52: Algebraic Operators. All of these procedures are implemented for the data types: short, int, long, real, double, and complex, except the modulus functions amodT() and amodkT(), which are not implemented for complex. Complex Operators These procedures involve complex operators, but involve not only complex arguments. Procedure Data Type Arguments Function ----------------------------------------------------------------------- acjgT x (a, b, npix) Complex conjugate of a complex vector aimgT silrd (a, b, npix) Imaginary part of a complex vector aupxT silrdx (a, b, c, npix) Unpack the real and imaginary parts of a complex vector apkxT silrds (a, b, c, npix) Pack a complex vector given the real and imaginary parts ----------------------------------------------------------------------- Table 2.53: Complex Operators. acjgT() is implemented only for complex arrays. The first argument to aimgT() and aupxT() must be a complex array. The last argument to aupxT() must be a complex array. Fourier Transforms Procedure Arguments Transform Type ----------------------------------------------------------------------- afftrr (sr, si, fr, fi, npix) Forward real Fourier transform, real arrays afftrx (a, b, npix) Forward real Fourier transform, complex output afftxr (sr, si, fr, fi, npix) Forward complex Fourier transform, real arrays afftxx (a, b, npix) Forward complex Fourier transform, complex arrays aiftrr (sr, si, fr, fi, npix) Inverse real Fourier transform, real arrays aiftrx (a, b, npix) Inverse real Fourier transform, complex output aiftxr (sr, si, fr, fi, npix) Inverse complex Fourier transform, real arrays aiftxx (a, b, npix) Inverse complex Fourier transform, complex arrays ----------------------------------------------------------------------- Table 2.54: Fourier Transforms. The transform may be performed in place. The size of the arrays must be a power of two. Transformations Function Data Types Parameters Purpose ----------------------------------------------------------------------- agltT csilrdx (a, b, npix, low,high, General piecewise linear kmul, kadd, nrange) transformation altrT silrdx (a, b, npix, k1, k2, Linear transformation of a vector k3) altaT silrdx (a, b, npix, k1, k2) Linear map vector to vector altmT silrdx (a, b, npix, k1, k2) Linear map vector to vector amapT silrd (, b, npix, a1, a2, b1, b2) Linear mapping of a vector with clipping aluiT silrd (a, b, x, npix) Vector lookup and interpolate (linear) alutT csil (a, b, nchar, lut) Vector transform via lookup table ----------------------------------------------------------------------- Table 2.55: Transformations. Miscellaneous Procedures Function Data Type Parameters Purpose ----------------------------------------------------------------------- aminT csilrdx (a, b, c, npix) Vector minimum of two vectors aminkT csilrdx (a, b, c, npix) Vector minimum of a vector and a scalar amaxT csilrdx (a, b, c, npix) Vector maximum of two vectors amaxkT csilrdx (a, b, c, npix) Vector maximum of a vector and a scalar amed3T csilrd (a, b, c, med, npix) Vector median of three vectors amed4T csilrd (a, b, c, d, med, npix) Vector median of four vectors amed5T csilrd (a, b, c, d, e, med, npix) Vector median of five vectors arltT silrdx (a, npix, floor, newval) Vector replace pixel if < scalar argtT silrdx (a, npix, ceil newval) Vector replace pixel if > scalar aselT csilrdx (a, b, c, sel, npix) Vector select from two vectors based on boolean flag vector asokT csilrdx (a, npix, ksel) Selection of the kth smallest element of a vector acnvT silrd (a, b, npix, kernel, kpix) Convolve two vectors acnvrT silrd (a, b, npix, kernel, kpix) Convolve a vector with a real kernel asrtT csilrdx (a, b, npix) Sort a vector in increasing order abavT silrdx (a, b, nblocks, npix_block) Block average a vector absuT silrd (a, b, nblocks, npix_block) Block sum a vector awsuT silrdx (a, b, c, npix, k1, k2) Weighted sum of two vectors ahgmT csilrd (a, npix, hgm, nbins, z1, z2) Accumulate the histogram of a series of vectors ----------------------------------------------------------------------- Table 2.56: Miscellaneous Procedures. Scalar Results These procedures return a scalar value from computation upon a vector. In most cases, the data type of the function, vector or vectors, and the returned value must match. Exceptions are aravt() and awvgt(), in which the returned value is the number of points remaining in the sample after rejection. Procedure Call Data Types Parameters Purpose ----------------------------------------------------------------------- hival = ahivT csilrdx (a, npix) Compute the high (max) value of a vector loval = alovT csilrdx (a, npix) Compute the low (min) value of a vector alimT csilrdx (a, npix, minval, maxval) Compute the limits (min and max) of a vector dot = adotT silrdx (a, b, npix) Dot product of two vectors aavgT silrdx (a, npix, mean, sigma) Mean and standard deviation of a vector ngpix = aravT silrdx (a, npix, mean, sigma, ksig) Mean and standard deviation of a vector with pixel rejection (mean and sigma are floating point) ngpix = awvgT silrdx (a, npix, mean, sigma, lcut, hcut) Mean and standard deviation of a windowed vector (mean, sigma, lcut and hcut are floating point) med = amedT csilrdx (a, npix) Median value of a vector ssqrs = assqT silrdx (a, npix) Sum of squares of a vector (returns floating point results) sum = asumT silrdx (a, npix) Sum of a vector (returns floating point results) y = apolT rd (x, coeff, ncoeff) Polynomial evaluation ----------------------------------------------------------------------- Table 2.57: Scalar Results. Vector Graphics - gio The gio package allows an IRAF application written in SPP to draw graphics without regard to the ultimate plotting device. There is a complete description in the document Graphics I/O Design [Tody84b] available using the help command in the cl: help gio$doc/gio.hlp fi+. Here we primarily list the procedures, their calling sequences and a brief description of their function. The gio library allows a task to draw graphics with relatively little regard for specific graphics hardware. Nevertheless, some features are rather dependent on particular device characteristics. High-Level Plotting Procedures There are two procedures that allow an application to simply draw a graph using a set of data. Procedure Call Purpose ----------------------------------------------------------------------- gplotv (v, npts, x1, x2, title) Complete plot gploto (gp, v, npts, x1, x2, title) Plot a vector ----------------------------------------------------------------------- Table 2.58: Graph Drawing Functions. gplotv is completely self-contained. The application simply passes an array of real values in the argument v and the number of elements in the array in npts. The arguments x1 and x2 may be used to specify the X-axis values to assign to the first and last elements of the data vector v. Finally, the argument title is a character string plotted at the top of the graph. This may be specified as EOS, a null string, in which case no title is plotted. Note that gplotv() does not require the graphics descriptor argument (gp here). Opening and closing graphics are done entirely within the procedure. On the other hand, gploto() does require the descriptor. That is, the graphics must have been opened by gopen() (see below). All other gio procedures require the graphics descriptor argument. gploto() therefore permits more flexibility in resetting default plotting parameters. Setup These procedures enable graphics to be written to a particular device and control such operations as clearing the device (starting a new frame or page). Procedure Call Purpose ----------------------------------------------------------------------- gp = gopen (device, mode, fd) Open graphics gclose (gp) Close graphics gdeactivate (gp, flags) Deactivate graphics workstation greactivate (gp, flags) Activate graphics workstation gcancel (gp) Discard buffered graphics output gflush (gp) Flush buffered graphics output gclear (gp) Clear and reset the workstation gframe (gp) Advance the frame greset (gp, f) Reset graphics state gmftitle (gp, metafile_title) Comment metacode gpagefile (gp, fname, prompt) Page a file ----------------------------------------------------------------------- Table 2.59: Graphics Device Setup Functions. Note the distinction between the arguments to gopen(). The first is a string specifying the device on which to plot. This is most often coded using a string assigned from a cl parameter to be assigned by the user. The second argument is the gio I/O mode, analogous to the fio I/O modes. This is usually coded using a parameter constant. NEW_FILE will initialize graphics, erasing the screen or starting a new page while APPEND will not initialize graphics but will use the scaling and other parameters from the most recent graph (as long as the graphics buffer was not flushed). The final parameter is the graphics stream to use for the graphics metacode out- put. There are three streams specified using defined parameter constants: STDGRAPH, STDPLOT, and STDIMAGE. The streams behave identically but are resolved separately in disposing of the final plot. Example 2.27 briefly demonstrates the most common way of opening graphics: Example 2.27: Opening Graphics. Graphics Parameters There are a number of internal gio parameters that can be set in an SPP task. These control such aspects of the plot such as line width and text format. The system include file must be included to allow reading or writing these parameters. It is also possible to query, but not set, certain attributes of the specified graphics device. Procedure Call Purpose ----------------------------------------------------------------------- gsetT (gp, param, value) Set graphics parameter val = gstaT (gp, param) Query numeric graphics parameter nchar = gstats (gp, param, outstr, maxch) Query string graphics parameter val = ggetT (gp, devcap) Query numeric device parameter nchar = ggets (gp, devcap, outstr, maxch) Query string device parameter ----------------------------------------------------------------------- Table 2.60: Graphics Parameter Control Functions. Use gsetT() to set the value of a parameter and gstatT() to inquire its value. Note the distinction between these procedures and the ggetT() procedures to query device characteristics from the graphics capabilities (graphcap) file. gsetT() is implemented for int, real, and string data types, gstatT() is implemented for int, and real data types, and ggetT() is implemented for bool, int, and real data types. Scaling These procedures deal with plot scaling. There are two fundamental coordinate systems used by gio: normalized device coordinates or NDC, whose range is always 0:1 in both directions regardless of the device, and the world coordinate system or WCS, defined by the application and corresponding to the user's data coordinates. Procedure Call Purpose ----------------------------------------------------------------------- gsview (gp, x1, x2, y1, y2) Set NDC viewport ggview (gp, x1, x2, y1, y2) Get NDC viewport gswind (gp, x1, x2, y1, y2) Set WCS window ggwind (gp, x1, s2, y1, y2) Get WCS window gascale (gp, v, npts, axis) Set absolute WCS scale grscale (gp, v, npts, axis) Set relative WCS scale ggscale (gp, x, y, dx, dy) Get WCS scale gctran (gp, x1, y1, x2, y2, wcs1, wcs2) Transform coordinates gcurpos (gp, x, y) Get current pen position ----------------------------------------------------------------------- Table 2.61: Plot Scaling Functions. NDC is associated with WCS using gsview() and gswind() to establish the plot scale. This may also be accomplished for a given set of data using gascale() or grscale(). Drawing The usual graphics primitives are available in gio such as basic pen moves and draws, line, marker, polyline, polymarker, and text drawing. The coordinates in every case are assumed to be in world coordinates (WC). Procedure Call Purpose ----------------------------------------------------------------------- gamove (gp, x, y) Pen up move in absolute WC grmove (gp, x, y) Pen up move in relative WC gadraw (gp, x, y) Pen down move in absolute WC grdraw (gp, x, y) Pen down draw in relative WC ---------------------------------------------------------------------- Table 2.62: Pen Movement Primitives. Move and draw may be absolute or relative to the last pen position. Procedure Call Purpose ---------------------------------------------------------------------- gline (gp, x1, y1, x2, y2) Draw a line gpline (gp, x, y, npts) Draw a polyline gvline (gp, v, npts, x1, x2) Vector a polyline gtext (gp, x, y, text, format) Draw text gfill (gp, x, y, npts, style) Area fill glabax (gp, title, xlabel, ylabel) Draw labeled axes gmark (gp, x, y, marktype, xsize, ysize) Draw a marker gpmark (gp, x, y, npts, marktype, xsize, ysize) Draw a polymarker gvmark (gp, v, npts, x1, x2, marktype, xsize, ysize) Vector a polymarker gumark (gp, x, y, npts, xcen, ycen, xsize, ysize, fill) User defined marker ----------------------------------------------------------------------- Table 2.63: Drawing Primitives. gpline() and gpmark() take two vectors, with the X and Y coordinates of each point, while gvline() and gvmark() take a single vector of Y coordinates, and the X coordinates are evenly distributed along the X-axis, ranging from x1 at v[1] to x2 at v[npts] in WCS coordinates. Procedure Call Purpose ----------------------------------------------------------------------- gpcell (gp, m, nx, ny, x1, y1, x2, y2) Draw a cell array ggcell (gp, m, nx, ny, x1, y1, x2, y2) Read a cell array ----------------------------------------------------------------------- Table 2.64: Cell Array Primitives. A cell array is a gray-scale image. It is up to the graphics kernels (device drivers) to support capabilities such as drawing cell arrays or filled polygons. Most of the kernels do not support these. Cursor Interaction IRAF supports cursor read back through the cl so that a task may query the cursor. See "Interactive Graphics Cursor" on page 51 for a slightly more complete description of cursor interaction. Procedure Call Purpose ----------------------------------------------------------------------- gscur (gp, x, y) Move device cursor stat = ggcur (gp, x, y, key) Get cursor position clgcur (param, wx, wy, wcs, key, strval, maxch Graphics cursor ----------------------------------------------------------------------- Table 2.65: Cursor Interaction Functions. Note that clgcur() is a clio procedure, not a gio procedure. Therefore, it does not require the graphics descriptor argument. Not all devices support moving the cursor from host software so gscur() may not have any effect. Terminal I/O - tty The tty interface is a table driven, device independent interface for controlling terminal and printer devices. Devices are described either by environment definitions, or by an entry in the tty database file. The tty database file is the standard Berkeley Unix termcap terminal capability database file (a text file), to which have been added entries for local printer devices. Accessing the Unix termcap file directly without modification is sometimes awkward, but the benefits of accessing a widely used, standard database more than compensate for any clumsiness. When the cl starts up, the following environment variables are defined to describe the default terminal and printer devices. The user may subsequently change the values of these variables with the set statement or with the stty program. Variable Contents ----------------------------------------------------------------------- printer Default printer (e.g., versatec) terminal Default terminal (e.g., vt100, tek4012) termcap Terminal or printer database filename ttybaud Baud rate, default 9600 ttyncols Number of characters per line ttynlines Number of lines per screen ----------------------------------------------------------------------- Table 2.66: TTY Environment Variables. The variables defining the names of the default terminal and printer devices will normally correspond to the names of device entries in the termcap file. The name of a file containing a single termcap entry for the device may optionally be given; the filename must contain a virtual filename (VFN) or operating system filename (OSFN) directory prefix to be recognized as a filename. The default termcap file is dev$termcap. Terminal initialization files (used to set tab stops) are files of the form dev$tty.tbi, where tty is the last field of the Unix pathname in the if termcap entry. If the first character of the if filename string is not a /, an IRAF VFN should be given. The value strings for the environment variables ttyncols and ttynlines, defining the screen dimensions, are extracted from the termcap file by the stty program during start-up. The screen dimensions are defined in the environment for two reasons: efficiency, and if a window is used, the logical screen dimensions may be less than the physical screen dimensions. Most applications programs should therefore use envgeti() rather than ttygeti() to get the screen dimensions. ttygeti() returns the physical screen dimensions as given in the termcap file. Open and Close Before any tty control sequences can be output, the tty device descriptor must be read from the termcap file into a buffer for efficient access. ttyodes() is used to open the tty descriptor; ttycdes() should be called when done to close the descriptor, returning all buffer space used. If ttyname is terminal or printer, the descriptor for the default terminal or printer is accessed. Procedure Call Purpose ----------------------------------------------------------------------- tty = ttyodes (ttyname) Open tty descriptor ttycdes (tty) Close tty ----------------------------------------------------------------------- Table 2.67: TTY Open and Close Functions. Low Level Database Access, TTY Control The ttyget() procedures are used to get capabilities from the database entry. If the named capability is not found, ttygeti() returns zero, ttygetb() returns false, and ttygets() returns the null string. ttysubi() performs argument substitution on a control sequence containing at most two integer arguments (such as a cursor motion control sequence), generating an output sequence suitable for input to ttyputs(). ttyputs() puts the control sequence to the output file, padding as required given the number of affected lines. The baud rate and pad character, used to generate padding, are evaluated at ttyodes() time and are conveyed to ttyputs() in the tty descriptor. Procedure Call Purpose ----------------------------------------------------------------------- value = ttygett (tty, cap) Get a numeric parameter nchars = ttygets (tty, cap, outstr, maxch) Get a string parameter ttyputs (fd, tty, ctrlstr, afflncnt) Put a string parameter ttysub (ctrlstr, outstr, maxch, arg1, arg2) ----------------------------------------------------------------------- Table 2.68: Low-Level TTY Database Functions. ttygett() is implemented for int, real, and bool data types. High-Level Control Procedure Call Purpose ----------------------------------------------------------------------- stat = ttyctrl (fd, tty, cap, afflncnt) Output a control sequence ttyso (fd, tty, YES|NO) Turn standout mode on or off ttygoto (fd, tty, col, line) Move cursor absolute ttyinit (fd, tty) Send :is and :if, if defined ttyclear (fd, tty) Clear screen ttyclearln (fd, tty) Clear the current line ttyputline (fd, tty, textline, map_cc) Put a text line ----------------------------------------------------------------------- Table 2.69: High-Level TTY Functions. ttyctrl() calls ttygets() and ttyputs() to process and output a control sequence (slightly less efficiently than if the control string is buffered by the user code). ttygoto() moves the cursor to the desired column and line. ttyputline() is like the fio putline(), except that it processes any form feeds, standout mode directives, and other control characters (including tabs) embedded in the text. Lines longer than ttyncols are broken into several output lines. ttyputline() is used by the help, page, type, and lprint utilities to map tabs and standout mode directives for a particular output device. Standout mode is mapped as reverse video on most VDTs, and as underscore on most printers and on overstrike terminals such as the Tektronix 4012. 2.9 Bit & Byte Operations - osb Byte and Character Conversions Procedure Call Purpose ----------------------------------------------------------------------- strpak (str, os_sttr, maxch) Pack OS string strupk (os_str, str, maxch) Unpack OS string chrpak (a, a_off, b, b_off, nchars) Pack char chrupk (a, a_off, b, b_off, nchars) Unpack char bitpak (ival, wordp, offset, nbits) Pack an integer into a bitfield bitupk (wordp, offset, nbits) Unpack an unsigned integer bit field bitmov (a, a_off, b, b_off, nbits) Move a sequence of bits bytmov (a, a_off, b, b_off, nbytes) Move bytes bswaps (a, b, nshorts) Byte swap short bswap1 (a, b, nlongs) Byte swap long ----------------------------------------------------------------------- Table 2.70: Byte and Character Conversions. chars are signed integers, whereas bytes as unsigned integers. The bswapT() routines are used to swap bytes in short and long integer arrays, as is sometimes required when transporting data between machines. The mii package is available for conversions between a machine indepen- dent integer format and the SPP data types (documented elsewhere). See "Binary File I/O" on page 98 for an example of extracting individual bytes from a word. Character Comparisons The following are macro functions defined in the system include file ctype.h. The statement include must be in the code in order to use them. Procedure Call Purpose ----------------------------------------------------------------------- bool = IS_UPPER (char) Upper case? bool = IS_LOWER (char) Lower case? bool = IS_DIGIT (char) Numeral? bool = IS_PRINT (char) Printable character? bool = IS_CNTRL (char) Control Character? bool = IS_ASCII (char) 7-bit ASCII character? bool = IS_ALPHA (char) Letter (either case)? bool = IS_ALNUM (char) Alphanumeric character? bool = IS_WHITE (char) White space character? char = TO_DIGIT (char) Convert integer to char int = TO_INTEG (char) Convert digit to integer char = TO_UPPER (char) Convert to upper case char = TO_LOWER (char) Convert to lower case ----------------------------------------------------------------------- Table 2.71: Character Comparison Functions. These are macro definitions, not procedures (they produce in-line code and need not be declared). TO_UPPER() and TO_LOWER() must only be applied to letters of the proper case (use the procedures chrupr(), chrlwr() otherwise). Pack and Unpack Characters These procedures convert between SPP character strings (short int arrays) and packed byte blocks, i.e., a sequence of characters stored one per byte, delimited by EOS (ASCII NUL). The conversion may be performed in-place. That is, the input and output arrays may be the same. Procedure Call Purpose ----------------------------------------------------------------------- strpak (instr, outstr, maxch) Pack an SPP string into bytes strupk (instr, outstr, maxch) Unpack an SPP string from bytes chrpak (a, aoff, b, boff, nchars) Pack chars into bytes chrupk (a, aoff, b, boff, nchars) Unpack chars from bytes ----------------------------------------------------------------------- Table 2.72: Pack and Unpack Functions. Fortran Strings There are two procedures that convert between SPP and Fortran character strings: f77pak() converts an SPP string to a Fortran string and f77upk() converts a Fortran string to an SPP string. An example is shown in Example 2.28. Procedure Call Purpose ----------------------------------------------------------------------- f77pak (spp, f77, maxch) Convert SPP string to Fortran string f77upk (F77, spp, maxch) Convert Fortran string to SPP string ----------------------------------------------------------------------- Table 2.73: SPP/Fortran String Conversion. Example 2.28: Converting Fortran/SPP Strings. Note the escaped Fortran statement, preceded by %. See also "Fortran statements" on page 7. Machine Independent I/O - mii The mii integer format provides for three machine independent integer data types and two IEEE floating point formats. Data Type Type of Number ----------------------------------------------------------------------- MII_BYTE 8-bit unsigned byte MII_SHORT 16-bit twos-complement signed integer MII_LONG 32-bit twos-complement signed integer MII_REAL 32-bit IEEE floating point MII_DOUBLE 64-bit IEEE floating point ----------------------------------------------------------------------- Table 2.74: Machine-Independent Integer Data Types. These types are defined in the system include file mii.h which must be included if using mii. The mii data types are the same as are used in the FITS transportable image format. In the case of the short and long integers, the most significant bytes of an integer are given first. The routines in this package are provided for converting to and from the mii format and the SPP format. The latter format, of course, is potentially quite machine dependent. The implementation given here assumes that the SPP data types include 16-bit and 32-bit twos-complement integers; the ordering of the bytes within these integer formats is described by the machine constants BYTE_SWAP2 and BYTE_SWAP4. Byte swapping for the IEEE floating formats is defined by the machine constants IEEE_SWAP4 and IEEE_SWAP8. Procedure Call Purpose ----------------------------------------------------------------------- miipak (spp, mii, nelems, spptype, miitype) Pack an SPP array into an mii array miiupk (mii, spp, nelems, miitype, spptype) Unpack an mii array into an SPP array nchars = miipksize (nelems, miitype) Size (chars) of the SPP array required to store mii nelem = miinelem (nchars, miitype) Number of mii elements in an SPP array ----------------------------------------------------------------------- Table 2.75: Machine-Independent/SPP Conversion Functions. Note the distinction in the above table between the size of an mii array, specified as the number of array elements and the size of the SPP buffer, specified as the number of SPP chars. The following example illustrates reading an mii binary file consisting of byte (eight bit unsigned) values: Example 2.29: Reading an mii Binary File. Pixel Lists - plio The pixel list package is a general package for flagging individual pixels or regions of an image, to mark some subset of the pixels in an image. This may be done to flag bad pixels, or to identify those regions of an image to be processed by some applications program. When the pixel list package is used to flag the bad pixels in an image we call this a bad pixel mask, or BPM. When used to identify the regions of an image to be processed (or ignored), the list is called a region mask. The document Pixel List Package Design [Tody88] fully describes the details of the pixel list package. Here we only summarize and present a brief example. Example 2.30 opens a data image and the associated mask image, and sums the pixels within the area indicated by the mask. Example 2.30: Opening Data Image and Associated Mask. A more complex application might use the spatial information provided by v and npix, or the flag values provided by mval (for an integer mask). For example, a surface fitting routine would accumulate each line segment into a least squares matrix, using the coordinate information provided as well as the pixel values. World Coordinates - mwcs The mini-World Coordinate System (mwcs) interface is a package of procedures to handle the general problem of representing a linear or nonlinear world coordinate system (WCS). It may be used for determining the coordinates of pixels in an image, for example. Of course, enough information must be available to perform the appropriate coordinate transformations. While the interface is designed with the typical application to image data in mind, mwcs is intended as a general coordinate transformation facility for use with any type of data, as an embedded interface in other software, including system interfaces such as imio and gio as well as user applications. The mwcs package is referred to as a prototype since some functionality is missing. o All WCS functions are built in (hard coded), hence the interface is not extensible at runtime and the only way to support new applications is through modification of the interface (by adding new function drivers). o There is no support for modeling geometric distortions, except possibly in one dimension. o There is no provision for storing more than one world coordinate system in FITS oriented image headers, although multiple WCS are supported internally by the interface, and are preserved and restored across mw_save() and mw_load() operations. o Coordinate transforms involving dependent axes must include all such axes explicitly in the transform. Dependent axes are axes which are related, either by a rotation, or by a WCS function. Operations which could subset dependent axis groups, and which are therefore disallowed, include setting up a transform with an axes bitmap which excludes dependent axes, or more importantly, an image section involving dimen- sional reduction, where the axis to be removed is not independent. This could happen, for example, if a two-dimensional image were rotated and one tried to open a one-dimensional section of the rotated image. For a more detailed discussion of the mwcs implementation and coordinate transformations in general, refer to the document Mini-WCS Interface [Tody89], also available on-line in sys$mwcs/MWCS.hlp. Use the help facility in the IRAF cl to read or print it. Coordinate Systems The mwcs package defines three coordinate systems between which two transformations are performed. The three coordinate systems are defined as follows: o Physical - The physical coordinate system is the raw coordinate system of the data. In the case of an image, the physical coordinate system refers to the pixel coordinates of the original data frame. All other coor- dinates systems are defined in terms of the physical system (reference frame). o Logical - The logical coordinate system is defined by the Lterm (see below) in terms of the physical coordinate system. In the case of an image, the logical coordinate system specifies raw pixel coordinates rel- ative to some image section or derived image, i.e., the coordinates used for image I/O. In the mwcs the Lterm specifies a simple linear transfor- mation, in pixel units, between the original physical image matrix and the current image section. o World - The world coordinate system is defined by the Wterm (see below) in terms of the physical coordinate system. Any number of dif- ferent kinds of world coordinate systems are conceivable. Examples are the tangent (gnomonic) projection, specifying right ascension and decli- nation relative to the original data image, or any linear WCS, e.g., a lin- ear dispersion relation for spectral data. Multiple world coordinate systems may be simultaneously defined in terms of the same physical system. The coordinate systems are referred to by the strings physical, logical, and world. Note that there may be many Wterms specified for any one WCS. The world system refers to the current Wterm defined. Other Wterms are referred to by user-supplied names (see mw_newsystem()) and can be made the current system by mw_ssystem(). The two transformations are specified by the Lterm and the Wterm. The Lterm specifies a linear transformation between the physical and logical coordinate systems. The Wterm specifies the transformation between the physical and world coordinate systems The general flow of transforming coordinates is: 1. Retrieve or Create the Lterm and/or Wterm using mw_open(), mw_openim(), etc. 2. Modify the Lterm and/or Wterm (if necessary) using mw_slterm(), mw_swterm(), etc. 3. Precompute the transformations between the coordinate systems using the procedure mw_sctran() 4. Perform the transformations for specific coordinates using mw_ctran(), etc. A WCS always has a number of predefined attributes, and may also have any number of user defined, or WCS specific, attributes. These are defined when the WCS is created, in the wattr argument input to mw_swtype(), or in a subsequent call to mw_swattrs(). The WCS attributes for a specific axis may be queried with the function mw_gwattrs(). Attribute values may be modified, or new attributes defined, with mw_swattrs(). The issue of WCS attributes is discussed further in the next section. The WCS attributes which can be set by the wattr term consist of a number of standard attributes, plus an arbitrary number of additional WCS specific (application defined) attributes. The following standard attributes are reserved (but not necessarily defined) for each WCS: Attribute Definition ----------------------------------------------------------------------- units Axis units (pixels, etc.) label Axis label, for plots format Axis numeric format, for tick labels wtype WCS type, e.g., linear ----------------------------------------------------------------------- Table 2.76: WCS Standard Attributes. In addition, the following are defined for the entire WCS, regardless of the axis: Attribute Definition ----------------------------------------------------------------------- system System name (logical, physical, etc.) object External object with which WCS is associated ----------------------------------------------------------------------- Table 2.77: WCS Attributes. For example, to determine the WCS type for axis 1: call mw_gwattrs (mw, 1, "wtype", wtype, SZ_WTYPE) Axis Mapping The coordinate transformation procedures include support for a feature called axis mapping, used to implement dimensional reduction. A example of dimensional reduction occurs in imio, when an image section is used to specify a subraster of an image of dimension less than the full physical image. For example, the section might specify a one dimensional line or column of a two or higher dimensional image, or a two dimensional section of a three dimensional image. When this occurs the application sees a logical image of dimension equal to that of the image section, since logically an image section is an image. Dimensional reduction is implemented in mwcs by a transformation on the input and output coordinate vectors. The internal mwcs coordinate system is unaffected by either dimensional reduction or axis mapping; axis mapping affects only the view of the WCS as seen by the application using the coordinate transformation procedures. For example, if the physical image is an image cube and we access the logical image section [*,5,*], an axis mapping may be set up which maps physical axis one to logical axis one, physical axis two to the constant 5, and physical axis three to logical axis two. The internal system remains three dimensional, but the application sees a two dimensional system. Upon input, the missing axis y=5 is added to the two dimensional input coordinate vectors, producing a three dimensional coordinate vector for internal use. During output, axis two is dropped and replaced by axis three. The axis map is entered with mw_saxmap() and queried with mw_gaxmap(). Here, axno is a vector, with axno[i] specifying the logical axis to be mapped onto physical axis i. If zero is specified, the constant axval[i] is used instead. Axis mapping may be enabled or disabled with a call to mw_seti(). Axis mapping affects all of the coordinate transformation procedures and all of the coordinate system specification procedures. Axis mapping is not used with those procedures which directly access or modify the physical or world systems (e.g., mw_slterm() or mw_swterm()) since full knowledge of the physical system is necessary for such operations. Object Creation and Storage The mwcs interface routines used to create or access mwcs objects, or save and restore mwcs objects in external storage, are summarized below. Procedure Call Purpose ----------------------------------------------------------------------- mw = mw_open (bufptr, ndim) Create an mwcs object mw = mw_openim (im) Create an mwcs object based on information from an image ms = mw_newcopy (mw) Create new copy of an mwcs object mw_close (mw) Remove an mwcs object mw_load (mw, bufptr) Reload an mwcs object mw_save (mw, bufptr, buflen) Save mwcs information in a buffer mw_laodim (mw, im) Reload a mwcs object from image header information mw_saveim (mw, im) Save an mwcs object into an image header ----------------------------------------------------------------------- Table 2.78: MWCS Object Functions. mw_open() creates a new mwcs object and a pointer to it is returned. If bufptr is NULL, then an identity transformation is created with the dimension specified by ndim. If bufptr is pointing to an encoded mwcs buffer, the mwcs object is loaded with that information mw_openim() initializes an mwcs object with data from the image pointed to by the image descriptor im. If the image contains no mwcs information, an identity transformation is loaded instead. mw_newcopy() creates a new mwcs object that is a copy of the mwcs object specified by mw. mw_close() deallocates the memory structures associated with the mwcs object mw. mwcs objects can be saved in an encoded, machine-independent format in a memory array. This array can then be saved into a file, sent over the network, etc. mw_save() will save the contents of the mwcs object mw into the memory pointed to by the char pointer bufptr. If bufptr is NULL, a memory buffer is allocated whose pointer is returned in bufptr. If bufptr is not NULL, the buffer, of length buflen, is used (and resized if necessary). The length of the buffer is returned. The buffer bufptr can be used in the calls mw_open() and mw_load(). mw_load() reloads the mwcs object mw with information contained in the buffer bufptr saved by mw_save(). mw_loadim() reloads an existing mwcs object mw with information from the image pointed to by the image descriptor im. mw_saveim() saves the contents of the mwcs object mw into the image pointed to by the image descriptor im. Coordinate Transformation Procedures The mwcs procedures used to perform coordinate transformations are summarized below. Procedure Call Purpose ----------------------------------------------------------------------- ct = mw_sctran (mw, system1, system2, axes) Compile a coordinate transformation between systems ival = mw_gctransT (ct, ltm, ltv, axtype1, axtype2, maxdim) Return the compiled transformation mx_ctfree (ct) Deallocate the coordinate transformation structure x2 = mw_c1tranT (ct, x1) Return the transformation of a single point mw_v1tranT (ct, x1, x2, npts) Return the transformation of an array of points mw_c2tranT (ct, x1, y1, x2, y2) Return the two-dimensional transformation of a point mw_v2tranT (ct, x1, y1, x2, y2, npts) Transform an array of two dimensional points mw_ctranT (ct, p1, p2, ndim) Transform an arbitrarily dimensioned point mw_vtranT (ct, v1, v2, ndim, npts) Transform an array of arbitrarily dimensioned points ----------------------------------------------------------------------- Table 2.79: MWCS Coordinate Transformation Procedures. The mw_sctran() procedure precomputes the transformation from one coordinate system, system1, to another, system2, for the specified axes in the mwcs object mw returning a pointer to the optimized coordinate transformation. This pointer, ct is used in the subsequent coordinate transformation calls, mw_c2tran(), etc. The axes argument is a bitfield that represents which axes the transformation should apply to. That is, if you wish to transform the first two axes (x and y), set axis = 3. The mw_gctrant() procedure retrieves a compiled linear transformation and returns the dimensionality of the transformation. The argument ltm contains the coefficient determination matrix, ltv contains the translation vector, axtype1 contains the axis types for each of the axes in the source coordinate system, axtype2 contains the axis types in the destination coordinate system, and maxdim specifies the maximum dimensionality that the arrays can handle. Coordinate System Specification The procedures used to enter, modify, or inspect the mwcs logical and world coordinate transformations are summarized below. Procedure Call Purpose ----------------------------------------------------------------------- mw_sltermT (mw, ltm, ltv, ndim) Set the Lterm for the specified object mw_gltermT (mw, ltm, ltv, ndim) Get the Lterm for the specified object mw_ssystem (mw, system) Set the default world system mw_newsystem (mw, system, ndim) Create a new world coordinate system mw_swtermT (mw, r, w, cd, ndim) Set the Wterm for the current system mw_gwtermT (mw, r, w, cd, ndim) Get the Wterm for the current system ----------------------------------------------------------------------- Table 2.80: MWCS System Specification Functions. The procedures mw_sltermT() and mw_gltermT() are used to directly enter or inspect the Lterm of the mwcs object mw, which consists of the linear transformation matrix ltm and the translation vector ltv, both of dimension ndim, defining the transformation from the physical system to the logical system. Procedure Call Purpose ----------------------------------------------------------------------- mw_saxmap (mw, axno, axval, ndim) Set the axis mapping mw_gaxmap (mw, axno, axval, ndim) Get the axis mapping mw_swtype (mw, axis, naxes, wtype, wattr) Set the axis type and attribute mw_swattrs (mw, axis, attribute, valstr) Set the axis attribute mw_gwattrs (mw, axis, attribute, valstr) Get the axis attributes mw_swsampT (mw, axis, pv, wv, npts) Set a world system using sampled data mw_gwsampT (mw, axis, pv, wv, npts) Get a world system using sampled data ----------------------------------------------------------------------- Table 2.81: Axis Specification Functions. Procedure Call Purpose ----------------------------------------------------------------------- mw_translator (mw, ltv_1, ltm, ltv_2, ndim) Apply a general transformation to the Lterm, single precision mw_translated (mw, ltv_1, ltm, ltv_2, ndim) Apply a general transformation to the Lterm, double precision mw_rotate (mw, theta, center, axes) Apply a rotation transformation to the Lterm mw_scale (mw, scale, axes) Apply a scale transformation to the Lterm mw_shift (mw, shift, axes) Apply a translation (shift) transformation to the Lterm ----------------------------------------------------------------------- Table 2.82: Applying Transformations to Lterm. If the logical system undergoes successive linear transformations, mw_translate() may be used to translate, rather than replace, the Lterm of the mwcs object mw, where the given transformation matrix and translation vector refer to the relative transformation undergone by the logical system. This will always work since the Lterm is initialized to the identity matrix when a new mwcs object is created. See also mw_rotate(), mw_scale(), and mw_shift(). Generic coordinate transformations are available using the procedures mw_translate(), mw_rotate(), mw_scale, and mw_shift. The mw_translate() procedure is the most general, with the others provided as convenient front-ends. Note that mw_rotate() rotates the Lterm of the mwcs object mw through the angle theta, specified in radians, about an arbitrary point center for the specified axes. The axes argument is a bitfield representing which axes to which the transformation applies. That is, each bit represents an axis to transform. mwcs Parameters The mwcs status procedures, used to query or set the mwcs parameters, are as follows. Procedure Call Purpose ----------------------------------------------------------------------- mw_seti (mw, what, ival) Set a parameter ival = mw_stati (mw, what) Retrieve a parameter ----------------------------------------------------------------------- Table 2.83: MWCS Status Procedures. Name Type Description ----------------------------------------------------------------------- MW_NDIM int Dimensionality of logical system MW_NWCS int Number of WCS defined MW_REFIM int Reference image, if any MW_USEAXMAP bool true if axis mapping is enabled MW_NPHYSDIM int Dimensionality of physical system MW_SAVELEN int Character required for mw_save() buffer ----------------------------------------------------------------------- Table 2.84: MWCS Interface Parameters. MW_NDIM may differ from MW_NPHYSDIM if dimensional reduction has been specified and axis mapping is enabled. MW_NWCS returns the number of WCS currently defined; at least two WCS are always defined, i.e., the logical and physical systems (the world system will default to the physical system if not otherwise defined). Matrix Routines The following general purpose matrix manipulation routines are used internally within the interface to compile or evaluate transformations, and may be useful in applications code as well. Procedure Call Purpose ----------------------------------------------------------------------- mw_invertt (o_ltm, n_ltm, ndim) Invert a square matrix mw_mmult (ltm_1, ltm_2, ltm_out, ndim) Multiply two matrices mw_vmult (ltm, ltv_in, ltv_out, ndim) Multiply a matrix and a vector ----------------------------------------------------------------------- Table 2.85: Matrix Routines. Each is implemented for both real and double variables. They operate on square matrices whose dimensions are specified by ndim, i.e., ltm[ndim,ndim]. Examples This section presents of a few simple examples to demonstrate the basic workings of the mwcs interface. The examples will be code fragments showing the necessary declarations, etc., and are not intended to be complete programs. Example 2.31 shows how to retrieve the mwcs information from an image. Example 2.32 will create a WCS such that the world system is centered on an image and the axis decrease value with increasing pixel value. Example 2.33 shows some examples of transforming coordinates with an already opened mwcs object. Assume that the mwcs object describes a transformations for a three dimensional image. The final example (Example 2.34) prints all the values for all the attributes of all the axis of an image's mwcs. Example 2.31: Retrieving mwcs Information From an Image. This next example creates a WCS such that the world system is centered on an image and the axis decreases with increasing pixel values. Example 2.32: Creating WCS Centered on Image. The following examples transform coordinates with an already opened mwcs object. Assume that the object describes a transformation for a 3-dimensional image. Example 2.33: Transforming Coordinates in an Open mwcs. The example below prints all values for all attributes of all axes of an image's mwcs. Example 2.34: Printing Axis Attribute Values for a mwcs. Miscellaneous - etc cl Environment Variables These procedures return the value of a cl environment variable. There is a separate procedure for each of the data types bool, int, real, double, and character strings. There is no distinction made between the variously sized integer variables. If the variable is not found or cannot be converted to the appropriate data type, the procedures abort. Procedure Call Purpose ----------------------------------------------------------------------- bool = envgetb (varname) Get a boolean environment variable int = envgeti (varname) Get an integer environment variable real = envgetr (varname) Get a real environment variable double = envgetd (varname) Get a double environment variable envgets (key, value, maxch) Get a string environment variable ----------------------------------------------------------------------- Table 2.86: Reading Environment Variables. Time and Timing These procedures deal with absolute local time as well as relative CPU clock time. Procedure Call Purpose ----------------------------------------------------------------------- brktime (ltime, tm) Convert a long integer time into year, month, day, etc. long = clktime (old_time) Get the clock time cnvdate (ltime, outstr, maxch) Convert long integer time to date string (short format) cnvtime (ltime, outstr, maxch) Convert long integer time to time string (long format) long = cputime (old_cputime) Get the CPU time consumed by process sys_mtime() Mark the time (for timing programs) sys_ptime() Print the elapsed time since last mark ----------------------------------------------------------------------- Table 2.87: Clock and Timing Procedures. The clktime() procedure gets the current clock time (local standard time) in units of seconds since 00:00:00 1 January 1980. This can be broken down into days, hours, seconds, etc. with brktime(), or printed as a date and time string with cnvtime(). The brktime() breaks the long integer time returned by clktime() into the fields of the structure defined in . The procedure is valid from 00:00:00 on 1 January 1980 to 23:23:59 28 on February 2100. cnvdate() converts a time in integer seconds since midnight on 1 January 1980 into a short string such as "May 15 18:24". cnvtime() converts a time in integer seconds since midnight on 1 January 1980 into a string, i.e., "Mon 16:30:05 17-Mar-82". The length of the output strings for the procedures is given by the parameter SZ_DATE in . Parameter Contents ----------------------------------------------------------------------- SZ_TIME Size of dow 00:00:00 dd-Mmm-yy SZ_DATE Size of mmm dd hh:mm LEN_TMSTRUCT Length of time struct TM_SEC Seconds (0-59) TM_MIN Minutes (0-59) TM_HOUR Hour (0-23) TM_MDAY Day of month (1-31) TM_MONTH Month (1-12) TM_YEAR Year, e.g., 1982 TM_WDAY Day of week (Sunday is 1) TM_YDAY Day of year (1-366) ----------------------------------------------------------------------- Table 2.88: Time Parameters. Process Information These procedures return information about the current process. Procedure Call Purpose ----------------------------------------------------------------------- getuid (outstr, maxch) Get the name of the runtime user of a program gethost (outstr, maxch) Get the network name of the host machine int = getpid() Get the process id sysid (oustr, maxch) Return a line of text identifying the process ----------------------------------------------------------------------- Table 2.89: Process Information Functions. The getpid() procedure returns an integer process identifier, while the others return a string value. The sysid() procedure returns a line of text identifying the current user, machine, and version of IRAF, and containing the current date and time of the form: NOAO/IRAF V1.3 username@lyra Tue 09:47:50 27-Aug-85 The string NOAO/IRAF V1.3 is given by the value of the cl environment variable version. The string username is the value of the environment variable userid, defined by the user in the login.cl file. The output string is not terminated by a newline. Convert Flags These procedures convert between bool variables and int logical flags having the values YES or NO. Procedure Call Purpose ----------------------------------------------------------------------- int = btoi (boolean_value) Convert boolean to integer flag bool = itob (int_value) Convert integer to boolean ----------------------------------------------------------------------- Table 2.90: Flag Conversion Functions. Miscellaneous Functions Procedure Call Purpose ----------------------------------------------------------------------- int = lpopen (device, mode, type) Open the line printer as a file int = oscmd (cmd, infile, outfile, errfile) Send a command to the host operating system pagefiles (files) Display a text file or files on the standard output qsort (x, nelem, compare) General quick sort for any data structure tsleep (seconds) Delay process execution ----------------------------------------------------------------------- Table 2.91: Miscellaneous Functions. The oscmd() procedure sends a machine dependent command to the host operating system. It tries to spool the standard output and error output in the named files if the names for the files are not null. The integer flag OK is returned if the command executes successfully. The qsort() procedure is a general quicksort for arbitrary objects. The argument x is an int array indexing the array to be sorted. The user supplied function compare(x1,x2) is used to compare objects indexed by x. The value returned by compare has the following significance for sorting in increasing order: