This is gnuastro.info, produced by makeinfo version 7.0.3 from
gnuastro.texi.

This book documents version 0.21 of the GNU Astronomy Utilities
(Gnuastro).  Gnuastro provides various programs and libraries for
astronomical data manipulation and analysis.

   Copyright © 2015-2023 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: 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_fits_hdu_open’.

 -- 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_fits_hdu_open’.

 -- 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.

     ‘hdu_option_name’ is used in error messages related to the given
     HDU name/identifier.  It is expected to the command-line option
     name that users to your program can specify the HDU for this
     particular input.  For example if the given ‘hdu’ doesn’t exist in
     ‘filename’, a descriptive error message is printed which instructs
     the users how to find and fix the problem.  The text in that error
     message, also suggests the option to use to fix the problem (hence
     the purpose of this argument).

 -- 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_fits_hdu_open’.

     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)
     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_comment_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_comment_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_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
          *title, char *filename, char *hdu)
     Write the list of keywords in ‘keylist’ into the ‘hdu’ extension of
     the file called ‘filename’ (the file must already exist) and free
     the list.

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

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

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

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

 -- Function:
          void
          gal_fits_key_write_in_ptr (gal_fits_list_key_t **keylist,
          fitsfile *fptr)
     Write the list of keywords in ‘keylist’ into the given CFITSIO
     ‘fitsfile’ pointer and free keylist.  For more on the input
     ‘keylist’, see the description and example for
     ‘gal_fits_key_write’, above.

 -- Function:
          void
          gal_fits_key_write_version (gal_fits_list_key_t **keylist,
          char *title, char *filename, char *hdu)
     Write the (optional, when ‘keylist!=NULL’) given list of keywords
     under the optional FITS keyword ‘title’, then print all the
     important version and date information.  This is basically, just a
     wrapper over ‘gal_fits_key_write_version_in_ptr’.

 -- Function:
          void
          gal_fits_key_write_version_in_ptr (gal_fits_list_key_t
          **keylist, char *title, fitsfile *fptr)
     Write or update (all the) keyword(s) in ‘headers’ into the FITS
     pointer, but also the date, name of your program (‘program_name’),
     along with the versions of CFITSIO, WCSLIB (when available), GSL,
     Gnuastro, and (the possible) commit information into the header as
     described in *note Output FITS files::.

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

 -- Function:
          void
          gal_fits_key_write_config (gal_fits_list_key_t **keylist, char
          *title, char *extname, char *filename, char *hdu, char
          *hdu_option_name)
     Write the given keyword list (‘keylist’) into the ‘hdu’ extension
     of ‘filename’, ending it with version information.  This function
     will write ‘extname’ as the name of the extension (value to the
     standard ‘EXTNAME’ FITS keyword).  The list of keywords will then
     be printed under a title called ‘title’.

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

     For more on ‘hdu_option_name’ see the description of
     ‘gal_fits_hdu_open’ in *note FITS HDUs::.

 -- Function:
          gal_list_str_t *
          gal_fits_with_keyvalue (gal_list_str_t *files, char *hdu, char
          *name, gal_list_str_t *values)
     Given a list of FITS file names (‘files’), a certain HDU (‘hdu’), a
     certain keyword name (‘name’), and a list of acceptable values
     (‘values’), return the subset of file names where the requested
     keyword name has one of the acceptable values.

 -- 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_fits_hdu_open’ in *note FITS HDUs::.

   ---------- 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_fits_hdu_open’ in *note FITS HDUs::.

 -- Function:
          gal_data_t *
          gal_fits_img_read (char *filename, char *hdu, size_t
          minmapsize, int quietmmap)
     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_fits_hdu_open’ in *note FITS HDUs::.

     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);
          data->wcs=gal_wcs_read(filename, hdu, 0, 0, 0, &data->wcs->nwcs);

 -- 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_fits_hdu_open’ in *note FITS HDUs::.

 -- Function:
          fitsfile *
          gal_fits_img_write_to_ptr (gal_data_t *input, char *filename)
     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.

 -- Function:
          void
          gal_fits_img_write (gal_data_t *data, char *filename,
          gal_fits_list_key_t *headers, char *program_string)
     Write the ‘input’ dataset into the FITS file named ‘filename’.
     Also add the ‘headers’ keywords to the newly created HDU/extension
     along with your program’s name (‘program_string’).

 -- Function:
          void
          gal_fits_img_write_to_type (gal_data_t *data, char *filename,
          gal_fits_list_key_t *headers, char *program_string, int type)
     Convert the ‘input’ dataset into ‘type’, then write it into the
     FITS file named ‘filename’.  Also add the ‘headers’ 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.

     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 *headers, char *program_string)
     Write the ‘input’ dataset into ‘filename’ using the ‘wcsstr’ while
     correcting the ‘CRPIX’ values.

     This function is mainly useful when you want to make FITS files in
     parallel (from one main WCS structure, with just differing CRPIX).
     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_fits_hdu_open’ in *note FITS HDUs::.

     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_fits_hdu_open’ in *note FITS HDUs::.

     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)
     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::.

     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:
          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)
     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_fits_hdu_open’ in *note FITS HDUs::.

     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 *headers, char *program_string)
     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 ‘headers’ list and if
     ‘program_string!=NULL’ it will be used in a commented keyword title
     just above the written version information.

 -- 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);
          inwcs=gal_wcs_read("image.fits", "1", 0, 0, 0, &nwcs);
          data->wcs=gal_wcs_distortion_convert(inwcs, GAL_WCS_DISTORTION_TPV,
                                               NULL);
          wcsfree(inwcs);
          gal_fits_img_write(data, "tpv.fits", NULL, NULL);

 -- 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 Box shape 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_fits_hdu_open’ in *note FITS HDUs::.

     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);
            in2=gal_fits_img_read("image2.fits", "1", -1, 1);

            /* 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, NULL);

            /* 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);

          /* 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, char *program_string)
     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.


File: gnuastro.info,  Node: Qsort functions,  Next: K-d tree,  Prev: Polygons,  Up: Gnuastro library

12.3.18 Qsort functions (‘qsort.h’)
-----------------------------------

When sorting a dataset is necessary, the C programming language provides
the ‘qsort’ (Quick sort) function.  ‘qsort’ is a generic function which
allows you to sort any kind of data structure (not just a single array
of numbers).  To define “greater” and “smaller” (for sorting), ‘qsort’
needs another function, even for simple numerical types.  The functions
introduced in this section are to passed onto ‘qsort’.

   Note that larger and smaller operators are not defined on NaN
elements.  Therefore, if the input array is a floating point type, and
contains NaN values, the relevant functions of this section are going to
put the NaN elements at the end of the list (after the sorted non-NaN
elements), irrespective of the requested sorting order (increasing or
decreasing).

   The first class of functions below (with ‘TYPE’ in their names) can
be used for sorting a simple numeric array.  Just replace ‘TYPE’ with
the dataset’s numeric datatype.  The second set of functions can be used
to sort indices (leave the actual numbers untouched).  To use the second
set of functions, a global variable or structure are also necessary as
described below.

 -- Global variable: gal_qsort_index_single
     Pointer to an array (for example, ‘float *’ or ‘int *’) to use as a
     reference in ‘gal_qsort_index_single_TYPE_d’ or
     ‘gal_qsort_index_single_TYPE_i’, see the explanation of these
     functions for more.  Note that if _more than one_ array is to be
     sorted in a multi-threaded operation, these functions will not work
     as expected.  However, when all the threads just sort the indices
     based on a _single array_, this global variable can safely be used
     in a multi-threaded scenario.

 -- Type (C struct): gal_qsort_index_multi
     Structure to get the sorted indices of multiple datasets on
     multiple threads with ‘gal_qsort_index_multi_d’ or
     ‘gal_qsort_index_multi_i’.  Note that the ‘values’ array will not
     be changed by these functions, it is only read.  Therefore all the
     ‘values’ elements in the (to be sorted) array of
     ‘gal_qsort_index_multi’ must point to the same place.

          struct gal_qsort_index_multi
          {
            float *values;         /* Array of values (same in all).      */
            size_t  index;         /* Index of each element to be sorted. */
          };

 -- Function:
          int
          gal_qsort_TYPE_d (const void *a, const void *b)
     When passed to ‘qsort’, this function will sort a ‘TYPE’ array in
     decreasing order (first element will be the largest).  Please
     replace ‘TYPE’ (in the function name) with one of the *note Numeric
     data types::, for example, ‘gal_qsort_int32_d’, or
     ‘gal_qsort_float64_d’.

 -- Function:
          int
          gal_qsort_TYPE_i (const void *a, const void *b)
     When passed to ‘qsort’, this function will sort a ‘TYPE’ array in
     increasing order (first element will be the smallest).  Please
     replace ‘TYPE’ (in the function name) with one of the *note Numeric
     data types::, for example, ‘gal_qsort_int32_i’, or
     ‘gal_qsort_float64_i’.

 -- Function:
          int
          gal_qsort_index_single_TYPE_d (const void *a, const void *b)
     When passed to ‘qsort’, this function will sort a ‘size_t’ array
     based on decreasing values in the ‘gal_qsort_index_single’.  The
     global ‘gal_qsort_index_single’ pointer has a ‘void *’ pointer
     which will be cast to the proper type based on this function: for
     example ‘gal_qsort_index_single_uint16_d’ will cast the array to an
     unsigned 16-bit integer type.  The array that
     ‘gal_qsort_index_single’ points to will not be changed, it is only
     read.  For example, see this demo program:

          #include <stdio.h>
          #include <stdlib.h>           /* qsort is defined in stdlib.h. */
          #include <gnuastro/qsort.h>

          int
          main (void)
          {
            size_t s[4]={0, 1, 2, 3};
            float f[4]={1.3,0.2,1.8,0.1};
            gal_qsort_index_single=f;
            qsort(s, 4, sizeof(size_t), gal_qsort_index_single_float_d);
            printf("%zu, %zu, %zu, %zu\n", s[0], s[1], s[2], s[3]);
            return EXIT_SUCCESS;
          }

     The output will be: ‘2, 0, 1, 3’.

 -- Function:
          int
          gal_qsort_index_single_TYPE_i (const void *a, const void *b)
     Similar to ‘gal_qsort_index_single_TYPE_d’, but will sort the
     indexes such that the values of ‘gal_qsort_index_single’ can be
     parsed in increasing order.

 -- Function:
          int
          gal_qsort_index_multi_d (const void *a, const void *b)
     When passed to ‘qsort’ with an array of ‘gal_qsort_index_multi’,
     this function will sort the array based on the values of the given
     indices.  The sorting will be ordered according to the ‘values’
     pointer of ‘gal_qsort_index_multi’.  Note that ‘values’ must point
     to the same place in all the structures of the
     ‘gal_qsort_index_multi’ array.

     This function is only useful when the indices of multiple arrays on
     multiple threads are to be sorted.  If your program is single
     threaded, or all the indices belong to a single array (sorting
     different sub-sets of indices in a single array on multiple
     threads), it is recommended to use ‘gal_qsort_index_single_d’.

 -- Function:
          int
          gal_qsort_index_multi_i (const void *a, const void *b)
     Similar to ‘gal_qsort_index_multi_d’, but the result will be sorted
     in increasing order (first element will have the smallest value).


File: gnuastro.info,  Node: K-d tree,  Next: Permutations,  Prev: Qsort functions,  Up: Gnuastro library

12.3.19 K-d tree (‘kdtree.h’)
-----------------------------

K-d tree is a space-partitioning binary search tree for organizing
points in a k-dimensional space.  They are a very useful data structure
for multidimensional searches like range searches and nearest neighbor
searches.  For a more formal and complete introduction see the Wikipedia
page (https://en.wikipedia.org/wiki/K-d_tree).

   Each non-leaf node in a k-d tree divides the space into two parts,
known as half-spaces.  To select the top/root node for partitioning, we
find the median of the points and make a hyperplane normal to the first
dimension.  The points to the left of this space are represented by the
left subtree of that node and points to the right of the space are
represented by the right subtree.  This is then repeated for all the
points in the input, thus associating a “left” and “right” branch for
each input point.

   Gnuastro uses the standard algorithms of the k-d tree with one small
difference that makes it much more memory and CPU optimized.  The set of
input points that define the tree nodes are given as a list of
Gnuastro’s data container type, see *note List of gal_data_t::.  Each
‘gal_data_t’ in the list represents the point’s coordinate in one
dimension, and the first element in the list is the first dimension.
Hence the number of data values in each ‘gal_data_t’ (which must be
equal in all of them) represents the number of points.  This is the same
format that Gnuastro’s Table reading/writing functions read/write
columns in tables, see *note Table input output::.

   The output k-d tree is a list of two ‘gal_data_t’s, representing the
input’s row-number (or index, counting from 0) of the left and right
subtrees of each row.  Each ‘gal_data_t’ thus has the same number of
rows (or points) as the input, but only containing integers with a type
of ‘uint32_t’ (unsigned 32-bit integer).  If a node has no left, or
right subtree, then ‘GAL_BLANK_UINT32’ will be used.  Below you can see
the simple tree for 2D points from Wikipedia.  The input point
coordinates are represented as two input ‘gal_data_t’s (‘X’ and ‘Y’,
where ‘X->next=Y’ and ‘Y->next=NULL’).  If you had three dimensional
points, you could define an extra ‘gal_data_t’ such that ‘Y->next=Z’ and
‘Z->next=NULL’.  The output is always a list of two ‘gal_data_t’s, where
the first one contains the index of the left sub-tree in the input, and
the second one, the index of the right subtree.  The index of the root
node (‘0’ in the case below(1)) is also returned as a single number.

     INDEX         INPUT              OUTPUT              K-D Tree
     (as guide)    X --> Y        LEFT --> RIGHT        (visualized)
     ----------    -------        --------------     ------------------
     0             5     4        1        2               (5,4)
     1             2     3        BLANK    4               /   \
     2             7     2        5        3           (2,3)    \
     3             9     6        BLANK    BLANK           \    (7,2)
     4             4     7        BLANK    BLANK         (4,7)  /   \
     5             8     1        BLANK    BLANK               (8,1) (9,6)

   This format is therefore scalable to any number of dimensions: the
number of dimensions are determined from the number of nodes in the
input list of ‘gal_data_t’s (for example, using ‘gal_list_data_number’).
In Gnuastro’s k-d tree implementation, there are thus no special
structures to keep every tree node (which would take extra memory and
would need to be moved around as the tree is being created).  Everything
is done internally on the index of each point in the input dataset: the
only thing that is flipped/sorted during tree creation is the index to
the input row for any number of dimensions.  As a result, Gnuastro’s k-d
tree implementation is very memory and CPU efficient and its two output
columns can directly be written into a standard table (without having to
define any special binary format).

 -- Function:
          gal_data_t *
          gal_kdtree_create (gal_data_t *coords_raw, size_t *root)
     Create a k-d tree in a bottom-up manner (from leaves to the root).
     This function returns two ‘gal_data_t’s connected as a list, see
     description above.  The first dataset contains the indexes of left
     and right nodes of the subtrees for each input node.  The index of
     the root node is written into the memory that ‘root’ points to.
     ‘coords_raw’ is the list of the input points (one ‘gal_data_t’ per
     dimension, see above).  If the input dataset has no data
     (‘coords_raw->size==0’), this function will return a ‘NULL’
     pointer.

     For example, assume you have the simple set of points below (from
     the visualized example at the start of this section) in a
     plain-text file called ‘coordinates.txt’:

          $ cat coordinates.txt
          5     4
          2     3
          7     2
          9     6
          4     7
          8     1

     With the program below, you can calculate the kd-tree, and write it
     in a FITS file (while keeping the root index as a FITS keyword
     inside of it).

          #include <stdio.h>
          #include <gnuastro/table.h>
          #include <gnuastro/kdtree.h>

          int
          main (void)
          {
            gal_data_t *input, *kdtree;
            char kdtreefile[]="kd-tree.fits";
            char inputfile[]="coordinates.txt";

            /* To write the root within the saved file. */
            size_t root;
            char *unit="index";
            char *keyname="KDTROOT";
            gal_fits_list_key_t *keylist=NULL;
            char *comment="k-d tree root index (counting from 0).";

            /* Read the input table. Note: this assumes the table only
             * contains your input point coordinates (one column for each
             * dimension). If it contains more columns with other properties
             * for each point, you can specify which columns to read by
             * name or number, see the documentation of 'gal_table_read'. */
            input=gal_table_read(inputfile, "1", NULL, NULL,
                                 GAL_TABLE_SEARCH_NAME, 0, -1, 0, NULL);

            /* Construct a k-d tree. The index of root is stored in `root` */
            kdtree=gal_kdtree_create(input, &root);

            /* Write the k-d tree to a file and write root index and input
             * name as FITS keywords ('gal_table_write' frees 'keylist').*/
            gal_fits_key_list_title_add(&keylist, "k-d tree parameters", 0);
            gal_fits_key_write_filename("KDTIN", inputfile, &keylist, 0);
            gal_fits_key_list_add_end(&keylist, GAL_TYPE_SIZE_T, keyname, 0,
                                      &root, 0, comment, 0, unit, 0);
            gal_table_write(kdtree, &keylist, NULL, GAL_TABLE_FORMAT_BFITS,
                            kdtreefile, "kdtree", 0);

            /* Clean up and return. */
            gal_list_data_free(input);
            gal_list_data_free(kdtree);
            return EXIT_SUCCESS;
          }

     You can inspect the saved k-d tree FITS table with Gnuastro’s *note
     Table:: (first command below), and you can see the keywords
     containing the root index with *note Fits:: (second command below):

          asttable kd-tree.fits
          astfits kd-tree.fits -h1

 -- Function:
          size_t
          gal_kdtree_nearest_neighbour (gal_data_t *coords_raw,
          gal_data_t *kdtree, size_t root, double *point, double
          *least_dist)
     Returns the index of the nearest input point to the query point
     (‘point’, assumed to be an array with same number of elements as
     ‘gal_data_t’s in ‘coords_raw’).  The distance between the query
     point and its nearest neighbor is stored in the space that
     ‘least_dist’ points to.  This search is efficient due to the
     constant checking for the presence of possible best points in other
     branches.  If it is not possible for the other branch to have a
     better nearest neighbor, that branch is not searched.

     As an example, let’s use the k-d tree that was created in the
     example of ‘gal_kdtree_create’ (above) and find the nearest row to
     a given coordinate (‘point’).  This will be a very common scenario,
     especially in large and multi-dimensional datasets where the k-d
     tree creation can take long and you do not want to re-create the
     k-d tree every time.  In the ‘gal_kdtree_create’ example output, we
     also wrote the k-d tree root index as a FITS keyword (‘KDTROOT’),
     so after loading the two table data (input coordinates and k-d
     tree), we will read the root from the FITS keyword.  This is a very
     simple example, but the scalability is clear: for example, it is
     trivial to parallelize (see *note Library demo - multi-threaded
     operation::).

          #include <stdio.h>
          #include <gnuastro/table.h>
          #include <gnuastro/kdtree.h>

          int
          main (void)
          {
            /* INPUT: desired point. */
            double point[2]={8.9,5.9};

            /* Same as example in description of 'gal_kdtree_create'. */
            gal_data_t *input, *kdtree;
            char kdtreefile[]="kd-tree.fits";
            char inputfile[]="coordinates.txt";

            /* Processing variables of this function. */
            char kdtreehdu[]="1";
            double *in_x, *in_y, least_dist;
            size_t root, nkeys=1, nearest_index;
            gal_data_t *rkey, *keysll=gal_data_array_calloc(nkeys);

            /* Read the input coordinates, see comments in example of
             * 'gal_kdtree_create' for more. */
            input=gal_table_read(inputfile, "1", NULL, NULL,
                                 GAL_TABLE_SEARCH_NAME, 0, -1, 0, NULL);

            /* Read the k-d tree contents (created before). */
            kdtree=gal_table_read(kdtreefile, "1", NULL, NULL,
                                  GAL_TABLE_SEARCH_NAME, 0, -1, 0, NULL);

            /* Read the k-d tree root index from the header keyword.
             * See example in description of 'gal_fits_key_read_from_ptr'.*/
            keysll[0].name="KDTROOT";
            keysll[0].type=GAL_TYPE_SIZE_T;
            gal_fits_key_read(kdtreefile, kdtreehdu, keysll, 0, 0);
            keysll[0].name=NULL; /* Since we did not allocate it. */
            rkey=gal_data_copy_to_new_type(&keysll[0], GAL_TYPE_SIZE_T);
            root=((size_t *)(rkey->array))[0];

            /* Find the nearest neighbour of the point. */
            nearest_index=gal_kdtree_nearest_neighbour(input, kdtree, root,
                                                       point, &least_dist);

            /* Print the results. */
            in_x=input->array;
            in_y=input->next->array;
            printf("(%g, %g): nearest is (%g, %g), with a distance of %g\n",
                   point[0], point[1], in_x[nearest_index],
                   in_y[nearest_index], least_dist);

            /* Clean up and return. */
            gal_data_free(rkey);
            gal_list_data_free(input);
            gal_list_data_free(kdtree);
            gal_data_array_free(keysll, nkeys, 1);
            return EXIT_SUCCESS;
          }

   ---------- Footnotes ----------

   (1) This example input table is the same as the example in Wikipedia
(as of December 2020).  However, on the Wikipedia output, the root node
is (7,2), not (5,4).  The difference is primarily because there are 6
rows and the median element of an even number of elements can vary by
integer calculation strategies.  Here we use 0-based indexes for finding
median and round to the smaller integer.


File: gnuastro.info,  Node: Permutations,  Next: Matching,  Prev: K-d tree,  Up: Gnuastro library

12.3.20 Permutations (‘permutation.h’)
--------------------------------------

Permutation is the technical name for re-ordering of values.  The need
for permutations occurs a lot during (mainly low-level) processing.  To
do permutation, you must provide two inputs: an array of values (that
you want to re-order in place) and a permutation array which contains
the new index of each element (let’s call it ‘perm’).  The diagram below
shows the input array before and after the re-ordering.

     permute:    AFTER[ i       ] = BEFORE[ perm[i] ]     i = 0 .. N-1
     inverse:    AFTER[ perm[i] ] = BEFORE[ i       ]     i = 0 .. N-1

   The functions here are a re-implementation of the GNU Scientific
Library’s ‘gsl_permute’ function.  The reason we did not use that
function was that it uses system-specific types (like ‘long’ and ‘int’)
which can have different widths on different systems, hence are not
easily convertible to Gnuastro’s fixed width types (see *note Numeric
data types::).  There is also a separate function for each type, heavily
using macros to allow a ‘base’ function to work on all the types.  Thus
it is hard to read/understand.  Hence, Gnuastro contains a re-write of
their steps in a new type-agnostic method which is a single function
that can work on any type.

   As described in GSL’s source code and manual, this implementation
comes from Donald Knuth’s _Art of computer programming_ book, in the
"Sorting and Searching" chapter of Volume 3 (3rd ed).  Exercise 10 of
Section 5.2 defines the problem and in the answers, Knuth describes the
solution.  So if you are interested, please have a look there for more.

   We are in contact with the GSL developers and in the future(1) we
will submit these implementations to GSL. If they are finally
incorporated there, we will delete this section in future versions.

 -- Function:
          void
          gal_permutation_check (size_t *permutation, size_t size)
     Print how ‘permutation’ will re-order an array that has ‘size’
     elements for each element in one one line.

 -- Function:
          void
          gal_permutation_apply (gal_data_t *input, size_t *permutation)
     Apply ‘permutation’ on the ‘input’ dataset (can have any type), see
     above for the definition of permutation.

 -- Function:
          void
          gal_permutation_apply_inverse (gal_data_t *input, size_t
          *permutation)
     Apply the inverse of ‘permutation’ on the ‘input’ dataset (can have
     any type), see above for the definition of permutation.

 -- Function:
          void
          gal_permutation_transpose_2d (gal_data_t *input)
     Transpose an input 2D matrix into a new dataset.  If the input is
     not a square, this function will change the ‘input->array’ element
     to a newly allocated array (the old one will be freed internally).
     Therefore, in case you have already stored ‘input->array’ for other
     usage _before_ this function, and the input is not a square, be
     sure to update the previously stored pointer if the input is not a
     square.

   ---------- Footnotes ----------

   (1) Gnuastro’s Task 14497 (http://savannah.gnu.org/task/?14497).  If
this task is still “postponed” when you are reading this and you are
interested to help, your contributions would be very welcome.  Both
Gnuastro and GSL developers are very busy, hence both would appreciate
your help.


File: gnuastro.info,  Node: Matching,  Next: Statistical operations,  Prev: Permutations,  Up: Gnuastro library

12.3.21 Matching (‘match.h’)
----------------------------

Matching is often necessary when two measurements of the same points
have been done using different instruments (or hardware), different
software or different configurations of the same software.  In other
words, you have two catalogs or tables, and each has N columns
containing the N-dimensional “coordinate” values of each point.  Each
table can have other columns too, for example, one can have magnitudes
in one filter, and another can have morphology measurements.

   The matching functions here will use the coordinate columns of the
two tables to find a permutation for each, and the total number of
matched rows ($N_{match}$).  This will enable you to match by the
positions if you like.  At a higher level, you can apply the permutation
to the magnitude or morphology columns to merge the catalogs over the
$N_{match}$ rows.  The input and output data formats of the functions
are the some and described below before the actual functions.  Each
function also has extra arguments due to the particular algorithm it
uses for the matching.

   The two inputs of the functions (‘coord1’ and ‘coord2’) must be *note
List of gal_data_t::.  Each ‘gal_data_t’ node in ‘coord1’ or ‘coord2’
should be a single dimensional dataset (column in a table) and all the
nodes (in each) must have the same number of elements (rows).  In other
words, each column can be visualized as having the coordinates of each
point in its respective dimension.  The dimensions of the coordinates is
determined by the number of ‘gal_data_t’ nodes in the two input lists
(which must be equal).  The number of rows (or the number of elements in
each ‘gal_data_t’) in the columns of ‘coord1’ and ‘coord2’ can (and,
usually will!)  be different.  In summary, these functions will be happy
if you use ‘gal_table_read’ to read the two coordinate columns from a
file, see *note Table input output::.

   The functions below return a simply-linked list of three 1D datasets
(see *note List of gal_data_t::), let’s call the returned dataset ‘ret’.
The first two (‘ret’ and ‘ret->next’) are permutations.  In other words,
the ‘array’ elements of both have a type of ‘size_t’, see *note
Permutations::.  The third node (‘ret->next->next’) is the calculated
distance for that match and its array has a type of ‘double’.  The
number of matches will be put in the space pointed by the ‘nummatched’
argument.  If there was not any match, this function will return ‘NULL’.

   The two permutations can be applied to the rows of the two inputs:
the first one (‘ret’) should be applied to the rows of the table
containing ‘coord1’ and the second one (‘ret->next’) to the table
containing ‘coord2’.  After applying the returned permutations to the
inputs, the top ‘nummatched’ elements of both will match with each
other.  The ordering of the rest of the elements is undefined (depends
on the matching function used).  The third node is the distances between
the respective match (which may be elliptical distance, see discussion
of “aperture” below).

   The functions will not simply return the nearest neighbor as a match.
This is because the nearest neighbor may be too far to be a meaningful!
They will check the distance between the nearest neighbor of each point
and only return a match if it is within an acceptable N-dimensional
distance (or “aperture”).  The matching aperture is defined by the
‘aperture’ array that is an input argument to the functions.

   If several points of one catalog lie within this aperture of a point
in the other catalog, the nearest is defined as the match.  In a 2D
situation (where the input lists have two nodes), for the most generic
case, ‘aperture’ must have three elements: the major axis length, axis
ratio and position angle (see *note Defining an ellipse and
ellipsoid::).  If ‘aperture[1]==1’, the aperture will be a circle of
radius ‘aperture[0]’ and the third value will not be used.  When the
aperture is an ellipse, distances between the points are also calculated
in the respective elliptical distances ($r_{el}$ in *note Defining an
ellipse and ellipsoid::).

   *Output permutations ignore internal sorting*: the output
permutations will correspond to the initial inputs.  Therefore, even
when ‘inplace!=0’ (and this function re-arranges the inputs in place),
the output permutation will correspond to original (possibly non-sorted)
inputs.  The reason for this is that you rarely want to permute the
actual positional columns after the match.  Usually, you also have other
columns (such as the magnitude and morphology) and you want to find how
they differ between the objects that match.  Once you have the
permutations, they can be applied to those other columns (see *note
Permutations::) and the higher-level processing can continue.  So if you
do not need the coordinate columns for the rest of your analysis, it is
better to set ‘inplace=1’.

 -- Function:
          gal_data_t *
          gal_match_sort_based (gal_data_t *coord1, gal_data_t *coord2,
          double *aperture, int sorted_by_first, int inplace, size_t
          minmapsize, int quietmmap, size_t *nummatched)

     Use a basic sort-based match to find the matching points of two
     input coordinates.  See the descriptions above on the format of the
     inputs and outputs.  To speed up the search, this function will
     sort the input coordinates by their first column (first axis).  If
     _both_ are already sorted by their first column, you can avoid the
     sorting step by giving a non-zero value to ‘sorted_by_first’.

     When sorting is necessary and ‘inplace’ is non-zero, the actual
     input columns will be sorted.  Otherwise, an internal copy of the
     inputs will be made, used (sorted) and later freed before
     returning.  Therefore, when ‘inplace==0’, inputs will remain
     untouched, but this function will take more time and memory.  If
     internal allocation is necessary and the space is larger than
     ‘minmapsize’, the space will be not allocated in the RAM, but in a
     file, see description of ‘--minmapsize’ and ‘--quietmmap’ in *note
     Processing options::.

 -- Function:
          gal_data_t *
          gal_match_kdtree (gal_data_t *coord1, gal_data_t *coord2,
          gal_data_t *coord1_kdtree, size_t kdtree_root, double
          *aperture, size_t numthreads, size_t minmapsize, int
          quietmmap, size_t *nummatched)

     Use the k-d tree concept for finding matches between two catalogs,
     optionally in parallel (on ‘numthreads’ threads).  The k-d tree of
     the first input (‘coord1_kdtree’), and its root index
     (‘kdtree_root’), should be constructed and found before calling
     this function, to do this, you can use the ‘gal_kdtree_create’ of
     *note K-d tree::.  The desired ‘aperture’ array is the same as
     ‘gal_match_sort_based’ and described at the top of this section.
     If ‘coord1_kdtree==NULL’, this function will return a ‘NULL’
     pointer and write a value of ‘0’ in the space that ‘nummatched’
     points to.

     The final number of matches is returned in ‘nummatched’ and the
     format of the returned dataset (three columns) is described above.
     If internal allocation is necessary and the space is larger than
     ‘minmapsize’, the space will be not allocated in the RAM, but in a
     file, see description of ‘--minmapsize’ and ‘--quietmmap’ in *note
     Processing options::.


File: gnuastro.info,  Node: Statistical operations,  Next: Fitting functions,  Prev: Matching,  Up: Gnuastro library

12.3.22 Statistical operations (‘statistics.h’)
-----------------------------------------------

After reading a dataset into memory from a file or fully simulating it
with another process, the most common processes that will be done on it
are statistical operations to let you quantify different aspects of the
data.  the functions in this section describe Gnuastro’s current set of
tools for this job.  All these functions can work on any numeric data
type natively (see *note Numeric data types::) and can also work on
tiles over a dataset.  Hence the inputs and outputs are in Gnuastro’s
*note Generic data container::.

 -- Macro: GAL_STATISTICS_SIG_CLIP_MAX_CONVERGE
     The maximum number of clips, when $\sigma$-clipping should be done
     by convergence.  If the clipping does not converge before making
     this many clips, all $\sigma$-clipping outputs will be NaN.

 -- Macro: GAL_STATISTICS_MODE_GOOD_SYM
     The minimum acceptable symmetricity of the mode calculation.  If
     the symmetricity of the derived mode is less than this value, all
     the returned values by ‘gal_statistics_mode’ will have a value of
     NaN.

 -- Macro: GAL_STATISTICS_BINS_INVALID
 -- Macro: GAL_STATISTICS_BINS_REGULAR
 -- Macro: GAL_STATISTICS_BINS_IRREGULAR
     Macros used to identify if the regularity of the bins when defining
     bins.

 -- Function:
          gal_data_t *
          gal_statistics_number (gal_data_t *input)
     Return a single-element dataset with type ‘size_t’ which contains
     the number of non-blank elements in ‘input’.

 -- Function:
          gal_data_t *
          gal_statistics_minimum (gal_data_t *input)
     Return a single-element dataset containing the minimum non-blank
     value in ‘input’.  The numerical datatype of the output is the same
     as ‘input’.

 -- Function:
          gal_data_t *
          gal_statistics_maximum (gal_data_t *input)
     Return a single-element dataset containing the maximum non-blank
     value in ‘input’.  The numerical datatype of the output is the same
     as ‘input’.

 -- Function:
          gal_data_t *
          gal_statistics_sum (gal_data_t *input)
     Return a single-element (‘double’ or ‘float64’) dataset containing
     the sum of the non-blank values in ‘input’.

 -- Function:
          gal_data_t *
          gal_statistics_mean (gal_data_t *input)
     Return a single-element (‘double’ or ‘float64’) dataset containing
     the mean of the non-blank values in ‘input’.

 -- Function:
          gal_data_t *
          gal_statistics_std (gal_data_t *input)
     Return a single-element (‘double’ or ‘float64’) dataset containing
     the standard deviation of the non-blank values in ‘input’.

 -- Function:
          gal_data_t *
          gal_statistics_mean_std (gal_data_t *input)
     Return a two-element (‘double’ or ‘float64’) dataset containing the
     mean and standard deviation of the non-blank values in ‘input’.
     The first element of the returned dataset is the mean and the
     second is the standard deviation.

     This function will calculate both values in one pass over the
     dataset.  Hence when both the mean and standard deviation of a
     dataset are necessary, this function is much more efficient than
     calling ‘gal_statistics_mean’ and ‘gal_statistics_std’ separately.

 -- Function:
          double
          gal_statistics_std_from_sums (double sum, double sump2, size_t
          num)
     Return the standard deviation from the values that can be obtained
     in a single pass through the distribution: ‘sum’: the sum of the
     elements, ‘sump2’: the sum of the power-of-2 of each element, and
     ‘num’: the number of elements.

     This is a low-level function that is only useful after the
     distribution of values has been parsed (and the three input
     arguments are calculated).  It is the lower-level function that is
     used in functions like ‘gal_statistics_std’, or other components of
     Gnuastro that measure the standard deviation (for example,
     MakeCatalog’s ‘--std’ column).

 -- Function:
          gal_data_t *
          gal_statistics_median (gal_data_t *input, int inplace)
     Return a single-element dataset containing the median of the
     non-blank values in ‘input’.  The numerical datatype of the output
     is the same as ‘input’.

     Calculating the median involves sorting the dataset and removing
     blank values, for better performance (and less memory usage), you
     can give a non-zero value to the ‘inplace’ argument.  In this case,
     the sorting and removal of blank elements will be done directly on
     the input dataset.  However, after this function the original
     dataset may have changed (if it was not sorted or had blank
     values).

 -- Function:
          size_t
          gal_statistics_quantile_index (size_t size, double quantile)
     Return the index of the element that has a quantile of ‘quantile’
     assuming the dataset has ‘size’ elements.

 -- Function:
          gal_data_t *
          gal_statistics_quantile (gal_data_t *input, double quantile,
          int inplace)
     Return a single-element dataset containing the value with in a
     quantile ‘quantile’ of the non-blank values in ‘input’.  The
     numerical datatype of the output is the same as ‘input’.  See
     ‘gal_statistics_median’ for a description of ‘inplace’.

 -- Function:
          size_t
          gal_statistics_quantile_function_index (gal_data_t *input,
          gal_data_t *value, int inplace)
     Return the index of the quantile function (inverse quantile) of
     ‘input’ at ‘value’.  In other words, this function will return the
     index of the nearest element (of a sorted and non-blank) ‘input’ to
     ‘value’.  If the value is outside the range of the input, then this
     function will return ‘GAL_BLANK_SIZE_T’.

 -- Function:
          gal_data_t *
          gal_statistics_quantile_function (gal_data_t *input,
          gal_data_t *value, int inplace)

     Return a single-element dataset containing the quantile function of
     the non-blank values in ‘input’ at ‘value’ (a single-element
     dataset).  The numerical data type is of the returned dataset is
     ‘float64’ (or ‘double’).  In other words, this function will return
     the quantile of ‘value’ in ‘input’.  ‘value’ has to have the same
     type as ‘input’.  See ‘gal_statistics_median’ for a description of
     ‘inplace’.

     When all elements are blank, the returned value will be NaN. If the
     value is smaller than the input’s smallest element, the returned
     value will be negative infinity.  If the value is larger than the
     input’s largest element, then the returned value will be positive
     infinity

 -- Function:
          gal_data_t *
          gal_statistics_unique (gal_data_t *input, int inplace)
     Return a 1D dataset with the same numeric data type as the input,
     but only containing its unique elements and without any (possible)
     blank/NaN elements.  Note that the input’s number of dimensions is
     irrelevant for this function.  If ‘inplace’ is not zero, then the
     unique values will over-write the allocated space of the input,
     otherwise a new space will be allocated and the input will not be
     touched.

 -- Function:
          int
          gal_statistics_has_negative (gal_data_t *input)
     Return ‘1’ if the input dataset contains a negative number and ‘0’
     otherwise.  If the dataset doesn’t have a numeric type (as in a
     string), this function will abort with, saying that it does not
     recognize the file type.

 -- Function:
          gal_data_t *
          gal_statistics_mode (gal_data_t *input, float mirrordist, int
          inplace)
     Return a four-element (‘double’ or ‘float64’) dataset that contains
     the mode of the ‘input’ distribution.  This function implements the
     non-parametric algorithm to find the mode that is described in
     Appendix C of Akhlaghi and Ichikawa [2015]
     (https://arxiv.org/abs/1505.01664).

     In short it compares the actual distribution and its “mirror
     distribution” to find the mode.  In order to be efficient, you can
     determine how far the comparison goes away from the mirror through
     the ‘mirrordist’ parameter (think of it as a multiple of
     sigma/error).  See ‘gal_statistics_median’ for a description of
     ‘inplace’.

     The output array has the following elements (in the given order,
     note that counting in C starts from 0).
          array[0]: mode
          array[1]: mode quantile.
          array[2]: symmetricity.
          array[3]: value at the end of symmetricity.

 -- Function:
          gal_data_t *
          gal_statistics_mode_mirror_plots (gal_data_t *input,
          gal_data_t *value, size_t numbins, int inplace, double
          *mirror_val)
     Make a mirrored histogram and cumulative frequency plot (with
     ‘numbins’) with the mirror distribution of the ‘input’ having a
     value in ‘value’.  If all the input elements are blank, or the
     mirror value is outside the range of the input, this function will
     return a ‘NULL’ pointer.

     The output is a list of data structures (see *note List of
     gal_data_t::): the first is the bins with one bin at the mirror
     point, the second is the histogram with a maximum of one and the
     third is the cumulative frequency plot (with a maximum of one).

 -- Function:
          int
          gal_statistics_is_sorted (gal_data_t *input, int updateflags)
     Return ‘0’ if the input is not sorted, if it is sorted, this
     function will return ‘1’ and ‘2’ if it is increasing or decreasing,
     respectively.  This function will abort with an error if ‘input’
     has zero elements and will return ‘1’ (sorted, increasing) when
     there is only one element.  This function will only look into the
     dataset if the ‘GAL_DATA_FLAG_SORT_CH’ bit of ‘input->flag’ is ‘0’,
     see *note Generic data container::.

     When the flags do not indicate a previous check _and_ ‘updateflags’
     is non-zero, this function will set the flags appropriately to
     avoid having to re-check the dataset in future calls (this can be
     very useful when repeated checks are necessary).  When
     ‘updateflags==0’, this function has no side-effects on the dataset:
     it will not toggle the flags.

     If you want to re-check a dataset with the blank-value-check flag
     already set (for example, if you have made changes to it), then
     explicitly set the ‘GAL_DATA_FLAG_SORT_CH’ bit to zero before
     calling this function.  When there are no other flags, you can
     simply set the flags to zero (with ‘input->flag=0’), otherwise you
     can use this expression:

          input->flag &= ~GAL_DATA_FLAG_SORT_CH;

 -- Function:
          void
          gal_statistics_sort_increasing (gal_data_t *input)
     Sort the input dataset (in place) in an increasing order and toggle
     the sort-related bit flags accordingly.

 -- Function:
          void
          gal_statistics_sort_decreasing (gal_data_t *input)
     Sort the input dataset (in place) in a decreasing order and toggle
     the sort-related bit flags accordingly.

 -- Function:
          gal_data_t *
          gal_statistics_no_blank_sorted (gal_data_t *input, int
          inplace)
     Remove all the blanks and sort the input dataset.  If ‘inplace’ is
     non-zero this will happen on the input dataset (in the allocated
     space of the input dataset).  However, if ‘inplace’ is zero, this
     function will allocate a new copy of the dataset and work on that.
     Therefore if ‘inplace==0’, the input dataset will be modified.

     This function uses the bit flags of the input, so if you have
     modified the dataset, set ‘input->flag=0’ before calling this
     function.  Also note that ‘inplace’ is only for the dataset
     elements.  Therefore even when ‘inplace==0’, if the input is
     already sorted _and_ has no blank values, then the flags will be
     updated to show this.

     If all the elements were blank, then the returned dataset’s ‘size’
     will be zero.  This is thus a good parameter to check after calling
     this function to see if there actually were any non-blank elements
     in the input or not and take the appropriate measure.  This can
     help avoid strange bugs in later steps.  The flags of a zero-sized
     returned dataset will indicate that it has no blanks and is sorted
     in an increasing order.  Even if having blank values or being
     sorted is not defined on a zero-element dataset, it is up to the
     caller to choose what they will do with a zero-element dataset.
     The flags have to be set after this function any way.

 -- Function:
          gal_data_t *
          gal_statistics_regular_bins (gal_data_t *input, gal_data_t
          *inrange, size_t numbins, double onebinstart)
     Generate an array of regularly spaced elements as a 1D array
     (column) of type ‘double’ (i.e., ‘float64’, it has to be double to
     account for small differences on the bin edges).  The input
     arguments are described below

     ‘input’
          The dataset you want to apply the bins to.  This is only
          necessary if the range argument is not complete, see below.
          If ‘inrange’ has all the necessary information, you can pass a
          ‘NULL’ pointer for this.

     ‘inrange’
          This dataset keeps the desired range along each dimension of
          the input data structure, it has to be in ‘float’ (i.e.,
          ‘float32’) type.

             • If you want the full range of the dataset (in any
               dimensions, then just set ‘inrange’ to ‘NULL’ and the
               range will be specified from the minimum and maximum
               value of the dataset (‘input’ cannot be ‘NULL’ in this
               case).

             • If there is one element for each dimension in range, then
               it is viewed as a quantile (Q), and the range will be: ‘Q
               to 1-Q’.

             • If there are two elements for each dimension in range,
               then they are assumed to be your desired minimum and
               maximum values.  When either of the two are NaN, the
               minimum and maximum will be calculated for it.

     ‘numbins’
          The number of bins: must be larger than 0.

     ‘onebinstart’
          A desired value to start one bin.  Note that with this option,
          the bins will not start and end exactly on the given range
          values, it will be slightly shifted to accommodate this
          request (enough for the bin containing the value to start at
          it).  If you do not have any preference on where to start a
          bin, set this to NAN.

 -- Function:
          gal_data_t *
          gal_statistics_histogram (gal_data_t *input, gal_data_t *bins,
          int normalize, int maxone)
     Make a histogram of all the elements in the given dataset with bin
     values that are defined in the ‘bins’ structure (see
     ‘gal_statistics_regular_bins’, they currently have to be equally
     spaced).  The returned histogram is a 1-D ‘gal_data_t’ of type
     ‘GAL_TYPE_FLOAT32’, with the same number of elements as ‘bins’.
     For each bin, it will contain the number of input elements that
     fell inside of that bin.

     Let’s write the center of the $i$th element of the bin array as
     $b_i$, and the fixed half-bin width as $h$.  Then element $j$ of
     the input array ($in_j$) will be counted in $b_i$ if $(b_i-h) \le
     in_j < (b_i+h)$.  However, if $in_j$ is somewhere in the last bin,
     the condition changes to $(b_i-h) \le in_j \le (b_i+h)$.

     If ‘normalize!=0’, the histogram will be “normalized” such that the
     sum of the counts column will be one.  In other words, all the
     counts in every bin will be divided by the total number of counts.
     If ‘maxone!=0’, the histogram’s maximum count will be 1.  In other
     words, the counts in every bin will be divided by the value of the
     maximum.  In both of these cases, the output dataset will have a
     ‘GAL_DATA_FLOAT32’ datatype.

 -- Function:
          gal_data_t *
          gal_statistics_histogram2d (gal_data_t *input, gal_data_t
          *bins)
     This function is very similar to ‘gal_statistics_histogram’, but
     will build a 2D histogram (count how many of the elements of
     ‘input’ are a within a 2D box.  The bins comprising the first
     dimension of the 2D box are defined by ‘bins’.  The bins of the
     second dimension are defined by ‘bins->next’ (‘bins’ is a *note
     List of gal_data_t::).  Both the ‘bin’ and ‘bin->next’ can be
     created with ‘gal_statistics_regular_bins’.

     This function returns a list of ‘gal_data_t’ with three
     nodes/columns, so you can directly write them into a table (see
     *note Table input output::).  Assuming ‘bins’ has $N1$ bins and
     ‘bins->next’ has $N2$ bins, each node/column of the returned output
     is a 1D array with $N1\times N2$ elements.  The first and second
     columns are the center of the 2D bin along the first and second
     dimensions and have a ‘double’ data type.  The third column is the
     2D histogram (the number of input elements that have a value within
     that 2D bin) and has a ‘uint32’ data type (see *note Numeric data
     types::).

 -- Function:
          gal_data_t *
          gal_statistics_cfp (gal_data_t *input, gal_data_t *bins, int
          normalize)
     Make a cumulative frequency plot (CFP) of all the elements in
     ‘input’ with bin values that are defined in the ‘bins’ structure
     (see ‘gal_statistics_regular_bins’).

     The CFP is built from the histogram: in each bin, the value is the
     sum of all previous bins in the histogram.  Thus, if you have
     already calculated the histogram before calling this function, you
     can pass it onto this function as the data structure in
     ‘bins->next’ (see ‘List of gal_data_t’).  If ‘bin->next!=NULL’,
     then it is assumed to be the histogram.  If it is ‘NULL’, then the
     histogram will be calculated internally and freed after the job is
     finished.

     When a histogram is given and it is normalized, the CFP will also
     be normalized (even if the normalized flag is not set here): note
     that a normalized CFP’s maximum value is 1.

 -- Function:
          gal_data_t *
          gal_statistics_sigma_clip (gal_data_t *input, float multip,
          float param, int inplace, int quiet)
     Apply $\sigma$-clipping on a given dataset and return a dataset
     that contains the results.  For a description of $\sigma$-clipping
     see *note Sigma clipping::.  ‘multip’ is the multiple of the
     standard deviation (or $\sigma$, that is used to define outliers in
     each round of clipping).

     The role of ‘param’ is determined based on its value.  If ‘param’
     is larger than ‘1’ (one), it must be an integer and will be
     interpreted as the number clips to do.  If it is less than ‘1’
     (one), it is interpreted as the tolerance level to stop the
     iteration.

     The returned dataset (let’s call it ‘out’) contains a four-element
     array with type ‘GAL_TYPE_FLOAT32’.  The final number of clips is
     stored in the ‘out->status’.
          float *array=out->array;
          array[0]: Number of points used.
          array[1]: Median.
          array[2]: Mean.
          array[3]: Standard deviation.

     If the $\sigma$-clipping does not converge or all input elements
     are blank, then this function will return NaN values for all the
     elements above.

 -- Function:
          gal_data_t *
          gal_statistics_outlier_bydistance (int pos1_neg0, gal_data_t
          *input, size_t window_size, float sigma, float sigclip_multip,
          float sigclip_param, int inplace, int quiet)

     Find the first positive outlier (if ‘pos1_neg0!=0’) in the ‘input’
     distribution.  When ‘pos1_neg0==0’, the same algorithm goes to the
     start of the dataset.  The returned dataset contains a single
     element: the first positive outlier.  It is one of the dataset’s
     elements, in the same type as the input.  If the process fails for
     any reason (for example, no outlier was found), a ‘NULL’ pointer
     will be returned.

     All (possibly existing) blank elements are first removed from the
     input dataset, then it is sorted.  A sliding window of
     ‘window_size’ elements is parsed over the dataset.  Starting from
     the ‘window_size’-th element of the dataset, in the direction of
     increasing values.  This window is used as a reference.  The first
     element where the distance to the previous (sorted) element is
     ‘sigma’ units away from the distribution of distances in its window
     is considered an outlier and returned by this function.

     Formally, if we assume there are $N$ non-blank elements.  They are
     first sorted.  Searching for the outlier starts on element $W$.
     Let’s take $v_i$ to be the $i$-th element of the sorted input (with
     no blank values) and $m$ and $\sigma$ as the $\sigma$-clipped
     median and standard deviation from the distances of the previous
     $W$ elements (not including $v_i$).  If the value given to ‘sigma’
     is displayed with $s$, the $i$-th element is considered as an
     outlier when the condition below is true.

                  $${(v_i-v_{i-1})-m\over \sigma}>s$$

     The ‘sigclip_multip’ and ‘sigclip_param’ arguments specify the
     properties of the $\sigma$-clipping (see *note Sigma clipping:: for
     more).  You see that by this definition, the outlier cannot be any
     of the lower half elements.  The advantage of this algorithm
     compared to $\sigma$-clippign is that it only looks backwards (in
     the sorted array) and parses it in one direction.

     If ‘inplace!=0’, the removing of blank elements and sorting will be
     done within the input dataset’s allocated space.  Otherwise, this
     function will internally allocate (and later free) the necessary
     space to keep the intermediate space that this process requires.

     If ‘quiet!=0’, this function will report the parameters every time
     it moves the window as a separate line with several columns.  The
     first column is the value, the second (in square brackets) is the
     sorted index, the third is the distance of this element from the
     previous one.  The Fourth and fifth (in parenthesis) are the median
     and standard deviation of the $\sigma$-clipped distribution within
     the window and the last column is the difference between the third
     and fourth, divided by the fifth.

 -- Function:
          gal_data_t *
          gal_statistics_outlier_flat_cfp (gal_data_t *input, size_t
          numprev, float sigclip_multip, float sigclip_param, float
          thresh, size_t numcontig, int inplace, int quiet, size_t
          *index)

     Return the first element in the given dataset where the cumulative
     frequency plot first becomes significantly flat for a sufficient
     number of elements.  The returned dataset only has one element
     (with the same type as the input).  If ‘index!=NULL’, the index
     (counting from zero, after sorting the dataset and removing any
     blanks) is written in the space that ‘index’ points to.  If no
     sufficiently flat portion is found, the returned pointer will be
     ‘NULL’.

     The flatness on the cumulative frequency plot is defined like this
     (see *note Histogram and Cumulative Frequency Plot::): on the
     sorted dataset, for every point ($a_i$), we calculate
     $d_i=a_{i+2}-a_{i-2}$.  This done on the first $N$ elements (value
     of ‘numprev’).  After element $a_{N+2}$, we start estimating the
     flatness as follows: for every element we use the $N$, $d_i$
     measurements before it as the reference.  Let’s call this set $D_i$
     for element $i$.  The $\sigma$-clipped median ($m$) and standard
     deviation ($s$) of $D_i$ are then calculated.  The
     $\sigma$-clipping can be configured with the two ‘sigclip_param’
     and ‘sigclip_multip’ arguments.

     Taking $t$ as the significance threshold (value to ‘thresh’), a
     point is considered flat when $a_i>m+t\sigma$.  But a single point
     satisfying this condition will probably just be due to noise.  To
     make a more robust estimate, this significance/condition has to
     hold for ‘numcontig’ contiguous elements after $a_i$.  When this is
     satisfied, $a_i$ is returned as the point where the distribution’s
     cumulative frequency plot becomes flat.

     To get a good estimate of $m$ and $s$, it is thus recommended to
     set ‘numprev’ as large as possible.  However, be careful not to set
     it too high: the checks in the paragraph above are not done on the
     first ‘numprev’ elements and this function assumes the flatness
     occurs after them.  Also, be sure that the value to ‘numcontig’ is
     much less than ‘numprev’, otherwise $\sigma$-clipping may not be
     able to remove the immediate outliers in $D_i$ near the boundary of
     the flat region.

     When ‘quiet==0’, the basic measurements done on each element are
     printed on the command-line (good for finding the best parameters).
     When ‘inplace!=0’, the sorting and removal of blank elements is
     done on the input dataset, so the input may be altered after this
     function.


File: gnuastro.info,  Node: Fitting functions,  Next: Binary datasets,  Prev: Statistical operations,  Up: Gnuastro library

12.3.23 Fitting functions (‘fit.h’)
-----------------------------------

After doing a measurement, it is usually necessary to parameterize the
relation that has been found.  The functions in this section are
wrappers over the GNU Scientific Library (GSL) Linear Least-Squares
Fitting (https://www.gnu.org/software/gsl/doc/html/lls.html), to make
them easily accessible using Gnuastro’s *note Generic data container::.
The respective GSL function is mentioned under each function.

 -- Global integer: GAL_FIT_INVALID
 -- Global integer: GAL_FIT_LINEAR
 -- Global integer: GAL_FIT_LINEAR_WEIGHTED
 -- Global integer: GAL_FIT_LINEAR_NO_CONSTANT
 -- Global integer: GAL_FIT_LINEAR_NO_CONSTANT_WEIGHTED
 -- Global integer: GAL_FIT_POLYNOMIAL
 -- Global integer: GAL_FIT_POLYNOMIAL_WEIGHTED
 -- Global integer: GAL_FIT_POLYNOMIAL_NUMBER
     Identifiers for the various types of fitting functions.  These can
     be used by the callers of these functions to select between various
     fitting types.  They can easily be converted to, and from, fixed
     human-readable strings using the ‘gal_fit_name_*’ functions below.
     The last one ‘GAL_FIT_ROBUST_NUMBER’ is the total number of
     available fitting methods (can be used to add more macros in the
     calling program and to avoid overlaps with existing codes).

 -- Global integer: GAL_FIT_ROBUST_INVALID
 -- Global integer: GAL_FIT_ROBUST_DEFAULT
 -- Global integer: GAL_FIT_ROBUST_BISQUARE
 -- Global integer: GAL_FIT_ROBUST_CAUCHY
 -- Global integer: GAL_FIT_ROBUST_FAIR
 -- Global integer: GAL_FIT_ROBUST_HUBER
 -- Global integer: GAL_FIT_ROBUST_OLS
 -- Global integer: GAL_FIT_ROBUST_WELSCH
 -- Global integer: GAL_FIT_ROBUST_NUMBER
     Identifiers for the various types of robust polynomial fitting
     functions.  For a description of each, see
     <https://www.gnu.org/s/gsl/doc/html/lls.html#c.gsl_multifit_robust_alloc>.
     The last one ‘GAL_FIT_ROBUST_NUMBER’ is the total number of
     available functions (can be used to add more macros in the calling
     program and to avoid overlaps with existing codes).

 -- Function:
          uint8_t
          gal_fit_name_to_id (char *name)
     Return the internal code of a standard human-readable name for the
     various fitting functions.  If the name is not recognized, the
     returned value will be ‘GAL_FIT_INVALID’.

 -- Function:
          char *
          gal_fit_name_from_id (uint8_t fitid)
     Return a standard human-readable name for the fitting function
     identified with the ‘fitid’ (read as “fitting ID”).  If the fitting
     ID couldn’t be recognized, a NULL pointer is returned.

 -- Function:
          uint8_t
          gal_fit_name_robust_to_id (char *name)
     Return the internal code of a standard human-readable name for the
     various robust fitting types.  If the name is not recognized, the
     returned value will be ‘GAL_FIT_INVALID’.

 -- Function:
          char *
          gal_fit_name_robust_from_id (uint8_t robustid)
     Return a standard human-readable name for the input robust fitting
     type.  If the fitting ID couldn’t be recognized, a NULL pointer is
     returned.

 -- Function:
          gal_data_t *
          gal_fit_1d_linear (gal_data_t *xin, gal_data_t *yin,
          gal_data_t *ywht)
     Preform a 1D linear regression fit with a constant term(1) in the
     form of $Y=c_0+c_1X$.  The input ‘xin’ contains the independent
     variable values and ‘yin’ contains the measured variable values for
     each independent variable.  When ‘ywht!=NULL’, it is assumed to
     contain the “weight” of each Y measurement (if you don’t have
     weights on your measured values, simply set this to ‘NULL’).  The
     weight of each measurement is the inverse of its variance.  For a
     Gaussian error distribution with standard deviation $\sigma$, the
     weight is therefore $1/\sigma^2$.

     If any of the values in any of the inputs is blank (NaN in floating
     point), the final fitted parameters will all be NaN. To remove rows
     with a NaN/blank, you can use ‘gal_blank_remove_rows’ (which will
     remove all rows with a blank values in any of the columns with a
     single call).

     The output is a single dataset with a ‘GAL_TYPE_FLOAT64’ type with
     6 elements:
       1. $c_0$: the constant in $Y=c_0+c_1X$.
       2. $c_1$: the multiple in $Y=c_0+c_1X$.
       3. First element of variance-covariance matrix.
       4. Second and third (which are equal) elements of the
          variance-covariance matrix.
       5. Fourth element of the variance-covariance matrix.
       6. The reduced $\chi^2$ of the fit.

 -- Function:
          gal_data_t *
          gal_fit_1d_linear_no_constant (gal_data_t *xin, gal_data_t
          *yin, gal_data_t *ywht)
     Preform a 1D linear regression fit _without_ a constant term(2),
     formally: $Y=c_1X$.  The input ‘xin’ contains the independent
     variable values and ‘yin’ contains the measured variable values for
     each independent variable.  When ‘ywht!=NULL’, it is assumed to
     contain the “weight” of each Y measurement (if you don’t have
     weights on your measured values, simply set this to ‘NULL’).  The
     weight of each measurement is the inverse of its variance.  For a
     Gaussian error distribution with standard deviation $\sigma$, the
     weight is therefore $1/\sigma^2$.

     If any of the values in any of the inputs is blank (NaN in floating
     point), the final fitted parameters will all be NaN. To remove rows
     with a NaN/blank, you can use ‘gal_blank_remove_rows’ (which will
     remove all rows with a blank values in any of the columns with a
     single call).

     The output is a single dataset with a ‘GAL_TYPE_FLOAT64’ type with
     3 elements:
       1. $c_1$: the multiple in $Y=c_0+c_1X$.
       2. Variance of $c_1$.
       3. The reduced $\chi^2$ of the fit.

 -- Function:
          gal_data_t *
          gal_fit_1d_linear_estimate (gal_data_t *fit, gal_data_t *xin)
     Given a linear least squares fit output (‘fit’), estimate the fit
     on an arbitrary number of independent variable (horizontal axis, or
     X, in an X-Y plot) within ‘xin’.  ‘fit’ is assumed to be the output
     of either ‘gal_fit_1d_linear’ or ‘gal_fit_1d_linear_no_constant’.
     In case you haven’t used those functions to obtain the constants
     and covariance matrix elements, see the description of those
     functions for the expected format of ‘fit’.

     This function returns two columns (as a *note List of
     gal_data_t::): The top node of the list is the estimated values at
     the input X-axis positions, and the next node is the errors in the
     estimation.  Naturally, both have the same number of elements as
     ‘xin’.  Being a list, helps in easily printing the output columns
     to a table (see *note Table input output::).

 -- Function:
          gal_data_t *
          gal_fit_1d_polynomial (gal_data_t *xin, gal_data_t *yin,
          gal_data_t *ywht, size_t maxpower, double *redchisq)
     Preform a 1D polynomial fit, formally:
     $Y=c+0+c_1X+c_2X^2+\cdots+c_nX^n$ (using GSL’s multi-parameter
     regression(3)).  The largest power of $X$ is determined with the
     ‘maxpower’ argument (which is $n$ in the equation above).  The
     reduced $\chi^2$ of the fit is written in the space that
     ‘*redchisq’ points to.

     The input ‘xin’ contains the independent variable values and the
     input ‘yin’ contains the measured variable values for each
     independent variable.  When ‘ywht!=NULL’, it is assumed to contain
     the “weight” of each Y measurement (if you don’t have weights on
     your measured values, simply set this to ‘NULL’).  The weight of
     each measurement is the inverse of its variance.  For a Gaussian
     error distribution with standard deviation $\sigma$, the weight is
     therefore $1/\sigma^2$.

     If any of the values in any of the inputs is blank (NaN in floating
     point), the final fitted parameters will all be NaN. To remove rows
     with a NaN/blank, you can use ‘gal_blank_remove_rows’ (which will
     remove all rows with a blank values in any of the columns with a
     single call).

     The output of this function is a list of two datasets, linked as a
     list (as a *note List of gal_data_t::).  Both have a
     ‘GAL_TYPE_FLOAT64’ type, and are described below (in order).
       1. A one dimensional and contains $n+1$ elements (for the $n+1$
          constants that have been found $(c_0, c_1, c_2, \cdots, c_n)$.
       2. A two dimensional variance-covariance matrix with
          $(n+1)\times(n+1)$ elements.

 -- Function:
          gal_data_t *
          gal_fit_1d_polynomial_robust (gal_data_t *xin, gal_data_t
          *yin, size_t maxpower, uint8_t robustid, double *redchisq)
     Preform a 1D robust polynomial fit, formally:
     $Y=c+0+c_1X+c_2X^2+\cdots+c_nX^n$ (using GSL’s robust linear
     regression(4)).  See the description there for the details.

     The inputs and outputs of this function are almost identical to
     ‘gal_fit_1d_polynomial’, with the difference that you need to
     specify the function to reject outliers through the ‘robustid’
     input argument.  You can pass any of the ‘GAL_FIT_ROBUST_*’ codes
     defined at the top of this section to this (the names are identical
     to the names in GSL).

 -- Function:
          gal_data_t *
          gal_fit_1d_polynomial_estimate (gal_data_t *fit, gal_data_t
          *xin)
     Given a 1D polynomial fit output (‘fit’), estimate the fit on an
     arbitrary number of independent variable (horizontal axis, or X, in
     an X-Y plot) within ‘xin’.  ‘fit’ is assumed to be the output of
     ‘gal_fit_1d_polynomial’.  In case you haven’t used this function to
     obtain the constants and covariance matrix, see the description of
     that function for the expected format of ‘fit’.

     This function returns two columns (as a *note List of
     gal_data_t::): The top node of the list is the estimated values at
     the input X-axis positions, and the next node is the errors in the
     estimation.  Naturally, both have the same number of elements as
     ‘xin’.  Being a list, helps in easily printing the output columns
     to a table (see *note Table input output::).

   ---------- Footnotes ----------

   (1) 
<https://www.gnu.org/s/gsl/doc/html/lls.html#linear-regression-with-a-constant-term>

   (2) 
<https://www.gnu.org/s/gsl/doc/html/lls.html#linear-regression-without-a-constant-term>

   (3) 
<https://www.gnu.org/s/gsl/doc/html/lls.html#multi-parameter-regression>

   (4) 
<https://www.gnu.org/software/gsl/doc/html/lls.html#robust-linear-regression>


File: gnuastro.info,  Node: Binary datasets,  Next: Labeled datasets,  Prev: Fitting functions,  Up: Gnuastro library

12.3.24 Binary datasets (‘binary.h’)
------------------------------------

Binary datasets only have two (usable) values: 0 (also known as
background) or 1 (also known as foreground).  They are created after
some binary classification is applied to the dataset.  The most common
is thresholding: for example, in an image, pixels with a value above the
threshold are given a value of 1 and those with a value less than the
threshold are assigned a value of 0.

   Since there is only two values, in the processing of binary images,
you are usually concerned with the positioning of an element and its
vicinity (neighbors).  When a dataset has more than one dimension,
multiple classes of immediate neighbors (that are touching the element)
can be defined for each data-element.  To separate these different
classes of immediate neighbors, we define _connectivity_.

   The classification is done by the distance from element center to the
neighbor’s center.  The nearest immediate neighbors have a connectivity
of 1, the second nearest class of neighbors have a connectivity of 2 and
so on.  In total, the largest possible connectivity for data with ‘ndim’
dimensions is ‘ndim’.  For example, in a 2D dataset, 4-connected
neighbors (that share an edge and have a distance of 1 pixel) have a
connectivity of 1.  The other 4 neighbors that only share a vertice
(with a distance of $\sqrt{2}$ pixels) have a connectivity of 2.
Conventionally, the class of connectivity-2 neighbors also includes the
connectivity 1 neighbors, so for example, we call them 8-connected
neighbors in 2D datasets.

   Ideally, one bit is sufficient for each element of a binary dataset.
However, CPUs are not designed to work on individual bits, the smallest
unit of memory addresses is a byte (containing 8 bits on modern CPUs).
Therefore, in Gnuastro, the type used for binary dataset is ‘uint8_t’
(see *note Numeric data types::).  Although it does take 8-times more
memory, this choice offers much better performance and the some extra
(useful) features.

   The advantage of using a full byte for each element of a binary
dataset is that you can also have other values (that will be ignored in
the processing).  One such common “other” value in real datasets is a
blank value (to mark regions that should not be processed because there
is no data).  The constant ‘GAL_BLANK_UINT8’ value must be used in these
cases (see *note Library blank values::).  Another is some temporary
value(s) that can be given to a processed pixel to avoid having another
copy of the dataset as in ‘GAL_BINARY_TMP_VALUE’ that is described
below.

 -- Macro: GAL_BINARY_TMP_VALUE
     The functions described below work on a ‘uint8_t’ type dataset with
     values of 1 or 0 (no other pixel will be touched).  However, in
     some cases, it is necessary to put temporary values in each element
     during the processing of the functions.  This temporary value has a
     special meaning for the operation and will be operated on.  So if
     your input datasets have values other than 0 and 1 that you do not
     want these functions to work on, be sure they are not equal to this
     macro’s value.  Note that this value is also different from
     ‘GAL_BLANK_UINT8’, so your input datasets may also contain blank
     elements.

 -- Function:
          gal_data_t *
          gal_binary_erode (gal_data_t *input, size_t num, int
          connectivity, int inplace)
     Do ‘num’ erosions on the ‘connectivity’-connected neighbors of
     ‘input’ (see above for the definition of connectivity).

     If ‘inplace’ is non-zero _and_ the input’s type is
     ‘GAL_TYPE_UINT8’, then the erosion will be done within the input
     dataset and the returned pointer will be ‘input’.  Otherwise,
     ‘input’ is copied (and converted if necessary) to ‘GAL_TYPE_UINT8’
     and erosion will be done on this new dataset which will also be
     returned.  This function will only work on the elements with a
     value of 1 or 0.  It will leave all the rest unchanged.

     Erosion (inverse of dilation) is an operation in mathematical
     morphology where each foreground pixel that is touching a
     background pixel is flipped (changed to background).  The
     ‘connectivity’ value determines the definition of “touching”.
     Erosion will thus decrease the area of the foreground regions by
     one layer of pixels.

 -- Function:
          gal_data_t *
          gal_binary_dilate (gal_data_t *input, size_t num, int
          connectivity, int inplace)
     Do ‘num’ dilations on the ‘connectivity’-connected neighbors of
     ‘input’ (see above for the definition of connectivity).  For more
     on ‘inplace’ and the output, see ‘gal_binary_erode’.

     Dilation (inverse of erosion) is an operation in mathematical
     morphology where each background pixel that is touching a
     foreground pixel is flipped (changed to foreground).  The
     ‘connectivity’ value determines the definition of “touching”.
     Dilation will thus increase the area of the foreground regions by
     one layer of pixels.

 -- Function:
          gal_data_t *
          gal_binary_open (gal_data_t *input, size_t num, int
          connectivity, int inplace)
     Do ‘num’ openings on the ‘connectivity’-connected neighbors of
     ‘input’ (see above for the definition of connectivity).  For more
     on ‘inplace’ and the output, see ‘gal_binary_erode’.

     Opening is an operation in mathematical morphology which is defined
     as erosion followed by dilation (see above for the definitions of
     erosion and dilation).  Opening will thus remove the outer
     structure of the foreground.  In this implementation, ‘num’
     erosions are going to be applied on the dataset, then ‘num’
     dilations.

 -- Function:
          gal_data_t *
          gal_binary_number_neighbors (gal_data_t *input, int
          connectivity, int inplace)
     Return an image of the same size as the input, but where each
     non-zero and non-blank input pixel is replaced with the number of
     its non-zero and non-blank neighbors.  The input dataset is assumed
     to be binary (having an unsigned, 8-bit dataset).  The neighbors
     are defined through the ‘connectivity’ argument (see above) and if
     ‘inplace!=0’, then the output will be written into the input.

 -- Function:
          size_t
          gal_binary_connected_components (gal_data_t *binary,
          gal_data_t **out, int connectivity)
     Return the number of connected components in ‘binary’ through the
     breadth first search algorithm (finding all pixels belonging to one
     component before going on to the next).  Connection between two
     pixels is defined based on the value to ‘connectivity’.  ‘out’ is a
     dataset with the same size as ‘binary’ with ‘GAL_TYPE_INT32’ type.
     Every pixel in ‘out’ will have the label of the connected component
     it belongs to.  The labeling of connected components starts from 1,
     so a label of zero is given to the input’s background pixels.

     When ‘*out!=NULL’ (its space is already allocated), it will be
     cleared (to zero) at the start of this function.  Otherwise, when
     ‘*out==NULL’, the necessary dataset to keep the output will be
     allocated by this function.

     ‘binary’ must have a type of ‘GAL_TYPE_UINT8’, otherwise this
     function will abort with an error.  Other than blank pixels (with a
     value of ‘GAL_BLANK_UINT8’ defined in *note Library blank
     values::), all other non-zero pixels in ‘binary’ will be considered
     as foreground (and will be labeled).  Blank pixels in the input
     will also be blank in the output.

 -- Function:
          gal_data_t *
          gal_binary_connected_indexs(gal_data_t *binary, int
          connectivity)
     Build a ‘gal_data_t’ linked list, where each node of the list
     contains an array with indices of the connected regions.  Therefore
     the arrays of each node can have a different size.  Note that the
     indices will only be calculated on the pixels with a value of 1 and
     internally, it will temporarily change the values to 2 (and return
     them back to 1 in the end).

 -- Function:
          gal_data_t *
          gal_binary_connected_adjacency_matrix (gal_data_t *adjacency,
          size_t *numconnected)
     Find the number of connected labels and new labels based on an
     adjacency matrix, which must be a square binary array (type
     ‘GAL_TYPE_UINT8’).  The returned dataset is a list of new labels
     for each old label.  In other words, this function will find the
     objects that are connected (possibly through a third object) and in
     the output array, the respective elements for all input labels is
     going to have the same value.  The total number of connected labels
     is put into the space that ‘numconnected’ points to.

     An adjacency matrix defines connection between two labels.  For
     example, let’s assume we have 5 labels and we know that labels 1
     and 5 are connected to label 3, but are not connected with each
     other.  Also, labels 2 and 4 are not touching any other label.  So
     in total we have 3 final labels: one combined object (merged from
     labels 1, 3, and 5) and the initial labels 2 and 4.  The input
     adjacency matrix would look like this (note the extra row and
     column for a label 0 which is ignored):

                      INPUT                             OUTPUT
                      =====                             ======
                    in_lab  1  2  3  4  5   |
                                            |       numconnected = 3
                         0  0  0  0  0  0   |
          in_lab 1 -->   0  0  0  1  0  0   |
          in_lab 2 -->   0  0  0  0  0  0   |  Returned: new labels for the
          in_lab 3 -->   0  1  0  0  0  1   |       5 initial objects
          in_lab 4 -->   0  0  0  0  0  0   |   | 0 | 1 | 2 | 1 | 3 | 1 |
          in_lab 5 -->   0  0  0  1  0  0   |

     Although the adjacency matrix as used here is symmetric, currently
     this function assumes that it is filled on both sides of the
     diagonal.

 -- Function:
          gal_data_t *
          gal_binary_connected_adjacency_list (gal_list_sizet_t
          **listarr, size_t number, size_t minmapsize, int quietmmap,
          size_t *numconnected)
     Find the number of connected labels and new labels based on an
     adjacency list.  The output of this function is identical to that
     of ‘gal_binary_connected_adjacency_matrix’.  But the major
     difference is that it uses a list of connected labels to each label
     instead of a square adjacency matrix.  This is done because when
     the number of labels becomes very large (for example, on the scale
     of 100,000), the adjacency matrix can consume more than 10GB of
     RAM!

     The input list has the following format: it is an array of pointers
     to ‘gal_list_sizet_t *’ (or ‘gal_list_sizet_t **’).  The array has
     ‘number’ elements and each ‘listarr[i]’ is a linked list of
     ‘gal_list_sizet_t *’.  As a demonstration, the input of the same
     example in ‘gal_binary_connected_adjacency_matrix’ would look like
     below and the output of this function will be identical to there.

          listarr[0] = NULL
          listarr[1] = 3
          listarr[2] = NULL
          listarr[3] = 1 -> 5
          listarr[4] = NULL
          listarr[5] = 3

     From this example, it is already clear that this method will
     consume far less memory.  But because it needs to parse lists (and
     not easily jump between array elements), it can be slower.  But in
     scenarios where there are too many objects (that may exceed the
     whole system’s RAM+SWAP), this option is a good alternative and the
     drop in processing speed is worth getting the job done.

     Similar to ‘gal_binary_connected_adjacency_matrix’, this function
     will write the final number of connected labels in ‘numconnected’.
     But since it takes no ‘gal_data_t *’ argument (where it can inherit
     the ‘minmapsize’ and ‘quietmmap’ parameters), it also needs these
     as input.  For more on ‘minmapsize’ and ‘quietmmap’, see *note
     Memory management::.

 -- Function:
          gal_data_t *
          gal_binary_holes_label (gal_data_t *input, int connectivity,
          size_t *numholes)
     Label all the holes in the foreground (non-zero elements in input)
     as independent regions.  Holes are background regions (zero-valued
     in input) that are fully surrounded by the foreground, as defined
     by ‘connectivity’.  The returned dataset has a 32-bit signed
     integer type with the size of the input.  All holes in the input
     will have labels/counters greater or equal to ‘1’.  The rest of the
     background regions will still have a value of ‘0’ and the initial
     foreground pixels will have a value of ‘-1’.  The total number of
     holes will be written where ‘numholes’ points to.

 -- Function:
          void
          gal_binary_holes_fill (gal_data_t *input, int connectivity,
          size_t maxsize)
     Fill all the holes (0 valued pixels surrounded by 1 valued pixels)
     of the binary ‘input’ dataset.  The connectivity of the holes can
     be set with ‘connectivity’.  Holes larger than ‘maxsize’ are not
     filled.  This function currently only works on a 2D dataset.


File: gnuastro.info,  Node: Labeled datasets,  Next: Convolution functions,  Prev: Binary datasets,  Up: Gnuastro library

12.3.25 Labeled datasets (‘label.h’)
------------------------------------

A labeled dataset is one where each element/pixel has an integer label
(or counter).  The label identifies the group/class that the element
belongs to.  This form of labeling allows the higher-level study of all
pixels within a certain class.

   For example, to detect objects/targets in an image/dataset, you can
apply a threshold to separate the noise from the signal (to detect
diffuse signal, a threshold is useless and more advanced methods are
necessary, for example *note NoiseChisel::).  But the output of
detection is a binary dataset (which is just a very low-level labeling
of ‘0’ for noise and ‘1’ for signal).

   The raw detection map is therefore hardly useful for any kind of
analysis on objects/targets in the image.  One solution is to use a
connected-components algorithm (see ‘gal_binary_connected_components’ in
*note Binary datasets::).  It is a simple and useful way to
separate/label connected patches in the foreground.  This higher-level
(but still elementary) labeling therefore allows you to count how many
connected patches of signal there are in the dataset and is a major
improvement compared to the raw detection.

   However, when your objects/targets are touching, the simple connected
components algorithm is not enough and a still higher-level labeling
mechanism is necessary.  This brings us to the necessity of the
functions in this part of Gnuastro’s library.  The main inputs to the
functions in this section are already labeled datasets (for example,
with the connected components algorithm above).

   Each of the labeled regions are independent of each other (the labels
specify different classes of targets).  Therefore, especially in large
datasets, it is often useful to process each label on independent CPU
threads in parallel rather than in series.  Therefore the functions of
this section actually use an array of pixel/element indices (belonging
to each label/class) as the main identifier of a region.  Using indices
will also allow processing of overlapping labels (for example, in
deblending problems).  Just note that overlapping labels are not yet
implemented, but planned.  You can use ‘gal_label_indexs’ to generate
lists of indices belonging to separate classes from the labeled input.

 -- Macro: GAL_LABEL_INIT
 -- Macro: GAL_LABEL_RIVER
 -- Macro: GAL_LABEL_TMPCHECK
     Special negative integer values used internally by some of the
     functions in this section.  Recall that meaningful labels are
     considered to be positive integers ($\geq1$).  Zero is
     conventionally kept for regions with no labels, therefore negative
     integers can be used for any extra classification in the labeled
     datasets.

 -- Function:
          gal_data_t *
          gal_label_indexs (gal_data_t *labels, size_t numlabs, size_t
          minmapsize, int quietmmap)

     Return an array of ‘gal_data_t’ containers, each containing the
     pixel indices of the respective label (see *note Generic data
     container::).  ‘labels’ contains the label of each element and has
     to have an ‘GAL_TYPE_INT32’ type (see *note Library data types::).
     Only positive (greater than zero) values in ‘labels’ will be
     used/indexed, other elements will be ignored.

     Meaningful labels start from ‘1’ and not ‘0’, therefore the output
     array of ‘gal_data_t’ will contain ‘numlabs+1’ elements.  The first
     (zero-th) element of the output (‘indexs[0]’ in the example below)
     will be initialized to a dataset with zero elements.  This will
     allow easy (non-confusing) access to the indices of each
     (meaningful) label.

     ‘numlabs’ is the number of labels in the dataset.  If it is given a
     value of zero, then the maximum value in the input (largest label)
     will be found and used.  Therefore if it is given, but smaller than
     the actual number of labels, this function may/will crash (it will
     write in un-allocated space).  ‘numlabs’ is therefore useful in a
     highly optimized/checked environment.

     For example, if the returned array is called ‘indexs’, then
     ‘indexs[10].size’ contains the number of elements that have a label
     of ‘10’ in ‘labels’ and ‘indexs[10].array’ is an array (after
     casting to ‘size_t *’) containing the indices of each one of those
     elements/pixels.

     By _index_ we mean the 1D position: the input number of dimensions
     is irrelevant (any dimensionality is supported).  In other words,
     each element’s index is the number of elements/pixels between it
     and the dataset’s first element/pixel.  Therefore it is always
     greater or equal to zero and stored in ‘size_t’ type.

 -- Function:
          size_t
          gal_label_watershed (gal_data_t *values, gal_data_t *indexs,
          gal_data_t *label, size_t *topinds, int min0_max1)
     Use the watershed algorithm(1) to “over-segment” the pixels in the
     ‘indexs’ dataset based on values in the ‘values’ dataset.
     Internally, each local extrema (maximum or minimum, based on
     ‘min0_max1’) and its surrounding pixels will be given a unique
     label.  For demonstration, see Figures 8 and 9 of Akhlaghi and
     Ichikawa [2015] (http://arxiv.org/abs/1505.01664).  If
     ‘topinds!=NULL’, it is assumed to point to an already allocated
     space to write the index of each clump’s local extrema, otherwise,
     it is ignored.

     The ‘values’ dataset must have a 32-bit floating point type
     (‘GAL_TYPE_FLOAT32’, see *note Library data types::) and will only
     be read by this function.  ‘indexs’ must contain the indices of the
     elements/pixels that will be over-segmented by this function and
     have a ‘GAL_TYPE_SIZE_T’ type, see the description of
     ‘gal_label_indexs’, above.  The final labels will be written in the
     respective positions of ‘labels’, which must have a
     ‘GAL_TYPE_INT32’ type and be the same size as ‘values’.

     When ‘indexs’ is already sorted, this function will ignore
     ‘min0_max1’.  To judge if the dataset is sorted or not (by the
     values the indices correspond to in ‘values’, not the actual
     indices), this function will look into the bits of ‘indexs->flag’,
     for the respective bit flags, see *note Generic data container::.
     If ‘indexs’ is not already sorted, this function will sort it
     according to the values of the respective pixel in ‘values’.  The
     increasing/decreasing order will be determined by ‘min0_max1’.
     Note that if this function is called on multiple threads _and_
     ‘values’ points to a different array on each thread, this function
     will not return a reasonable result.  In this case, please sort
     ‘indexs’ prior to calling this function (see
     ‘gal_qsort_index_multi_d’ in *note Qsort functions::).

     When ‘indexs’ is decreasing (increasing), or ‘min0_max1’ is ‘1’
     (‘0’), local minima (maxima), are considered rivers (watersheds)
     and given a label of ‘GAL_LABEL_RIVER’ (see above).

     Note that rivers/watersheds will also be formed on the edges of the
     labeled regions or when the labeled pixels touch a blank pixel.
     Therefore this function will need to check for the presence of
     blank values.  To be most efficient, it is thus recommended to use
     ‘gal_blank_present’ (with ‘updateflag=1’) prior to calling this
     function (see *note Library blank values::.  Once the flag has been
     set, no other function (including this one) that needs special
     behavior for blank pixels will have to parse the dataset to see if
     it has blank values any more.

     If you are sure your dataset does not have blank values (by the
     design of your software), to avoid an extra parsing of the dataset
     and improve performance, you can set the two bits manually (see the
     description of ‘flags’ in *note Generic data container::):
          input->flag |=  GAL_DATA_FLAG_BLANK_CH; /* Set bit to 1. */
          input->flag &= ~GAL_DATA_FLAG_HASBLANK; /* Set bit to 0. */

 -- Function:
          void
          gal_label_clump_significance (gal_data_t *values, gal_data_t
          *std, gal_data_t *label, gal_data_t *indexs, struct
          gal_tile_two_layer_params *tl, size_t numclumps, size_t
          minarea, int variance, int keepsmall, gal_data_t *sig,
          gal_data_t *sigind)
     This function is usually called after ‘gal_label_watershed’, and is
     used as a measure to identify which over-segmented “clumps” are
     real and which are noise.

     A measurement is done on each clump (using the ‘values’ and ‘std’
     datasets, see below).  To help in multi-threaded environments, the
     operation is only done on pixels which are indexed in ‘indexs’.  It
     is expected for ‘indexs’ to be sorted by their values in ‘values’.
     If not sorted, the measurement may not be reliable.  If sorted in a
     decreasing order, then clump building will start from their highest
     value and vice-versa.  See the description of ‘gal_label_watershed’
     for more on ‘indexs’.

     Each “clump” (identified by a positive integer) is assumed to be
     surrounded by at least one river/watershed pixel (with a
     non-positive label).  This function will parse the pixels
     identified in ‘indexs’ and make a measurement on each clump and
     over all the river/watershed pixels.  The number of clumps
     (‘numclumps’) must be given as an input argument and any clump that
     is smaller than ‘minarea’ is ignored (because of scatter).  If
     ‘variance’ is non-zero, then the ‘std’ dataset is interpreted as
     variance, not standard deviation.

     The ‘values’ and ‘std’ datasets must have a ‘float’ (32-bit
     floating point) type.  Also, ‘label’ and ‘indexs’ must respectively
     have ‘int32’ and ‘size_t’ types.  ‘values’ and ‘label’ must have
     the same size, but ‘std’ can have three possible sizes: 1) a single
     element (which will be used for the whole dataset, 2) the same size
     as ‘values’ (so a different error can be assigned to every pixel),
     3) a single value for each tile, based on the ‘tl’ tessellation
     (see *note Tile grid::).  In the last case, a tile/value will be
     associated to each clump based on its flux-weighted (only positive
     values) center.

     The main output is an internally allocated, 1-dimensional array
     with one value per label.  The array information (length, type,
     etc.)  will be written into the ‘sig’ generic data container.
     Therefore ‘sig->array’ must be ‘NULL’ when this function is called.
     After this function, the details of the array (number of elements,
     type and size, etc) will be written in to the various components of
     ‘sig’, see the definition of ‘gal_data_t’ in *note Generic data
     container::.  Therefore ‘sig’ must already be allocated before
     calling this function.

     Optionally (when ‘sigind!=NULL’, similar to ‘sig’) the clump labels
     of each measurement in ‘sig’ will be written in ‘sigind->array’.
     If ‘keepsmall’ zero, small clumps (where no measurement is made)
     will not be included in the output table.

     This function is initially intended for a multi-threaded
     environment.  In such cases, you will be writing arrays of clump
     measures from different regions in parallel into an array of
     ‘gal_data_t’s.  You can simply allocate (and initialize), such an
     array with the ‘gal_data_array_calloc’ function in *note Arrays of
     datasets::.  For example, if the ‘gal_data_t’ array is called
     ‘array’, you can pass ‘&array[i]’ as ‘sig’.

     Along with some other functions in ‘label.h’, this function was
     initially written for *note Segment::.  The description of the
     parameter used to measure a clump’s significance is fully given in
     Akhlaghi [2019] (https://arxiv.org/abs/1909.11230).

 -- Function:
          void
          gal_label_grow_indexs (gal_data_t *labels, gal_data_t *indexs,
          int withrivers, int connectivity)
     Grow the (positive) labels of ‘labels’ over the pixels in ‘indexs’
     (see description of ‘gal_label_indexs’).  The pixels (position in
     ‘indexs’, values in ‘labels’) that must be “grown” must have a
     value of ‘GAL_LABEL_INIT’ in ‘labels’ before calling this function.
     For a demonstration see Columns 2 and 3 of Figure 10 in Akhlaghi
     and Ichikawa [2015] (http://arxiv.org/abs/1505.01664).

     In many aspects, this function is very similar to over-segmentation
     (watershed algorithm, ‘gal_label_watershed’).  The big difference
     is that in over-segmentation local maximums (that are not touching
     any already labeled pixel) get a separate label.  However, here the
     final number of labels will not change.  All pixels that are not
     directly touching a labeled pixel just get pushed back to the start
     of the loop, and the loop iterates until its size does not change
     any more.  This is because in a generic scenario some of the
     indexed pixels might not be reachable through other indexed pixels.

     The next major difference with over-segmentation is that when there
     is only one label in growth region(s), it is not mandatory for
     ‘indexs’ to be sorted by values.  If there are multiple labeled
     regions in growth region(s), then values are important and you can
     use ‘qsort’ with ‘gal_qsort_index_single_d’ to sort the indices by
     values in a separate array (see *note Qsort functions::).

     This function looks for positive-valued neighbors of each pixel in
     ‘indexs’ and will label a pixel if it touches one.  Therefore, it
     is very important that only pixels/labels that are intended for
     growth have positive values in ‘labels’ before calling this
     function.  Any non-positive (zero or negative) value will be
     ignored as a label by this function.  Thus, it is recommended that
     while filling in the ‘indexs’ array values, you initialize all the
     pixels that are in ‘indexs’ with ‘GAL_LABEL_INIT’, and set
     non-labeled pixels that you do not want to grow to ‘0’.

     This function will write into both the input datasets.  After this
     function, some of the non-positive ‘labels’ pixels will have a new
     positivelabel and the number of useful elements in ‘indexs’ will
     have decreased.  The index of those pixels that could not be
     labeled will remain inside ‘indexs’.  If ‘withrivers’ is non-zero,
     then pixels that are immediately touching more than one positive
     value will be given a ‘GAL_LABEL_RIVER’ label.

     Note that the ‘indexs->array’ is not re-allocated to its new size
     at the end(2).  But since ‘indexs->dsize[0]’ and ‘indexs->size’
     have new values after this function is returned, the extra elements
     just will not be used until they are ultimately freed by
     ‘gal_data_free’.

     Connectivity is a value between ‘1’ (fewest number of neighbors)
     and the number of dimensions in the input (most number of
     neighbors).  For example, in a 2D dataset, a connectivity of ‘1’
     and ‘2’ corresponds to 4-connected and 8-connected neighbors.

   ---------- Footnotes ----------

   (1) The watershed algorithm was initially introduced by Vincent and
Soille (https://doi.org/10.1109/34.87344).  It starts from the minima
and puts the pixels in, one by one, to grow them until the touch (create
a watershed).  For more, also see the Wikipedia article:
<https://en.wikipedia.org/wiki/Watershed_%28image_processing%29>.

   (2) Note that according to the GNU C Library, even a ‘realloc’ to a
smaller size can also cause a re-write of the whole array, which is not
a cheap operation.


File: gnuastro.info,  Node: Convolution functions,  Next: Pooling functions,  Prev: Labeled datasets,  Up: Gnuastro library

12.3.26 Convolution functions (‘convolve.h’)
--------------------------------------------

Convolution is a very common operation during data analysis and is
thoroughly described as part of Gnuastro’s *note Convolve:: program
which is fully devoted to this job.  Because of the complete
introduction that was presented there, we will directly skip onto the
currently available convolution functions in Gnuastro’s library.

   As of this version, only spatial domain convolution is available in
Gnuastro’s libraries.  We have not had the time to liberate the
frequency domain function convolution and de-convolution functions that
are available in the Convolve program(1).

 -- Function:
          gal_data_t *
          gal_convolve_spatial (gal_data_t *tiles, gal_data_t *kernel,
          size_t numthreads, int edgecorrection, int convoverch, int
          conv_on_blank)
     Convolve the given ‘tiles’ dataset (possibly a list of tiles, see
     *note List of gal_data_t:: and *note Tessellation library::) with
     ‘kernel’ on ‘numthreads’ threads.  When ‘edgecorrection’ is
     non-zero, it will correct for the edge dimming effects as discussed
     in *note Edges in the spatial domain::.  When ‘conv_on_blank’ is
     non-zero, this function will also attempt convolution over the
     blank pixels (and therefore give values to the blank pixels that
     are near non-blank pixels).

     ‘tiles’ can be a single/complete dataset, but in that case the
     speed will be very slow.  Therefore, for larger images, it is
     recommended to give a list of tiles covering a dataset.  To create
     a tessellation that fully covers an input image, you may use
     ‘gal_tile_full’, or ‘gal_tile_full_two_layers’ to also define
     channels over your input dataset.  These functions are discussed in
     *note Tile grid::.  You may then pass the list of tiles to this
     function.  This is the recommended way to call this function
     because spatial domain convolution is slow and breaking the job
     into many small tiles and working on simultaneously on several
     threads can greatly speed up the processing.

     If the tiles are defined within a channel (a larger tile), by
     default convolution will be done within the channel, so pixels on
     the edge of a channel will not be affected by their neighbors that
     are in another channel.  See *note Tessellation:: for the necessity
     of channels in astronomical data analysis.  This behavior may be
     disabled when ‘convoverch’ is non-zero.  In this case, it will
     ignore channel borders (if they exist) and mix all pixels that
     cover the kernel within the dataset.

 -- Function:
          void
          gal_convolve_spatial_correct_ch_edge (gal_data_t *tiles,
          gal_data_t *kernel, size_t numthreads, int edgecorrection, int
          conv_on_blank, gal_data_t *tocorrect)
     Correct the edges of channels in an already convolved image when it
     was initially convolved with ‘gal_convolve_spatial’ and
     ‘convoverch==0’.  In that case, strong boundaries might exist on
     the channel edges.  So if you later need to remove those boundaries
     at later steps of your processing, you can call this function.  It
     will only do convolution on the tiles that are near the edge and
     were effected by the channel borders.  Other pixels in the image
     will not be touched.  Hence, it is much faster.  When
     ‘conv_on_blank’ is non-zero, this function will also attempt
     convolution over the blank pixels (and therefore give values to the
     blank pixels that are near non-blank pixels).

   ---------- Footnotes ----------

   (1) Hence any help would be greatly appreciated.


File: gnuastro.info,  Node: Pooling functions,  Next: Interpolation,  Prev: Convolution functions,  Up: Gnuastro library

12.3.27 Pooling functions (‘pool.h’)
------------------------------------

Pooling is the process of reducing the complexity of the input image
(its size and variation of pixel values).  Its underlying concepts, and
an analysis of its usefulness, is fully described in *note Pooling
operators::.  The following functions are available pooling in Gnuastro.
Just note that unlike the Arithmetic operators, the output of these
functions should contain a correct WCS in their output.

 -- Function:
          gal_data_t *
          gal_pool_max (gal_data_t *input, size_t psize, size_t
          numthreads)
     Return the max-pool of ‘input’, assuming a pool size of ‘psize’
     pixels.  The number of threads to use can be set with ‘numthreads’.

 -- Function:
          gal_data_t *
          gal_pool_min (gal_data_t *input, size_t psize, size_t
          numthreads)
     Return the min-pool of ‘input’, assuming a pool size of ‘psize’
     pixels.  The number of threads to use can be set with ‘numthreads’.

 -- Function:
          gal_data_t *
          gal_pool_sum (gal_data_t *input, size_t psize, size_t
          numthreads)
     Return the sum-pool of ‘input’, assuming a pool size of ‘psize’
     pixels.  The number of threads to use can be set with ‘numthreads’.

 -- Function:
          gal_data_t *
          gal_pool_mean (gal_data_t *input, size_t psize, size_t
          numthreads)
     Return the mean-pool of ‘input’, assuming a pool size of ‘psize’
     pixels.  The number of threads to use can be set with ‘numthreads’.

 -- Function:
          gal_data_t *
          gal_pool_median (gal_data_t *input, size_t psize, size_t
          numthreads)
     Return the median-pool of ‘input’, assuming a pool size of ‘psize’
     pixels.  The number of threads to use can be set with ‘numthreads’.


File: gnuastro.info,  Node: Interpolation,  Next: Warp library,  Prev: Pooling functions,  Up: Gnuastro library

12.3.28 Interpolation (‘interpolate.h’)
---------------------------------------

During data analysis, it happens that parts of the data cannot be given
a value, but one is necessary for the higher-level analysis.  For
example, a very bright star saturated part of your image and you need to
fill in the saturated pixels with some values.  Another common usage
case are masked sky-lines in 1D spectra that similarly need to be
assigned a value for higher-level analysis.  In other situations, you
might want a value in an arbitrary point: between the elements/pixels
where you have data.  The functions described in this section are for
such operations.

   The parametric interpolations discussed below are wrappers around the
interpolation functions of the GNU Scientific Library (or GSL, see *note
GNU Scientific Library::).  To identify the different GSL interpolation
types, Gnuastro’s ‘gnuastro/interpolate.h’ header file contains macros
that are discussed below.  The GSL wrappers provided here are not yet
complete because we are too busy.  If you need them, please consider
helping us in adding them to Gnuastro’s library.  Your contributions
would be very welcome and appreciated.

 -- Macro: GAL_INTERPOLATE_NEIGHBORS_METRIC_RADIAL
 -- Macro: GAL_INTERPOLATE_NEIGHBORS_METRIC_MANHATTAN
 -- Macro: GAL_INTERPOLATE_NEIGHBORS_METRIC_INVALID
     The metric used to find distance for nearest neighbor
     interpolation.  A radial metric uses the simple Euclidean function
     to find the distance between two pixels.  A manhattan metric will
     always be an integer and is like steps (but is also much faster to
     calculate than radial metric because it does not need a square root
     calculation).

 -- Macro: GAL_INTERPOLATE_NEIGHBORS_FUNC_MIN
 -- Macro: GAL_INTERPOLATE_NEIGHBORS_FUNC_MAX
 -- Macro: GAL_INTERPOLATE_NEIGHBORS_FUNC_MEAN
 -- Macro: GAL_INTERPOLATE_NEIGHBORS_FUNC_MEDIAN
 -- Macro: GAL_INTERPOLATE_NEIGHBORS_FUNC_INVALID
     The various types of nearest-neighbor interpolation functions for
     ‘gal_interpolate_neighbors’.  The names are descriptive for the
     operation they do, so we will not go into much more detail here.
     The median operator will be one of the most used, but operators
     like the maximum are good to fill the center of saturated stars.

 -- Function:
          gal_data_t *
          gal_interpolate_neighbors (gal_data_t *input, struct
          gal_tile_two_layer_params *tl, uint8_t metric, size_t
          numneighbors, size_t numthreads, int onlyblank, int
          aslinkedlist, int function)

     Interpolate the values in the input dataset using a calculated
     statistics from the distribution of their ‘numneighbors’ closest
     neighbors.  The desired statistics is determined from the ‘func’
     argument, which takes any of the ‘GAL_INTERPOLATE_NEIGHBORS_FUNC_’
     macros (see above).  This function is non-parametric and thus
     agnostic to the input’s number of dimension or shape of the
     distribution.

     Distance can be defined on different metrics that are identified
     through ‘metric’ (taking values determined by the
     ‘GAL_INTERPOLATE_NEIGHBORS_METRIC_’ macros described above).  If
     ‘onlyblank’ is non-zero, then only blank elements will be
     interpolated and pixels that already have a value will be left
     untouched.  This function is multi-threaded and will run on
     ‘numthreads’ threads (see ‘gal_threads_number’ in *note
     Multithreaded programming::).

     ‘tl’ is Gnuastro’s tessellation structure used to define tiles over
     an image and is fully described in *note Tile grid::.  When
     ‘tl!=NULL’, then it is assumed that the ‘input->array’ contains one
     value per tile and interpolation will respect certain tessellation
     properties, for example, to not interpolate over channel borders.

     If several datasets have the same set of blank values, you do not
     need to call this function multiple times.  When ‘aslinkedlist’ is
     non-zero, then ‘input’ will be seen as a *note List of
     gal_data_t::.  In this case, the same neighbors will be used for
     all the datasets in the list.  Of course, the values for each
     dataset will be different, so a different value will be written in
     each dataset, but the neighbor checking that is the most CPU
     intensive part will only be done once.

     This is a non-parametric and robust function for interpolation.
     The interpolated values are also always within the range of the
     non-blank values and strong outliers do not get created.  However,
     this type of interpolation must be used with care when there are
     gradients.  This is because it is non-parametric and if there are
     not enough neighbors, step-like features can be created.

 -- Macro: GAL_INTERPOLATE_1D_INVALID
     This is just a place-holder to manage errors.
 -- Macro: GAL_INTERPOLATE_1D_LINEAR
     [From GSL:] Linear interpolation.  This interpolation method does
     not require any additional memory.
 -- Macro: GAL_INTERPOLATE_1D_POLYNOMIAL
     [From GSL:] Polynomial interpolation.  This method should only be
     used for interpolating small numbers of points because polynomial
     interpolation introduces large oscillations, even for well-behaved
     datasets.  The number of terms in the interpolating polynomial is
     equal to the number of points.
 -- Macro: GAL_INTERPOLATE_1D_CSPLINE
     [From GSL:] Cubic spline with natural boundary conditions.  The
     resulting curve is piece-wise cubic on each interval, with matching
     first and second derivatives at the supplied data-points.  The
     second derivative is chosen to be zero at the first point and last
     point.
 -- Macro: GAL_INTERPOLATE_1D_CSPLINE_PERIODIC
     [From GSL:] Cubic spline with periodic boundary conditions.  The
     resulting curve is piece-wise cubic on each interval, with matching
     first and second derivatives at the supplied data-points.  The
     derivatives at the first and last points are also matched.  Note
     that the last point in the data must have the same y-value as the
     first point, otherwise the resulting periodic interpolation will
     have a discontinuity at the boundary.
 -- Macro: GAL_INTERPOLATE_1D_AKIMA
     [From GSL:] Non-rounded Akima spline with natural boundary
     conditions.  This method uses the non-rounded corner algorithm of
     Wodicka.
 -- Macro: GAL_INTERPOLATE_1D_AKIMA_PERIODIC
     [From GSL:] Non-rounded Akima spline with periodic boundary
     conditions.  This method uses the non-rounded corner algorithm of
     Wodicka.
 -- Macro: GAL_INTERPOLATE_1D_STEFFEN
     [From GSL:] Steffen’s method(1) guarantees the monotonicity of the
     interpolating function between the given data points.  Therefore,
     minima and maxima can only occur exactly at the data points, and
     there can never be spurious oscillations between data points.  The
     interpolated function is piece-wise cubic in each interval.  The
     resulting curve and its first derivative are guaranteed to be
     continuous, but the second derivative may be discontinuous.

 -- Function:
          gsl_spline *
          gal_interpolate_1d_make_gsl_spline (gal_data_t *X, gal_data_t
          *Y, int type_1d)
     Allocate and initialize a GNU Scientific Library (GSL) 1D
     ‘gsl_spline’ structure using the non-blank elements of ‘Y’.
     ‘type_1d’ identifies the interpolation scheme and must be one of
     the ‘GAL_INTERPOLATE_1D_*’ macros defined above.

     If ‘X==NULL’, the X-axis is assumed to be integers starting from
     zero (the index of each element in ‘Y’).  Otherwise, the values in
     ‘X’ will be used to initialize the interpolation structure.  Note
     that when given, ‘X’ must _not_ contain any blank elements and it
     must be sorted (in increasing order).

     Each interpolation scheme needs a minimum number of elements to
     successfully operate.  If the number of non-blank values in ‘Y’ is
     less than this number, this function will return a ‘NULL’ pointer.

     To be as generic and modular as possible, GSL’s tools are
     low-level.  Therefore before doing the interpolation, many steps
     are necessary (like preparing your dataset, then allocating and
     initializing ‘gsl_spline’).  The metadata available in Gnuastro’s
     *note Generic data container:: make it easy to hide all those
     preparations within this function.

     Once ‘gsl_spline’ has been initialized by this function, the
     interpolation can be evaluated for any X value within the non-blank
     range of the input using ‘gsl_spline_eval’ or ‘gsl_spline_eval_e’.

     For example, in the small program below (‘sample-interp.c’), we
     read the first two columns of the table in ‘table.txt’ and feed
     them to this function to later estimate the values in the second
     column for three selected points.  You can use *note BuildProgram::
     to compile and run this function, see *note Library demo programs::
     for more.

     Contents of the ‘table.txt’ file:
          $ cat table.txt
          0  0
          1  2
          3  6
          4  8
          6  12
          8  16
          9  18

     Contents of the ‘sample-interp.c’ file:
          #include <stdio.h>
          #include <stdlib.h>
          #include <gnuastro/table.h>
          #include <gnuastro/interpolate.h>

          int
          main(void)
          {
            size_t i;
            gal_data_t *X, *Y;
            gsl_spline *spline;
            gsl_interp_accel *acc;
            gal_list_str_t *cols=NULL;

            /* Change the values based on your input table. */
            double points[]={1.8, 2.5, 7};

            /* Read the first two columns from `tab.txt'.
               IMPORTANT: the list is first-in-first-out, so the output
               column order is the inverse of the input order. */
            gal_list_str_add(&cols, "1", 0);
            gal_list_str_add(&cols, "2", 0);
            Y=gal_table_read("table.txt", NULL, NULL, cols,
                             GAL_TABLE_SEARCH_NAME, 0, 1, -1, 1, NULL);
            X=Y->next;

            /* Allocate the GSL interpolation accelerator and make the
               `gsl_spline' structure. */
            acc=gsl_interp_accel_alloc();
            spline=gal_interpolate_1d_make_gsl_spline(X, Y,
                                           GAL_INTERPOLATE_1D_STEFFEN);

            /* Calculate the respective value for all the given points,
               if `spline' could be allocated. */
            if(spline)
              for(i=0; i<(sizeof points)/(sizeof *points); ++i)
                printf("%f: %f\n", points[i],
                       gsl_spline_eval(spline, points[i], acc));

            /* Clean up and return. */
            gal_data_free(X);
            gal_data_free(Y);
            gsl_spline_free(spline);
            gsl_interp_accel_free(acc);
            gal_list_str_free(cols, 0);
            return EXIT_SUCCESS;
          }

Compile and run this program with *note BuildProgram:: to see the
interpolation results for the three points within the program.
     $ astbuildprog sample-interp.c --quiet
     1.800000: 3.600000
     2.500000: 5.000000
     7.000000: 14.000000

 -- Function:
          void
          gal_interpolate_1d_blank (gal_data_t *in, int type_1d)
     Fill the blank elements of ‘in’ using the rest of the elements and
     the given interpolation.  The interpolation scheme can be set
     through ‘type_1d’, which accepts any of the ‘GAL_INTERPOLATE_1D_*’
     macros above.  The interpolation is internally done in 64-bit
     floating point type (‘double’).  However the evaluated/interpolated
     values (originally blank) will be written (in ‘in’) with its
     original numeric datatype, using C’s standard type conversion.

     By definition, interpolation is only defined “between” valid
     points.  Therefore, if any number of elements on the start or end
     of the 1D array are blank, those elements will not be interpolated
     and will remain blank.  To see if any blank (non-interpolated)
     elements remain, you can use ‘gal_blank_present’ on ‘in’ after this
     function is finished.

   ---------- Footnotes ----------

   (1) <http://adsabs.harvard.edu/abs/1990A%26A...239..443S>

