next_group up previous contents
Up: CFHT FITS Handling Library Previous: 8. Recipes for Converting   Contents

Subsections

9. Examples

9.1 Display any Primary or Extension Header (fhlist.c)

This program will show the FITS header from any file, or any extension within the file (by using a feature of fh_file() which searches for an extension when the filename contains ``fitsfile[extname]''.)

This small program is also a good way to test the behavior of fh_file().


   #include "fh/fh.h"
   
   int
   main(int argc, const char* argv[])
   {
      HeaderUnit hu = fh_create();

      if (fh_file(hu, argv[1], FH_FILE_RDONLY) != FH_SUCCESS)
	 exit(1);
      fh_show(hu);
      fh_destroy(hu); /* No errors possible, since RDONLY */
      exit(0);
   }


   #include "fh/fh.h"

   int
   main(int argc, const char* argv[])
   {
      HeaderUnit hu = fh_create();
      const char* card;

      if (fh_file(hu, argv[1], FH_FILE_RDONLY) != FH_SUCCESS)
	 exit(1);
      for (card = fh_first(hu); card; card = fh_next(hu))
      {
         printf("%.*s\n", strlen(card)==80?80:79, card);
      }

      fh_destroy(hu); /* No errors possible, since RDONLY */
      exit(0);
   }

9.2 Loop through all extensions by EXTNAME (fhextname.c)

When there is a separate FITS file for each amplifier, finding the names of all the ``extensions'' is as easy as listing all the files in a subdirectory. Here's a utility which generates an equivalent list of names for MEF Files. The output from this program can be used as the arguments to a pipeline program which uses fh_file() to open one file or extension each time it is run. Multiple FITS files may be given on the command line. In this example, the `fhextname' program is used just as `ls' would have been with basic FITS files:


   #!/bin/sh
   for i in `fhextname *.fits`
   do
      reduce "$i"
   done

Note that this also works for split files, since `fhextname' just prints the name of the fits file itself, if there are no extensions.

Here is the source code for `fhextname':


   #include <stdio.h>
   #include <stdlib.h>
   #include "fh/fh.h"

   int
   main(int argc, const char* argv[])
   {
      HeaderUnit hu = fh_create();
      HeaderUnit ehu;
      char extname[FH_MAX_STRLEN+1];
      int i, ext;

      for (i = 1; i < argc; i++)
      {
         if (fh_file(hu, argv[i], FH_FILE_RDONLY) != FH_SUCCESS)
            exit(EXIT_FAILURE);

         if (fh_extensions(hu) < 1)
         {
            printf("%s\n", argv[i]); /* No extensions?  Print the filename. */
         }
         else for (ext = 1; ext <= fh_extensions(hu); ext++)
         {
            if (!(ehu = fh_ehu(hu, ext)) ||
   	        fh_get_str(ehu, "EXTNAME", extname, sizeof(extname)) != FH_SUCCESS)
            {
               fprintf(stderr, "error: Cannot read EXTNAME from `%s' for extension #%d\n", argv[i], ext);
               fh_destroy(hu);
               exit(EXIT_FAILURE);
            }
            printf("%s[%s]\n", argv[i], extname);
         }
         fh_destroy(hu); /* No errors to check, since RDONLY */
      }
      exit(EXIT_SUCCESS);
   }

9.3 Tool to Set any Keyword(s) (fhset.c)

Here is the source code for `fhset', a command line utility which sets arbitrary keywords and comment fields in a FITS file (and extension units, if it has any.) The following would cause this tool to update/add GAIN (a float value), OBSID (an integer), CCD (a string) and INHERIT (boolean).


   #!/bin/sh
   fhset 12345o.fits "GAIN=1.35" "OBSID=12345" "CCD='Cam corder CCD'" "INHERIT=F"

Here is the source for the fhset.c program:


   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
   #include "fh/fh.h"

   int
   main(int argc, const char* argv[])
   {
      HeaderUnit hu = fh_create();
      int i, exitcode = EXIT_SUCCESS;

      if (argc < 2)
      {
         fprintf(stderr, "usage: fhset <fitsfile> KEYWORD=value [/comment] [KEYWORD=value [/comment] ...]\n");
         exit(2);
      }

      if (fh_file(hu, argv[1], FH_FILE_RDWR) != FH_SUCCESS)
         exit(EXIT_FAILURE);
   
      for (i = 2; i < argc; i++)
      {
         char* arg = strdup(argv[i]);
         char* val = strchr(arg, '=');
         const char* com;

         com = 0;
         if (!val)
         {
            fprintf(stderr, "fhset: error: Specify KEYWORD=value (with no spaces)\n");
            fh_destroy(hu);
            exit(2);
         }
         *val++ = '\0';
         if (i + 1 < argc && *argv[i + 1]=='/')
         { com = argv[++i]; com++; } /* Don't include the '/' itself. */
         fh_set_val(hu, FH_AUTO, arg, val, com);
      }
      /*
       * Write the changes to the file, and unlock it.
       */
      if (fh_rewrite(hu) != FH_SUCCESS) exitcode = EXIT_FAILURE;
      if (fh_destroy(hu) != FH_SUCCESS) exitcode = EXIT_FAILURE;
      exit(exitcode);
   }

9.4 Tool for making Reserve Space (fhreserve.c)

This one still has to be written . . .

9.5 Update a Card with known Keyword

In this example, the keyword WEATHER may or may not exist.


   #include <stdio.h>
   #include <stdlib.h>
   #include "fh/fh.h"

   int
   main(int argc, const char* argv[])
   {
      HeaderUnit hu = fh_create();
      int exitcode = EXIT_SUCCESS;

      /*
       * This program does not like to read from pipes.  Check explicitly.
       */
      if (!argv[1] || !strcmp(argv[1], "-"))
      {
         fprintf(stderr, "error: Updating FITS cards requires an input file.\n")
         exit(EXIT_FAILURE);
      }
      if (fh_file(hu, argv[1], FH_FILE_RDWR) != FH_SUCCESS)
         exit(EXIT_FAILURE);
      fh_set_str(hu, FH_AUTO, "WEATHER", "Excellent", "This card is bogus");
      if (fh_rewrite(hu) != FH_SUCCESS) exitcode = EXIT_FAILURE;
      /* File is now changed (and automatically unlocked) */
      if (fh_destroy(hu) != FH_SUCCESS) exitcode = EXIT_FAILURE;
      exit(exitcode);
   }

9.6 Add set of COMMENT cards to already open file

This example is not a complete program, but a function within a larger program which has its own way of opening a file descriptor (and thus, does not want to use fh_file.)


   PASSFAIL
   add_some_comments(int fd)
   {
      HeaderUnit hu = fh_create();
      PASSFAIL rtn = PASS;

      if (fh_read(hu, fd, FH_AUTO) != FH_SUCCESS) rtn = FAIL;
      else
      {
         fh_set_com(hu, FH_AUTO, "COMMENT", "Here's the 1st of 3 lines");
         fh_set_com(hu, FH_AUTO, "COMMENT", "which will be added");
         fh_set_com(hu, FH_AUTO, "COMMENT", "to the end of the header");
         if (fh_rewrite(hu) != FH_SUCCESS) rtn = FAIL;
      }

      /* Don't forget to free memory, even on failure, */
      /* especially since this unlocks the file too. */
      if (fh_destroy(hu) != FH_SUCCESS) rtn = FAIL;
      return rtn;
   }

9.7 Build a FITS File from Scratch

Here a complete FITS file is built from scratch, using routines in libfh. It demonstrates several other things which the examples above do not:

Source code follows:


   #include <stdio.h>
   #include <stdlib.h>
   #include <time.h>
   #include "fh/fh.h"

   int
   main(int argc, const char* argv[])
   {
      HeaderUnit hu = fh_create();
      time_t date = time(0);
      short* data;
      int exitcode = EXIT_SUCCESS;
      int fd = STDOUT_FILENO;	/* By default, write to stdout */
      double etime = 10.0;	/* Normally these values might */
      int w = 2048, h = 4096;	/*  not be hardcoded like this */

      data = malloc(sizeof(short)*w*h);

      fh_reserve(hu, 50); /* Reserve space for 50 cards (TCS, Elixir?, etc.) */
      fh_set_bool(hu, FH_AUTO, "SIMPLE", 1, "Standard FITS");
      fh_set_int(hu,  FH_AUTO, "BITPIX", 16,"16-bit data");
      fh_set_int(hu,  FH_AUTO, "NAXIS",  2, "Number of axes");
      fh_set_int(hu,  FH_AUTO, "NAXIS1", w, "Number of pixel columns");
      fh_set_int(hu,  FH_AUTO, "NAXIS2", h, "Number of pixel rows");
      fh_set_int(hu,  FH_AUTO, "PCOUNT", 0, "No 'random' parameters");
      fh_set_int(hu,  FH_AUTO, "GCOUNT", 1, "Only one group");

      strftime(str, sizeof(str)-1, "%Y-%m-%dT%T", gmtime(&date));
      fh_set_str(hu, 104, "DATE", str, "UTC Date of file creation");
      strftime(str, sizeof(str)-1, "%a %b %d %H:%M:%S %Z %Y", localtime(&date));
      fh_set_str(hu, 104.1,"HSTTIME", str, "Local time in Hawaii");
      fh_set_str(hu, 105,  "ORIGIN", "CFHT", "Canada-France-Hawaii Telescope");
      fh_set_flt(hu, 141., "BZERO",	0.0, 6,	"Zero factor");
      fh_set_flt(hu, 142., "BSCALE",	1.0, 2, "Scale factor");
      fh_set_flt(hu, 150, "DATAMIN", datamin, 6, "Minimum value of the data");
      fh_set_flt(hu, 151, "DATAMAX", datamax, 6, "Maximum value of the data");
      fh_set_flt(hu, 160, "SATURATE", 4016.0, 6, "Saturation value");
      fh_set_flt(hu, 220, "EXPTIME", etime, 5, "Integration time (seconds)");
      sprintf(str, "%d %d", binmode + 1, binmode + 1);
      fh_set_str(hu, 230, "CCDSUM", str, "Binning factors");
      fh_set_com(hu, 1400.0, "COMMENT", "");
      fh_set_com(hu, 1400.1, "COMMENT", " Camera status record:");
      fh_set_com(hu, 1400.2, "COMMENT", "");
      if (camera_status==0)
        fh_set_str(hu, 1410, "DETSTAT", "ok", "(camera_status is 0)");
      else
        fh_set_int(hu, 1411, "DETSTAT", sbstat.imaging_ccd_status, "error!");
      fh_set_str(hu, 1601,"DETECTOR", info.camera_name, info.serial_number);
      if (fh_write(hu, fd) != FH_SUCCESS ||
          fh_write_padded_image(hu, fd, data, w*h*sizeof(unsigned short)) != FH_SUCCESS)
         exitcode = EXIT_FAILURE;
      if (fh_destroy(hu) != FH_SUCCESS) exitcode = EXIT_FAILURE;
      exit(exitcode);
   }

9.8 Build an MEF File from Scratch

The fh_ehu*() functions are only used to access extensions within an already existing MEF. The are not used when building an MEF File for the first time. This task must be done by writing the appropriate interleaved header units and image data manually.

The following example constructs a very minimal MEF File with only two extensions. For a more comprehensive example, see the source code of DetCom, /cfht/src/medusa/detcom/detcom/det_data.c.


   #include <stdio.h>
   #include <stdlib.h>
   #include "fh/fh.h"

   #define NEXTEND 2

   int
   main(int argc, const char* argv[])
   {
      short dummy_data[3 * 2] = { 1, 2, 3, 4, 5, 6 };
      HeaderUnit phu, ehu;
      int i, fd = STDOUT_FILENO;

      phu = fh_create();
      fh_set_bool(phu, FH_AUTO, "SIMPLE",  1, "Standard FITS");
      fh_set_int( phu, FH_AUTO, "BITPIX", 16, "Bits per pixel (not appl. to PHU)");
      fh_set_int( phu, FH_AUTO, "NAXIS",   0, "No image data with primary header");
      fh_set_bool(phu, FH_AUTO, "EXTEND",  1, "File contains extensions");
      fh_set_int( phu, FH_AUTO, "NEXTEND", NEXTEND, "Number of extensions");
      fh_write(phu, fd);
      fh_destroy(phu);

      for (i = 0; i < NEXTEND; i++)
      {
         char str[FH_MAX_STRLEN+1];

         sprintf(str, "im%02d", i);
         ehu = fh_create();
         fh_set_str(ehu, FH_AUTO, "XTENSION", "IMAGE", "Image extension");
         fh_set_int(ehu, FH_AUTO, "BITPIX", 16, "Bits per pixel");
         fh_set_int(ehu, FH_AUTO, "NAXIS",   2, "Number of axes");
         fh_set_int(ehu, FH_AUTO, "NAXIS1",  3, "Number of pixel columns");
         fh_set_int(ehu, FH_AUTO, "NAXIS2",  2, "Number of pixel rows");
         fh_set_int(ehu, FH_AUTO, "PCOUNT",  0, "No 'random' parameters");
         fh_set_int(ehu, FH_AUTO, "GCOUNT",  1, "Only one group");
         fh_set_str(ehu, FH_AUTO, "EXTNAME", str, "Extension name");
         fh_write(ehu, fd);
         fh_write_padded_image(ehu, fd, dummy_data, sizeof(dummy_data));
         fh_destroy(ehu);
      }
   }


next_group up previous contents
Up: CFHT FITS Handling Library Previous: 8. Recipes for Converting   Contents
Sidik Isani
2001-04-27