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
, char *hdu_option_name
)
¶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 beforehand 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 itself (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 **keylist
, char *comment
)
¶Add a DATE
keyword to the input list of keywords containing the date this function was activated in the format of YYYY-MM-DDThh:mm:ss
.
This function will also add a DATEUTC
keyword that specifies if the date is in UTC or local time (this depends on CFITSIO being able to detect UTC in the running operating system or not).
The comment of the keyword should also be specified as the second argument.
The comment is useful to inform users what this date refers to; for example the program starting time, its ending time, or etc.
For more, see the description under DATE
in Output FITS files.
void
(gal_fits_list_key_t **keylist
)
¶Add the version of Gnuastro Mandatory dependencies to the list of keywords.
Each software’s keyword has the same name as the software itself (for example GNUASTRO
or GSL
.
For the full list of software, see Output FITS files.
void
(gal_fits_list_key_t **keylist
)
¶If the optional libgit2 dependency is installed and your program is being run in a directory that is under version control, a COMMIT
keyword will be added on the top of the list of keywords.
For more, see the description of COMMIT
in Output FITS files.
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 keyword265.
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 *filename
, char *hdu
, char *hdu_option_name
, int freekeys
, int create_fits_not_exists
)
¶Write the list of keywords in keylist
into the hdu
extension of the file called filename
.
If the file may not exist before this function is activated, set create_fits_not_exists
to non-zero and set the HDU to "0"
.
If the keywords should be freed after they are written, set the freekeys
value to non-zero.
For more on hdu_option_name
see the description of gal_array_read
in Array input output.
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_list_title_add(&keylist, "Matching metadata", 0); gal_fits_key_write(keylist, filename, "1", "NONE", 1, 0); return EXIT_SUCCESS; }
void
(gal_fits_list_key_t *keylist
, fitsfile *fptr
, int freekeys
)
¶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.
gal_list_str_t *
(gal_list_str_t *files, char *hdu, char *name, gal_list_str_t *values, char *hdu_option_name)
¶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.
For more on hdu_option_name
see the description of gal_array_read
in Array input output.
gal_list_str_t *
(gal_list_str_t *files
, char *hdu
, char *name
, char *hdu_option_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.
For more on hdu_option_name
see the description of gal_array_read
in Array input output.
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.23 manual, July 2024.