gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master 1e961f5 067/125: Starting to use gal_data_t in


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 1e961f5 067/125: Starting to use gal_data_t in MakeProfiles
Date: Sun, 23 Apr 2017 22:36:39 -0400 (EDT)

branch: master
commit 1e961f55bfe3a3d73e25c584882bbdf2ec2f3b49
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Starting to use gal_data_t in MakeProfiles
    
    Work has started on porting the root data structure (`gal_data_t') into
    MakeProfiles. It currently compiles and just starts to parse the options,
    so it is not yet complete, never the less, the changes have been
    substantial enough to commit before further progress.
    
    These are the list of things done so far:
    
     - Until now, `gal_data_free' would take two arguments to either free the
       contents of the structure and/or the main structure its self. But the
       value to the second option was confusing. So now, it only takes one
       argument and frees the structure and its contents. There is a new
       function (`gal_data_free_contents') dedicated to freeing the contents of
       the structure and not the structure its self.
    
     - `gal_fits_write_img' uses the `name', `unit' and `comment' field of the
       data structure to set the FITS file's `EXTNAME', `BUNIT', and `COMMENT'
       (at the top) keywords. So there is no longer any need for the `extname'
       argument.
    
     - In MakeProfiles, the user interface variables are now fully defined in
       the main program structure. With the removal of the `*set' variables,
       the `uiparams' structure is mostly irrelevant and just a source of
       confusion, so it was removed.
    
     - The checking of variable ranges will now be done as part of the option
       parsing, so in `bootstrap.conf', a new `range' field is added to
       `argp_option' to allow this checking during the parsing and further
       simplify each program's design.
    
     - With the option range checks that are going to be done during option
       parsing, there is no more need for the numerous `gal_checkset_*'
       functions related to numerical range checking. So they have been
       removed.
    
     - The programs dealing with data structures didn't care about
       dimensionality until now, so I hadn't noticed that the FITS
       reading/writing functions were actually reading the dimentionality in
       the FITS/Fortran format (row first), not in the C format (column
       first). So the type of the `dsize' field in `gal_data_t' is now set to
       `size_t' and the FITS reading/writing functions convert it to the `long
       *naxes' type that is in the FITS/Fortran format.
    
     - Some address@hidden' fields at the start of the "Developing" chapter 
should
       actually have been address@hidden'! They have been corrected now.
    
     - The `Makefile.am' of the built programs still kept the old `cite.h',
       this is now corrected to `authors-cite.h'.
---
 bin/arithmetic/Makefile.am            |    2 +-
 bin/arithmetic/arithmetic.c           |    7 +-
 bin/arithmetic/ui.c                   |    2 +-
 bin/mkprof/Makefile.am                |    2 +-
 bin/mkprof/args.h                     |  590 ++++++++-----------
 bin/mkprof/{cite.h => authors-cite.h} |   28 +-
 bin/mkprof/main.c                     |    2 +-
 bin/mkprof/main.h                     |  155 ++---
 bin/mkprof/mkprof.c                   |  129 ++---
 bin/mkprof/mkprof.h                   |    2 +-
 bin/mkprof/oneprofile.c               |   26 +-
 bin/mkprof/ui.c                       | 1017 +++------------------------------
 bin/table/Makefile.am                 |    2 +-
 bin/table/ui.c                        |    4 +-
 bootstrap.conf                        |    7 +-
 doc/gnuastro.texi                     |    6 +-
 lib/arithmetic-binary.c               |   12 +-
 lib/arithmetic-onlyint.c              |   14 +-
 lib/arithmetic.c                      |   26 +-
 lib/checkset.c                        |  458 ---------------
 lib/checkset.h                        |  127 ----
 lib/commonopts.h                      |    2 +
 lib/data.c                            |   53 +-
 lib/fits.c                            |  218 ++++---
 lib/gnuastro/data.h                   |   17 +-
 lib/gnuastro/fits.h                   |   38 +-
 lib/mesh.c                            |   14 +-
 lib/options.c                         |  185 +++++-
 lib/options.h                         |   19 +-
 lib/table.c                           |    2 +-
 lib/txt.c                             |    4 +-
 tmpfs-config-make                     |    2 +-
 32 files changed, 894 insertions(+), 2278 deletions(-)

diff --git a/bin/arithmetic/Makefile.am b/bin/arithmetic/Makefile.am
index 657a834..0b50fa5 100644
--- a/bin/arithmetic/Makefile.am
+++ b/bin/arithmetic/Makefile.am
@@ -28,7 +28,7 @@ AM_CPPFLAGS = -I\$(top_srcdir)/bootstrapped/lib
 ## Utility and its sources
 bin_PROGRAMS = astarithmetic
 
-astarithmetic_SOURCES = main.c main.h cite.h ui.c ui.h args.h  \
+astarithmetic_SOURCES = main.c main.h authors-cite.h ui.c ui.h args.h  \
 arithmetic.c arithmetic.h operands.c operands.h
 
 astarithmetic_LDADD = $(top_builddir)/bootstrapped/lib/libgnu.la       \
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index e5d8987..9341239 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -357,15 +357,14 @@ reversepolish(struct imgarithparams *p)
          printed as an integer.  */
       d2=gal_data_copy_to_new_type(d1, GAL_DATA_TYPE_DOUBLE);
       printf("%g\n", *(double *)d2->array);
-      gal_data_free(d2, 0);
+      gal_data_free(d2);
     }
   else
     {
       /* Put a copy of the WCS structure from the reference image, it
          will be freed while freeing d1. */
       d1->wcs=p->refdata.wcs;
-      gal_fits_write_img(d1, p->cp.output, "Arithmetic", NULL,
-                         PROGRAM_STRING);
+      gal_fits_write_img(d1, p->cp.output, NULL, PROGRAM_STRING);
       if(!p->cp.quiet)
         printf(" - Output written to %s\n", p->cp.output);
     }
@@ -373,7 +372,7 @@ reversepolish(struct imgarithparams *p)
 
   /* Clean up, note that above, we copied the pointer to `refdata->wcs'
      into `d1', so it is freed when freeing d1. */
-  gal_data_free(d1, 0);
+  gal_data_free(d1);
   free(p->refdata.dsize);
 
   /* Clean up. Note that the tokens were taken from the command-line
diff --git a/bin/arithmetic/ui.c b/bin/arithmetic/ui.c
index c2ccd96..0585473 100644
--- a/bin/arithmetic/ui.c
+++ b/bin/arithmetic/ui.c
@@ -82,7 +82,7 @@ ui_read_check_only_options(struct imgarithparams *p)
 
         default:
           error(EXIT_FAILURE, 0, "option key %d not recognized in "
-                "`fill_params_from_options'", options[i].key);
+                "`ui_read_check_only_options'", options[i].key);
         }
 
   /* If any of the mandatory options were not given, then print an error
diff --git a/bin/mkprof/Makefile.am b/bin/mkprof/Makefile.am
index d3c5717..776569c 100644
--- a/bin/mkprof/Makefile.am
+++ b/bin/mkprof/Makefile.am
@@ -29,7 +29,7 @@ AM_CPPFLAGS = -I\$(top_srcdir)/bootstrapped/lib
 bin_PROGRAMS = astmkprof
 
 astmkprof_SOURCES = main.c main.h ui.c ui.h mkprof.c mkprof.h args.h   \
-oneprofile.c oneprofile.h profiles.c profiles.h cite.h
+oneprofile.c oneprofile.h profiles.c profiles.h authors-cite.h
 
 astmkprof_LDADD = $(top_builddir)/bootstrapped/lib/libgnu.la            \
 -lgnuastro
diff --git a/bin/mkprof/args.h b/bin/mkprof/args.h
index 585da3f..0bfc5f1 100644
--- a/bin/mkprof/args.h
+++ b/bin/mkprof/args.h
@@ -23,31 +23,37 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #ifndef ARGS_H
 #define ARGS_H
 
-#include <commonargs.h>
-#include <fixedstringmacros.h>
-
 
 
 
 
-/* Definition parameters for the argp: */
-const char *argp_program_version=SPACK_STRING"\n"GAL_STRINGS_COPYRIGHT
-  "\n\nWritten by Mohammad Akhlaghi";
-const char *argp_program_bug_address=PACKAGE_BUGREPORT;
-static char args_doc[] = "[BackgroundImage] Catalog";
+/* Include necessary headers. */
+#include <commonopts.h>
+#include <authors-cite.h>
+#include <fixedstringmacros.h>
 
 
 
 
 
-const char doc[] =
-  /* Before the list of options: */
-  GAL_STRINGS_TOP_HELP_INFO
-  SPACK_NAME" will create a FITS image containing any number of mock "
-  "astronomical profiles based on an input catalog. All the profiles "
-  "will be built from the center outwards. First by Monte Carlo "
-  "integration, then using the central pixel position. The tolerance "
-  "level specifies when to switch to a latter.\n"
+/* Definition parameters for the argp: */
+const char *
+argp_program_version = PROGRAM_STRING "\n"
+                       GAL_STRINGS_COPYRIGHT
+                       "\n\nWritten/developed by "PROGRAM_AUTHORS;
+
+const char *
+argp_program_bug_address = PACKAGE_BUGREPORT;
+
+static char
+args_doc[] = "[BackgroundImage] Catalog";
+
+const char
+doc[] = GAL_STRINGS_TOP_HELP_INFO PROGRAM_NAME" will create a FITS image "
+  "containing any number of mock astronomical profiles based on an input "
+  "catalog. All the profiles will be built from the center outwards. First "
+  "by Monte Carlo integration, then using the central pixel position. The "
+  "tolerance level specifies when to switch to a latter.\n"
   GAL_STRINGS_MORE_HELP_INFO
   /* After the list of options: */
   "\v"
@@ -57,14 +63,61 @@ const char doc[] =
 
 
 
-/*
+/* Keys for each option.
+
    Available letters (-V which is used by GNU is also removed):
 
    a d f g j k l u v
-   A B E G H I J L M O Q U W Z
-
-   Maximum integer used so far: 517
-*/
+   A E G H I J L M O Q U W Z     */
+enum option_keys_enum
+{
+  /* With short-option version. */
+  ARGS_OPTION_BACKHDU_KEY         = 'B',
+  ARGS_OPTION_NAXIS1_KEY          = 'x',
+  ARGS_OPTION_NAXIS2_KEY          = 'y',
+  ARGS_OPTION_INPUTASCANVAS_KEY   = 'C',
+  ARGS_OPTION_OVERSAMPLE_KEY      = 's',
+  ARGS_OPTION_INDIVIDUAL_KEY      = 'i',
+  ARGS_OPTION_NOMERGED_KEY        = 'm',
+  ARGS_OPTION_TYPE_KEY            = 'T',
+  ARGS_OPTION_NUMRANDOM_KEY       = 'r',
+  ARGS_OPTION_TOLERANCE_KEY       = 't',
+  ARGS_OPTION_TUNITINP_KEY        = 'p',
+  ARGS_OPTION_XSHIFT_KEY          = 'X',
+  ARGS_OPTION_YSHIFT_KEY          = 'Y',
+  ARGS_OPTION_PREPFORCONV_KEY     = 'c',
+  ARGS_OPTION_ZEROPOINT_KEY       = 'z',
+  ARGS_OPTION_CIRCUMWIDTH_KEY     = 'w',
+  ARGS_OPTION_REPLACE_KEY         = 'R',
+  ARGS_OPTION_ENVSEED_KEY         = 'e',
+  ARGS_OPTION_MFORFLATPIX_KEY     = 'F',
+
+  /* Only with long version. */
+  ARGS_OPTION_PSFINIMG_KEY        = 1000,
+  ARGS_OPTION_MAGATPEAK_KEY,
+  ARGS_OPTION_XCOL_KEY,
+  ARGS_OPTION_YCOL_KEY,
+  ARGS_OPTION_RACOL_KEY,
+  ARGS_OPTION_DECCOL_KEY,
+  ARGS_OPTION_FCOL_KEY,
+  ARGS_OPTION_RCOL_KEY,
+  ARGS_OPTION_NCOL_KEY,
+  ARGS_OPTION_PCOL_KEY,
+  ARGS_OPTION_QCOL_KEY,
+  ARGS_OPTION_MCOL_KEY,
+  ARGS_OPTION_TCOL_KEY,
+  ARGS_OPTION_CRPIX1_KEY,
+  ARGS_OPTION_CRPIX2_KEY,
+  ARGS_OPTION_CRVAL1_KEY,
+  ARGS_OPTION_CRVAL2_KEY,
+  ARGS_OPTION_RESOLUTION_KEY,
+};
+
+
+
+
+
+/* Option definition array. */
 static struct argp_option options[] =
   {
     {
@@ -82,6 +135,15 @@ static struct argp_option options[] =
       "Input:",
       1
     },
+    {
+      "backhdu",
+      ARGS_OPTION_BACKHDU_KEY,
+      "INT/STR",
+      0,
+      "HDU of background image.",
+      1,
+      NULL, GAL_DATA_TYPE_STRING
+    },
 
 
 
@@ -92,67 +154,75 @@ static struct argp_option options[] =
     },
     {
       "naxis1",
-      'x',
+      ARGS_OPTION_NAXIS1_KEY,
       "INT",
       0,
       "Number of pixels along first FITS axis.",
-      2
+      2,
+      NULL, GAL_DATA_TYPE_ULONG
     },
     {
       "naxis2",
-      'y',
+      ARGS_OPTION_NAXIS2_KEY,
       "INT",
       0,
       "Number of pixels along second FITS axis.",
-      2
+      2,
+      NULL, GAL_DATA_TYPE_ULONG
     },
     {
       "inputascanvas",
-      'C',
+      ARGS_OPTION_INPUTASCANVAS_KEY,
       0,
       0,
       "Use input image for output size and WCS.",
-      2
+      2,
+      NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
       "oversample",
-      's',
+      ARGS_OPTION_OVERSAMPLE_KEY,
       "INT",
       0,
       "Scale of oversampling.",
-      2
+      2,
+      NULL, GAL_DATA_TYPE_ULONG
     },
     {
       "psfinimg",
-      509,
+      ARGS_OPTION_PSFINIMG_KEY,
       0,
       0,
       "PSF profiles made with all in output image.",
-      2
+      2,
+      NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
       "individual",
-      'i',
+      ARGS_OPTION_INDIVIDUAL_KEY,
       0,
       0,
       "Build all profiles separately.",
-      2
+      2,
+      NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
       "nomerged",
-      'm',
+      ARGS_OPTION_NOMERGED_KEY,
       0,
       0,
       "Do not create a merged image of all profiles.",
-      2
+      2,
+      NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
       "type",
-      'T',
+      ARGS_OPTION_TYPE_KEY,
       "STR",
       0,
       "uchar, short, long, longlong, float, double.",
-      2
+      2,
+      NULL, GAL_DATA_TYPE_STRING
     },
 
 
@@ -166,91 +236,102 @@ static struct argp_option options[] =
     },
     {
       "numrandom",
-      'r',
+      ARGS_OPTION_NUMRANDOM_KEY,
       "INT",
       0,
       "No. of random points in Monte Carlo integration.",
-      3
+      3,
+      NULL, GAL_DATA_TYPE_ULONG
     },
     {
       "tolerance",
-      't',
+      ARGS_OPTION_TOLERANCE_KEY,
       "FLT",
       0,
       "Tolerance to switch to less accurate method.",
-      3
+      3,
+      NULL, GAL_DATA_TYPE_FLOAT
     },
     {
       "tunitinp",
-      'p',
+      ARGS_OPTION_TUNITINP_KEY,
       0,
       0,
       "Truncation is in units of pixels, not radius.",
-      3
+      3,
+      NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
       "xshift",
-      'X',
+      ARGS_OPTION_XSHIFT_KEY,
       "FLT",
       0,
       "Shift profile centers and enlarge image, X axis.",
-      3
+      3,
+      NULL, GAL_DATA_TYPE_FLOAT
     },
     {
       "yshift",
-      'Y',
+      ARGS_OPTION_YSHIFT_KEY,
       "FLT",
       0,
       "Shift profile centers and enlarge image, Y axis.",
-      3
+      3,
+      NULL, GAL_DATA_TYPE_FLOAT
     },
     {
       "prepforconv",
-      'c',
+      ARGS_OPTION_PREPFORCONV_KEY,
       0,
       0,
       "Shift and expand based on first catalog PSF.",
-      3
+      3,
+      NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
       "zeropoint",
-      'z',
+      ARGS_OPTION_ZEROPOINT_KEY,
       "FLT",
       0,
       "Magnitude zero point.",
-      3
+      3,
+      NULL, GAL_DATA_TYPE_FLOAT
     },
     {
       "circumwidth",
-      'w',
+      ARGS_OPTION_CIRCUMWIDTH_KEY,
       "FLT",
       0,
       "Width of circumference (inward) profiles",
-      3
+      3,
+      NULL, GAL_DATA_TYPE_FLOAT
     },
     {
       "replace",
-      'R',
+      ARGS_OPTION_REPLACE_KEY,
       0,
       0,
       "Replace overlapping profile pixels, don't add.",
-      3
+      3,
+      NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
       "magatpeak",
-      515,
+      ARGS_OPTION_MAGATPEAK_KEY,
       0,
       0,
       "Magnitude is for peak pixel, not full profile.",
-      3
+      3,
+      NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
     {
       "envseed",
-      'e',
+      ARGS_OPTION_ENVSEED_KEY,
       0,
       0,
       "Use GSL_RNG_SEED environment variable for seed.",
-      3
+      3,
+      NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
 
 
@@ -264,100 +345,112 @@ static struct argp_option options[] =
     },
     {
       "xcol",
-      500,
-      "INT",
+      ARGS_OPTION_XCOL_KEY,
+      "INT/STR",
       0,
       "Center along first FITS axis (horizontal).",
-      4
+      4,
+      NULL, GAL_DATA_TYPE_STRING
     },
     {
       "ycol",
-      501,
-      "INT",
+      ARGS_OPTION_YCOL_KEY,
+      "INT/STR",
       0,
       "Center along second FITS axis (vertical).",
-      4
+      4,
+      NULL, GAL_DATA_TYPE_STRING
     },
     {
       "racol",
-      516,
-      "INT",
+      ARGS_OPTION_RACOL_KEY,
+      "INT/STR",
       0,
       "Center right ascension.",
-      4
+      4,
+      NULL, GAL_DATA_TYPE_STRING
     },
     {
       "deccol",
-      517,
-      "INT",
+      ARGS_OPTION_DECCOL_KEY,
+      "INT/STR",
       0,
       "Center declination.",
-      4
+      4,
+      NULL, GAL_DATA_TYPE_STRING
     },
     {
       "fcol",
-      502,
-      "INT",
+      ARGS_OPTION_FCOL_KEY,
+      "INT/STR",
       0,
       "Sersic (0), Moffat (1), Gaussian (2), Point (3),\n"
       "Flat (4), Circumference (5).",
-      4
+      4,
+      NULL, GAL_DATA_TYPE_STRING
     },
     {
       "rcol",
-      503,
-      "INT",
+      ARGS_OPTION_RCOL_KEY,
+      "INT/STR",
       0,
       "Effective radius or FWHM in pixels.",
-      4
+      4,
+      NULL, GAL_DATA_TYPE_STRING
     },
     {
       "ncol",
-      504,
-      "INT",
+      ARGS_OPTION_NCOL_KEY,
+      "INT/STR",
       0,
       "Sersic index or Moffat beta.",
-      4
+      4,
+      NULL, GAL_DATA_TYPE_STRING
     },
     {
       "pcol",
-      505,
-      "INT",
+      ARGS_OPTION_PCOL_KEY,
+      "INT/STR",
       0,
       "Position angle.",
-      4
+      4,
+      NULL, GAL_DATA_TYPE_STRING
     },
     {
       "qcol",
-      506,
-      "INT",
+      ARGS_OPTION_QCOL_KEY,
+      "INT/STR",
       0,
       "Axis ratio.",
-      4
+      4,
+      NULL, GAL_DATA_TYPE_STRING
     },
     {
       "mcol",
-      507,
-      "INT",
+      ARGS_OPTION_MCOL_KEY,
+      "INT/STR",
       0,
       "Magnitude.",
-      4
+      4,
+      NULL, GAL_DATA_TYPE_STRING
     },
     {
       "tcol",
-      508,
-      "INT",
+      ARGS_OPTION_TCOL_KEY,
+      "INT/STR",
       0,
       "Truncation in units of --rcol, unless --tunitinp.",
-      4
+      4,
+      NULL, GAL_DATA_TYPE_STRING
     },
     {
       "mforflatpix",
-      'F',
+      ARGS_OPTION_MFORFLATPIX_KEY,
       0,
       0,
       "mcol is flat pixel value (when fcol is 4 or 5)",
-      4
+      4,
+      NULL, GAL_OPTIONS_NO_ARG_TYPE
     },
 
 
@@ -371,43 +464,48 @@ static struct argp_option options[] =
     },
     {
       "crpix1",
-      510,
+      ARGS_OPTION_CRPIX1_KEY,
       "FLT",
       0,
       "Pixel coordinate of reference point (axis 1).",
-      5
+      5,
+      NULL, GAL_DATA_TYPE_DOUBLE
     },
     {
       "crpix2",
-      511,
+      ARGS_OPTION_CRPIX2_KEY,
       "FLT",
       0,
       "Pixel coordinate of reference point (axis 2).",
-      5
+      5,
+      NULL, GAL_DATA_TYPE_DOUBLE
     },
     {
       "crval1",
-      512,
+      ARGS_OPTION_CRVAL1_KEY,
       "FLT",
       0,
       "Right ascension at reference point (degrees).",
-      5
+      5,
+      NULL, GAL_DATA_TYPE_DOUBLE
     },
     {
       "crval2",
-      513,
+      ARGS_OPTION_CRVAL2_KEY,
       "FLT",
       0,
       "Declination at reference point (degrees).",
-      5
+      5,
+      NULL, GAL_DATA_TYPE_DOUBLE
     },
     {
       "resolution",
-      514,
+      ARGS_OPTION_RESOLUTION_KEY,
       "FLT",
       0,
       "Resolution of image (arcseconds/pixel).",
-      5
+      5,
+      NULL, GAL_DATA_TYPE_DOUBLE
     },
 
 
@@ -418,32 +516,14 @@ static struct argp_option options[] =
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 /* Parse a single option: */
-static error_t
+error_t
 parse_opt(int key, char *arg, struct argp_state *state)
 {
-  size_t tmp;
-
-  /* Save the arguments structure: */
   struct mkprofparams *p = state->input;
 
-  /* Set the pointer to the common parameters for all programs
-     here: */
-  state->child_inputs[0]=&p->cp;
+  /* Pass `gal_options_common_params' into the child parser.  */
+  state->child_inputs[0] = &p->cp;
 
   /* In case the user incorrectly uses the equal sign (for example
      with a short format or with space in the long format, then `arg`
@@ -457,241 +537,21 @@ parse_opt(int key, char *arg, struct argp_state *state)
                "there should be no space between the option, equal sign "
                "and value");
 
+  /* Set the key to this option. */
   switch(key)
     {
 
-    /* Operating modes:  */
-    case 509:
-      p->psfinimg=1;
-      break;
-    case 'i':
-      p->individual=1;
-      break;
-
-    /* Output: */
-    case 'x':
-      gal_checkset_sizet_l_zero(arg, &tmp, "naxis1", key, p->cp.spack,
-                                NULL, 0);
-      p->naxes[0]=tmp;
-      p->up.naxis1set=1;
-      break;
-    case 'y':
-      gal_checkset_sizet_l_zero(arg, &tmp, "naxis2", key, p->cp.spack,
-                                NULL, 0);
-      p->naxes[1]=tmp;
-      p->up.naxis2set=1;
-      break;
-    case 'C':
-      p->up.inputascanvas=1;
-      p->up.inputascanvasset=1;
-      break;
-    case 's':
-      gal_checkset_sizet_l_zero(arg, &p->oversample, "oversample", key,
-                                p->cp.spack, NULL, 0);
-      p->up.oversampleset=1;
-      break;
-    case 'm':
-      p->nomerged=1;
-      break;
-    case 'w':
-      gal_checkset_double_l_value(arg, &p->circumwidth, "circumwidth", key,
-                                  p->cp.spack, MINCIRCUMWIDTH, NULL, 0);
-      p->up.circumwidthset=1;
-      break;
-    case 'R':
-      p->replace=1;
-      p->up.replaceset=1;
-      break;
-    case 'T':
-      gal_checkset_known_types(arg, &p->up.type, NULL, 0);
-      p->up.typeset=1;
-      break;
-
-    /* Profiles: */
-    case 'r':
-      gal_checkset_sizet_l_zero(arg, &p->numrandom, "numrandom", key,
-                                p->cp.spack, NULL, 0);
-      p->up.numrandomset=1;
-      break;
-    case 't':
-      gal_checkset_float_l_0(arg, &p->tolerance, "tolerance", key,
-                             p->cp.spack, NULL, 0);
-      p->up.toleranceset=1;
-      break;
-    case 'z':
-      gal_checkset_any_float(arg, &p->zeropoint, "zeropoint", key,
-                             p->cp.spack, NULL, 0);
-      p->up.zeropointset=1;
-      break;
-    case 'p':
-      p->tunitinp=1;
-      p->up.tunitinpset=1;
-      break;
-    case 'c':
-      p->up.prepforconv=1;
-      p->up.prepforconvset=1;
-      break;
-    case 'X':
-      gal_checkset_sizet_el_zero(arg, &tmp, "xshift", key, p->cp.spack,
-                                 NULL, 0);
-      p->shift[0]=tmp;
-      p->up.xshiftset=1;
-      break;
-    case 'Y':
-      gal_checkset_sizet_el_zero(arg, &tmp, "yshift", key, p->cp.spack,
-                                 NULL, 0);
-      p->shift[1]=tmp;
-      p->up.yshiftset=1;
-      break;
-    case 515:
-      p->magatpeak=1;
-      break;
-    case 'e':
-      p->envseed=1;
-      p->up.envseedset=1;
-      break;
-
-   /* Catalog */
-    case 500:
-      gal_checkset_sizet_el_zero(arg, &p->xcol, "xcol", ' ', p->cp.spack,
-                                 NULL, 0);
-      p->up.xcolset=1;
-      break;
-    case 501:
-      gal_checkset_sizet_el_zero(arg, &p->ycol, "ycol", ' ', p->cp.spack,
-                                 NULL, 0);
-      p->up.ycolset=1;
-      break;
-    case 516:
-      gal_checkset_sizet_el_zero(arg, &p->racol, "racol", ' ', p->cp.spack,
-                                 NULL, 0);
-      p->up.racolset=1;
-      break;
-    case 517:
-      gal_checkset_sizet_el_zero(arg, &p->deccol, "deccol", ' ', p->cp.spack,
-                                 NULL, 0);
-      p->up.deccolset=1;
-      break;
-    case 502:
-      gal_checkset_sizet_el_zero(arg, &p->fcol, "fcol", ' ', p->cp.spack,
-                                 NULL, 0);
-      p->up.fcolset=1;
-      break;
-    case 503:
-      gal_checkset_sizet_el_zero(arg, &p->rcol, "rcol", ' ', p->cp.spack,
-                                 NULL, 0);
-      p->up.rcolset=1;
-      break;
-    case 504:
-      gal_checkset_sizet_el_zero(arg, &p->ncol, "ncol", ' ', p->cp.spack,
-                                 NULL, 0);
-      p->up.ncolset=1;
-      break;
-    case 505:
-      gal_checkset_sizet_el_zero(arg, &p->pcol, "pcol", ' ', p->cp.spack,
-                                 NULL, 0);
-      p->up.pcolset=1;
-      break;
-    case 506:
-      gal_checkset_sizet_el_zero(arg, &p->qcol, "qcol", ' ', p->cp.spack,
-                                 NULL, 0);
-      p->up.qcolset=1;
-      break;
-    case 507:
-      gal_checkset_sizet_el_zero(arg, &p->mcol, "mcol", ' ', p->cp.spack,
-                                 NULL, 0);
-      p->up.mcolset=1;
-      break;
-    case 508:
-      gal_checkset_sizet_el_zero(arg, &p->tcol, "tcol", ' ', p->cp.spack,
-                                 NULL, 0);
-      p->up.tcolset=1;
-      break;
-    case 'F':
-      p->mforflatpix=1;
-      p->up.mforflatpixset=1;
-      break;
-
-
-
-    /* WCS parameters: */
-    case 510:
-      gal_checkset_any_double(arg, &p->crpix[0], "crpix1", key, p->cp.spack,
-                              NULL, 0);
-      p->up.crpix1set=1;
-      break;
-    case 511:
-      gal_checkset_any_double(arg, &p->crpix[1], "crpix2", key, p->cp.spack,
-                              NULL, 0);
-      p->up.crpix2set=1;
-      break;
-    case 512:
-      gal_checkset_any_double(arg, &p->crval[0], "crval1", key, p->cp.spack,
-                              NULL, 0);
-      p->up.crval1set=1;
-      break;
-    case 513:
-      gal_checkset_any_double(arg, &p->crval[1], "crval2", key, p->cp.spack,
-                              NULL, 0);
-      p->up.crval2set=1;
-      break;
-    case 514:
-      gal_checkset_float_l_0(arg, &p->resolution, "resolution", key,
-                             p->cp.spack, NULL, 0);
-      p->up.resolutionset=1;
-      break;
-
-
-
-
-
-
-    /* Read the non-option arguments: */
+    /* Read the non-option tokens (arguments): */
     case ARGP_KEY_ARG:
-
-      /* See what type of input value it is and put it in. */
-      if( gal_fits_name_is_fits(arg) )
-        {
-          if(p->up.backname)
-            argp_error(state, "only one input FITS image (the background) "
-                       "should be input. You have given more");
-          else
-            p->up.backname=arg;
-        }
-      else
-        {
-          if(p->up.catname)
-            argp_error(state, "only one catalog file can be given");
-          else
-            p->up.catname=arg;
-        }
+      gal_linkedlist_add_to_stll(&p->allargs, arg, 0);
       break;
 
 
-
-
-
-
-    /* The command line options and arguments are finished. */
-    case ARGP_KEY_END:
-      if(p->cp.setdirconf==0 && p->cp.setusrconf==0
-         && p->cp.printparams==0)
-        {
-          if(state->arg_num==0)
-            argp_error(state, "no argument given");
-          if(p->up.catname==NULL)
-            argp_error(state, "no catalog provided");
-        }
-      break;
-
-
-
-
-
-
+    /* This is an option, set its value. */
     default:
-      return ARGP_ERR_UNKNOWN;
+      return gal_options_set_from_key(key, arg, options, &p->cp);
     }
+
   return 0;
 }
 
@@ -699,19 +559,21 @@ parse_opt(int key, char *arg, struct argp_state *state)
 
 
 
-/* Specify the children parsers: */
-struct argp_child children[]=
-  {
-    {&commonargp, 0, NULL, 0},
-    {0, 0, 0, 0}
-  };
-
-
-
+/* Define the child argp structure. */
+static struct argp
+gal_options_common_child = {gal_commonopts_options,
+                            gal_options_common_argp_parse,
+                            NULL, NULL, NULL, NULL, NULL};
 
+/* Use the child argp structure in list of children (only one for now). */
+static struct argp_child
+children[]=
+{
+  {&gal_options_common_child, 0, NULL, 0},
+  {0, 0, 0, 0}
+};
 
-/* Basic structure defining the whole argument reading process. */
-static struct argp thisargp = {options, parse_opt, args_doc,
-                               doc, children, NULL, NULL};
-
+/* Set all the necessary argp parameters. */
+static struct argp
+thisargp = {options, parse_opt, args_doc, doc, children, NULL, NULL};
 #endif
diff --git a/bin/mkprof/cite.h b/bin/mkprof/authors-cite.h
similarity index 60%
rename from bin/mkprof/cite.h
rename to bin/mkprof/authors-cite.h
index 738c956..5c37dd5 100644
--- a/bin/mkprof/cite.h
+++ b/bin/mkprof/authors-cite.h
@@ -20,19 +20,19 @@ General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
 **********************************************************************/
-#ifndef CITE_H
-#define CITE_H
-
-#define MKPROFBIBTEX ""
-
-#define PRINTCITEABORT {                                                \
-    printf("\nWe hope %s has been useful for your research.\n"          \
-           "Citations are vital for the continued work on %s.\n"        \
-           "Thank you for citing it in your research paper.\n"          \
-           "\nPlease cite as \"%s\":\n\n%s\n\n%s",                      \
-           SPACK_NAME, SPACK_NAME, SPACK_STRING,                        \
-           GAL_STRINGS_MAIN_BIBTEX, MKPROFBIBTEX);                      \
-    exit(EXIT_SUCCESS);                                                 \
-}
+#ifndef AUTHORS_CITE_H
+#define AUTHORS_CITE_H
+
+/* When any specific citation is necessary, please add its BibTeX (from ADS
+   hopefully) to this variable along with a title decribing what this
+   paper/book does for the progarm in a short line. In the following line
+   put a row of `-' with the same length and then put the BibTeX.
+
+   See the `gnuastro_bibtex' variable in `lib/options' (from the top
+   Gnuastro source code directory) as an example.*/
+
+#define PROGRAM_BIBTEX "";
+
+#define PROGRAM_AUTHORS "Mohammad Akhlaghi";
 
 #endif
diff --git a/bin/mkprof/main.c b/bin/mkprof/main.c
index a7aadf1..1bfe637 100644
--- a/bin/mkprof/main.c
+++ b/bin/mkprof/main.c
@@ -36,7 +36,7 @@ int
 main (int argc, char *argv[])
 {
   struct timeval t1;
-  struct mkprofparams p={{0}, {0}, 0};
+  struct mkprofparams p={{0}, 0};
 
   /* Set the starting time.*/
   time(&p.rawtime);
diff --git a/bin/mkprof/main.h b/bin/mkprof/main.h
index 0fe466c..0d382f4 100644
--- a/bin/mkprof/main.h
+++ b/bin/mkprof/main.h
@@ -28,37 +28,50 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <gnuastro/fits.h>
 
-#include <commonparams.h>
+#include <options.h>
 
 
 /* Progarm name macros: */
-#define SPACK           "astmkprof"      /* Subpackage executable name. */
-#define SPACK_NAME      "MakeProfiles"   /* Subpackage full name.       */
-#define SPACK_STRING    SPACK_NAME" ("PACKAGE_NAME") "PACKAGE_VERSION
-#define LOGFILENAME     SPACK".log"
-#define LOGNUMCOLS      5
+#define PROGRAM_NAME "Arithmetic"      /* Program full name.       */
+#define PROGRAM_EXEC "astarithmetic"   /* Program executable name. */
+#define PROGRAM_STRING PROGRAM_NAME" (" PACKAGE_NAME ") " PACKAGE_VERSION
 
-#define DEGREESTORADIANS M_PI/180.0f
 
-#define SERSICCODE         0
-#define MOFFATCODE         1
-#define GAUSSIANCODE       2
-#define POINTCODE          3
-#define FLATCODE           4
-#define CIRCUMFERENCECODE  5
-#define MAXIMUMCODE        5
 
+/* Some constants */
 #define EPSREL_FOR_INTEG   2
-#define MINCIRCUMWIDTH     0.5f
+#define DEGREESTORADIANS   M_PI/180.0f
+
+
+
+/* Types of profiles. */
+enum profile_types
+{
+  PROFILE_SERSIC,               /* Sersic profile.           */
+  PROFILE_MOFFAT,               /* Moffat Profile.           */
+  PROFILE_GAUSSIAN,             /* Gaussian Profile.         */
+  PROFILE_POINT,                /* Point profile.            */
+  PROFILE_FLAT,                 /* Flat profile.             */
+  PROFILE_CIRCUMFERENCE,        /* Circumference profile.    */
+
+  MAXIMUM_PROFILE_CODE,         /* Just for a sanity checck. */
+};
+#define MINCIRCUMWIDTH       0.5f
+
+
 
-/* Log columns:
+/* Log file:
 
    0: ID.
    1: Overlap magnitude.
    2: Number of accurate pixels.
    3: Fraction of accurate values.
-   4: Is individual file created?
- */
+   4: Is individual file created?   */
+#define LOGNUMCOLS      5
+#define LOGFILENAME     PROGRAM_EXEC".log"
+
+
+
 
 
 struct builtqueue
@@ -84,72 +97,16 @@ struct builtqueue
 
 
 
-struct uiparams
-{
-  int               type;  /* User's desired output bitpix.            */
-  char         *backname;  /* Name of background image file name.      */
-  char          *backhdu;  /* HDU of background image.                 */
-  char          *catname;  /* Name of catalog of parameters.           */
-  int        prepforconv;  /* Shift and expand by size of first psf.   */
-  int      inputascanvas;  /* Input image's header for size and WCS.   */
-
-  /* Check if all parameters are read (use .def file for
-     comparison). The non optional parameters (like the catalog and
-     input FITS images that come in from arguments, not options) are
-     checked in the args.h files. */
-
-  int         backhduset;
-  int          naxis1set;
-  int          naxis2set;
-  int      oversampleset;
-  int     circumwidthset;
-  int         envseedset;
-  int         replaceset;
-  int            typeset;
-  int   inputascanvasset;
-
-  int        tunitinpset;
-  int       numrandomset;
-  int       toleranceset;
-  int       zeropointset;
-  int          xshiftset;
-  int          yshiftset;
-  int     prepforconvset;
-
-  int            fcolset;
-  int            xcolset;
-  int            ycolset;
-  int           racolset;
-  int          deccolset;
-  int            rcolset;
-  int            ncolset;
-  int            pcolset;
-  int            qcolset;
-  int            mcolset;
-  int            tcolset;
-  int     mforflatpixset;
-
-  int          crpix1set;
-  int          crpix2set;
-  int          crval1set;
-  int          crval2set;
-  int      resolutionset;
-};
-
-
-
-
-
 struct mkprofparams
 {
-  /* Other structures */
-  struct uiparams     up;  /* User interface parameters.               */
-  struct gal_commonparams cp; /* Common parameters.                    */
+  /* Common parameters structure. */
+  struct gal_options_common_params cp; /* Common parameters.           */
 
   /* Operating modes */
   int           psfinimg;  /* ==1: Build PSF profiles in image.        */
   int         individual;  /* ==1: Build all catalog separately.       */
 
+
   /* Profiles */
   int            replace;  /* Replace overlaping profile pixel values. */
   size_t       numrandom;  /* Number of radom points for integration.  */
@@ -158,30 +115,18 @@ struct mkprofparams
   double     circumwidth;  /* Width of circumference (inward).         */
   int          magatpeak;  /* Mag only for peak pixel, not all profile.*/
   int            envseed;  /* Use GSL_RNG_SEED for random seed.        */
+  int        mforflatpix;  /* mcol is flat pixel value (f is 4 or 5).  */
   int           tunitinp;  /* ==1: Truncation unit is in pixels.       */
                            /* ==0: It is in radial parameter.          */
-  /* Catalog */
-  size_t            fcol;  /* Column specifying profile function.      */
-  size_t            xcol;  /* X column of profile center.              */
-  size_t            ycol;  /* Y column of profile center.              */
-  size_t           racol;  /* RA column of profile center.             */
-  size_t          deccol;  /* Dec column of profile center.            */
-  size_t            rcol;  /* Effective radius of profile.             */
-  size_t            ncol;  /* Sersic index column of profile.          */
-  size_t            pcol;  /* Position angle column of profile.        */
-  size_t            qcol;  /* Axis ratio column of profile.            */
-  size_t            mcol;  /* Magnitude column.                        */
-  size_t            tcol;  /* Truncation of the profiles.              */
-  int        mforflatpix;  /* mcol is flat pixel value (f is 4 or 5). */
 
   /* Random number generator */
   gsl_rng           *rng;  /* Main instance of random number generator.*/
 
+
   /* Output */
   char         *basename;  /* Merged image name with no directory.     */
   char           *outdir;  /* Output directory.                        */
   int           anyblank;  /* ==1: there are blanks in back.           */
-  int             bitpix;  /* bitpix of backgroud/output image.        */
   int           nomerged;  /* ==1: Don't make a merged image of all.   */
   long          naxes[2];  /* Size of the output image.                */
   long          shift[2];  /* Shift along axeses position of profiles. */
@@ -189,14 +134,37 @@ struct mkprofparams
   int               nwcs;  /* Number of WCS.                           */
   struct wcsprm     *wcs;  /* WCSparam structure.                      */
 
+
   /* WCS: */
   double        crpix[2];  /* CRPIX FITS header keywords.              */
   double        crval[2];  /* CRVAL FITS header keywords.              */
   float       resolution;  /* PC1_1 and PC2_2 FITS header keywords.    */
 
-  /* Internal parameters: */
+
+  /* User interface variables. */
+  struct gal_linkedlist_stll *allargs; /* Keep all input arguments.    */
+  int               type;  /* User's desired output bitpix.            */
+  char         *backname;  /* Name of background image file name.      */
+  char          *backhdu;  /* HDU of background image.                 */
+  char          *catname;  /* Name of catalog of parameters.           */
+  int        prepforconv;  /* Shift and expand by size of first psf.   */
+  int      inputascanvas;  /* Input image's header for size and WCS.   */
+  size_t            fcol;  /* Column specifying profile function.      */
+  size_t            xcol;  /* X column of profile center.              */
+  size_t            ycol;  /* Y column of profile center.              */
+  size_t           racol;  /* RA column of profile center.             */
+  size_t          deccol;  /* Dec column of profile center.            */
+  size_t            rcol;  /* Effective radius of profile.             */
+  size_t            ncol;  /* Sersic index column of profile.          */
+  size_t            pcol;  /* Position angle column of profile.        */
+  size_t            qcol;  /* Axis ratio column of profile.            */
+  size_t            mcol;  /* Magnitude column.                        */
+  size_t            tcol;  /* Truncation of the profiles.              */
+
+
+  /* Processing parameters: */
   time_t         rawtime;  /* Starting time of the program.            */
-  float             *out;  /* Output image.                            */
+  gal_data_t        *out;  /* Output image.                            */
   double            *cat;  /* Input catalog.                           */
   size_t             cs0;  /* Number of rows in input catalog.         */
   size_t             cs1;  /* Number of columns in input catalog.      */
@@ -205,6 +173,7 @@ struct mkprofparams
   pthread_cond_t  qready;  /* bq is ready to be written.               */
   pthread_mutex_t  qlock;  /* Mutex lock to change builtq.             */
   double       halfpixel;  /* Half pixel in oversampled image.         */
+  int            outtype;  /* Type of finally merged output image.     */
   char        *wcsheader;  /* The WCS header information for main img. */
   int         wcsnkeyrec;  /* The number of keywords in the WCS header.*/
   char    *mergedimgname;  /* Name of merged image.                    */
diff --git a/bin/mkprof/mkprof.c b/bin/mkprof/mkprof.c
index 4f0713a..67ecc2a 100644
--- a/bin/mkprof/mkprof.c
+++ b/bin/mkprof/mkprof.c
@@ -119,53 +119,48 @@ saveindividual(struct mkonthread *mkp)
 {
   struct mkprofparams *p=mkp->p;
 
-  size_t len;
   double crpix[2];
+  gal_data_t *data;
   long os=p->oversample;
   struct builtqueue *ibq=mkp->ibq;
-  char *outname, *jobname, *outdir=p->outdir;
+  char *filename, *jobname, *outdir=p->outdir;
 
-  /* Allocate the space for the name of this file. */
-  errno=0;
-  len=strlen(outdir)+NUMBERNAMESTRLEN+strlen(p->mergedimgname);
-  outname=malloc(len*sizeof *outname);
-  if(outname==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for name of object in "
-          "row %zu of %s", len*sizeof *outname, ibq->id,
-          p->up.catname);
-
-  /* Save the correct CRPIX values: */
-  crpix[0] = p->crpix[0] - os*(mkp->fpixel_i[0]-1);
-  crpix[1] = p->crpix[1] - os*(mkp->fpixel_i[1]-1);
+  /* Note that `width' is in FITS format, not C. */
+  size_t dsize[2]={mkp->width[1], mkp->width[0]};
 
   /* Write the name and remove a similarly named file. */
-  sprintf(outname, "%s%zu_%s", outdir, ibq->id, p->basename);
-  gal_checkset_check_remove_file(outname, p->cp.dontdelete);
+  asprintf(&filename, "%s%zu_%s", outdir, ibq->id, p->basename);
+  gal_checkset_check_remove_file(filename, p->cp.dontdelete);
 
-  /* Write the array to file (A separately built PSF doesn't need WCS
-     coordinates): */
+  /* Put the array into a data structure */
+  data=gal_data_alloc(ibq->img, GAL_DATA_TYPE_FLOAT, 2, dsize, NULL, 0,
+                      p->cp.minmapsize, "MockImage", "Brightness", NULL);
+
+  /* Write the array to file (a separately built PSF doesn't need WCS
+     coordinates). */
   if(ibq->ispsf && p->psfinimg==0)
-    gal_fits_array_to_file(outname, "MockImg", FLOAT_IMG, ibq->img,
-                           mkp->width[1], mkp->width[0], 0, NULL, NULL,
-                           SPACK_STRING);
+    gal_fits_write_img(data, filename, NULL, PROGRAM_STRING);
   else
-    gal_fits_atof_correct_wcs(outname, "MockImg", FLOAT_IMG, ibq->img,
-                              mkp->width[1], mkp->width[0], p->wcsheader,
-                              p->wcsnkeyrec, crpix, SPACK_STRING);
+    {
+      /* Save the correct CRPIX values: */
+      crpix[0] = p->crpix[0] - os*(mkp->fpixel_i[0]-1);
+      crpix[1] = p->crpix[1] - os*(mkp->fpixel_i[1]-1);
+
+      /* Write the image. */
+      gal_fits_write_img_wcs_string(data, filename, p->wcsheader,
+                                    p->wcsnkeyrec, crpix, NULL,
+                                    PROGRAM_STRING);
+    }
   ibq->indivcreated=1;
 
   /* Report if in verbose mode. */
-  if(p->cp.verb)
+  if(!p->cp.quiet)
     {
-      errno=0;
-      jobname=malloc((len+100)*sizeof *jobname);
-      if(jobname==NULL)
-        error(EXIT_FAILURE, errno, "jobname in mkprof.c");
-      sprintf(jobname, "%s created.", outname);
+      asprintf(&jobname, "%s created.", filename);
       gal_timing_report(NULL, jobname, 2);
       free(jobname);
     }
-  free(outname);
+  free(filename);
 }
 
 
@@ -252,7 +247,7 @@ build(void *inparam)
 
 
       /* Find the bounding box size (NOT oversampled). */
-      if((int)cat[p->fcol]==POINTCODE)
+      if((int)cat[p->fcol]==PROFILE_POINT)
         mkp->width[0]=mkp->width[1]=1;
       else
         gal_box_ellipse_in_box(mkp->truncr, mkp->q*mkp->truncr,
@@ -378,14 +373,12 @@ build(void *inparam)
 void
 writelog(struct mkprofparams *p)
 {
-  int space[]={6, 10, 15}, prec[]={3, 6};
-  int int_cols[]={0, 2, 4, -1}, accu_cols[]={-1};
   char comments[1000], gitdescribe[100], *gd=gal_git_describe();
 
   if(gd) sprintf(gitdescribe, " from %s,", gd);
   else   gitdescribe[0]='\0';
 
-  sprintf(comments, "# Log file for "SPACK_STRING".\n"
+  sprintf(comments, "# Log file for "PROGRAM_STRING".\n"
           "# Created%s on %s"
           "# Column 0: Row number in catalog (starting from zero).\n"
           "# Column 1: Overlap magnitude with final image "
@@ -396,9 +389,10 @@ writelog(struct mkprofparams *p)
           "# Column 4: An individual image was created.\n",
           ctime(&p->rawtime), gitdescribe, p->zeropoint);
 
-
+  /*
   gal_txtarray_array_to_txt(p->log, p->cs0, LOGNUMCOLS, comments, int_cols,
                             accu_cols, space, prec, 'f', LOGFILENAME);
+  */
 }
 
 
@@ -408,30 +402,31 @@ writelog(struct mkprofparams *p)
 void
 write(struct mkprofparams *p)
 {
-  void *array;
   char *jobname;
   double sum, *log;
   struct timeval t1;
   long os=p->oversample;
   int replace=p->replace;
+  gal_data_t *out, *towrite;
   size_t complete=0, cs0=p->cs0;
   struct builtqueue *ibq=NULL, *tbq;
-  int verb=p->cp.verb, bitpix=p->bitpix;
-  float *out, *to, *from, *colend, *rowend;
+  float *to, *from, *colend, *rowend;
   size_t i, j, iw, jw, ii, jj, w=p->naxes[0], ow;
 
+  /* Note that `naxes' is in the FITS standard, not C. */
+  size_t dsize[2]={p->naxes[1], p->naxes[0]};
 
-  /* Allocate the output array if necessary. */
+  /* The `out' data structure is the canvas on which all the profiles will
+     be built. When there is no background image specified, this should be
+     a cleared (all zeros) image. But the user might want to build the
+     profiles on a canvas (of real data or other mock images). If so, the
+     `p->out' was read-in/allocated in `ui.c'. */
   if(p->out)
     out=p->out;
   else
-    {
-      errno=0;
-      out=calloc(p->naxes[0]*p->naxes[1], sizeof *out);
-      if(out==NULL)
-        error(EXIT_FAILURE, 0, "%zu bytes for output image",
-              p->naxes[0]*p->naxes[1]*sizeof *out);
-    }
+    out=p->out=gal_data_alloc(NULL, GAL_DATA_TYPE_FLOAT, 2, dsize, p->wcs, 1,
+                   p->cp.minmapsize, "Combined mock image", "Brightness",
+                   NULL);
 
 
   /* Write each image into the output array. */
@@ -484,7 +479,7 @@ write(struct mkprofparams *p)
              know the images overlap, iw and jw are both smaller than
              the two image number of columns and number of rows, so
              w-jw and ow-jw will always be positive. */
-          to=out+i*w+j;
+          to=out->array+i*w+j;
           from=ibq->img+ii*ow+jj;
           rowend=to+iw*w;
           do
@@ -521,7 +516,7 @@ write(struct mkprofparams *p)
 
       /* Report if in verbose mode. */
       ++complete;
-      if(verb && p->nomerged==0)
+      if(!p->cp.quiet && p->nomerged==0)
         {
           errno=0;
           jobname=malloc(100*sizeof *jobname);
@@ -547,40 +542,32 @@ write(struct mkprofparams *p)
   if(p->nomerged==0)
     {
       /* Get the current time for verbose output. */
-      if(verb) gettimeofday(&t1, NULL);
+      if(!p->cp.quiet) gettimeofday(&t1, NULL);
 
       /* Make a temporary array of the desired type for writing the
          output. */
-      if(bitpix==FLOAT_IMG)
-        array=out;
+      if(out->type==GAL_DATA_TYPE_FLOAT)
+        towrite=out;
       else
-        gal_fits_change_type(out, FLOAT_IMG, p->naxes[1]*p->naxes[0],
-                             p->anyblank, &array, bitpix);
+        {
+          towrite=gal_data_copy_to_new_type(out, p->outtype);
+          free(out);
+        }
 
-      /* Write the array to the output FITS file. */
-      gal_fits_array_to_file(p->mergedimgname, "Mock image",
-                             bitpix, array, p->naxes[1],
-                             p->naxes[0], p->anyblank, p->wcs,
-                             NULL, SPACK_STRING);
+      /* Write the final image into a FITS file. */
+      gal_fits_write_img(towrite, p->mergedimgname, NULL, PROGRAM_STRING);
 
-      /* Free `array' if it was allocated separately.*/
-      if(bitpix!=FLOAT_IMG)
-        free(array);
+      /* Clean up */
+      gal_data_free(towrite);
 
       /* In verbose mode, print the information. */
-      if(verb)
+      if(!p->cp.quiet)
         {
-          errno=0;
-          jobname=malloc((strlen(p->mergedimgname)+100)*sizeof *jobname);
-          if(jobname==NULL)
-            error(EXIT_FAILURE, errno, "final report in mkprof.c");
-          sprintf(jobname, "%s created.", p->mergedimgname);
+          asprintf(&jobname, "%s created.", p->mergedimgname);
           gal_timing_report(&t1, jobname, 1);
           free(jobname);
         }
     }
-
-  free(out);
 }
 
 
@@ -678,7 +665,7 @@ mkprof(struct mkprofparams *p)
 
   /* Write the created arrays into the image. */
   write(p);
-  if(p->cp.nolog==0)
+  if(p->cp.log)
     writelog(p);
 
   /* If numthreads>1, then wait for all the jobs to finish and destroy
diff --git a/bin/mkprof/mkprof.h b/bin/mkprof/mkprof.h
index 7ab17a2..8264317 100644
--- a/bin/mkprof/mkprof.h
+++ b/bin/mkprof/mkprof.h
@@ -45,7 +45,7 @@ struct mkonthread
   double (*profile)(struct mkonthread *); /* Function to use.         */
   double           truncr;   /* Truncation radius in pixels.          */
   double         intruncr;   /* Inner truncation radius in pixels.    */
-  long           width[2];   /* The width of the enclosing box.       */
+  long           width[2];   /* Enclosing box in FITS axes, not C.    */
   float          peakflux;   /* Flux at profile peak.                 */
   float        brightness;   /* The brightness of the profile.        */
   int                func;   /* Radial function of the profile.       */
diff --git a/bin/mkprof/oneprofile.c b/bin/mkprof/oneprofile.c
index 32481bf..0f70e36 100644
--- a/bin/mkprof/oneprofile.c
+++ b/bin/mkprof/oneprofile.c
@@ -250,7 +250,7 @@ makepixbypix(struct mkonthread *mkp)
   p=x*mkp->width[0]+y;
 
   /* If this is a point source, just fill that one pixel and go. */
-  if(mkp->func==POINTCODE)
+  if(mkp->func==PROFILE_POINT)
     { img[p]=1; return; }
 
   /* Allocate the byt array to not repeat completed pixels. */
@@ -259,15 +259,15 @@ makepixbypix(struct mkonthread *mkp)
   if(byt==NULL)
     error(EXIT_FAILURE, 0, "%zu bytes for map of object in row %zu of "
           "data in %s", is0*is1*sizeof *byt, ibq->id,
-          mkp->p->up.catname);
+          mkp->p->catname);
 
   /* Start the queue: */
   byt[p]=1;
   gal_linkedlist_add_to_tosll_end( &lQ, &sQ, p, r_circle(p, mkp) );
 
   /* If random points are necessary, then do it: */
-  if(mkp->func==SERSICCODE || mkp->func==MOFFATCODE
-     || mkp->func==GAUSSIANCODE)
+  if(mkp->func==PROFILE_SERSIC || mkp->func==PROFILE_MOFFAT
+     || mkp->func==PROFILE_GAUSSIAN)
     {
       while(sQ)
         {
@@ -353,7 +353,7 @@ makepixbypix(struct mkonthread *mkp)
           /* For the circumference, if the profile is too elongated
              and circumwidth is too small, then some parts of the
              circumference will not be shown without this condition. */
-          if(mkp->func==CIRCUMFERENCECODE) img[p]=profile(mkp);
+          if(mkp->func==PROFILE_CIRCUMFERENCE) img[p]=profile(mkp);
           continue;
         }
 
@@ -407,7 +407,7 @@ int
 ispsf(double fcolvalue)
 {
   int f=fcolvalue;
-  if(f==MOFFATCODE || f==GAUSSIANCODE)
+  if(f==PROFILE_MOFFAT || f==PROFILE_GAUSSIAN)
     return 1;
   else return 0;
 }
@@ -441,7 +441,7 @@ setprofparams(struct mkonthread *mkp)
   /* Fill the profile dependent parameters. */
   switch (mkp->func)
     {
-    case SERSICCODE:
+    case PROFILE_SERSIC:
       mkp->correction       = 1;
       mkp->profile          = &Sersic;
       mkp->sersic_re        = cat[rcol];
@@ -452,7 +452,7 @@ setprofparams(struct mkonthread *mkp)
 
 
 
-    case MOFFATCODE:
+    case PROFILE_MOFFAT:
       mkp->correction       = 1;
       mkp->profile          = &Moffat;
       mkp->moffat_nb        = -1.0f*cat[p->ncol];
@@ -469,7 +469,7 @@ setprofparams(struct mkonthread *mkp)
 
 
 
-    case GAUSSIANCODE:
+    case PROFILE_GAUSSIAN:
       mkp->correction       = 1;
       mkp->profile          = &Gaussian;
       sigma                 = cat[rcol]/2.35482f;
@@ -485,7 +485,7 @@ setprofparams(struct mkonthread *mkp)
 
 
 
-    case POINTCODE:
+    case PROFILE_POINT:
       mkp->correction       = 1;
       mkp->fixedvalue       = 1.0f;
       mkp->profile          = &Flat;
@@ -493,7 +493,7 @@ setprofparams(struct mkonthread *mkp)
 
 
 
-    case FLATCODE:
+    case PROFILE_FLAT:
       mkp->profile          = &Flat;
       mkp->truncr           = tp ? cat[tcol] : cat[tcol]*cat[rcol];
       if(p->mforflatpix)
@@ -510,7 +510,7 @@ setprofparams(struct mkonthread *mkp)
 
 
 
-    case CIRCUMFERENCECODE:
+    case PROFILE_CIRCUMFERENCE:
       mkp->profile          = &Circumference;
       mkp->truncr           = tp ? cat[tcol] : cat[tcol]*cat[rcol];
       mkp->intruncr         = mkp->truncr - p->circumwidth;
@@ -599,7 +599,7 @@ makeoneprofile(struct mkonthread *mkp)
   mkp->ibq->img=calloc(size, sizeof *mkp->ibq->img);
   if(mkp->ibq->img==NULL)
     error(EXIT_FAILURE, 0, "%zu bytes for object in row %zu of data in %s",
-          size*sizeof *mkp->ibq->img, mkp->ibq->id, mkp->p->up.catname);
+          size*sizeof *mkp->ibq->img, mkp->ibq->id, mkp->p->catname);
 
 
   /* Build the profile in the image. */
diff --git a/bin/mkprof/ui.c b/bin/mkprof/ui.c
index 43ca5fe..7c11fd5 100644
--- a/bin/mkprof/ui.c
+++ b/bin/mkprof/ui.c
@@ -1,6 +1,6 @@
 /*********************************************************************
-MakeProfiles - Create mock astronomical profiles.
-MakeProfiles is part of GNU Astronomy Utilities (Gnuastro) package.
+Arithmetic - Do arithmetic operations on images.
+Arithmetic is part of GNU Astronomy Utilities (Gnuastro) package.
 
 Original author:
      Mohammad Akhlaghi <address@hidden>
@@ -22,41 +22,26 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 **********************************************************************/
 #include <config.h>
 
-#include <math.h>
-#include <time.h>
+#include <argp.h>
 #include <errno.h>
 #include <error.h>
 #include <stdio.h>
-#include <stdlib.h>
 
-#include <nproc.h>               /* From Gnulib.                   */
-
-#include <gnuastro/box.h>
-#include <gnuastro/wcs.h>
 #include <gnuastro/fits.h>
-#include <gnuastro/array.h>
-#include <gnuastro/txtarray.h>
-#include <gnuastro/statistics.h>
+#include <gnuastro/table.h>
+#include <gnuastro/linkedlist.h>
 
-#include <timing.h>              /* Includes time.h and sys/time.h */
+#include <nproc.h>  /* from Gnulib, in Gnuastro's source */
+#include <timing.h>
+#include <options.h>
 #include <checkset.h>
-#include <commonargs.h>
-#include <configfiles.h>
 
 #include "main.h"
-#include "mkprof.h"
 
-#include "ui.h"                  /* Needs main.h.                  */
-#include "args.h"                /* Needs main.h, includes argp.h. */
-#include "oneprofile.h"          /* Needs main.h and mkprof.h.     */
+#include "ui.h"
+#include "args.h"
 
 
-/* Set the file names of the places where the default parameters are
-   put. */
-#define CONFIG_FILE SPACK CONF_POSTFIX
-#define SYSCONFIG_FILE SYSCONFIG_DIR "/" CONFIG_FILE
-#define USERCONFIG_FILEEND USERCONFIG_DIR CONFIG_FILE
-#define CURDIRCONFIG_FILE CURDIRCONFIG_DIR CONFIG_FILE
 
 
 
@@ -65,880 +50,72 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 
 /**************************************************************/
-/**************       Options and parameters    ***************/
+/***************       Sanity Check         *******************/
 /**************************************************************/
-void
-readconfig(char *filename, struct mkprofparams *p)
+/* ONLY check options. When arguments are involved, do the check in
+   `ui_check_options_and_arguments'. */
+static void
+ui_read_check_only_options(struct mkprofparams *p)
 {
-  FILE *fp;
-  char *line, *name, *value;
-  struct uiparams *up=&p->up;
-  size_t lineno=0, len=200, tmp;
-  struct gal_commonparams *cp=&p->cp;
-  char key='a';        /* Not used, just a place holder. */
-
-  /* When the file doesn't exist or can't be opened, it is ignored. It
-     might be intentional, so there is no error. If a parameter is
-     missing, it will be reported after all defaults are read. */
-  fp=fopen(filename, "r");
-  if (fp==NULL) return;
-
-
-  /* Allocate some space for `line` with `len` elements so it can
-     easily be freed later on. The value of `len` is arbitarary at
-     this point, during the run, getline will change it along with the
-     pointer to line. */
-  errno=0;
-  line=malloc(len*sizeof *line);
-  if(line==NULL)
-    error(EXIT_FAILURE, errno, "ui.c: %zu bytes in readdefaults",
-          len * sizeof *line);
-
-  /* Read the tokens in the file:  */
-  while(getline(&line, &len, fp) != -1)
-    {
-      /* Prepare the "name" and "value" strings, also set lineno. */
-      GAL_CONFIGFILES_START_READING_LINE;
-
-      /* Inputs: */
-      if(strcmp(name, "hdu")==0)
-        gal_checkset_allocate_copy_set(value, &cp->hdu, &cp->hduset);
-
-
-
-      /* Outputs: */
-      else if(strcmp(name, "output")==0)
-        gal_checkset_allocate_copy_set(value, &cp->output, &cp->outputset);
-
-      else if(strcmp(name, "naxis1")==0)
-        {
-          if(up->naxis1set) continue;
-          gal_checkset_sizet_l_zero(value, &tmp, name, key, SPACK,
-                                    filename, lineno);
-          p->naxes[0]=tmp;
-          up->naxis1set=1;
-        }
-      else if(strcmp(name, "inputascanvas")==0)
-        {
-          if(up->inputascanvasset) continue;
-          gal_checkset_int_zero_or_one(value, &up->inputascanvas, name,
-                                       key, SPACK, filename, lineno);
-          up->inputascanvasset=1;
-        }
-      else if(strcmp(name, "naxis2")==0)
-        {
-          if(up->naxis2set) continue;
-          gal_checkset_sizet_l_zero(value, &tmp, name, key, SPACK,
-                                    filename, lineno);
-          p->naxes[1]=tmp;
-          up->naxis2set=1;
-        }
-      else if(strcmp(name, "oversample")==0)
-        {
-          if(up->oversampleset) continue;
-          gal_checkset_sizet_l_zero(value, &p->oversample, name, key,
-                                    SPACK, filename, lineno);
-          up->oversampleset=1;
-        }
-      else if(strcmp(name, "replace")==0)
-        {
-          if(up->replaceset) continue;
-          gal_checkset_int_zero_or_one(value, &p->replace, name,
-                                       key, SPACK, filename, lineno);
-          up->replaceset=1;
-        }
-      else if(strcmp(name, "type")==0)
-        {
-          if(p->up.typeset) continue;
-          gal_checkset_known_types(value, &p->up.type, filename, lineno);
-          p->up.typeset=1;
-        }
-
-
-
-
-      /* Profiles: */
-      else if(strcmp(name, "tunitinp")==0)
-        {
-          if(up->tunitinpset) continue;
-          gal_checkset_int_zero_or_one(value, &p->tunitinp, name, key,
-                                       SPACK, filename, lineno);
-          up->tunitinpset=1;
-        }
-      else if(strcmp(name, "numrandom")==0)
-        {
-          if(up->numrandomset) continue;
-          gal_checkset_sizet_l_zero(value, &p->numrandom, name, key, SPACK,
-                                    filename, lineno);
-          up->numrandomset=1;
-        }
-      else if(strcmp(name, "tolerance")==0)
-        {
-          if(up->toleranceset) continue;
-          gal_checkset_float_l_0(value, &p->tolerance, name, key, SPACK,
-                                 filename, lineno);
-          up->toleranceset=1;
-        }
-      else if(strcmp(name, "zeropoint")==0)
-        {
-          if(up->zeropointset) continue;
-          gal_checkset_any_float(value, &p->zeropoint, name, key, SPACK,
-                                 filename, lineno);
-          up->zeropointset=1;
-        }
-      else if(strcmp(name, "prepforconv")==0)
-        {
-          if(up->prepforconvset) continue;
-          gal_checkset_int_zero_or_one(value, &p->up.prepforconv, name, key,
-                                       SPACK, filename, lineno);
-          up->prepforconvset=1;
-        }
-      else if(strcmp(name, "xshift")==0)
-        {
-          if(up->xshiftset) continue;
-          gal_checkset_sizet_el_zero(value, &tmp, name, key, SPACK,
-                                     filename, lineno);
-          p->shift[0]=tmp;
-          up->xshiftset=1;
-        }
-      else if(strcmp(name, "yshift")==0)
-        {
-          if(up->yshiftset) continue;
-          gal_checkset_sizet_el_zero(value, &tmp, name, key, SPACK,
-                                     filename, lineno);
-          p->shift[1]=tmp;
-          up->yshiftset=1;
-        }
-      else if(strcmp(name, "circumwidth")==0)
-        {
-          if(up->circumwidthset) continue;
-          gal_checkset_double_l_value(value, &p->circumwidth, name, key,
-                                      SPACK, MINCIRCUMWIDTH, filename,
-                                      lineno);
-          up->circumwidthset=1;
-        }
-      else if(strcmp(name, "envseed")==0)
-        {
-          if(up->envseedset) continue;
-          gal_checkset_int_zero_or_one(value, &p->envseed, name, key,
-                                       SPACK, filename, lineno);
-          up->envseedset=1;
-        }
-
-
-
-
-      /* Catalog: */
-      else if(strcmp(name, "xcol")==0)
-        {
-          if(up->xcolset) continue;
-          gal_checkset_sizet_el_zero(value, &p->xcol, name, key, SPACK,
-                                     filename, lineno);
-          up->xcolset=1;
-        }
-      else if(strcmp(name, "ycol")==0)
-        {
-          if(up->ycolset) continue;
-          gal_checkset_sizet_el_zero(value, &p->ycol, name, key, SPACK,
-                                     filename, lineno);
-          up->ycolset=1;
-        }
-      else if(strcmp(name, "racol")==0)
-        {
-          if(up->racolset) continue;
-          gal_checkset_sizet_el_zero(value, &p->racol, name, key, SPACK,
-                                     filename, lineno);
-          up->racolset=1;
-        }
-      else if(strcmp(name, "deccol")==0)
-        {
-          if(up->deccolset) continue;
-          gal_checkset_sizet_el_zero(value, &p->deccol, name, key, SPACK,
-                                     filename, lineno);
-          up->deccolset=1;
-        }
-      else if(strcmp(name, "fcol")==0)
-        {
-          if(up->fcolset) continue;
-          gal_checkset_sizet_el_zero(value, &p->fcol, name, key, SPACK,
-                                     filename, lineno);
-          up->fcolset=1;
-        }
-      else if(strcmp(name, "rcol")==0)
-        {
-          if(up->rcolset) continue;
-          gal_checkset_sizet_el_zero(value, &p->rcol, name, key, SPACK,
-                                     filename, lineno);
-          up->rcolset=1;
-        }
-      else if(strcmp(name, "ncol")==0)
-        {
-          if(up->ncolset) continue;
-          gal_checkset_sizet_el_zero(value, &p->ncol, name, key, SPACK,
-                                     filename, lineno);
-          up->ncolset=1;
-        }
-      else if(strcmp(name, "pcol")==0)
-        {
-          if(up->pcolset) continue;
-          gal_checkset_sizet_el_zero(value, &p->pcol, name, key, SPACK,
-                                     filename, lineno);
-          up->pcolset=1;
-        }
-      else if(strcmp(name, "qcol")==0)
-        {
-          if(up->qcolset) continue;
-          gal_checkset_sizet_el_zero(value, &p->qcol, name, key, SPACK,
-                                     filename, lineno);
-          up->qcolset=1;
-        }
-      else if(strcmp(name, "mcol")==0)
-        {
-          if(up->mcolset) continue;
-          gal_checkset_sizet_el_zero(value, &p->mcol, name, key, SPACK,
-                                     filename, lineno);
-          up->mcolset=1;
-        }
-      else if(strcmp(name, "tcol")==0)
-        {
-          if(up->tcolset) continue;
-          gal_checkset_sizet_el_zero(value, &p->tcol, name, key, SPACK,
-                                     filename, lineno);
-          up->tcolset=1;
-        }
-      else if(strcmp(name, "mforflatpix")==0)
-        {
-          if(up->mforflatpixset) continue;
-          gal_checkset_int_zero_or_one(value, &p->mforflatpix, name, key,
-                                       SPACK, filename, lineno);
-          up->mforflatpixset=1;
-        }
-
-
-
+  size_t i;
+  struct argp_option *o=options;
+  struct gal_linkedlist_stll *namell=NULL, *docll=NULL;
 
-
-      /* WCS: */
-      else if(strcmp(name, "crpix1")==0)
-        {
-          if(up->crpix1set) continue;
-          gal_checkset_any_double(value, &p->crpix[0], name, key, SPACK,
-                                  filename, lineno);
-          up->crpix1set=1;
-        }
-      else if(strcmp(name, "crpix2")==0)
-        {
-          if(up->crpix2set) continue;
-          gal_checkset_any_double(value, &p->crpix[1], name, key, SPACK,
-                                  filename, lineno);
-          up->crpix2set=1;
-        }
-      else if(strcmp(name, "crval1")==0)
-        {
-          if(up->crval1set) continue;
-          gal_checkset_any_double(value, &p->crval[0], name, key, SPACK,
-                                  filename, lineno);
-          up->crval1set=1;
-        }
-      else if(strcmp(name, "crval2")==0)
+  /* Put the program's option values into the structure. */
+  for(i=0; !gal_options_is_last(&o[i]); ++i)
+    if( o[i].key && o[i].name )
+      switch(o[i].key)
         {
-          if(up->crval2set) continue;
-          gal_checkset_any_double(value, &p->crval[1], name, key, SPACK,
-                                  filename, lineno);
-          up->crval2set=1;
-        }
-      else if(strcmp(name, "resolution")==0)
-        {
-          if(up->resolutionset) continue;
-          gal_checkset_any_float(value, &p->resolution, name, key, SPACK,
-                                 filename, lineno);
-          up->resolutionset=1;
-        }
-
-
-
-      /* Operating modes: */
-      /* Read options common to all programs */
-      GAL_CONFIGFILES_READ_COMMONOPTIONS_FROM_CONF
-
-
-      else
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      "`%s` not recognized.\n", name);
-    }
-
-  free(line);
-  fclose(fp);
-}
-
-
-
-
-
-
-void
-printvalues(FILE *fp, struct mkprofparams *p)
-{
-  struct uiparams *up=&p->up;
-  struct gal_commonparams *cp=&p->cp;
-
-  fprintf(fp, "\n# Input:\n");
-  if(cp->hduset)
-    GAL_CHECKSET_PRINT_STRING_MAYBE_WITH_SPACE("hdu", cp->hdu);
-
-  fprintf(fp, "\n# Output:\n");
-  if(cp->outputset)
-    fprintf(fp, CONF_SHOWFMT"%s\n", "output", cp->output);
-  if(up->naxis1set)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "naxis1", p->naxes[0]);
-  if(up->naxis2set)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "naxis2", p->naxes[1]);
-  if(up->inputascanvasset)
-    fprintf(fp, CONF_SHOWFMT"%d\n", "inputascanvas", up->inputascanvas);
-  if(up->oversampleset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "oversample", p->oversample);
-  if(up->replaceset)
-    fprintf(fp, CONF_SHOWFMT"%d\n", "replace", p->replace);
-  if(up->typeset)
-    gal_configfiles_print_type(fp, p->up.type);
-
-  fprintf(fp, "\n# Profiles:\n");
-  if(up->tunitinpset)
-    fprintf(fp, CONF_SHOWFMT"%d\n", "tunitinp", p->tunitinp);
-  if(up->numrandomset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "numrandom", p->numrandom);
-  if(up->toleranceset)
-    fprintf(fp, CONF_SHOWFMT"%.2f\n", "tolerance", p->tolerance);
-  if(up->zeropointset)
-    fprintf(fp, CONF_SHOWFMT"%.2f\n", "zeropoint", p->zeropoint);
-  if(up->circumwidthset)
-    fprintf(fp, CONF_SHOWFMT"%.2f\n", "circumwidth", p->circumwidth);
-  if(up->envseedset)
-    fprintf(fp, CONF_SHOWFMT"%d\n", "envseed", p->envseed);
-
-  fprintf(fp, "\n# Catalog:\n");
-  if(up->xcolset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "xcol", p->xcol);
-  if(up->ycolset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "ycol", p->ycol);
-  if(up->racolset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "racol", p->racol);
-  if(up->deccolset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "deccol", p->deccol);
-  if(up->fcolset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "fcol", p->fcol);
-  if(up->rcolset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "rcol", p->rcol);
-  if(up->ncolset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "ncol", p->ncol);
-  if(up->pcolset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "pcol", p->pcol);
-  if(up->qcolset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "qcol", p->qcol);
-  if(up->mcolset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "mcol", p->mcol);
-  if(up->tcolset)
-    fprintf(fp, CONF_SHOWFMT"%zu\n", "tcol", p->tcol);
-  if(up->mforflatpixset)
-    fprintf(fp, CONF_SHOWFMT"%d\n", "mforflatpix", p->mforflatpix);
-
-  fprintf(fp, "\n# WCS:\n");
-  if(up->crpix1set)
-    fprintf(fp, CONF_SHOWFMT"%g\n", "crpix1", p->crpix[0]);
-  if(up->crpix2set)
-    fprintf(fp, CONF_SHOWFMT"%g\n", "crpix2", p->crpix[1]);
-  if(up->crval1set)
-    fprintf(fp, CONF_SHOWFMT"%g\n", "crval1", p->crval[0]);
-  if(up->crval2set)
-    fprintf(fp, CONF_SHOWFMT"%g\n", "crval2", p->crval[1]);
-  if(up->resolutionset)
-    fprintf(fp, CONF_SHOWFMT"%g\n", "resolution", p->resolution);
-
-  /* For the operating mode, first put the macro to print the common
-     options, then the (possible options particular to this
-     program). */
-  fprintf(fp, "\n# Operating modes:\n");
-  GAL_CONFIGFILES_PRINT_COMMONOPTIONS;
-}
-
-
-
-
-
-void
-checkifset(struct mkprofparams *p)
-{
-  struct uiparams *up=&p->up;
-
-  int intro=0;
-  if(p->cp.hduset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("hdu");
-  if(up->tunitinpset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("tunitinp");
-  if(up->numrandomset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("numrandom");
-  if(up->toleranceset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("tolerance");
-  if(up->zeropointset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("zeropoint");
-  if(up->fcolset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("fcol");
-  if(up->rcolset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("rcol");
-  if(up->ncolset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("ncol");
-  if(up->pcolset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("pcol");
-  if(up->qcolset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("qcol");
-  if(up->mcolset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("mcol");
-  if(up->oversampleset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("oversample");
-  if(up->circumwidthset==0)
-    GAL_CONFIGFILES_REPORT_NOTSET("circumwidth");
-
-
-  /* The output image size, type, and WCS are only necessary if the user
-     has not provided an input image. */
-  if(p->up.backname==NULL)
-    {
-      if(up->typeset==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("type");
-      if(up->naxis1set==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("naxis1");
-      if(up->naxis2set==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("naxis2");
-      if(up->crpix1set==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("crpix1");
-      if(up->crpix2set==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("crpix2");
-      if(up->crval1set==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("crval1");
-      if(up->crval2set==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("crval2");
-      if(up->resolutionset==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("resolution");
-    }
-
-
-  /* The X and Y columns are only needed when the RA and Dec columns have
-     not been given. */
-  if(up->racolset==0 && up->deccolset==0)
-    {
-      if(up->xcolset==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("xcol");
-      if(up->ycolset==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("ycol");
-    }
-  /* The `if' statment above made sure that at least one of the RA and Dec
-     columns have been specified. So make sure that both are specified. */
-  else if(up->racolset!=up->deccolset)
-    {
-      if(up->racolset==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("racol");
-      if(up->deccolset==0)
-        GAL_CONFIGFILES_REPORT_NOTSET("deccol");
-    }
-
-  GAL_CONFIGFILES_END_OF_NOTSET_REPORT;
-}
-
-
-
-
 
+          /* Input */
+        case ARGS_OPTION_BACKHDU_KEY:
+          gal_checkset_allocate_copy(o[i].value, &p->backhdu);
+          break;
 
 
+          /* Output */
+        case ARGS_OPTION_NAXIS1_KEY:
+          printf("\nJust before checking value to naxis1.\n"); exit(0);
+          gal_options_check_set(&o[i], &p->naxes[0], GAL_OPTIONS_RANGE_GT_0);
+          break;
 
+        case ARGS_OPTION_NAXIS2_KEY:
+          gal_options_check_set(&o[i], &p->naxes[1], GAL_OPTIONS_RANGE_GT_0);
+          break;
 
 
 
+          /* Operating mode */
 
 
 
-
-
-
-
-
-
-/**************************************************************/
-/***************       Sanity Check         *******************/
-/**************************************************************/
-void
-sanitycheck(struct mkprofparams *p)
-{
-  int d0f1;
-  long width[2]={1,1};
-  struct uiparams *up=&p->up;
-  double truncr, *cat=p->cat, *row;
-  size_t i, j, columns[9], cs1=p->cs1;
-  char *tmpname=NULL, *xcolstr, *ycolstr;
-
-
-
-  /* Check if over-sampling is an odd number, then set/modify the
-     respective values.*/
-  if(p->oversample%2==0)
-    error(EXIT_FAILURE, 0, "the value to the `--oversample' (`-s') option "
-          "must be an odd number. Please run the following command for a "
-          "complete explanation:\n\n  info gnuastro \"Oversampling\"\n\nOr "
-          "See the \"Oversampling\" section of the Gnuastro book.");
-  p->halfpixel = 0.5f/p->oversample;
-  p->naxes[0] *= p->oversample;
-  p->naxes[1] *= p->oversample;
-
-
-
-  /* When the RA and Dec columns have been given use them for the profile
-     positions instead of the X and Y columns. In the next step we are
-     going to convert the RAs and Decs to Xs and Ys and until then, we are
-     just dealing with the columns, not the actual values, so it is safe
-     (and greatfly simplifies the sanity checks below) to set xcol to ra
-     column and ycol to deccol. Also use this check to set the string that
-     should be printed if the column is not within the catalog's number of
-     columsn*/
-  if(up->racolset)
-    {
-      p->xcol=p->racol;
-      p->ycol=p->deccol;
-      xcolstr="racol";
-      ycolstr="deccol";
-    }
-  else
-    {
-      xcolstr="xcol";
-      ycolstr="ycol";
-    }
-
-
-  /* If the column numbers are not equal. */
-  columns[0]=p->xcol; columns[1]=p->ycol; columns[2]=p->fcol;
-  columns[3]=p->rcol; columns[4]=p->ncol; columns[5]=p->pcol;
-  columns[6]=p->qcol; columns[7]=p->mcol; columns[8]=p->tcol;
-  for(i=0;i<9;++i)
-    for(j=0;j<9;++j)
-      if(i!=j && columns[i]==columns[j])
-        error(EXIT_FAILURE, 0, "at least two of the specified columns "
-              "are set to %zu! By adding the `-P` or `--printparams` "
-              "option you can check the final column numbers. They "
-              "all have to be different", columns[i]);
-
-
-  /* If all the columns are within the catalog and have proper values. */
-  GAL_CHECKSET_CHECK_COL_IN_CAT(p->xcol, xcolstr);
-  GAL_CHECKSET_CHECK_COL_IN_CAT(p->ycol, ycolstr);
-  GAL_CHECKSET_CHECK_COL_IN_CAT(p->fcol, "fcol");
-  GAL_CHECKSET_CHECK_COL_IN_CAT(p->rcol, "rcol");
-  GAL_CHECKSET_CHECK_COL_IN_CAT(p->ncol, "ncol");
-  GAL_CHECKSET_CHECK_COL_IN_CAT(p->pcol, "pcol");
-  GAL_CHECKSET_CHECK_COL_IN_CAT(p->qcol, "qcol");
-  GAL_CHECKSET_CHECK_COL_NUM_IN_CAT(p->mcol, "mcol");
-  GAL_CHECKSET_CHECK_COL_IN_CAT(p->tcol, "tcol");
-
-
-  /* If there were terms that gal_txtarray_txt_to_array could not read,
-     delete the log file. Note that don't care about the whole input
-     catalog, we just want the columns that are important to
-     MakeProfiles. The GAL_CHECKSET_CHECK_COL_IN_CAT tests above checked
-     those columns and they are fine. For example the user might have some
-     alphabetic information in the input file, but as long as the columns
-     we want are correct, we have no problem. We can't remove this line
-     before those tests, because in their errors, those tests guide the
-     reader to check the `txtarray.log' file. */
-  gal_checkset_check_remove_file(GAL_TXTARRAY_LOG, 0);
-
-
-  /* Check if all the profile codes are within the desired range: */
-  for(i=0;i<p->cs0;++i)
-    if(cat[i*cs1+p->fcol]<0 || cat[i*cs1+p->fcol]>MAXIMUMCODE)
-      error(EXIT_FAILURE, 0, "%s: In row %zu, the function code should"
-            "be positive and smaller or equal to %d",
-            p->up.catname, i+1, MAXIMUMCODE);
-
-
-  /* If any of xshift or yshift is non-zero, the other should be too!
-     Note that conditional operators return 1 if true and 0 if false,
-     so if one is non-zero while the other is zero, then sum will be
-     1. Otherwise the sum will either be 0 or 2.*/
-  switch ( (p->shift[0]!=0) + (p->shift[1]!=0) )
-    {
-      /* If prepforconv is called, then xshift and yshift should be
-         zero. Also a Moffat or Gaussian profile should exist in the
-         image. */
-    case 0:
-      if(p->up.prepforconv)
-        {
-          /* Check if there is at least one Moffat or Gaussian profile. */
-          j=0;
-          for(i=0;i<p->cs0;++i)
-            if(ispsf(cat[i*cs1+p->fcol]))
-              {
-                j=i;
-                break;
-              }
-
-          /* If there is no PSF in the catalog, then you can ignore
-             prepforconv. */
-          if(i<p->cs0)
-            {
-              /* Set the row, to simplify: */
-              row=&cat[j*cs1];
-
-              /* Find the correct xshift and yshift using the first Moffat
-                 or Gaussian profile (in row 'j'). Note that the output of
-                 encloseellipse will be the total width, we only want half
-                 of it for the shift.*/
-              truncr = ( p->tunitinp ? row[p->tcol] :
-                         row[p->tcol] * row[p->rcol]/2);
-              gal_box_ellipse_in_box(truncr, row[p->qcol]*truncr,
-                                     row[p->pcol]*DEGREESTORADIANS, width);
-              p->shift[0]  = (width[0]/2)*p->oversample;
-              p->shift[1]  = (width[1]/2)*p->oversample;
-            }
+        default:
+          error(EXIT_FAILURE, 0, "option key %d not recognized in "
+                "`ui_read_check_only_options'", o[i].key);
         }
-      break;
-
-    case 1:
-      error(EXIT_FAILURE, 0, "at least one of `--xshift` (`-X`) or "
-            "`--yshift` (`-Y`) are zero");
-      break;
 
-    case 2:
-      p->shift[0] *= p->oversample;
-      p->shift[1] *= p->oversample;
-      break;
-
-    default:
-      error(EXIT_FAILURE, 0, "a bug in sanitycheck (ui.c)! In checks "
-            "for shifts. Please contact us so we can fix it");
-    }
-  p->naxes[0] += 2*p->shift[0];
-  p->naxes[1] += 2*p->shift[1];
-
-
-  /* Check the output name: */
-  d0f1=gal_checkset_dir_0_file_1(p->cp.output, p->cp.dontdelete);
-  if(d0f1)                        /* --output is a file name. */
-    {
-      p->mergedimgname=p->cp.output;
-      p->outdir=gal_checkset_dir_part(p->mergedimgname);
-    }
-  else                                /* --output is a directory name. */
-    {
-      errno=0;
-      p->outdir=malloc((strlen(p->cp.output)+1)*sizeof *p->outdir);
-      if(p->outdir==NULL)
-        error(EXIT_FAILURE, errno, "%zu bytes for p->outdir in ui.c",
-              (strlen(p->cp.output)+1)*sizeof *p->outdir);
-      strcpy(p->outdir, p->cp.output);
-      gal_checkset_check_dir_write_add_slash(&p->outdir);
-      gal_checkset_automatic_output(p->up.catname, ".fits",
-                                    p->cp.removedirinfo, p->cp.dontdelete,
-                                    &tmpname);
-      p->mergedimgname=gal_checkset_malloc_cat(p->outdir, tmpname);
-      free(tmpname);
-    }
-  p->basename=gal_checkset_not_dir_part(p->mergedimgname);
+  /* If any of the mandatory options were not given, then print an error
+     listing them and abort. */
+  if(namell)
+    gal_options_mandatory_error(namell, docll);
 }
 
 
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**************************************************************/
-/***************       Preparations         *******************/
-/**************************************************************/
-void
-preparewcs(struct mkprofparams *p)
+/* Sanity check on options AND arguments. If only option values are to be
+   checked, use `ui_read_check_only_options'. */
+static void
+ui_check_options_and_arguments(struct mkprofparams *p)
 {
-  int status;
-  struct wcsprm *wcs;
-  long os=p->oversample;
 
-  /* Allocate the memory necessary for the wcsprm structure. */
-  errno=0;
-  wcs=p->wcs=malloc(sizeof *wcs);
-  if(wcs==NULL)
-    error(EXIT_FAILURE, errno, "%zu for wcs in preparewcs", sizeof *wcs);
-
-  /* Initialize the structure (allocate all the arrays). */
-  wcs->flag=-1;
-  if( (status=wcsini(1, 2, wcs)) )
-    error(EXIT_FAILURE, 0, "wcsinit error %d: %s",
-          status, wcs_errmsg[status]);
-
-  /* Correct the CRPIX values based on oversampling and shifting. */
-  p->crpix[0] = p->crpix[0]*os + p->shift[0] - os/2;
-  p->crpix[1] = p->crpix[1]*os + p->shift[1] - os/2;
-
-  /* Fill in all the important WCS structure parameters. */
-  wcs->equinox=2000.0f;
-  wcs->crpix[0]=p->crpix[0];
-  wcs->crpix[1]=p->crpix[1];
-  wcs->crval[0]=p->crval[0];
-  wcs->crval[1]=p->crval[1];
-  wcs->pc[0]=-1.0f*p->resolution/3600/p->oversample;
-  wcs->pc[3]=p->resolution/3600/p->oversample;
-  wcs->pc[1]=wcs->pc[2]=0.0f;
-  wcs->cdelt[0]=wcs->cdelt[1]=1.0f;
-  strcpy(wcs->cunit[0], "deg");
-  strcpy(wcs->cunit[1], "deg");
-  strcpy(wcs->ctype[0], "RA---TAN");
-  strcpy(wcs->ctype[1], "DEC--TAN");
-
-  /* Set up the wcs structure with the constants defined above. */
-  status=wcsset(wcs);
-  if(status)
-    error(EXIT_FAILURE, 0, "wcsset error %d: %s", status,
-          wcs_errmsg[status]);
-
-  /* When individual mode is requested, write the WCS structure to a header
-     string to speed up the process: if we don't do it here, this process
-     will be necessary on every individual profile's output. */
-  if(p->individual)
-    {
-      status=wcshdo(WCSHDO_safe, wcs, &p->wcsnkeyrec, &p->wcsheader);
-      if(status)
-        error(EXIT_FAILURE, 0, "wcshdo error %d: %s", status,
-              wcs_errmsg[status]);
-    }
 }
 
 
 
 
 
-void
-preparearrays(struct mkprofparams *p)
-{
-  void *array=NULL;
-  size_t i, naxes[2];
-  double *wcstoimg=NULL;
-  struct uiparams *up=&p->up;
-
-  /* Allocate space for the log file: */
-  p->log=malloc(p->cs0*LOGNUMCOLS*sizeof *p->log);
-  if(p->log==NULL)
-    error(EXIT_FAILURE, 0, "Allocating %zu bytes for log file",
-          p->cs0*LOGNUMCOLS*sizeof *p->log);
-
-
-  /* If a background image is specified, then use that as the output
-     image to build the profiles over. */
-  if(up->backname)
-    {
-      /* Read the input WCS. */
-      gal_fits_read_wcs(up->backname, p->cp.hdu, 0, 0, &p->nwcs, &p->wcs);
-
-      /* Read in the background image and its coordinates: */
-      p->anyblank=gal_fits_hdu_to_array(up->backname, p->cp.hdu,
-                                        &p->bitpix, &array,
-                                        &naxes[1], &naxes[0]);
-      p->naxes[1]=naxes[1];
-      p->naxes[0]=naxes[0];
-
-      /* The the type of the input image is not float, then convert it
-         to float to add the mock profile. */
-      if(p->bitpix==FLOAT_IMG)
-        p->out=array;
-      else
-        {
-          gal_fits_change_type(array, p->bitpix, p->naxes[1]*p->naxes[0],
-                               p->anyblank, (void **)(&p->out),
-                               FLOAT_IMG);
-          free(array);
-        }
-
-      /* If the user just wanted the headers, then change all non-NaN
-         pixels to 0.0f. */
-      if(up->inputascanvas)
-        gal_array_freplace_nonnans(p->out, naxes[0]*naxes[1], 0.0f);
-    }
-
-
-  /* Make the WCS structure if it has not been set so far. */
-  if(p->wcs==NULL)
-    preparewcs(p);
-
-  /* Set the output image type when a background image is not specified,
-     or when inputascanvas is called (with a background image). */
-  if(!up->backname || up->inputascanvas)
-    p->bitpix=up->type;
-
-  /* Convert the RA and Dec to X and Y. We will make a temporary array with
-     four rows and the same number of columns, then use that array and the
-     WCS structure to get X and Y values. Those X and Y values will then be
-     replaced with the RAs and Decs of the original catalog. Recall that
-     this is only done in the RAM, not the actual input file, so there is
-     no problem. One of the reasons we are doing this is that WCSLIB needs
-     the X and Ys and the RA and Decs to be in touching pieces of memory
-     and we can't guarantee that (the user might have these columns in
-     any order). */
-  if(up->racolset)
-    {
-      /* Allocate the space for the temporary array. */
-      errno=0;
-      wcstoimg=malloc(4*p->cs0*sizeof *wcstoimg);
-      if(wcstoimg==NULL)
-        error(EXIT_FAILURE, errno, "%zu bytes for wcstoimg",
-              4*p->cs0*sizeof *wcstoimg);
-
-
-      /* Fill in the first two columns with the RA and Dec. */
-      for(i=0;i<p->cs0;++i)
-        {
-          wcstoimg[ i*4   ] = p->cat[ i*p->cs1+p->racol  ];
-          wcstoimg[ i*4+1 ] = p->cat[ i*p->cs1+p->deccol ];
-          wcstoimg[ i*4+2 ] = wcstoimg[ i*4+3 ] = NAN;
-        }
-
-
-      /* Convert the X and Y to RA and Dec. */
-      gal_wcs_radec_array_to_xy(p->wcs, wcstoimg, wcstoimg+2, p->cs0, 4);
-
-
-      /* Write the produced X and Y into the input catalog, note that in
-         `sanitycheck', xcol became identical to racol and ycol to
-         deccol. Note that oversampling has been applied to the WCS
-         structure. However, when X and Y are given, oversampling is not
-         applied at this point, so we have to correct for the WCS's
-         oversampling.*/
-      for(i=0;i<p->cs0;++i)
-        {
-          p->cat[ i*p->cs1+p->xcol  ] = wcstoimg[ i*4+2 ] / p->oversample;
-          p->cat[ i*p->cs1+p->ycol  ] = wcstoimg[ i*4+3 ] / p->oversample;
-        }
-
-
-      /* Free the temporary array space. */
-      free(wcstoimg);
-    }
-
-  /* Allocate the random number generator: */
-  gsl_rng_env_setup();
-  p->rng=gsl_rng_alloc(gsl_rng_default);
-}
-
-
-
-
 
 
 
@@ -960,85 +137,43 @@ preparearrays(struct mkprofparams *p)
 void
 setparams(int argc, char *argv[], struct mkprofparams *p)
 {
-  char *jobname;
-  struct timeval t1;
-  struct gal_commonparams *cp=&p->cp;
-  char message[GAL_TIMING_VERB_MSG_LENGTH_V];
+  struct gal_options_common_params *cp=&p->cp;
 
   /* Set the non-zero initial values, the structure was initialized to
-     have a zero value for all elements. */
-  cp->spack            = SPACK;
-  cp->verb             = 1;
-  cp->numthreads       = num_processors(NPROC_CURRENT);
-  cp->removedirinfo    = 1;
-
-  p->out               = NULL;
-  p->wcs               = NULL;
-  p->mforflatpix       = 0;
-  p->up.inputascanvas  = 0;
-
-  /* Read the arguments. */
+     have a zero/NULL value for all elements. */
+  cp->poptions        = options;
+  cp->program_name    = PROGRAM_NAME;
+  cp->program_exec    = PROGRAM_EXEC;
+  cp->program_bibtex  = PROGRAM_BIBTEX;
+  cp->program_authors = PROGRAM_AUTHORS;
+  cp->coptions        = gal_commonopts_options;
+  cp->numthreads      = num_processors(NPROC_CURRENT);
+
+  /* Read the command-line options and arguments. */
   errno=0;
   if(argp_parse(&thisargp, argc, argv, 0, 0, p))
     error(EXIT_FAILURE, errno, "parsing arguments");
 
-  /* Add the user default values and save them if asked. */
-  GAL_CONFIGFILES_CHECK_SET_CONFIG;
-
-  /* Check if all the required parameters are set. */
-  checkifset(p);
+  /* Read the configuration files. */
+  gal_options_read_config_files(cp);
 
-  /* Print the values for each parameter. */
-  if(cp->printparams)
-    GAL_CONFIGFILES_REPORT_PARAMETERS_SET;
+  /* Read the options into the program's structure, and check them and
+     their relations prior to printing. */
+  ui_read_check_only_options(p);
 
-  /* Read catalog if given. */
-  gal_txtarray_txt_to_array(p->up.catname, &p->cat, &p->cs0, &p->cs1);
-
-  /* If cp->output was not specified on the command line or in any of
-     the configuration files, then automatic output should be used, in
-     which case, cp->output should be the current directory. */
-  if(p->cp.outputset==0)
-    {
-      gal_checkset_allocate_copy("./", &p->cp.output);
-      p->cp.outputset=1;
-    }
+  /* Print the option values if asked. Note that this needs to be done
+     after the sanity check so un-sane values are not printed in the output
+     state. */
+  gal_options_print_state(cp);
 
-  /* Do a sanity check, then remove the possibly existing log file
-     created by gal_txtarray_txt_to_array. */
-  gettimeofday(&t1, NULL);
-  sanitycheck(p);
+  /* Check that the options and arguments fit well with each other. Note
+     that arguments don't go in a configuration file. So this test should
+     be done after (possibly) printing the option values. */
+  ui_check_options_and_arguments(p);
 
-  /* Prepare the necessary arrays: */
-  preparearrays(p);
-
-  /* Everything is ready, notify the user of the program starting. */
-  if(cp->verb)
-    {
-      printf(SPACK_NAME" started on %s", ctime(&p->rawtime));
-
-      errno=0;
-      jobname=malloc(strlen(p->up.catname)+100*sizeof *jobname);
-      if(jobname==NULL)
-        error(EXIT_FAILURE, errno, "jobname in ui.c");
-      sprintf(jobname, "%zu profile%sread from %s", p->cs0,
-              p->cs0>1?"s ":" ", p->up.catname);
-      gal_timing_report(&t1, jobname, 1);
-      free(jobname);
-
-      sprintf(message, "Random number generator (RNG) type: %s",
-              gsl_rng_name(p->rng));
-      gal_timing_report(NULL, message, 1);
-      if(p->envseed)
-        {
-          sprintf(message, "RNG seed for all profiles: %zu",
-                  gsl_rng_default_seed);
-          gal_timing_report(NULL, message, 1);
-        }
-
-      sprintf(message, "Using %zu threads.", cp->numthreads);
-      gal_timing_report(NULL, message, 1);
-    }
+  /* Free all the allocated spaces in the option structures. */
+  gal_options_free(options);
+  gal_options_free(gal_commonopts_options);
 }
 
 
@@ -1099,7 +234,7 @@ freeandreport(struct mkprofparams *p, struct timeval *t1)
   /* Free the random number generator: */
   gsl_rng_free(p->rng);
 
-  /* Print the final message. */
-  if(p->cp.verb)
-    gal_timing_report(t1, SPACK_NAME" finished in: ", 0);
+  /* Report the duration of the job */
+  if(!p->cp.quiet)
+    gal_timing_report(t1,  PROGRAM_NAME" finished in", 0);
 }
diff --git a/bin/table/Makefile.am b/bin/table/Makefile.am
index 2a0ecc7..8df496b 100644
--- a/bin/table/Makefile.am
+++ b/bin/table/Makefile.am
@@ -28,7 +28,7 @@ AM_CPPFLAGS = -I\$(top_srcdir)/bootstrapped/lib
 ## Utility and its sources
 bin_PROGRAMS = asttable
 
-asttable_SOURCES = main.c main.h cite.h ui.c ui.h args.h       \
+asttable_SOURCES = main.c main.h authors-cite.h ui.c ui.h args.h       \
 table.c table.h
 
 asttable_LDADD = $(top_builddir)/bootstrapped/lib/libgnu.la             \
diff --git a/bin/table/ui.c b/bin/table/ui.c
index 2b3e865..aff168d 100644
--- a/bin/table/ui.c
+++ b/bin/table/ui.c
@@ -136,7 +136,7 @@ ui_read_check_only_options(struct tableparams *p)
 
         default:
           error(EXIT_FAILURE, 0, "option key %d not recognized in "
-                "`fill_params_from_options'", options[i].key);
+                "`ui_read_check_only_options'", options[i].key);
         }
 
   /* If any of the mandatory options were not given, then print an error
@@ -228,7 +228,7 @@ ui_preparations(struct tableparams *p)
 
       /* Free the information from all the columns. */
       for(i=0;i<numcols;++i)
-        gal_data_free(&allcols[i], 1);
+        gal_data_free_contents(&allcols[i]);
       free(allcols);
 
 
diff --git a/bootstrap.conf b/bootstrap.conf
index 99db2bb..f496e6d 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -141,10 +141,15 @@ bootstrap_post_import_hook()
              print "  void *value;";                \
                                                     \
              printf "\n";                           \
-             print "  /* Type of value (see lib/gnuastro/data.h)."; \
+             print "  /* Type of value (see lib/gnuastro/data.h).";          \
              print "     IMPORTANT: currently ONLY a Gnuastro addition. */"; \
              print "  int type;";                   \
                                                     \
+             printf "\n";                           \
+             print "  /* Acceptable range of value (see lib/options.h).";    \
+             print "     IMPORTANT: currently ONLY a Gnuastro addition. */"; \
+             print "  int range;";                  \
+                                                    \
              print;                                 \
              inargp=0;                              \
           }                                         \
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 5acd0ed..01572b0 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -17871,10 +17871,10 @@ knowledge and authority'' can be broken, see 
@ref{Science and its
 tools}. The following software architecture can be one of the most basic
 and easy to understand for any interested inquirer.
 
-In this chapter, first some general design choices are tackled in @code{Why
-C} and @code{Program design philosophy}. The project management webpage and
+In this chapter, first some general design choices are tackled in @ref{Why
+C} and @ref{Program design philosophy}. The project management webpage and
 mailing lists are explained in @ref{Gnuastro project webpage} and
address@hidden mailing lists}. In @ref{Coding conventions}, Gnuastro's
address@hidden mailing lists}. In @ref{Coding conventions}, Gnuastro's
 adopted coding conventions are discussed and is followed by @ref{Program
 source} which describes how to easily navigate the source files in each
 program and also contains a template program to easily add new
diff --git a/lib/arithmetic-binary.c b/lib/arithmetic-binary.c
index 7c959e0..9fd0d62 100644
--- a/lib/arithmetic-binary.c
+++ b/lib/arithmetic-binary.c
@@ -481,7 +481,7 @@ arithmetic_binary(int operator, unsigned char flags, 
gal_data_t *lo,
   if( o->type != final_otype )
     {
       tmp_o=gal_data_copy_to_new_type(o, final_otype);
-      gal_data_free(o, 0);
+      gal_data_free(o);
       o=tmp_o;
     }
 
@@ -495,14 +495,14 @@ arithmetic_binary(int operator, unsigned char flags, 
gal_data_t *lo,
      they are different from the original pointers, they were allocated. */
   if(flags & GAL_ARITHMETIC_FREE)
     {
-      if     (o==l)       gal_data_free(r, 0);
-      else if(o==r)       gal_data_free(l, 0);
-      else              { gal_data_free(l, 0); gal_data_free(r, 0); }
+      if     (o==l)       gal_data_free(r);
+      else if(o==r)       gal_data_free(l);
+      else              { gal_data_free(l); gal_data_free(r); }
     }
   else
     {
-      if(l!=lo)           gal_data_free(l, 0);
-      if(r!=ro)           gal_data_free(r, 0);
+      if(l!=lo)           gal_data_free(l);
+      if(r!=ro)           gal_data_free(r);
     }
 
   /* Return */
diff --git a/lib/arithmetic-onlyint.c b/lib/arithmetic-onlyint.c
index 51431a4..b848edc 100644
--- a/lib/arithmetic-onlyint.c
+++ b/lib/arithmetic-onlyint.c
@@ -413,7 +413,7 @@ arithmetic_onlyint_binary(int operator, unsigned char flags,
   if( o->type != final_otype )
     {
       tmp_o=gal_data_copy_to_new_type(o, final_otype);
-      gal_data_free(o, 0);
+      gal_data_free(o);
       o=tmp_o;
     }
 
@@ -427,14 +427,14 @@ arithmetic_onlyint_binary(int operator, unsigned char 
flags,
      they are different from the original pointers, they were allocated. */
   if(flags & GAL_ARITHMETIC_FREE)
     {
-      if     (o==l)       gal_data_free(r, 0);
-      else if(o==r)       gal_data_free(l, 0);
-      else              { gal_data_free(l, 0); gal_data_free(r, 0); }
+      if     (o==l)       gal_data_free(r);
+      else if(o==r)       gal_data_free(l);
+      else              { gal_data_free(l); gal_data_free(r); }
     }
   else
     {
-      if(l!=lo)           gal_data_free(l, 0);
-      if(r!=ro)           gal_data_free(r, 0);
+      if(l!=lo)           gal_data_free(l);
+      if(r!=ro)           gal_data_free(r);
     }
 
   /* Return */
@@ -512,7 +512,7 @@ arithmetic_onlyint_bitwise_not(unsigned char flags, 
gal_data_t *in)
      the pointers: if they are different from the original pointers, they
      were allocated. */
   if( (flags & GAL_ARITHMETIC_FREE) && o!=in)
-    gal_data_free(in, 0);
+    gal_data_free(in);
 
   /* Return */
   return o;
diff --git a/lib/arithmetic.c b/lib/arithmetic.c
index 4d9d1a5..686cf99 100644
--- a/lib/arithmetic.c
+++ b/lib/arithmetic.c
@@ -71,7 +71,7 @@ arithmetic_change_type(gal_data_t *data, int operator, 
unsigned char flags)
 
   /* Delete the input structure if the user asked for it. */
   if(flags & GAL_ARITHMETIC_FREE)
-    gal_data_free(data, 0);
+    gal_data_free(data);
 
   /* Return */
   return out;
@@ -145,7 +145,7 @@ arithmetic_not(gal_data_t *data, unsigned char flags)
 
   /* Delete the input structure if the user asked for it. */
   if(flags & GAL_ARITHMETIC_FREE)
-    gal_data_free(data, 0);
+    gal_data_free(data);
 
   /* Return */
   return out;
@@ -229,7 +229,7 @@ arithmetic_abs(unsigned char flags, gal_data_t *in)
 
   /* Clean up and return */
   if( (flags & GAL_ARITHMETIC_FREE) && out!=in)
-    gal_data_free(in, 0);
+    gal_data_free(in);
   return out;
 }
 
@@ -448,8 +448,8 @@ arithmetic_check_float_input(gal_data_t *in, int operator, 
char *numstr)
 static gal_data_t *
 arithmetic_unary_function(int operator, unsigned char flags, gal_data_t *in)
 {
-  long dsize=1;
   gal_data_t *o;
+  size_t dsize=1;
 
   /* If we want inplace output, set the output pointer to the input
      pointer, for every pixel, the operation will be independent. */
@@ -512,7 +512,7 @@ arithmetic_unary_function(int operator, unsigned char 
flags, gal_data_t *in)
      the pointers: if they are different from the original pointers, they
      were allocated. */
   if( (flags & GAL_ARITHMETIC_FREE) && o!=in)
-    gal_data_free(in, 0);
+    gal_data_free(in);
 
   /* Return */
   return o;
@@ -681,9 +681,9 @@ arithmetic_binary_function_flt(int operator, unsigned char 
flags,
      were allocated. */
   if(flags & GAL_ARITHMETIC_FREE)
     {
-      if     (o==l)       gal_data_free(r, 0);
-      else if(o==r)       gal_data_free(l, 0);
-      else              { gal_data_free(l, 0); gal_data_free(r, 0); }
+      if     (o==l)       gal_data_free(r);
+      else if(o==r)       gal_data_free(l);
+      else              { gal_data_free(l); gal_data_free(r); }
     }
 
   /* Return */
@@ -832,8 +832,8 @@ arithmetic_where(unsigned char flags, gal_data_t *out, 
gal_data_t *cond,
   /* Clean up if necessary. */
   if(flags & GAL_ARITHMETIC_FREE)
     {
-      gal_data_free(cond, 0);
-      gal_data_free(iftrue, 0);
+      gal_data_free(cond);
+      gal_data_free(iftrue);
     }
 }
 
@@ -1153,7 +1153,7 @@ arithmetic_multioperand(int operator, unsigned char 
flags, gal_data_t *list)
       while(tmp!=NULL)
         {
           ttmp=tmp->next;
-          if(tmp!=out) gal_data_free(tmp, 0);
+          if(tmp!=out) gal_data_free(tmp);
           tmp=ttmp;
         }
     }
@@ -1450,7 +1450,7 @@ gal_arithmetic_convert_to_compiled_type(gal_data_t *in, 
unsigned char flags)
         {
           out=gal_data_copy_to_new_type(in, ntype);
           if(flags & GAL_ARITHMETIC_FREE)
-            { gal_data_free(in, 0); in=NULL; }
+            { gal_data_free(in); in=NULL; }
         }
       else
         {
@@ -1522,7 +1522,7 @@ gal_arithmetic(int operator, unsigned char flags, ...)
     case GAL_ARITHMETIC_OP_ISBLANK:
       d1 = va_arg(va, gal_data_t *);
       out = gal_data_flag_blank(d1);
-      if(flags & GAL_ARITHMETIC_FREE) gal_data_free(d1, 0);
+      if(flags & GAL_ARITHMETIC_FREE) gal_data_free(d1);
       break;
 
     case GAL_ARITHMETIC_OP_WHERE:
diff --git a/lib/checkset.c b/lib/checkset.c
index ad9ab0e..78333ac 100644
--- a/lib/checkset.c
+++ b/lib/checkset.c
@@ -37,464 +37,6 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include "checkset.h"
 
 
-#define FIXEDFORFILE        "The value of `%s` (given as %s)"
-#define FIXEDFOROPTION      "The value of `--%s (-%c)` (given as %s)"
-#define NOTEMSG_NOTNUMBER   "not readable as number"
-#define NOTEMSG_EQZEROORONE "should be ==0 or ==1"
-#define NOTEMSG_LEQZERO     "should be >=0"
-#define NOTEMSG_LARGERZERO  "should be >0"
-#define NOTEMSG_4OR8        "should be either 4 or 8"
-#define NOTEMSG_SMALLERONE  "should be >=0 and <=1"
-
-
-#define CHECKFULLNUMBER   if(*tailptr!='\0'){                           \
-    if(filename)                                                        \
-      error_at_line(EXIT_FAILURE, 0, filename, lineno,                  \
-                    FIXEDFORFILE" "NOTEMSG_NOTNUMBER, lo, optarg);      \
-    else                                                                \
-      error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_NOTNUMBER,        \
-            lo, so, optarg);                                            \
-  }
-
-
-
-
-/****************************************************************
- ************      Check and convert strings    *****************
- ****************************************************************/
-/* See if a given string is a floating point number, if so, put it in
-   the number.*/
-int
-gal_checkset_str_is_double(char *string, double *out)
-{
-  char *tailptr;
-  double tmp=*out;
-  *out=strtod(string, &tailptr);
-
-  /* If the tail pointer (tailptr) is the string NULL character, then
-     the string was a single double precision floating point
-     number. However, if it is any other character, then put the
-     initial value of out back inside of it and return 0. */
-  if(*tailptr=='\0') return 1;
-  *out=tmp;
-  return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/****************************************************************
- *****************      Check the numbers    ********************
- ****************************************************************/
-void
-gal_checkset_int_zero_or_one(char *optarg, int *var, char *lo, char so,
-                             char *spack, char *filename, size_t lineno)
-{
-  long tmp;
-  char *tailptr;
-
-  *var=tmp=strtol(optarg, &tailptr, 0);
-
-  CHECKFULLNUMBER;
-  if(tmp!=0 && tmp!=1)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_EQZEROORONE, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_EQZEROORONE,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-
-void
-gal_checkset_int_4_or_8(char *optarg, int *var, char *lo, char so,
-                        char *spack, char *filename, size_t lineno)
-{
-  long tmp;
-  char *tailptr;
-
-  *var=tmp=strtol(optarg, &tailptr, 0);
-
-  CHECKFULLNUMBER;
-  if(tmp!=4 && tmp!=8)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_EQZEROORONE, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_EQZEROORONE,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-
-void
-gal_checkset_int_el_zero(char *optarg, int *var, char *lo, char so,
-                         char *spack, char *filename, size_t lineno)
-{
-  long tmp;
-  char *tailptr;
-  *var=tmp=strtol(optarg, &tailptr, 0);
-
-  CHECKFULLNUMBER;
-  if(tmp<0)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_LEQZERO, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_LEQZERO,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-
-void
-gal_checkset_int_l_zero(char *optarg, int *var, char *lo, char so,
-                        char *spack, char *filename, size_t lineno)
-{
-  long tmp;
-  char *tailptr;
-  *var=tmp=strtol(optarg, &tailptr, 0);
-
-  CHECKFULLNUMBER;
-  if(tmp<=0)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_LARGERZERO, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_LARGERZERO,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-
-void
-gal_checkset_int_smaller_equal_to(char *optarg, int *var, char *lo, char so,
-                                  char *spack, char *filename, size_t lineno,
-                                  long maxvalue)
-{
-  long tmp;
-  char *tailptr;
-  *var=tmp=strtol(optarg, &tailptr, 0);
-
-  CHECKFULLNUMBER;
-  if(tmp>maxvalue)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_4OR8, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_4OR8,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-
-void
-gal_checkset_long_el_zero(char *optarg, long *var, char *lo, char so,
-                          char *spack, char *filename, size_t lineno)
-{
-  long tmp;
-  char *tailptr;
-  *var=tmp=strtol(optarg, &tailptr, 0);
-
-  CHECKFULLNUMBER;
-  if(tmp<0)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_LEQZERO, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_LEQZERO,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-
-void
-gal_checkset_any_long(char *optarg, long *var, char *lo, char so,
-                      char *spack, char *filename, size_t lineno)
-{
-  char *tailptr;
-  *var=strtol(optarg, &tailptr, 0);
-
-  CHECKFULLNUMBER;
-}
-
-
-
-
-
-/* size_t is always >=0. But if the user gives a negative value, it
-   will become an extremely large number (because size_t is
-   unsigned). So we read the user's value in long, which accepts
-   negative values, then we check that value before placing it in the
-   size_t pointer.*/
-void
-gal_checkset_sizet_el_zero(char *optarg, size_t *var, char *lo, char so,
-                           char* spack, char *filename, size_t lineno)
-{
-  long tmp;
-  char *tailptr;
-  *var=tmp=strtol(optarg, &tailptr, 0);
-
-  CHECKFULLNUMBER;
-  if(tmp<0)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_LEQZERO, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_LEQZERO,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-/* See explanation for gal_checkset_sizet_l_zero above. */
-void
-gal_checkset_sizet_l_zero(char *optarg, size_t *var, char *lo, char so,
-                          char* spack, char *filename, size_t lineno)
-{
-  long tmp;
-  char *tailptr;
-  *var=tmp=strtol(optarg, &tailptr, 0);
-
-  CHECKFULLNUMBER;
-  if(tmp<=0)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_LARGERZERO, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_LARGERZERO,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-
-/* Positive and odd size_t. */
-void
-gal_checkset_sizet_p_odd(char *optarg, size_t *var, char *lo, char so,
-                         char* spack, char *filename, size_t lineno)
-{
-  long tmp;
-  char *tailptr;
-  *var=tmp=strtol(optarg, &tailptr, 0);
-
-  CHECKFULLNUMBER;
-  if(tmp<0 || tmp%2==0)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" should be >0 and odd.", lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" should be >0 and odd",
-              lo, so, optarg);
-    }
-}
-
-
-
-
-
-void
-gal_checkset_float_l_0(char *optarg, float *var, char *lo, char so,
-                       char* spack, char *filename, size_t lineno)
-{
-  float tmp;
-  char *tailptr;
-  *var=tmp=strtod(optarg, &tailptr);
-
-  CHECKFULLNUMBER;
-  if(tmp<=0)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_LARGERZERO, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_LARGERZERO,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-
-void
-gal_checkset_float_l_0_s_1(char *optarg, float *var, char *lo, char so,
-                         char* spack, char *filename, size_t lineno)
-{
-  float tmp;
-  char *tailptr;
-  *var=tmp=strtod(optarg, &tailptr);
-
-  CHECKFULLNUMBER;
-  if(tmp>1.0f || tmp<0)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_SMALLERONE, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_SMALLERONE,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-void
-gal_checkset_any_float(char *optarg, float *var, char *lo, char so,
-                       char *spack, char *filename, size_t lineno)
-{
-  char *tailptr;
-  *var=strtod(optarg, &tailptr);
-
-  CHECKFULLNUMBER;
-}
-
-
-
-
-void
-gal_checkset_double_l_0(char *optarg, double *var, char *lo, char so,
-                        char* spack, char *filename, size_t lineno)
-{
-  double tmp;
-  char *tailptr;
-  *var=tmp=strtod(optarg, &tailptr);
-
-  CHECKFULLNUMBER;
-  if(tmp<=0)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_LARGERZERO, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_LARGERZERO,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-
-void
-gal_checkset_double_el_0(char *optarg, double *var, char *lo, char so,
-                         char* spack, char *filename, size_t lineno)
-{
-  double tmp;
-  char *tailptr;
-  *var=tmp=strtod(optarg, &tailptr);
-
-  CHECKFULLNUMBER;
-  if(tmp<0)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" "NOTEMSG_LARGERZERO, lo, optarg);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" "NOTEMSG_LARGERZERO,
-              lo, so, optarg);
-    }
-}
-
-
-
-
-
-void
-gal_checkset_double_l_value(char *optarg, double *var, char *lo, char so,
-                            char* spack, double value, char *filename,
-                            size_t lineno)
-{
-  float tmp;
-  char *tailptr;
-  *var=tmp=strtod(optarg, &tailptr);
-
-  CHECKFULLNUMBER;
-  if(tmp<=value)
-    {
-      if(filename)
-        error_at_line(EXIT_FAILURE, 0, filename, lineno,
-                      FIXEDFORFILE" should be > %.4f", lo, optarg, value);
-      else
-        error(EXIT_FAILURE, 0, FIXEDFOROPTION" should be > %.4f",
-              lo, so, optarg, value);
-    }
-}
-
-
-
-
-
-void
-gal_checkset_any_double(char *optarg, double *var, char *lo, char so,
-                        char *spack, char *filename, size_t lineno)
-{
-  char *tailptr;
-  *var=strtod(optarg, &tailptr);
-
-  CHECKFULLNUMBER;
-}
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 
diff --git a/lib/checkset.h b/lib/checkset.h
index 218ef90..aaa24d4 100644
--- a/lib/checkset.h
+++ b/lib/checkset.h
@@ -49,133 +49,6 @@ __BEGIN_C_DECLS  /* From C++ preparations */
 
 
 
-/**************************************************************/
-/*********                 Macros                **************/
-/**************************************************************/
-/* Check if the column number is within the boundaries of a catalog. */
-#define GAL_CHECKSET_CHECK_COL_NUM_IN_CAT(INCOL,NAME) {                 \
-    if( (INCOL) >= p->cs1 )                                             \
-      error(EXIT_FAILURE, 0, "%s only has %zu columns while you "       \
-            "have requested column %zu (counting from zero) for "       \
-            "`--%s`", p->up.catname, p->cs1, (INCOL), (NAME));          \
-  }
-
-
-
-
-
-/* Check both the column number and that the values in the column are
-   finitte numbers (not infinities or NAN). */
-#define GAL_CHECKSET_CHECK_COL_IN_CAT(INCOL,NAME) {                     \
-    size_t i;                                                           \
-                                                                        \
-    if( (INCOL) >= p->cs1 )                                             \
-      error(EXIT_FAILURE, 0, "%s only has %zu columns while you "       \
-            "have requested column %zu (counting from zero) for "       \
-            "`--%s`", p->up.catname, p->cs1, (INCOL), (NAME));          \
-                                                                        \
-    for(i=0;i<p->cs0;++i)                                               \
-      if( !isfinite(p->cat[i*p->cs1+(INCOL)]) )                         \
-        error(EXIT_FAILURE, 0, "%s: column %zu (--%s) in row %zu "      \
-              "could not be read as a number. See %s. Note that "       \
-              "counting starts from zero",                              \
-              p->up.catname, (INCOL), (NAME), i, GAL_TXTARRAY_LOG);     \
-  }
-
-
-
-
-#define GAL_CHECKSET_PRINT_STRING_MAYBE_WITH_SPACE(name,string) {       \
-    if(gal_checkset_string_has_space(string))                           \
-      fprintf(fp, CONF_SHOWFMT"\"%s\"\n", name, string);                \
-    else                                                                \
-      fprintf(fp, CONF_SHOWFMT"%s\n", name, string);                    \
-  }
-
-
-
-/****************************************************************
- ************      Check and convert strings    *****************
- ****************************************************************/
-int
-gal_checkset_str_is_double(char *string, double *out);
-
-
-
-/**************************************************************/
-/********* Read arguments and check their values **************/
-/**************************************************************/
-void
-gal_checkset_int_zero_or_one(char *optarg, int *var, char *lo, char so,
-                             char* spack, char *filename, size_t lineno);
-
-void
-gal_checkset_int_4_or_8(char *optarg, int *var, char *lo, char so,
-                        char *spack, char *filename, size_t lineno);
-
-void
-gal_checkset_int_el_zero(char *optarg, int *var, char *lo, char so,
-                         char *spack, char *filename, size_t lineno);
-
-void
-gal_checkset_int_l_zero(char *optarg, int *var, char *lo, char so,
-                        char *spack, char *filename, size_t lineno);
-
-void
-gal_checkset_int_smaller_equal_to(char *optarg, int *var, char *lo,
-                                  char so, char *spack, char *filename,
-                                  size_t lineno, long maxvalue);
-
-void
-gal_checkset_long_el_zero(char *optarg, long *var, char *lo, char so,
-                          char *spack, char *filename, size_t lineno);
-
-void
-gal_checkset_any_long(char *optarg, long *var, char *lo, char so,
-                      char *spack, char *filename, size_t lineno);
-
-void
-gal_checkset_sizet_el_zero(char *optarg, size_t *var, char *lo, char so,
-                           char *spack, char *filename, size_t lineno);
-
-void
-gal_checkset_sizet_l_zero(char *optarg, size_t *var, char *lo, char so,
-                          char *spack, char *filename, size_t lineno);
-
-void
-gal_checkset_sizet_p_odd(char *optarg, size_t *var, char *lo, char so,
-                         char* spack, char *filename, size_t lineno);
-
-void
-gal_checkset_float_l_0(char *optarg, float *var, char *lo, char so,
-                       char *spack, char *filename, size_t lineno);
-
-void
-gal_checkset_float_l_0_s_1(char *optarg, float *var, char *lo, char so,
-                           char *spack, char *filename, size_t lineno);
-
-void
-gal_checkset_any_float(char *optarg, float *var, char *lo, char so,
-                       char *spack, char *filename, size_t lineno);
-
-void
-gal_checkset_double_l_0(char *optarg, double *var, char *lo, char so,
-                        char *spack, char *filename, size_t lineno);
-
-void
-gal_checkset_double_el_0(char *optarg, double *var, char *lo, char so,
-                         char* spack, char *filename, size_t lineno);
-
-void
-gal_checkset_double_l_value(char *optarg, double *var, char *lo, char so,
-                            char* spack, double value, char *filename,
-                            size_t lineno);
-
-void
-gal_checkset_any_double(char *optarg, double *var, char *lo, char so,
-                        char *spack, char *filename, size_t lineno);
-
-
 
 /**************************************************************/
 /**********          Check fixed strings           ************/
diff --git a/lib/commonopts.h b/lib/commonopts.h
index 420522d..b529f96 100644
--- a/lib/commonopts.h
+++ b/lib/commonopts.h
@@ -24,6 +24,8 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #ifndef __GAL_COMMONOPTS_H__
 #define __GAL_COMMONOPTS_H__
 
+#include <gnuastro/data.h>
+
 /* Common options for all programs.
 
    IMPORTANT NOTE:
diff --git a/lib/data.c b/lib/data.c
index 48aa615..94e53ea 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -604,7 +604,7 @@ gal_data_mmap(gal_data_t *data, int clear)
 */
 void
 gal_data_initialize(gal_data_t *data, void *array, int type,
-                    size_t ndim, long *dsize, struct wcsprm *wcs,
+                    size_t ndim, size_t *dsize, struct wcsprm *wcs,
                     int clear, size_t minmapsize, char *name,
                     char *unit, char *comment)
 {
@@ -694,7 +694,7 @@ gal_data_initialize(gal_data_t *data, void *array, int type,
    force the array into the hdd/ssd (mmap it), then set minmapsize=-1
    (largest possible size_t value), in this way, no file will be larger. */
 gal_data_t *
-gal_data_alloc(void *array, int type, size_t ndim, long *dsize,
+gal_data_alloc(void *array, int type, size_t ndim, size_t *dsize,
                struct wcsprm *wcs, int clear, size_t minmapsize,
                char *name, char *unit, char *comment)
 {
@@ -813,20 +813,18 @@ gal_data_string_fixed_alloc_size(gal_data_t *data)
 
 
 
-/* Free the allocated contents of a data structure and possibly also the
-   data structure its self. When `only_contents' is zero, the actual data
-   structure will also be freed, see bellow.
-
-   The reason for the `only_contents' argument is that the data structure
-   might be allocated as an array (statically like `gal_data_t da[20]', or
-   dynamically like `gal_data_t *da; da=malloc(20*sizeof *da);'). In both
-   cases, a loop will be necessary to delete the allocated contents of each
-   element of the data structure array, but not the structure its
-   self. After that loop, if the array of data structures was statically
-   allocated, you don't have to do anything. If it was dynamically
-   allocated, we just have to run `free(da)'.*/
+/* Free the allocated contents of a data structure, not the structure
+   itsself. The reason for this function begin separate from
+   `gal_data_free) is that the data structure might be allocated as an
+   array (statically like `gal_data_t da[20]', or dynamically like
+   `gal_data_t *da; da=malloc(20*sizeof *da);'). In both cases, a loop will
+   be necessary to delete the allocated contents of each element of the
+   data structure array, but not the structure its self. After that loop,
+   if the array of data structures was statically allocated, you don't have
+   to do anything. If it was dynamically allocated, we just have to run
+   `free(da)'.*/
 void
-gal_data_free(gal_data_t *data, int only_contents)
+gal_data_free_contents(gal_data_t *data)
 {
   /* Free all the possible allocations. */
   if(data->name)    free(data->name);
@@ -856,10 +854,19 @@ gal_data_free(gal_data_t *data, int only_contents)
     }
   else
     if(data->array) free(data->array);
+}
+
+
 
-  /* Finally, free the actual data structure. */
-  if(only_contents==0)
-    free(data);
+
+
+/* Free the contents of the data structure and the data structure
+   itsself. */
+void
+gal_data_free(gal_data_t *data)
+{
+  gal_data_free_contents(data);
+  free(data);
 }
 
 
@@ -917,7 +924,7 @@ gal_data_add_existing_to_ll(gal_data_t **list, gal_data_t 
*newnode)
 
 void
 gal_data_add_to_ll(gal_data_t **list, void *array, int type, size_t ndim,
-                   long *dsize, struct wcsprm *wcs, int clear,
+                   size_t *dsize, struct wcsprm *wcs, int clear,
                    size_t minmapsize, char *name, char *unit, char *comment)
 {
   gal_data_t *newnode;
@@ -998,7 +1005,7 @@ gal_data_free_ll(gal_data_t *list)
   while(list!=NULL)
     {
       tmp=list->next;
-      gal_data_free(list, 0);
+      gal_data_free(list);
       list=tmp;
     }
 }
@@ -1991,7 +1998,7 @@ gal_data_to_same_type(gal_data_t *f,   gal_data_t *s,
     {
       *of=gal_data_copy_to_new_type(f, type);
       if(freeinputs)
-        gal_data_free(f, 0);
+        gal_data_free(f);
     }
   else
     *of=f;
@@ -2001,7 +2008,7 @@ gal_data_to_same_type(gal_data_t *f,   gal_data_t *s,
     {
       *os=gal_data_copy_to_new_type(s, type);
       if(freeinputs)
-        gal_data_free(s, 0);
+        gal_data_free(s);
     }
   else
     *os=s;
@@ -2034,7 +2041,7 @@ gal_data_to_same_type(gal_data_t *f,   gal_data_t *s,
 gal_data_t *
 gal_data_string_to_number(char *string)
 {
-  long dsize[1]={1};
+  size_t dsize[1]={1};
   int fnz=-1, lnz=0;     /* `F'irst (or `L'ast) `N'on-`Z'ero. */
   void *ptr, *numarr;
   char *tailptr, *cp;
diff --git a/lib/fits.c b/lib/fits.c
index 8f1fd82..19ab01d 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -462,9 +462,9 @@ gal_fits_datatype_to_type(int datatype)
 
 
 
-/*************************************************************
- **************        Get information         ***************
- *************************************************************/
+/**************************************************************/
+/**********                  HDU                   ************/
+/**************************************************************/
 void
 gal_fits_num_hdus(char *filename, int *numhdu)
 {
@@ -488,75 +488,17 @@ gal_fits_num_hdus(char *filename, int *numhdu)
 
 
 
-/* Note that the FITS standard defines any array as an `image',
-   irrespective of how many dimensions it has. */
-void
-gal_fits_img_info(fitsfile *fptr, int *type, size_t *ndim, long **dsize)
-{
-  size_t i;
-  int bitpix, status=0, naxis;
-  long naxes[GAL_DATA_MAXDIM];
-
-  /* Get the BITPIX, number of dimensions and size of each dimension. */
-  if( fits_get_img_param(fptr, GAL_DATA_MAXDIM, &bitpix, &naxis,
-                         naxes, &status) )
-    gal_fits_io_error(status, NULL);
-  *ndim=naxis;
-
-  /* Convert bitpix to Gnuastro's known types. */
-  *type=gal_fits_bitpix_to_type(bitpix);
-
-  /* Allocate space for the size along each dimension. */
-  errno=0;
-  *dsize=malloc( *ndim * sizeof **dsize );
-  if(*dsize==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for dsize in gal_fits_img_info",
-          *ndim * sizeof **dsize);
-
-  /* Put the size of each dimention into the output array. */
-  for(i=0;i<*ndim;++i)
-    (*dsize)[i]=naxes[i];
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**************************************************************/
-/**********                  HDU                   ************/
-/**************************************************************/
 /* Check the desired HDU in a FITS image and also if it has the
    desired type. */
 fitsfile *
 gal_fits_read_hdu(char *filename, char *hdu, unsigned char img0_tab1)
 {
-  size_t len;
   char *ffname;
   fitsfile *fptr;
   int status=0, hdutype;
 
   /* Add hdu to filename: */
-  errno=0;
-  len=strlen(filename)+strlen(hdu)+4;
-  ffname=malloc(len*sizeof *ffname);
-  if(ffname==NULL)
-    error(EXIT_FAILURE, errno, "%zu characters", len);
-  sprintf(ffname, "%s[%s#]", filename, hdu);
+  asprintf(&ffname, "%s[%s#]", filename, hdu);
 
   /* Open the FITS file: */
   if( fits_open_file(&fptr, ffname, READONLY, &status) )
@@ -591,6 +533,42 @@ gal_fits_read_hdu(char *filename, char *hdu, unsigned char 
img0_tab1)
 
 
 
+/* Given the filename and HDU, this function will return the CFITSIO code
+   for the type of data it contains (table, or image). The CFITSIO codes
+   are:
+
+       IMAGE_HDU:    An image HDU.
+       ASCII_TBL:    An ASCII table HDU.
+       BINARY_TBL:   BINARY TABLE HDU.       */
+int
+gal_fits_hdu_type(char *filename, char *hdu)
+{
+  char *ffname;
+  fitsfile *fptr;
+  int hdutype, status=0;
+
+  /* Add hdu to filename: */
+  asprintf(&ffname, "%s[%s#]", filename, hdu);
+
+  /* Open the FITS file: */
+  if( fits_open_file(&fptr, ffname, READONLY, &status) )
+    gal_fits_io_error(status, "reading this FITS file");
+
+  /* Check the type of the given HDU: */
+  if (fits_get_hdu_type(fptr, &hdutype, &status) )
+    gal_fits_io_error(status, NULL);
+
+  /* Clean up and return.. */
+  free(ffname);
+  if( fits_close_file(fptr, &status) )
+    gal_fits_io_error(status, NULL);
+  return hdutype;
+}
+
+
+
+
+
 
 
 
@@ -1235,6 +1213,35 @@ gal_fits_read_wcs(char *filename, char *hdu, size_t 
hstartwcs,
  ***********            Array functions            ***********
  *************************************************************/
 
+/* Note that the FITS standard defines any array as an `image',
+   irrespective of how many dimensions it has. */
+void
+gal_fits_img_info(fitsfile *fptr, int *type, size_t *ndim, size_t **dsize)
+{
+  size_t i;
+  int bitpix, status=0, naxis;
+  long naxes[GAL_DATA_MAXDIM];
+
+  /* Get the BITPIX, number of dimensions and size of each dimension. */
+  if( fits_get_img_param(fptr, GAL_DATA_MAXDIM, &bitpix, &naxis,
+                         naxes, &status) )
+    gal_fits_io_error(status, NULL);
+  *ndim=naxis;
+
+  /* Convert bitpix to Gnuastro's known types. */
+  *type=gal_fits_bitpix_to_type(bitpix);
+
+  /* Allocate the array to keep the dimension size and fill it in, note
+     that its order is the opposite of naxes. */
+  *dsize=gal_data_malloc_array(GAL_DATA_TYPE_LONG, *ndim);
+  for(i=0; i<*ndim; ++i)
+    (*dsize)[i]=naxes[*ndim-1-i];
+}
+
+
+
+
+
 /* Read a FITS image into an array corresponding to fitstype and also
    save the size of the array.
 
@@ -1246,12 +1253,12 @@ gal_fits_read_img_hdu(char *filename, char *hdu, size_t 
minmapsize)
 {
   void *blank;
   int anyblank;
-  size_t i, ndim;
+  long *fpixel;
   fitsfile *fptr;
   int status=0, type;
   gal_data_t *img, *keysll=NULL;
-  long *fpixel, *dsize, dsize_key=1;
   char **str, *name=NULL, *unit=NULL;
+  size_t i, ndim, *dsize, dsize_key=1;
 
 
   /* Check HDU for realistic conditions: */
@@ -1273,11 +1280,7 @@ gal_fits_read_img_hdu(char *filename, char *hdu, size_t 
minmapsize)
 
 
   /* Set the fpixel array (first pixel in all dimensions): */
-  errno=0;
-  fpixel=malloc(ndim*sizeof *fpixel);
-  if(fpixel==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for fpixel in "
-          "`gal_fits_read_img_hdu'", ndim*sizeof *fpixel);
+  fpixel=gal_data_malloc_array(GAL_DATA_TYPE_LONG, ndim);
   for(i=0;i<ndim;++i) fpixel[i]=1;
 
 
@@ -1296,7 +1299,7 @@ gal_fits_read_img_hdu(char *filename, char *hdu, size_t 
minmapsize)
 
 
   /* Allocate the space for the array and for the blank values. */
-  img=gal_data_alloc(NULL, type, (long)ndim, dsize, NULL, 0, minmapsize,
+  img=gal_data_alloc(NULL, type, ndim, dsize, NULL, 0, minmapsize,
                      name, unit, NULL);
   blank=gal_data_alloc_blank(type);
   gal_data_free_ll(keysll);
@@ -1340,7 +1343,7 @@ gal_fits_read_to_type(char *inputname, char *hdu, int 
type,
   if(in->type!=type)
     {
       converted=gal_data_copy_to_new_type(in, type);
-      gal_data_free(in, 0);
+      gal_data_free(in);
       in=converted;
     }
 
@@ -1409,14 +1412,20 @@ gal_fits_read_float_kernel(char *filename, char *hdu, 
size_t minmapsize)
    WCS information) into a FITS file, but will not close it. Instead it
    will pass along the FITS pointer for further modification. */
 fitsfile *
-gal_fits_write_img_fitsptr(gal_data_t *data, char *filename, char *extname)
+gal_fits_write_img_fitsptr(gal_data_t *data, char *filename)
 {
+  size_t i;
   void *blank;
-  long fpixel=1;
   fitsfile *fptr;
   char *wcsheader;
+  long fpixel=1, *naxes;
   int nkeyrec, status=0, datatype=gal_fits_type_to_datatype(data->type);
 
+  /* Fill the `naxes' array (in opposite order, and `long' type): */
+  naxes=gal_data_malloc_array(GAL_DATA_TYPE_LONG, data->ndim);
+  for(i=0;i<data->ndim;++i)
+    naxes[data->ndim-1-i]=data->dsize[i];
+
   /* Check if the file already exists. If it does, we want to add the array
      as a new extension. */
   if(access(filename,F_OK) != -1 )
@@ -1426,7 +1435,7 @@ gal_fits_write_img_fitsptr(gal_data_t *data, char 
*filename, char *extname)
 
   /* Create the FITS file and put the image into it. */
   fits_create_img(fptr, gal_fits_type_to_bitpix(data->type),
-                  data->ndim, data->dsize, &status);
+                  data->ndim, naxes, &status);
   fits_write_img(fptr, datatype, fpixel, data->size, data->array, &status);
 
   /* If we have blank pixels, we need to define a BLANK keyword when we are
@@ -1449,8 +1458,16 @@ gal_fits_write_img_fitsptr(gal_data_t *data, char 
*filename, char *extname)
       }
 
   /* Write the extension name to the header. */
-  fits_write_key(fptr, TSTRING, "EXTNAME", extname, "", &status);
-  gal_fits_io_error(status, NULL);
+  if(data->name)
+    fits_write_key(fptr, TSTRING, "EXTNAME", data->name, "", &status);
+
+  /* Write the units to the header. */
+  if(data->unit)
+    fits_write_key(fptr, TSTRING, "BUNIT", data->unit, "", &status);
+
+  /* Write comments if they exist. */
+  if(data->comment)
+    fits_write_comment(fptr, data->comment, &status);
 
   /* If a WCS structure is present, write it in */
   if(data->wcs)
@@ -1464,6 +1481,7 @@ gal_fits_write_img_fitsptr(gal_data_t *data, char 
*filename, char *extname)
     }
 
   /* Report any errors if we had any */
+  free(naxes);
   gal_fits_io_error(status, NULL);
   return fptr;
 }
@@ -1473,17 +1491,17 @@ gal_fits_write_img_fitsptr(gal_data_t *data, char 
*filename, char *extname)
 
 
 void
-gal_fits_write_img(gal_data_t *data, char *filename, char *extname,
-                   struct gal_fits_key_ll *headers, char *spack_string)
+gal_fits_write_img(gal_data_t *data, char *filename,
+                   struct gal_fits_key_ll *headers, char *program_string)
 {
   int status=0;
   fitsfile *fptr;
 
   /* Write the data array into a FITS file and keep it open: */
-  fptr=gal_fits_write_img_fitsptr(data, filename, extname);
+  fptr=gal_fits_write_img_fitsptr(data, filename);
 
   /* Write all the headers and the version information. */
-  gal_fits_write_keys_version(fptr, headers, spack_string);
+  gal_fits_write_keys_version(fptr, headers, program_string);
 
   /* Close the FITS file. */
   fits_close_file(fptr, &status);
@@ -1494,17 +1512,37 @@ gal_fits_write_img(gal_data_t *data, char *filename, 
char *extname,
 
 
 
+/* This function is mainly useful when you want to make FITS files in
+   parallel (from one main WCS structure, with just differing CRPIX) for
+   two reasons:
+
+      - 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 can't write the header keywords
+        in each thread.   */
 void
-gal_fits_write_img_update_crpix(gal_data_t *data, char *filename,
-                                char *extname,
-                                struct gal_fits_key_ll *headers,
-                                double *crpix, char *spack_string)
+gal_fits_write_img_wcs_string(gal_data_t *data, char *filename,
+                              char *wcsheader, int nkeyrec, double *crpix,
+                              struct gal_fits_key_ll *headers,
+                              char *program_string)
 {
   int status=0;
   fitsfile *fptr;
 
-  /* Write the data array into a FITS file and keep it open: */
-  fptr=gal_fits_write_img_fitsptr(data, filename, extname);
+  /* The data should not have any WCS structure for this function. */
+  if(data->wcs)
+    error(EXIT_FAILURE, 0, "`gal_fits_write_img_wcs_string' can only "
+          "accept inputs with no WCS.");
+
+  /* Write the data array into a FITS file and keep it open. */
+  fptr=gal_fits_write_img_fitsptr(data, filename);
+
+  /* Write the WCS headers into the FITS file. */
+  gal_fits_add_wcs_to_header(fptr, wcsheader, nkeyrec);
 
   /* Update the CRPIX keywords. Note that we don't want to change the
      values in the WCS information of gal_data_t. Because, it often happens
@@ -1520,7 +1558,7 @@ gal_fits_write_img_update_crpix(gal_data_t *data, char 
*filename,
     }
 
   /* Write all the headers and the version information. */
-  gal_fits_write_keys_version(fptr, NULL, spack_string);
+  gal_fits_write_keys_version(fptr, headers, program_string);
 
   /* Close the file and return. */
   fits_close_file(fptr, &status);
@@ -1985,8 +2023,8 @@ gal_fits_table_read(char *filename, char *hdu, size_t 
numrows,
                     int minmapsize)
 {
   size_t i=0;
-  long dsize;
   void *blank;
+  size_t dsize;
   char **strarr;
   fitsfile *fptr;
   int status=0, anynul;
@@ -2002,8 +2040,8 @@ gal_fits_table_read(char *filename, char *hdu, size_t 
numrows,
       /* Allocate the necessary data structure (including the array) for
          this column. */
       dsize=numrows;
-      gal_data_add_to_ll(&out, NULL, allcols[ind->v].type, 1, &dsize, NULL, 0,
-                         minmapsize, allcols[ind->v].name,
+      gal_data_add_to_ll(&out, NULL, allcols[ind->v].type, 1, &dsize,
+                         NULL, 0, minmapsize, allcols[ind->v].name,
                          allcols[ind->v].unit, allcols[ind->v].comment);
 
       /* For a string column, we need an allocated array for each element,
diff --git a/lib/gnuastro/data.h b/lib/gnuastro/data.h
index 7f77034..41ab816 100644
--- a/lib/gnuastro/data.h
+++ b/lib/gnuastro/data.h
@@ -127,17 +127,14 @@ enum gal_data_types
 
       - `minmapsize' ==  0:  array is definitely mmap'd.
 
-      - `minmapsize' == -1: array is definitely in RAM.
-
-    - The `dsize' array is in the `long' type because CFITSIO uses the long
-      type and this will make it easier to call CFITSIO functions.*/
+      - `minmapsize' == -1: array is definitely in RAM.   */
 typedef struct gal_data_t
 {
   /* Basic information on array of data. */
   void             *array;  /* Array keeping data elements.                */
   int                type;  /* Type of data (from `gal_data_alltypes').    */
   size_t             ndim;  /* Number of dimensions in the array.          */
-  long             *dsize;  /* Size of array along each dimension.         */
+  size_t           *dsize;  /* Size of array along each dimension.         */
   size_t             size;  /* Total number of data-elements.              */
   char          *mmapname;  /* File name of the mmap.                      */
   size_t       minmapsize;  /* Minimum number of bytes to mmap the array.  */
@@ -207,12 +204,12 @@ gal_data_alloc_number(int type, void *number);
 
 void
 gal_data_initialize(gal_data_t *data, void *array, int type,
-                    size_t ndim, long *dsize, struct wcsprm *wcs,
+                    size_t ndim, size_t *dsize, struct wcsprm *wcs,
                     int clear, size_t minmapsize, char *name,
                     char *unit, char *comment);
 
 gal_data_t *
-gal_data_alloc(void *array, int type, size_t ndim, long *dsize,
+gal_data_alloc(void *array, int type, size_t ndim, size_t *dsize,
                struct wcsprm *wcs, int clear, size_t minmapsize,
                char *name, char *unit, char *comment);
 
@@ -223,8 +220,10 @@ size_t
 gal_data_string_fixed_alloc_size(gal_data_t *data);
 
 void
-gal_data_free(gal_data_t *data, int only_contents);
+gal_data_free_contents(gal_data_t *data);
 
+void
+gal_data_free(gal_data_t *data);
 
 
 
@@ -236,7 +235,7 @@ gal_data_add_existing_to_ll(gal_data_t **list, gal_data_t 
*newnode);
 
 void
 gal_data_add_to_ll(gal_data_t **list, void *array, int type, size_t ndim,
-                   long *dsize, struct wcsprm *wcs, int clear,
+                   size_t *dsize, struct wcsprm *wcs, int clear,
                    size_t minmapsize, char *name, char *unit, char *comment);
 
 gal_data_t *
diff --git a/lib/gnuastro/fits.h b/lib/gnuastro/fits.h
index 8fb9370..a8d519b 100644
--- a/lib/gnuastro/fits.h
+++ b/lib/gnuastro/fits.h
@@ -134,27 +134,18 @@ gal_fits_datatype_to_type(int type);
 
 
 
-
-/*************************************************************
- **************        Get information         ***************
- *************************************************************/
-void
-gal_fits_num_hdus(char *filename, int *numhdu);
-
-void
-gal_fits_img_info(fitsfile *fptr, int *type, size_t *ndim, long **dsize);
-
-
-
-
-
 /**************************************************************/
 /**********                  HDU                   ************/
 /**************************************************************/
 
+void
+gal_fits_num_hdus(char *filename, int *numhdu);
+
 fitsfile *
 gal_fits_read_hdu(char *filename, char *hdu, unsigned char img0_tab1);
 
+int
+gal_fits_hdu_type(char *filename, char *hdu);
 
 
 
@@ -192,7 +183,7 @@ gal_fits_update_keys(fitsfile *fptr, struct gal_fits_key_ll 
**keylist);
 
 void
 gal_fits_write_keys_version(fitsfile *fptr, struct gal_fits_key_ll *headers,
-                            char *spack_string);
+                            char *program_string);
 
 
 
@@ -216,6 +207,9 @@ gal_fits_read_wcs(char *filename, char *hdu, size_t 
hstartwcs,
 /*************************************************************
  ******************     Array functions      *****************
  *************************************************************/
+void
+gal_fits_img_info(fitsfile *fptr, int *type, size_t *ndim, size_t **dsize);
+
 gal_data_t *
 gal_fits_read_img_hdu(char *filename, char *hdu, size_t minmapsize);
 
@@ -227,17 +221,17 @@ gal_data_t *
 gal_fits_read_float_kernel(char *filename, char *hdu, size_t minmapsize);
 
 fitsfile *
-gal_fits_write_img_fitsptr(gal_data_t *data, char *filename, char *extname);
+gal_fits_write_img_fitsptr(gal_data_t *data, char *filename);
 
 void
-gal_fits_write_img(gal_data_t *data, char *filename, char *extname,
-                   struct gal_fits_key_ll *headers, char *spack_string);
+gal_fits_write_img(gal_data_t *data, char *filename,
+                   struct gal_fits_key_ll *headers, char *program_string);
 
 void
-gal_fits_write_img_update_crpix(gal_data_t *data, char *filename,
-                                char *extname,
-                                struct gal_fits_key_ll *headers,
-                                double *crpix, char *spack_string);
+gal_fits_write_img_wcs_string(gal_data_t *data, char *filename,
+                              char *wcsheader, int nkeyrec, double *crpix,
+                              struct gal_fits_key_ll *headers,
+                              char *program_string);
 
 
 
diff --git a/lib/mesh.c b/lib/mesh.c
index 76ed614..166c2a8 100644
--- a/lib/mesh.c
+++ b/lib/mesh.c
@@ -453,7 +453,7 @@ gal_mesh_value_file(struct gal_mesh_params *mp, char 
*filename,
                     char *extname1, char *extname2, struct wcsprm *wcs,
                     char *spack_string)
 {
-  long dsize[2];
+  size_t dsize[2];
   gal_data_t data;
   float *tmp1=NULL, *tmp2=NULL;
 
@@ -473,16 +473,18 @@ gal_mesh_value_file(struct gal_mesh_params *mp, char 
*filename,
          differently. */
       if(mp->garray1==mp->cgarray1) gal_mesh_full_garray(mp, 0);
       data.wcs=NULL; /* Not the original image size, to have same WCS */
+      data.name=extname1;
       data.array=mp->fgarray1;
       data.dsize[0]=mp->gs0*mp->nch2;
       data.dsize[1]=mp->gs1*mp->nch1;
-      gal_fits_write_img(&data, filename, extname1, NULL, spack_string);
+      gal_fits_write_img(&data, filename, NULL, spack_string);
       if(mp->ngarrays==2)
         {
           /* Note that gal_mesh_full_garray will correct both the meshs if
              there are two.*/
+          data.name=extname2;
           data.array=mp->fgarray2;
-          gal_fits_write_img(&data, filename, extname2, NULL, spack_string);
+          gal_fits_write_img(&data, filename, NULL, spack_string);
         }
     }
   else
@@ -490,13 +492,15 @@ gal_mesh_value_file(struct gal_mesh_params *mp, char 
*filename,
       gal_mesh_check_garray(mp, &tmp1, &tmp2);
       data.wcs=wcs;
       data.array=tmp1;
+      data.name=extname1;
       data.dsize[0]=mp->s0;
       data.dsize[1]=mp->s1;
-      gal_fits_write_img(&data, filename, extname1, NULL, spack_string);
+      gal_fits_write_img(&data, filename, NULL, spack_string);
       if(mp->ngarrays==2)
         {
           data.array=tmp2;
-          gal_fits_write_img(&data, filename, extname2, NULL, spack_string);
+          data.name=extname2;
+          gal_fits_write_img(&data, filename, NULL, spack_string);
         }
       free(tmp1);
       free(tmp2);
diff --git a/lib/options.c b/lib/options.c
index c2bc18d..afbd4b3 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -30,6 +30,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <gnuastro/txt.h>
 #include <gnuastro/data.h>
+#include <gnuastro/arithmetic.h>
 #include <gnuastro/linkedlist.h>
 
 #include <options.h>
@@ -895,7 +896,189 @@ gal_options_read_config_files(struct 
gal_options_common_params *cp)
 
 
 /**********************************************************************/
-/************            After sanity check            ***************/
+/************                Sanity check               ***************/
+/**********************************************************************/
+/* All the command-line and configuration file options have been read. But
+   for the higher level steps of your program, you can't go over the
+   options array every time to find the recorded value (as a `void *'
+   pointer). Also, if the option was given, you want to make sure its value
+   is in the correct/acceptable range you expect for this option.
+
+   This function takes the argp_option structure you are checking
+   (`option') and a pointer to the (already allocated) space you want to
+   put its value in (`out'), along with the `condition' that the value to
+   this option must satisfy.
+
+   Outputs:
+
+    - If the option has a value and the condition is met, the value is put
+      into the `out' pointer and this function will return 1.
+
+    - If the option has a value and the condition isn't met, an error
+      message will be printed and the program will abort.
+
+    - If the option wasn't given a value, this function will return 0, and
+      put a blank value (depending on the type) in the value pointed by
+      `out'.  */
+int
+gal_options_check_set(struct argp_option *option, void *out, int condition)
+{
+  size_t dsize=1;
+  int operator1, operator2;
+  gal_data_t *value, *ref1, *ref2, *check1, *check2;
+  int arithflags = ( GAL_ARITHMETIC_INPLACE
+                     | GAL_ARITHMETIC_FREE
+                     | GAL_ARITHMETIC_NUMOK );
+
+
+  /* This function should only be used for numerical types. */
+  if(option->type==GAL_DATA_TYPE_STRING || option->type==GAL_DATA_TYPE_STRLL)
+    error(EXIT_FAILURE, 0, "A bug! `gal_options_check_set' should only be "
+          "used for numerical types. However it has been used for the "
+          "`%s' option, which has a type of `%s'", option->name,
+          gal_data_type_as_string(option->type, 1) );
+
+
+  /* If the option is given a value, then check it and return 1 if it is in
+     range. If its not in range, abort with an error.  */
+  if(option->value)
+    {
+      /* Put the option value into a data structure. */
+      value=gal_data_alloc(option->value, option->type, 1, &dsize, NULL,
+                           0, -1, NULL, NULL, NULL);
+
+      /* Set the operator(s): */
+      switch(condition)
+        {
+
+        case GAL_OPTIONS_RANGE_GT_0:
+          ref1=gal_data_alloc(NULL, GAL_DATA_TYPE_UCHAR, 1, &dsize, NULL,
+                              0, -1, NULL, NULL, NULL);
+          *(unsigned char *)(ref1->array)=0;
+          operator1=GAL_ARITHMETIC_OP_GT;
+          ref2=NULL;
+          break;
+
+
+        case GAL_OPTIONS_RANGE_GE_0:
+          ref1=gal_data_alloc(NULL, GAL_DATA_TYPE_UCHAR, 1, &dsize, NULL,
+                              0, -1, NULL, NULL, NULL);
+          *(unsigned char *)(ref1->array)=0;
+          operator1=GAL_ARITHMETIC_OP_GE;
+          ref2=NULL;
+          break;
+
+
+        case GAL_OPTIONS_RANGE_GE_0_LE_1:
+          ref1=gal_data_alloc(NULL, GAL_DATA_TYPE_UCHAR, 1, &dsize, NULL,
+                              0, -1, NULL, NULL, NULL);
+          ref2=gal_data_alloc(NULL, GAL_DATA_TYPE_UCHAR, 1, &dsize, NULL,
+                              0, -1, NULL, NULL, NULL);
+          *(unsigned char *)(ref1->array)=0;
+          *(unsigned char *)(ref2->array)=1;
+          operator1=GAL_ARITHMETIC_OP_GE;
+          operator1=GAL_ARITHMETIC_OP_LE;
+          break;
+
+        default:
+          error(EXIT_FAILURE, 0, "condition code %d not recognized in "
+                "`gal_options_check_set'", condition);
+        }
+
+      /* Use the arithmetic library to check for the condition. */
+      check1=gal_arithmetic(operator1, arithflags, value, ref1);
+
+      /* Clean up and return. Note that we used the actual value pointer in
+         the data structure, so first we need to set it to NULL, so
+         `gal_data_free' doesn't free it, we need it for later (for example
+         to print the option values). */
+      value->array=NULL;
+      gal_data_free(value);
+      return 1;
+    }
+
+  /* The option didn't have a value, set the output value as blank and
+     return 0. */
+  else
+    {
+      /* Set the output value. */
+      switch(option->type)
+        {
+        case GAL_DATA_TYPE_UCHAR:
+          *(unsigned char *)out = GAL_DATA_BLANK_UCHAR;
+          break;
+
+        case GAL_DATA_TYPE_CHAR:
+          *(char *)out = GAL_DATA_BLANK_CHAR;
+          break;
+
+        case GAL_DATA_TYPE_USHORT:
+          *(unsigned short *)out = GAL_DATA_BLANK_USHORT;
+          break;
+
+        case GAL_DATA_TYPE_SHORT:
+          *(short *)out = GAL_DATA_BLANK_SHORT;
+          break;
+
+        case GAL_DATA_TYPE_UINT:
+          *(unsigned int *)out = GAL_DATA_BLANK_UINT;
+          break;
+
+        case GAL_DATA_TYPE_INT:
+          *(int *)out = GAL_DATA_BLANK_INT;
+          break;
+
+        case GAL_DATA_TYPE_ULONG:
+          *(unsigned long *)out = GAL_DATA_BLANK_ULONG;
+          break;
+
+        case GAL_DATA_TYPE_LONG:
+          *(long *)out = GAL_DATA_BLANK_LONG;
+          break;
+
+        case GAL_DATA_TYPE_LONGLONG:
+          *(LONGLONG *)out = GAL_DATA_BLANK_LONGLONG;
+          break;
+
+        case GAL_DATA_TYPE_FLOAT:
+          *(float *)out = GAL_DATA_BLANK_FLOAT;
+          break;
+
+        case GAL_DATA_TYPE_DOUBLE:
+          *(double *)out = GAL_DATA_BLANK_DOUBLE;
+          break;
+
+        default:
+          error(EXIT_FAILURE, 0, "type code %d not recognized in "
+                "`gal_options_check_set'", option->type);
+        }
+
+      /* Return: */
+      return 0;
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**********************************************************************/
+/************              Printing/Writing             ***************/
 /**********************************************************************/
 /* We don't want to print the values of configuration specific options and
    the output option. The output value is assumed to be specific to each
diff --git a/lib/options.h b/lib/options.h
index 26b4b40..d38d47b 100644
--- a/lib/options.h
+++ b/lib/options.h
@@ -74,6 +74,16 @@ enum options_option_keys
 };
 
 
+/* Conditions to check */
+enum gal_options_check_values
+{
+  GAL_OPTIONS_RANGE_ANY,
+  GAL_OPTIONS_RANGE_GT_0,
+  GAL_OPTIONS_RANGE_GE_0,
+  GAL_OPTIONS_RANGE_GE_0_LE_1,
+};
+
+
 /* The structure keeping all the values of the common options in Gnuastro's
    programs. */
 struct gal_options_common_params
@@ -104,7 +114,7 @@ struct gal_options_common_params
 
 
 /**********************************************************************/
-/************         Main user functions/macros        ***************/
+/************              Option utilities             ***************/
 /**********************************************************************/
 
 int
@@ -140,6 +150,13 @@ gal_options_common_argp_parse(int key, char *arg, struct 
argp_state *state);
 
 
 
+/**********************************************************************/
+/************              Printing/Writing             ***************/
+/**********************************************************************/
+
+int
+gal_options_check_set(struct argp_option *option, void *out, int condition);
+
 
 
 /**********************************************************************/
diff --git a/lib/table.c b/lib/table.c
index 586c324..e39b244 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -741,7 +741,7 @@ gal_table_read(char *filename, char *hdu, struct 
gal_linkedlist_stll *cols,
 
   /* Clean up. */
   for(i=0;i<numcols;++i)
-    gal_data_free(&allcols[i], 1);
+    gal_data_free_contents(&allcols[i]);
   free(allcols);
   gal_linkedlist_free_sll(indexll);
 
diff --git a/lib/txt.c b/lib/txt.c
index 2c3ba2a..76e0a9c 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -356,7 +356,7 @@ txt_info_from_first_row(char *line, gal_data_t **colsll)
                     pointer. Otherwise we will break up the chain.*/
               if(prev) prev->next=col->next; else *colsll=col->next;
               tmp=col->next;
-              gal_data_free(col, 0);
+              gal_data_free(col);
               col=tmp;
             }
           else                /* Column has data.                          */
@@ -727,7 +727,7 @@ gal_txt_table_read(char *filename, size_t numrows, 
gal_data_t *colinfo,
 {
   FILE *fp;
   char *line;
-  long dsize;
+  size_t dsize;
   char **tokens;
   gal_data_t *out=NULL;
   struct gal_linkedlist_sll *ind;
diff --git a/tmpfs-config-make b/tmpfs-config-make
index 219fca8..e337626 100755
--- a/tmpfs-config-make
+++ b/tmpfs-config-make
@@ -131,7 +131,7 @@ cd $build_dir
 # ####################################
 if [ ! -f Makefile ]; then
     $srcdir/configure --srcdir=$srcdir --disable-shared CFLAGS="-g -O0"\
-                      --enable-table --enable-arithmetic
+                      --enable-arithmetic --enable-table --enable-mkprof
 fi
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]