GNU Astronomy Utilities


Next: , Previous: , Up: FITS files   [Contents][Index]


10.3.11.4 FITS header keywords

Each FITS extension/HDU contains a raw dataset which can either be a table or an image along with some header keywords. The keywords can be used to store meta-data about the actual dataset. The functions in this section describe Gnuastro’s high-level functions for reading and writing FITS keywords. Similar to all Gnuastro’s FITS-related functions, these functions are all wrappers for CFITSIO’s low-level functions.

The necessary meta-data (header keywords) for a particular dataset are commonly numerous, it is much more efficient to list them in one variable and call the reading/writing functions once. Hence the functions in this section use linked lists, a thorough introduction to them is given in Linked lists (list.h). To reading FITS keywords, these functions use a list of Gnuastro’s generic dataset format that is discussed in List of gal_data_t. To write FITS keywords we define the gal_fits_list_key_t node that is defined below.

Type (C struct): gal_fits_list_key_t

Structure for writing FITS keywords. This structure is used for one keyword and you don’t need to set all elements. With the next element, you can link it to another keyword thus creating a linked list to add any number of keywords easily and at any step during your program (see Linked lists (list.h) for an introduction on lists). See the functions below for adding elements to the list.

typedef struct gal_fits_list_key_t
{
  int                        kfree;   /* ==1, free name.      */
  int                        vfree;   /* ==1, free value.     */
  int                        cfree;   /* ==1, free comment.   */
  uint8_t                     type;   /* Keyword value type.  */
  char                    *keyname;   /* Keyword Name.        */
  void                      *value;   /* Keyword value.       */
  char                    *comment;   /* Keyword comment.     */
  char                       *unit;   /* Keyword unit.        */
  struct gal_fits_list_key_t *next;   /* Next keyword.        */
} gal_fits_list_key_t;
Function:
void *
gal_fits_key_img_blank (uint8_t type)

Returns a pointer to an allocated space containing the value to the FITS BLANK header keyword, when the input array has a type of type. This is useful when you want to write the BLANK keyword using CFITSIO’s fits_write_key function.

According to the FITS standard: “If the BSCALE and BZERO keywords do not have the default values of 1.0 and 0.0, respectively, then the value of the BLANK keyword must equal the actual value in the FITS data array that is used to represent an undefined pixel and not the corresponding physical value”. Therefore a special BLANK value is needed for datasets containing signed 8-bit, unsigned 16-bit, unsigned 32-bit, and unsigned 64-bit integers (types that are defined with BSCALE and BZERO in the FITS standard).

Not usable when reading a dataset: As quoted from the FITS standard above, the value returned by this function can only be generically used for the writing of the BLANK keyword header. It must not be used as the blank pointer when when reading a FITS array using CFITSIO. When reading an array with CFITSIO, you can use gal_blank_alloc_write to generate the necessary pointer.

Function:
void
gal_fits_key_clean_str_value (char *string)

Remove the single quotes and possible extra spaces around the keyword values that CFITSIO returns when reading a string keyword. CFITSIO doesn’t remove the two single quotes around the string value of a keyword. Hence the strings it reads are like: 'value ', or 'some_very_long_value'. To use the value during your processing, it is commonly necessary to remove the single quotes (and possible extra spaces). This function will do this within the allocated space of the string.

Function:
char *
gal_fits_key_date_to_struct_tm (char *fitsdate, struct tm *tp)

Parse fitsdate as a FITS date format string (most generally: YYYY-MM-DDThh:mm:ss.ddd...) into the C library’s broken-down time structure, or struct tm (declared in time.h) and return a pointer to a newly allocated array for the sub-second part of the format (.ddd...). Therefore it needs to be freed afterwards (if it isn’t NULL) When there is no sub-second portion, this pointer will be NULL.

This is a relatively low-level function, an easier function to use is gal_fits_key_date_to_seconds which will return the sub-seconds as double precision floating point.

Note that the FITS date format mentioned above is the most complete representation. The following two formats are also acceptable: YYYY-MM-DDThh:mm:ss and YYYY-MM-DD. This option can also interpret the older FITS date format where only two characters are given to the year and the date format is reversed (DD/MM/YYThh:mm:ss.ddd...). In this case (following the GNU C Library), this option will make the following assumption: values 68 to 99 correspond to the years 1969 to 1999, and values 0 to 68 as the years 2000 to 2068.

Function:
size_t
gal_fits_key_date_to_seconds (char *fitsdate, char **subsecstr, double *subsec)

Return the Unix epoch time (number of seconds that have passed since 00:00:00 Thursday, January 1st, 1970) corresponding to the FITS date format string fitsdate (see description of gal_fits_key_date_to_struct_tm above). This function will return GAL_BLANK_SIZE_T if the broken-down time couldn’t be converted to seconds.

The Unix epoch time is in units of seconds, but the FITS date format allows sub-second accuracy. The last two arguments are for the (optional) sub-second portion. If fitsdate contains sub-second accuracy, then the starting of the sub-second part’s string is stored in subsecstr (allocated separately), and subsec will be the corresponding numerical value (between 0 and 1, in double precision floating point). So to avoid leaking memory, when subsecstr!=NULL, it must be freed.

This is a very useful function for operations on the FITS date values, for example sorting FITS files by their dates, or finding the time difference between two FITS files. The advantage of working with the Unix epoch time is that you don’t have to worry about calendar details (for example the number of days in different months, or leap years, etc).

Function:
void
gal_fits_key_read_from_ptr (fitsfile *fptr, gal_data_t *keysll, int readcomment, int readunit)

Read the list of keyword values from a FITS pointer. The input should be a linked list of Gnuastro’s generic data container (gal_data_t). Before calling this function, you just have to set the name and desired type values of each node in the list to the keyword you want it to keep the value of. The given name value will be directly passed to CFITSIO to read the desired keyword name. This function will allocate space to keep the value. If readcomment and readunit are non-zero, this function will also try to read the possible comments and units of the keyword.

Here is one example of using this function:

/* Allocate an array of datasets. */
gal_data_t *keysll=gal_data_array_calloc(N);

/* Make the array usable as a list too (by setting `next'). */
for(i=0;i<N-1;++i) keysll[i].next=keysll[i+1];

/* Fill the datasets with a `name' and a `type'. */
keysll[0].name="NAME1";     keysll[0].type=GAL_TYPE_INT32;
keysll[1].name="NAME2";     keysll[1].type=GAL_TYPE_STRING;
...
...

/* Call this function. */
gal_fits_key_read_from_ptr(fptr, keysll, 0, 0);

/* Use the values as you like... */

/* Free all the allocated spaces. Note that `name' wasn't allocated
   in this example, so we should explicitly set it to NULL before
   calling `gal_data_array_free'. */
for(i=0;i<N;++i) keysll[i].name=NULL;
gal_data_array_free(keysll, N, 1);

If the array pointer of each keyword’s dataset is not NULL, then it is assumed that the space to keep the value has already been allocated. If it is NULL, space will be allocated for the value by this function.

Strings need special consideration: the reason is that generally, gal_data_t needs to also allow for array of strings (as it supports arrays of integers for example). Hence when reading a string value, two allocations may be done by this function (one if array!=NULL).

Therefore, when using the values of strings after this function, keysll[i].array must be interpreted as char **: one allocation for the pointer, one for the actual characters. If you use something like the example, above you don’t have to worry about the freeing, gal_data_array_free will free both allocations. So to read a string, one easy way would be the following:

char *str, **strarray;
strarr = keysll[i].array;
str    = strarray[0];

If CFITSIO is unable to read a keyword for any reason the status element of the respective gal_data_t will be non-zero. If it is zero, then the keyword was found and successfully read. Otherwise, it is a CFITSIO status value. You can use CFITSIO’s error reporting tools or gal_fits_io_error (see FITS Macros, errors and filenames) for reporting the reason of the failure. A tip: when the keyword doesn’t exist, CFITSIO’s status value will be KEY_NO_EXIST.

CFITSIO will start searching for the keywords from the last place in the header that it searched for a keyword. So it is much more efficient if the order that you ask for keywords is based on the order they are stored in the header.

Function:
void
gal_fits_key_read (char *filename, char *hdu, gal_data_t *keysll, int readcomment, int readunit)

Same as gal_fits_read_keywords_fptr (see above), but accepts the filename and HDU as input instead of an already opened CFITSIO fitsfile pointer.

Function:
void
gal_fits_key_list_add (gal_fits_list_key_t **list, uint8_t type, char *keyname, int kfree, void *value, int vfree, char *comment, int cfree, char *unit, int ufree)

Add a keyword to the top of list of header keywords that need to be written into a FITS file. In the end, the keywords will have to be freed, so it is important to know before hand if they were allocated or not (hence the presence of the arguments ending in free). If the space for the respective element is not allocated, set these arguments to 0 (zero).

You can call this function multiple times on a single list add several keys that will be written in one call to gal_fits_key_write or gal_fits_key_write_in_ptr. However, the resulting list will be a last-in-first-out list (for more on lists, see Linked lists (list.h)). Hence, the written keys will have the inverse order of your calls to this function. To avoid this problem, you can either use gal_fits_key_list_add_end instead (which will add each key to the end of the list, not to the top like this function). Alternatively, you can use gal_fits_key_list_reverse after adding all the keys with this function.

Important note for strings: the value should be the pointer to the string its-self (char *), not a pointer to a pointer (char **).

Function:
void
gal_fits_key_list_add_end (gal_fits_list_key_t **list, uint8_t type, char *keyname, int kfree, void *value, int vfree, char *comment, int cfree, char *unit, int ufree)

Similar to gal_fits_key_list_add, but add the given keyword to the end of the list, see the description of gal_fits_key_list_add for more. Use this function if you want the keywords to be written in the same order that you add nodes to the list of keywords.

Function:
void
gal_fits_key_list_title_add (gal_fits_list_key_t **list, char *title, int tfree)

Add a special “title” keyword (with the title string) to the top of the keywords list.

Function:
void
gal_fits_key_list_title_add_end (gal_fits_list_key_t **list, char *title, int tfree)

Add a special “title” keyword (with the title string) to the end/bottom of the keywords list.

Function:
void
gal_fits_key_list_reverse (gal_fits_list_key_t **list)

Reverse the input list of keywords.

Function:
void
gal_fits_key_write_title_in_ptr (char *title, fitsfile *fptr)

Add two lines of “title” keywords to the given CFITSIO fptr pointer. The first line will be blank and the second will have the string in title roughly in the middle of the line (a fixed distance from the start of the keyword line). A title in the list of keywords helps in classifying the keywords into groups and inspecting them by eye. If title==NULL, this function won’t do anything.

Function:
void
gal_fits_key_write_filename (char *keynamebase, char *filename, gal_fits_list_key_t **list, int top1end0)

Put filename into the gal_fits_list_key_t list (possibly broken up into multiple keywords) to later write into a HDU header. The keynamebase string will be appended with a _N (N>0) and used as the keyword name. If top1end0!=0, then the keywords containing the filename will be added to the top of the list.

The FITS standard sets a maximum length for the value of a keyword. This creates problems with file names (which include directories). Because file names/addresses can become very long. Therefore, when filename is longer than the maximum length of a FITS keyword value, this function will break it into several keywords (breaking up the string on directory separators).

Function:
void
gal_fits_key_write_wcsstr (fitsfile *fptr, char *wcsstr, int nkeyrec)

Write the WCS header string (produced with WCSLIB’s wcshdo function) into the CFITSIO fitsfile pointer. nkeyrec is the number of FITS header keywords in wcsstr. This function will put a few blank keyword lines along with a comment WCS information before writing each keyword record.

Function:
void
gal_fits_key_write (gal_fits_list_key_t **keylist, char *title, char *filename, char *hdu)

Write the list of keywords in keylist into the hdu extension of the file called filename (the file must already exist) and free the list.

The list nodes are meant to be dynamically allocated (because they will be freed after being written). We thus recommend using the gal_fits_key_list_add or gal_fits_key_list_add_end to create and fill the list. Below is one fully working example of using this function to write a keyword into an existing FITS file.

#include <stdio.h>
#include <stdlib.h>
#include <gnuastro/fits.h>

int main()
{
  char *filename="test.fits";
  gal_fits_list_key_t *keylist=NULL;

  char *unit="unit";
  float value=123.456;
  char *keyname="MYKEY";
  char *comment="A good description of the key";
  gal_fits_key_list_add_end(&keylist, GAL_TYPE_FLOAT32, keyname, 0,
                            &value, 0, comment, 0, unit, 0);
  gal_fits_key_write(&keylist, "Matching metadata", filename, "1");
  return EXIT_SUCCESS;
}
Function:
void
gal_fits_key_write_in_ptr (gal_fits_list_key_t **keylist, fitsfile *fptr)

Write the list of keywords in keylist into the given CFITSIO fitsfile pointer and free keylist. For more on the input keylist, see the description and example for gal_fits_key_write, above.

Function:
void
gal_fits_key_write_version (gal_fits_list_key_t **keylist, char *title, char *filename, char *hdu)

Write the (optional, when keylist!=NULL) given list of keywords under the optional FITS keyword title, then print all the important version and date information. This is basically, just a wrapper over gal_fits_key_write_version_in_ptr.

Function:
void
gal_fits_key_write_version_in_ptr (gal_fits_list_key_t **keylist, char *title, fitsfile *fptr)

Write or update (all the) keyword(s) in headers into the FITS pointer, but also the date, name of your program (program_name), along with the versions of CFITSIO, WCSLIB (when available), GSL, Gnuastro, and (the possible) commit information into the header as described in Output FITS files.

Since the data processing depends on the versions of the libraries you have used, it is strongly recommended to include this information in every FITS output. gal_fits_img_write and gal_fits_tab_write will automatically use this function.

Function:
void
gal_fits_key_write_config (gal_fits_list_key_t **keylist, char *title, char *extname, char *filename, char *hdu)

Write the given keyword list (keylist) into the hdu extension of filename, ending it with version information. This function will write extname as the name of the extension (value to the standard EXTNAME FITS keyword). The list of keywords will then be printed under a title called title.

This function is used by many Gnuastro programs and is primarily intended for writing configuration settings of a program into the zero-th extension of their FITS outputs (which is empty when the FITS file is created by Gnuastro’s program and this library).


Next: , Previous: , Up: FITS files   [Contents][Index]