next_group up previous contents
Up: CFHT FITS Handling Library Previous: 7. Including and Linking   Contents

Subsections

8. Examples

8.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_file(argv[1], FH_FILE_RDONLY);
   
      if (!hu) exit(1);
      fh_show(hu);
      fh_destroy(hu);
      exit(0);
   }

8.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, ehu;
      char extname[80];
      int i, ext;

      for (i = 1; i < argc; i++)
      {
         if (!(hu = fh_file(argv[i], FH_FILE_RDONLY)))
            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);
      }
      exit(EXIT_SUCCESS);
   }

8.3 Tool to Set any Keywords (fhset.c)

Here is the source code for `fhset', a command line utility which sets arbitrary keywords 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;
      int i, exitcode = EXIT_SUCCESS;

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

      if (!(hu = fh_file(argv[1], FH_FILE_RDWR)))
         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_value(hu, FH_AUTO, arg, val, com);
      }
      /*
       * Write the changes to the file, and unlock it.
       */
      if (fh_rewrite(hu) != FH_SUCCESS) exitcode = EXIT_FAILURE;

      fh_destroy(hu);
      exit(exitcode);
   }

8.4 Update a Card with known Keyword

In this example, the KeyWord WEATHER may or may not exist. If it doesn't it will be added to the end of the header. If there is no room, the program will fail.


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

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

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

8.5 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;

      /*
       * fd must be at the start of the appropriate header block.
       * Call lseek(fd, 0, SEEK_SET); before calling add_some_comments
       * if needed.
       */
      if (fh_read(hu, fd, FH_AUTO) != FH_SUCCESS ||
          fh_set_com(hu, FH_AUTO, "COMMENT", "Here's the 1st of 3 lines") != FH_SUCCESS ||
          fh_set_com(hu, FH_AUTO, "COMMENT", "which will be added") != FH_SUCCESS ||
          fh_set_com(hu, FH_AUTO, "COMMENT", "to the end of the header") != FH_SUCCESS ||
          fh_rewrite(hu) != FH_SUCCESS)
      {
         rtn = FAIL;
      }
      /* Don't forget to free memory, even on failure, */
      /* especially since this unlocks the file too. */
      fh_destroy(hu);
      return rtn;
   }

8.6 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:


   #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 */

      /*
       * The following would not normally be hardcoded,
       * but for this example they are.
       */
      double etime = 10.0;
      int w = 2048;
      int h = 4096;

      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;

      fh_destroy(hu);
      exit(exitcode);
   }

8.7 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 contructs 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[80];

         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: 7. Including and Linking   Contents
Sidik Isani
2001-04-21