gnuastro (0.22)
This is gnuastro.info, produced by makeinfo version 7.1 from
gnuastro.texi.
This book documents version 0.22 of the GNU Astronomy Utilities
(Gnuastro). Gnuastro provides various programs and libraries for
astronomical data manipulation and analysis.
Copyright © 2015-2024 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License,
Version 1.3 or any later version published by the Free Software
Foundation; with no Invariant Sections, no Front-Cover Texts, and
no Back-Cover Texts. A copy of the license is included in the
section entitled "GNU Free Documentation License".
INFO-DIR-SECTION Astronomy
START-INFO-DIR-ENTRY
* Gnuastro: (gnuastro). GNU Astronomy Utilities.
* libgnuastro: (gnuastro)Gnuastro library. Full Gnuastro library doc.
* help-gnuastro: (gnuastro)help-gnuastro mailing list. Getting help.
* bug-gnuastro: (gnuastro)Report a bug. How to report bugs
* Arithmetic: (gnuastro)Arithmetic. Arithmetic operations on pixels.
* astarithmetic: (gnuastro)Invoking astarithmetic. Options to Arithmetic.
* BuildProgram: (gnuastro)BuildProgram. Compile and run programs using Gnuastro's library.
* astbuildprog: (gnuastro)Invoking astbuildprog. Options to BuildProgram.
* ConvertType: (gnuastro)ConvertType. Convert different file types.
* astconvertt: (gnuastro)Invoking astconvertt. Options to ConvertType.
* Convolve: (gnuastro)Convolve. Convolve an input file with kernel.
* astconvolve: (gnuastro)Invoking astconvolve. Options to Convolve.
* CosmicCalculator: (gnuastro)CosmicCalculator. For cosmological params.
* astcosmiccal: (gnuastro)Invoking astcosmiccal. Options to CosmicCalculator.
* Crop: (gnuastro)Crop. Crop region(s) from image(s).
* astcrop: (gnuastro)Invoking astcrop. Options to Crop.
* Fits: (gnuastro)Fits. View and manipulate FITS extensions and keywords.
* astfits: (gnuastro)Invoking astfits. Options to Fits.
* MakeCatalog: (gnuastro)MakeCatalog. Make a catalog from labeled image.
* astmkcatalog: (gnuastro)Invoking astmkcatalog. Options to MakeCatalog.
* MakeProfiles: (gnuastro)MakeProfiles. Make mock profiles.
* astmkprof: (gnuastro)Invoking astmkprof. Options to MakeProfiles.
* Match: (gnuastro)Match. Match two separate catalogs.
* astmatch: (gnuastro)Invoking astmatch. Options to Match.
* NoiseChisel: (gnuastro)NoiseChisel. Detect signal in noise.
* astnoisechisel: (gnuastro)Invoking astnoisechisel. Options to NoiseChisel.
* Segment: (gnuastro)Segment. Segment detections based on signal structure.
* astsegment: (gnuastro)Invoking astsegment. Options to Segment.
* Query: (gnuastro)Query. Access remote databases for downloading data.
* astquery: (gnuastro)Invoking astquery. Options to Query.
* Statistics: (gnuastro)Statistics. Get image Statistics.
* aststatistics: (gnuastro)Invoking aststatistics. Options to Statistics.
* Table: (gnuastro)Table. Read and write FITS binary or ASCII tables.
* asttable: (gnuastro)Invoking asttable. Options to Table.
* Warp: (gnuastro)Warp. Warp a dataset to a new grid.
* astwarp: (gnuastro)Invoking astwarp. Options to Warp.
* astscript: (gnuastro)Installed scripts. Gnuastro's installed scripts.
* astscript-ds9-region: (gnuastro)Invoking astscript-ds9-region. Options to this script
* astscript-fits-view: (gnuastro)Invoking astscript-fits-view. Options to this script
* astscript-pointing-simulate: (gnuastro)Invoking astscript-pointing-simulate. Options to this script
* astscript-psf-scale-factor: (gnuastro)Invoking astscript-psf-scale-factor. Options to this script
* astscript-psf-select-stars: (gnuastro)Invoking astscript-psf-select-stars. Options to this script
* astscript-psf-stamp: (gnuastro)Invoking astscript-psf-stamp. Options to this script
* astscript-psf-subtract: (gnuastro)Invoking astscript-psf-subtract. Options to this script
* astscript-psf-unite: (gnuastro)Invoking astscript-psf-unite. Options to this script
* astscript-radial-profile: (gnuastro)Invoking astscript-radial-profile. Options to this script
* astscript-sort-by-night: (gnuastro)Invoking astscript-sort-by-night. Options to this script
* astscript-zeropoint: (gnuastro)Invoking astscript-zeropoint. Options to this script
END-INFO-DIR-ENTRY
File: gnuastro.info, Node: Library data container, Next: Dimensions, Prev: Library blank values, Up: Gnuastro library
12.3.6 Data container (‘data.h’)
--------------------------------
Astronomical datasets have various dimensions, for example, 1D spectra
or table columns, 2D images, or 3D Integral field data cubes. Datasets
can also have various numeric data types, depending on the
operation/purpose, for example, processed images are commonly stored in
floating point format, but their mask images are integers (allowing
bit-wise flags to identify certain classes of pixels to keep or mask,
see *note Numeric data types::). Certain other information about a
dataset are also commonly necessary, for example, the units of the
dataset, the name of the dataset and some comments. To deal with any
generic dataset, Gnuastro defines the ‘gal_data_t’ as input or output.
* Menu:
* Generic data container:: Definition of Gnuastro's generic container.
* Dataset allocation:: Allocate, initialize and free a dataset.
* Arrays of datasets:: Functions to help with array of datasets.
* Copying datasets:: Functions to copy a dataset to a new one.
File: gnuastro.info, Node: Generic data container, Next: Dataset allocation, Prev: Library data container, Up: Library data container
12.3.6.1 Generic data container (‘gal_data_t’)
..............................................
To be able to deal with any dataset (various dimensions, numeric data
types, units and higher-level structures), Gnuastro defines the
‘gal_data_t’ type which is the input/output container of choice for many
of Gnuastro library's functions. It is defined in ‘gnuastro/data.h’.
If you will be using ('‘# include’'ing) those libraries, you do not need
to include this header explicitly, it is already included by any library
header that uses ‘gal_data_t’.
-- Type (C struct): gal_data_t
The main container for datasets in Gnuastro. It can host data of
any dimensions, with any numeric data type. It is actually a
structure, but ‘typedef’'d as a new type to avoid having to write
the ‘struct’ before any declaration. The actual structure is shown
below which is followed by a description of each element.
typedef struct gal_data_t
{
void *restrict array; /* Basic array information. */
uint8_t type;
size_t ndim;
size_t *dsize;
size_t size;
int quietmmap;
char *mmapname;
size_t minmapsize;
int nwcs; /* WCS information. */
struct wcsprm *wcs;
uint8_t flag; /* Content description. */
int status;
char *name;
char *unit;
char *comment;
int disp_fmt; /* For text printing. */
int disp_width;
int disp_precision;
struct gal_data_t *next; /* For higher-level datasets. */
struct gal_data_t *block;
} gal_data_t;
The list below contains a description for each ‘gal_data_t’ element.
‘void *restrict array’
This is the pointer to the main array of the dataset containing the
raw data (values). All the other elements in this data-structure
are actually meta-data enabling us to use/understand the series of
values in this array. It must allow data of any type (see *note
Numeric data types::), so it is defined as a ‘void *’ pointer. A
‘void *’ array is not directly usable in C, so you have to cast it
to proper type before using it, please see *note Library demo -
reading a image:: for a demonstration.
The ‘restrict’ keyword was formally introduced in C99 and is used
to tell the compiler that at any moment only this pointer will
modify what it points to (a pixel in an image for example)(1).
This extra piece of information can greatly help in compiler
optimizations and thus the running time of the program. But older
compilers might not have this capability, so at ‘./configure’ time,
Gnuastro checks this feature and if the user's compiler does not
support ‘restrict’, it will be removed from this definition.
‘uint8_t type’
A fixed code (integer) used to identify the type of data in ‘array’
(see *note Numeric data types::). For the list of acceptable
values to this variable, please see *note Library data types::.
‘size_t ndim’
The dataset's number of dimensions.
‘size_t *dsize’
The size of the dataset along each dimension. This is an array
(with ‘ndim’ elements), of positive integers in row-major order(2)
(based on C). When a data file is read into memory with Gnuastro's
libraries, this array is dynamically allocated based on the number
of dimensions that the dataset has.
It is important to remember that C's row-major ordering is the
opposite of the FITS standard which is in column-major order: in
the FITS standard the fastest dimension's size is specified by
‘NAXIS1’, and slower dimensions follow. The FITS standard was
defined mainly based on the FORTRAN language which is the opposite
of C's approach to multi-dimensional arrays (and also starts
counting from 1 not 0). Hence if a FITS image has ‘NAXIS1==20’ and
‘NAXIS2==50’, the ‘dsize’ array must be filled with ‘dsize[0]==50’
and ‘dsize[1]==20’.
The fastest dimension is the one that is contiguous in memory: to
increment by one along that dimension, just go to the next element
in the array. As we go to slower dimensions, the number of memory
cells we have to skip for an increment along that dimension becomes
larger.
‘size_t size’
The total number of elements in the dataset. This is actually a
multiplication of all the values in the ‘dsize’ array, so it is not
an independent parameter. However, low-level operations with the
dataset (irrespective of its dimensions) commonly need this number,
so this element is designed to avoid calculating it every time.
‘int quietmmap’
When this value is zero, and the dataset must not be allocated in
RAM (see ‘mmapname’ and ‘minmapsize’ below), a warning will be
printed to inform the user when the file is created and when it is
deleted. The warning includes the filename, the size in bytes, and
the fact that they can toggle this behavior through ‘--minmapsize’
option in Gnuastro's programs.
‘char *mmapname’
Name of file hosting the ‘mmap’'d contents of ‘array’. If the
value of this variable is ‘NULL’, then the contents of ‘array’ are
actually stored in RAM, not in a file on the HDD/SSD. See the
description of ‘minmapsize’ below for more.
If a file is used, it will be kept in the ‘gnuastro_mmap’ directory
of the running directory. Its name is randomly selected to allow
multiple arrays at the same time, see description of ‘--minmapsize’
in *note Processing options::. When ‘gal_data_free’ is called the
randomly named file will be deleted.
‘size_t minmapsize’
The minimum size of an array (in bytes) to store the contents of
‘array’ as a file (on the non-volatile HDD/SSD), not in RAM. This
can be very useful for large datasets which can be very memory
intensive and the user's RAM might not be sufficient to
keep/process it. A random filename is assigned to the array which
is available in the ‘mmapname’ element of ‘gal_data_t’ (above), see
there for more. ‘minmapsize’ is stored in each ‘gal_data_t’, so it
can be passed on to subsequent/derived datasets.
See the description of the ‘--minmapsize’ option in *note
Processing options:: for more on using this value.
‘nwcs’
The number of WCS coordinate representations (for WCSLIB).
‘struct wcsprm *wcs’
The main WCSLIB structure keeping all the relevant information
necessary for WCSLIB to do its processing and convert data-set
positions into real-world positions. When it is given a ‘NULL’
value, all possible WCS calculations/measurements will be ignored.
‘uint8_t flag’
Bit-wise flags to describe general properties of the dataset. The
number of bytes available in this flag is stored in the
‘GAL_DATA_FLAG_SIZE’ macro. Note that you should use bit-wise
operators(3) to check these flags. The currently recognized bits
are stored in these macros:
‘GAL_DATA_FLAG_BLANK_CH’
Marking that the dataset has been checked for blank values or
not. When a dataset does not have any blank values, the
‘GAL_DATA_FLAG_HASBLANK’ bit will be zero. But upon
initialization, all bits also get a value of zero. Therefore,
a checker needs this flag to see if the value in
‘GAL_DATA_FLAG_HASBLANK’ is reliable (dataset has actually
been parsed for a blank value) or not.
Also, if it is necessary to re-check the presence of flags,
you just have to set this flag to zero and call
‘gal_blank_present’ for example, to parse the dataset and
check for blank values. Note that for improved efficiency,
when this flag is set, ‘gal_blank_present’ will not actually
parse the dataset, it will just use ‘GAL_DATA_FLAG_HASBLANK’.
‘GAL_DATA_FLAG_HASBLANK’
This bit has a value of ‘1’ when the given dataset has blank
values. If this bit is ‘0’ and ‘GAL_DATA_FLAG_BLANK_CH’ is
‘1’, then the dataset has been checked and it did not have any
blank values, so there is no more need for further checks.
‘GAL_DATA_FLAG_SORT_CH’
Marking that the dataset is already checked for being sorted
or not and thus that the possible ‘0’ values in
‘GAL_DATA_FLAG_SORTED_I’ and ‘GAL_DATA_FLAG_SORTED_D’ are
meaningful. The logic behind this is similar to that in
‘GAL_DATA_FLAG_BLANK_CH’.
‘GAL_DATA_FLAG_SORTED_I’
This bit has a value of ‘1’ when the given dataset is sorted
in an increasing manner. If this bit is ‘0’ and
‘GAL_DATA_FLAG_SORT_CH’ is ‘1’, then the dataset has been
checked and was not sorted (increasing), so there is no more
need for further checks.
‘GAL_DATA_FLAG_SORTED_D’
This bit has a value of ‘1’ when the given dataset is sorted
in a decreasing manner. If this bit is ‘0’ and
‘GAL_DATA_FLAG_SORT_CH’ is ‘1’, then the dataset has been
checked and was not sorted (decreasing), so there is no more
need for further checks.
The macro ‘GAL_DATA_FLAG_MAXFLAG’ contains the largest internally
used bit-position. Higher-level flags can be defined with the
bit-wise shift operators using this macro to define internal flags
for libraries/programs that depend on Gnuastro without causing any
possible conflict with the internal flags discussed above or having
to check the values manually on every release.
‘int status’
A context-specific status values for this data-structure. This
integer will not be set by Gnuastro's libraries. You can use it
keep some additional information about the dataset (with integer
constants) depending on your applications.
‘char *name’
The name of the dataset. If the dataset is a multi-dimensional
array and read/written as a FITS image, this will be the value in
the ‘EXTNAME’ FITS keyword. If the dataset is a one-dimensional
table column, this will be the column name. If it is set to ‘NULL’
(by default), it will be ignored.
‘char *unit’
The units of the dataset (for example, ‘BUNIT’ in the standard FITS
keywords) that will be read from or written to files/tables along
with the dataset. If it is set to ‘NULL’ (by default), it will be
ignored.
‘char *comment’
Any further explanation about the dataset which will be written to
any output file if present.
‘disp_fmt’
Format to use for printing each element of the dataset to a plain
text file, the acceptable values to this element are defined in
*note Table input output::. Based on C's ‘printf’ standards.
‘disp_width’
Width of printing each element of the dataset to a plain text file,
the acceptable values to this element are defined in *note Table
input output::. Based on C's ‘printf’ standards.
‘disp_precision’
Precision of printing each element of the dataset to a plain text
file, the acceptable values to this element are defined in *note
Table input output::. Based on C's ‘printf’ standards.
‘gal_data_t *next’
Through this pointer, you can link a ‘gal_data_t’ with other
datasets related datasets, for example, the different columns in a
dataset each have one ‘gal_data_t’ associate with them and they are
linked to each other using this element. There are several
functions described below to facilitate using ‘gal_data_t’ as a
linked list. See *note Linked lists:: for more on these wonderful
high-level constructs.
‘gal_data_t *block’
Pointer to the start of the complete allocated block of memory.
When this pointer is not ‘NULL’, the dataset is not treated as a
contiguous patch of memory. Rather, it is seen as covering only a
portion of the larger patch of memory that ‘block’ points to. See
*note Tessellation library:: for a more thorough explanation and
functions to help work with tiles that are created from this
pointer.
---------- Footnotes ----------
(1) Also see <https://en.wikipedia.org/wiki/Restrict>.
(2) Also see
<https://en.wikipedia.org/wiki/Row-_and_column-major_order>.
(3) See <https://en.wikipedia.org/wiki/Bitwise_operations_in_C>.
File: gnuastro.info, Node: Dataset allocation, Next: Arrays of datasets, Prev: Generic data container, Up: Library data container
12.3.6.2 Dataset allocation
...........................
Gnuastro's main data container was defined in *note Generic data
container::. The functions listed in this section describe the most
basic operations on ‘gal_data_t’: those related to allocation and
freeing. These functions are declared in ‘gnuastro/data.h’ which is
also visible from the function names (see *note Gnuastro library::).
-- Function:
gal_data_t *
gal_data_alloc (void *array, uint8_t type, size_t ndim, size_t
*dsize, struct wcsprm *wcs, int clear, size_t minmapsize, int
quietmmap, char *name, char *unit, char *comment)
Dynamically allocate a ‘gal_data_t’ and initialize it will all the
given values. See the description of ‘gal_data_initialize’ and
*note Generic data container:: for more information. This function
will often be the most frequently used because it allocates the
‘gal_data_t’ hosting all the values _and_ initializes it. Once you
are done with the dataset, be sure to clean up all the allocated
spaces with ‘gal_data_free’.
-- Function:
void
gal_data_initialize (gal_data_t *data, void *array, uint8_t
type, size_t ndim, size_t *dsize, struct wcsprm *wcs, int
clear, size_t minmapsize, int quietmmap, char *name, char
*unit, char *comment)
Initialize the given data structure (‘data’) with all the given
values. Note that the raw input ‘gal_data_t’ must already have
been allocated before calling this function. For a description of
each variable see *note Generic data container::. It will set the
values and do the necessary allocations. If they are not ‘NULL’,
all input arrays (‘dsize’, ‘wcs’, ‘name’, ‘unit’, ‘comment’) are
separately copied (allocated) by this function for usage in ‘data’,
so you can safely use one value to initialize many datasets or use
statically allocated variables in this function call. Once you are
done with the dataset, you can free all the allocated spaces with
‘gal_data_free_contents’.
If ‘array’ is not ‘NULL’, it will be directly copied into
‘data->array’ (based on the total number of elements calculated
from ‘dsize’) and no new space will be allocated for the array of
this dataset, this has many low-level advantages and can be used to
work on regions of a dataset instead of the whole allocated array
(see the description under ‘block’ in *note Generic data
container:: for one example). If the given pointer is not the
start of an allocated block of memory or it is used in multiple
datasets, be sure to set it to ‘NULL’ (with ‘data->array=NULL’)
before cleaning up with ‘gal_data_free_contents’.
‘ndim’ may be zero. In this case no allocation will occur,
‘data->array’ and ‘data->dsize’ will be set to ‘NULL’ and
‘data->size’ will be zero. However (when necessary) ‘dsize’ must
not have any zero values (a dimension of length zero is not
defined).
-- Function:
gal_data_t *
gal_data_alloc_empty (size_t ndim, size_t minmapsize, int
quietmmap)
Allocate an empty dataset with a certain number of dimensions, but
no 'array' component. The ‘size’ element will be set to zero and
the ‘dsize’ array will be properly allocated (based on the number
of dimensions), but all elements will be zero. This is useful in
scenarios where you just need a ‘gal_data_t’ for metadata.
-- Function:
void
gal_data_free_contents (gal_data_t *data)
Free all the non-‘NULL’ pointers in ‘gal_data_t’ except for ‘next’
and ‘block’. All freed arrays are set to ‘NULL’. If ‘data’ is
actually a tile (‘data->block!=NULL’, see *note Tessellation
library::), then ‘data->array’ is not freed. For a complete
description of ‘gal_data_t’ and its contents, see *note Generic
data container::.
-- Function:
void
gal_data_free (gal_data_t *data)
Free all the non-‘NULL’ pointers in ‘gal_data_t’, then free the
actual data structure.
File: gnuastro.info, Node: Arrays of datasets, Next: Copying datasets, Prev: Dataset allocation, Up: Library data container
12.3.6.3 Arrays of datasets
...........................
Gnuastro's generic data container (‘gal_data_t’) is a very versatile
structure that can be used in many higher-level contexts. One such
higher-level construct is an array of ‘gal_data_t’ structures to
simplify the allocation (and later cleaning) of several ‘gal_data_t’s
that are related.
For example, each column in a table is usually represented by one
‘gal_data_t’ (so it has its own name, data type, units, etc.). A table
(with many columns) can be seen as an array of ‘gal_data_t’s (when the
number of columns is known a-priori). The functions below are defined
to create a cleared array of data structures and to free them when none
are necessary any more. These functions are declared in
‘gnuastro/data.h’ which is also visible from the function names (see
*note Gnuastro library::).
-- Function:
gal_data_t *
gal_data_array_calloc (size_t size)
Allocate an array of ‘gal_data_t’ with ‘size’ elements. This
function will also initialize all the values (‘NULL’ for pointers
and 0 for other types). You can use ‘gal_data_initialize’ to fill
each element of the array afterwards. The following code snippet
is one example of doing this.
size_t i;
gal_data_t *dataarr;
dataarr=gal_data_array_calloc(10);
for(i=0;i<10;++i) gal_data_initialize(&dataarr[i], ...);
...
gal_data_array_free(dataarr, 10, 1);
-- Function:
void
gal_data_array_free (gal_data_t *dataarr, size_t num, int
free_array)
Free all the ‘num’ elements within ‘dataarr’ and the actual
allocated array. If ‘free_array’ is not zero, then the ‘array’
element of all the datasets will also be freed, see *note Generic
data container::.
-- Function:
gal_data_t **
gal_data_array_ptr_calloc (size_t size)
Allocate an array of pointers to Gnuastro's generic data structure
and initialize all pointers to ‘NULL’. This is useful when you
want to allocate individual datasets later (for example, with
‘gal_data_alloc’).
-- Function:
void
gal_data_array_ptr_free (gal_data_t **dataptr, size_t size,
int free_array);
Free all the individual datasets within the elements of ‘dataptr’,
then free ‘dataptr’ itself (the array of pointers that was probably
allocated with ‘gal_data_array_ptr_calloc’.
File: gnuastro.info, Node: Copying datasets, Prev: Arrays of datasets, Up: Library data container
12.3.6.4 Copying datasets
.........................
The functions in this section describes Gnuastro's facilities to copy a
given dataset into another. The new dataset can have a different type
(including a string), it can be already allocated (in which case only
the values will be written into it). In all these cases, if the input
dataset is a tile or a list, only the data within the given tile, or the
given node in a list, are copied. If the input is a list, the ‘next’
pointer will also be copied to the output, see *note List of
gal_data_t::.
In many of the functions here, it is possible to copy the dataset to
a new numeric data type (see *note Numeric data types::. In such cases,
Gnuastro's library is going to use the native conversion by C. So if you
are converting to a smaller type, it is up to you to make sure that the
values fit into the output type.
-- Function:
gal_data_t *
gal_data_copy (gal_data_t *in)
Return a new dataset that is a copy of ‘in’, all of ‘in’'s
meta-data will also copied into the output, except for ‘block’. If
the dataset is a tile/list, only the given tile/node will be
copied, the ‘next’ pointer will also be copied however.
-- Function:
gal_data_t *
gal_data_copy_to_new_type (gal_data_t *in, uint8_t newtype)
Return a copy of the dataset ‘in’, converted to ‘newtype’, see
*note Library data types:: for Gnuastro library's type identifiers.
The returned dataset will have all meta-data except their type and
‘block’ equal to the input's metadata. If the dataset is a
tile/list, only the given tile/node will be copied, the ‘next’
pointer will also be copied however.
-- Function:
gal_data_t *
gal_data_copy_to_new_type_free (gal_data_t *in, uint8_t
newtype)
Return a copy of the dataset ‘in’ that is converted to ‘newtype’
and free the input dataset. See *note Library data types:: for
Gnuastro library's type identifiers. The returned dataset will
have all meta-data, except their type, equal to the input's
metadata (including ‘next’). Note that if the input is a tile
within a larger block, it will not be freed. This function is
similar to ‘gal_data_copy_to_new_type’, except that it will free
the input dataset.
-- Function:
void
gal_data_copy_to_allocated (gal_data_t *in, gal_data_t *out)
Copy the contents of the array in ‘in’ into the already allocated
array in ‘out’. The types of the input and output may be
different, type conversion will be done internally. When ‘in->size
!= out->size’ this function will behave as follows:
‘out->size < in->size’
This function will not re-allocate the necessary space, it
will abort with an error, so please check before calling this
function.
‘out->size > in->size’
This function will write the values in ‘out->size’ and
‘out->dsize’ from the same values of ‘in’. So if you want to
use a pre-allocated space/dataset multiple times with varying
input sizes, be sure to reset ‘out->size’ before every call to
this function.
-- Function:
gal_data_t *
gal_data_copy_string_to_number (char *string)
Read ‘string’ into the smallest type that can store the value (see
*note Numeric data types::). This function is just a wrapper for
the ‘gal_type_string_to_number’, but will put the value into a
single-element dataset.
File: gnuastro.info, Node: Dimensions, Next: Linked lists, Prev: Library data container, Up: Gnuastro library
12.3.7 Dimensions (‘dimension.h’)
---------------------------------
An array is a contiguous region of memory. Hence, at the lowest level,
every element of an array just has one single-valued position: the
number of elements that lie between it and the first element in the
array. This is also known as the _index_ of the element within the
array. A dataset's number of dimensions is high-level abstraction
(meta-data) that we project onto that contiguous patch of memory. When
the array is interpreted as a one-dimensional dataset, this index is
also the _coordinate_ of the element. But once we associate the patch
of memory with a higher dimension, there must also be one coordinate for
each dimension.
The functions and macros in this section provide you with the tools
to convert an index into a coordinate and vice-versa along with several
other issues for example, issues with the neighbors of an element in a
multi-dimensional context.
-- Function:
size_t
gal_dimension_total_size (size_t ndim, size_t *dsize)
Return the total number of elements for a dataset with ‘ndim’
dimensions that has ‘dsize’ elements along each dimension.
-- Function:
int
gal_dimension_is_different (gal_data_t *first, gal_data_t
*second)
Return ‘1’ (one) if the two datasets do not have the same size
along all dimensions. This function will also return ‘1’ when the
number of dimensions of the two datasets are different.
-- Function:
size_t *
gal_dimension_increment (size_t ndim, size_t *dsize)
Return an allocated array that has the number of elements necessary
to increment an index along every dimension. For example, along
the fastest dimension (last element in the ‘dsize’ and returned
arrays), the value is ‘1’ (one).
-- Function:
size_t
gal_dimension_num_neighbors (size_t ndim)
The maximum number of neighbors (any connectivity) that a data
element can have in ‘ndim’ dimensions. Effectively, this function
just returns $3^n-1$ (where $n$ is the number of dimensions).
-- Function-like macro: GAL_DIMENSION_FLT_TO_INT (FLT)
Calculate the integer pixel position that the floating point ‘FLT’
number belongs to. In the FITS format (and thus in Gnuastro), the
center of each pixel is allocated on an integer (not it edge), so
the pixel which hosts a floating point number cannot simply be
found with internal type conversion.
-- Function:
void
gal_dimension_add_coords (size_t *c1, size_t *c2, size_t *out,
size_t ndim)
For every dimension, add the coordinates in ‘c1’ with ‘c2’ and put
the result into ‘out’. In other words, for dimension ‘i’ run
‘out[i]=c1[i]+c2[i];’. Hence ‘out’ may be equal to any one of ‘c1’
or ‘c2’.
-- Function:
size_t
gal_dimension_coord_to_index (size_t ndim, size_t *dsize,
size_t *coord)
Return the index (counting from zero) from the coordinates in
‘coord’ (counting from zero) assuming the dataset has ‘ndim’
elements and the size of the dataset along each dimension is in the
‘dsize’ array.
-- Function:
void
gal_dimension_index_to_coord (size_t index, size_t ndim,
size_t *dsize, size_t *coord)
Fill in the ‘coord’ array with the coordinates that correspond to
‘index’ assuming the dataset has ‘ndim’ elements and the size of
the dataset along each dimension is in the ‘dsize’ array. Note
that both ‘index’ and each value in ‘coord’ are assumed to start
from ‘0’ (zero). Also that the space which ‘coord’ points to must
already be allocated before calling this function.
-- Function:
size_t
gal_dimension_dist_manhattan (size_t *a, size_t *b, size_t
ndim)
Return the manhattan distance (see Wikipedia
(https://en.wikipedia.org/wiki/Taxicab_geometry)) between the two
coordinates ‘a’ and ‘b’ (each an array of ‘ndim’ elements).
-- Function:
float
gal_dimension_dist_radial (size_t *a, size_t *b, size_t ndim)
Return the radial distance between the two coordinates ‘a’ and ‘b’
(each an array of ‘ndim’ elements).
-- Function:
float
gal_dimension_dist_elliptical (double *center, double *pa_deg,
double *q, size_t ndim, double *point)
Return the elliptical/ellipsoidal distance of the single point
‘point’ (containing ‘ndim’ values: coordinates of the point in each
dimension) from an ellipse that is defined by ‘center’, ‘pa_deg’
and ‘q’. ‘center’ is the coordinates of the ellipse center (also
with ‘ndim’ elements). ‘pa’ is the position-angle in degrees (the
angle of the semi-major axis from the first dimension in a 2D
ellipse) and ‘q’ is the axis ratio.
In a 2D ellipse, ‘pa’ and ‘q’ are a single-element array. However,
in a 3D ellipsoid, ‘pa’ must have three elements, and ‘q’ must have
2 elements. For more see *note Defining an ellipse and
ellipsoid::.
-- Function:
gal_data_t *
gal_dimension_collapse_sum (gal_data_t *in, size_t c_dim,
gal_data_t *weight)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by summing all elements in that direction. If
‘weight!=NULL’, it must be a single-dimensional array, with the
same size as the dimension to be collapsed. The respective weight
will be multiplied to each element during the collapse.
For generality, the returned dataset will have a ‘GAL_TYPE_FLOAT64’
type. See *note Copying datasets:: for converting the returned
dataset to a desired type. Also, for more on the application of
this function, see the Arithmetic program's ‘collapse-sum’ operator
(which uses this function) in *note Arithmetic operators::.
-- Function:
gal_data_t *
gal_dimension_collapse_mean (gal_data_t *in, size_t c_dim,
gal_data_t *weight)
Similar to ‘gal_dimension_collapse_sum’ (above), but the collapse
will be done by calculating the mean along the requested dimension,
not summing over it.
-- Function:
gal_data_t *
gal_dimension_collapse_number (gal_data_t *in, size_t c_dim)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by counting how many non-blank elements there are along
that dimension.
For generality, the returned dataset will have a ‘GAL_TYPE_INT32’
type. See *note Copying datasets:: for converting the returned
dataset to a desired type. Also, for more on the application of
this function, see the Arithmetic program's ‘collapse-number’
operator (which uses this function) in *note Arithmetic
operators::.
-- Function:
gal_data_t *
gal_dimension_collapse_minmax (gal_data_t *in, size_t c_dim,
int max1_min0)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by using the largest/smallest non-blank value along
that dimension. If ‘max1_min0’ is non-zero, then the collapsed
dataset will have the maximum value along the given dimension and
if it is zero, the minimum.
-- Function:
gal_data_t *
gal_dimension_collapse_median (gal_data_t *in, size_t c_dim,
size_t numthreads, size_t minmapsize, int quietmmap)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by finding the median non-blank value along that
dimension. Since the median involves sorting, this operator
benefits from many threads (which needs to be set with
‘numthreads’). For more on ‘minmapsize’ and ‘quietmmap’ see *note
Memory management::.
-- Function:
gal_data_t *
gal_dimension_collapse_sclip_std (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by finding the standard deviation of pixels along that
dimension after sigma-clipping. Since sigma-clipping involves
sorting, this operator benefits from many threads (which needs to
be set with ‘numthreads’). For more on ‘minmapsize’ and
‘quietmmap’ see *note Memory management::. For more on sigma
clipping, see *note Sigma clipping::.
-- Function:
gal_data_t *
gal_dimension_collapse_sclip_fill_std (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Similar to ‘gal_dimension_collapse_sclip_std’, but with filled
re-clipping (see *note Filled re-clipping::).
-- Function:
gal_data_t *
gal_dimension_collapse_sclip_mad (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by finding the median absolute deviation (MAD) of
pixels along that dimension after sigma-clipping. Since
sigma-clipping involves sorting, this operator benefits from many
threads (which needs to be set with ‘numthreads’). For more on
‘minmapsize’ and ‘quietmmap’ see *note Memory management::. For
more on sigma clipping, see *note Sigma clipping::.
-- Function:
gal_data_t *
gal_dimension_collapse_sclip_fill_mad (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Similar to ‘gal_dimension_collapse_sclip_mad’, but with filled
re-clipping (see *note Filled re-clipping::).
-- Function:
gal_data_t *
gal_dimension_collapse_sclip_mean (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by finding the mean of pixels along that dimension
after sigma-clipping. Since sigma-clipping involves sorting, this
operator benefits from many threads (which needs to be set with
‘numthreads’). For more on ‘minmapsize’ and ‘quietmmap’ see *note
Memory management::. For more on sigma clipping, see *note Sigma
clipping::.
-- Function:
gal_data_t *
gal_dimension_collapse_sclip_fill_mean (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Similar to ‘gal_dimension_collapse_sclip_mean’, but with filled
re-clipping (see *note Filled re-clipping::).
-- Function:
gal_data_t *
gal_dimension_collapse_sclip_median (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by finding the median of pixels along that dimension
after sigma-clipping. Since sigma-clipping involves sorting, this
operator benefits from many threads (which needs to be set with
‘numthreads’). For more on ‘minmapsize’ and ‘quietmmap’ see *note
Memory management::. For more on sigma clipping, see *note Sigma
clipping::.
-- Function:
gal_data_t *
gal_dimension_collapse_sclip_fill_median (gal_data_t *in,
size_t c_dim, float multip, float param, size_t numthreads,
size_t minmapsize, int quietmmap)
Similar to ‘gal_dimension_collapse_sclip_median’, but with filled
re-clipping (see *note Filled re-clipping::).
-- Function:
gal_data_t *
gal_dimension_collapse_sclip_number (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by finding the number of pixels along that dimension
after sigma-clipping. Since sigma-clipping involves sorting, this
operator benefits from many threads (which needs to be set with
‘numthreads’). For more on ‘minmapsize’ and ‘quietmmap’ see *note
Memory management::. For more on sigma clipping, see *note Sigma
clipping::.
-- Function:
gal_data_t *
gal_dimension_collapse_sclip_fill_number (gal_data_t *in,
size_t c_dim, float multip, float param, size_t numthreads,
size_t minmapsize, int quietmmap)
Similar to ‘gal_dimension_collapse_sclip_number’, but with filled
re-clipping (see *note Filled re-clipping::).
-- Function:
gal_data_t *
gal_dimension_collapse_mclip_std (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by finding the standard deviation of pixels along that
dimension after median absolute deviation (MAD) clipping. Since
MAD-clipping involves sorting, this operator benefits from many
threads (which needs to be set with ‘numthreads’). For more on
‘minmapsize’ and ‘quietmmap’ see *note Memory management::. For
more on MAD-clipping, see *note MAD clipping::.
-- Function:
gal_data_t *
gal_dimension_collapse_mclip_fill_std (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Similar to ‘gal_dimension_collapse_mclip_std’, but with filled
re-clipping (see *note Filled re-clipping::).
-- Function:
gal_data_t *
gal_dimension_collapse_mclip_mad (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by finding the median absolute deviation (MAD) of
pixels along that dimension after median absolute deviation (MAD)
clipping. Since MAD-clipping involves sorting, this operator
benefits from many threads (which needs to be set with
‘numthreads’). For more on ‘minmapsize’ and ‘quietmmap’ see *note
Memory management::. For more on MAD-clipping, see *note MAD
clipping::.
-- Function:
gal_data_t *
gal_dimension_collapse_mclip_fill_mad (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Similar to ‘gal_dimension_collapse_mclip_mad’, but with filled
re-clipping (see *note Filled re-clipping::).
-- Function:
gal_data_t *
gal_dimension_collapse_mclip_mean (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by finding the mean of pixels along that dimension
after median absolute deviation (MAD) clipping. Since MAD-clipping
involves sorting, this operator benefits from many threads (which
needs to be set with ‘numthreads’). For more on ‘minmapsize’ and
‘quietmmap’ see *note Memory management::. For more on
MAD-clipping, see *note MAD clipping::.
-- Function:
gal_data_t *
gal_dimension_collapse_mclip_fill_mean (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Similar to ‘gal_dimension_collapse_mclip_mean’, but with filled
re-clipping (see *note Filled re-clipping::).
-- Function:
gal_data_t *
gal_dimension_collapse_mclip_median (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by finding the median of pixels along that dimension
after median absolute deviation (MAD) clipping. Since MAD-clipping
involves sorting, this operator benefits from many threads (which
needs to be set with ‘numthreads’). For more on ‘minmapsize’ and
‘quietmmap’ see *note Memory management::. For more on
MAD-clipping, see *note MAD clipping::.
-- Function:
gal_data_t *
gal_dimension_collapse_mclip_fill_median (gal_data_t *in,
size_t c_dim, float multip, float param, size_t numthreads,
size_t minmapsize, int quietmmap)
Similar to ‘gal_dimension_collapse_mclip_median’, but with filled
re-clipping (see *note Filled re-clipping::).
-- Function:
gal_data_t *
gal_dimension_collapse_mclip_number (gal_data_t *in, size_t
c_dim, float multip, float param, size_t numthreads, size_t
minmapsize, int quietmmap)
Collapse the input dataset (‘in’) along the given dimension
(‘c_dim’, in C definition: starting from zero, from the slowest
dimension), by finding the number of pixels along that dimension
after median absolute deviation (MAD) clipping. Since MAD-clipping
involves sorting, this operator benefits from many threads (which
needs to be set with ‘numthreads’). For more on ‘minmapsize’ and
‘quietmmap’ see *note Memory management::. For more on
MAD-clipping, see *note MAD clipping::.
-- Function:
gal_data_t *
gal_dimension_collapse_mclip_fill_number (gal_data_t *in,
size_t c_dim, float multip, float param, size_t numthreads,
size_t minmapsize, int quietmmap)
Similar to ‘gal_dimension_collapse_mclip_number’, but with filled
re-clipping (see *note Filled re-clipping::).
-- Function:
size_t
gal_dimension_remove_extra (size_t ndim, size_t *dsize, struct
wcsprm *wcs)
Remove extra dimensions (those that only have a length of 1) from
the basic size information of a dataset. ‘ndim’ is the number of
dimensions and ‘dsize’ is an array with ‘ndim’ elements containing
the size along each dimension in the C dimension order. When
‘wcs!=NULL’, the respective dimension will also be removed from the
WCS.
This function will return the new number of dimensions and the
‘dsize’ elements will contain the length along each new dimension.
-- Function-like macro: GAL_DIMENSION_NEIGHBOR_OP (index, ndim, dsize,
connectivity, dinc, operation)
Parse the neighbors of the element located at ‘index’ and do the
requested operation on them. This is defined as a macro to allow
easy definition of any operation on the neighbors of a given
element without having to use loops within your source code (the
loops are implemented by this macro). For an example of using this
function, please see *note Library demo - inspecting neighbors::.
The input arguments to this function-like macro are described
below:
‘index’
Distance of this element from the first element in the array
on a contiguous patch of memory (starting from 0), see the
discussion above.
‘ndim’
The number of dimensions associated with the contiguous patch
of memory.
‘dsize’
The full array size along each dimension. This must be an
array and is assumed to have the same number elements as
‘ndim’. See the discussion under the same element in *note
Generic data container::.
‘connectivity’
Most distant neighbors to consider. Depending on the number
of dimensions, different neighbors may be defined for each
element. This function-like macro distinguish between these
different neighbors with this argument. It has a value
between ‘1’ (one) and ‘ndim’. For example, in a 2D dataset,
4-connected neighbors have a connectivity of ‘1’ and
8-connected neighbors have a connectivity of ‘2’. Note that
this is inclusive, so in this example, a connectivity of ‘2’
will also include connectivity ‘1’ neighbors.
‘dinc’
An array keeping the length necessary to increment along each
dimension. You can make this array with the following
function. Just do not forget to free the array after you are
done with it:
size_t *dinc=gal_dimension_increment(ndim, dsize);
free(dinc);
‘dinc’ depends on ‘ndim’ and ‘dsize’, but it must be defined
outside this function-like macro since it involves allocation
to help in performance.
‘operation’
Any C operation that you would like to do on the neighbor.
This macro will provide you a ‘nind’ variable that can be used
as the index of the neighbor that is currently being studied.
It is defined as '‘size_t ndim;’'. Note that ‘operation’ will
be repeated the number of times there is a neighbor for this
element.
This macro works fully within its own ‘{}’ block and except for the
‘nind’ variable that shows the neighbor's index, all the variables
within this macro's block start with ‘gdn_’.
File: gnuastro.info, Node: Linked lists, Next: Array input output, Prev: Dimensions, Up: Gnuastro library
12.3.8 Linked lists (‘list.h’)
------------------------------
An array is a contiguous region of memory that is very efficient and
easy to use for recording and later accessing any random element as fast
as any other. This makes array the primary data container when you have
many elements (for example, an image which has millions of pixels). One
major problem with an array is that the number of elements that go into
it must be known in advance and adding or removing an element will
require a re-set of all the other elements. For example, if you want to
remove the 3rd element in a 1000 element array, all 997 subsequent
elements have to pulled back by one position, the reverse will happen if
you need to add an element.
In many contexts such situations never come up, for example, you do
not want to shift all the pixels in an image by one or two pixels from
some random position in the image: their positions have scientific
value. But in other contexts you will find yourself frequently
adding/removing an a-priori unknown number of elements. Linked lists
(or _lists_ for short) are the data-container of choice in such
situations. As in a chain, each _node_ in a list is an independent C
structure, keeping its own data along with pointer(s) to its immediate
neighbor(s). Below, you can see one simple linked list node structure
along with an ASCII art schematic of how we can use the ‘next’ pointer
to add any number of elements to the list that we want. By convention,
a list is terminated when ‘next’ is the ‘NULL’ pointer.
struct list_float /* --------- --------- */
{ /* | Value | | Value | */
float value; /* | --- | | --- | */
struct list_float *next; /* | next-|--> | next-|--> NULL */
} /* --------- --------- */
The schematic shows another great advantage of linked lists: it is
very easy to add or remove/pop a node anywhere in the list. If you want
to modify the first node, you just have to change one pointer. If it is
in the middle, you just have to change two. You initially define a
variable of this type with a ‘NULL’ pointer as shown below:
struct list_float *list=NULL;
To add or remove/pop a node from the list you can use functions provided
for the respective type in the sections below.
When you add an element to the list, it is conventionally added to the
"top" of the list: the general list pointer will point to the newly
created node, which will point to the previously created node and so on.
So when you "pop" from the top of the list, you are actually retrieving
the last value you put in and changing the list pointer to the next
youngest node. This is thus known as a "last-in-first-out" list. This
is the most efficient type of linked list (easier to implement and
faster to process). Alternatively, you can add each newly created node
at the end of the list. If you do that, you will get a
"first-in-first-out" list. But that will force you to go through the
whole list for each new element that is created (this will slow down the
processing)(1).
The node example above creates the simplest kind of a list. We can
define each node with two pointers to both the next and previous
neighbors, this is called a "Doubly linked list". In general, lists are
very powerful and simple constructs that can be very useful. But going
into more detail would be out of the scope of this short introduction in
this book. Wikipedia (https://en.wikipedia.org/wiki/Linked_list) has a
nice and more thorough discussion of the various types of lists. To
appreciate/use the beauty and elegance of these powerful constructs even
further, see Chapter 2 (Information Structures, in volume 1) of Donald
Knuth's "The art of computer programming".
In this section we will review the functions and structures that are
available in Gnuastro for working on lists. They differ by the type of
data that each node can keep. For each linked-list node structure, we
will first introduce the structure, then the functions for working on
the structure. All these structures and functions are defined and
declared in ‘gnuastro/list.h’.
* Menu:
* List of strings:: Simply linked list of strings.
* List of int32_t:: Simply linked list of int32_ts.
* List of size_t:: Simply linked list of size_ts.
* List of float:: Simply linked list of floats.
* List of double:: Simply linked list of doubles
* List of void:: Simply linked list of void * pointers.
* Ordered list of size_t:: Simply linked, ordered list of size_t.
* Doubly linked ordered list of size_t:: Definition and functions.
* List of gal_data_t:: Simply linked list Gnuastro's generic datatype.
---------- Footnotes ----------
(1) A better way to get a first-in-first-out is to first keep the
data as last-in-first-out until they are all read. Afterwards, reverse
the list by popping each node and immediately add it to the new list.
This practically reverses the last-in-first-out list to a
first-in-first-out one. All the list types discussed in this chapter
have a function with a ‘_reverse’ suffix for this job.
File: gnuastro.info, Node: List of strings, Next: List of int32_t, Prev: Linked lists, Up: Linked lists
12.3.8.1 List of strings
........................
Probably one of the most common lists you will be using are lists of
strings. They are the best tools when you are reading the user's
inputs, or when adding comments to the output files. Below you can see
Gnuastro's string list type and several functions to help in adding,
removing/popping, reversing and freeing the list.
-- Type (C struct): gal_list_str_t
A single node in a list containing a string of characters.
typedef struct gal_list_str_t
{
char *v;
struct gal_list_str_t *next;
} gal_list_str_t;
-- Function:
void
gal_list_str_add (gal_list_str_t **list, char *value, int
allocate)
Add a new node to the list of strings (‘list’) and update it. The
new node will contain the string ‘value’. If ‘allocate’ is not
zero, space will be allocated specifically for the string of the
new node and the contents of ‘value’ will be copied into it. This
can be useful when your string may be changed later in the program,
but you want your list to remain. Here is one short/simple example
of initializing and adding elements to a string list:
gal_list_str_t *list=NULL;
gal_list_str_add(&list, "bottom of list.", 1);
gal_list_str_add(&list, "second last element of list.", 1);
-- Function:
char *
gal_list_str_pop (gal_list_str_t **list)
Pop the top element of ‘list’, change ‘list’ to point to the next
node in the list, and return the string that was in the popped
node. If ‘*list==NULL’, then this function will also return a
‘NULL’ pointer.
-- Function:
size_t
gal_list_str_number (gal_list_str_t *list)
Return the number of nodes in ‘list’.
-- Function:
gal_list_str_t *
gal_list_str_last (gal_list_str_t *list)
Return a pointer to the last node in ‘list’.
-- Function:
void
gal_list_str_print (gal_list_str_t *list)
Print the strings within each node of ‘*list’ on the standard
output in the same order that they are stored. Each string is
printed on one line. This function is mainly good for
checking/debugging your program. For program outputs, it is best
to make your own implementation with a better, more user-friendly,
format. For example, the following code snippet.
size_t i=0;
gal_list_str_t *tmp;
for(tmp=list; tmp!=NULL; tmp=tmp->next)
printf("String %zu: %s\n", ++i, tmp->v);
-- Function:
void
gal_list_str_reverse (gal_list_str_t **list)
Reverse the order of the list such that the top node in the list
before calling this function becomes the bottom node after it.
-- Function:
void
gal_list_str_free (gal_list_str_t *list, int freevalue)
Free every node in ‘list’. If ‘freevalue’ is not zero, also free
the string within the nodes.
-- Function:
gal_list_str_t *
gal_list_str_extract (char *string)
Extract space-separated components of the input string. If any
space element should be kept (and not considered as a delimiter
between two tokens), precede it with a backslash (‘\’). Be aware
that in C programming, when including a backslash character within
a string literal, the correct format is indeed to use two
backslashes ("\\") to represent a single backslash:
gal_list_str_extract("bottom of\\ list");
-- Function:
char *
gal_list_str_cat (gal_list_str_t *list, char delimiter)
Concatenate (append) the input list of strings into a single string
where each node is separated from the next with the given
‘delimiter’. The space for the output string is allocated by this
function and should be freed when you have finished with it.
If there is any delimiter characters are present in any of the
elements, a backslash (‘\’) will be printed before the SPACE
character. This is necessary, otherwise, a function like
‘gal_list_str_extract’ will not be able to extract the elements
back into separate elements in a list.
File: gnuastro.info, Node: List of int32_t, Next: List of size_t, Prev: List of strings, Up: Linked lists
12.3.8.2 List of ‘int32_t’
..........................
Signed integers are the best types when you are dealing with a positive
or negative integers. The are generally useful in many contexts, for
example when you want to keep the order of a series of states (each
state stored as a given number in an ‘enum’ for example). On many
modern systems, ‘int32_t’ is just an alias for ‘int’, so you can use
them interchangeably. To make sure, check the size of ‘int’ on your
system:
-- Type (C struct): gal_list_i32_t
A single node in a list containing a 32-bit signed integer (see
*note Numeric data types::).
typedef struct gal_list_i32_t
{
int32_t v;
struct gal_list_i32_t *next;
} gal_list_i32_t;
-- Function:
void
gal_list_i32_add (gal_list_i32_t **list, int32_t value)
Add a new node (containing ‘value’) to the top of the ‘list’ of
‘int32_t’s (‘uint32_t’ is equal to ‘int’ on many modern systems),
and update ‘list’. Here is one short example of initializing and
adding elements to a string list:
gal_list_i32_t *list=NULL;
gal_list_i32_add(&list, 52);
gal_list_i32_add(&list, -4);
-- Function:
int32_t
gal_list_i32_pop (gal_list_i32_t **list)
Pop the top element of ‘list’ and return the value. This function
will also change ‘list’ to point to the next node in the list. If
‘*list==NULL’, then this function will also return
‘GAL_BLANK_INT32’ (see *note Library blank values::).
-- Function:
size_t
gal_list_i32_number (gal_list_i32_t *list)
Return the number of nodes in ‘list’.
-- Function:
size_t
gal_list_i32_last (gal_list_i32_t *list)
Return a pointer to the last node in ‘list’.
-- Function:
void
gal_list_i32_print (gal_list_i32_t *list)
Print the integers within each node of ‘*list’ on the standard
output in the same order that they are stored. Each integer is
printed on one line. This function is mainly good for
checking/debugging your program. For program outputs, it is best
to make your own implementation with a better, more user-friendly
format. For example, the following code snippet. You can also
modify it to print all values in one line, etc., depending on the
context of your program.
size_t i=0;
gal_list_i32_t *tmp;
for(tmp=list; tmp!=NULL; tmp=tmp->next)
printf("Number %zu: %s\n", ++i, tmp->v);
-- Function:
void
gal_list_i32_reverse (gal_list_i32_t **list)
Reverse the order of the list such that the top node in the list
before calling this function becomes the bottom node after it.
-- Function:
int32_t *
gal_list_i32_to_array (gal_list_i32_t *list, int reverse,
size_t *num)
Dynamically allocate an array and fill it with the values in
‘list’. The function will return a pointer to the allocated array
and put the number of elements in the array into the ‘num’ pointer.
If ‘reverse’ has a non-zero value, the array will be filled in the
opposite order of elements in ‘list’. This function can be useful
after you have finished reading an initially unknown number of
values and want to put them in an array for easy random access.
-- Function:
void
gal_list_i32_free (gal_list_i32_t *list)
Free every node in ‘list’.
File: gnuastro.info, Node: List of size_t, Next: List of float, Prev: List of int32_t, Up: Linked lists
12.3.8.3 List of ‘size_t’
.........................
The ‘size_t’ type is a unique type in C: as the name suggests it is
defined to store sizes, or more accurately, the distances between memory
locations. Hence it is always positive (an ‘unsigned’ type) and it is
directly related to the address-able spaces on the host system: on
32-bit and 64-bit systems it is an alias for ‘uint32_t’ and ‘uint64_t’,
respectively (see *note Numeric data types::).
‘size_t’ is the default compiler type to index an array (recall that
an array index in C is just a pointer increment of a given _size_).
Since it is unsigned, it is a great type for counting (where negative is
not defined), you are always sure it will never exceed the system's
(virtual) memory and since its name has the word "size" inside it, it
provides a good level of documentation(1). In Gnuastro, we do all
counting and array indexing with this type, so this list is very handy.
As discussed above, ‘size_t’ maps to different types on different
machines, so a portable way to print them with ‘printf’ is to use C99's
‘%zu’ format.
-- Type (C struct): gal_list_sizet_t
A single node in a list containing a ‘size_t’ value (which maps to
‘uint32_t’ or ‘uint64_t’ on 32-bit and 64-bit systems), see *note
Numeric data types::.
typedef struct gal_list_sizet_t
{
size_t v;
struct gal_list_sizet_t *next;
} gal_list_sizet_t;
-- Function:
void
gal_list_sizet_add (gal_list_sizet_t **list, size_t value)
Add a new node (containing ‘value’) to the top of the ‘list’ of
‘size_t’s and update ‘list’. Here is one short example of
initializing and adding elements to a string list:
gal_list_sizet_t *list=NULL;
gal_list_sizet_add(&list, 45493);
gal_list_sizet_add(&list, 930484);
-- Function:
sizet_t
gal_list_sizet_pop (gal_list_sizet_t **list)
Pop the top element of ‘list’ and return the value. This function
will also change ‘list’ to point to the next node in the list. If
‘*list==NULL’, then this function will also return
‘GAL_BLANK_SIZE_T’ (see *note Library blank values::).
-- Function:
size_t
gal_list_sizet_number (gal_list_sizet_t *list)
Return the number of nodes in ‘list’.
-- Function:
size_t
gal_list_sizet_last (gal_list_sizet_t *list)
Return a pointer to the last node in ‘list’.
-- Function:
void
gal_list_sizet_print (gal_list_sizet_t *list)
Print the values within each node of ‘*list’ on the standard output
in the same order that they are stored. Each integer is printed on
one line. This function is mainly good for checking/debugging your
program. For program outputs, it is best to make your own
implementation with a better, more user-friendly format. For
example, the following code snippet. You can also modify it to
print all values in one line, etc., depending on the context of
your program.
size_t i=0;
gal_list_sizet_t *tmp;
for(tmp=list; tmp!=NULL; tmp=tmp->next)
printf("Number %zu: %zu\n", ++i, tmp->v);
-- Function:
void
gal_list_sizet_reverse (gal_list_sizet_t **list)
Reverse the order of the list such that the top node in the list
before calling this function becomes the bottom node after it.
-- Function:
size_t *
gal_list_sizet_to_array (gal_list_sizet_t *list, int reverse,
size_t *num)
Dynamically allocate an array and fill it with the values in
‘list’. The function will return a pointer to the allocated array
and put the number of elements in the array into the ‘num’ pointer.
If ‘reverse’ has a non-zero value, the array will be filled in the
inverse of the order of elements in ‘list’. This function can be
useful after you have finished reading an initially unknown number
of values and want to put them in an array for easy random access.
-- Function:
void
gal_list_sizet_free (gal_list_sizet_t *list)
Free every node in ‘list’.
---------- Footnotes ----------
(1) So you know that a variable of this type is not used to store
some generic state for example.
File: gnuastro.info, Node: List of float, Next: List of double, Prev: List of size_t, Up: Linked lists
12.3.8.4 List of ‘float’
........................
Single precision floating point numbers can accurately store real number
until 7.2 decimals and only consume 4 bytes (32-bits) of memory, see
*note Numeric data types::. Since astronomical data rarely reach that
level of precision, single precision floating points are the type of
choice to keep and read data. However, when processing the data, it is
best to use double precision floating points (since errors propagate).
-- Type (C struct): gal_list_f32_t
A single node in a list containing a 32-bit single precision
‘float’ value: see *note Numeric data types::.
typedef struct gal_list_f32_t
{
float v;
struct gal_list_f32_t *next;
} gal_list_f32_t;
-- Function:
void
gal_list_f32_add (gal_list_f32_t **list, float value)
Add a new node (containing ‘value’) to the top of the ‘list’ of
‘float’s and update ‘list’. Here is one short example of
initializing and adding elements to a string list:
gal_list_f32_t *list=NULL;
gal_list_f32_add(&list, 3.89);
gal_list_f32_add(&list, 1.23e-20);
-- Function:
float
gal_list_f32_pop (gal_list_f32_t **list)
Pop the top element of ‘list’ and return the value. This function
will also change ‘list’ to point to the next node in the list. If
‘*list==NULL’, then this function will return ‘GAL_BLANK_FLOAT32’
(NaN, see *note Library blank values::).
-- Function:
size_t
gal_list_f32_number (gal_list_f32_t *list)
Return the number of nodes in ‘list’.
-- Function:
size_t
gal_list_f32_last (gal_list_f32_t *list)
Return a pointer to the last node in ‘list’.
-- Function:
void
gal_list_f32_print (gal_list_f32_t *list)
Print the values within each node of ‘*list’ on the standard output
in the same order that they are stored. Each floating point number
is printed on one line. This function is mainly good for
checking/debugging your program. For program outputs, it is best
to make your own implementation with a better, more user-friendly
format. For example, in the following code snippet. You can also
modify it to print all values in one line, etc., depending on the
context of your program.
size_t i=0;
gal_list_f32_t *tmp;
for(tmp=list; tmp!=NULL; tmp=tmp->next)
printf("Number %zu: %f\n", ++i, tmp->v);
-- Function:
void
gal_list_f32_reverse (gal_list_f32_t **list)
Reverse the order of the list such that the top node in the list
before calling this function becomes the bottom node after it.
-- Function:
float *
gal_list_f32_to_array (gal_list_f32_t *list, int reverse,
size_t *num)
Dynamically allocate an array and fill it with the values in
‘list’. The function will return a pointer to the allocated array
and put the number of elements in the array into the ‘num’ pointer.
If ‘reverse’ has a non-zero value, the array will be filled in the
inverse of the order of elements in ‘list’. This function can be
useful after you have finished reading an initially unknown number
of values and want to put them in an array for easy random access.
-- Function:
void
gal_list_f32_free (gal_list_f32_t *list)
Free every node in ‘list’.
File: gnuastro.info, Node: List of double, Next: List of void, Prev: List of float, Up: Linked lists
12.3.8.5 List of ‘double’
.........................
Double precision floating point numbers can accurately store real number
until 15.9 decimals and consume 8 bytes (64-bits) of memory, see *note
Numeric data types::. This level of precision makes them very good for
serious processing in the middle of a program's execution: in many
cases, the propagation of errors will still be insignificant compared to
actual observational errors in a data set. But since they consume 8
bytes and more CPU processing power, they are often not the best choice
for storing and transferring of data.
-- Type (C struct): gal_list_f64_t
A single node in a list containing a 64-bit double precision
‘double’ value: see *note Numeric data types::.
typedef struct gal_list_f64_t
{
double v;
struct gal_list_f64_t *next;
} gal_list_f64_t;
-- Function:
void
gal_list_f64_add (gal_list_f64_t **list, double value)
Add a new node (containing ‘value’) to the top of the ‘list’ of
‘double’s and update ‘list’. Here is one short example of
initializing and adding elements to a string list:
gal_list_f64_t *list=NULL;
gal_list_f64_add(&list, 3.8129395763193);
gal_list_f64_add(&list, 1.239378923931e-20);
-- Function:
double
gal_list_f64_pop (gal_list_f64_t **list)
Pop the top element of ‘list’ and return the value. This function
will also change ‘list’ to point to the next node in the list. If
‘*list==NULL’, then this function will return ‘GAL_BLANK_FLOAT64’
(NaN, see *note Library blank values::).
-- Function:
size_t
gal_list_f64_number (gal_list_f64_t *list)
Return the number of nodes in ‘list’.
-- Function:
size_t
gal_list_f64_last (gal_list_f64_t *list)
Return a pointer to the last node in ‘list’.
-- Function:
void
gal_list_f64_print (gal_list_f64_t *list)
Print the values within each node of ‘*list’ on the standard output
in the same order that they are stored. Each floating point number
is printed on one line. This function is mainly good for
checking/debugging your program. For program outputs, it is best
to make your own implementation with a better, more user-friendly
format. For example, in the following code snippet. You can also
modify it to print all values in one line, etc., depending on the
context of your program.
size_t i=0;
gal_list_f64_t *tmp;
for(tmp=list; tmp!=NULL; tmp=tmp->next)
printf("Number %zu: %f\n", ++i, tmp->v);
-- Function:
void
gal_list_f64_reverse (gal_list_f64_t **list)
Reverse the order of the list such that the top node in the list
before calling this function becomes the bottom node after it.
-- Function:
double *
gal_list_f64_to_array (gal_list_f64_t *list, int reverse,
size_t *num)
Dynamically allocate an array and fill it with the values in
‘list’. The function will return a pointer to the allocated array
and put the number of elements in the array into the ‘num’ pointer.
If ‘reverse’ has a non-zero value, the array will be filled in the
inverse of the order of elements in ‘list’. This function can be
useful after you have finished reading an initially unknown number
of values and want to put them in an array for easy random access.
-- Function:
gal_data_t *
gal_list_f64_to_data (gal_list_f64_t *list, uint8_t type,
size_t minmapsize, int quietmmap)
Write the values in the given ‘list’ into a ‘gal_data_t’ dataset of
the requested ‘type’. The order of the values in the dataset will
be the same as the order from the top of the list.
-- Function:
void
gal_list_f64_free (gal_list_f64_t *list)
Free every node in ‘list’.
File: gnuastro.info, Node: List of void, Next: Ordered list of size_t, Prev: List of double, Up: Linked lists
12.3.8.6 List of ‘void *’
.........................
In C, ‘void *’ is the most generic pointer. Usually pointers are
associated with the type of content they point to. For example, ‘int *’
means a pointer to an integer. This ancillary information about the
contents of the memory location is very useful for the compiler,
catching bad errors and also documentation (it helps the reader see what
the address in memory actually contains). However, ‘void *’ is just a
raw address (pointer), it contains no information on the contents it
points to.
These properties make the ‘void *’ very useful when you want to treat
the contents of an address in different ways. You can use the ‘void *’
list defined in this section and its function on any kind of data: for
example, you can use it to keep a list of custom data structures that
you have built for your own separate program. Each node in the list can
keep anything and this gives you great versatility. But in using ‘void
*’, please beware that "with great power comes great responsibility".
-- Type (C struct): gal_list_void_t
A single node in a list containing a ‘void *’ pointer.
typedef struct gal_list_void_t
{
void *v;
struct gal_list_void_t *next;
} gal_list_void_t;
-- Function:
void
gal_list_void_add (gal_list_void_t **list, void *value)
Add a new node (containing ‘value’) to the top of the ‘list’ of
‘void *’s and update ‘list’. Here is one short example of
initializing and adding elements to a string list:
gal_list_void_t *list=NULL;
gal_list_f64_add(&list, some_pointer);
gal_list_f64_add(&list, another_pointer);
-- Function:
void *
gal_list_void_pop (gal_list_void_t **list)
Pop the top element of ‘list’ and return the value. This function
will also change ‘list’ to point to the next node in the list. If
‘*list==NULL’, then this function will return ‘NULL’.
-- Function:
size_t
gal_list_void_number (gal_list_void_t *list)
Return the number of nodes in ‘list’.
-- Function:
size_t
gal_list_void_last (gal_list_void_t *list)
Return a pointer to the last node in ‘list’.
-- Function:
void
gal_list_void_reverse (gal_list_void_t **list)
Reverse the order of the list such that the top node in the list
before calling this function becomes the bottom node after it.
-- Function:
void
gal_list_void_free (gal_list_void_t *list)
Free every node in ‘list’.
File: gnuastro.info, Node: Ordered list of size_t, Next: Doubly linked ordered list of size_t, Prev: List of void, Up: Linked lists
12.3.8.7 Ordered list of ‘size_t’
.................................
Positions/sizes in a dataset are conventionally in the ‘size_t’ type
(see *note List of size_t::) and it sometimes occurs that you want to
parse and read the values in a specific order. For example, you want to
start from one pixel and add pixels to the list based on their distance
to that pixel. So that ever time you pop an element from the list, you
know it is the nearest that has not yet been studied. The
‘gal_list_osizet_t’ type and its functions in this section are designed
to facilitate such operations.
-- Type (C struct): gal_list_osizet_t
Each node in this singly-linked list contains a ‘size_t’ value and
a floating point value. The floating point value is used as a
reference to add new nodes in a sorted manner. At any moment, the
first popped node in this list will have the smallest ‘tosort’
value, and subsequent nodes will have larger to values.
typedef struct gal_list_osizet_t
{
size_t v; /* The actual value. */
float s; /* The parameter to sort by. */
struct gal_list_osizet_t *next;
} gal_list_osizet_t;
-- Function:
void
gal_list_osizet_add (gal_list_osizet_t **list, size_t value,
float tosort)
Allocate space for a new node in ‘list’, and store ‘value’ and
‘tosort’ into it. The new node will not necessarily be at the
"top" of the list. If ‘*list!=NULL’, then the ‘tosort’ values of
existing nodes is inspected and the given node is placed in the
list such that the top element (which is popped with
‘gal_list_osizet_pop’) has the smallest ‘tosort’ value.
-- Function:
size_t
gal_list_osizet_pop (gal_list_osizet_t **list, float
*sortvalue)
Pop a node from the top of ‘list’, return the node's ‘value’ and
put its sort value in the space that ‘sortvalue’ points to. This
function will also free the allocated space for the popped node and
after this function, ‘list’ will point to the next node (which has
a larger ‘tosort’ element).
-- Function:
void
gal_list_osizet_to_sizet_free (gal_list_osizet_t *in,
gal_list_sizet_t **out)
Convert the ordered list of ‘size_t’s into an ordinary ‘size_t’
linked list. This can be useful when all the elements have been
added and you just need to pop-out elements and do not care about
the sorting values any more. After the conversion is done, this
function will free the input list. Note that the ‘out’ list does
not have to be empty. If it already contains some nodes, the new
nodes will be added on top of them.
File: gnuastro.info, Node: Doubly linked ordered list of size_t, Next: List of gal_data_t, Prev: Ordered list of size_t, Up: Linked lists
12.3.8.8 Doubly linked ordered list of ‘size_t’
...............................................
An ordered list of indices is required in many contexts, one example was
discussed at the beginning of *note Ordered list of size_t::. But the
list that was introduced there only has one point of entry: you can
always only parse the list from smallest to largest. In this section,
the doubly-linked ‘gal_list_dosizet_t’ node is defined which will allow
us to parse the values in ascending or descending order.
-- Type (C struct): gal_list_dosizet_t
Doubly-linked, ordered ‘size_t’ list node structure. Each node in
this Doubly-linked list contains a ‘size_t’ value and a floating
point value. The floating point value is used as a reference to
add new nodes in a sorted manner. In the functions here, this
linked list can be pointed to by two pointers (largest and
smallest) with the following format:
largest pointer
|
NULL <-- (v0,s0) <--> (v1,s1) <--> ... (vn,sn) --> NULL
|
smallest pointer
At any moment, the two pointers will point to the nodes containing
the "largest" and "smallest" values and the rest of the nodes will
be sorted. This is useful when an unknown number of nodes are
being added continuously and during the operations it is important
to have the nodes in a sorted format.
typedef struct gal_list_dosizet_t
{
size_t v; /* The actual value. */
float s; /* The parameter to sort by. */
struct gal_list_dosizet_t *prev;
struct gal_list_dosizet_t *next;
} gal_list_dosizet_t;
-- Function:
void
gal_list_dosizet_add (gal_list_dosizet_t **largest,
gal_list_dosizet_t **smallest, size_t value, float tosort)
Allocate space for a new node in ‘list’, and store ‘value’ and
‘tosort’ into it. If the list is empty, both ‘largest’ and
‘smallest’ must be ‘NULL’.
-- Function:
size_t
gal_list_dosizet_pop_smallest (gal_list_dosizet_t **largest,
gal_list_dosizet_t **smallest, float tosort)
Pop the value with the smallest reference from the doubly linked
list and store the reference into the space pointed to by ‘tosort’.
Note that even though only the smallest pointer will be popped,
when there was only one node in the list, the ‘largest’ pointer
also has to change, so we need both.
-- Function:
void
gal_list_dosizet_print (gal_list_dosizet_t *largest,
gal_list_dosizet_t *smallest)
Print the largest and smallest values sequentially until the list
is parsed.
-- Function:
void
gal_list_dosizet_to_sizet (gal_list_dosizet_t *in,
gal_list_sizet_t **out)
Convert the doubly linked, ordered ‘size_t’ list into a
singly-linked list of ‘size_t’.
-- Function:
void
gal_list_dosizet_free (gal_list_dosizet_t *largest)
Free the doubly linked, ordered ‘sizet_t’ list.
File: gnuastro.info, Node: List of gal_data_t, Prev: Doubly linked ordered list of size_t, Up: Linked lists
12.3.8.9 List of ‘gal_data_t’
.............................
Gnuastro's generic data container has a ‘next’ element which enables it
to be used as a singly-linked list (see *note Generic data container::).
The ability to connect the different data containers offers great
advantages. For example, each column in a table in an independent
dataset: with its own name, units, numeric data type (see *note Numeric
data types::). Another application is in Tessellating an input dataset
into separate tiles or only studying particular regions, or tiles, of a
larger dataset (see *note Tessellation:: and *note Tessellation
library::). Each independent tile over the dataset can be connected to
the others as a linked list and thus any number of tiles can be
represented with one variable.
-- Function:
void
gal_list_data_add (gal_data_t **list, gal_data_t *newnode)
Add an already allocated dataset (‘newnode’) to top of ‘list’.
Note that if ‘newnode->next!=NULL’ (‘newnode’ is itself a list),
then ‘list’ will be added to its end.
In this example multiple images are linked together as a list:
int quietmmap=1;
size_t minmapsize=-1;
gal_data_t *tmp, *list=NULL;
tmp = gal_fits_img_read("file1.fits", "1", minmapsize, quietmmap,
NULL);
gal_list_data_add( &list, tmp );
tmp = gal_fits_img_read("file2.fits", "1", minmapsize, quietmmap,
NULL);
gal_list_data_add( &list, tmp );
-- Function:
void
gal_list_data_add_alloc (gal_data_t **list, void *array,
uint8_t type, size_t ndim, size_t *dsize, struct wcsprm *wcs,
int clear, size_t minmapsize, int quietmmap, char *name, char
*unit, char *comment)
Allocate a new dataset (with ‘gal_data_alloc’ in *note Dataset
allocation::) and put it as the first element of ‘list’. Note that
if this is the first node to be added to the list, ‘list’ must be
‘NULL’.
-- Function:
gal_data_t *
gal_list_data_pop (gal_data_t **list)
Pop the top node from ‘list’ and return it.
-- Function:
void
gal_list_data_remove (gal_data_t **list, gal_data_t *node)
Remove ‘node’ from the given ‘list’. After finding the given node,
this function will just set ‘node->next=NULL’ and correct the
‘next’ node of its previous element to its next element (thus
"removing" it from the list). If ‘node’ doesn't exist in the list,
this function won't make any change to list.
-- Function:
gal_data_t *
gal_list_data_select_by_name (gal_data_t *list, char *name)
Select the dataset within the list, that has a ‘name’ element that
is identical (case-sensitive) to the given ‘name’. If not found, a
‘NULL’ pointer will be returned.
Note that this dataset will not be popped from the list, only a
pointer to it will be returned and if you free it or change its
‘next’ element, it may harm your original list.
-- Function:
gal_data_t *
gal_list_data_select_by_id (gal_data_t *table, char *idstr,
size_t *index)
Select the dataset within the list that can be identified with the
string given to ‘idstr’ (which can be a counter, starting from 1,
or a name). If not found, a ‘NULL’ pointer will be returned.
Note that this dataset will not be popped from the list, only a
pointer to it will be returned and if you free it or change its
‘next’ element, it may harm your original list.
-- Function:
void
gal_list_data_reverse (gal_data_t **list)
Reverse the order of the list such that the top node in the list
before calling this function becomes the bottom node after it.
-- Function:
gal_data_t **
gal_list_data_to_array_ptr (gal_data_t *list, size_t *num)
Allocate and return an array of ‘gal_data_t *’ pointers with the
same number of elements as the nodes in ‘list’. The pointers will
be put in the same order that the list is parsed. Hence the N-th
element in the array will point to the same dataset that the N-th
node in the list points to.
-- Function:
size_t
gal_list_data_number (gal_data_t *list)
Return the number of nodes in ‘list’.
-- Function:
gal_data_t *
gal_list_data_last (gal_data_t *list)
Return a pointer to the last node in ‘list’.
-- Function:
void
gal_list_data_free (gal_data_t *list)
Free all the datasets in ‘list’ along with all the allocated spaces
in each.
File: gnuastro.info, Node: Array input output, Next: Table input output, Prev: Linked lists, Up: Gnuastro library
12.3.9 Array input output
-------------------------
Getting arrays (commonly images or cubes) from a file into your program
or writing them after the processing into an output file are some of the
most common operations. The functions in this section are designed for
such operations with the known file types. The functions here are thus
just wrappers around functions of lower-level file type functions of
this library, for example, *note FITS files:: or *note TIFF files::. If
the file type of the input/output file is already known, you can use the
functions in those sections respectively.
-- Function:
int
gal_array_name_recognized (char *filename)
Return 1 if the given file name corresponds to one of the
recognized file types for reading arrays.
-- Function:
int
gal_array_name_recognized_multiext (char *filename)
Return 1 if the given file name corresponds to one of the
recognized file types for reading arrays which may contain multiple
extensions (for example FITS or TIFF) formats.
-- Function:
int
gal_array_file_recognized (char *filename)
Similar to ‘gal_array_name_recognized’, but for FITS files, it will
also check the contents of the file if the recognized file name
suffix is not found. See the description of
‘gal_fits_file_recognized’ for more (*note FITS macros errors
filenames::).
-- Function:
gal_data_t
gal_array_read (char *filename, char *extension,
gal_list_str_t *lines, size_t minmapsize, int quietmmap, char
*hdu_option_name)
Read the array within the given extension (‘extension’) of
‘filename’, or the ‘lines’ list (see below). If the array is
larger than ‘minmapsize’ bytes, then it will not be read into RAM,
but a file on the HDD/SSD (no difference for the programmer).
Messages about the memory-mapped file can be disabled with
‘quietmmap’.
‘extension’ will be ignored for files that do not support them (for
example JPEG or text). For FITS files, ‘extension’ can be a number
or a string (name of the extension), but for TIFF files, it has to
be number. In both cases, counting starts from zero.
For multi-channel formats (like RGB images in JPEG or TIFF), this
function will return a *note List of gal_data_t::: one data
structure per channel. Thus if you just want a single array (and
want to check if the user has not given a multi-channel input), you
can check the ‘next’ pointer of the returned ‘gal_data_t’.
‘lines’ is a list of strings with each node representing one line
(including the new-line character), see *note List of strings::.
It will mostly be the output of ‘gal_txt_stdin_read’, which is used
to read the program's input as separate lines from the standard
input (see *note Text files::). Note that ‘filename’ and ‘lines’
are mutually exclusive and one of them must be ‘NULL’.
‘hdu_option_name’ is used in error messages related to extensions
(e.g., HDUs in FITS) and is expected to be the command-line option
name that users of your program can specify to select an input HDU
for this particular input; for example, if the kernel is used as
the input, users should determine ‘--khdu’ for this option. If the
given ‘extension’ doesn't exist in ‘filename’, a descriptive error
message is printed instructing the users how to find and fix the
problem. This error message also suggests the option to use in
order to help users of your program to inform them what option they
should give a HDU to. If you don't have an option that is
configured by the users of your program, you can set this to ‘NONE’
or ‘NULL’.
-- Function:
void
gal_array_read_to_type (char *filename, char *extension,
gal_list_str_t *lines, uint8_t type, size_t minmapsize, int
quietmmap, char *hdu_option_name)
Similar to ‘gal_array_read’, but the output data structure(s) will
have a numeric data type of ‘type’, see *note Numeric data types::.
-- Function:
void
gal_array_read_one_ch (char *filename, char *extension,
gal_list_str_t *lines, size_t minmapsize, int quietmmap, char
*hdu_option_name)
Read the dataset within ‘filename’ (extension/hdu/dir ‘extension’)
and make sure it is only a single channel. This is just a simple
wrapper around ‘gal_array_read’ that checks if there was more than
one dataset and aborts with an informative error if there is more
than one channel in the dataset.
Formats like JPEG or TIFF support multiple channels per input, but
it may happen that your program only works on a single dataset.
This function can be a convenient way to make sure that the data
that comes into your program is only one channel.
Regarding ‘*hdu_option_name’, see the description for the same
argument in the description of ‘gal_array_read’.
-- Function:
void
gal_array_read_one_ch_to_type (char *filename, char
*extension, gal_list_str_t *lines, uint8_t type, size_t
minmapsize, int quietmmap, char *hdu_option_name)
Similar to ‘gal_array_read_one_ch’, but the output data structure
will has a numeric data type of ‘type’, see *note Numeric data
types::.
File: gnuastro.info, Node: Table input output, Next: FITS files, Prev: Array input output, Up: Gnuastro library
12.3.10 Table input output (‘table.h’)
--------------------------------------
Tables are a collection of one dimensional datasets that are packed
together into one file. They are the single most common format to store
high-level (processed) information, hence they play a very important
role in Gnuastro. For a more thorough introduction, please see *note
Table::. Gnuastro's Table program, and all the other programs that can
read from and write into tables, use the functions of this section for
reading and writing their input/output tables. For a simple
demonstration of using the constructs introduced here, see *note Library
demo - reading and writing table columns::.
Currently only plain text (see *note Gnuastro text table format::)
and FITS (ASCII and binary) tables are supported by Gnuastro. However,
the low-level table infra-structure is written such that accommodating
other formats is also possible and in future releases more formats will
hopefully be supported. Please do not hesitate to suggest your favorite
format so it can be implemented when possible.
-- Macro: GAL_TABLE_DEF_WIDTH_STR
-- Macro: GAL_TABLE_DEF_WIDTH_INT
-- Macro: GAL_TABLE_DEF_WIDTH_LINT
-- Macro: GAL_TABLE_DEF_WIDTH_FLT
-- Macro: GAL_TABLE_DEF_WIDTH_DBL
-- Macro: GAL_TABLE_DEF_PRECISION_INT
-- Macro: GAL_TABLE_DEF_PRECISION_FLT
-- Macro: GAL_TABLE_DEF_PRECISION_DBL
The default width and precision for generic types to use in writing
numeric types into a text file (plain text and FITS ASCII tables).
When the dataset does not have any pre-set width and precision (see
‘disp_width’ and ‘disp_precision’ in *note Generic data
container::) these will be directly used in C's ‘printf’ command to
write the number as a string.
-- Macro: GAL_TABLE_DISPLAY_FMT_STRING
-- Macro: GAL_TABLE_DISPLAY_FMT_DECIMAL
-- Macro: GAL_TABLE_DISPLAY_FMT_UDECIMAL
-- Macro: GAL_TABLE_DISPLAY_FMT_OCTAL
-- Macro: GAL_TABLE_DISPLAY_FMT_HEX
-- Macro: GAL_TABLE_DISPLAY_FMT_FIXED
-- Macro: GAL_TABLE_DISPLAY_FMT_EXP
-- Macro: GAL_TABLE_DISPLAY_FMT_GENERAL
The display format used in C's ‘printf’ to display data of
different types. The ‘_STRING’ and ‘_DECIMAL’ are unique for
printing strings and signed integers, they are mainly here for
completeness. However, unsigned integers and floating points can
be displayed in multiple formats:
Unsigned integer
For unsigned integers, it is possible to choose from
‘_UDECIMAL’ (unsigned decimal), ‘_OCTAL’ (octal notation, for
example, ‘125’ in decimal will be displayed as ‘175’), and
‘_HEX’ (hexadecimal notation, for example, ‘125’ in decimal
will be displayed as ‘7D’).
Floating point
For floating point, it is possible to display the number in
‘_FLOAT’ (floating point, for example, ‘1500.345’), ‘_EXP’
(exponential, for example, ‘1.500345e+03’), or ‘_GENERAL’
which is the best of the two for the given number.
-- Macro: GAL_TABLE_FORMAT_INVALID
-- Macro: GAL_TABLE_FORMAT_TXT
-- Macro: GAL_TABLE_FORMAT_AFITS
-- Macro: GAL_TABLE_FORMAT_BFITS
All the current acceptable table formats to Gnuastro. The ‘AFITS’
and ‘BFITS’ represent FITS ASCII tables and FITS Binary tables.
You can use these anywhere you see the ‘tableformat’ variable.
-- Macro: GAL_TABLE_SEARCH_INVALID
-- Macro: GAL_TABLE_SEARCH_NAME
-- Macro: GAL_TABLE_SEARCH_UNIT
-- Macro: GAL_TABLE_SEARCH_COMMENT
When the desired column is not a number, these values determine if
the string to match, or regular expression to search, be in the
_name_, _units_ or _comments_ of the column metadata. These values
should be used for the ‘searchin’ variables of the functions.
-- Function:
uint8_t
gal_table_displayflt_from_str (char *string)
Convert the input ‘string’ into one of the
‘GAL_TABLE_DISPLAY_FMT_FIXED’ (for fixed-point notation) or
‘GAL_TABLE_DISPLAY_FMT_EXP’ (for exponential notation).
-- Function:
char *
gal_table_displayflt_to_str (uint8_t id)
Convert the input identifier (one of the
‘GAL_TABLE_DISPLAY_FMT_FIXED’; for fixed-point notation, or
‘GAL_TABLE_DISPLAY_FMT_EXP’; for exponential notation) into a
standard string that is used to identify them.
-- Function:
gal_data_t *
gal_table_info (char *filename, char *hdu, gal_list_str_t
*lines, size_t *numcols, size_t *numrows, int *tableformat)
Store the information of each column of a table into an array of
meta-data ‘gal_data_t’s. In a metadata ‘gal_data_t’, the size
elements are zero (‘ndim=size=0’ and ‘dsize=NULL’) but other
relevant elements are filled). See the end of this description for
the exact components of each ‘gal_data_t’ that are filled.
The returned array of ‘gal_data_t’s has ‘numcols’ datasets (one
data structure for each column). The number of rows in each
dataset is stored in ‘numrows’ (in a table, all the columns have
the same number of rows). The format of the table (e.g., ASCII
text file, or FITS binary or ASCII table) will be put in
‘tableformat’ (macros defined above). If the ‘filename’ is not a
FITS file, then ‘hdu’ will not be used (can be ‘NULL’).
The input must be either a file (specified by ‘filename’) or a list
of strings (‘lines’). ‘lines’ is a list of strings with each node
representing one line (including the new-line character), see *note
List of strings::. It will mostly be the output of
‘gal_txt_stdin_read’, which is used to read the program's input as
separate lines from the standard input (see *note Text files::).
Note that ‘filename’ and ‘lines’ are mutually exclusive and one of
them must be ‘NULL’.
In the output datasets, only the meta-data strings (column name,
units and comments), will be allocated and set as shown below.
This function is just for column information (meta-data), not
column contents.
*restrict array -> Blank value (if present, in col's own type).
type -> Type of column data.
ndim -> 0
*dsize -> NULL
size -> 0
quietmmap -> ------------
*mmapname -> ------------
minmapsize -> Repeat (length of vector; 1 if not vector).
nwcs -> ------------
*wcs -> ------------
flag -> 'GAL_TABLEINTERN_FLAG_*' macros.
status -> ------------
*name -> Column name.
*unit -> Column unit.
*comment -> Column comments.
disp_fmt -> 'GAL_TABLE_DISPLAY_FMT' macros.
disp_width -> Width of string columns.
disp_precision -> ------------
*next -> Pointer to next column's metadata
*block -> ------------
-- Function:
void
gal_table_print_info (gal_data_t *allcols, size_t numcols,
size_t numrows, char *hdu_option_name)
Print the column information for all the columns (output of
‘gal_table_info’) to standard output. The output is in the same
format as this command with Gnuastro Table program (see *note
Invoking asttable::):
$ asttable --info table.fits
-- Function:
gal_data_t *
gal_table_read (char *filename, char *hdu, gal_list_str_t
*lines, gal_list_str_t *cols, int searchin, int ignorecase,
size_t numthreads, size_t minmapsize, int quietmmap, size_t
*colmatch, char *hdu_option_name)
Read the specified columns in a file (named ‘filename’), or list of
strings (‘lines’) into a linked list of data structures. If the
file is FITS, then ‘hdu’ will also be used, otherwise, ‘hdu’ is
ignored. For more on ‘hdu_option_name’ see the description of
‘gal_array_read’ in *note Array input output::.
‘lines’ is a list of strings with each node representing one line
(including the new-line character), see *note List of strings::.
It will mostly be the output of ‘gal_txt_stdin_read’, which is used
to read the program's input as separate lines from the standard
input (see *note Text files::). Note that ‘filename’ and ‘lines’
are mutually exclusive and one of them must be ‘NULL’.
The information to search for columns should be specified by the
‘cols’ list of strings (see *note List of strings::). The string
in each node of the list may be a number, an exact match to a
column name, or a regular expression (in GNU AWK format) enclosed
in ‘/ /’. The ‘searchin’ value must be one of the macros defined
above. If ‘cols’ is NULL, then this function will read the full
table. Also, the ‘ignorecase’ value should be 1 if you want to
ignore the case of alphabetic characters while matching/searching
column meta-data (see *note Input output options::).
For FITS tables, each column will be read independently. Therefore
they will be read in ‘numthreads’ CPU threads to greatly speed up
the reading when there are many columns and rows. However, this
only happens if CFITSIO was configured with ‘--enable-reentrant’.
This test has been done at Gnuastro's configuration time; if so,
‘GAL_CONFIG_HAVE_FITS_IS_REENTRANT’ will have a value of 1,
otherwise, it will have a value of 0. For more on this macro, see
*note Configuration information::). Multi-threaded table reading
is not currently applicable to other table formats (only for FITS
tables).
The output is an individually allocated list of datasets (see *note
List of gal_data_t::) with the same order of the ‘cols’ list. Note
that one column node in the ‘cols’ list might give multiple columns
(for example, from regular expressions), in this case, the order of
output columns that correspond to that one input, are in order of
the table (which column was read first). So the first requested
column is the first popped data structure and so on.
if ‘colmatch!=NULL’, it is assumed to be an array that has at least
the same number of elements as nodes in the ‘cols’ list. The
number of columns that matched each input column will be stored in
each element.
-- Function:
gal_list_sizet_t *
gal_table_list_of_indexs (gal_list_str_t *cols, gal_data_t
*allcols, size_t numcols, int searchin, int ignorecase, char
*filename, char *hdu, size_t *colmatch)
Returns a list of indices (starting from 0) of the input columns
that match the names/numbers given to ‘cols’. This is a low-level
operation which is called by ‘gal_table_read’ (described above),
see there for more on each argument's description. ‘allcols’ is
the returned array of ‘gal_table_info’.
-- Function:
void
gal_table_comments_add_intro (gal_list_str_t **comments, char
*program_string, time_t *rawtime)
Add some basic information to the list of ‘comments’. This basic
information includes the following information
• If the program is run in a Git version controlled directory,
Git's description is printed (see description under ‘COMMIT’
in *note Output FITS files::).
• The calendar time that is stored in ‘rawtime’ (‘time_t’ is C's
calendar time format defined in ‘time.h’). You can calculate
the time in this format with the following expressions:
time_t rawtime;
time(&rawtime);
• The name of your program in ‘program_string’. If it is
‘NULL’, this line is ignored.
-- Function:
void
gal_table_write (gal_data_t *cols, struct gal_fits_list_key_t
**keylist, gal_list_str_t *comments, int tableformat, char
*filename, char *extname, uint8_t colinfoinstdout, int
freekeys)
Write ‘cols’ (a list of datasets, see *note List of gal_data_t::)
into a table stored in ‘filename’. The format of the table can be
determined with ‘tableformat’ that accepts the macros defined
above. When ‘filename==NULL’, the column information will be
printed on the standard output (command-line).
If ‘comments!=NULL’, the list of comments (see *note List of
strings::) will also be printed into the output table. When the
output table is a plain text file, every node of ‘comments’ will be
printed after a ‘#’ (so it can be considered as a comment) and in
FITS table they will follow a ‘COMMENT’ keyword.
If a file named ‘filename’ already exists, the operation depends on
the type of output. When ‘filename’ is a FITS file, the table will
be added as a new extension after all existing extensions. If
‘filename’ is a plain text file, this function will abort with an
error.
If ‘filename’ is a FITS file, the table extension will have the
name ‘extname’.
When ‘colinfoinstdout!=0’ and ‘filename==NULL’ (columns are printed
in the standard output), the dataset metadata will also printed in
the standard output. When printing to the standard output, the
column information can be piped into another program for further
processing and thus the meta-data (lines starting with a ‘#’) must
be ignored. In such cases, you only print the column values by
passing ‘0’ to ‘colinfoinstdout’.
-- Function:
void
gal_table_write_log (gal_data_t *logll, char *program_string,
time_t *rawtime, gal_list_str_t *comments, char *filename, int
quiet)
Write the ‘logll’ list of datasets into a table in ‘filename’ (see
*note List of gal_data_t::). This function is just a wrapper
around ‘gal_table_comments_add_intro’ and ‘gal_table_write’ (see
above). If ‘quiet’ is non-zero, this function will print a message
saying that the ‘filename’ has been created.
-- Function:
gal_data_t *
gal_table_col_vector_extract (gal_data_t *vector,
gal_list_sizet_t *indexs)
Given the "vector" column ‘vector’ (which is assumed to be a 2D
dataset), extract the tokens that are identified in the ‘indexs’
list into a list of one dimensional datasets. For more on vector
columns in tables, see *note Vector columns::.
-- Function:
gal_data_t *
gal_table_cols_to_vector (gal_data_t *list)
Merge the one-dimensional datasets in the given list into one
2-dimensional dataset that can be treated as a vector column. All
the input datasets have to have the same size and type. For more
on vector columns in tables, see *note Vector columns::.
File: gnuastro.info, Node: FITS files, Next: File input output, Prev: Table input output, Up: Gnuastro library
12.3.11 FITS files (‘fits.h’)
-----------------------------
The FITS format is the most common format to store data (images and
tables) in astronomy. The CFITSIO library already provides a very good
low-level collection of functions for manipulating FITS data. The
low-level nature of CFITSIO is defined for versatility and portability.
As a result, even a simple and basic operation, like reading an image or
table column into memory, will require a special sequence of CFITSIO
function calls which can be inconvenient and buggy to manage in separate
locations. To ease this process, Gnuastro's library provides wrappers
for CFITSIO functions. With these, it much easier to read, write, or
modify FITS file data, header keywords and extensions. Hence, if you
feel these functions do not exactly do what you want, we strongly
recommend reading the CFITSIO manual to use its great features directly
(afterwards, send us your wrappers so we can include it here for others
to benefit also).
All the functions and macros introduced in this section are declared
in ‘gnuastro/fits.h’. When you include this header, you are also
including CFITSIO's ‘fitsio.h’ header. So you do not need to explicitly
include ‘fitsio.h’ anymore and can freely use any of its macros or
functions in your code along with those discussed here.
* Menu:
* FITS macros errors filenames:: General macros, errors and checking names.
* CFITSIO and Gnuastro types:: Conversion between FITS and Gnuastro types.
* FITS HDUs:: Opening and getting information about HDUs.
* FITS header keywords:: Reading and writing FITS header keywords.
* FITS arrays:: Reading and writing FITS images/arrays.
* FITS tables:: Reading and writing FITS tables.
File: gnuastro.info, Node: FITS macros errors filenames, Next: CFITSIO and Gnuastro types, Prev: FITS files, Up: FITS files
12.3.11.1 FITS Macros, errors and filenames
...........................................
Some general constructs provided by Gnuastro's FITS handling functions
are discussed here. In particular there are several useful functions
about FITS file names.
-- Macro: GAL_FITS_MAX_NDIM
The maximum number of dimensions a dataset can have in FITS format,
according to the FITS standard this is 999.
-- Function:
void
gal_fits_io_error (int status, char *message)
If ‘status’ is non-zero, this function will print the CFITSIO error
message corresponding to status, print ‘message’ (optional) in the
next line and abort the program. If ‘message==NULL’, it will print
a default string after the CFITSIO error.
-- Function:
int
gal_fits_name_is_fits (char *name)
If the ‘name’ is an acceptable CFITSIO FITS filename return ‘1’
(one), otherwise return ‘0’ (zero). The currently acceptable FITS
suffixes are ‘.fits’, ‘.fit’, ‘.fits.gz’, ‘.fits.Z’, ‘.imh’,
‘.fits.fz’. IMH is the IRAF format which is acceptable to CFITSIO.
-- Function:
int
gal_fits_suffix_is_fits (char *suffix)
Similar to ‘gal_fits_name_is_fits’, but only for the suffix. The
suffix does not have to start with '<.>': this function will return
‘1’ (one) for both ‘fits’ and ‘.fits’.
-- Function:
int
gal_fits_file_recognized (char *name)
Return ‘1’ if the given file name (possibly including its contents)
is a FITS file. This is necessary in when the contents of a FITS
file do follow the FITS standard, but it the file does not have a
Gnuastro-recognized FITS suffix. Therefore, it will first call
‘gal_fits_name_is_fits’, if the result is negative, then this
function will attempt to open the file with CFITSIO and if it
works, it will close it again and return 1. In the process of
opening the file, CFITSIO will just to open the file, no reading
will take place, so it should have minimal CPU footprint.
-- Function:
char *
gal_fits_name_save_as_string (char *filename, char *hdu)
If the name is a FITS name, then put a ‘(hdu: ...)’ after it and
return the string. If it is not a FITS file, just print the name,
if ‘filename==NULL’, then return the string ‘stdin’. Note that the
output string's space is allocated.
This function is useful when you want to report a random file to
the user which may be FITS or not (for a FITS file, simply the
filename is not enough, the HDU is also necessary).
File: gnuastro.info, Node: CFITSIO and Gnuastro types, Next: FITS HDUs, Prev: FITS macros errors filenames, Up: FITS files
12.3.11.2 CFITSIO and Gnuastro types
....................................
Both Gnuastro and CFITSIO have special and different identifiers for
each type that they accept. Gnuastro's type identifiers are fully
described in *note Library data types:: and are usable for all kinds of
datasets (images, table columns, etc) as part of Gnuastro's *note
Generic data container::. However, following the FITS standard, CFITSIO
has different identifiers for images and tables. Following CFITSIO's
own convention, we will use ‘bitpix’ for image type identifiers and
‘datatype’ for its internal identifiers (and mainly used in tables).
The functions introduced in this section can be used to convert between
CFITSIO and Gnuastro's type identifiers.
One important issue to consider is that CFITSIO's types are not fixed
width (for example, ‘long’ may be 32-bits or 64-bits on different
systems). However, Gnuastro's types are defined by their width. These
functions will use information on the host system to do the proper
conversion. To have a portable (usable on different systems) code, is
thus recommended to use these functions and not to assume a fixed
correspondence between CFITSIO and Gnuastro's types.
-- Function:
uint8_t
gal_fits_bitpix_to_type (int bitpix)
Return the Gnuastro type identifier that corresponds to CFITSIO's
‘bitpix’ on this system.
-- Function:
int
gal_fits_type_to_bitpix (uint8_t type)
Return the CFITSIO ‘bitpix’ value that corresponds to Gnuastro's
‘type’.
-- Function:
char
gal_fits_type_to_bin_tform (uint8_t type)
Return the FITS standard binary table ‘TFORM’ character that
corresponds to Gnuastro's ‘type’.
-- Function:
int
gal_fits_type_to_datatype (uint8_t type)
Return the CFITSIO ‘datatype’ that corresponds to Gnuastro's ‘type’
on this machine.
-- Function:
uint8_t
gal_fits_datatype_to_type (int datatype, int is_table_column)
Return Gnuastro's type identifier that corresponds to the CFITSIO
‘datatype’. Note that when dealing with CFITSIO's ‘TLONG’, the
fixed width type differs between tables and images. So if the
corresponding dataset is a table column, put a non-zero value into
‘is_table_column’.
File: gnuastro.info, Node: FITS HDUs, Next: FITS header keywords, Prev: CFITSIO and Gnuastro types, Up: FITS files
12.3.11.3 FITS HDUs
...................
A FITS file can contain multiple HDUs/extensions. The functions in this
section can be used to get basic information about the extensions or
open them. Note that ‘fitsfile’ is defined in CFITSIO's ‘fitsio.h’
which is automatically included by Gnuastro's ‘gnuastro/fits.h’.
-- Function:
fitsfile *
gal_fits_open_to_write (char *filename)
If ‘filename’ exists, open it and return the ‘fitsfile’ pointer
that corresponds to it. If ‘filename’ does not exist, the file
will be created which contains a blank first extension and the
pointer to its next extension will be returned.
-- Function:
size_t
gal_fits_hdu_num (char *filename)
Return the number of HDUs/extensions in ‘filename’.
-- Function:
unsigned long
gal_fits_hdu_datasum (char *filename, char *hdu, char
*hdu_option_name)
Return the ‘DATASUM’ of the given HDU in the given FITS file. For
more on ‘DATASUM’ in the FITS standard, see *note Keyword
inspection and manipulation:: (under the ‘checksum’ component of
‘--write’). For more on ‘hdu_option_name’ see the description of
‘gal_array_read’ in *note Array input output::.
-- Function:
unsigned long
gal_fits_hdu_datasum_encoded (char *filename, char *hdu, char
*hdu_option_name)
Similar to ‘gal_fits_hdu_datasum’, but the returned value is always
a 16-character string following the encoding that is described in
the FITS standard (primarily for the ‘CHECKSUM’ keyword, but can
also be used for ‘DATASUM’.
-- Function:
unsigned long
gal_fits_hdu_datasum_ptr (fitsfile *fptr)
Return the ‘DATASUM’ of the already opened HDU in ‘fptr’. For more
on ‘DATASUM’ in the FITS standard, see *note Keyword inspection and
manipulation:: (under the ‘checksum’ component of ‘--write’).
-- Function:
int
gal_fits_hdu_format (char *filename, char *hdu, char
*hdu_option_name)
Return the format of the HDU as one of CFITSIO's recognized macros:
‘IMAGE_HDU’, ‘ASCII_TBL’, or ‘BINARY_TBL’. For more on
‘hdu_option_name’ see the description of ‘gal_array_read’ in *note
Array input output::.
-- Function:
int
gal_fits_hdu_is_healpix (fitsfile *fptr)
Return ‘1’ if the dataset may be a HEALpix grid and ‘0’ otherwise.
Technically, it is considered to be a HEALPix if the HDU is not an
ASCII table, and has the ‘NSIDE’, ‘FIRSTPIX’ and ‘LASTPIX’.
-- Function:
fitsfile *
gal_fits_hdu_open (char *filename, char *hdu, int iomode, int
exitonerror, char *hdu_option_name)
Open the HDU/extension ‘hdu’ from ‘filename’ and return a pointer
to CFITSIO's ‘fitsfile’. ‘iomode’ determines how the FITS file
will be opened using CFITSIO's macros: ‘READONLY’ or ‘READWRITE’.
The string in ‘hdu’ will be appended to ‘filename’ in square
brackets so CFITSIO only opens this extension. You can use any
formatting for the ‘hdu’ that is acceptable to CFITSIO. See the
description under ‘--hdu’ in *note Input output options:: for more.
If ‘exitonerror!=0’ and the given HDU cannot be opened for any
reason, the function will exit the program, and print an
informative message. Otherwise, when the HDU cannot be opened, it
will just return a NULL pointer. For more on ‘hdu_option_name’ see
the description of ‘gal_array_read’ in *note Array input output::.
-- Function:
fitsfile *
gal_fits_hdu_open_format (char *filename, char *hdu, int
img0_tab1, char *hdu_option_name)
Open (in read-only format) the ‘hdu’ HDU/extension of ‘filename’ as
an image or table. When ‘img0_tab1’ is ‘0’(zero) but the HDU is a
table, this function will abort with an error. It will also abort
with an error when ‘img0_tab1’ is ‘1’ (one), but the HDU is an
image. For more on ‘hdu_option_name’ see the description of
‘gal_array_read’ in *note Array input output::.
A FITS HDU may contain both tables or images. When your program
needs one of these formats, you can call this function so if the
user provided the wrong HDU/file, it will abort and inform the user
that the file/HDU is has the wrong format.
File: gnuastro.info, Node: FITS header keywords, Next: FITS arrays, Prev: FITS HDUs, Up: FITS files
12.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 *note Linked lists::. To reading FITS keywords, these
functions use a list of Gnuastro's generic dataset format that is
discussed in *note 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 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 *note Linked lists:: 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;
-- Function:
int
gal_fits_key_exists_fptr (fitsfile *fptr, char *keyname)
Return 1 (true) if the opened FITS file pointer contains the
requested keyword and 0 (false) otherwise.
-- 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 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.
-- 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 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.
-- 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 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).
-- 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 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 *note FITS macros
errors 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.
-- Function:
void
gal_fits_key_read (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.
-- 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 *note Linked lists::). 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. If ‘cfree’ is non-zero, the space allocated
for ‘comment’ will be freed immediately after writing the keyword
(in another function).
-- Function:
void
gal_fits_key_list_title_add_end (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.
-- Function:
void
gal_fits_key_list_fullcomment_add (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).
-- Function:
void
gal_fits_key_list_fullcomment_add_end (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.
-- Function:
void
gal_fits_key_list_add_date (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 *note Output
FITS files::.
-- Function:
void
gal_fits_key_list_add_software_versions (gal_fits_list_key_t
**keylist)
Add the version of Gnuastro *note 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 *note Output FITS files::.
-- Function:
void
gal_fits_key_list_add_git_commit (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 *note Output FITS files::.
-- 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 will not
do anything.
-- Function:
void
gal_fits_key_write_filename (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 keyword(1). 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.
-- Function:
void
gal_fits_key_write_wcsstr (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.
-- Function:
void
gal_fits_key_write (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 *note
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;
}
-- Function:
void
gal_fits_key_write_in_ptr (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.
-- Function:
gal_list_str_t *
gal_fits_with_keyvalue (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 *note
Array input output::.
-- Function:
gal_list_str_t *
gal_fits_unique_keyvalues (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 *note Array input
output::.
---------- Footnotes ----------
(1) 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.
File: gnuastro.info, Node: FITS arrays, Next: FITS tables, Prev: FITS header keywords, Up: FITS files
12.3.11.5 FITS arrays (images)
..............................
Images (or multi-dimensional arrays in general) are one of the common
data formats that is stored in FITS files. Only one image may be stored
in each FITS HDU/extension. The functions described here can be used to
get the information of, read, or write images in FITS files.
-- Function:
void
gal_fits_img_info (fitsfile *fptr, int *type, size_t *ndim,
size_t **dsize, char **name, char **unit)
Read the type (see *note Library data types::), number of
dimensions, and size along each dimension of the CFITSIO ‘fitsfile’
into the ‘type’, ‘ndim’, and ‘dsize’ pointers respectively. If
‘name’ and ‘unit’ are not ‘NULL’ (point to a ‘char *’), then if the
image has a name and units, the respective string will be put in
these pointers.
-- Function:
size_t *
gal_fits_img_info_dim (char *filename, char *hdu, size_t
*ndim, char *hdu_option_name)
Put the number of dimensions in the ‘hdu’ extension of ‘filename’
in the space that ‘ndim’ points to and return the size of the
dataset along each dimension as an allocated array with ‘*ndim’
elements. For more on ‘hdu_option_name’ see the description of
‘gal_array_read’ in *note Array input output::.
-- Function:
gal_data_t *
gal_fits_img_read (char *filename, char *hdu, size_t
minmapsize, int quietmmap, char *hdu_option_name)
Read the contents of the ‘hdu’ extension/HDU of ‘filename’ into a
Gnuastro generic data container (see *note Generic data
container::) and return it. If the necessary space is larger than
‘minmapsize’, then do not keep the data in RAM, but in a file on
the HDD/SSD. For more on ‘minmapsize’ and ‘quietmmap’ see the
description under the same name in *note Generic data container::.
For more on ‘hdu_option_name’ see the description of
‘gal_array_read’ in *note Array input output::.
Note that this function only reads the main data within the
requested FITS extension, the WCS will not be read into the
returned dataset. To read the WCS, you can use ‘gal_wcs_read’
function as shown below. Afterwards, the ‘gal_data_free’ function
will free both the dataset and any WCS structure (if there are
any).
data=gal_fits_img_read(filename, hdu, -1, 1, NULL);
data->wcs=gal_wcs_read(filename, hdu, 0, 0, 0, &data->wcs->nwcs,
NULL);
-- Function:
gal_data_t *
gal_fits_img_read_to_type (char *inputname, char *inhdu,
uint8_t type, size_t minmapsize, int quietmmap, char
*hdu_option_name)
Read the contents of the ‘hdu’ extension/HDU of ‘filename’ into a
Gnuastro generic data container (see *note Generic data
container::) of type ‘type’ and return it.
This is just a wrapper around ‘gal_fits_img_read’ (to read the
image/array of any type) and ‘gal_data_copy_to_new_type_free’ (to
convert it to ‘type’ and free the initially read dataset). See the
description there for more.
-- Function:
gal_data_t *
gal_fits_img_read_kernel (char *filename, char *hdu, size_t
minmapsize, int quietmmap, char *hdu_option_name)
Read the ‘hdu’ of ‘filename’ as a convolution kernel. A
convolution kernel must have an odd size along all dimensions, it
must not have blank (NaN in floating point types) values and must
be flipped around the center to make the proper convolution (see
*note Convolution process::). If there are blank values, this
function will change the blank values to ‘0.0’. If the input image
does not have the other two requirements, this function will abort
with an error describing the condition to the user. The finally
returned dataset will have a ‘float32’ type.
For more on ‘hdu_option_name’ see the description of
‘gal_array_read’ in *note Array input output::.
-- Function:
fitsfile *
gal_fits_img_write_to_ptr (gal_data_t *input, char *filename,
gal_fits_list_key_t *keylist, int freekeys)
Write the ‘input’ dataset into a FITS file named ‘filename’ and
return the corresponding CFITSIO ‘fitsfile’ pointer. This function
will not close ‘fitsfile’, so you can still add other extensions to
it after this function or make other modifications.
In case you want to add keywords into the HDU that contain the
data, you can use the second two arguments (see the description of
‘gal_fits_key_write’). These keywords will be written into the HDU
before writing the data: when there are more than roughly 5
keywords (assuming your dataset has WCS) and your dataset is large,
this can result in significant optimization of the running time
(because adding a keyword beyond the 36 key slots will cause the
whole data to shift for another block of 36 keywords).
-- Function:
void
gal_fits_img_write (gal_data_t *data, char *filename,
gal_fits_list_key_t *keylist, int freekeys)
Write the ‘input’ dataset into the FITS file named ‘filename’.
Also add the list of header keywords (‘keylist’) to the newly
created HDU/extension The list of keywords will be freed after
writing into the HDU, if you need them later, keep a separate copy
of the list before calling this function.
For the importance of why it is better to add your keywords in this
function (before writing the data) or after it, see the description
of ‘gal_fits_img_write_to_ptr’.
-- Function:
void
gal_fits_img_write_to_type (gal_data_t *data, char *filename,
gal_fits_list_key_t *keylist, int type, int freekeys)
Convert the ‘input’ dataset into ‘type’, then write it into the
FITS file named ‘filename’. Also add the ‘keylist’ keywords to the
newly created HDU/extension along with your program's name
(‘program_string’). After the FITS file is written, this function
will free the copied dataset (with type ‘type’) from memory.
For the importance of why it is better to add your keywords in this
function (before writing the data) or after it, see the description
of ‘gal_fits_img_write_to_ptr’. This is just a wrapper for the
‘gal_data_copy_to_new_type’ and ‘gal_fits_img_write’ functions.
-- Function:
void
gal_fits_img_write_corr_wcs_str (gal_data_t *data, char
*filename, char *wcsstr, int nkeyrec, double *crpix,
gal_fits_list_key_t *keylist, int freekeys)
Write the ‘input’ dataset into ‘filename’ using the ‘wcsstr’ while
correcting the ‘CRPIX’ values. For the importance of why it is
better to add your keywords in this function (before writing the
data) or after it, see the description of
‘gal_fits_img_write_to_ptr’.
This function is mainly useful when you want to make FITS files in
parallel (from one main WCS structure, with just a differing
CRPIX), for more on the arguments, see the description of
‘gal_fits_img_write’. This can happen in the following cases for
example:
• When a large number of FITS images (with WCS) need to be
created in parallel, it can be much more efficient to write
the header's WCS keywords once at first, write them in the
FITS file, then just correct the CRPIX values.
• WCSLIB's header writing function is not thread safe. So when
writing FITS images in parallel, we cannot write the header
keywords in each thread.
File: gnuastro.info, Node: FITS tables, Prev: FITS arrays, Up: FITS files
12.3.11.6 FITS tables
.....................
Tables are one of the common formats of data that is stored in FITS
files. Only one table may be stored in each FITS HDU/extension, but
each table column must be viewed as a different dataset (with its own
name, units and numeric data type for example). The only constraint of
the column datasets in a table is that they must be one-dimensional and
have the same number of elements as the other columns. The functions
described here can be used to get the information of, read, or write
columns into FITS tables.
-- Function:
void
gal_fits_tab_size (fitsfile *fitsptr, size_t *nrows, size_t
*ncols)
Read the number of rows and columns in the table within CFITSIO's
‘fitsptr’.
-- Function:
int
gal_fits_tab_format (fitsfile *fitsptr)
Return the format of the FITS table contained in CFITSIO's
‘fitsptr’. Recall that FITS tables can be in binary or ASCII
formats. This function will return ‘GAL_TABLE_FORMAT_AFITS’ or
‘GAL_TABLE_FORMAT_BFITS’ (defined in *note Table input output::).
If the ‘fitsptr’ is not a table, this function will abort the
program with an error message informing the user of the problem.
-- Function:
gal_data_t *
gal_fits_tab_info (char *filename, char *hdu, size_t *numcols,
size_t *numrows, int *tableformat, char *hdu_option_name)
Store the information of each column in ‘hdu’ of ‘filename’ into an
array of data structures with ‘numcols’ elements (one data
structure for each column) see *note Arrays of datasets::. The
total number of rows in the table is also put into the memory that
‘numrows’ points to. The format of the table (e.g., FITS binary or
ASCII table) will be put in ‘tableformat’ (macros defined in *note
Table input output::). For more on ‘hdu_option_name’ see the
description of ‘gal_array_read’ in *note Array input output::.
This function is just for column information. Therefore it only
stores meta-data like column name, units and comments. No actual
data (contents of the columns for example, the ‘array’ or ‘dsize’
elements) will be allocated by this function. This is a low-level
function particular to reading tables in FITS format. To be
generic, it is recommended to use ‘gal_table_info’ which will allow
getting information from a variety of table formats based on the
filename (see *note Table input output::).
-- Function:
gal_data_t *
gal_fits_tab_read (char *filename, char *hdu, size_t numrows,
gal_data_t *colinfo, gal_list_sizet_t *indexll, size_t
numthreads, size_t minmapsize, int quietmmap, char
*hdu_option_name)
Read the columns given in the list ‘indexll’ from a FITS table (in
‘filename’ and HDU/extension ‘hdu’) into the returned linked list
of data structures, see *note List of size_t:: and *note List of
gal_data_t::. For more on ‘hdu_option_name’ see the description of
‘gal_array_read’ in *note Array input output::.
Each column will be read independently, therefore they will be read
in ‘numthreads’ CPU threads to greatly speed up the reading when
there are many columns and rows. However, this only happens if
CFITSIO was configured with ‘--enable-reentrant’. This test has
been done at Gnuastro's configuration time; if so,
‘GAL_CONFIG_HAVE_FITS_IS_REENTRANT’ will have a value of 1,
otherwise, it will have a value of 0. For more on this macro, see
*note Configuration information::).
If the necessary space for each column is larger than ‘minmapsize’,
do not keep it in the RAM, but in a file in the HDD/SSD. For more
on ‘minmapsize’ and ‘quietmmap’, see the description under the same
name in *note Generic data container::.
Each column will have ‘numrows’ rows and ‘colinfo’ contains any
further information about the columns (returned by
‘gal_fits_tab_info’, described above). Note that this is a
low-level function, so the output data linked list is the inverse
of the input indexes linked list. It is recommended to use
‘gal_table_read’ for generic reading of tables, see *note Table
input output::.
-- Function:
void
gal_fits_tab_write (gal_data_t *cols, gal_list_str_t
*comments, int tableformat, char *filename, char *extname,
gal_fits_list_key_t *keywords, int freekeys)
Write the list of datasets in ‘cols’ (see *note List of
gal_data_t::) as separate columns in a FITS table in ‘filename’.
If ‘filename’ already exists then this function will write the
table as a new extension called ‘extname’, after all existing ones.
The format of the table (ASCII or binary) may be specified with the
‘tableformat’ (see *note Table input output::). If
‘comments!=NULL’, each node of the list of strings will be written
as a ‘COMMENT’ keywords in the output FITS file (see *note List of
strings::.
In case your table needs metadata keywords, you can use the
‘listkeys’ and ‘freekeys’. For more on these, see the description
of ‘gal_fits_key_write_in_ptr’.
This is a low-level function for tables. It is recommended to use
‘gal_table_write’ for generic writing of tables in a variety of
formats, see *note Table input output::.
File: gnuastro.info, Node: File input output, Next: World Coordinate System, Prev: FITS files, Up: Gnuastro library
12.3.12 File input output
-------------------------
The most commonly used file format in astronomical data analysis is the
FITS format (see *note Fits:: for an introduction), therefore Gnuastro's
library provides a large and separate collection of functions to
read/write data from/to them (see *note FITS files::). However, FITS is
not well recognized outside the astronomical community and cannot be
imported into documents or slides. Therefore, in this section, we
discuss the other different file formats that Gnuastro's library
recognizes.
* Menu:
* Text files:: Reading and writing from/to plain text files.
* TIFF files:: Reading and writing from/to TIFF files.
* JPEG files:: Reading and writing from/to JPEG files.
* EPS files:: Writing to EPS files.
* PDF files:: Writing to PDF files.
File: gnuastro.info, Node: Text files, Next: TIFF files, Prev: File input output, Up: File input output
12.3.12.1 Text files (‘txt.h’)
..............................
The most universal and portable format for data storage are plain text
files. They can be viewed and edited on any text editor or even on the
command-line. This section are describes some functions that help in
reading from and writing to plain text files.
Lines are one of the most basic building blocks (delimiters) of a
text file. Some operating systems like Microsoft Windows, terminate
their ASCII text lines with a carriage return character and a new-line
character (two characters, also known as CRLF line terminators). While
Unix-like operating systems just use a single new-line character. The
functions below that read an ASCII text file are able to identify lines
with both kinds of line terminators.
Gnuastro defines a simple format for metadata of table columns in a
plain text file that is discussed in *note Gnuastro text table format::.
The functions to get information from, read from and write to plain text
files also follow those conventions.
-- Macro: GAL_TXT_LINESTAT_INVALID
-- Macro: GAL_TXT_LINESTAT_BLANK
-- Macro: GAL_TXT_LINESTAT_COMMENT
-- Macro: GAL_TXT_LINESTAT_DATAROW
Status codes for lines in a plain text file that are returned by
‘gal_txt_line_stat’. Lines which have a <#> character as their
first non-white character are considered to be comments. Lines
with nothing but white space characters are considered blank. The
remaining lines are considered as containing data.
-- Function:
int
gal_txt_line_stat (char *line)
Check the contents of ‘line’ and see if it is a blank, comment, or
data line. The returned values are the macros that start with
‘GAL_TXT_LINESTAT’.
-- Function:
char *
gal_txt_trim_space (char *str)
Trim the white space characters before and after the given string.
The operation is done within the allocated space of the string, so
if you need the string untouched, please pass an allocated copy of
the string to this function. The returned pointer is within the
input string. If the input pointer is ‘NULL’, or the string only
has white-space characters, the returned pointer will be ‘NULL’.
-- Function:
int
gal_txt_contains_string (char *full, char *match)
Return 1 if the string that ‘match’ points to, can be exactly found
within the string that ‘full’ points to (character by character).
The to-match string can be in any part of the full string. If any
of the two strings have zero length or are a ‘NULL’ pointer, this
function will return 0.
-- Function:
gal_data_t *
gal_txt_table_info (char *filename, gal_list_str_t *lines,
size_t *numcols, size_t *numrows)
Store the information of each column in a text file ‘filename’, or
list of strings (‘lines’) into an array of data structures with
‘numcols’ elements (one data structure for each column) see *note
Arrays of datasets::. The total number of rows in the table is
also put into the memory that ‘numrows’ points to.
‘lines’ is a list of strings with each node representing one line
(including the new-line character), see *note List of strings::.
It will mostly be the output of ‘gal_txt_stdin_read’, which is used
to read the program's input as separate lines from the standard
input (see below). Note that ‘filename’ and ‘lines’ are mutually
exclusive and one of them must be ‘NULL’.
This function is just for column information. Therefore it only
stores meta-data like column name, units and comments. No actual
data (contents of the columns for example, the ‘array’ or ‘dsize’
elements) will be allocated by this function. This is a low-level
function particular to reading tables in plain text format. To be
generic, it is recommended to use ‘gal_table_info’ which will allow
getting information from a variety of table formats based on the
filename (see *note Table input output::).
-- Function:
gal_data_t *
gal_txt_table_read (char *filename, gal_list_str_t *lines,
size_t numrows, gal_data_t *colinfo, gal_list_sizet_t
*indexll, size_t minmapsize, int quietmmap)
Read the columns given in the list ‘indexll’ from a plain text file
(‘filename’) or list of strings (‘lines’), into a linked list of
data structures (see *note List of size_t:: and *note List of
gal_data_t::). If the necessary space for each column is larger
than ‘minmapsize’, do not keep it in the RAM, but in a file on the
HDD/SSD. For more one ‘minmapsize’ and ‘quietmmap’, see the
description under the same name in *note Generic data container::.
‘lines’ is a list of strings with each node representing one line
(including the new-line character), see *note List of strings::.
It will mostly be the output of ‘gal_txt_stdin_read’, which is used
to read the program's input as separate lines from the standard
input (see below). Note that ‘filename’ and ‘lines’ are mutually
exclusive and one of them must be ‘NULL’.
Note that this is a low-level function, so the output data list is
the inverse of the input indices linked list. It is recommended to
use ‘gal_table_read’ for generic reading of tables in any format,
see *note Table input output::.
-- Function:
gal_data_t *
gal_txt_image_read (char *filename, gal_list_str_t *lines,
size_t minmapsize, int quietmmap)
Read the 2D plain text dataset in file (‘filename’) or list of
strings (‘lines’) into a dataset and return the dataset. If the
necessary space for the image is larger than ‘minmapsize’, do not
keep it in the RAM, but in a file on the HDD/SSD. For more on
‘minmapsize’ and ‘quietmmap’, see the description under the same
name in *note Generic data container::.
‘lines’ is a list of strings with each node representing one line
(including the new-line character), see *note List of strings::.
It will mostly be the output of ‘gal_txt_stdin_read’, which is used
to read the program's input as separate lines from the standard
input (see below). Note that ‘filename’ and ‘lines’ are mutually
exclusive and one of them must be ‘NULL’.
-- Function:
gal_list_str_t *
gal_txt_stdin_read (long timeout_microsec)
Read the complete standard input and return a list of strings with
each line (including the new-line character) as one node of that
list. If the standard input is already filled (for example,
connected to another program's output with a pipe), then this
function will parse the whole stream.
If Standard input is not pre-configured and the _first line_ is
typed/written in the terminal before ‘timeout_microsec’
micro-seconds, it will continue parsing until reaches an
end-of-file character (<CTRL-D> after a new-line on the keyboard)
with no time limit. If nothing is entered before
‘timeout_microsec’ micro-seconds, it will return ‘NULL’.
All the functions that can read plain text tables will accept a
filename as well as a list of strings (intended to be the output of
this function for using Standard input). The reason for keeping
the standard input is that once something is read from the standard
input, it is hard to put it back. We often need to read a text
file several times: once to count how many columns it has and which
ones are requested, and another time to read the desired columns.
So it easier to keep it all in allocated memory and pass it on from
the start for each round.
-- Function:
gal_list_str_t *
gal_txt_read_to_list (char *filename)
Read the contents of the given plain-text file and put each word
(separated by a SPACE character, into a new node of the output
list. The order of nodes in the output is the same as the input.
Any new-line character at the end of a word is removed in the
output list.
-- Function:
void
gal_txt_write (gal_data_t *cols, struct gal_fits_list_key_t
**keylist, gal_list_str_t *comment, char *filename, uint8_t
colinfoinstdout, int tab0_img1, int freekeys)
Write ‘cols’ in a plain text file ‘filename’ (table when
‘tab0_img1==0’ and image when ‘tab0_img1==1’). ‘cols’ may have one
or two dimensions which determines the output:
1D
‘cols’ is treated as a column and a list of datasets (see
*note List of gal_data_t::): every node in the list is written
as one column in a table.
2D
‘cols’ is a two dimensional array, it cannot be treated as a
list (only one 2D array can currently be written to a text
file). So if ‘cols->next!=NULL’ the next nodes in the list
are ignored and will not be written.
This is a low-level function for tables. It is recommended to use
‘gal_table_write’ for generic writing of tables in a variety of
formats, see *note Table input output::.
It is possible to add two types of metadata to the printed table:
comments and keywords. Each string in the list given to ‘comments’
will be printed into the file as a separate line, starting with
‘#’. Keywords have a more specific and computer-parsable format
and are passed through ‘keylist’. Each keyword is also printed in
one line, but with the format below. Because of the various
components in a keyword, it is thus necessary to use the
‘gal_fits_list_key_t’ data structure. For more, see *note FITS
header keywords::.
# [key] NAME: VALUE / [UNIT] KEYWORD COMMENT.
If ‘filename’ already exists this function will abort with an error
and will not write over the existing file. Before calling this
function make sure if the file exists or not. If ‘comments!=NULL’,
a ‘#’ will be put at the start of each node of the list of strings
and will be written in the file before the column meta-data in
‘filename’ (see *note List of strings::).
When ‘filename==NULL’, the column information will be printed on
the standard output (command-line). When ‘colinfoinstdout!=0’ and
‘filename==NULL’ (columns are printed in the standard output), the
dataset metadata will also printed in the standard output. When
printing to the standard output, the column information can be
piped into another program for further processing and thus the
meta-data (lines starting with a ‘#’) must be ignored. In such
cases, you only print the column values by passing ‘0’ to
‘colinfoinstdout’.
File: gnuastro.info, Node: TIFF files, Next: JPEG files, Prev: Text files, Up: File input output
12.3.12.2 TIFF files (‘tiff.h’)
...............................
Outside of astronomy, the TIFF standard is arguably the most commonly
used format to store high-precision data/images. Unlike FITS however,
the TIFF standard only supports images (not tables), but like FITS, it
has support for all standard data types (see *note Numeric data types::)
which is the primary reason other fields use it.
Another similarity of the TIFF and FITS standards is that TIFF
supports multiple images in one file. The TIFF standard calls each one
of these images (and their accompanying meta-data) a 'directory'
(roughly equivalent to the FITS extensions). Unlike FITS however, the
directories can only be identified by their number (counting from zero),
recall that in FITS you can also use the extension name to identify it.
The functions described here allow easy reading (and later writing)
of TIFF files within Gnuastro or for users of Gnuastro's libraries.
Currently only reading is supported, but if you are interested, please
get in touch with us.
-- Function:
int
gal_tiff_name_is_tiff (char *name)
Return ‘1’ if ‘name’ has a TIFF suffix. This can be used to make
sure that a given input file is TIFF. See ‘gal_tiff_suffix_is_tiff’
for a list of recognized suffixes.
-- Function:
int
gal_tiff_suffix_is_tiff (char *name)
Return ‘1’ if ‘suffix’ is a recognized TIFF suffix. The recognized
suffixes are ‘tif’, ‘tiff’, ‘TIFF’ and ‘TIFF’.
-- Function:
size_t
gal_tiff_dir_string_read (char *string)
Return the number within ‘string’ as a ‘size_t’ number to identify
a TIFF directory. Note that the directories start counting from
zero.
-- Function:
gal_data_t *
gal_tiff_read (char *filename, size_t dir, size_t minmapsize,
int quietmmap)
Read the ‘dir’ directory within the TIFF file ‘filename’ and return
the contents of that TIFF directory as ‘gal_data_t’. If the
directory's image contains multiple channels, the output will be a
list (see *note List of gal_data_t::).
-- Function:
void
gal_tiff_write (gal_data_t *in, char *filename, int widthinpx,
int heightinpix, int bitspersample, int numimg)
Write the given dataset (‘in’) into ‘filename’ (a TIFF file) with
the specified image width in pixels (‘widthinpix’),height in pixels
(‘heightinpix’), bits per sample (‘bitspersample’), and number of
images (‘numimg’).
File: gnuastro.info, Node: JPEG files, Next: EPS files, Prev: TIFF files, Up: File input output
12.3.12.3 JPEG files (‘jpeg.h’)
...............................
The JPEG file format is one of the most common formats for storing and
transferring images, recognized by almost all image rendering and
processing programs. In particular, because of its lossy compression
algorithm, JPEG files can have low volumes, making it used heavily on
the internet. For more on this file format, and a comparison with
others, please see *note Recognized file formats::.
For scientific purposes, the lossy compression and very limited
dynamic range (8-bit integers) make JPEG very unattractive for storing
of valuable data. However, because of its commonality, it will
inevitably be needed in some situations. The functions here can be used
to read and write JPEG images into Gnuastro's *note Generic data
container::. If the JPEG file has more than one color channel, each
channel is treated as a separate node in a list of datasets (see *note
List of gal_data_t::).
-- Function:
int
gal_jpeg_name_is_jpeg (char *name)
Return ‘1’ if ‘name’ has a JPEG suffix. This can be used to make
sure that a given input file is JPEG. See ‘gal_jpeg_suffix_is_jpeg’
for a list of recognized suffixes.
-- Function:
int
gal_jpeg_suffix_is_jpeg (char *name)
Return ‘1’ if ‘suffix’ is a recognized JPEG suffix. The recognized
suffixes are ‘.jpg’, ‘.JPG’, ‘.jpeg’, ‘.JPEG’, ‘.jpe’, ‘.jif’,
‘.jfif’ and ‘.jfi’.
-- Function:
gal_data_t *
gal_jpeg_read (char *filename, size_t minmapsize, int
quietmmap)
Read the JPEG file ‘filename’ and return the contents as
‘gal_data_t’. If the directory's image contains multiple
colors/channels, the output will be a list with one node per
color/channel (see *note List of gal_data_t::).
-- Function:
void
gal_jpeg_write (gal_data_t *in, char *filename, uint8_t
quality, float widthincm)
Write the given dataset (‘in’) into ‘filename’ (a JPEG file). If
‘in’ is a list, then each node in the list will be a color channel,
therefore there can only be 1, 3 or 4 nodes in the list. If the
number of nodes is different, then this function will abort the
program with a message describing the cause. The lossy JPEG
compression level can be set through ‘quality’ which is a value
between 0 and 100 (inclusive, 100 being the best quality). The
display width of the JPEG file in units of centimeters (to suggest
to viewers/users, only a meta-data) can be set through ‘widthincm’.
File: gnuastro.info, Node: EPS files, Next: PDF files, Prev: JPEG files, Up: File input output
12.3.12.4 EPS files (‘eps.h’)
.............................
The Encapsulated PostScript (EPS) format is commonly used to store
images (or individual/single-page parts of a document) in the PostScript
documents. For a more complete introduction, please see *note
Recognized file formats::. To provide high quality graphics, the
Postscript language is a vectorized format, therefore pixels (elements
of a "rasterized" format) are not defined in their context.
To display rasterized images, PostScript does allow arrays of pixels.
However, since the over-all EPS file may contain many vectorized
elements (for example, borders, text, or other lines over the text) and
interpreting them is not trivial or necessary within Gnuastro's scope,
Gnuastro only provides some functions to write a dataset (in the
‘gal_data_t’ format, see *note Generic data container::) into EPS.
-- Macro: GAL_EPS_MARK_COLNAME_TEXT
-- Macro: GAL_EPS_MARK_COLNAME_FONT
-- Macro: GAL_EPS_MARK_COLNAME_XPIX
-- Macro: GAL_EPS_MARK_COLNAME_YPIX
-- Macro: GAL_EPS_MARK_COLNAME_SHAPE
-- Macro: GAL_EPS_MARK_COLNAME_COLOR
-- Macro: GAL_EPS_MARK_COLNAME_SIZE1
-- Macro: GAL_EPS_MARK_COLNAME_SIZE2
-- Macro: GAL_EPS_MARK_COLNAME_ROTATE
-- Macro: GAL_EPS_MARK_COLNAME_FONTSIZE
-- Macro: GAL_EPS_MARK_COLNAME_LINEWIDTH
Name of column that the required property will be read from.
-- Macro: GAL_EPS_MARK_DEFAULT_SHAPE
-- Macro: GAL_EPS_MARK_DEFAULT_COLOR
-- Macro: GAL_EPS_MARK_DEFAULT_SIZE1
-- Macro: GAL_EPS_MARK_DEFAULT_SIZE2
-- Macro: GAL_EPS_MARK_DEFAULT_SIZE2_ELLIPSE
-- Macro: GAL_EPS_MARK_DEFAULT_ROTATE
-- Macro: GAL_EPS_MARK_DEFAULT_LINEWIDTH
-- Macro: GAL_EPS_MARK_DEFAULT_FONT
-- Macro: GAL_EPS_MARK_DEFAULT_FONTSIZE
Default values for the various mark properties. These constants
will be used if the caller has not provided any of the given
property.
-- Function:
int
gal_eps_name_is_eps (char *name)
Return ‘1’ if ‘name’ has an EPS suffix. This can be used to make
sure that a given input file is EPS. See ‘gal_eps_suffix_is_eps’
for a list of recognized suffixes.
-- Function:
int
gal_eps_suffix_is_eps (char *name)
Return ‘1’ if ‘suffix’ is a recognized EPS suffix. The recognized
suffixes are ‘.eps’, ‘.EPS’, ‘.epsf’, ‘.epsi’.
-- Function:
void
gal_eps_to_pt (float widthincm, size_t *dsize, size_t
*w_h_in_pt)
Given a specific width in centimeters (‘widthincm’ and the number
of he dataset's pixels in each dimension (‘dsize’) calculate the
size of he output in PostScript points. The output values are
written in the ‘w_h_in_pt’ array (which has to be allocated before
calling this unction). The first element in ‘w_h_in_pt’ is the
width and the second is the height of the image.
-- Function:
uint8_t
gal_eps_shape_name_to_id (char *name)
Return the shape ID of a mark from its name (which is not
case-sensitive).
-- Function:
uint8_t
gal_eps_shape_id_to_name (uint8_t id)
Return the shape name from its ID.
-- Function:
void
gal_eps_write (gal_data_t *in, char *filename, float
widthincm, uint32_t borderwidth, uint8_t bordercolor, int hex,
int dontoptimize, int forps, gal_data_t *marks)
Write the ‘in’ dataset into an EPS file called ‘filename’. ‘in’
has to be an unsigned 8-bit character type ‘GAL_TYPE_UINT8’, see
*note Numeric data types::). The desired width of the image in
human/non-pixel units can be set with he ‘widthincm’ argument. If
‘borderwidth’ is non-zero, it is interpreted as the width (in
points) of a solid black border around the mage. A border can
helpful when importing the EPS file into a document. The color of
the border can be set with ‘bordercolor’, use the macros in *note
Color functions::. If ‘forpdf’ is not zero, the output can be
imported into a Postscript file directly (not as an "encapsulated"
postscript, which is the default).
EPS files are plain-text (can be opened/edited in a text editor),
therefore there are different encodings to store the data (pixel
values) within them. Gnuastro supports the Hexadecimal and ASCII85
encoding. ASCII85 is more efficient (producing small file sizes),
so it is the default encoding. To use Hexadecimal encoding, set
‘hex’ to a non-zero value.
By default, when the dataset only has two values, this function
will use the PostScript optimization that allows setting the pixel
values per bit, not byte (*note Recognized file formats::). This
can greatly help reduce the file size. However, when
‘dontoptimize!=0’, this optimization is disabled: even though there
are only two values (is binary), the difference between them does
not correspond to the full contrast of black and white.
If ‘marks!=NULL’, it is assumed to contain multiple columns of
information to draw marks over the background image. The multiple
columns are a linked list of 1D ‘gal_data_t’ of the same size
(number of rows) that are connected to each other through the
‘next’ element (this is the same format that Gnuastro's library
uses for tables, see *note Table input output:: or *note Library
demo - reading and writing table columns::).
The macros defined above that have the format of
‘GAL_EPS_MARK_COLNAME_*’ show all the possible columns that you can
provide in this linked list. Only the two coordinate columns are
mandatory (‘GAL_EPS_MARK_COLNAME_XPIX’ and
‘GAL_EPS_MARK_COLNAME_YPIX’. If any of the other properties is not
in the linked list, then the default properties of the
‘GAL_EPS_MARK_DEFAULT_*’ macros will be used (also defined above.
The columns are identified based on the ‘name’ element of
Gnuastro's generic data structure (see *note Generic data
container::). The names must have the pre-defined names of the
‘GAL_EPS_MARK_COLNAME_*’ macros (case sensitive). Therefore, the
order of columns in the list is irrelevant!
File: gnuastro.info, Node: PDF files, Prev: EPS files, Up: File input output
12.3.12.5 PDF files (‘pdf.h’)
.............................
The portable document format (PDF) has arguably become the most common
format used for distribution of documents. In practice, a PDF file is
just a compiled PostScript file. For a more complete introduction,
please see *note Recognized file formats::. To provide high quality
graphics, the PDF is a vectorized format, therefore pixels (elements of
a "rasterized" format) are not defined in their context. As a result,
similar to *note EPS files::, Gnuastro only writes datasets to a PDF
file, not vice-versa.
-- Function:
int
gal_pdf_name_is_pdf (char *name)
Return ‘1’ if ‘name’ has an PDF suffix. This can be used to make
sure that a given input file is PDF. See ‘gal_pdf_suffix_is_pdf’
for a list of recognized suffixes.
-- Function:
int
gal_pdf_suffix_is_pdf (char *name)
Return ‘1’ if ‘suffix’ is a recognized PDF suffix. The recognized
suffixes are ‘.pdf’ and ‘.PDF’.
-- Function:
void
gal_pdf_write (gal_data_t *in, char *filename, float
widthincm, uint32_t borderwidth, uint8_t bordercolor, int
dontoptimize, gal_data_t *marks)
Write the ‘in’ dataset into an EPS file called ‘filename’. ‘in’
has to be an unsigned 8-bit character type (‘GAL_TYPE_UINT8’, see
*note Numeric data types::). The desired width of the image in
human/non-pixel units can be set with the ‘widthincm’ argument. If
‘borderwidth’ is non-zero, it is interpreted as the width (in
points) of a solid black border around the image. A border can
helpful when importing the PDF file into a document. The color of
the border can be set with ‘bordercolor’, use the macros in *note
Color functions::.
This function is just a wrapper for the ‘gal_eps_write’ function in
*note EPS files::. After making the EPS file, Ghostscript (with a
version of 9.10 or above, see *note Optional dependencies::) will
be used to compile the EPS file to a PDF file. Therefore if
Ghostscript does not exist, does not have the proper version, or
fails for any other reason, the EPS file will remain. It can be
used to find the cause, or use another converter or PostScript
compiler.
By default, when the dataset only has two values, this function
will use the PostScript optimization that allows setting the pixel
values per bit,not byte (*note Recognized file formats::). This
can greatly help reduce the file size. However, when
‘dontoptimize!=0’, this optimization is disabled: even though there
are only two values (is binary), the difference between them does
not correspond to the full contrast of black and white.
If ‘marks!=NULL’, it is assumed to contain information on how to
draw marks over the image. This is directly fed to the
‘gal_eps_write’ function, so for more on how to provide the mark
information, see the description of ‘gal_eps_write’ in *note EPS
files::.
File: gnuastro.info, Node: World Coordinate System, Next: Arithmetic on datasets, Prev: File input output, Up: Gnuastro library
12.3.13 World Coordinate System (‘wcs.h’)
-----------------------------------------
The FITS standard defines the world coordinate system (WCS) as a
mechanism to associate physical values to positions within a dataset.
For example, it can be used to convert pixel coordinates in an image to
celestial coordinates like the right ascension and declination. The
functions in this section are mainly just wrappers over CFITSIO, WCSLIB
and GSL library functions to help in common applications.
[*Tread safety*] Since WCSLIB version 5.18 (released in January
2018), most WCSLIB functions are thread safe(1). Gnuastro has
high-level functions to easily spin-off threads and speed up your
programs. For a fully working example see *note Library demo -
multi-threaded operation::. However you still need to be cautious in
the following scenarios below.
• Many users or operating systems may still use an older version.
• The ‘wcsprm’ structure of WCSLIB is not thread-safe: you can't use
the same pointer on multiple threads. For example, if you use
‘gal_wcs_img_to_world’ simultaneously on multiple threads, you
shouldn't pass the same ‘wcsprm’ structure pointer. You can use
‘gal_wcs_copy’ to keep and use separate copies the main structure
within each thread, and later free the copies with ‘gal_wcs_free’.
The full set of functions and global constants that are defined by
Gnuastro's ‘gnuastro/wcs.h’ are described below.
-- Global integer: GAL_WCS_DISTORTION_TPD
-- Global integer: GAL_WCS_DISTORTION_SIP
-- Global integer: GAL_WCS_DISTORTION_TPV
-- Global integer: GAL_WCS_DISTORTION_DSS
-- Global integer: GAL_WCS_DISTORTION_WAT
-- Global integer: GAL_WCS_DISTORTION_INVALID
Gnuastro identifiers of the various WCS distortion conventions, for
more, see Calabretta et al. (2004, preprint)(2). Among these, SIP
is a prior distortion, the rest other are sequent distortions. TPD
is a superset of all these, hence it has both prior and sequeal
distortion coefficients. More information is given in the
documentation of ‘dis.h’, from the WCSLIB manual(3).
-- Global integer: GAL_WCS_COORDSYS_EQB1950
-- Global integer: GAL_WCS_COORDSYS_EQJ2000
-- Global integer: GAL_WCS_COORDSYS_ECB1950
-- Global integer: GAL_WCS_COORDSYS_ECJ2000
-- Global integer: GAL_WCS_COORDSYS_GALACTIC
-- Global integer: GAL_WCS_COORDSYS_SUPERGALACTIC
-- Global integer: GAL_WCS_COORDSYS_INVALID
Recognized WCS coordinate systems in Gnuastro. ‘EQ’ and ‘EC’ stand
for the EQuatorial and ECliptic coordinate systems. In the
equatorial and ecliptic coordinates, ‘B1950’ stands for the
Besselian 1950 epoch and ‘J2000’ stands for the Julian 2000 epoch.
-- Global integer: GAL_WCS_LINEAR_MATRIX_PC
-- Global integer: GAL_WCS_LINEAR_MATRIX_CD
-- Global integer: GAL_WCS_LINEAR_MATRIX_INVALID
Identifiers of the linear transformation matrix: either in the
‘PCi_j’ or the ‘CDi_j’ formalism. For more, see the description of
‘--wcslinearmatrix’ in *note Input output options::.
-- Global integer: GAL_WCS_PROJECTION_AZP
-- Global integer: GAL_WCS_PROJECTION_SZP
-- Global integer: GAL_WCS_PROJECTION_TAN
-- Global integer: GAL_WCS_PROJECTION_STG
-- Global integer: GAL_WCS_PROJECTION_SIN
-- Global integer: GAL_WCS_PROJECTION_ARC
-- Global integer: GAL_WCS_PROJECTION_ZPN
-- Global integer: GAL_WCS_PROJECTION_ZEA
-- Global integer: GAL_WCS_PROJECTION_AIR
-- Global integer: GAL_WCS_PROJECTION_CYP
-- Global integer: GAL_WCS_PROJECTION_CEA
-- Global integer: GAL_WCS_PROJECTION_CAR
-- Global integer: GAL_WCS_PROJECTION_MER
-- Global integer: GAL_WCS_PROJECTION_SFL
-- Global integer: GAL_WCS_PROJECTION_PAR
-- Global integer: GAL_WCS_PROJECTION_MOL
-- Global integer: GAL_WCS_PROJECTION_AIT
-- Global integer: GAL_WCS_PROJECTION_COP
-- Global integer: GAL_WCS_PROJECTION_COE
-- Global integer: GAL_WCS_PROJECTION_COD
-- Global integer: GAL_WCS_PROJECTION_COO
-- Global integer: GAL_WCS_PROJECTION_BON
-- Global integer: GAL_WCS_PROJECTION_PCO
-- Global integer: GAL_WCS_PROJECTION_TSC
-- Global integer: GAL_WCS_PROJECTION_CSC
-- Global integer: GAL_WCS_PROJECTION_QSC
-- Global integer: GAL_WCS_PROJECTION_HPX
-- Global integer: GAL_WCS_PROJECTION_XPH
The various types of recognized FITS WCS projections; for more
details see *note Align pixels with WCS considering distortions::.
-- Macro: GAL_WCS_FLTERROR
Limit of rounding for floating point errors.
-- Function:
int
gal_wcs_distortion_name_to_id (char *name)
Convert the given string (assumed to be a FITS-standard,
string-based distortion identifier) to a Gnuastro's integer-based
distortion identifier (one of the ‘GAL_WCS_DISTORTION_*’ macros
defined above). The sting-based distortion identifiers have three
characters and are all in capital letters.
-- Function:
int
gal_wcs_distortion_name_from_id (int id)
Convert the given Gnuastro integer-based distortion identifier (one
of the ‘GAL_WCS_DISTORTION_*’ macros defined above) to the
string-based distortion identifier) of the FITS standard. The
sting-based distortion identifiers have three characters and are
all in capital letters.
-- Function:
int
gal_wcs_coordsys_name_to_id (char *name)
Convert the given string to Gnuastro's integer-based WCS coordinate
system identifier (one of the ‘GAL_WCS_COORDSYS_*’, listed above).
The expected strings can be seen in the description of the
‘--wcscoordsys’ option of the Fits program, see *note Keyword
inspection and manipulation::.
-- Function:
int
gal_wcs_distortion_name_to_id (char *name)
Convert the given string (assumed to be a FITS-standard,
string-based distortion identifier) to a Gnuastro's integer-based
distortion identifier (one of the ‘GAL_WCS_DISTORTION_*’ macros
defined above). The sting-based distortion identifiers have three
characters and are all in capital letters.
-- Function:
int
gal_wcs_projection_name_from_id (int id)
Convert the given Gnuastro integer-based projection identifier (one
of the ‘GAL_WCS_PROJECTION_*’ macros defined above) to the
string-based distortion identifier) of the FITS standard. The
string-based projection identifiers have three characters and are
all in capital letters. For a description of the various
projections, see *note Align pixels with WCS considering
distortions::.
-- Function:
int
gal_wcs_projection_name_to_id (char *name)
Convert the given string (assumed to be a FITS-standard,
string-based projection identifier) to a Gnuastro's integer-based
projection identifier (one of the ‘GAL_WCS_PROJECTION_*’ macros
defined above). The string-based projection identifiers have three
characters and are all in capital letters. For a description of
the various projections, see *note Align pixels with WCS
considering distortions::.
-- Function:
struct wcsprm *
gal_wcs_create (double *crpix, double *crval, double *cdelt,
double *pc, char **cunit, char **ctype, size_t ndim, int
linearmatrix)
Given all the most common standard components of the WCS standard,
construct a ‘struct wcsprm’, initialize and set it for future
processing. See the FITS WCS standard for more on these keywords.
All the arrays must have ‘ndim’ elements with them except for ‘pc’
which should have ‘ndim*ndim’ elements (a square matrix). Also,
‘cunit’ and ‘ctype’ are arrays of strings. If
‘GAL_WCS_LINEAR_MATRIX_CD’ is passed to ‘linearmatrix’ then the
output WCS structure will have a CD matrix (even though you have
given a PC and CDELT matrix as input to this function). Otherwise,
the output will have a PC and CDELT matrix (which is the
recommended format by WCSLIB).
#include <stdio.h>
#include <stdlib.h>
#include <gnuastro/wcs.h>
int
main(void)
{
int status;
size_t ndim=2;
struct wcsprm *wcs;
double crpix[]={50, 50};
double pc[]={-1, 0, 0, 1};
double cdelt[]={0.4, 0.4};
double crval[]={178.23, 36.98};
char *cunit[]={"deg", "deg"};
char *ctype[]={"RA---TAN", "DEC--TAN"};
int linearmatrix = GAL_WCS_LINEAR_MATRIX_PC;
/* Allocate and fill the 'wcsprm' structure. */
wcs=gal_wcs_create(crpix, crval, cdelt, pc, cunit,
ctype, ndim, linearmatrix);
printf("WCS structure created.\n");
/*... Add any operation with the WCS structure here ...*/
/* Free the WCS structure. */
gal_wcs_free(wcs);
printf("WCS structure freed.\n");
/* Return successfully. */
return EXIT_SUCCESS;
}
-- Function:
struct wcsprm *
gal_wcs_read_fitsptr (fitsfile *fptr, int linearmatrix, size_t
hstartwcs, size_t hendwcs, int *nwcs)
Return the WCSLIB ‘wcsprm’ structure that is read from the CFITSIO
‘fptr’ pointer to an opened FITS file. With older WCSLIB versions
(in particular below version 5.18) this function may not be
thread-safe.
Also put the number of coordinate representations found into the
space that ‘nwcs’ points to. To read the WCS structure directly
from a filename, see ‘gal_wcs_read’ below. After processing has
finished, you should free the WCS structure that this function
returns with ‘gal_wcs_free’.
The ‘linearmatrix’ argument takes one of three values: ‘0’,
‘GAL_WCS_LINEAR_MATRIX_PC’ and ‘GAL_WCS_LINEAR_MATRIX_CD’. It will
determine the format of the WCS when it is later written to file
with ‘gal_wcs_write’ or ‘gal_wcs_write_in_fitsptr’ (which is called
by ‘gal_fits_img_write’) So if you do not want to write the WCS
into a file later, just give it a value of ‘0’. For more on the
difference between these modes, see the description of
‘--wcslinearmatrix’ in *note Input output options::.
If you do not want to search the full FITS header for WCS-related
FITS keywords (for example, due to conflicting keywords), but only
a specific range of the header keywords you can use the ‘hstartwcs’
and ‘hendwcs’ arguments to specify the keyword number range
(counting from zero). If ‘hendwcs’ is larger than ‘hstartwcs’,
then only keywords in the given range will be checked. Hence, to
ignore this feature (and search the full FITS header), give both
these arguments the same value.
If the WCS information could not be read from the FITS file, this
function will return a ‘NULL’ pointer and put a zero in ‘nwcs’. A
WCSLIB error message will also be printed in ‘stderr’ if there was
an error.
This function is just a wrapper over WCSLIB's ‘wcspih’ function
which is not thread-safe. Therefore, be sure to not call this
function simultaneously (over multiple threads).
-- Function:
struct wcsprm *
gal_wcs_read (char *filename, char *hdu, int linearmatrix,
size_t hstartwcs, size_t hendwcs, int *nwcs, char
*hdu_option_name)
[*Not thread-safe*] Return the WCSLIB structure that is read from
the HDU/extension ‘hdu’ of the file ‘filename’. Also put the
number of coordinate representations found into the space that
‘nwcs’ points to. Please see ‘gal_wcs_read_fitsptr’ for more. For
more on ‘hdu_option_name’ see the description of ‘gal_array_read’
in *note Array input output::.
After processing has finished, you should free the WCS structure
that this function returns with ‘gal_wcs_free’.
-- Function:
void
gal_wcs_free (struct wcsprm *wcs)
Free the contents _and_ the space that ‘wcs’ points to. WCSLIB's
‘wcsfree’ function only frees the contents of the ‘wcsprm’
structure, not the actual pointer. However, Gnuastro's ‘wcsprm’
creation and reading functions allocate the structure also. This
higher-level function therefore simplifies the processing. A
complete working example is given in the description of
‘gal_wcs_create’.
-- Function:
char *
gal_wcs_dimension_name (struct wcsprm *wcs, size_t dimension)
Return an allocated string array (that should be freed later)
containing the first part of the ‘CTYPEi’ FITS keyword (which
contains the dimension name in the FITS standard). For example, if
‘CTYPE1’ is ‘RA---TAN’, the string that function returns will be
‘RA’. Recall that the second component of ‘CTYPEi’ contains the
type of projection.
-- Function:
char *
gal_wcs_write_wcsstr (struct wcsprm *wcs, int *nkeyrec)
Return an allocated string which contains the respective FITS
keywords for the given WCS structure into it. The number of
keywords is written in the space pointed by ‘nkeyrec’. Each FITS
keyword is 80 characters wide (according to the FITS standard), and
the next one is placed immediately after it, so the full string has
‘80*nkeyrec’ bytes. The output of this function can later be
written into an opened FITS file using ‘gal_fits_key_write_wcsstr’
(see *note FITS header keywords::).
-- Function:
void
gal_wcs_write (struct wcsprm *wcs, char *filename, char
*extname, gal_fits_list_key_t *keylist, int freekeys)
Write the given WCS structure into the second extension of an empty
FITS header. The first/primary extension will be empty like the
default format of all Gnuastro outputs. When ‘extname!=NULL’ it
will be used as the FITS extension name. Any set of extra headers
can also be written through the ‘keylist’ list. If ‘freekeys!=0’
then the list of keywords will be freed after they are written.
-- Function:
void
gal_wcs_write_in_fitsptr (fitsfile *fptr, struct wcsprm *wcs)
Convert the input ‘wcs’ structure (keeping the WCS
programmatically) into FITS keywords and write them into the given
FITS file pointer. This is a relatively low-level function which
assumes the FITS file has already been opened with CFITSIO. If you
just want to write the WCS into an empty file, you can use
‘gal_wcs_write’ (which internally calls this function after
creating the FITS file and later closes it safely).
-- Function:
struct wcsprm *
gal_wcs_copy (struct wcsprm *wcs)
Return a fully allocated (independent) copy of ‘wcs’.
-- Function:
struct wcsprm *
gal_wcs_copy_new_crval (struct wcsprm *wcs, double *crval)
Return a fully allocated (independent) copy of ‘wcs’ with a new set
of ‘CRVAL’ values. WCSLIB keeps a lot of extra information within
‘wcsprm’ and for optimizations, those extra information are used in
its calculations. Therefore, if you want to change parameters like
the reference point's sky coordinate values (‘CRVAL’), simply
changing the values in ‘wcs->crval[0]’ or ‘wcs->crval[1]’ will not
affect WCSLIB's calculations; you need to call this function.
-- Function:
void
gal_wcs_remove_dimension (struct wcsprm *wcs, size_t fitsdim)
Remove the given FITS dimension from the given ‘wcs’ structure.
-- Function:
void
gal_wcs_on_tile (gal_data_t *tile)
Create a WCSLIB ‘wcsprm’ structure for ‘tile’ using WCS parameters
of the tile's allocated block dataset, see *note Tessellation
library:: for the definition of tiles. If ‘tile’ already has a WCS
structure, this function will not do anything.
In many cases, tiles are created for internal/low-level processing.
Hence for performance reasons, when creating the tiles they do not
have any WCS structure. When needed, this function can be used to
add a WCS structure to each tile tile by copying the WCS structure
of its block and correcting the reference point's coordinates
within the tile.
-- Function:
double *
gal_wcs_warp_matrix (struct wcsprm *wcs)
Return the Warping matrix of the given WCS structure as an array of
double precision floating points. This will be the final matrix,
irrespective of the type of storage in the WCS structure. Recall
that the FITS standard has several methods to store the matrix.
The output is an allocated square matrix with each side equal to
the number of dimensions.
-- Function:
void
gal_wcs_clean_small_errors (struct wcsprm *wcs)
Errors can make small differences between the pixel-scale elements
(‘CDELT’) and can also lead to extremely small values in the ‘PC’
matrix. With this function, such errors will be "cleaned" as
follows: 1) if the maximum difference between the ‘CDELT’ elements
is smaller than the reference error, it will be set to the mean
value. When the FITS keyword ‘CRDER’ (optional) is defined it will
be used as a reference, if not the default value is
‘GAL_WCS_FLTERROR’. 2) If any of the PC elements differ from 0, 1
or -1 by less than ‘GAL_WCS_FLTERROR’, they will be rounded to the
respective value.
-- Function:
void
gal_wcs_decompose_pc_cdelt (struct wcsprm *wcs)
Decompose the ‘PCi_j’ and ‘CDELTi’ elements of ‘wcs’. According to
the FITS standard, in the ‘PCi_j’ WCS formalism, the rotation
matrix elements $m_{ij}$ are encoded in the ‘PCi_j’ keywords and
the scale factors are encoded in the ‘CDELTi’ keywords. There is
also another formalism (the ‘CDi_j’ formalism) which merges the two
into one matrix.
However, WCSLIB's internal operations are apparently done in the
‘PCi_j’ formalism. So its outputs are also all in that format by
default. When the input is a ‘CDi_j’, WCSLIB will still read the
matrix directly into the ‘PCi_j’ matrix and the ‘CDELTi’ values are
set to ‘1’ (one). This function is designed to correct such
issues: after it is finished, the ‘CDELTi’ values in ‘wcs’ will
correspond to the pixel scale, and the ‘PCi_j’ will correction show
the rotation.
-- Function:
void
gal_wcs_to_cd (struct wcsprm *wcs)
Make sure that the WCS structure's ‘PCi_j’ and ‘CDi_j’ keywords
have the same value and that the ‘CDELTi’ keywords have a value of
1.0. Also, set the ‘wcs->altlin=2’ (for the ‘CDi_j’ formalism).
With these changes ‘gal_wcs_write_in_fitsptr’ (and thus
‘gal_wcs_write’ and ‘gal_fits_img_write’ and its derivatives) will
have an output file in the format of ‘CDi_j’.
-- Function:
int
gal_wcs_coordsys_identify (struct wcsprm *wcs)
Read the given WCS structure and return its coordinate system as
one of Gnuastro's WCS coordinate system identifiers (the macros
‘GAL_WCS_COORDSYS_*’, listed above).
-- Function:
struct wcsprm *
gal_wcs_coordsys_convert (struct wcsprm *inwcs, int
coordsysid)
Return a newly allocated WCS structure with the ‘coordsysid’
coordinate system identifier. The Gnuastro WCS distortion
identifiers are defined in the ‘GAL_WCS_COORDSYS_*’ macros
mentioned above. Since the returned dataset is newly allocated, if
you do not need the original dataset after this, use the WCSLIB
library function ‘wcsfree’ to free the input, for example,
‘wcsfree(inwcs)’.
-- Function:
void
gal_wcs_coordsys_convert_points (int sys1, double *lng1_d,
double *lat1_d, int sys2, double *lng2_d, double *lat2_d,
size_t number)
Convert the input set of longitudes (‘lng1_d’, in degrees) and
latitudes (‘lat1_d’, in degrees) within a recognized coordinate
system (‘sys1’; one of the ‘GAL_WCS_COORDSYS_*’ macros above) into
an output coordinate system (‘sys2’). The output values are
written in ‘lng2_d’ and ‘lng2_d’. The total number of points
should be given in ‘number’. If you want the operation to be done
in place (without allocating a new dataset), give the same pointers
to the coordinate arguments.
-- Function:
void
gal_wcs_coordsys_sys1_ref_in_sys2 (int sys1, int sys2, double
*lng2, double *lat2)
Return the longitude and latitude of the reference point (on the
equator) of the first coordinate system (‘sys1’) within the second
system (‘sys2’). Coordinate systems are identified by the
‘GAL_WCS_COORDSYS_*’ macros above.
-- Function:
int
gal_wcs_distortion_identify (struct wcsprm *wcs)
Returns the Gnuastro identifier for the distortion of the input WCS
structure. The returned value is one of the ‘GAL_WCS_DISTORTION_*’
macros defined above. When the input pointer to a structure is
‘NULL’, or it does not contain a distortion, the returned value
will be ‘GAL_WCS_DISTORTION_INVALID’.
-- Function:
struct wcsprm *
gal_wcs_distortion_convert(struct wcsprm *inwcs, int
outdisptype, size_t *fitsize)
Return a newly allocated WCS structure, where the distortion is
implemented in a different standard, identified by the identifier
‘outdisptype’. The Gnuastro WCS distortion identifiers are defined
in the ‘GAL_WCS_DISTORTION_*’ macros mentioned above.
The available conversions in this function will grow. Currently it
only supports converting TPV to SIP and vice versa, following the
recipe of Shupe et al. (2012)(4). Please get in touch with us if
you need other types of conversions.
For some conversions, direct analytical conversions do not exist.
It is thus necessary to model and fit the two types. In such
cases, it is also necessary to specify the ‘fitsize’ array that is
the size of the array along each C-ordered dimension, so you can
simply pass the ‘dsize’ element of your ‘gal_data_t’ dataset, see
*note Generic data container::. Currently this is only necessary
when converting TPV to SIP. For other conversions you may simply
pass a ‘NULL’ pointer.
For example, if you want to convert the TPV coefficients of your
input ‘image.fits’ to SIP coefficients, you can use the following
functions (which are also available as a command-line operation in
*note Fits::).
int nwcs;
gal_data_t *data=gal_fits_img_read("image.fits", "1", -1, 1, NULL);
inwcs=gal_wcs_read("image.fits", "1", 0, 0, 0, &nwcs, NULL);
data->wcs=gal_wcs_distortion_convert(inwcs, GAL_WCS_DISTORTION_TPV,
NULL);
wcsfree(inwcs);
gal_fits_img_write(data, "tpv.fits", NULL, 0);
-- Function:
double
gal_wcs_angular_distance_deg (double r1, double d1, double r2,
double d2)
Return the angular distance (in degrees) between a point located at
(‘r1’, ‘d1’) to (‘r2’, ‘d2’). All input coordinates are in
degrees. The distance (along a great circle) on a sphere between
two points is calculated with the equation below.
$$\cos(d)=\sin(d_1)\sin(d_2)+\cos(d_1)\cos(d_2)\cos(r_1-r_2)$$
However, since the pixel scales are usually very small numbers,
this function will not use that direct formula. It will be use the
Haversine formula (https://en.wikipedia.org/wiki/Haversine_formula)
which is better considering floating point errors:
$${\sin^2(d)\over 2}=\sin^2\left( {d_1-d_2\over 2} \right)+\cos(d_1)\cos(d_2)\sin^2\left( {r_1-r_2\over 2} \right)$$
-- Function:
void
gal_wcs_box_vertices_from_center (double ra_center, double
dec_center, double ra_delta, double dec_delta, double *out)
Calculate the vertices of a rectangular box given the central RA
and Dec and delta of each. The vertice coordinates are written in
the space that ‘out’ points to (assuming it has space for eight
‘double’s).
Given the spherical nature of the coordinate system, the vertice
lengths can't be calculated with a simple addition/subtraction.
For the declination, a simple addition/subtraction is enough.
Also, on the equator (where the RA is defined), a simple
addition/subtraction along the RA is fine. However, at other
declinations, the new RA after a shift needs special treatment,
such that close to the poles, a shift of 1 degree can correspond to
a new RA that is much more distant than the original RA. Assuming a
point at Right Ascension (RA) and Declination of $\alpha$ and
$\delta$, a shift of $R$ degrees along the positive RA direction
corresponds to a right ascension of
$\alpha+\frac{R}{\cos(\delta)}$. For more, see the description of
‘box-vertices-on-sphere’ in *note Coordinate and border
operators::.
The 8 coordinates of the 4 vertices of the box are written in the
order below. Where "bottom" corresponds to a lower declination and
"top" to higher declination, "left" corresponds to a larger RA and
"right" corresponds to lower RA.
out[0]: bottom-left RA
out[1]: bottom-left Dec
out[2]: bottom-right RA
out[3]: bottom-right Dec
out[4]: top-right RA
out[5]: top-right Dec
out[6]: top-left RA
out[7]: top-left Dec
-- Function:
double *
gal_wcs_pixel_scale (struct wcsprm *wcs)
Return the pixel scale for each dimension of ‘wcs’ in degrees. The
output is an allocated array of double precision floating point
type with one element for each dimension. If it is not successful,
this function will return ‘NULL’.
-- Function:
double
gal_wcs_pixel_area_arcsec2 (struct wcsprm *wcs)
Return the pixel area of ‘wcs’ in arc-second squared. This only
works when the input dataset has at least two dimensions and the
units of the first two dimensions (‘CUNIT’ keywords) are ‘deg’ (for
degrees). In other cases, this function will return a NaN.
-- Function:
int
gal_wcs_coverage (char *filename, char *hdu, size_t *ondim,
double **ocenter, double **owidth, double **omin, double
**omax, char *hdu_option_name)
Find the sky coverage of the image HDU (‘hdu’) within ‘filename’.
The number of dimensions is written into ‘ndim’, and space for the
various output arrays is internally allocated and filled with the
respective values. Therefore you need to free them afterwards.
For more on ‘hdu_option_name’ see the description of
‘gal_array_read’ in *note Array input output::.
Currently this function only supports images that are less than 180
degrees in width (which is usually the case!). This requirement
has been necessary to account for images that cross the RA=0 hour
circle on the sky. Please get in touch with us at
<mailto:bug-gnuastro@gnu.org> if you have an image that is larger
than 180 degrees so we try to find a solution based on need.
-- Function:
gal_data_t *
gal_wcs_world_to_img (gal_data_t *coords, struct wcsprm *wcs,
int inplace)
Convert the linked list of world coordinates in ‘coords’ to a
linked list of image coordinates given the input WCS structure.
‘coords’ must be a linked list of data structures of float64
('double') type, see*note Linked lists:: and *note List of
gal_data_t::. The top (first popped/read) node of the linked list
must be the first WCS coordinate (RA in an image usually) etc.
Similarly, the top node of the output will be the first image
coordinate (in the FITS standard). In case WCSLIB fails to convert
any of the coordinates (for example, the RA of one coordinate is
given as 400!), the respective element in the output will be
written as NaN.
If ‘inplace’ is zero, then the output will be a newly allocated
list and the input list will be untouched. However, if ‘inplace’
is non-zero, the output values will be written into the input's
already allocated array and the returned pointer will be the same
pointer to ‘coords’ (in other words, you can ignore the returned
value). Note that in the latter case, only the values will be
changed, things like units or name (if present) will be untouched.
-- Function:
gal_data_t *
gal_wcs_img_to_world (gal_data_t *coords, struct wcsprm *wcs,
int inplace)
Convert the linked list of image coordinates in ‘coords’ to a
linked list of world coordinates given the input WCS structure.
See the description of ‘gal_wcs_world_to_img’ for more details.
---------- Footnotes ----------
(1)
<https://www.atnf.csiro.au/people/mcalabre/WCS/wcslib/threads.html>
(2) <https://www.atnf.csiro.au/people/mcalabre/WCS/dcs_20040422.pdf>
(3)
<https://www.atnf.csiro.au/people/mcalabre/WCS/wcslib/dis_8h.html>
(4) Proc. of SPIE Vol. 8451 84511M-1.
<https://doi.org/10.1117/12.925460>, also available at
<http://web.ipac.caltech.edu/staff/shupe/reprints/SIP_to_PV_SPIE2012.pdf>.
File: gnuastro.info, Node: Arithmetic on datasets, Next: Tessellation library, Prev: World Coordinate System, Up: Gnuastro library
12.3.14 Arithmetic on datasets (‘arithmetic.h’)
-----------------------------------------------
When the dataset's type and other information are already known, any
programming language (including C) provides some very good tools for
various operations (including arithmetic operations like addition) on
the dataset with a simple loop. However, as an author of a program,
making assumptions about the type of data, its dimensions and other
basic characteristics will come with a large processing burden.
For example, if you always read your data as double precision
floating points for a simple operation like addition with an integer
constant, you will be wasting a lot of CPU and memory when the input
dataset is ‘int32’ type for example, (see *note Numeric data types::).
This overhead may be small for small images, but as you scale your
process up and work with hundred/thousands of files that can be very
large, this overhead will take a significant portion of the processing
power. The functions and macros in this section are designed precisely
for this purpose: to allow you to do any of the defined operations on
any dataset with no overhead (in the native type of the dataset).
Gnuastro's Arithmetic program uses the functions and macros of this
section, so please also have a look at the *note Arithmetic:: program
and in particular *note Arithmetic operators:: for a better description
of the operators discussed here.
The main function of this library is ‘gal_arithmetic’ that is
described below. It can take an arbitrary number of arguments as
operands (depending on the operator, similar to ‘printf’). Its first
two arguments are integers specifying the flags and operator. So first
we will review the constants for the recognized flags and operators and
discuss them, then introduce the actual function.
-- Macro: GAL_ARITHMETIC_FLAG_INPLACE
-- Macro: GAL_ARITHMETIC_FLAG_FREE
-- Macro: GAL_ARITHMETIC_FLAG_NUMOK
-- Macro: GAL_ARITHMETIC_FLAG_ENVSEED
-- Macro: GAL_ARITHMETIC_FLAG_QUIET
-- Macro: GAL_ARITHMETIC_FLAGS_BASIC
Bit-wise flags to pass onto ‘gal_arithmetic’ (see below). To pass
multiple flags, use the bitwise-or operator. For example, if you
pass ‘GAL_ARITHMETIC_FLAG_INPLACE | GAL_ARITHMETIC_FLAG_NUMOK’,
then the operation will be done in-place (without allocating a new
array), and a single number will also be acceptable (that will be
applied to all the pixels). Each flag is described below:
‘GAL_ARITHMETIC_FLAG_INPLACE’
Do the operation in-place (in the input dataset, thus
modifying it) to improve CPU and memory usage. If this flag
is used, after ‘gal_arithmetic’ finishes, the input dataset
will be modified. It is thus useful if you have no more need
for the input after the operation.
‘GAL_ARITHMETIC_FLAG_FREE’
Free (all the) input dataset(s) after the operation is done.
Hence the inputs are no longer usable after ‘gal_arithmetic’.
‘GAL_ARITHMETIC_FLAG_NUMOK’
It is acceptable to use a number and an array together. For
example, if you want to add all the pixels in an image with a
single number you can pass this flag to avoid having to
allocate a constant array the size of the image (with all the
pixels having the same number).
‘GAL_ARITHMETIC_FLAG_ENVSEED’
Use the pre-defined environment variable for setting the
random number generator seed when an operator needs it (for
example, ‘mknoise-sigma’). For more on random number
generation in Gnuastro see *note Generating random numbers::.
‘GAL_ARITHMETIC_FLAG_QUIET’
Do not print any warnings or messages for operators that may
benefit from it. For example, by default the ‘mknoise-sigma’
operator prints the random number generator function and seed
that it used (in case the user wants to reproduce this result
later). By activating this bit flag to the call, that extra
information is not printed on the command-line.
‘GAL_ARITHMETIC_FLAGS_BASIC’
A wrapper for activating the three "basic" operations that are
commonly necessary together: ‘GAL_ARITHMETIC_FLAG_INPLACE’,
‘GAL_ARITHMETIC_FLAG_FREE’ and ‘GAL_ARITHMETIC_FLAG_NUMOK’.
-- Macro: GAL_ARITHMETIC_OP_PLUS
-- Macro: GAL_ARITHMETIC_OP_MINUS
-- Macro: GAL_ARITHMETIC_OP_MULTIPLY
-- Macro: GAL_ARITHMETIC_OP_DIVIDE
-- Macro: GAL_ARITHMETIC_OP_LT
-- Macro: GAL_ARITHMETIC_OP_LE
-- Macro: GAL_ARITHMETIC_OP_GT
-- Macro: GAL_ARITHMETIC_OP_GE
-- Macro: GAL_ARITHMETIC_OP_EQ
-- Macro: GAL_ARITHMETIC_OP_NE
-- Macro: GAL_ARITHMETIC_OP_AND
-- Macro: GAL_ARITHMETIC_OP_OR
Binary operators (requiring two operands) that accept datasets of
any recognized type (see *note Numeric data types::). When
‘gal_arithmetic’ is called with any of these operators, it expects
two datasets as arguments. For a full description of these
operators with the same name, see *note Arithmetic operators::.
The first dataset/operand will be put on the left of the operator
and the second will be put on the right. The output type of the
first four is determined from the input types (largest type of the
inputs). The rest (which are all conditional operators) will
output a binary ‘uint8_t’ (or ‘unsigned char’) dataset with values
of either ‘0’ (zero) or ‘1’ (one).
-- Macro: GAL_ARITHMETIC_OP_NOT
The logical NOT operator. When ‘gal_arithmetic’ is called with
this operator, it only expects one operand (dataset), since this is
a unary operator. The output is ‘uint8_t’ (or ‘unsigned char’)
dataset of the same size as the input. Any non-zero element in the
input will be ‘0’ (zero) in the output and any ‘0’ (zero) will have
a value of ‘1’ (one).
-- Macro: GAL_ARITHMETIC_OP_ISBLANK
A unary operator with output that is ‘1’ for any element in the
input that is blank, and ‘0’ for any non-blank element. When
‘gal_arithmetic’ is called with this operator, it will only expect
one input dataset. The output dataset will have ‘uint8_t’ (or
‘unsigned char’) type.
‘gal_arithmetic’ with this operator is just a wrapper for the
‘gal_blank_flag’ function of *note Library blank values:: and this
operator is just included for completeness in arithmetic
operations. So in your program, it might be easier to just call
‘gal_blank_flag’.
-- Macro: GAL_ARITHMETIC_OP_WHERE
The three-operand _where_ operator thoroughly discussed in *note
Arithmetic operators::. When ‘gal_arithmetic’ is called with this
operator, it will only expect three input datasets: the first
(which is the same as the returned dataset) is the array that will
be modified. The second is the condition dataset (that must have a
‘uint8_t’ or ‘unsigned char’ type), and the third is the value to
be used if condition is non-zero.
As a result, note that the order of operands when calling
‘gal_arithmetic’ with ‘GAL_ARITHMETIC_OP_WHERE’ is the opposite of
running Gnuastro's Arithmetic program with the ‘where’ operator
(see *note Arithmetic::). This is because the latter uses the
reverse-Polish notation which is not necessary when calling a
function (see *note Reverse polish notation::).
-- Macro: GAL_ARITHMETIC_OP_SQRT
-- Macro: GAL_ARITHMETIC_OP_LOG
-- Macro: GAL_ARITHMETIC_OP_LOG10
Unary operator functions for calculating the square root
($\sqrt{i}$), $ln(i)$ and $log(i)$ mathematical operators on each
element of the input dataset. The returned dataset will have a
floating point type, but its precision is determined from the
input: if the input is a 64-bit floating point, the output will
also be 64-bit. Otherwise, the returned dataset will be 32-bit
floating point: you do not gain precision by using these operators,
but you gain in operating speed if you use the sufficient
precision. See *note Numeric data types:: for more on the
precision of floating point numbers to help in selecting your
required floating point precision.
If you want your output to be 64-bit floating point but your input
is a different type, you can convert the input to a 64-bit floating
point type with ‘gal_data_copy_to_new_type’ or
‘gal_data_copy_to_new_type_free’(see *note Copying datasets::).
Alternatively, you can use the ‘GAL_ARITHMETIC_OP_TO_FLOAT64’
operators in the arithmetic library.
-- Macro: GAL_ARITHMETIC_OP_SIN
-- Macro: GAL_ARITHMETIC_OP_COS
-- Macro: GAL_ARITHMETIC_OP_TAN
-- Macro: GAL_ARITHMETIC_OP_ASIN
-- Macro: GAL_ARITHMETIC_OP_ACOS
-- Macro: GAL_ARITHMETIC_OP_ATAN
-- Macro: GAL_ARITHMETIC_OP_ATAN2
Trigonometric functions (and their inverse). All the angles,
either inputs or outputs, are in units of degrees.
-- Macro: GAL_ARITHMETIC_OP_SINH
-- Macro: GAL_ARITHMETIC_OP_COSH
-- Macro: GAL_ARITHMETIC_OP_TANH
-- Macro: GAL_ARITHMETIC_OP_ASINH
-- Macro: GAL_ARITHMETIC_OP_ACOSH
-- Macro: GAL_ARITHMETIC_OP_ATANH
Hyperbolic functions (and their inverse).
-- Macro: GAL_ARITHMETIC_OP_RA_TO_DEGREE
-- Macro: GAL_ARITHMETIC_OP_DEC_TO_DEGREE
-- Macro: GAL_ARITHMETIC_OP_DEGREE_TO_RA
-- Macro: GAL_ARITHMETIC_OP_DEGREE_TO_DEC
Unary operators to convert between degrees (as a single floating
point number) to the sexagesimal Right Ascension and Declination
format (as strings, respectively in the format of ‘_h_m_s’ and
‘_d_m_s’). The first two operators expect a string operand (in the
sexagesimal formats mentioned above, but also in the ‘_:_:_’) and
will return a double-precision floating point operand. The latter
two are the opposite.
-- Macro: GAL_ARITHMETIC_OP_COUNTS_TO_MAG
-- Macro: GAL_ARITHMETIC_OP_MAG_TO_COUNTS
-- Macro: GAL_ARITHMETIC_OP_MAG_TO_SB
-- Macro: GAL_ARITHMETIC_OP_SB_TO_MAG
-- Macro: GAL_ARITHMETIC_OP_COUNTS_TO_JY
-- Macro: GAL_ARITHMETIC_OP_JY_TO_COUNTS
-- Macro: GAL_ARITHMETIC_OP_MAG_TO_JY
-- Macro: GAL_ARITHMETIC_OP_JY_TO_MAG
-- Macro: GAL_ARITHMETIC_OP_MAG_TO_NANOMAGGY
-- Macro: GAL_ARITHMETIC_OP_NANOMAGGY_TO_MAG
Binary operators for converting brightness and surface brightness
units to and from each other. The first operand to all of them are
the values in the input unit (left of the ‘-TO-’, for example
counts in ‘COUNTS_TO_MAG’). The second popped operand is the zero
point (right of the ‘-TO-’, for example magnitudes in
‘COUNTS_TO_MAG’). The exceptions are the operators that involve
surface brightness (those with ‘SB’). For the surface brightness
related operators, the second popped operand is the area in units
of arcsec$^2$ and the third popped operand is the final unit.
-- Macro: GAL_ARITHMETIC_OP_COUNTS_TO_SB
-- Macro: GAL_ARITHMETIC_OP_SB_TO_COUNTS
Operators for converting counts to surface brightness and
vice-versa. These operators take three operands: 1) the input
dataset in units of counts or surface brightness (depending on the
operator), 2) the zero point, 3) the area in units of arcsec$^2$.
-- Macro: GAL_ARITHMETIC_OP_AU_TO_PC
-- Macro: GAL_ARITHMETIC_OP_PC_TO_AU
-- Macro: GAL_ARITHMETIC_OP_LY_TO_PC
-- Macro: GAL_ARITHMETIC_OP_PC_TO_LY
-- Macro: GAL_ARITHMETIC_OP_LY_TO_AU
-- Macro: GAL_ARITHMETIC_OP_AU_TO_LY
Unary operators to convert various distance units to and from each
other: Astronomical Units (AU), Parsecs (PC) and Light years (LY).
-- Macro: GAL_ARITHMETIC_OP_MINVAL
-- Macro: GAL_ARITHMETIC_OP_MAXVAL
-- Macro: GAL_ARITHMETIC_OP_NUMBERVAL
-- Macro: GAL_ARITHMETIC_OP_SUMVAL
-- Macro: GAL_ARITHMETIC_OP_MEANVAL
-- Macro: GAL_ARITHMETIC_OP_STDVAL
-- Macro: GAL_ARITHMETIC_OP_MEDIANVAL
Unary operand statistical operators that will return a single value
for datasets of any size. These are just wrappers around similar
functions in *note Statistical operations:: and are included in
‘gal_arithmetic’ only for completeness (to use easily in *note
Arithmetic::). In your programs, it will probably be easier if you
use those ‘gal_statistics_’ functions directly.
-- Macro: GAL_ARITHMETIC_OP_UNIQUE
-- Macro: GAL_ARITHMETIC_OP_NOBLANK
Unary operands that will remove some elements from the input
dataset. The first will return the unique elements, and the second
will return the non-blank elements. Due to the removal of
elements, the dimensionality of the output will be lost.
These are just wrappers over the ‘gal_statistics_unique’ and
‘gal_blank_remove’. These are just wrappers around similar
functions in *note Statistical operations:: and are included in
‘gal_arithmetic’ only for completeness (to use easily in *note
Arithmetic::). In your programs, it will probably be easier if you
use those ‘gal_statistics_’ functions directly.
-- Macro: GAL_ARITHMETIC_OP_ABS
Unary operand absolute-value operator.
-- Macro: GAL_ARITHMETIC_OP_MIN
-- Macro: GAL_ARITHMETIC_OP_MAX
-- Macro: GAL_ARITHMETIC_OP_NUMBER
-- Macro: GAL_ARITHMETIC_OP_SUM
-- Macro: GAL_ARITHMETIC_OP_MEAN
-- Macro: GAL_ARITHMETIC_OP_STD
-- Macro: GAL_ARITHMETIC_OP_MEDIAN
Multi-operand statistical operations. When ‘gal_arithmetic’ is
called with any of these operators, it will expect only a single
operand that will be interpreted as a list of datasets (see *note
List of gal_data_t::). These operators can work on multiple
threads using the ‘numthreads’ argument. See the discussion under
the ‘min’ operator in *note Arithmetic operators::.
The output will be a single dataset with each of its elements
replaced by the respective statistical operation on the whole list.
The type of the output is determined from the operator
(irrespective of the input type): for ‘GAL_ARITHMETIC_OP_MIN’ and
‘GAL_ARITHMETIC_OP_MAX’, it will be the same type as the input, for
‘GAL_ARITHMETIC_OP_NUMBER’, the output will be ‘GAL_TYPE_UINT32’
and for the rest, it will be ‘GAL_TYPE_FLOAT32’.
-- Macro: GAL_ARITHMETIC_OP_QUANTILE
Similar to the operands above (including ‘GAL_ARITHMETIC_MIN’),
except that when ‘gal_arithmetic’ is called with these operators,
it requires two arguments. The first is the list of datasets like
before, and the second is the 1-element dataset with the quantile
value. The output type is the same as the inputs.
-- Macro: GAL_ARITHMETIC_OP_SIGCLIP_STD
-- Macro: GAL_ARITHMETIC_OP_SIGCLIP_MEAN
-- Macro: GAL_ARITHMETIC_OP_SIGCLIP_MEDIAN
-- Macro: GAL_ARITHMETIC_OP_SIGCLIP_NUMBER
Similar to the operands above (including ‘GAL_ARITHMETIC_MIN’),
except that when ‘gal_arithmetic’ is called with these operators,
it requires two arguments. The first is the list of datasets like
before, and the second is the 2-element list of $\sigma$-clipping
parameters. The first element in the parameters list is the
multiple of sigma and the second is the termination criteria (see
*note Sigma clipping::). The output type of
‘GAL_ARITHMETIC_OP_SIGCLIP_NUMBER’ will be ‘GAL_TYPE_UINT32’ and
for the rest it will be ‘GAL_TYPE_FLOAT32’.
-- Macro: GAL_ARITHMETIC_OP_MKNOISE_SIGMA
-- Macro: GAL_ARITHMETIC_OP_MKNOISE_POISSON
-- Macro: GAL_ARITHMETIC_OP_MKNOISE_UNIFORM
Add noise to the input dataset. These operators take two
arguments: the first is the input data set (can have any
dimensionality or number of elements. The second argument is the
noise specifier (a single element, of any type): for a fixed-sigma
noise, it is the Gaussian standard deviation, for the Poisson
noise, it is the background (see *note Photon counting noise::) and
for the uniform distribution it is the width of the interval around
each element of the input dataset.
By default, a separate random number generator seed will be used on
each separate run of these operators. Therefore two identical runs
on the same input will produce different results. You can get
reproducible results by setting the ‘GAL_RNG_SEED’ environment
variable and activating the ‘GAL_ARITHMETIC_FLAG_ENVSEED’ flag.
For more on random number generation in Gnuastro, see *note
Generating random numbers::.
By default these operators will print the random number generator
function and seed (in case the user wants to reproduce the result
later), but this can be disabled by activating the bit-flag
‘GAL_ARITHMETIC_FLAG_QUIET’ described above.
-- Macro: GAL_ARITHMETIC_OP_RANDOM_FROM_HIST
-- Macro: GAL_ARITHMETIC_OP_RANDOM_FROM_HIST_RAW
Select random values from a custom distribution (defined by a
histogram). For more, see the description of the respective
operators in *note Generating random numbers::.
-- Macro: GAL_ARITHMETIC_OP_STITCH
Stitch a list of input datasets along the requested dimension. See
the description of the ‘stitch’ operator in Arithmetic (*note
Dimensionality changing operators::).
-- Macro: GAL_ARITHMETIC_OP_POW
Binary operator to-power operator. When ‘gal_arithmetic’ is called
with any of these operators, it will expect two operands: raising
the first by the second (returning a floating point, inputs can be
integers).
-- Macro: GAL_ARITHMETIC_OP_BITAND
-- Macro: GAL_ARITHMETIC_OP_BITOR
-- Macro: GAL_ARITHMETIC_OP_BITXOR
-- Macro: GAL_ARITHMETIC_OP_BITLSH
-- Macro: GAL_ARITHMETIC_OP_BITRSH
-- Macro: GAL_ARITHMETIC_OP_MODULO
Binary integer-only operand operators. These operators are only
defined on integer data types. When ‘gal_arithmetic’ is called
with any of these operators, it will expect two operands: the first
is put on the left of the operator and the second on the right.
The ones starting with ‘BIT’ are the respective bit-wise operators
in C and ‘MODULO’ is the modulo/remainder operator. For a
discussion on these operators, please see *note Arithmetic
operators::.
The output type is determined from the input types and C's internal
conversions: it is strongly recommended that both inputs have the
same type (any integer type), otherwise the bit-wise behavior will
be determined by your compiler.
-- Macro: GAL_ARITHMETIC_OP_BITNOT
The unary bit-wise NOT operator. When ‘gal_arithmetic’ is called
with any of these operators, it will expect one operand of an
integer type and preform the bitwise-NOT operation on it. The
output will have the same type as the input.
-- Macro: GAL_ARITHMETIC_OP_TO_UINT8
-- Macro: GAL_ARITHMETIC_OP_TO_INT8
-- Macro: GAL_ARITHMETIC_OP_TO_UINT16
-- Macro: GAL_ARITHMETIC_OP_TO_INT16
-- Macro: GAL_ARITHMETIC_OP_TO_UINT32
-- Macro: GAL_ARITHMETIC_OP_TO_INT32
-- Macro: GAL_ARITHMETIC_OP_TO_UINT64
-- Macro: GAL_ARITHMETIC_OP_TO_INT64
-- Macro: GAL_ARITHMETIC_OP_TO_FLOAT32
-- Macro: GAL_ARITHMETIC_OP_TO_FLOAT64
Unary type-conversion operators. When ‘gal_arithmetic’ is called
with any of these operators, it will expect one operand and convert
it to the requested type. Note that with these operators,
‘gal_arithmetic’ is just a wrapper over the
‘gal_data_copy_to_new_type’ or ‘gal_data_copy_to_new_type_free’
that are discussed in ‘Copying datasets’. It accepts these
operators only for completeness and easy usage in *note
Arithmetic::. So in your programs, it might be preferable to
directly use those functions.
-- Macro: GAL_ARITHMETIC_OP_E
-- Macro: GAL_ARITHMETIC_OP_C
-- Macro: GAL_ARITHMETIC_OP_G
-- Macro: GAL_ARITHMETIC_OP_H
-- Macro: GAL_ARITHMETIC_OP_AU
-- Macro: GAL_ARITHMETIC_OP_LY
-- Macro: GAL_ARITHMETIC_OP_PI
-- Macro: GAL_ARITHMETIC_OP_AVOGADRO
-- Macro: GAL_ARITHMETIC_OP_FINESTRUCTURE
Return the respective mathematical constant. For their description
please see *note Constants::. The constant values are taken from
the GNU Scientific Library's headers (defined in ‘gsl/gsl_math.h’).
-- Macro: GAL_ARITHMETIC_OP_BOX_AROUND_ELLIPSE
Return the width (along horizontal) and height (along vertical) of
a box that encompasses an ellipse with the same center point. For
more on the three input operands to this operator see the
description of ‘box-around-ellipse’. This function returns two
datasets as a ‘gal_data_t’ linked list. The top element of the
list is the height and its next element is the width.
-- Macro: GAL_ARITHMETIC_OP_BOX_VERTICES_ON_SPHERE
Return the vertices of a (possibly rectangular) box on a sphere,
given its center RA, Dec and the width of the box along the two
dimensions. It will take the spherical nature of the coordinate
system into account (for more, see the description of
‘gal_wcs_box_vertices_from_center’ in *note World Coordinate
System::). This function returns 8 datasets as a ‘gal_data_t’
linked list in the following order: bottom-left RA, bottom-left
Dec, bottom-right RA, bottom-right Dec, top-right RA, top-right
Dec, top-left RA, top-left Dec.
-- Macro: GAL_ARITHMETIC_OP_MAKENEW
Create a new, zero-valued dataset with an unsigned 8-bit data type.
The length along each dimension of the dataset should be given as a
single list of ‘gal_data_t’s. The number of dimensions is derived
from the number of nodes in the list and the length along each
dimension is the single-valued element within that list. Just note
that the list should be in the reverse of the desired dimensions.
-- Macro: GAL_ARITHMETIC_OP_MAKENEW
Given a dataset and a constant,
-- Macro: GAL_ARITHMETIC_OPSTR_LOADCOL_HDU
-- Macro: GAL_ARITHMETIC_OPSTR_LOADCOL_FILE
-- Macro: GAL_ARITHMETIC_OPSTR_LOADCOL_PREFIX
-- Macro: GAL_ARITHMETIC_OPSTR_LOADCOL_HDU_LEN
-- Macro: GAL_ARITHMETIC_OPSTR_LOADCOL_FILE_LEN
-- Macro: GAL_ARITHMETIC_OPSTR_LOADCOL_PREFIX_LEN
Constant components of the ‘load-col-’ operator (see *note Loading
external columns::). These are just fixed strings (and their
lengths) that are placed in between the various components of that
operator to allow choosing a certain column of a certain HDU of a
certain file.
-- Macro: GAL_ARITHMETIC_OP_INDEX
-- Macro: GAL_ARITHMETIC_OP_COUNTER
-- Macro: GAL_ARITHMETIC_OP_INDEXONLY
-- Macro: GAL_ARITHMETIC_OP_COUNTERONLY
Return a dataset with the same number of elements and
dimensionality as the first (and only!) input dataset. But each
output pixel's value will be replaced by its index (counting from
0) or counter (counting from 1). Note that the
‘GAL_ARITHMETIC_OP_INDEX’ and ‘GAL_ARITHMETIC_OP_INDEXONLY’
operators are identical within the library (same for the counter
operators). They are given separate macros here to help the
higher-level callers to manage their inputs separately (see *note
Size and position operators::).
-- Macro: GAL_ARITHMETIC_OP_SIZE
Size operator that will return a single value for datasets of any
kind. When ‘gal_arithmetic’ is called with this operator, it
requires two arguments. The first is the dataset, and the second
is a single integer value. The output type is a single integer.
-- Macro: GAL_ARITHMETIC_OP_SWAP
Return the first dataset, but with the second dataset being placed
in the ‘next’ element of the first. This is useful to swap the
operators on the stacks of the higher-level programs that call the
arithmetic library.
-- Macro: GAL_ARITHMETIC_OP_EQB1950_TO_EQJ2000
-- Macro: GAL_ARITHMETIC_OP_EQB1950_TO_ECB1950
-- Macro: GAL_ARITHMETIC_OP_EQB1950_TO_ECJ2000
-- Macro: GAL_ARITHMETIC_OP_EQB1950_TO_GALACTIC
-- Macro: GAL_ARITHMETIC_OP_EQB1950_TO_SUPERGALACTIC
-- Macro: GAL_ARITHMETIC_OP_EQJ2000_TO_EQB1950
-- Macro: GAL_ARITHMETIC_OP_EQJ2000_TO_ECB1950
-- Macro: GAL_ARITHMETIC_OP_EQJ2000_TO_ECJ2000
-- Macro: GAL_ARITHMETIC_OP_EQJ2000_TO_GALACTIC
-- Macro: GAL_ARITHMETIC_OP_EQJ2000_TO_SUPERGALACTIC
-- Macro: GAL_ARITHMETIC_OP_ECB1950_TO_EQB1950
-- Macro: GAL_ARITHMETIC_OP_ECB1950_TO_EQJ2000
-- Macro: GAL_ARITHMETIC_OP_ECB1950_TO_ECJ2000
-- Macro: GAL_ARITHMETIC_OP_ECB1950_TO_GALACTIC
-- Macro: GAL_ARITHMETIC_OP_ECB1950_TO_SUPERGALACTIC
-- Macro: GAL_ARITHMETIC_OP_ECJ2000_TO_EQB1950
-- Macro: GAL_ARITHMETIC_OP_ECJ2000_TO_EQJ2000
-- Macro: GAL_ARITHMETIC_OP_ECJ2000_TO_ECB1950
-- Macro: GAL_ARITHMETIC_OP_ECJ2000_TO_GALACTIC
-- Macro: GAL_ARITHMETIC_OP_ECJ2000_TO_SUPERGALACTIC
-- Macro: GAL_ARITHMETIC_OP_GALACTIC_TO_EQB1950
-- Macro: GAL_ARITHMETIC_OP_GALACTIC_TO_EQJ2000
-- Macro: GAL_ARITHMETIC_OP_GALACTIC_TO_ECB1950
-- Macro: GAL_ARITHMETIC_OP_GALACTIC_TO_ECJ2000
-- Macro: GAL_ARITHMETIC_OP_GALACTIC_TO_SUPERGALACTIC
-- Macro: GAL_ARITHMETIC_OP_SUPERGALACTIC_TO_EQB1950
-- Macro: GAL_ARITHMETIC_OP_SUPERGALACTIC_TO_EQJ2000
-- Macro: GAL_ARITHMETIC_OP_SUPERGALACTIC_TO_ECB1950
-- Macro: GAL_ARITHMETIC_OP_SUPERGALACTIC_TO_ECJ2000
-- Macro: GAL_ARITHMETIC_OP_SUPERGALACTIC_TO_GALACTIC
Operators that convert recognized celestial coordinates to and from
each other. They all take two operands and return two
‘gal_data_t’s (as a list). For more on celestial coordinate
conversion, see *note Coordinate conversion operators::.
-- Function:
gal_data_t *
gal_arithmetic (int operator, size_t numthreads, int flags,
...)
Apply the requested arithmetic operator on the operand(s). The
_operator_ is identified through the macros above (that start with
‘GAL_ARITHMETIC_OP_’). The number of necessary operands (number of
arguments to replace '‘...’' in the declaration of this function,
above) depends on the operator and is described under each
operator, above. Each operand has a type of '‘gal_data_t *’' (see
last paragraph with example).
If the operator can work on multiple threads, the number of threads
can be specified with ‘numthreads’. When the operator is
single-threaded, ‘numthreads’ will be ignored. Special conditions
can also be specified with the ‘flag’ operator (a bit-flag with
bits described above, for example, ‘GAL_ARITHMETIC_FLAG_INPLACE’ or
‘GAL_ARITHMETIC_FLAG_FREE’).
‘gal_arithmetic’ is a multi-argument function (like C's ‘printf’).
In other words, the number of necessary arguments is not fixed and
depends on the value to ‘operator’. Below, you can see a minimal,
fully working example, showing how different operators need
different numbers of arguments.
#include <stdio.h>
#include <stdlib.h>
#include <gnuastro/fits.h>
#include <gnuastro/arithmetic.h>
int
main(void)
{
/* Define the datasets and flag. */
gal_data_t *in1, *in2, *out1, *out2;
int flag=GAL_ARITHMETIC_FLAGS_BASIC;
/* Read the input images. */
in1=gal_fits_img_read("image1.fits", "1", -1, 1, NULL);
in2=gal_fits_img_read("image2.fits", "1", -1, 1, NULL);
/* Take the logarithm (base-e) of the first input. */
out1=gal_arithmetic(GAL_ARITHMETIC_OP_LOG, 1, flag, in1);
/* Add the second input with the logarithm of the first. */
out2=gal_arithmetic(GAL_ARITHMETIC_OP_PLUS, 1, flag, in2, out1);
/* Write the output into a file. */
gal_fits_img_write(out2, "out.fits", NULL, 0);
/* Clean up. Due to the in-place flag (in
* 'GAL_ARITHMETIC_FLAGS_BASIC'), 'out1' and 'out2' point to the
* same array in memory and due to the freeing flag, any input
* dataset(s) that were not returned have been freed internally
* by 'gal_arithmetic'. Therefore it is only necessary to free
* 'out2': all other allocated spaces have been freed internally.
* before reaching this point. */
gal_data_free(out2);
/* Return control back to the OS (saying that we succeeded). */
return EXIT_SUCCESS;
}
As you see above, you can feed the returned dataset from one call
of ‘gal_arithmetic’ to another call. The advantage of using
‘gal_arithmetic’ (as opposed to manually writing a ‘for’ or ‘while’
loop and doing the operation with the ‘+’ operator and ‘log()’
function yourself), is that you do not have to worry about the type
of the input data (for a list of acceptable data types in Gnuastro,
see *note Library data types::). Arithmetic will automatically
deal with the data types internally and choose the best output type
depending on the operator.
-- Function:
int
gal_arithmetic_set_operator (char *string, size_t
*num_operands)
Return the operator macro/code that corresponds to ‘string’. The
number of operands that it needs are written into the space that
‘*num_operands’ points to. If the string could not be interpreted
as an operator, this function will return
‘GAL_ARITHMETIC_OP_INVALID’.
This function will check ‘string’ with the fixed human-readable
names (using ‘strcmp’) for the operators and return the two
numbers. Note that ‘string’ must only contain the single operator
name and nothing else (not even any extra white space).
-- Function:
char *
gal_arithmetic_operator_string (int operator)
Return the human-readable standard string that corresponds to the
given operator. For example, when the input is
‘GAL_ARITHMETIC_OP_PLUS’ or ‘GAL_ARITHMETIC_OP_MEAN’, the strings
‘+’ or ‘mean’ will be returned.
-- Function:
gal_data_t *
gal_arithmetic_load_col (char *str, int searchin, int
ignorecase, size_t minmapsize, int quietmmap)
Return the column that corresponds to the identifier in the input
string (‘str’). ‘str’ is expected to be in the format of the
‘load-col-’ operator (see *note Loading external columns::). This
function will extract the column identifier, the file name and the
HDU (if necessary) from the string, read the requested column in
memory and return it.
See *note Table input output:: for the macros that can be given to
‘searchin’ and ‘ignorecase’ and *note Generic data container:: for
the definitions of ‘minmapsize’ and ‘quietmmap’.
File: gnuastro.info, Node: Tessellation library, Next: Bounding box, Prev: Arithmetic on datasets, Up: Gnuastro library
12.3.15 Tessellation library (‘tile.h’)
---------------------------------------
In many contexts, it is desirable to slice the dataset into subsets or
tiles (overlapping or not). In such a way that you can work on each
tile independently. One method would be to copy that region to a
separate allocated space, but in many contexts this is not necessary and
in fact can be a big burden on CPU/Memory usage. The ‘block’ pointer in
Gnuastro's *note Generic data container:: is defined for such
situations: where allocation is not necessary. You just want to read
the data or write to it independently (or in coordination with) other
regions of the dataset. Added with parallel processing, this can
greatly improve the time/memory consumption.
See the figure below for example: assume the ‘larger’ dataset is a
contiguous block of memory that you are interpreting as a 2D array. But
you only want to work on the smaller ‘tile’ region.
larger
---------------------------------
| |
| tile |
| ---------- |
| | | |
| |_ | |
| |*| | |
| ---------- |
| tile->block = larger |
|_ |
|*| |
---------------------------------
To use ‘gal_data_t’'s ‘block’ concept, you allocate a ‘gal_data_t
*tile’ which is initialized with the pointer to the first element in the
sub-array (as its ‘array’ argument). Note that this is not necessarily
the first element in the larger array. You can set the size of the tile
along with the initialization as you please. Recall that, when given a
non-‘NULL’ pointer as ‘array’, ‘gal_data_initialize’ (and thus
‘gal_data_alloc’) do not allocate any space and just uses the given
pointer for the new ‘array’ element of the ‘gal_data_t’. So your ‘tile’
data structure will not be pointing to a separately allocated space.
After the allocation is done, you just point ‘tile->block’ to the
‘larger’ dataset which hosts the full block of memory. Where relevant,
Gnuastro's library functions will check the ‘block’ pointer of their
input dataset to see how to deal with dimensions and increments so they
can always remain within the tile. The tools introduced in this section
are designed to help in defining and working with tiles that are created
in this manner.
Since the block structure is defined as a pointer, arbitrary levels
of tessellation/grid-ing are possible (‘tile->block’ may itself be a
tile in an even larger allocated space). Therefore, just like a
linked-list (see *note Linked lists::), it is important to have the
‘block’ pointer of the largest (allocated) dataset set to ‘NULL’.
Normally, you will not have to worry about this, because
‘gal_data_initialize’ (and thus ‘gal_data_alloc’) will set the ‘block’
element to ‘NULL’ by default, just remember not to change it. You can
then only change the ‘block’ element for the tiles you define over the
allocated space.
Below, we will first review constructs for *note Independent tiles::
and then define the current approach to fully tessellating a dataset (or
covering every pixel/data-element with a non-overlapping tile grid in
*note Tile grid::. This approach to dealing with parts of a larger
block was inspired from a similarly named concept in the GNU Scientific
Library (GSL), see its "Vectors and Matrices" chapter for their
implementation.
* Menu:
* Independent tiles:: Work on or check independent tiles.
* Tile grid:: Cover a full dataset with non-overlapping tiles.
File: gnuastro.info, Node: Independent tiles, Next: Tile grid, Prev: Tessellation library, Up: Tessellation library
12.3.15.1 Independent tiles
...........................
The most general application of tiles is to treat each independently,
for example they may overlap, or they may not cover the full image.
This section provides functions to help in checking/inspecting such
tiles. In *note Tile grid:: we will discuss functions that
define/work-with a tile grid (where the tiles do not overlap and fully
cover the input dataset). Therefore, the functions in this section are
general and can be used for the tiles produced by that section also.
-- Function:
void
gal_tile_start_coord (gal_data_t *tile, size_t *start_coord)
Calculate the starting coordinates of a tile in its allocated block
of memory and write them in the memory that ‘start_coord’ points to
(which must have ‘tile->ndim’ elements).
-- Function:
void
gal_tile_start_end_coord (gal_data_t *tile, size_t *start_end,
int rel_block)
Put the starting and ending (end point is not inclusive)
coordinates of ‘tile’ into the ‘start_end’ array. It is assumed
that a space of ‘2*tile->ndim’ has been already allocated (static
or dynamic) for ‘start_end’ before this function is called.
‘rel_block’ (or relative-to-block) is only relevant when ‘tile’ has
an intermediate tile between it and the allocated space (like a
channel, see ‘gal_tile_full_two_layers’). If it does not
(‘tile->block’ points the allocated dataset), then the value to
‘rel_block’ is irrelevant.
When ‘tile->block’ is itself a larger block and ‘rel_block’ is set
to 0, then the starting and ending positions will be based on the
position within ‘tile->block’, not the allocated space.
-- Function:
void *
gal_tile_start_end_ind_inclusive (gal_data_t *tile, gal_data_t
*work, size_t *start_end_inc)
Put the indices of the first/start and last/end pixels (inclusive)
in a tile into the ‘start_end’ array (that must have two elements).
NOTE: this function stores the index of each point, not its
coordinates. It will then return the pointer to the start of the
tile in the ‘work’ data structure (which does not have to be equal
to ‘tile->block’.
The outputs of this function are defined to make it easy to parse
over an n-dimensional tile. For example, this function is one of
the most important parts of the internal processing of in
‘GAL_TILE_PARSE_OPERATE’ function-like macro that is described
below.
-- Function:
gal_data_t *
gal_tile_series_from_minmax (gal_data_t *block, size_t
*minmax, size_t number)
Construct a list of tile(s) given coordinates of the minimum and
maximum of each tile. The minimum and maximums are assumed to be
inclusive and in C order (slowest dimension first). The returned
pointer is an allocated ‘gal_data_t’ array that can later be freed
with ‘gal_data_array_free’ (see *note Arrays of datasets::).
Internally, each element of the output array points to the next
element, so the output may also be treated as a list of datasets
(see *note List of gal_data_t::) and passed onto the other
functions described in this section.
The array keeping the minimum and maximum coordinates for each tile
must have the following format. So in total ‘minmax’ must have
‘2*ndim*number’ elements.
| min0_d0 | min0_d1 | max0_d0 | max0_d1 | ...
... | minN_d0 | minN_d1 | maxN_d0 | maxN_d1 |
-- Function:
gal_data_t *
gal_tile_block (gal_data_t *tile)
Return the dataset that contains ‘tile’'s allocated block of
memory. If tile is immediately defined as part of the allocated
block, then this is equivalent to ‘tile->block’. However, it is
possible to have multiple layers of tiles (where ‘tile->block’ is
itself a tile). So this function is the most generic way to get to
the actual allocated dataset.
-- Function:
size_t
gal_tile_block_increment (gal_data_t *block, size_t *tsize,
size_t num_increment, size_t *coord)
Return the increment necessary to start at the next contiguous
patch memory associated with a tile. ‘block’ is the allocated
block of memory and ‘tsize’ is the size of the tile along every
dimension. If ‘coord’ is ‘NULL’, it is ignored. Otherwise, it
will contain the coordinate of the start of the next contiguous
patch of memory.
This function is intended to be used in a loop and ‘num_increment’
is the main variable to this function. For the first time you call
this function, it should be ‘1’. In subsequent calls (while you
are parsing a tile), it should be increased by one.
-- Function:
gal_data_t *
gal_tile_block_write_const_value (gal_data_t *tilevalues,
gal_data_t *tilesll, int withblank, int initialize)
Write a constant value for each tile over the area it covers in an
allocated dataset that is the size of ‘tile’'s allocated block of
memory (found through ‘gal_tile_block’ described above). The
arguments to this function are:
‘tilevalues’
This must be an array that has the same number of elements as
the nodes in in ‘tilesll’ and in the same order that 'tilesll'
elements are parsed (from top to bottom, see *note Linked
lists::). As a result the array's number of dimensions is
irrelevant, it will be parsed contiguously.
‘tilesll’
The list of input tiles (see *note List of gal_data_t::).
Internally, it might be stored as an array (for example, the
output of ‘gal_tile_series_from_minmax’ described above), but
this function does not care, it will parse the ‘next’ elements
to go to the next tile. This function will not pop-from or
free the ‘tilesll’, it will only parse it from start to end.
‘withblank’
If the block containing the tiles has blank elements, those
blank elements will be blank in the output of this function
also, hence the array will be initialized with blank values
when this option is called (see below).
‘initialize’
Initialize the allocated space with blank values before
writing in the constant values. This can be useful when the
tiles do not cover the full allocated block.
-- Function:
gal_data_t *
gal_tile_block_check_tiles (gal_data_t *tilesll)
Make a copy of the memory block and fill it with the index of each
tile in ‘tilesll’ (counting from 0). The non-filled areas will
have blank values. The output dataset will have a type of
‘GAL_TYPE_INT32’ (see *note Library data types::).
This function can be used when you want to check the coverage of
each tile over the allocated block of memory. It is just a wrapper
over the ‘gal_tile_block_write_const_value’ (with ‘withblank’ set
to zero).
-- Function:
void *
gal_tile_block_relative_to_other (gal_data_t *tile, gal_data_t
*other)
Return the pointer corresponding to the start of the region covered
by ‘tile’ over the ‘other’ dataset. See the examples in
‘GAL_TILE_PARSE_OPERATE’ for some example applications of this
function.
-- Function:
void
gal_tile_block_blank_flag (gal_data_t *tilell, size_t
numthreads)
Check if each tile in the list has blank values and update its
‘flag’ to mark this check and its result (see *note Generic data
container::). The operation will be done on ‘numthreads’ threads.
-- Function-like macro: GAL_TILE_PARSE_OPERATE (IN, OTHER, PARSE_OTHER,
CHECK_BLANK, OP)
Parse ‘IN’ (which can be a tile or a fully allocated block of
memory) and do the ‘OP’ operation on it. ‘OP’ can be any
combination of C expressions. If ‘OTHER!=NULL’, ‘OTHER’ will be
interpreted as a dataset and this macro will allow access to its
element(s) and it can optionally be parsed while parsing over ‘IN’.
If ‘OTHER’ is a fully allocated block of memory (not a tile), then
the same region that is covered by ‘IN’ within its own block will
be parsed (the same starting pixel with the same number of pixels
in each dimension). Hence, in this case, the blocks of ‘OTHER’ and
‘IN’ must have the same size. When ‘OTHER’ is a tile it must have
the same size as ‘IN’ and parsing will start from its starting
element/pixel. Also, the respective allocated blocks of ‘OTHER’
and ‘IN’ (if different) may have different sizes. Using ‘OTHER’
(along with ‘PARSE_OTHER’), this function-like macro will thus
enable you to parse and define your own operation on two fixed size
regions in one or two blocks of memory. In the latter case, they
may have different numeric data types, see *note Numeric data
types::).
The input arguments to this macro are explained below, the expected
type of each argument are also written following the argument name:
‘IN (gal_data_t)’
Input dataset, this can be a tile or an allocated block of
memory.
‘OTHER (gal_data_t)’
Dataset (‘gal_data_t’) to parse along with ‘IN’. It can be
‘NULL’. In that case, ‘o’ (see description of ‘OP’ below)
will be ‘NULL’ and should not be used. If ‘PARSE_OTHER’ is
zero, only its first element will be used and the size of this
dataset is irrelevant.
When ‘OTHER’ is a block of memory, it has to have the same
size as the allocated block of ‘IN’. When it s a tile, it has
to have the same size as ‘IN’.
‘PARSE_OTHER (int)’
Parse the other dataset along with the input. When this is
non-zero and ‘OTHER!=NULL’, then the ‘o’ pointer will be
incremented to cover the ‘OTHER’ tile at the same rate as ‘i’,
see description of ‘OP’ for ‘i’ and ‘o’.
‘CHECK_BLANK (int)’
If it is non-zero, then the input will be checked for blank
values and ‘OP’ will only be called when we are not on a blank
element.
‘OP’
Operator: this can be any number of C expressions. This macro
is going to define a ‘itype *i’ variable which will increment
over each element of the input array/tile. ‘itype’ will be
replaced with the C type that corresponds to the type of
‘INPUT’. As an example, if ‘INPUT’'s type is
‘GAL_DATA_UINT16’ or ‘GAL_DATA_FLOAT32’, ‘i’ will be defined
as ‘uint16’ or ‘float’ respectively.
This function-like macro will also define an ‘otype *o’ which
you can use to access an element of the ‘OTHER’ dataset (if
‘OTHER!=NULL’). ‘o’ will correspond to the type of ‘OTHER’
(similar to ‘itype’ and ‘INPUT’ discussed above). If
‘PARSE_OTHER’ is non-zero, then ‘o’ will also be incremented
to the same index element but in the other array. You can use
these along with any other variable you define before this
macro to process the input and/or the other.
All variables within this function-like macro begin with
‘tpo_’ except for the three variables listed below.
Therefore, as long as you do not start the names of your
variables with this prefix everything will be fine. Note that
‘i’ (and possibly ‘o’) will be incremented once by this
function-like macro, so do not increment them within ‘OP’.
‘i’
Pointer to the element of ‘INPUT’ that is being parsed
with the proper type.
‘o’
Pointer to the element of ‘OTHER’ that is being parsed
with the proper type. ‘o’ can only be used if
‘OTHER!=NULL’ and it will be parsed/incremented if
‘PARSE_OTHER’ is non-zero.
‘b’
Blank value in the type of ‘INPUT’.
You can use a given tile (‘tile’ on a dataset that it was not
initialized with but has the same size, let's call it ‘new’) with
the following steps:
void *tarray;
gal_data_t *tblock;
/* `tile->block' must be corrected AFTER `tile->array'. */
tarray = tile->array;
tblock = tile->block;
tile->array = gal_tile_block_relative_to_other(tile, new);
tile->block = new;
/* Parse and operate over this region of the `new' dataset. */
GAL_TILE_PARSE_OPERATE(tile, NULL, 0, 0, {
YOUR_PROCESSING;
});
/* Reset `tile->block' and `tile->array'. */
tile->array=tarray;
tile->block=tblock;
You can work on the same region of another block in one run of this
function-like macro. To do that, you can make a fake tile and pass
that as the ‘OTHER’ argument. Below is a demonstration, ‘tile’ is
the actual tile that you start with and ‘new’ is the other block of
allocated memory.
size_t zero=0;
gal_data_t *faketile;
/* Allocate the fake tile, these can be done outside a loop
* (over many tiles). */
faketile=gal_data_alloc(NULL, new->type, 1, &zero,
NULL, 0, -1, 1, NULL, NULL, NULL);
free(faketile->array); /* To keep things clean. */
free(faketile->dsize); /* To keep things clean. */
faketile->block = new;
faketile->ndim = new->ndim;
/* These can be done in a loop (over many tiles). */
faketile->size = tile->size;
faketile->dsize = tile->dsize;
faketile->array = gal_tile_block_relative_to_other(tile, new);
/* Do your processing.... in a loop (over many tiles). */
GAL_TILE_PARSE_OPERATE(tile, faketile, 1, 1, {
YOUR_PROCESSING_EXPRESSIONS;
});
/* Clean up (outside the loop). */
faketile->array=NULL;
faketile->dsize=NULL;
gal_data_free(faketile);
File: gnuastro.info, Node: Tile grid, Prev: Independent tiles, Up: Tessellation library
12.3.15.2 Tile grid
...................
One very useful application of tiles is to completely cover an input
dataset with tiles. Such that you know every pixel/data-element of the
input image is covered by only one tile. The constructs in this section
allow easy definition of such a tile structure. They will create lists
of tiles that are also usable by the general tools discussed in *note
Independent tiles::.
As discussed in *note Tessellation::, (mainly raw) astronomical
images will mostly require two layers of tessellation, one for amplifier
channels which all have the same size and another (smaller tile-size)
tessellation over each channel. Hence, in this section we define a
general structure to keep the main parameters of this two-layer
tessellation and help in benefiting from it.
-- Type (C struct): gal_tile_two_layer_params
The general structure to keep all the necessary parameters for a
two-layer tessellation.
struct gal_tile_two_layer_params
{
/* Inputs */
size_t *tilesize; /*******************************/
size_t *numchannels; /* These parameters have to be */
float remainderfrac; /* filled manually before */
uint8_t workoverch; /* calling the functions in */
uint8_t checktiles; /* this section. */
uint8_t oneelempertile; /*******************************/
/* Internal parameters. */
size_t ndim;
size_t tottiles;
size_t tottilesinch;
size_t totchannels;
size_t *channelsize;
size_t *numtiles;
size_t *numtilesinch;
char *tilecheckname;
size_t *permutation;
size_t *firsttsize;
/* Tile and channel arrays (which are also lists). */
gal_data_t *tiles;
gal_data_t *channels;
};
-- Function:
size_t *
gal_tile_full (gal_data_t *input, size_t *regular, float
remainderfrac, gal_data_t **out, size_t multiple, size_t
**firsttsize)
Cover the full dataset with (mostly) identical tiles and return the
number of tiles created along each dimension. The regular tile
size (along each dimension) is determined from the ‘regular’ array.
If ‘input’'s size is not an exact multiple of ‘regular’ for each
dimension, then the tiles touching the edges in that dimension will
have a different size to fully cover every element of the input
(depending on ‘remainderfrac’).
The output is an array with the same dimensions as ‘input’ which
contains the number of tiles along each dimension. See *note
Tessellation:: for a description of its application in Gnuastro's
programs and ‘remainderfrac’, just note that this function defines
only one layer of tiles.
This is a low-level function (independent of the
‘gal_tile_two_layer_params’ structure defined above). If you want
a two-layer tessellation, directly call ‘gal_tile_full_two_layers’
that is described below. The input arguments to this function are:
‘input’
The main dataset (allocated block) which you want to create a
tessellation over (only used for its sizes). So ‘input’ may
be a tile also.
‘regular’
The size of the regular tiles along each of the input's
dimensions. So it must have the same number of elements as
the dimensions of ‘input’ (or ‘input->ndim’).
‘remainderfrac’
The significant fraction of the remainder space to see if it
should be split into two and put on both sides of a dimension
or not. This is thus only relevant ‘input’ length along a
dimension is not an exact multiple of the regular tile size
along that dimension. See *note Tessellation:: for a more
thorough discussion.
‘out’
Pointer to the array of data structures that will keep all the
tiles (see *note Arrays of datasets::). If ‘*out==NULL’, then
the necessary space to keep all the tiles will be allocated.
If not, then all the tile information will be filled from the
dataset that ‘*out’ points to, see ‘multiple’ for more.
‘multiple’
When ‘*out==NULL’ (and thus will be allocated by this
function), allocate space for ‘multiple’ times the number of
tiles needed. This can be very useful when you have several
more identically sized ‘inputs’, and you want all their tiles
to be allocated (and thus indexed) together, even though they
have different ‘block’ datasets (that then link to one
allocated space). See the definition of channels in *note
Tessellation:: and ‘gal_tile_full_two_layers’ below.
‘firsttsize’
The size of the first tile along every dimension. This is
only different from the regular tile size when ‘regular’ is
not an exact multiple of ‘input’'s length along every
dimension. This array is allocated internally by this
function.
-- Function:
void
gal_tile_full_sanity_check (char *filename, char *hdu,
gal_data_t *input, struct gal_tile_two_layer_params *tl)
Make sure that the input parameters (in ‘tl’, short for two-layer)
correspond to the input dataset. ‘filename’ and ‘hdu’ are only
required for error messages. Also, allocate and fill the
‘tl->channelsize’ array.
-- Function:
void
gal_tile_full_two_layers (gal_data_t *input, struct
gal_tile_two_layer_params *tl)
Create the two layered tessellation in ‘tl’. The general set of
steps you need to take to define the two-layered tessellation over
an image can be seen in the example code below.
gal_data_t *input;
struct gal_tile_two_layer_params tl;
char *filename="input.fits", *hdu="1";
/* Set all the inputs shown in the structure definition. */
...
/* Read the input dataset. */
input=gal_fits_img_read(filename, hdu, -1, 1, NULL);
/* Do a sanity check and preparations. */
gal_tile_full_sanity_check(filename, hdu, input, &tl);
/* Build the two-layer tessellation*/
gal_tile_full_two_layers(input, &tl);
/* `tl.tiles' and `tl.channels' are now a lists of tiles.*/
-- Function:
void
gal_tile_full_permutation (struct gal_tile_two_layer_params
*tl)
Make a permutation to allow the conversion of tile location in
memory to its location in the full input dataset and put it in
‘tl->permutation’. If a permutation has already been defined for
the tessellation, this function will not do anything. If
permutation will not be necessary (there is only one channel or one
dimension), then this function will not do anything
(‘tl->permutation’ must have been initialized to ‘NULL’).
When there is only one channel OR one dimension, the tiles are
allocated in memory in the same order that they represent the input
data. However, to make channel-independent processing possible in
a generic way, the tiles of each channel are allocated
contiguously. So, when there is more than one channel AND more
than one dimension, the index of the tile does not correspond to
its position in the grid covering the input dataset.
The example below may help clarify: assume you have a 6x6
tessellation with two channels in the horizontal and one in the
vertical. On the left you can see how the tile IDs correspond to
the input dataset. NOTE how '03' is on the second row, not on the
first after '02'. On the right, you can see how the tiles are
stored in memory (and shown if you simply write the array into a
FITS file for example).
Corresponding to input In memory
---------------------- --------------
15 16 17 33 34 35 30 31 32 33 34 35
12 13 14 30 31 32 24 25 26 27 28 29
09 10 11 27 28 29 18 19 20 21 22 23
06 07 08 24 25 26 <-- 12 13 14 15 16 17
03 04 05 21 22 23 06 07 08 09 10 11
00 01 02 18 19 20 00 01 02 03 04 05
As a result, if your values are stored in same order as the tiles,
and you want them in over-all memory (for example, to save as a
FITS file), you need to permute the values:
gal_permutation_apply(values, tl->permutation);
If you have values over-all and you want them in tile-order, you
can apply the inverse permutation:
gal_permutation_apply_inverse(values, tl->permutation);
Recall that this is the definition of permutation in this context:
permute: IN_ALL[ i ] = IN_MEMORY[ perm[i] ]
inverse: IN_ALL[ perm[i] ] = IN_MEMORY[ i ]
-- Function:
void
gal_permutation_apply_onlydim0 (gal_data_t *input, size_t
*permutation)
Similar to ‘gal_permutation_apply’, but when the dataset is
2-dimensional, permute each row (dimension 1 in C) as one element.
In other words, only permute along dimension 0. The ‘permutation’
array should therefore only have ‘input->dsize[0]’ elements.
-- Function:
void
gal_tile_full_values_write (gal_data_t *tilevalues, struct
gal_tile_two_layer_params *tl, int withblank, char *filename,
gal_fits_list_key_t *keys, int freekeys)
Write one value for each tile into a file. It is important to note
that the values in ‘tilevalues’ must be ordered in the same manner
as the tiles, so ‘tilevalues->array[i]’ is the value that should be
given to ‘tl->tiles[i]’. The ‘tl->permutation’ array must have
been initialized before calling this function with
‘gal_tile_full_permutation’.
If ‘withblank’ is non-zero, then block structure of the tiles will
be checked and all blank pixels in the block will be blank in the
final output file also.
-- Function:
gal_data_t *
gal_tile_full_values_smooth (gal_data_t *tilevalues, struct
gal_tile_two_layer_params *tl, size_t width, size_t
numthreads)
Smooth the given values with a flat kernel of the given ‘width’.
This cannot be done manually because if ‘tl->workoverch==0’, tiles
in different channels must not be mixed/smoothed. Also the tiles
are contiguous within the channel, not within the image, see the
description under ‘gal_tile_full_permutation’.
-- Function:
size_t
gal_tile_full_id_from_coord (struct gal_tile_two_layer_params
*tl, size_t *coord)
Return the ID of the tile that corresponds to the coordinates
‘coord’. Having this ID, you can use the ‘tl->tiles’ array to get
to the proper tile or read/write a value into an array that has one
value per tile.
-- Function:
void
gal_tile_full_free_contents (struct gal_tile_two_layer_params
*tl)
Free all the allocated arrays within ‘tl’.
File: gnuastro.info, Node: Bounding box, Next: Polygons, Prev: Tessellation library, Up: Gnuastro library
12.3.16 Bounding box (‘box.h’)
------------------------------
Functions related to reporting the bounding box of certain inputs are
declared in ‘gnuastro/box.h’. All coordinates in this header are in the
FITS format (first axis is the horizontal and the second axis is
vertical).
-- Function:
void
gal_box_bound_ellipse_extent (double a, double b, double
theta_deg, double *extent)
Return the maximum extent along each dimension of the given ellipse
from the center of the ellipse. Therefore this is half the extent
of the box in each dimension. ‘a’ is the ellipse semi-major axis,
‘b’ is the semi-minor axis, ‘theta_deg’ is the position angle in
degrees. The extent in each dimension is in floating point format
and stored in ‘extent’ which must already be allocated before this
function.
-- Function:
void
gal_box_bound_ellipse (double a, double b, double theta_deg,
long *width)
Any ellipse can be enclosed into a rectangular box. This function
will write the height and width of that box where ‘width’ points
to. It assumes the center of the ellipse is located within the
central pixel of the box. ‘a’ is the ellipse semi-major axis
length, ‘b’ is the semi-minor axis, ‘theta_deg’ is the position
angle in degrees. The ‘width’ array will contain the output size
in long integer type. ‘width[0]’, and ‘width[1]’ are the number of
pixels along the first and second FITS axis. Since the ellipse
center is assumed to be in the center of the box, all the values in
‘width’ will be an odd integer.
-- Function:
void
gal_box_bound_ellipsoid_extent (double *semiaxes, double
*euler_deg, double *extent)
Return the maximum extent along each dimension of the given
ellipsoid from its center. Therefore this is half the extent of
the box in each dimension. The semi-axis lengths of the ellipsoid
must be present in the 3 element ‘semiaxis’ array. The ‘euler_deg’
array contains the three ellipsoid Euler angles in degrees. For a
description of the Euler angles, see description of
‘gal_box_bound_ellipsoid’ below. The extent in each dimension is
in floating point format and stored in ‘extent’ which must already
be allocated before this function.
-- Function:
void
gal_box_bound_ellipsoid (double *semiaxes, double *euler_deg,
long *width)
Any ellipsoid can be enclosed into a rectangular volume/box. The
purpose of this function is to give the integer size/width of that
box. The semi-axes lengths of the ellipse must be in the
‘semiaxes’ array (with three elements). The major axis length must
be the first element of ‘semiaxes’. The only other condition is
that the next two semi-axes must both be smaller than the first.
The orientation of the major axis is defined through three proper
Euler angles (ZXZ order in degrees) that are given in the
‘euler_deg’ array. The ‘width’ array will contain the output size
in long integer type (in FITS axis order). Since the ellipsoid
center is assumed to be in the center of the box, all the values in
‘width’ will be an odd integer.
The proper Euler angles can be defined in many ways (which axes to
rotate about). For a full description of the Euler angles, please
see Wikipedia (https://en.wikipedia.org/wiki/Euler_angles). Here
we adopt the ZXZ (or $Z_1X_2Z_3$) proper Euler angles were the
first rotation is done around the Z axis, the second one about the
(rotated) X axis and the third about the (rotated) Z axis.
-- Function:
void
gal_box_border_from_center (double center, size_t ndim, long
*width, long *fpixel, long *lpixel)
Given the center coordinates in ‘center’ and the ‘width’ (along
each dimension) of a box, return the coordinates of the first
(‘fpixel’) and last (‘lpixel’) pixels. All arrays must have ‘ndim’
elements (one for each dimension).
-- Function:
void
gal_box_border_rotate_around_center (long *fpixel, long
*lpixel, size_t ndim, float rotate_deg)
Modify the input first and last pixels (‘fpixel’ and ‘lpixel’, that
you can estimate with ‘gal_box_border_from_center’) to account for
the given rotation (in units of degrees) in 2D (currently ‘ndim’
can only have a value of ‘2’).
-- Function:
int
gal_box_overlap (long *naxes, long *fpixel_i, long *lpixel_i,
long *fpixel_o, long *lpixel_o, size_t ndim)
An ‘ndim’-dimensional dataset of size ‘naxes’ (along each
dimension, in FITS order) and a box with first and last (inclusive)
coordinate of ‘fpixel_i’ and ‘lpixel_i’ is given. This box does
not necessarily have to lie within the dataset, it can be outside
of it, or only partially overlap. This function will change the
values of ‘fpixel_i’ and ‘lpixel_i’ to exactly cover the overlap in
the input dataset's coordinates.
This function will return 1 if there is an overlap and 0 if there
is not. When there is an overlap, the coordinates of the first and
last pixels of the overlap will be put in ‘fpixel_o’ and
‘lpixel_o’.
File: gnuastro.info, Node: Polygons, Next: Qsort functions, Prev: Bounding box, Up: Gnuastro library
12.3.17 Polygons (‘polygon.h’)
------------------------------
Polygons are commonly necessary in image processing. For example, in
Crop they are used for cutting out non-rectangular regions of a image
(see *note Crop::), and in Warp, for mapping different pixel grids over
each other (see *note Warp::).
Polygons come in two classes: convex and concave (or generally,
non-convex!), see below for a demonstration. Convex polygons are those
where all inner angles are less than 180 degrees. By contrast, a convex
polygon is one where an inner angle may be more than 180 degress.
Concave Polygon Convex Polygon
D --------C D------------- C
\ | E / |
\E | \ |
/ | \ |
A--------B A ----------B
In all the functions here the vertices (and points) are defined as an
array. So a polygon with 4 vertices will be identified with an array of
8 elements with the first two elements keeping the 2D coordinates of the
first vertice and so on.
-- Macro: GAL_POLYGON_MAX_CORNERS
The largest number of vertices a polygon can have in this library.
-- Macro: GAL_POLYGON_ROUND_ERR
We have to consider floating point round-off errors when dealing
with polygons. For example, we will take ‘A’ as the maximum of ‘A’
and ‘B’ when ‘A>B-GAL_POLYGON_ROUND_ERR’.
-- Function:
void
gal_polygon_vertices_sort_convex (double *in, size_t n, size_t
*ordinds)
We have a simple polygon (that can result from projection, so its
edges do not collide or it does not have holes) and we want to
order its corners in an anticlockwise fashion. This is necessary
for clipping it and finding its area later. The input vertices can
have practically any order.
The input (‘in’) is an array containing the coordinates (two
values) of each vertice. ‘n’ is the number of corners. So ‘in’
should have ‘2*n’ elements. The output (‘ordinds’) is an array
with ‘n’ elements specifying the indices in order. This array must
have been allocated before calling this function. The indexes are
output for more generic usage, for example, in a homographic
transform (necessary in warping an image, see *note Linear warping
basics::), the necessary order of vertices is the same for all the
pixels. In other words, only the positions of the vertices change,
not the way they need to be ordered. Therefore, this function
would only be necessary once.
As a summary, the input is unchanged, only ‘n’ values will be put
in the ‘ordinds’ array. Such that calling the input coordinates in
the following fashion will give an anti-clockwise order when there
are 4 vertices:
1st vertice: in[ordinds[0]*2], in[ordinds[0]*2+1]
2nd vertice: in[ordinds[1]*2], in[ordinds[1]*2+1]
3rd vertice: in[ordinds[2]*2], in[ordinds[2]*2+1]
4th vertice: in[ordinds[3]*2], in[ordinds[3]*2+1]
The implementation of this is very similar to the Graham scan in
finding the Convex Hull. However, in projection we will never have
a concave polygon (the left condition below, where this algorithm
will get to E before D), we will always have a convex polygon
(right case) or E will not exist! This is because we are always
going to be calculating the area of the overlap between a
quadrilateral and the pixel grid or the quadrilateral itself.
The ‘GAL_POLYGON_MAX_CORNERS’ macro is defined so there will be no
need to allocate these temporary arrays separately. Since we are
dealing with pixels, the polygon cannot really have too many
vertices.
-- Function:
int
gal_polygon_is_convex (double *v, size_t n)
Returns ‘1’ if the polygon is convex with vertices defined by ‘v’
and ‘0’ if it is a concave polygon. Note that the vertices of the
polygon should be sorted in an anti-clockwise manner.
-- Function:
double
gal_polygon_area_flat (double *v, size_t n)
Find the area of a polygon with vertices defined in ‘v’ on a
euclidian (flat) coordinate system. ‘v’ points to an array of
doubles which keep the positions of the vertices such that ‘v[0]’
and ‘v[1]’ are the positions of the first vertice to be considered.
-- Function:
double
gal_polygon_area_sky (double *v, size_t n)
Find the area of a polygon with vertices defined in ‘v’ on a
celestial coordinate system. This is a coordinate system where the
first coordinate goes from 0 to 360 (increasing to the right),
while the second coordinate ranges from -90 to +90 (on the poles).
‘v’ points to an array of doubles which keep the positions of the
vertices such that ‘v[0]’ and ‘v[1]’ are the positions of the first
vertice to be considered.
This function uses an approximation to account for the curvature of
the sky and the different nature of spherical coordinates with
respect to the flat coordinate system. Bug 64617
(https://savannah.gnu.org/bugs/index.php?64617) has been defined in
Gnuastro to address this problem. Please check that bug in case it
has been fixed. Until this bug is fixed, here are some tips:
• Subtract the RA and Dec of all the vertice coordinates from a
constant so the center of the polygon falls on (RA, Dec) of
(180,0). The sphere has a similar nature everywhere on it, so
shifting the polygon vertices will not change its area; this
also removes issues with the RA=0 or RA=360 coordinate and
decrease issues caused by RA depending on declination.
• These approximations should not cause any statistically
significant error on normal (less than a few degrees) scales.
But it won't hurt to do a small sanity check for your
particular usage scenario.
• Any help (even in the mathematics of the problem; not
necessary programming) would be appreciated (we didn't have
time to derive the necessary equations), so if you have some
background in this and can prepare the mathematical
description of the problem, please get in touch.
-- Function:
int
gal_polygon_is_inside (double *v, double *p, size_t n)
Returns ‘0’ if point ‘p’ in inside a polygon, either convex or
concave. The vertices of the polygon are defined by ‘v’ and ‘0’
otherwise, they have to be ordered in an anti-clockwise manner.
This function uses the winding number algorithm
(https://en.wikipedia.org/wiki/Point_in_polygon#Winding_number_algorithm),
to check the points. Note that this is a generic function (working
on both concave and convex polygons, so if you know before-hand
that your polygon is convex, it is much more efficient to use
‘gal_polygon_is_inside_convex’.
-- Function:
int
gal_polygon_is_inside_convex (double *v, double *p, size_t n)
Return ‘1’ if the point ‘p’ is within the polygon whose vertices
are defined by ‘v’. The polygon is assumed to be convex, for a
more generic function that deals with concave and convex polygons,
see ‘gal_polygon_is_inside’. Note that the vertices of the polygon
have to be sorted in an anti-clock-wise manner.
-- Function:
int
gal_polygon_ppropin (double *v, double *p, size_t n)
Similar to ‘gal_polygon_is_inside_convex’, except that if the point
‘p’ is on one of the edges of a polygon, this will return ‘0’.
-- Function:
int
gal_polygon_is_counterclockwise (double *v, size_t n)
Returns ‘1’ if the sorted polygon has a counter-clockwise
orientation and ‘0’ otherwise. This function uses the concept of
"winding", which defines the relative order in which the vertices
of a polygon are listed to determine the orientation of vertices.
For complex polygons (where edges, or sides, intersect), the most
significant orientation is returned. In a complex polygon, when
the alternative windings are equal (for example, an ‘8’-shape) it
will return ‘1’ (as if it was counter-clockwise). Note that the
polygon vertices have to be sorted before calling this function.
-- Function:
int
gal_polygon_to_counterclockwise (double *v, size_t n)
Arrange the vertices of the sorted polygon in place, to be in a
counter-clockwise direction. If the input polygon already has a
counter-clockwise direction it will not touch the input. The
return value is ‘1’ on successful execution. This function is just
a wrapper over ‘gal_polygon_is_counterclockwise’, and will reverse
the order of the vertices when necessary.
-- Function:
void
gal_polygon_clip (double *s, size_t n, double *c, size_t m,
double *o, size_t *numcrn)
Clip (find the overlap of) two polygons. This function uses the
Sutherland-Hodgman
(https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)
polygon clipping algorithm. Note that the vertices of both
polygons have to be sorted in an anti-clock-wise manner.
The Pseudocode from Wikipedia:
List outputList = subjectPolygon;
for (Edge clipEdge in clipPolygon) do
List inputList = outputList;
outputList.clear();
Point S = inputList.last;
for (Point E in inputList) do
if (E inside clipEdge) then
if (S not inside clipEdge) then
outputList.add(ComputeIntersection(S,E,clipEdge));
end if
outputList.add(E);
else if (S inside clipEdge) then
outputList.add(ComputeIntersection(S,E,clipEdge));
end if
S = E;
done
done
The difference is that we are not using lists, but arrays to keep
polygon vertices. The two polygons are called Subject ‘s’ and Clip
‘c’ with ‘n’ and ‘m’ vertices respectively. The output is stored
in ‘o’ and the number of elements in the output are stored in what
‘*numcrn’ (for number of corners) points to.
-- Function:
void
gal_polygon_vertices_sort (double *vertices, size_t n, size_t
*ordinds)
Sort the indices of the un-ordered ‘vertices’ array to a
counter-clockwise polygon in the already allocated space of
‘ordinds’. It is assumed that there are ‘n’ vertices, and thus
that ‘vertices’ contains ‘2*n’ elements where the two coordinates
of the first vertice occupy the first two elements of the array and
so on.
The polygon can be both concave and convex (see the start of this
section). However, note that for concave polygons there is no
unique sort from an un-ordered set of vertices. So after this
function you may want to use ‘gal_polygon_is_convex’ and print a
warning to check the output if the polygon was concave.
Note that the contents of the ‘vertices’ array are left untouched
by this function. If you want to write the ordered vertice
coordinates in another array with the same size, you can use a loop
like this:
for(i=0;i<n;++i)
{
ordered[i*2 ] = vertices[ ordinds[i]*2 ];
ordered[i*2+1] = vertices[ ordinds[i]*2 + 1];
}
In this algorithm, we find the rightmost and leftmost points (based
on their x-coordinate) and use the diagonal vector between those
points to group the points in arrays based on their position with
respect to this vector. For anticlockwise sorting, all the points
below the vector are sorted by their ascending x-coordinates and
points above the vector are sorted in decreasing order using
‘qsort’. Finally, both these arrays are merged together to get the
final sorted array of points, from which the points are indexed
into the ‘ordinds’ using linear search.