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.
struct
): gal_fits_list_key_t ¶Structure for writing FITS keywords. This structure is used for one keyword
and you do not 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 tfree; /* ==1, free title string. */ int kfree; /* ==1, free keyword name. */ int vfree; /* ==1, free keyword value. */ int cfree; /* ==1, free comment. */ int ufree; /* ==1, free unit. */ uint8_t type; /* Keyword value type. */ char *title; /* !=NULL, only print title.*/ char *keyname; /* Keyword Name. */ void *value; /* Keyword value. */ char *comment; /* Keyword comment. */ char *unit; /* Keyword unit. */ struct gal_fits_list_key_t *next; /* Pointer next keyword. */ } gal_fits_list_key_t;
int
(fitsfile *fptr
, char *keyname
)
¶Return 1 (true) if the opened FITS file pointer contains the requested keyword and 0 (false) otherwise.
void *
(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 |
void
(char *string
)
¶Remove the single quotes and possible extra spaces around the keyword values
that CFITSIO returns when reading a string keyword. CFITSIO does not 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.
char *
(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 is not 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.
size_t
(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 could not 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 you do not want sub-second information, just set the second argument to NULL
.
If fitsdate
contains sub-second accuracy and subsecstr!=NULL
, then the starting of the sub-second part’s string is stored in subsecstr
(malloc’ed), and subsec
will be the corresponding numerical value (between 0 and 1, in double precision floating point).
So to avoid leaking memory, if a sub-second string is requested, it must be freed after calling this function.
When a sub-second string does not exist (and it is requested), then a value of NULL
and NaN will be written in *subsecstr
and *subsec
respectively.
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 do not have to worry about calendar details (such as the number of days in different months or leap years).
void
(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 optionally, the desired type
of the value of each keyword.
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 no pre-defined type is requested for a certain keyword’s value, the smallest possible type to host the value will be found and used.
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' was not 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 do not 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 does not 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.
void
(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.
void
(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 **
).
void
(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.
void
(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.
If cfree
is non-zero, the space allocated for comment
will be freed immediately after writing the keyword (in another function).
void
(gal_fits_list_key_t **list
, char *title
, int tfree
)
¶Similar to gal_fits_key_list_title_add
, but put the comments at the end of the list.
void
(gal_fits_list_key_t **list
, char *comment
, int fcfree
)
¶Add a COMMENT
keyword to the top of the keywords list.
If the comment is longer than 70 characters, CFITSIO will automatically break it into multiple COMMENT
keywords.
If fcfree
is non-zero, the space allocated for comment
will be freed immediately after writing the keyword (in another function).
void
(gal_fits_list_key_t **list
, char *comment
, int fcfree
)
¶Similar to gal_fits_key_list_comment_add
, but put the comments at the end of the list.
void
(gal_fits_list_key_t **list
)
¶Reverse the input list of keywords.
void
(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 will not do anything.
void
(char *keynamebase
, char *filename
, gal_fits_list_key_t **list
, int top1end0
, int quiet
)
¶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 of 69 characters for the string values of a keyword254.
This creates problems with file names (which include directories) because file names/addresses can become longer than the maximum number of characters in a FITS keyword (around 70 characters).
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).
So the full file/directory address (including directories) can be longer than 69 characters.
However, if a single file or directory name (within a larger address) is longer than 69 characters, this function will truncate the name and print a warning.
If quiet!=0
, then the warning will not be printed.
void
(fitsfile *fptr
, struct wcsprm wcs
, 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.
void
(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; }
void
(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.
void
(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
.
void
(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.
void
(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).
gal_list_str_t *
(gal_list_str_t *files, char *hdu, char *name, gal_list_str_t *values)
¶Given a list of FITS file names (files
), a certain HDU (hdu
), a certain keyword name (name
), and a list of acceptable values (values
), return the subset of file names where the requested keyword name has one of the acceptable values.
gal_list_str_t *
(gal_list_str_t *files, char *hdu, char *name)
¶Given a list of FITS file names (files
), a certain HDU (hdu
), a certain keyword name (name
), return the list of unique values to that keyword name in all the files.
The limit is actually 71 characters (which is the full 80 character length, subtracted by 8 for the keyword name and one character for the =). However, for strings, FITS also requires two single quotes.
GNU Astronomy Utilities 0.20 manual, April 2023.