next up previous contents
Next: 10. Examples Up: CFHT FITS Handling Library Previous: 8. Including and Linking   Contents


9. Recipes for Converting to libfh

9.1 Opening a File

Find the place(s) in the code where a FITS file is opened and closed. For a Pegasus handler based on libff, the old call to open the file would look something like this:


and replace it with:

   HeaderUnit hu = fh_create();

   /* Use FH_FILE_RDONLY below, if you only want to read the file. */
   if (fh_file(hu, filename, FH_FILE_RDWR) != FH_SUCCESS)
      /* ERROR ... */

The FITS header, and all extension headers are now available by passing ``hu'' to the other functions of the library. Note: Since fh_file() returns a handle, it is possible to have multiple FITS files open at once.

9.2 Changing Keywords

Calls to the libff routine to set a string:

   ff_chng_value(FF_CARDNAME, FITS_STRING, string);

are changed to:

   fh_set_str(hu, FH_AUTO, "CARDNAME", string, comment);

The actual "CARDNAME" and `comment' field can be found by looking inside the ``handler.def'' template file. After a handler is converted, and if DetCom is generating the FITS file (i.e., leaving room with fh_reserve) then the .def template is no longer needed.

An upgraded handler still works fine with templates too, though, because it finds the template slots in the FITS file and uses those before looking for COMMENT reserve space.

ff_chng_value() calls with FITS_REAL, FITS_INTEGER, and FITS_LOGICAL are easiest to convert to directly to calls to fh_set_val(), which allows the calling program to do the sprintf'ing and precisely control the formatting of the value:

    double juliandate = ...;
    char String[FH_MAX_STRLEN+1];

    sprintf(String, "%15.6f", juliandate);
    ff_chng_value(FF_MJDOBS, FITS_REAL, String);


    double juliandate = ...;
    char String[FH_MAX_STRLEN+1];

    sprintf(String, "%15.6f", juliandate);
    fh_set_val(hu, FH_AUTO, "MJD-OBS", String, comment);

(Note how the actual name of the FITS keyword is not always the name of the defined symbol less the FF_. You must check the template and ff/ff.h for the real name.)

See sections on fh_set_int(), fh_set_flt(), and fh_set_bool() for a way to set integer, float, and T/F values using the library's internal formatting. This is recommended over fh_set_val(). The above call could be changed to:

    double juliandate = ...;
    fh_set_flt(hu, FH_AUTO, "MJD-OBS", juliandate, .6, comment);

9.3 ``Flushing'' Changes to a File

After all calls to fh_set_*() have been done, make one call to write the changes back to the file. Check for errors here!

    if (fh_rewrite(hu) != FH_SUCCESS) rtn = FAIL;
    if (fh_destroy(hu) != FH_SUCCESS) rtn = FAIL;
    return rtn;

WARNING: Do not combine the two statements above with '$\vert\vert$' (short-circuit logic), or simply ``return FAIL'' on the first failure because the memory and file locks associated with ``hu'' may not be properly released!

In Pegasus handlers with libff, this replaces calls to ff_flush() and ff_free().

9.4 Closing a File

Whether fh_file() or fh_create() was used, when the HeaderUnit is no longer needed, make a call to:

    if (fh_destroy(hu) != FH_SUCCESS) return FAIL;

In Pegasus handlers, this replaces the call to ff_free().

next up previous contents
Next: 10. Examples Up: CFHT FITS Handling Library Previous: 8. Including and Linking   Contents
Jim Thomas