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:
ff_init(filename);
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 ... */
If fh_file() was used instead of open(), fh_destroy() will close() the file, but for the same reasons, check the return of fh_destroy() if you opened a file for writing.
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);
becomes:
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);
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 '' (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().
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().