gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 8d64628 081/113: Recent work in master importe


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 8d64628 081/113: Recent work in master imported, minor conflicts fixed
Date: Fri, 16 Apr 2021 10:33:53 -0400 (EDT)

branch: master
commit 8d64628b961dfc1f8fffa63a7553950ad8ef7a96
Merge: 05cc693 e5cb5a8
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Recent work in master imported, minor conflicts fixed
    
    Two minor conflict came up in an error message and comment that were fixed
    easily. Also the `naxis' option in `bin/mkprof/astmkprof-3d.conf' was
    corrected to `mergedsize'.
---
 .gitignore                      |   3 +
 NEWS                            |  52 ++-
 THANKS                          |   2 +-
 bin/arithmetic/arithmetic.c     |  69 +++-
 bin/arithmetic/arithmetic.h     |   3 +
 bin/arithmetic/operands.c       | 128 +++++---
 bin/buildprog/Makefile.am       |   2 +-
 bin/buildprog/buildprog.c       |   7 +-
 bin/convolve/convolve.c         |   6 +
 bin/convolve/ui.c               |   4 +
 bin/cosmiccal/astcosmiccal.conf |  14 +-
 bin/crop/crop.c                 |   4 +-
 bin/crop/onecrop.c              |   4 +-
 bin/match/match.c               |  13 +-
 bin/match/ui.c                  |  33 +-
 bin/mkcatalog/columns.c         |  11 +-
 bin/mkcatalog/mkcatalog.c       |  25 +-
 bin/mkcatalog/ui.c              |   6 +
 bin/mknoise/mknoise.c           |   9 +-
 bin/mknoise/ui.c                |   4 +
 bin/mkprof/args.h               |   4 +-
 bin/mkprof/astmkprof-3d.conf    |   2 +-
 bin/mkprof/astmkprof.conf       |   2 +-
 bin/mkprof/mkprof.c             |   5 +
 bin/mkprof/ui.c                 |  14 +-
 bin/mkprof/ui.h                 |   2 +-
 bin/noisechisel/noisechisel.c   |   7 +
 bin/noisechisel/ui.c            |   4 +
 bin/segment/main.h              |   2 +-
 bin/segment/segment.c           |   7 +-
 bin/segment/ui.c                |   5 +
 bin/statistics/sky.c            |   3 +
 bin/statistics/statistics.c     |  13 +-
 bin/statistics/ui.c             |  20 +-
 bin/warp/ui.c                   |   4 +
 bin/warp/warp.c                 |   9 +-
 bootstrap.conf                  |   1 +
 configure.ac                    | 126 +++++---
 developer-build                 |  16 +-
 doc/announce-acknowledge.txt    |  12 -
 doc/gnuastro.en.html            |   8 +-
 doc/gnuastro.fr.html            |   8 +-
 doc/gnuastro.texi               | 694 +++++++++++++++++++++++++---------------
 doc/release-checklist.txt       |  46 +--
 lib/arithmetic.c                |  40 ++-
 lib/dimension.c                 | 106 +++++-
 lib/fits.c                      | 252 +++++++++++----
 lib/gnuastro-internal/options.h |   7 +
 lib/gnuastro/dimension.h        |   3 +-
 lib/gnuastro/fits.h             |  26 +-
 lib/options.c                   |  81 +++++
 lib/statistics.c                |   3 +-
 tests/Makefile.am               |   4 -
 tests/buildprog/simpleio.sh     |  10 +-
 tests/mkprof/mosaic1.sh         |   4 +-
 tests/mkprof/mosaic2.sh         |   3 +-
 tests/mkprof/mosaic3.sh         |   2 +-
 tests/mkprof/mosaic4.sh         |   2 +-
 tests/mkprof/radeccat.sh        |   2 +-
 59 files changed, 1382 insertions(+), 576 deletions(-)

diff --git a/.gitignore b/.gitignore
index 3db7e67..f1f06bd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,6 +84,7 @@ configure
 .gnuastro
 astmkprof
 astheader
+astsegment
 runtest.sh
 astmknoise
 config.sub
@@ -116,6 +117,8 @@ doc/gnuastro.vrs
 tests/versioncxx
 tests/multithread
 lib/gnuastro/config.h
+bin/buildprog/astbuildprog.conf
+
 
 
 
diff --git a/NEWS b/NEWS
index a0c9680..78e8e16 100644
--- a/NEWS
+++ b/NEWS
@@ -1,21 +1,65 @@
 GNU Astronomy Utilities NEWS                          -*- outline -*-
 
-* Noteworthy changes in release X.X (library 5.0.0) (YYYY-MM-DD) [alpha]
+* Noteworthy changes in release X.X (library X.X.X) (YYYY-MM-DD) [stable]
+
+** New features
+
+  All programs:
+   - Input files and parameters written as keywords in the first extension
+     of output when it is FITS. This is only relevant for some programs,
+     (for example not the Fits or Table programs).
+
+  Library:
+    -- gal_fits_key_list_reverse: Reverse the given list of FITS keywords.
+    -- gal_fits_key_write_title_in_ptr: Write a two-line title in FITS 
keywords.
+    -- gal_fits_key_write_in_ptr: New name of gal_fits_key_write.
+    -- gal_fits_key_write_version_in_ptr: new name of 
gal_fits_key_write_version.
+    -- gal_fits_key_write_config: write key list and version as config header.
+
+** Removed features
+
+** Changed features
+
+  MakeProfiles:
+    --mergedsize: new name for the old `--naxis' option. Since the option
+          names and values are now written into the FITS header of the
+          output, this option's name would get confused with the mandatory
+          FITS keyword `NAXIS'.
+
+  Library:
+    -- gal_fits_key_write: filename and hdu instead of FITS pointer.
+    -- gal_fits_key_write_version: filename and hdu instead of FITS pointer.
+    -- gal_fits_key_write_filename: write at the top or end of the input list.
+
+** Bugs fixed
+  bug #54493: Warp crashes when type isn't set.
+
+
+
+
+
+* Noteworthy changes in release 0.7 (library 5.0.0) (2018-08-08) [stable]
 
 ** New features
 
   Installation:
-    --enable-debug: enable debugging flags and disable optimization.
+    --enable-debug: debugging flags, no optimization, no shared libraries.
     --enable-check-with-valgrind: Run `make check' tests within Valgrind.
 
   Arithmetic:
     - `set-A': Set a name (`A' in this case) for the popped dataset. This
                allows only reading the dataset it into memory once and
                possibly using it many times.
+    - `fill-holes': Flip background (0) pixels surrounded by foreground (1).
     - `collapse-sum': collapse/remove a dimension by summing over it.
+    - `collapse-min': collapse/remove a dimension by using minimum value.
+    - `collapse-max': collapse/remove a dimension by using maximum value.
     - `collapse-mean': collapse/remove a dimension by averaging over it.
     - `collapse-number': Number of elements included in the collapse.
 
+  CosmicCalculator:
+    - Default cosmology set to Plank 2018 results (Paper VI).
+
   MakeCatalog:
     --minx: minimum position along first FITS axis.
     --maxx: maximum position along first FITS axis.
@@ -30,6 +74,7 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
     - gal_dimension_collapse_sum: collapse/remove a dimension by summing.
     - gal_dimension_collapse_mean: collapse/remove a dimension by averaging.
     - gal_dimension_collapse_number: collapse/remove a dimension by number.
+    - gal_dimension_collapse_minmax: collapse/remove a dimension by extremum.
     - gal_wcs_remove_dimension: Remove a dimension in the given WCS structure.
 
 ** Removed features
@@ -60,6 +105,9 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
   bug #54298: Table not writing array when there are no rows.
   bug #54312: Crash when CFITSIO doesn't have fits_is_reentrant function.
   bug #54346: Non '-I' or non '-L' strings in CPPFLAGS or LDFLAGS cause crash.
+  bug #54358: Arithmetic's where, not ignoring blank values in condition.
+  bug #54406: Insufficient sanity checks in mode symmetricity calculation.
+  bug #54430: BuildProgram fails with older Libtool versions on dash.
 
 
 
diff --git a/THANKS b/THANKS
index 69a9ebc..1dde839 100644
--- a/THANKS
+++ b/THANKS
@@ -36,10 +36,10 @@ support in Gnuastro. The list is ordered alphabetically (by 
family name).
     Brandon Invergo                      brandon@gnu.org
     Oryna Ivashtenko                     arinaivashtenko@gmail.com
     Aurélien Jarno                       aurelien.jarno@univ-lyon1.fr
-    Geoffry Krouchi                      geoffrey.krouchi@etu.univ-lyon1.fr
     Lee Kelvin                           l.s.kelvin@ljmu.ac.uk
     Brandon Kelly                        b.k.kelly@2017.ljmu.ac.uk
     Mohammad-Reza Khellat                moha.khe@gmail.com
+    Geoffry Krouchi                      geoffrey.krouchi@etu.univ-lyon1.fr
     Floriane Leclercq                    floriane.leclercq@univ-lyon1.fr
     Alan Lefor                           alefor@astr.tohoku.ac.jp
     Guillaume Mahler                     guillaume.mahler@univ-lyon1.fr
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index ba8ef38..e511e69 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -503,8 +503,8 @@ wrapper_for_filter(struct arithmeticparams *p, char *token, 
int operator)
 /*************            Other functions          *************/
 /***************************************************************/
 static int
-arithmetic_binary_conn_sanity_checks(gal_data_t *in, gal_data_t *conn,
-                                     char *operator)
+arithmetic_binary_sanity_checks(gal_data_t *in, gal_data_t *conn,
+                                char *operator)
 {
   int conn_int;
 
@@ -552,19 +552,14 @@ arithmetic_erode_dilate(struct arithmeticparams *p, char 
*token, int op)
   gal_data_t *conn = operands_pop(p, token);
   gal_data_t *in   = operands_pop(p, token);
 
-  /* Do the sanity checks and  */
+  /* Do the sanity checks. */
+  conn_int=arithmetic_binary_sanity_checks(in, conn, token);
+
+  /* Do the operation. */
   switch(op)
     {
-    case ARITHMETIC_OP_ERODE:
-      conn_int=arithmetic_binary_conn_sanity_checks(in, conn, "erode");
-      gal_binary_erode(in, 1, conn_int, 1);
-      break;
-
-    case ARITHMETIC_OP_DILATE:
-      conn_int=arithmetic_binary_conn_sanity_checks(in, conn, "dilate");
-      gal_binary_dilate(in, 1, conn_int, 1);
-      break;
-
+    case ARITHMETIC_OP_ERODE:  gal_binary_erode(in,  1, conn_int, 1); break;
+    case ARITHMETIC_OP_DILATE: gal_binary_dilate(in, 1, conn_int, 1); break;
     default:
       error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
             "problem. The operator code %d not recognized", __func__,
@@ -573,8 +568,6 @@ arithmetic_erode_dilate(struct arithmeticparams *p, char 
*token, int op)
 
   /* Push the result onto the stack. */
   operands_add(p, NULL, in);
-
-  /* Recall that`conn' was freed in the sanity check. */
 }
 
 
@@ -592,8 +585,7 @@ arithmetic_connected_components(struct arithmeticparams *p, 
char *token)
   gal_data_t *in   = operands_pop(p, token);
 
   /* Basic sanity checks. */
-  conn_int=arithmetic_binary_conn_sanity_checks(in, conn,
-                                                "connected-components");
+  conn_int=arithmetic_binary_sanity_checks(in, conn, token);
 
   /* Do the connected components labeling. */
   gal_binary_connected_components(in, &out, conn_int);
@@ -610,6 +602,29 @@ arithmetic_connected_components(struct arithmeticparams 
*p, char *token)
 
 
 static void
+arithmetic_fill_holes(struct arithmeticparams *p, char *token)
+{
+  int conn_int;
+
+  /* Pop the two necessary operands. */
+  gal_data_t *conn = operands_pop(p, token);
+  gal_data_t *in   = operands_pop(p, token);
+
+  /* Basic sanity checks. */
+  conn_int=arithmetic_binary_sanity_checks(in, conn, token);
+
+  /* Fill the holes */
+  gal_binary_holes_fill(in, conn_int, -1);
+
+  /* Push the result onto the stack. */
+  operands_add(p, NULL, in);
+}
+
+
+
+
+
+static void
 arithmetic_invert(struct arithmeticparams *p, char *token)
 {
   gal_data_t *in = operands_pop(p, token);
@@ -736,6 +751,14 @@ arithmetic_collapse(struct arithmeticparams *p, char 
*token, int operator)
       collapsed=gal_dimension_collapse_number(input, input->ndim-dim);
       break;
 
+    case ARITHMETIC_OP_COLLAPSE_MIN:
+      collapsed=gal_dimension_collapse_minmax(input, input->ndim-dim, 0);
+      break;
+
+    case ARITHMETIC_OP_COLLAPSE_MAX:
+      collapsed=gal_dimension_collapse_minmax(input, input->ndim-dim, 1);
+      break;
+
     default:
       error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
             "problem. The operator code %d is not recognized", __func__,
@@ -958,12 +981,18 @@ reversepolish(struct arithmeticparams *p)
             { op=ARITHMETIC_OP_DILATE;                nop=0;  }
           else if (!strcmp(token->v, "connected-components"))
             { op=ARITHMETIC_OP_CONNECTED_COMPONENTS;  nop=0;  }
+          else if (!strcmp(token->v, "fill-holes"))
+            { op=ARITHMETIC_OP_FILL_HOLES;            nop=0;  }
           else if (!strcmp(token->v, "invert"))
             { op=ARITHMETIC_OP_INVERT;                nop=0;  }
           else if (!strcmp(token->v, "interpolate-medianngb"))
             { op=ARITHMETIC_OP_INTERPOLATE_MEDIANNGB; nop=0;  }
           else if (!strcmp(token->v, "collapse-sum"))
             { op=ARITHMETIC_OP_COLLAPSE_SUM;          nop=0; }
+          else if (!strcmp(token->v, "collapse-min"))
+            { op=ARITHMETIC_OP_COLLAPSE_MIN;          nop=0; }
+          else if (!strcmp(token->v, "collapse-max"))
+            { op=ARITHMETIC_OP_COLLAPSE_MAX;          nop=0; }
           else if (!strcmp(token->v, "collapse-mean"))
             { op=ARITHMETIC_OP_COLLAPSE_MEAN;         nop=0; }
           else if (!strcmp(token->v, "collapse-number"))
@@ -1051,6 +1080,10 @@ reversepolish(struct arithmeticparams *p)
                   arithmetic_connected_components(p, token->v);
                   break;
 
+                case ARITHMETIC_OP_FILL_HOLES:
+                  arithmetic_fill_holes(p, token->v);
+                  break;
+
                 case ARITHMETIC_OP_INVERT:
                   arithmetic_invert(p, token->v);
                   break;
@@ -1060,6 +1093,8 @@ reversepolish(struct arithmeticparams *p)
                   break;
 
                 case ARITHMETIC_OP_COLLAPSE_SUM:
+                case ARITHMETIC_OP_COLLAPSE_MIN:
+                case ARITHMETIC_OP_COLLAPSE_MAX:
                 case ARITHMETIC_OP_COLLAPSE_MEAN:
                 case ARITHMETIC_OP_COLLAPSE_NUMBER:
                   arithmetic_collapse(p, token->v, op);
diff --git a/bin/arithmetic/arithmetic.h b/bin/arithmetic/arithmetic.h
index 4144006..4aef527 100644
--- a/bin/arithmetic/arithmetic.h
+++ b/bin/arithmetic/arithmetic.h
@@ -38,9 +38,12 @@ enum arithmetic_prog_operators
   ARITHMETIC_OP_ERODE,
   ARITHMETIC_OP_DILATE,
   ARITHMETIC_OP_CONNECTED_COMPONENTS,
+  ARITHMETIC_OP_FILL_HOLES,
   ARITHMETIC_OP_INVERT,
   ARITHMETIC_OP_INTERPOLATE_MEDIANNGB,
   ARITHMETIC_OP_COLLAPSE_SUM,
+  ARITHMETIC_OP_COLLAPSE_MIN,
+  ARITHMETIC_OP_COLLAPSE_MAX,
   ARITHMETIC_OP_COLLAPSE_MEAN,
   ARITHMETIC_OP_COLLAPSE_NUMBER,
 };
diff --git a/bin/arithmetic/operands.c b/bin/arithmetic/operands.c
index a4914ae..92ebcc4 100644
--- a/bin/arithmetic/operands.c
+++ b/bin/arithmetic/operands.c
@@ -43,7 +43,9 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 
 
-
+/**********************************************************************/
+/************            General info on operands       ***************/
+/**********************************************************************/
 size_t
 operands_num(struct arithmeticparams *p)
 {
@@ -58,6 +60,24 @@ operands_num(struct arithmeticparams *p)
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**********************************************************************/
+/************                Named operands             ***************/
+/**********************************************************************/
 static int
 operands_name_is_used_later(struct arithmeticparams *p, char *name)
 {
@@ -77,18 +97,59 @@ operands_name_is_used_later(struct arithmeticparams *p, 
char *name)
 
 
 
+/* Remove a name from the list of names and return the dataset it points
+   to. */
+static gal_data_t *
+operands_remove_name(struct arithmeticparams *p, char *name)
+{
+  gal_data_t *tmp, *removed=NULL, *prev=NULL;
+
+  /* Go over all the given names. */
+  for(tmp=p->named;tmp!=NULL;tmp=tmp->next)
+    {
+      if( !strcmp(tmp->name, name) )
+        {
+          removed=tmp;
+          if(prev) prev->next = tmp->next;
+          else     p->named   = tmp->next;
+        }
+
+      /* Set this node as the `prev' pointer. */
+      prev=tmp;
+    }
+
+  /* A small sanity check. */
+  if(removed==NULL)
+    error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
+          "problem. `removed' must not be NULL at this point", __func__,
+          PACKAGE_BUGREPORT);
+
+  /* Nothing in the list points to it now. So we can safely modify and
+     return it. */
+  free(removed->name);
+  removed->name=NULL;
+  return removed;
+}
+
+
+
+
+
 /* Pop a dataset and keep it in the `named' list for later use. */
 void
 operands_set_name(struct arithmeticparams *p, char *token)
 {
-  gal_data_t *tmp;
+  gal_data_t *tmp, *tofree;
   char *varname=&token[ SET_OPERATOR_PREFIX_LENGTH ];
 
-  /* Make sure the variable name hasn't been set before. */
+  /* If a dataset with this name already exists, it will be removed/deleted
+     so we can use the name for the newly designated dataset. */
   for(tmp=p->named; tmp!=NULL; tmp=tmp->next)
     if( !strcmp(varname, tmp->name) )
-      error(EXIT_FAILURE, 0, "`%s' was previously set as a name",
-            varname);
+      {
+        tofree=operands_remove_name(p, varname);
+        gal_data_free(tofree);
+      }
 
   /* Pop the top operand, then add it to the list of named datasets, but
      only if it is used in later tokens. If it isn't, free the popped
@@ -140,44 +201,6 @@ operands_is_name(struct arithmeticparams *p, char *token)
 
 
 
-/* Remove a name from the list of names and retrun the dataset it points
-   to. */
-static gal_data_t *
-operands_remove_name(struct arithmeticparams *p, char *name)
-{
-  gal_data_t *tmp, *removed=NULL, *prev=NULL;
-
-  /* Go over all the given names. */
-  for(tmp=p->named;tmp!=NULL;tmp=tmp->next)
-    {
-      if( !strcmp(tmp->name, name) )
-        {
-          removed=tmp;
-          if(prev) prev->next = tmp->next;
-          else     p->named   = tmp->next;
-        }
-
-      /* Set this node as the `prev' pointer. */
-      prev=tmp;
-    }
-
-  /* A small sanity check. */
-  if(removed==NULL)
-    error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
-          "problem. `removed' must not be NULL at this point", __func__,
-          PACKAGE_BUGREPORT);
-
-  /* Nothing in the list points to it now. So we can safely modify and
-     return it. */
-  free(removed->name);
-  removed->name=NULL;
-  return removed;
-}
-
-
-
-
-
 /* Return a copy of the named dataset. */
 static gal_data_t *
 operands_copy_named(struct arithmeticparams *p, char *name)
@@ -214,6 +237,25 @@ operands_copy_named(struct arithmeticparams *p, char *name)
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**********************************************************************/
+/************      Adding to and popping from stack     ***************/
+/**********************************************************************/
 void
 operands_add(struct arithmeticparams *p, char *filename, gal_data_t *data)
 {
diff --git a/bin/buildprog/Makefile.am b/bin/buildprog/Makefile.am
index 58d9b03..3f8f33e 100644
--- a/bin/buildprog/Makefile.am
+++ b/bin/buildprog/Makefile.am
@@ -59,7 +59,7 @@ EXTRA_DIST = main.h authors-cite.h args.h ui.h buildprog.h 
astbuildprog.conf.in
 # will change between the two (the `-I' or `-L' have been removed), so it
 # shouldn't be the same.
 astbuildprog.conf: $(top_srcdir)/bin/buildprog/astbuildprog.conf.in
-       cp $< $@
+       cat $< > $@
        infoadded="no";                                \
        for i in $(CPPFLAGS); do                       \
          v=$$(echo $$i | sed -e 's/^-I//');           \
diff --git a/bin/buildprog/buildprog.c b/bin/buildprog/buildprog.c
index 92f956d..298f86b 100644
--- a/bin/buildprog/buildprog.c
+++ b/bin/buildprog/buildprog.c
@@ -102,9 +102,10 @@ buildprog(struct buildprogparams *p)
     if( asprintf(&fullla, "%s/libgnuastro.la", LIBDIR)<0 )
       error(EXIT_FAILURE, 0, "%s: asprintf allocation", __func__);
 
-  /* Put the command to run into a string. */
-  if( asprintf(&command, "%s %s %s%s --mode=link gcc %s %s %s %s %s %s %s "
-               "-I%s %s -o %s",
+  /* Write the full Libtool command into a string (to run afterwards). */
+  if( asprintf(&command, "%s -c \"%s %s %s%s --mode=link gcc %s %s "
+               "%s %s %s %s %s -I%s %s -o %s\"",
+               GAL_CONFIG_GNULIBTOOL_SHELL,
                GAL_CONFIG_GNULIBTOOL_EXEC,
                p->cp.quiet ? "--quiet" : "",
                p->tag      ? "--tag="   : "",
diff --git a/bin/convolve/convolve.c b/bin/convolve/convolve.c
index ae23711..fae4a18 100644
--- a/bin/convolve/convolve.c
+++ b/bin/convolve/convolve.c
@@ -797,4 +797,10 @@ convolve(struct convolveparams *p)
   /* Save the output (which is in p->input) array. */
   gal_fits_img_write_to_type(p->input, cp->output, NULL, PROGRAM_NAME,
                              cp->type);
+
+  /* Write Convolve's parameters as keywords into the first extension of
+     the output. */
+  gal_fits_key_write_filename("input", p->filename, &cp->okeys, 1);
+  gal_fits_key_write_config(&cp->okeys, "Convolve configuration",
+                            "CONVOLVE-CONFIG", cp->output, "0");
 }
diff --git a/bin/convolve/ui.c b/bin/convolve/ui.c
index fe9cc53..356de22 100644
--- a/bin/convolve/ui.c
+++ b/bin/convolve/ui.c
@@ -539,6 +539,10 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct 
convolveparams *p)
   gal_options_print_state(&p->cp);
 
 
+  /* Prepare all the options as FITS keywords to write in output later. */
+  gal_options_as_fits_keywords(&p->cp);
+
+
   /* 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. */
diff --git a/bin/cosmiccal/astcosmiccal.conf b/bin/cosmiccal/astcosmiccal.conf
index bac2d94..b2644b1 100644
--- a/bin/cosmiccal/astcosmiccal.conf
+++ b/bin/cosmiccal/astcosmiccal.conf
@@ -22,18 +22,20 @@
 # ========
 #
 # The current default cosmological values in CosmicCalculator are taken
-# from the Planck 2015 results (paper XIII, A&A 594, A13 (2016), Table 4,
-# page 31, last column: "TT,TE,EE+lowP+lensing+ext").
+# from the Planck 2018 results (paper VI, arXiv:1807.06209, Table 2, last
+# column: "TT,TE,EE+lowE+lensing+BAO").
 #
-# http://www.aanda.org/articles/aa/full_html/2016/10/aa25830-15/aa25830-15.html
+# https://arxiv.org/abs/1807.06209
+# or
+# http://adsabs.harvard.edu/cgi-bin/bib_query?arXiv:1807.06209
 #
 # IMPORTANT NOTES: If you change these system-wide default values, please
 # change this comment and cite the source.
 
 # Input:
- H0              67.74
- olambda        0.6911
- omatter        0.3089
+ H0              67.66
+ olambda        0.6889
+ omatter        0.3111
  oradiation        0.0
 
 # Output:
diff --git a/bin/crop/crop.c b/bin/crop/crop.c
index 3f82835..0336c93 100644
--- a/bin/crop/crop.c
+++ b/bin/crop/crop.c
@@ -231,7 +231,7 @@ crop_mode_img(void *inparam)
           crp->centerfilled=onecrop_center_filled(crp);
 
           /* Add the final headers and close output FITS image: */
-          gal_fits_key_write_version(crp->outfits, NULL, PROGRAM_NAME);
+          gal_fits_key_write_version_in_ptr(NULL, NULL, crp->outfits);
           status=0;
           if( fits_close_file(crp->outfits, &status) )
             gal_fits_io_error(status, "CFITSIO could not close "
@@ -334,7 +334,7 @@ crop_mode_wcs(void *inparam)
           crp->centerfilled=onecrop_center_filled(crp);
 
           /* Write all the dependency versions and close the file. */
-          gal_fits_key_write_version(crp->outfits, NULL, PROGRAM_NAME);
+          gal_fits_key_write_version_in_ptr(NULL, NULL, crp->outfits);
           status=0;
           if( fits_close_file(crp->outfits, &status) )
             gal_fits_io_error(status, "CFITSIO could not close the "
diff --git a/bin/crop/onecrop.c b/bin/crop/onecrop.c
index a24ad29..6f3152f 100644
--- a/bin/crop/onecrop.c
+++ b/bin/crop/onecrop.c
@@ -808,12 +808,12 @@ onecrop(struct onecropparams *crp)
       /* A section has been added to the cropped image from this input
          image, so save the information of this image. */
       sprintf(basekeyname, "ICF%zu", crp->numimg);
-      gal_fits_key_write_filename(basekeyname, img->name, &headers);
+      gal_fits_key_write_filename(basekeyname, img->name, &headers, 0);
       sprintf(regionkey, "%sPIX", basekeyname);
       gal_fits_key_list_add_end(&headers, GAL_TYPE_STRING, regionkey,
                                 0, region, 0, "Range of pixels used for "
                                 "this output.", 0, NULL);
-      gal_fits_key_write(ofp, &headers);
+      gal_fits_key_write_in_ptr(&headers, ofp);
 
 
       /* Free the allocated array. */
diff --git a/bin/match/match.c b/bin/match/match.c
index 44c685c..011de6c 100644
--- a/bin/match/match.c
+++ b/bin/match/match.c
@@ -184,7 +184,7 @@ match_catalog_write_one(struct matchparams *p, gal_data_t 
*a, gal_data_t *b,
 
   /* Reverse the table and write it out. */
   gal_list_data_reverse(&cat);
-  gal_table_write(cat, NULL, p->cp.tableformat, p->cp.output, "MATCHED", 0);
+  gal_table_write(cat, NULL, p->cp.tableformat, p->out1name, "MATCHED", 0);
 }
 
 
@@ -308,6 +308,17 @@ match_catalog(struct matchparams *p)
 void
 match(struct matchparams *p)
 {
+  /* Do the correct type of matching. */
   if(p->mode==MATCH_MODE_CATALOG)
     match_catalog(p);
+
+  /* Write Match's configuration as keywords into the first extension of
+     the output. */
+  if(gal_fits_name_is_fits(p->out1name))
+    {
+      gal_fits_key_write_filename("input1", p->input1name, &p->cp.okeys, 1);
+      gal_fits_key_write_filename("input2", p->input2name, &p->cp.okeys, 1);
+      gal_fits_key_write_config(&p->cp.okeys, "Match configuration",
+                                "MATCH-CONFIG", p->out1name, "0");
+    }
 }
diff --git a/bin/match/ui.c b/bin/match/ui.c
index c4f4123..e7461ba 100644
--- a/bin/match/ui.c
+++ b/bin/match/ui.c
@@ -620,9 +620,8 @@ ui_read_columns(struct matchparams *p)
      names. */
   for(i=0;i<ccol1n;++i)
     {
-      gal_list_str_add(&cols1, strarr1[i], 0);
-      gal_list_str_add(&cols2, strarr2[i], 0);
-      strarr1[i]=strarr2[i]=NULL;  /* So they are not freed later. */
+      gal_list_str_add(&cols1, strarr1[i], 1);
+      gal_list_str_add(&cols2, strarr2[i], 1);
     }
   gal_list_str_reverse(&cols1);
   gal_list_str_reverse(&cols2);
@@ -645,9 +644,6 @@ ui_read_columns(struct matchparams *p)
   /* Free the extra spaces. */
   gal_list_str_free(cols1, 1);
   gal_list_str_free(cols2, 1);
-  gal_data_free(p->ccol1);
-  gal_data_free(p->ccol2);
-  p->ccol1=p->ccol2=NULL;
 }
 
 
@@ -697,7 +693,6 @@ ui_preparations_out_name(struct matchparams *p)
   /* Set the output file(s) name(s). */
   if(p->logasoutput)
     {
-      /* Set the logname (as output). */
       if(p->cp.output)
         gal_checkset_allocate_copy(p->cp.output, &p->logname);
       else
@@ -711,17 +706,24 @@ ui_preparations_out_name(struct matchparams *p)
         }
 
       /* Make sure a file with this name doesn't exist. */
-      gal_checkset_writable_remove(p->out1name, 0, p->cp.dontdelete);
+      gal_checkset_writable_remove(p->logname, 0, p->cp.dontdelete);
+
+      /* The main output name needs to be available in p->out1name (for the
+         final step when we want to write the input configurations as FITS
+         keywords). */
+      gal_checkset_allocate_copy(p->logname, &p->out1name);
     }
   else
     {
       if(p->outcols)
         {
-          if(p->cp.output==NULL)
-            p->cp.output = gal_checkset_automatic_output(&p->cp,
+          if(p->cp.output)
+            gal_checkset_allocate_copy(p->cp.output, &p->out1name);
+          else
+            p->out1name = gal_checkset_automatic_output(&p->cp,
                  p->input1name, ( p->cp.tableformat==GAL_TABLE_FORMAT_TXT
                                   ? "_matched.txt" : "_matched.fits") );
-          gal_checkset_writable_remove(p->cp.output, 0, p->cp.dontdelete);
+          gal_checkset_writable_remove(p->out1name, 0, p->cp.dontdelete);
         }
       else
         {
@@ -883,6 +885,13 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct 
matchparams *p)
 
   /* Read/allocate all the necessary starting arrays. */
   ui_preparations(p);
+
+
+  /* If the output is a FITS table, prepare all the options as FITS
+     keywords to write in output later. */
+  if(gal_fits_name_is_fits(p->out1name))
+      gal_options_as_fits_keywords(&p->cp);
+
 }
 
 
@@ -915,6 +924,8 @@ ui_free_report(struct matchparams *p, struct timeval *t1)
   free(p->out1name);
   free(p->out2name);
   free(p->cp.output);
+  gal_data_free(p->ccol1);
+  gal_data_free(p->ccol2);
 
   /* Print the final message.
   if(!p->cp.quiet)
diff --git a/bin/mkcatalog/columns.c b/bin/mkcatalog/columns.c
index bf9af4c..46a1d3e 100644
--- a/bin/mkcatalog/columns.c
+++ b/bin/mkcatalog/columns.c
@@ -1658,8 +1658,9 @@ columns_second_order(struct mkcatalog_passparams *pp, 
double *row,
 
     /* Error. */
     default:
-      error(EXIT_FAILURE, 0, "%s: a bug! Code %d not a recognized key",
-            __func__, key);
+      error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
+            "problem. %d is not a recognized key", __func__, PACKAGE_BUGREPORT,
+            key);
     }
 
   /* Return the output. */
@@ -1745,9 +1746,9 @@ columns_xy_extrema(struct mkcatalog_passparams *pp, 
size_t *coord, int key)
     case UI_KEY_MINZ: return coord[ndim-3] + 1;                   break;
     case UI_KEY_MAXZ: return coord[ndim-3] + tile->dsize[ndim-3]; break;
     default:
-      error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix "
-            "the problem. The value %d is not a recognized value",
-            __func__, PACKAGE_BUGREPORT, key);
+      error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
+            "problem. The value %d is not a recognized value", __func__,
+            PACKAGE_BUGREPORT, key);
     }
 
   /* Control should not reach here. */
diff --git a/bin/mkcatalog/mkcatalog.c b/bin/mkcatalog/mkcatalog.c
index 5e3a8f1..cfa385d 100644
--- a/bin/mkcatalog/mkcatalog.c
+++ b/bin/mkcatalog/mkcatalog.c
@@ -616,15 +616,10 @@ mkcatalog_write_outputs(struct mkcatalogparams *p)
   gal_list_str_t *comments;
 
 
-  /* OBJECT CATALOG
-     ============== */
+  /* OBJECT catalog */
   comments=mkcatalog_outputs_same_start(p, 0, "Detection");
 
-
-  /* Write objects catalog
-     ---------------------
-
-     Reverse the comments list (so it is printed in the same order here),
+  /* Reverse the comments list (so it is printed in the same order here),
      write the objects catalog and free the comments. */
   gal_list_str_reverse(&comments);
   gal_table_write(p->objectcols, comments, p->cp.tableformat, p->objectsout,
@@ -632,9 +627,7 @@ mkcatalog_write_outputs(struct mkcatalogparams *p)
   gal_list_str_free(comments, 1);
 
 
-
-  /* CLUMPS CATALOG
-     ============== */
+  /* CLUMPS catalog */
   if(p->clumps)
     {
       /* Make the comments. */
@@ -651,7 +644,17 @@ mkcatalog_write_outputs(struct mkcatalogparams *p)
       gal_list_str_free(comments, 1);
     }
 
-  /* Inform the user. */
+
+  /* Configuration information. */
+  if(gal_fits_name_is_fits(p->objectsout))
+    {
+      gal_fits_key_write_filename("input", p->objectsfile, &p->cp.okeys, 1);
+      gal_fits_key_write_config(&p->cp.okeys, "MakeCatalog configuration",
+                                "MKCATALOG-CONFIG", p->objectsout, "0");
+    }
+
+
+  /* Inform the user */
   if(!p->cp.quiet)
     {
       if(p->clumpsout==p->objectsout)
diff --git a/bin/mkcatalog/ui.c b/bin/mkcatalog/ui.c
index 95be85d..e254f31 100644
--- a/bin/mkcatalog/ui.c
+++ b/bin/mkcatalog/ui.c
@@ -1515,6 +1515,12 @@ ui_read_check_inputs_setup(int argc, char *argv[], 
struct mkcatalogparams *p)
   ui_preparations(p);
 
 
+  /* If the output is a FITS table, prepare all the options as FITS
+     keywords to write in output later. */
+  if(gal_fits_name_is_fits(p->objectsout))
+      gal_options_as_fits_keywords(&p->cp);
+
+
   /* Inform the user. */
   if(!p->cp.quiet)
     {
diff --git a/bin/mknoise/mknoise.c b/bin/mknoise/mknoise.c
index 4c1058a..9abbfe1 100644
--- a/bin/mknoise/mknoise.c
+++ b/bin/mknoise/mknoise.c
@@ -61,7 +61,7 @@ convertsaveoutput(struct mknoiseparams *p)
 
 
   /* Add the proper information to the header of the output: */
-  gal_fits_key_write_filename("INF", p->inputname, &headers);
+  gal_fits_key_write_filename("INF", p->inputname, &headers, 0);
   if( !isnan(p->background_mag) )
     {
       strcpy(keyname1, "BCKGRND");
@@ -97,7 +97,14 @@ convertsaveoutput(struct mknoiseparams *p)
 
   /* Save the output: */
   p->input=gal_data_copy_to_new_type_free(p->input, p->cp.type);
+  p->input->name="NOISED";
   gal_fits_img_write(p->input, p->cp.output, headers, PROGRAM_NAME);
+  p->input->name=NULL;
+
+  /* Write the configuration keywords. */
+  gal_fits_key_write_filename("input", p->inputname, &p->cp.okeys, 1);
+  gal_fits_key_write_config(&p->cp.okeys, "MakeNoise configuration",
+                            "MKNOISE-CONFIG", p->cp.output, "0");
 }
 
 
diff --git a/bin/mknoise/ui.c b/bin/mknoise/ui.c
index f713784..301d3f6 100644
--- a/bin/mknoise/ui.c
+++ b/bin/mknoise/ui.c
@@ -385,6 +385,10 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct 
mknoiseparams *p)
   gal_options_print_state(&p->cp);
 
 
+  /* Prepare all the options as FITS keywords to write in output later. */
+  gal_options_as_fits_keywords(&p->cp);
+
+
   /* 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. */
diff --git a/bin/mkprof/args.h b/bin/mkprof/args.h
index 99bddd2..6d9c224 100644
--- a/bin/mkprof/args.h
+++ b/bin/mkprof/args.h
@@ -89,8 +89,8 @@ struct argp_option program_options[] =
 
 
     {
-      "naxis",
-      UI_KEY_NAXIS,
+      "mergedsize",
+      UI_KEY_MERGEDSIZE,
       "INT[,INT,...]",
       0,
       "Merged image size along each dimension.",
diff --git a/bin/mkprof/astmkprof-3d.conf b/bin/mkprof/astmkprof-3d.conf
index 2df9040..9ccb1d0 100644
--- a/bin/mkprof/astmkprof-3d.conf
+++ b/bin/mkprof/astmkprof-3d.conf
@@ -21,7 +21,7 @@
  backhdu                          1
 
 # Output:
- naxis                  100,100,200
+ mergedsize             100,100,200
  oversample                       3
  circumwidth                      2
  type                       float32
diff --git a/bin/mkprof/astmkprof.conf b/bin/mkprof/astmkprof.conf
index bd727ce..b680412 100644
--- a/bin/mkprof/astmkprof.conf
+++ b/bin/mkprof/astmkprof.conf
@@ -21,7 +21,7 @@
  backhdu                   1
 
 # Output:
- naxis             1000,1000
+ mergedsize        1000,1000
  oversample                5
  circumwidth               2
  type                float32
diff --git a/bin/mkprof/mkprof.c b/bin/mkprof/mkprof.c
index c5ad3a7..409c786 100644
--- a/bin/mkprof/mkprof.c
+++ b/bin/mkprof/mkprof.c
@@ -598,6 +598,11 @@ mkprof_write(struct mkprofparams *p)
       /* Clean up */
       gal_data_free(out);
 
+      /* Write the configuration keywords. */
+      gal_fits_key_write_filename("input", p->catname, &p->cp.okeys, 1);
+      gal_fits_key_write_config(&p->cp.okeys, "MakeProfiles configuration",
+                                "MKPROF-CONFIG", p->mergedimgname, "0");
+
       /* In verbose mode, print the information. */
       if(!p->cp.quiet)
         {
diff --git a/bin/mkprof/ui.c b/bin/mkprof/ui.c
index 5fc7d22..495f61f 100644
--- a/bin/mkprof/ui.c
+++ b/bin/mkprof/ui.c
@@ -520,13 +520,13 @@ ui_read_check_only_options(struct mkprofparams *p)
           "(i.e., when the contents of `--mcol' must be interpretted as "
           "a magnitude, not brightness).");
 
-  /* Make sure no zero value is given for the `--naxis' option (only when
-     it is necessary). */
+  /* Make sure no zero value is given for the `--mergedsize' option (only
+     when it is necessary). */
   if(p->dsize && p->backname==NULL)
     for(i=0;p->dsize[i]!=GAL_BLANK_SIZE_T;++i)
       if(p->dsize[i]==0)
-        error(EXIT_FAILURE, 0, "values to `--naxes' option must not be "
-              "zero");
+        error(EXIT_FAILURE, 0, "values to `--mergedsize' option must not "
+              "be zero");
 }
 
 
@@ -1381,7 +1381,7 @@ ui_prepare_canvas(struct mkprofparams *p)
 
       /* Currently, things are only implemented for 2D or 3D. */
       if(p->ndim!=2 && p->ndim!=3)
-        error(EXIT_FAILURE, 0, "%zu numbers given to `--naxis', only 2 "
+        error(EXIT_FAILURE, 0, "%zu numbers given to `--naxis', only 2 or 3 "
               "values may be given", p->ndim);
 
       /* If any of the shift elements are zero, the others should be too!*/
@@ -1810,6 +1810,10 @@ ui_read_check_inputs_setup(int argc, char *argv[], 
struct mkprofparams *p)
   gal_options_print_state(&p->cp);
 
 
+  /* Prepare all the options as FITS keywords to write in output later. */
+  gal_options_as_fits_keywords(&p->cp);
+
+
   /* 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. */
diff --git a/bin/mkprof/ui.h b/bin/mkprof/ui.h
index 22ed6f1..446071a 100644
--- a/bin/mkprof/ui.h
+++ b/bin/mkprof/ui.h
@@ -54,7 +54,7 @@ enum option_keys_enum
   /* With short-option version. */
   UI_KEY_BACKGROUND      = 'k',
   UI_KEY_BACKHDU         = 'B',
-  UI_KEY_NAXIS           = 'x',
+  UI_KEY_MERGEDSIZE      = 'x',
   UI_KEY_CLEARCANVAS     = 'C',
   UI_KEY_KERNEL          = 'E',
   UI_KEY_OVERSAMPLE      = 's',
diff --git a/bin/noisechisel/noisechisel.c b/bin/noisechisel/noisechisel.c
index 060b865..593552e 100644
--- a/bin/noisechisel/noisechisel.c
+++ b/bin/noisechisel/noisechisel.c
@@ -202,6 +202,13 @@ noisechisel_output(struct noisechiselparams *p)
                              p->cp.output, keys, PROGRAM_NAME);
   p->std->name=NULL;
 
+
+  /* Write the configuration keywords. */
+  gal_fits_key_write_filename("input", p->inputname, &p->cp.okeys, 1);
+  gal_fits_key_write_config(&p->cp.okeys, "NoiseChisel configuration",
+                            "NOISECHISEL-CONFIG", p->cp.output, "0");
+
+
   /* Let the user know that the output is written. */
   if(!p->cp.quiet)
     printf("  - Output written to `%s'.\n", p->cp.output);
diff --git a/bin/noisechisel/ui.c b/bin/noisechisel/ui.c
index f147b2f..f48ea6e 100644
--- a/bin/noisechisel/ui.c
+++ b/bin/noisechisel/ui.c
@@ -739,6 +739,10 @@ ui_read_check_inputs_setup(int argc, char *argv[],
   gal_options_print_state(&p->cp);
 
 
+  /* Prepare all the options as FITS keywords to write in output later. */
+  gal_options_as_fits_keywords(&p->cp);
+
+
   /* 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. */
diff --git a/bin/segment/main.h b/bin/segment/main.h
index 3a72b3b..bb7842e 100644
--- a/bin/segment/main.h
+++ b/bin/segment/main.h
@@ -60,10 +60,10 @@ struct segmentparams
   char               *stdname;  /* File name of Standard deviation image. */
   char                *stdhdu;  /* HDU of Stanard deviation image.        */
   uint8_t            variance;  /* The input STD is actually variance.    */
-  uint8_t              minima;  /* Build clumps from their minima, maxima.*/
   uint8_t           rawoutput;  /* Output only object and clump labels.   */
 
   float            minskyfrac;  /* Undetected area min. frac. in tile.    */
+  uint8_t              minima;  /* Build clumps from their minima, maxima.*/
   size_t            snminarea;  /* Minimum area for segmentation.         */
   uint8_t             checksn;  /* Save the clump S/N values to a file.   */
   size_t          minnumfalse;  /* Min No. of det/seg for true quantile.  */
diff --git a/bin/segment/segment.c b/bin/segment/segment.c
index 189f7d0..c184e6f 100644
--- a/bin/segment/segment.c
+++ b/bin/segment/segment.c
@@ -1121,6 +1121,11 @@ segment_output(struct segmentparams *p)
       p->std->name=NULL;
     }
 
+  /* Write the configuration keywords. */
+  gal_fits_key_write_filename("input", p->inputname, &p->cp.okeys, 1);
+  gal_fits_key_write_config(&p->cp.okeys, "Segment configuration",
+                            "SEGMENT-CONFIG", p->cp.output, "0");
+
   /* Let the user know that the output is written. */
   if(!p->cp.quiet)
     printf("  - Output written to `%s'.\n", p->cp.output);
@@ -1228,7 +1233,7 @@ segment(struct segmentparams *p)
 
 
   /* If the user wanted to check the segmentation and hasn't called
-     `continueaftercheck', then stop NoiseChisel. */
+     `continueaftercheck', then stop Segment. */
   if(p->segmentationname && !p->continueaftercheck)
     ui_abort_after_check(p, p->segmentationname, NULL,
                          "showing all segmentation steps");
diff --git a/bin/segment/ui.c b/bin/segment/ui.c
index 246d336..07f341d 100644
--- a/bin/segment/ui.c
+++ b/bin/segment/ui.c
@@ -118,6 +118,7 @@ ui_initialize_options(struct segmentparams *p,
   p->medstd              = NAN;
   p->minstd              = NAN;
   p->maxstd              = NAN;
+  p->snquant             = NAN;
   p->clumpsnthresh       = NAN;
 
   /* Modify common options. */
@@ -894,6 +895,10 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct 
segmentparams *p)
   gal_options_print_state(&p->cp);
 
 
+  /* Prepare all the options as FITS keywords to write in output later. */
+  gal_options_as_fits_keywords(&p->cp);
+
+
   /* 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. */
diff --git a/bin/statistics/sky.c b/bin/statistics/sky.c
index 8b5bc62..8ab6a36 100644
--- a/bin/statistics/sky.c
+++ b/bin/statistics/sky.c
@@ -265,6 +265,9 @@ sky(struct statisticsparams *p)
   gal_tile_full_values_write(p->std_t, tl, !p->ignoreblankinsky, outname,
                              NULL, PROGRAM_NAME);
   p->sky_t->name = p->std_t->name = NULL;
+  gal_fits_key_write_filename("input", p->inputname, &p->cp.okeys, 1);
+  gal_fits_key_write_config(&p->cp.okeys, "Statistics configuration",
+                            "STATISTICS-CONFIG", outname, "0");
   if(!cp->quiet)
     printf("  - Written to `%s'.\n", outname);
 
diff --git a/bin/statistics/statistics.c b/bin/statistics/statistics.c
index 5cd1c63..9871220 100644
--- a/bin/statistics/statistics.c
+++ b/bin/statistics/statistics.c
@@ -255,6 +255,9 @@ statistics_interpolate_and_write(struct statisticsparams *p,
 
   /* Write the values. */
   gal_tile_full_values_write(values, &cp->tl, 1, output, NULL, PROGRAM_NAME);
+  gal_fits_key_write_filename("input", p->inputname, &p->cp.okeys, 1);
+  gal_fits_key_write_config(&p->cp.okeys, "Statistics configuration",
+                            "STATISTICS-CONFIG", output, "0");
 }
 
 
@@ -591,6 +594,15 @@ write_output_table(struct statisticsparams *p, gal_data_t 
*table,
   gal_table_write(table, comments, p->cp.tableformat, output, "TABLE", 0);
 
 
+  /* Write the configuration information if we have a FITS output. */
+  if(!strcmp(fix, "fits"))
+    {
+      gal_fits_key_write_filename("input", p->inputname, &p->cp.okeys, 1);
+      gal_fits_key_write_config(&p->cp.okeys, "Statistics configuration",
+                                "STATISTICS-CONFIG", output, "0");
+    }
+
+
   /* Let the user know, if we aren't in quiet mode. */
   if(!p->cp.quiet)
     printf("%s created.\n", output);
@@ -661,7 +673,6 @@ save_hist_and_or_cfp(struct statisticsparams *p)
   /* Set the output file name. */
   write_output_table(p, bins, suf, contents);
 
-
   /* Clean up. */
   gal_data_free(range);
 }
diff --git a/bin/statistics/ui.c b/bin/statistics/ui.c
index edf2e85..9ba99b9 100644
--- a/bin/statistics/ui.c
+++ b/bin/statistics/ui.c
@@ -791,8 +791,13 @@ void
 ui_preparations(struct statisticsparams *p)
 {
   gal_data_t *check;
+  int keepinputdir=p->cp.keepinputdir;
   struct gal_options_common_params *cp=&p->cp;
   struct gal_tile_two_layer_params *tl=&cp->tl;
+  char *checkbasename = p->cp.output ? p->cp.output : p->inputname;
+
+  /* Change `keepinputdir' based on if an output name was given. */
+  p->cp.keepinputdir = p->cp.output ? 1 : 0;
 
   /* Read the input. */
   if(p->isfits && p->hdu_type==IMAGE_HDU)
@@ -824,7 +829,7 @@ ui_preparations(struct statisticsparams *p)
       /* Make the tile check image if requested. */
       if(tl->checktiles)
         {
-          tl->tilecheckname=gal_checkset_automatic_output(cp, p->inputname,
+          tl->tilecheckname=gal_checkset_automatic_output(cp, checkbasename,
                                                           "_tiled.fits");
           check=gal_tile_block_check_tiles(tl->tiles);
           if(p->inputformat==INPUT_FORMAT_IMAGE)
@@ -841,7 +846,7 @@ ui_preparations(struct statisticsparams *p)
 
       /* Set the steps image name. */
       if(p->sky && p->checksky)
-        p->checkskyname=gal_checkset_automatic_output(cp, p->inputname,
+        p->checkskyname=gal_checkset_automatic_output(cp, checkbasename,
                                                       "_sky_steps.fits");
     }
 
@@ -875,6 +880,9 @@ ui_preparations(struct statisticsparams *p)
       if( !isnan(p->mirror) )             ++p->numoutfiles;
       if( p->histogram || p->cumulative ) ++p->numoutfiles;
     }
+
+  /* Reset `keepinputdir' to what it originally was. */
+  p->cp.keepinputdir=keepinputdir;
 }
 
 
@@ -949,6 +957,14 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct 
statisticsparams *p)
 
   /* Read/allocate all the necessary starting arrays. */
   ui_preparations(p);
+
+
+  /* Prepare all the options as FITS keywords to write in output
+     later. Note that in some modes, there is no output file, and
+     `ui_add_to_single_value' isn't yet prepared. */
+  if( (p->singlevalue && p->ontile) || p->sky || p->histogram \
+      || p->cumulative)
+    gal_options_as_fits_keywords(&p->cp);
 }
 
 
diff --git a/bin/warp/ui.c b/bin/warp/ui.c
index 1e052ad..2814683 100644
--- a/bin/warp/ui.c
+++ b/bin/warp/ui.c
@@ -929,6 +929,10 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct 
warpparams *p)
   gal_options_print_state(&p->cp);
 
 
+  /* Prepare all the options as FITS keywords to write in output later. */
+  gal_options_as_fits_keywords(&p->cp);
+
+
   /* 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. */
diff --git a/bin/warp/warp.c b/bin/warp/warp.c
index 7065ec6..fe89313 100644
--- a/bin/warp/warp.c
+++ b/bin/warp/warp.c
@@ -460,7 +460,7 @@ correct_wcs_save_output(struct warpparams *p)
     }
 
   /* Add the appropriate headers: */
-  gal_fits_key_write_filename("INF", p->inputname, &headers);
+  gal_fits_key_write_filename("INF", p->inputname, &headers, 0);
   for(i=0;i<9;++i)
     {
       sprintf(&keyword[i*FLEN_KEYWORD], "WMTX%zu_%zu", i/3+1, i%3+1);
@@ -470,9 +470,14 @@ correct_wcs_save_output(struct warpparams *p)
     }
 
   /* Save the output into the proper type and write it. */
-  if(p->cp.type!=p->output->type)
+  if(p->cp.type && p->cp.type!=p->output->type)
     p->output=gal_data_copy_to_new_type_free(p->output, p->cp.type);
   gal_fits_img_write(p->output, p->cp.output, headers, PROGRAM_NAME);
+
+  /* Write the configuration keywords. */
+  gal_fits_key_write_filename("input", p->inputname, &p->cp.okeys, 1);
+  gal_fits_key_write_config(&p->cp.okeys, "Warp configuration",
+                            "WARP-CONFIG", p->cp.output, "0");
 }
 
 
diff --git a/bootstrap.conf b/bootstrap.conf
index dc8120b..9c6d47b 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -226,6 +226,7 @@ gnulib_modules="
     gpl-3.0
     mbstok_r
     inttypes
+    system-posix
     git-version-gen
 "
 
diff --git a/configure.ac b/configure.ac
index 95f6d0e..771ca77 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,7 +50,7 @@ AC_CONFIG_MACRO_DIRS([bootstrapped/m4])
 
 # Library version, see the GNU Libtool manual ("Library interface versions"
 # section for the exact definition of each) for
-GAL_CURRENT=5
+GAL_CURRENT=6
 GAL_REVISION=0
 GAL_AGE=0
 GAL_LT_VERSION="${GAL_CURRENT}:${GAL_REVISION}:${GAL_AGE}"
@@ -112,11 +112,11 @@ AM_CONDITIONAL([COND_CHECK_WITH_VALGRIND], [test 
"x$enable_check_with_valgrind"
 # Set the compilation flags.
 AC_ARG_ENABLE(debug,
               [AS_HELP_STRING([--enable-debug],
-                              [No optimization, build with debug flags.])],
+                              [No optimization, debug flags, no shared lib.])],
               [AS_IF([test "x$enable_debug" != xno], [enable_debug=yes])],
               [enable_debug=no])
 AS_IF([test "x$enable_debug" = "xyes"],
-      [cflags_add="-g -O0"],
+      [cflags_add="-g -O0"; enable_shared=no],
       [cflags_add="-O3"])
 CFLAGS="-Wall $cflags_add $CFLAGS"
 CXXFLAGS="-Wall $cflags_add $CXXFLAGS"
@@ -278,6 +278,9 @@ AC_SEARCH_LIBS([wcspih], [wcs], [],
     [AC_MSG_ERROR([WCSLIB not found, cannot continue.])])
 
 
+
+
+
 # These are secondary tests for more fine-grained control in libraries that
 # have already been checked. We don't need to add them to the LIBS
 # variable, so we are using AC_CHECK_LIB for these tests.
@@ -311,27 +314,6 @@ AC_SUBST(HAVE_PTHREAD_BARRIER, [$has_pthread_barrier])
 
 
 
-
-# Gnulib checks:
-gl_INIT
-
-
-
-
-
-# Gnulib checks for the proper name for the C99 equivalent `restrict'
-# keyword and puts it in the `ac_cv_c_restrict' variable. If none exists,
-# it will put a `no' inside of this variable. As described in the output
-# `bootstrapped/m4/gnulib-common.m4', this is only necessary until Autoconf
-# 2.70 is released. Afterwards, we can use AC_C_RESTRICT.
-AS_IF([test "x$ac_cv_c_restrict" = "xno"],
-      [gal_restrict_replace=], [gal_restrict_replace=$ac_cv_c_restrict])
-AC_SUBST(RESTRICT_REPLACEMENT, [$gal_restrict_replace])
-
-
-
-
-
 # To add the help2man:
 AC_CHECK_PROG(has_help2man, help2man, [yes], [no])
 AM_CONDITIONAL([COND_HASHELP2MAN], [test "x$has_help2man" = "xyes"])
@@ -379,8 +361,11 @@ AC_SUBST(HAVE_LIBGIT2, [$has_libgit2])
 # Check the libtool executable on the system. Note that Gnuastro also ships
 # with a version of Libtool. We don't want Gnuastro's Libtool, here we want
 # to see if the system has libtool independent of Gnuastro so BuildProgram
-# can use it later.
+# can use it later. We also need to check some shells to run libtool within
+# them.
 AC_CHECK_PROG(has_libtool, libtool, [yes], [no])
+AC_CHECK_PROG(has_bash,    bash,    [yes], [no])
+AC_CHECK_PROG(has_zsh,     zsh,     [yes], [no])
 
 # If Libtool is present, make sure it is GNU Libtool
 AS_IF([test "x$has_libtool" = "xyes"],
@@ -399,10 +384,56 @@ AS_IF([test "x$has_gnulibtool" = "xyes"],
                [has_gnulibtool=yes; gnulibtool_exec=glibtool],
                [has_gnulibtool=no; anywarnings=yes] ) ])
 
-# Write the test results in the Makefiles and `config.h'.
-AM_CONDITIONAL([COND_HASGNULIBTOOL], [test "x$has_gnulibtool" = "xyes"])
-AC_DEFINE_UNQUOTED([GAL_CONFIG_GNULIBTOOL_EXEC], ["$gnulibtool_exec"],
-                   [The executable to call GNU Libtool])
+# Older versions of GNU Libtool have problems with the `dash' shell (a
+# minimalist shell) and will crash (due to not having the `+=' operator),
+# see bug #54430. So we need to check if the system's libtool and shell
+# (called by `sh' as in C's `system' function within BuildProgram) can work
+# with each other. If not, we need to search for Bash and tell BuildProgram
+# to use Bash instead of the default. But older versions of Bash also don't
+# support this operator, so we'll have to check with Bash is well.
+libtool_shell="none"
+AS_IF([test "x$has_gnulibtool" = "xyes"],
+      [
+        AC_MSG_CHECKING(for shell to use with libtool)
+
+        # Make a C source file and run Libtool on it with the specified
+        # shells.
+        outname=libtool_shell_test
+        cprog=libtool_shell_test.c
+        echo "#include <stdio.h>"                                 > $cprog
+        echo "int main(void){printf(\"success\\n\"); return 0;}" >> $cprog
+        ltargs="--quiet --tag=CC --mode=link $CC $cprog -O3 -o $outname"
+        AS_IF( sh -c "$gnulibtool_exec $ltargs" > /dev/null 2>&1,
+               [libtool_shell="sh"],
+               [AS_IF([test "x$has_bash" = "xyes"],
+                      [AS_IF(bash -c "$gnulibtool_exec $ltargs" > /dev/null 
2>&1,
+                             [libtool_shell="bash"]) ],
+                      [AS_IF([test "x$has_zsh" = "xyes"],
+                             [AS_IF(zsh -c "$gnulibtool_exec $ltargs" > 
/dev/null 2>&1,
+                                    [libtool_shell="zsh"]) ])
+                       ] )
+               ] )
+
+        # Clean up: note that no output might have been generated (when no
+        # proper shell was found). Therefore, for deleting the output file,
+        # we'll call `rm' with `-f' so it doesn't complain with an error in
+        # such cases.
+        rm $cprog
+        rm -f $outname
+        AC_MSG_RESULT($libtool_shell)
+      ])
+
+# If a good shell to call Libtool could be found, then Libtool is usable
+# within a program (BuildProgram in this case).
+AS_IF([test "x$libtool_shell" = "xnone"],
+      [usable_libtool=no; anywarnings=yes],
+      [
+        usable_libtool=yes
+        AC_DEFINE_UNQUOTED([GAL_CONFIG_GNULIBTOOL_SHELL], ["$libtool_shell"],
+                           [Shell program to use with GNU Libtool])
+        AC_DEFINE_UNQUOTED([GAL_CONFIG_GNULIBTOOL_EXEC], ["$gnulibtool_exec"],
+                           [The executable to call GNU Libtool])
+      ])
 
 
 
@@ -430,6 +461,12 @@ AM_CONDITIONAL([COND_HASGHOSTSCRIPT], [test 
"x$has_ghostscript" = "xyes"])
 
 
 
+# Gnulib checks:
+gl_INIT
+
+
+
+
 
 # Check if Gnulib tests should be done:
 AC_ARG_ENABLE([gnulibcheck],
@@ -442,6 +479,19 @@ AM_CONDITIONAL([COND_GNULIBCHECK], [test 
$enable_gnulibcheck = yes])
 
 
 
+# Gnulib checks for the proper name for the C99 equivalent `restrict'
+# keyword and puts it in the `ac_cv_c_restrict' variable. If none exists,
+# it will put a `no' inside of this variable. As described in the output
+# `bootstrapped/m4/gnulib-common.m4', this is only necessary until Autoconf
+# 2.70 is released. Afterwards, we can use AC_C_RESTRICT.
+AS_IF([test "x$ac_cv_c_restrict" = "xno"],
+      [gal_restrict_replace=], [gal_restrict_replace=$ac_cv_c_restrict])
+AC_SUBST(RESTRICT_REPLACEMENT, [$gal_restrict_replace])
+
+
+
+
+
 # Set the one general parameters:
 AC_DEFINE_UNQUOTED([CONF_POSTFIX], [".conf"], [Configuration file post fix.])
 AC_DEFINE_UNQUOTED([USERCONFIG_DIR], [".local/etc"], [User data dir.])
@@ -616,7 +666,7 @@ AS_IF([test $ayes = true ],
 
 # BuildProgram depends on the presence of GNU Libtool, if it isn't present,
 # then don't build it.
-AS_IF([test "x$has_gnulibtool" = "xno"], [enable_buildprog=no])
+AS_IF([test "x$usable_libtool" = "xno"], [enable_buildprog=no])
 
 
 
@@ -749,8 +799,8 @@ AS_IF([test x$enable_guide_message = xyes],
                AS_ECHO(["    version controlled directory to help in 
reproducibility."])
                AS_ECHO([]) ])
 
-        AS_IF([test "x$has_gnulibtool" = "xno"],
-              [AS_ECHO(["  - GNU Libtool, could not be found in your search 
path."])
+        AS_IF([test "x$usable_libtool" = "xno"],
+              [AS_ECHO(["  - GNU Libtool can't be used on this system (see 
below)."])
                AS_ECHO(["    Gnuastro's BuildProgram uses GNU libtool to link 
your source code"])
                AS_ECHO(["    with the various libraries (Gnuastro's 
dependencies). Therefore"])
                AS_ECHO(["    BuildProgram will not be built or installed. 
Please note that"])
@@ -759,12 +809,14 @@ AS_IF([test x$enable_guide_message = xyes],
                AS_ECHO(["    internal implementation of GNU Libtool to build 
its self. This"])
                AS_ECHO(["    warning is only to let you know that BuildProgram 
will not be"])
                AS_ECHO(["    part of this build. The executable names searched 
were \`libtool'"])
-               AS_ECHO(["    and \`glibtool'."])
+               AS_ECHO(["    and \`glibtool'. The shells searched were \`sh', 
\`bash' and \`zsh'."])
                AS_ECHO([])
-               AS_IF([test "x$has_libtool" = "xyes"],
-                     [AS_ECHO(["    -- A libtool implementation was found, but 
it isn't GNU."])
-                      AS_ECHO([])
-                     ])
+               AS_IF([test "x$has_gnulibtool" = "xyes"],
+                     [AS_ECHO(["    -- GNU Libtool is present, but couldn't be 
run in tested shells."])
+                      AS_ECHO([])],
+                     [AS_IF([test "x$has_libtool" = "xyes"],
+                            [AS_ECHO(["    -- A libtool implementation was 
found, but it isn't GNU."])
+                             AS_ECHO([]) ]) ])
               ])
 
         AS_IF([test "x$has_ghostscript" = "xno"],
diff --git a/developer-build b/developer-build
index e188c4d..63b622f 100755
--- a/developer-build
+++ b/developer-build
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! /bin/bash
 
 # This script will configure and build Gnuastro in parallel inside another
 # directory (to keep the source and build directories separate). By default
@@ -401,24 +401,14 @@ cd $build_dir
 
 
 # If a 'Makefile' doesn't exist, then configure Gnuastro.
-#
-# FOR DEBUGGING: uncomment the second half of this line. Gnuastro uses GNU
-# Libtool to build shared libraries for highly portable and maintainable
-# usage on a wide variety of systems. While this is great for binaries,
-# shared libraries can be a pain when debuggin. For this reason,
-# compilation of shared libraries can be turned off by specifying the
-# --disable-shared option to configure. With static libraries, compilation
-# (the 'make' command) will also significantly speed up. Also, by default
-# (in 'configure.ac'), we have set optimization flags which have to be
-# cancelled in debugging.
 if [ ! -f Makefile ]; then
 
     # Set the proper flags.
     if [ x$debug = x1 ]; then
-        confopts="--enable-debug --disable-shared"
+        confopts="--enable-debug"
     fi
     if [ x$valgrind = x1 ]; then
-        confopts="--enable-check-with-valgrind --disable-shared"
+        confopts="--enable-check-with-valgrind"
     fi
 
     # Run the configure script.
diff --git a/doc/announce-acknowledge.txt b/doc/announce-acknowledge.txt
index 49ab4ba..3e63c06 100644
--- a/doc/announce-acknowledge.txt
+++ b/doc/announce-acknowledge.txt
@@ -1,13 +1 @@
 Alphabetically ordered list to acknowledge in the next release.
-
-Valentina Abril-melgarejo
-Leindert Boogaard
-Nushkia Chamba
-Takashi Ichikawa
-Oryna Ivashtenko
-Geoffry Krouchi
-Alan Lefor
-Juan Molina Tobar
-Dmitrii Oparin
-Teymoor Saifollahi
-Jenny Sorce
diff --git a/doc/gnuastro.en.html b/doc/gnuastro.en.html
index b19f9da..e6a7b32 100644
--- a/doc/gnuastro.en.html
+++ b/doc/gnuastro.en.html
@@ -85,9 +85,9 @@ for entertaining and easy to read real world examples of using
 
 <p>
   The current stable release
-  is <a href="http://ftp.gnu.org/gnu/gnuastro/gnuastro-0.6.tar.gz";>Gnuastro
-  0.6</a> (June 4th, 2018).
-  Use <a href="http://ftpmirror.gnu.org/gnuastro/gnuastro-0.6.tar.gz";>a
+  is <a href="http://ftp.gnu.org/gnu/gnuastro/gnuastro-0.7.tar.gz";>Gnuastro
+  0.7</a> (August 8th, 2018).
+  Use <a href="http://ftpmirror.gnu.org/gnuastro/gnuastro-0.7.tar.gz";>a
   mirror</a> if possible.
 
   <!-- Comment the test release notice when the test release is not more
@@ -98,7 +98,7 @@ for entertaining and easy to read real world examples of using
   To stay up to date, please subscribe.</p>
 
 <p>For details of the significant changes in this release, please see the
-  <a 
href="https://git.savannah.gnu.org/cgit/gnuastro.git/plain/NEWS?id=gnuastro_v0.6";>NEWS</a>
+  <a 
href="https://git.savannah.gnu.org/cgit/gnuastro.git/plain/NEWS?id=gnuastro_v0.7";>NEWS</a>
   file.</p>
 
 <p>The
diff --git a/doc/gnuastro.fr.html b/doc/gnuastro.fr.html
index 62ba52e..7b9904d 100644
--- a/doc/gnuastro.fr.html
+++ b/doc/gnuastro.fr.html
@@ -85,15 +85,15 @@ h3 { clear: both; }
 <h3 id="download">Téléchargement</h3>
 
 <p>La version stable actuelle
-  est <a href="https://ftp.gnu.org/gnu/gnuastro/gnuastro-0.6.tar.gz";>Gnuastro
-  0.6</a> (sortie le 4 juin
-  2018). Utilisez <a 
href="https://ftpmirror.gnu.org/gnuastro/gnuastro-0.6.tar.gz";>un
+  est <a href="https://ftp.gnu.org/gnu/gnuastro/gnuastro-0.7.tar.gz";>Gnuastro
+  0.7</a> (sortie le 8 août
+  2018). Utilisez <a 
href="https://ftpmirror.gnu.org/gnuastro/gnuastro-0.7.tar.gz";>un
   miroir</a> si possible.  <br />Les nouvelles publications sont annoncées
   sur <a 
href="https://lists.gnu.org/mailman/listinfo/info-gnuastro";>info-gnuastro</a>.
   Abonnez-vous pour rester au courant.</p>
 
 <p>Les changements importants sont décrits dans le
-  fichier <a 
href="https://git.savannah.gnu.org/cgit/gnuastro.git/plain/NEWS?id=gnuastro_v0.6";>
+  fichier <a 
href="https://git.savannah.gnu.org/cgit/gnuastro.git/plain/NEWS?id=gnuastro_v0.7";>
   NEWS</a>.</p>
 
 <p>Le lien
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 061dab9..38bb4f5 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -297,7 +297,7 @@ Common program behavior
 * Tessellation::                Tile the dataset into non-overlapping bins.
 * Getting help::                Getting more information on the go.
 * Automatic output::            About automatic output names.
-* Output headers::              Common headers to all FITS outputs.
+* Output FITS files::           Common properties when outputs are FITS.
 
 Command-line
 
@@ -1710,21 +1710,23 @@ generic programs and libraries it is today.
 @c (alphabetical, except for the names in the paragraph above).
 In general, we would like to gratefully thank the following people for
 their useful and constructive comments and suggestions (in alphabetical
-order by family name): Marjan Akbari, Roland Bacon, Karl Berry, Leindert
-Boogaard, Nicolas Bouch@'e, Fernando Buitrago, Adrian Bunk, Rosa Calvi,
-Nushkia Chamba, Benjamin Clement, Nima Dehdilani, Antonio Diaz Diaz,
-Th@'er@`ese Godefroy, Madusha Gunawardhana, Stephen Hamer, Takashi
-Ichikawa, Ra@'ul Infante Sainz, Brandon Invergo, Aur@'elien Jarno, Lee
-Kelvin, Brandon Kelly, Mohammad-Reza Khellat, Floriane Leclercq, Alan
-Lefor, Guillaume Mahler, Francesco Montanari, Bertrand Pain, William Pence,
-Bob Proulx, Yahya Sefidbakht, Alejandro Serrano Borlaff, Lee Spitler,
-Richard Stallman, Ole Streicher, Alfred M. Szmidt, Michel Tallon, Juan
-C. Tello, @'Eric Thi@'ebaut, Ignacio Trujillo, David Valls-Gabaud, Aaron
-Watkins, Christopher Willmer, Sara Yousefi Taemeh, Johannes Zabl. The GNU
-French Translation Team is also managing the French version of the top
-Gnuastro webpage which we highly appreciate. Finally we should thank all
-the (sometimes anonymous) people in various online forums which patiently
-answered all our small (but important) technical questions.
+order by family name): Valentina Abril-melgarejo, Marjan Akbari, Roland
+Bacon, Karl Berry, Leindert Boogaard, Nicolas Bouch@'e, Fernando Buitrago,
+Adrian Bunk, Rosa Calvi, Nushkia Chamba, Benjamin Clement, Nima Dehdilani,
+Antonio Diaz Diaz, Th@'er@`ese Godefroy, Madusha Gunawardhana, Stephen
+Hamer, Takashi Ichikawa, Ra@'ul Infante Sainz, Brandon Invergo, Oryna
+Ivashtenko, Aur@'elien Jarno, Lee Kelvin, Brandon Kelly, Mohammad-Reza
+Khellat, Geoffry Krouchi, Floriane Leclercq, Alan Lefor, Guillaume Mahler,
+Juan Molina Tobar, Francesco Montanari, Dmitrii Oparin, Bertrand Pain,
+William Pence, Bob Proulx, Teymoor Saifollahi, Yahya Sefidbakht, Alejandro
+Serrano Borlaff, Jenny Sorce, Lee Spitler, Richard Stallman, Ole Streicher,
+Alfred M. Szmidt, Michel Tallon, Juan C. Tello, @'Eric Thi@'ebaut, Ignacio
+Trujillo, David Valls-Gabaud, Aaron Watkins, Christopher Willmer, Sara
+Yousefi Taemeh, Johannes Zabl. The GNU French Translation Team is also
+managing the French version of the top Gnuastro webpage which we highly
+appreciate. Finally we should thank all the (sometimes anonymous) people in
+various online forums which patiently answered all our small (but
+important) technical questions.
 
 All work on Gnuastro has been voluntary, but the authors are most grateful
 to the following institutions (in chronological order) for hosting us in
@@ -1934,7 +1936,7 @@ $ astmkprof -P
 
 # Output:
  type         float32     # Type of output: e.g., int16, float32, etc...
- naxis        1000,1000   # Number of pixels along first FITS axis.
+ mergedsize   1000,1000   # Number of pixels along first FITS axis.
  oversample   5           # Scale of oversampling (>0 and odd).
 
 [[[ ... Truncated lines ... ]]]
@@ -2017,7 +2019,7 @@ necessary parameters and runs MakeProfiles with the 
following command:
 
 @example
 
-$ astmkprof --prepforconv --naxis=500,500 --zeropoint=18.0 cat.txt
+$ astmkprof --prepforconv --mergedsize=500,500 --zeropoint=18.0 cat.txt
 MakeProfiles started on Sat Oct  6 16:26:56 953
   - 6 profiles read from cat.txt
   - Random number generator (RNG) type: mt19937
@@ -2182,7 +2184,8 @@ base=cat
 rm out.fits
 
 # Run MakeProfiles to create an oversampled FITS image.
-astmkprof --prepforconv --naxis=500,500 --zeropoint=18.0 "$base".txt
+astmkprof --prepforconv --mergedsize=500,500 --zeropoint=18.0   \
+          "$base".txt
 
 # Convolve the created image with the kernel.
 astconvolve --kernel=0_"$base".fits "$base".fits
@@ -2320,7 +2323,7 @@ This tutorial was first prepared for the ``Exploring the 
Ultra-Low Surface
 Brightness Universe'' workshop (November 2017) at the ISSI in Bern,
 Switzerland. It was further extended in the ``4th Indo-French Astronomy
 School'' (July 2018) organized by LIO, CRAL CNRS UMR5574, UCBL, and IUCAA
-in Lyon, France. We are very greatful to the organizers of these workshops
+in Lyon, France. We are very grateful to the organizers of these workshops
 and the attendees for the very fruitful discussions and suggestions that
 made this tutorial possible.
 
@@ -2710,8 +2713,8 @@ main(void)
   double area=4.03817;          /* Area of field (arcmin^2). */
   double z, adist, tandist;     /* Temporary variables.      */
 
-  /* Constants from Plank 2015 (Paper XIII, A&A 594, 2016) */
-  double H0=67.74, olambda=0.6911, omatter=0.3089, oradiation=0;
+  /* Constants from Plank 2018 (arXiv:1807.06209, Table 2) */
+  double H0=67.66, olambda=0.6889, omatter=0.3111, oradiation=0;
 
   /* Do the same thing for all redshifts (z) between 0.1 and 5. */
   for(z=0.1; z<5; z+=0.1)
@@ -3790,8 +3793,8 @@ $ wget $topurl/301/3716/6/frame-r-003716-6-0117.fits.bz2 
-Or.fits.bz2
 @noindent
 This server keeps the files in a Bzip2 compressed file format. So we'll
 first decompress it with the following command. By convention, compression
-programs delete the original file (compressed when un-compressing, or
-un-compressed when compressing). To keep the original file, you can use the
+programs delete the original file (compressed when uncompressing, or
+uncompressed when compressing). To keep the original file, you can use the
 @option{--keep} or @option{-k} option which is available in most
 compression programs for this job. Here, we don't need the compressed file
 any more, so we'll just let @command{bunzip} delete it for us and keep the
@@ -4888,7 +4891,7 @@ controlled source}). When @file{libgit2} is present, and 
Gnuastro's
 programs are run within a version controlled directory, outputs will
 contain the version number of the working directory's repository for future
 reproducibility. See the @command{COMMIT} keyword header in @ref{Output
-headers} for a discussion.
+FITS files} for a discussion.
 
 @item libjpeg
 @pindex libjpeg
@@ -5168,6 +5171,12 @@ $ sudo apt-get install ghostscript libtool-bin 
libjpeg-dev  \
                        libgsl0-dev libcfitsio-dev wcslib-dev
 @end example
 
+@noindent
+Gnuastro is @url{https://tracker.debian.org/pkg/gnuastro,packaged} in
+Debian (and thus some of its derivate operating systems). Just make sure it
+is the most recent version.
+
+
 @item @command{dnf}
 @itemx @command{yum} (Red Hat-based OSs: Red Hat, Fedora, CentOS, Scientific 
Linux, and etc)
 @cindex RHEL
@@ -5233,6 +5242,37 @@ $ sudo pacman -S ghostscript libtool libjpeg libtiff     
   \
                                                             \
                  gsl cfitsio wcslib
 @end example
+
+@item @command{zypper} (openSUSE and SUSE Linux Enterprise Server)
+@cindex openSUSE
+@cindex SUSE Linux Enterprise Server
+@cindex @command{zypper}
+@url{https://www.opensuse.org,openSUSE} is a community project supported by
+@url{https://www.suse.com,SUSE} with both stable and rolling releases.
+SUSE Linux Enterprise
+Server@footnote{@url{https://www.suse.com/products/server}} (SLES) is the
+commmercial offering which shares code and tools. Many additional packages
+are offered in the Build
+Service@footnote{@url{https://build.opensuse.org}}. openSUSE and SLES use
+@command{zypper} (cli) and YaST (GUI) for managing repositories and
+packages.
+
+@example
+$ sudo zypper install ghostscript_any libtool pkgconfig    \
+              cfitsio-devel gsl-devel libcurl-devel        \
+              libgit2-devel libjpeg62-devel libtiff-devel  \
+              wcslib-devel
+@end example
+@noindent
+When building Gnuastro, run the configure script with the following
+@code{CPPFLAGS} environment variable:
+
+@example
+$ ./configure CPPFLAGS="-I/usr/include/cfitsio"
+@end example
+
+@c Gnuastro is @url{https://software.opensuse.org/package/gnuastro,packaged}
+@c in @command{zypper}. Just make sure it is the most recent version.
 @end table
 
 Usually, when libraries are installed by operating system package managers,
@@ -5245,7 +5285,7 @@ of such problems and their solution are discussed below.
 @cartouche
 @noindent
 @strong{Not finding library during configuration:} If a library is
-installed, but during Gnuastro's @command{configre} step the library isn't
+installed, but during Gnuastro's @command{configure} step the library isn't
 found, then configure Gnuastro like the command below (correcting
 @file{/path/to/lib}). For more, see @ref{Known issues} and
 @ref{Installation directory}.
@@ -5512,7 +5552,7 @@ $ ./bootstrap --copy --gnulib-srcdir=$DEVDIR/gnulib
 @cindex GNU build system
 Since Gnulib and Autoconf archives are now available in your local
 directories, you don't need an internet connection every time you decide to
-remove all un-tracked files and redo the bootstrap (see box below). You can
+remove all untracked files and redo the bootstrap (see box below). You can
 also use the same command on any other project that uses Gnulib. All the
 necessary GNU C library functions, Autoconf macros and Automake inputs are
 now available along with the book figures. The standard GNU build system
@@ -5758,14 +5798,24 @@ program using the GNU build system (through the 
configure script).
 @cindex Valgrind
 @cindex Debugging
 @cindex GNU Debugger
-Compile/build Gnuastro with debugging information and no optimization. In
-order to allow more efficient programs when using Gnuastro (after the
+Compile/build Gnuastro with debugging information, no optimization and
+without shared libraries.
+
+In order to allow more efficient programs when using Gnuastro (after the
 installation), by default Gnuastro is built with a 3rd level (a very high
-level) optimization and no debugging information. But when there are
-crashes or un-expected behavior, debugging flags and disabling optimization
-can greatly help in localizing the problem. This configuration option is
-identical to manually calling the configuration script with
-@code{CFLAGS="-g -O0"}.
+level) optimization and no debugging information. By default, libraries are
+also built for static @emph{and} shared linking (see
+@ref{Linking}). However, when there are crashes or unexpected behavior,
+these three features can hinder the process of localizing the problem. This
+configuration option is identical to manually calling the configuration
+script with @code{CFLAGS="-g -O0" --disable-shared}.
+
+In the (rare) situations where you need to do your debugging on the shared
+libraries, don't use this option. Instead run the configure script by
+explicitly setting @code{CFLAGS} like this:
+@example
+$ ./configure CFLAGS="-g -O0"
+@end example
 
 @item --enable-check-with-valgrind
 @cindex Valgrind
@@ -5773,8 +5823,8 @@ Do the @command{make check} tests through Valgrind. 
Therefore, if any
 crashes or memory-related issues (segmentation faults in particular) occur
 in the tests, the output of Valgrind will also be put in the
 @file{tests/test-suite.log} file without having to manually modify the
-check scripts. This option will also build Gnuastro with no optimization
-and enable debugging flags (as if you also call @option{--enable-debug}).
+check scripts. This option will also activate Gnuastro's debug mode (see
+the @option{--enable-debug} configure-time option described above).
 
 Valgrind is free software. It is a program for easy checking of
 memory-related issues in programs. It runs a program within its own
@@ -6460,7 +6510,7 @@ as GDB, or Valgrind), disable optimization and also the 
building of shared
 libraries. Similar to running the configure script of below
 
 @example
-$ ./configure --enable-debug --disable-shared
+$ ./configure --enable-debug
 @end example
 
 Besides all the debugging advantages of building with this option, it will
@@ -6529,7 +6579,7 @@ to revert back to a different point in history. But 
Gnuastro also needs to
 bootstrap files and also your collaborators might (usually do!) find it too
 much of a burden to do the bootstrapping themselves. So it is convenient to
 have a tarball and PDF manual of the version you have installed (and are
-using in your reserach) handily available.
+using in your research) handily available.
 
 @item -h
 @itemx --help
@@ -6610,9 +6660,8 @@ this line:
 @end example
 
 @noindent
-In Texinfo, a line is commented with @code{@@c}. Therefore, un-comment
-this line by deleting the first two characters such that it changes
-to:
+In Texinfo, a line is commented with @code{@@c}. Therefore, uncomment this
+line by deleting the first two characters such that it changes to:
 
 @example
 @@afourpaper
@@ -6821,7 +6870,7 @@ command-line.
 * Tessellation::                Tile the dataset into non-overlapping bins.
 * Getting help::                Getting more information on the go.
 * Automatic output::            About automatic output names.
-* Output headers::              Common headers to all FITS outputs.
+* Output FITS files::           Common properties when outputs are FITS.
 @end menu
 
 @node Command-line, Configuration files, Common program behavior, Common 
program behavior
@@ -7602,7 +7651,7 @@ ignored.
 name. Therefore if two simultaneous calls (with @option{--log}) of a
 program are made in the same directory, the program will try to write to
 the same file. This will cause problems like unreasonable log file,
-un-defined behavior, or a crash.
+undefined behavior, or a crash.
 @end cartouche
 
 @cindex CPU threads, set number
@@ -7739,7 +7788,7 @@ parameters.
 In each step, there can also be a configuration file containing the common
 options in all the programs: @file{gnuastro.conf} (see @ref{Common
 options}). If options specific to one program are specified in this file,
-there will be un-recognized option errors, or unexpected behavior if the
+there will be unrecognized option errors, or unexpected behavior if the
 option has different behavior in another program. On the other hand, there
 is no problem with @file{astprogname.conf} containing common
 options@footnote{As an example, the @option{--setdirconf} and
@@ -8145,7 +8194,7 @@ are inclusive.
 @table @code
 @item u8
 @itemx uint8
-8-bit un-signed integers, range:@*
+8-bit unsigned integers, range:@*
 @mymath{[0\rm{\ to\ }2^8-1]} or @mymath{[0\rm{\ to\ }255]}.
 
 @item i8
@@ -8155,7 +8204,7 @@ are inclusive.
 
 @item u16
 @itemx uint16
-16-bit un-signed integers, range:@*
+16-bit unsigned integers, range:@*
 @mymath{[0\rm{\ to\ }2^{16}-1]} or @mymath{[0\rm{\ to\ }65535]}.
 
 @item i16
@@ -8165,7 +8214,7 @@ are inclusive.
 
 @item u32
 @itemx uint32
-32-bit un-signed integers, range:@* @mymath{[0\rm{\ to\ }2^{32}-1]} or
+32-bit unsigned integers, range:@* @mymath{[0\rm{\ to\ }2^{32}-1]} or
 @mymath{[0\rm{\ to\ }4294967295]}.
 
 @item i32
@@ -8175,7 +8224,7 @@ are inclusive.
 
 @item u64
 @itemx uint64
-64-bit un-signed integers, range@* @mymath{[0\rm{\ to\ }2^{64}-1]} or
+64-bit unsigned integers, range@* @mymath{[0\rm{\ to\ }2^{64}-1]} or
 @mymath{[0\rm{\ to\ }18446744073709551615]}.
 
 @item i64
@@ -9039,7 +9088,7 @@ list. We have other mailing lists and tools for those 
purposes, see
 
 
 
-@node Automatic output, Output headers, Getting help, Common program behavior
+@node Automatic output, Output FITS files, Getting help, Common program 
behavior
 @section Automatic output
 
 @cindex Automatic output file names
@@ -9094,15 +9143,57 @@ ABC01.jpg ABC02.jpg DEF01_detected.fits
 
 
 
-@node Output headers,  , Automatic output, Common program behavior
-@section Output headers
+@node Output FITS files,  , Automatic output, Common program behavior
+@section Output FITS files
 
+@cindex FITS
 @cindex Output FITS headers
 @cindex CFITSIO version on outputs
-The output FITS files created by Gnuastro's programs have some or all of
-the following standard keywords to keep the basic date and version
-information of Gnuastro, its dependencies and the pipeline that is using
-Gnuastro.
+The output of many of Gnuastro's programs are (or can be) FITS files. The
+FITS format has many useful features for storing scientific datasets
+(cubes, images and tables) along with a robust features for
+archivability. For more on this standard, please see @ref{Fits}.
+
+As a community convention described in @ref{Fits}, the first extension of
+all FITS files produced by Gnuastro's programs only contains the meta-data
+that is intended for the file's extension(s). For a Gnuastro program, this
+generic meta-data (that is stored as FITS keyword records) is its
+configuration when it produced this dataset: file name(s) of input(s) and
+option names, values and comments. Note that when the configuration is too
+trivial (only input filename, for example the program @ref{Table}) no
+meta-data is written in this extension.
+
+FITS keywords have the following limitations in regards to generic option
+names and values which are described below:
+
+@itemize
+@item
+If a keyword (option name) is longer than 8 characters, the first word in
+the record (80 character line) is @code{HIERARCH} which is followed by the
+keyword name.
+
+@item
+Values can be at most 75 characters, but for strings, this changes to 73
+(because of the two extra @key{'} characters that are necessary). However,
+if the value is a file name, containing slash (@key{/}) characters to
+separate directories, Gnuastro will break the value into multiple keywords.
+
+@item
+Keyword names ignore case, therefore they are all in capital letters.
+Therefore, if you want to use Grep to inspect these keywords, use the
+@option{-i} option, like the example below.
+
+@example
+$ astfits image_detected.fits -h0 | grep -i snquant
+@end example
+@end itemize
+
+The keywords above are classified (separated by an empty line and title) as
+a group titled ``ProgramName configuration''. This meta-data extension, as
+well as all the other extensions (which contain data), also contain have
+final group of keywords to keep the basic date and version information of
+Gnuastro, its dependencies and the pipeline that is using Gnuastro (if its
+under version control).
 
 @table @command
 
@@ -9182,10 +9273,10 @@ Here is one example of the last few lines of an example 
output.
               / Versions and date
 DATE    = '...'                / file creation date
 COMMIT  = 'v0-8-g547f6eb'      / Commit description in running dir.
-CFITSIO = '3.41    '           / CFITSIO version.
-WCSLIB  = '5.16    '           / WCSLIB version.
-GSL     = '2.3     '           / GNU Scientific Library version.
-GNUASTRO= '0.3'                / GNU Astronomy Utilities version.
+CFITSIO = '3.45    '           / CFITSIO version.
+WCSLIB  = '5.19    '           / WCSLIB version.
+GSL     = '2.5     '           / GNU Scientific Library version.
+GNUASTRO= '0.7     '           / GNU Astronomy Utilities version.
 END
 @end example
 
@@ -9282,19 +9373,20 @@ webpage} for the full text of all versions. Also see the
 for a nice introduction and history along with the full standard.
 
 @cindex Meta-data
-Other formats, for example a JPEG image, only have one image/dataset per
-file, however one great advantage of the FITS standard is that it allows
-you to keep multiple datasets (images or tables along with their meta-data)
-in one file. Each data + metadata is known as an extension, or more
-formally a header data unit or HDU, in the FITS standard. In theory the
-HDUs can be completely independent: you can have multiple images of
-different dimensions/sizes or tables as separate extensions in one
+Many common image formats, for example a JPEG, only have one image/dataset
+per file, however one great advantage of the FITS standard is that it
+allows you to keep multiple datasets (images or tables along with their
+separate meta-data) in one file. In the FITS standard, each data + metadata
+is known as an extension, or more formally a header data unit or HDU. The
+HDUs in a file can be completely independent: you can have multiple images
+of different dimensions/sizes or tables as separate extensions in one
 file. However, while the standard doesn't impose any constraints on the
 relation between the datasets, it is strongly encouraged to group data that
 are contextually related with each other in one file. For example an image
 and the table/catalog of objects and their measured properties in that
-image. Another example can be multiple images of one patch of sky in
-different colors (filters).
+image. Other examples can be images of one patch of sky in different colors
+(filters), or one raw telescope image along with its calibration data
+(tables or images).
 
 As discussed above, the extensions in a FITS file can be completely
 independent. To keep some information (meta-data) about the group of
@@ -9303,15 +9395,16 @@ convention: put no data in the first extension, so it 
is just
 meta-data. This extension can thus be used to store Meta-data regarding the
 whole file (grouping of extensions). Subsequent extensions may contain data
 along with their own separate meta-data. All of Gnuastro's programs also
-follow this convention: the main dataset (image or table) is in the second
-extension. See the example list of extension properties in @ref{Invoking
-astfits}.
+follow this convention: the main output dataset(s) are placed in the second
+(or later) extension(s). The first extension contains no data the program's
+configuration (input file name, along with all its option values) are
+stored as its meta-data, see @ref{Output FITS files}.
 
 The meta-data contain information about the data, for example which region
 of the sky an image corresponds to, the units of the data, what telescope,
-camera, and filter the data were taken with, the software that produced it,
-or it observation or processing date. Hence without the meta-data, the raw
-dataset is practically just a collection of numbers and really hard to
+camera, and filter the data were taken with, it observation date, or the
+software that produced it and its configuration. Without the meta-data, the
+raw dataset is practically just a collection of numbers and really hard to
 understand, or connect with the real world (other datasets). It is thus
 strongly encouraged to supplement your data (at any level of processing)
 with as much meta-data about your processing/science as possible.
@@ -11031,11 +11124,11 @@ value to this option is zero, no checking is done. 
This check is only
 applied when the cropped region(s) are defined by their center (not by the
 vertices, see @ref{Crop modes}).
 
-The units of the value are interpretted based on the @option{--mode} value
+The units of the value are interpreted based on the @option{--mode} value
 (in WCS or pixel units). The ultimate checked region size (in pixels) will
 be an odd integer around the center (converted from WCS, or when an even
 number of pixels are given to this option). In WCS mode, the value can be
-given as fractions, for example if the WCS untis are in degrees,
+given as fractions, for example if the WCS units are in degrees,
 @code{0.1/3600} will correspond to a check size of 0.1 arcseconds.
 
 Because survey regions don't often have a clean square or rectangle shape,
@@ -11512,7 +11605,8 @@ operators on the returned dataset.
 @cindex World Coordinate System (WCS)
 If any WCS is present, the returned dataset will also lack the respective
 dimension in its WCS matrix. Therefore, when the WCS is important for later
-processing, be sure that the input is aligned with the respective axises: all 
non-diagonal elements in the WCS matrix are zero.
+processing, be sure that the input is aligned with the respective axises:
+all non-diagonal elements in the WCS matrix are zero.
 
 @cindex IFU
 @cindex Data cubes
@@ -11544,6 +11638,16 @@ values, all the elements in the returned dataset will 
have a single value
 (the length of the collapsed dimension). Therefore this is mostly relevant
 when there are blank values in the dataset.
 
+@item collapse-min
+Similar to @option{collapse-sum}, but the returned dataset will have the
+same numeric type as the input and will contain the minimum value for each
+pixel along the collapsed dimension.
+
+@item collapse-max
+Similar to @option{collapse-sum}, but the returned dataset will have the
+same numeric type as the input and will contain the maximum value for each
+pixel along the collapsed dimension.
+
 @item erode
 @cindex Erosion
 Erode the foreground pixels (with value @code{1}) of the input dataset
@@ -11597,6 +11701,13 @@ If your input dataset doesn't have a binary type, but 
you know all its
 values are 0 or 1, you can use the @code{uint8} operator (below) to convert
 it to binary.
 
+@item fill-holes
+Flip background (0) pixels surrounded by foreground (1) in a binary
+dataset. This operator takes two operands (similar to
+@code{connected-components}): the first popped operand is the connectivity
+(to define a hole) and the second is the binary (0 or 1 valued) dataset to
+fill holes in.
+
 @item invert
 Invert an unsigned integer dataset. This is the only operator that ignores
 blank values (which are set to be the maximum values in the unsigned
@@ -11679,12 +11790,12 @@ $ astarithmetic modify.fits binary.fits if-true.fits 
where
 @end example
 
 The value of any pixel in @file{modify.fits} that corresponds to a non-zero
-pixel of @file{binary.fits} will be changed to the value of the same pixel
-in @file{if-true.fits} (this may also be a number). The 3rd and 2nd popped
-operands (@file{modify.fits} and @file{binary.fits} respectively, see
-@ref{Reverse polish notation}) have to have the same
-dimensions/size. @file{if-true.fits} can be either a number, or have the
-same dimension/size as the other two.
+@emph{and} non-blank pixel of @file{binary.fits} will be changed to the
+value of the same pixel in @file{if-true.fits} (this may also be a
+number). The 3rd and 2nd popped operands (@file{modify.fits} and
+@file{binary.fits} respectively, see @ref{Reverse polish notation}) have to
+have the same dimensions/size. @file{if-true.fits} can be either a number,
+or have the same dimension/size as the other two.
 
 The 2nd popped operand (@file{binary.fits}) has to have @code{uint8} (or
 @code{unsigned char} in standard C) type (see @ref{Numeric data types}). It
@@ -11774,7 +11885,7 @@ bitnot} will give @code{11010111}. Note that the 
bitwise operators only
 work on integer type datasets/numbers.
 
 @item uint8
-Convert the type of the popped operand to 8-bit un-signed integer type (see
+Convert the type of the popped operand to 8-bit unsigned integer type (see
 @ref{Numeric data types}). The internal conversion of C will be used.
 
 @item int8
@@ -11782,7 +11893,7 @@ Convert the type of the popped operand to 8-bit signed 
integer type (see
 @ref{Numeric data types}). The internal conversion of C will be used.
 
 @item uint16
-Convert the type of the popped operand to 16-bit un-signed integer type
+Convert the type of the popped operand to 16-bit unsigned integer type
 (see @ref{Numeric data types}). The internal conversion of C will be used.
 
 @item int16
@@ -11790,7 +11901,7 @@ Convert the type of the popped operand to 16-bit signed 
integer (see
 @ref{Numeric data types}). The internal conversion of C will be used.
 
 @item uint32
-Convert the type of the popped operand to 32-bit un-signed integer type
+Convert the type of the popped operand to 32-bit unsigned integer type
 (see @ref{Numeric data types}). The internal conversion of C will be used.
 
 @item int32
@@ -11798,7 +11909,7 @@ Convert the type of the popped operand to 32-bit signed 
integer type (see
 @ref{Numeric data types}). The internal conversion of C will be used.
 
 @item uint64
-Convert the type of the popped operand to 64-bit un-signed integer (see
+Convert the type of the popped operand to 64-bit unsigned integer (see
 @ref{Numeric data types}). The internal conversion of C will be used.
 
 @item float32
@@ -11812,20 +11923,25 @@ floating point (see @ref{Numeric data types}). The 
internal conversion of C
 will be used.
 
 @item set-AAA
-Set a name (all characters after the dash, @code{AAA} in the case shown
-here) for the first popped operand on the stack. The name can be any
-string, but avoid strings ending with standard filename suffixes (for
-example @file{.fits})@footnote{A dataset name like @file{a.fits} (which can
-be set with @command{set-a.fits}) will cause confusion in the the initial
-parser of Arithmetic. It will assume this name is a FITS file, and if it is
-used multiple times, Arithmetic will abort, complaining that you haven't
-provided enough HDUs.}. The named dataset will be freed from memory as soon
-as it is no longer needed in the rest of the command. This operator thus
+Set the characters after the dash (@code{AAA} in the case shown here) as a
+name for the first popped operand on the stack. The named dataset will be
+freed from memory as soon as it is no longer needed, or if the name is
+reset to refer to another dataset later in the command. This operator thus
 enables re-usability of a dataset without having to re-read it from a file
-everytime its necessary during a process.
+every time it is necessary during a process. When a dataset is necessary
+more than once, this operator can thus help simplify reading/writing on the
+command-line (thus avoiding potential bugs), while also speeding up the
+processing.
+
+Like all operators, this operator pops the top operand off of the main
+processing stack, but unlike other operands, it won't add anything back to
+the stack immediately. It will keep the popped dataset in memory through a
+separate list of named datasets (not on the main stack). That list will be
+used to add/copy any requested dataset to the main processing stack when
+the name is called.
 
 The name to give the popped dataset is part of the operator's name. For
-example the @code{set-a} operator of the command below, gives the name of
+example the @code{set-a} operator of the command below, gives the name
 ``@code{a}'' to the contents of @file{image.fits}. This name is then used
 instead of the actual filename to multiply the dataset by two.
 
@@ -11833,30 +11949,31 @@ instead of the actual filename to multiply the 
dataset by two.
 $ astarithmetic image.fits set-a a 2 x
 @end example
 
-This is a unique operator, because it doesn't actually do anything to the
-contents of the popped dataset, it just assigns a name to the dataset. This
-makes it very easy to use a single dataset on the command-line multiple
-times and avoid extra attempts at reading it into memory.
+The name can be any string, but avoid strings ending with standard filename
+suffixes (for example @file{.fits})@footnote{A dataset name like
+@file{a.fits} (which can be set with @command{set-a.fits}) will cause
+confusion in the the initial parser of Arithmetic. It will assume this name
+is a FITS file, and if it is used multiple times, Arithmetic will abort,
+complaining that you haven't provided enough HDUs.}.
 
 One example of the usefulness of this operator is in the @code{where}
 operator. For example, let's assume you want to mask all pixels larger than
 @code{5} in @file{image.fits} (extension number 1) with a NaN
-value. Without using this operator, you have to run
+value. Without setting a name for the dataset, you have to read the file
+two times from memory in a command like this:
 
 @example
 $ astarithmetic image.fits image.fits 5 gt nan where -g1
 @end example
 
 But with this operator you can simply give @file{image.fits} the name
-@code{i} and simplify the command above:
+@code{i} and simplify the command above to the more readable one below
+(which greatly helps when the filename is long):
 
 @example
 $ astarithmetic image.fits set-i   i i 5 gt nan where
 @end example
 
-This operator can thus help simplify reading/writing on the command-line
-(avoid potential bugs), while also speeding up your processing.
-
 @end table
 
 @cartouche
@@ -12132,22 +12249,20 @@ following sub-sections.
 @node Spatial domain convolution, Frequency domain and Fourier operations, 
Convolve, Convolve
 @subsection Spatial domain convolution
 
-The pixels in an input image represent different ``spatial''
-positions, therefore when convolution is done only using the actual
-input pixel values, we name the process as being done in the ``Spatial
-domain''. In particular this is in contrast to the ``frequency
-domain'' that we will discuss later in @ref{Frequency domain and
-Fourier operations}. In the spatial domain (and in realistic
-situations where the image and the convolution kernel don't extend to
-infinity), convolution is the process of changing the value of one
-pixel to the @emph{weighted} average of all the pixels in its
-@emph{neighborhood}.
-
-The `neighborhood' of each pixel (how many pixels in which direction)
-and the `weight' function (how much each neighboring pixel should
-contribute depending on its position) are given through a second image
-which is known as a ``kernel''@footnote{Also known as filter, here we
-will use `kernel'.}.
+The pixels in an input image represent different ``spatial'' positions,
+therefore when convolution is done only using the actual input pixel
+values, we name the process as being done in the ``Spatial domain''. In
+particular this is in contrast to the ``frequency domain'' that we will
+discuss later in @ref{Frequency domain and Fourier operations}. In the
+spatial domain (and in realistic situations where the image and the
+convolution kernel don't extend to infinity), convolution is the process of
+changing the value of one pixel to the @emph{weighted} average of all the
+pixels in its @emph{neighborhood}.
+
+The `neighborhood' of each pixel (how many pixels in which direction) and
+the `weight' function (how much each neighboring pixel should contribute
+depending on its position) are given through a second image which is known
+as a ``kernel''@footnote{Also known as filter, here we will use `kernel'.}.
 
 @menu
 * Convolution process::         More basic explanations.
@@ -12159,43 +12274,41 @@ will use `kernel'.}.
 
 In convolution, the kernel specifies the weight and positions of the
 neighbors of each pixel. To find the convolved value of a pixel, the
-central pixel of the kernel is placed on that pixel. The values of
-each overlapping pixel in the kernel and image are multiplied by each
-other and summed for all the kernel pixels. To have one pixel in the
-center, the sides of the convolution kernel have to be an odd
-number. This process effectively mixes the pixel values of each pixel
-with its neighbors, resulting in a blurred image compared to the
-sharper input image.
+central pixel of the kernel is placed on that pixel. The values of each
+overlapping pixel in the kernel and image are multiplied by each other and
+summed for all the kernel pixels. To have one pixel in the center, the
+sides of the convolution kernel have to be an odd number. This process
+effectively mixes the pixel values of each pixel with its neighbors,
+resulting in a blurred image compared to the sharper input image.
 
 @cindex Linear spatial filtering
-Formally, convolution is one kind of linear `spatial filtering' in
-image processing texts. If we assume that the kernel has @mymath{2a+1}
-and @mymath{2b+1} pixels on each side, the convolved value of a pixel
-placed at @mymath{x} and @mymath{y} (@mymath{C_{x,y}}) can be
-calculated from the neighboring pixel values in the input image
-(@mymath{I}) and the kernel (@mymath{K}) from
+Formally, convolution is one kind of linear `spatial filtering' in image
+processing texts. If we assume that the kernel has @mymath{2a+1} and
+@mymath{2b+1} pixels on each side, the convolved value of a pixel placed at
+@mymath{x} and @mymath{y} (@mymath{C_{x,y}}) can be calculated from the
+neighboring pixel values in the input image (@mymath{I}) and the kernel
+(@mymath{K}) from
 
 @dispmath{C_{x,y}=\sum_{s=-a}^{a}\sum_{t=-b}^{b}K_{s,t}\times{}I_{x+s,y+t}.}
 
 @cindex Correlation
 @cindex Convolution
-Any pixel coordinate that is outside of the image in the equation
-above will be considered to be zero. When the kernel is symmetric
-about its center the blurred image has the same orientation as the
-original image. However, if the kernel is not symmetric, the image
-will be affected in the opposite manner, this is a natural consequence
-of the definition of spatial filtering. In order to avoid this we can
-rotate the kernel about its center by 180 degrees so the convolved
-output can have the same original orientation. Technically speaking,
-only if the kernel is flipped the process is known
-@emph{Convolution}. If it isn't it is known as @emph{Correlation}.
+Any pixel coordinate that is outside of the image in the equation above
+will be considered to be zero. When the kernel is symmetric about its
+center the blurred image has the same orientation as the original
+image. However, if the kernel is not symmetric, the image will be affected
+in the opposite manner, this is a natural consequence of the definition of
+spatial filtering. In order to avoid this we can rotate the kernel about
+its center by 180 degrees so the convolved output can have the same
+original orientation. Technically speaking, only if the kernel is flipped
+the process is known @emph{Convolution}. If it isn't it is known as
+@emph{Correlation}.
 
-To be a weighted average, the sum of the weights (the pixels in the
-kernel) have to be unity. This will have the consequence that the
-convolved image of an object and un-convolved object will have the same
-brightness (see @ref{Flux Brightness and magnitude}), which is
-natural, because convolution should not eat up the object photons, it
-only disperses them.
+To be a weighted average, the sum of the weights (the pixels in the kernel)
+have to be unity. This will have the consequence that the convolved image
+of an object and unconvolved object will have the same brightness (see
+@ref{Flux Brightness and magnitude}), which is natural, because convolution
+should not eat up the object photons, it only disperses them.
 
 
 
@@ -12876,13 +12989,13 @@ image), where @mymath{k} is an integer, can thus be 
represented as:
 
 Note that in practice, our discrete data points are not found in this
 fashion. Each detector pixel (in an image for example) has an area and
-averages the signal it receives over that area, not a mathematical
-point as the Dirac @mymath{\delta} function defines. However, as long
-as the variation in the signal over one detector pixel is not
-significant, this can be a good approximation. Having put this issue
-to the side, we can now try to find the relation between the Fourier
-transforms of the un-sampled @mymath{f(l)} and the sampled
-@mymath{f_s(l)}. For a more clear notation, let's define:
+averages the signal it receives over that area, not a mathematical point as
+the Dirac @mymath{\delta} function defines. However, as long as the
+variation in the signal over one detector pixel is not significant, this
+can be a good approximation. Having put this issue to the side, we can now
+try to find the relation between the Fourier transforms of the unsampled
+@mymath{f(l)} and the sampled @mymath{f_s(l)}. For a more clear notation,
+let's define:
 
 @dispmath{F_s(\omega)\equiv{\cal F}[f_s]}
 
@@ -13766,7 +13879,7 @@ defined in @ref{Warping basics}, we have to `guess' the 
flux value of each
 pixel on the new grid based on the old grid, or re-sample it. Because of
 the `guessing', any form of warping on the data is going to degrade the
 image and mix the original pixel values with each other. So if an analysis
-can be done on an un-warped data image, it is best to leave the image
+can be done on an unwarped data image, it is best to leave the image
 untouched and pursue the analysis. However as discussed in @ref{Warp} this
 is not possible most of the times, so we have to accept the problem and
 re-sample the image.
@@ -14322,7 +14435,7 @@ the astronomical literature, researchers use a variety 
of methods to
 estimate the Sky value, so in @ref{Sky value misconceptions}) we review
 those and discuss their biases. From the definition of the Sky value, the
 most accurate way to estimate the Sky value is to run a detection algorithm
-(for example @ref{NoiseChisel}) over the dataset and use the un-detected
+(for example @ref{NoiseChisel}) over the dataset and use the undetected
 pixels. However, there is also a more crude method that maybe useful when
 good direct detection is not initially possible (for example due to too
 many cosmic rays in a shallow image). A more crude (but simpler method)
@@ -15652,7 +15765,7 @@ Use this file as the convolved image and don't do 
convolution (ignore
 @option{--kernel}). NoiseChisel will just check the size of the given
 dataset is the same as the input's size. If a wrong image (with the same
 size) is given to this option, the results (errors, bugs, and etc) are
-un-predictable. So please use this option with care and in a highly
+unpredictable. So please use this option with care and in a highly
 controlled environment, for example in the scenario discussed below.
 
 In almost all situations, as the input gets larger, the single most CPU
@@ -15774,7 +15887,7 @@ The quantile threshold to apply to the convolved image. 
The detection
 process begins with applying a quantile threshold to each of the tiles in
 the small tessellation. The quantile is only calculated for tiles that
 don't have any significant signal within them, see @ref{Quantifying signal
-in a tile}. Interpolation is then used to give a value to the un-successful
+in a tile}. Interpolation is then used to give a value to the unsuccessful
 tiles and it is finally smoothed.
 
 @cindex Quantile
@@ -15955,7 +16068,7 @@ only one pixel will be used for each tile (see 
@ref{Processing options}).
 The detection threshold: a multiple of the initial sky standard deviation
 added with the initial sky approximation (which you can inspect with
 @option{--checkdetsky}). This flux threshold is applied to the initially
-undetected regions on the un-convolved image. The background pixels that are
+undetected regions on the unconvolved image. The background pixels that are
 completely engulfed in a 4-connected foreground region are converted to
 background (holes are filled) and one opening (depth of 1) is applied over
 both the initially detected and undetected regions. The Signal to noise
@@ -15991,7 +16104,7 @@ threshold, this behavior (to abort NoiseChisel) can be 
disabled with
 @option{--continueaftercheck}.
 
 @item --minnumfalse=INT
-The minimum number of `pseudo-detections' over the un-detected regions to
+The minimum number of `pseudo-detections' over the undetected regions to
 identify a Signal-to-Noise ratio threshold. The Signal to noise ratio (S/N)
 of false pseudo-detections in each tile is found using the quantile of the
 S/N distribution of the psudo-detections over the undetected pixels in each
@@ -16114,7 +16227,9 @@ detection map is followed by a Sky and Sky standard 
deviation dataset
 (which are calculated from the binary image). By default (when
 @option{--rawoutput} isn't called), NoiseChisel will also subtract the Sky
 value from the input and save the sky-subtracted input as the first
-extension in the output.
+extension in the output with data. The zero-th extension (that contains no
+data), contains NoiseChisel's configuration as FITS keywords, see
+@ref{Output FITS files}.
 
 The name of the output file can be set by giving a value to
 @option{--output} (this is a common option between all programs and is
@@ -16443,12 +16558,12 @@ of this correction factor is irrelevant: because it 
uses the ambient noise
 applies that over the detected regions.
 
 A distribution's extremum (maximum or minimum) values, used in the new
-criteria, are strongly affected by scatter. On the other hand, the convolved
-image has much less scatter@footnote{For more on the effect of convolution
-on a distribution, see Section 3.1.1 of
+criteria, are strongly affected by scatter. On the other hand, the
+convolved image has much less scatter@footnote{For more on the effect of
+convolution on a distribution, see Section 3.1.1 of
 @url{https://arxiv.org/abs/1505.01664, Akhlaghi and Ichikawa
 [2015]}.}. Therefore @mymath{C_c-R_c} is a more reliable (with less
-scatter) measure to identify signal than @mymath{C-R} (on the un-convolved
+scatter) measure to identify signal than @mymath{C-R} (on the unconvolved
 image).
 
 Initially, the total clump signal-to-noise ratio of each clump was used,
@@ -16903,37 +17018,21 @@ created. This behavior can be disabled with 
@option{--continueaftercheck}.
 @subsubsection Segment output
 
 The main output of Segment are two label datasets (with integer types,
-separating the dataset's elements into different classes) with
-HDU/extension names of @code{CLUMPS} and @code{OBJECTS}. For a complete
-definition of clumps and objects, please see Section 3.2 of
-@url{https://arxiv.org/abs/1505.01664, Akhlaghi and Ichikawa [2015]} and
-@ref{Segmentation options}.
+separating the dataset's elements into different classes). They have
+HDU/extension names of @code{CLUMPS} and @code{OBJECTS}.
 
-The clumps are ``true'' local maxima (minima if @option{--minima} is
-called) and their surrounding pixels until a local minimum/maximum (caused
-by noise fluctuations, or another ``true'' clump). Therefore it may happen
-that some of the input detections aren't covered by clumps at all (very
-diffuse objects without any strong peak), while some objects may contain
-many clumps. Even in those that have clumps, there will be regions that are
-too diffuse. The diffuse regions (within the input detected regions) are
-given a negative label (-1) to help you separate them from the undetected
-regions (with a value of zero).
-
-Each clump is labeled with respect to its host object. Therefore, if an
-object has three clumps for example, the clumps within it have labels 1, 2
-and 3. As a result, if an initial detected region has multiple objects,
-each with a single clump, all the clumps will have a label of 1. The total
-number of clumps in the dataset is stored in the @code{NCLUMPS} keyword of
-the @code{CLUMPS} extension and printed in the verbose output of Segment
-(when @option{--quiet} is not called).
+Similar to all Gnuastro's FITS outputs, the zero-th extension/HDU of the
+main output file only contains header keywords and image or table. It
+contains the Segment input files and parameters (option names and values)
+as FITS keywords. Note that if an option name is longer than 8 characters,
+the keyword name is the second word. The first word is
+@code{HIERARCH}. Also note that according to the FITS standard, the keyword
+names must be in capital letters, therefore, if you want to use Grep to
+inspect these keywords, use the @option{-i} option, like the example below.
 
-The @code{OBJECTS} extension of the output will give a positive
-counter/label to every detected pixel in the input. As described in
-Akhlaghi and Ichikawa [2015], the true clumps are grown until a certain
-threshold. If the grown clumps touch other clumps and the connection is
-strong enough, they are considered part of the same @emph{object}. Once
-objects (grown clumps) are identified, they are grown to cover the whole
-detected area.
+@example
+$ astfits image_segmented.fits -h0 | grep -i snquant
+@end example
 
 @cindex DS9
 @cindex SAO DS9
@@ -16955,8 +17054,37 @@ The @code{OBJECTS} and @code{CLUMPS} extensions can be 
used as input into
 want to treat each clump separately, you can give a very large value (or
 even a NaN, which will always fail) to the @option{--gthresh} option (for
 example @code{--gthresh=1e10} or @code{--gthresh=nan}), see
-@ref{Segmentation options}. The options to configure the output of Segment
-are listed below:
+@ref{Segmentation options}.
+
+For a complete definition of clumps and objects, please see Section 3.2 of
+@url{https://arxiv.org/abs/1505.01664, Akhlaghi and Ichikawa [2015]} and
+@ref{Segmentation options}. The clumps are ``true'' local maxima (minima if
+@option{--minima} is called) and their surrounding pixels until a local
+minimum/maximum (caused by noise fluctuations, or another ``true''
+clump). Therefore it may happen that some of the input detections aren't
+covered by clumps at all (very diffuse objects without any strong peak),
+while some objects may contain many clumps. Even in those that have clumps,
+there will be regions that are too diffuse. The diffuse regions (within the
+input detected regions) are given a negative label (-1) to help you
+separate them from the undetected regions (with a value of zero).
+
+Each clump is labeled with respect to its host object. Therefore, if an
+object has three clumps for example, the clumps within it have labels 1, 2
+and 3. As a result, if an initial detected region has multiple objects,
+each with a single clump, all the clumps will have a label of 1. The total
+number of clumps in the dataset is stored in the @code{NCLUMPS} keyword of
+the @code{CLUMPS} extension and printed in the verbose output of Segment
+(when @option{--quiet} is not called).
+
+The @code{OBJECTS} extension of the output will give a positive
+counter/label to every detected pixel in the input. As described in
+Akhlaghi and Ichikawa [2015], the true clumps are grown until a certain
+threshold. If the grown clumps touch other clumps and the connection is
+strong enough, they are considered part of the same @emph{object}. Once
+objects (grown clumps) are identified, they are grown to cover the whole
+detected area.
+
+The options to configure the output of Segment are listed below:
 
 @table @option
 @item --continueaftercheck
@@ -17427,7 +17555,7 @@ intend to make apertures manually and not use a 
detection map (for example
 from @ref{Segment}), don't forget to use the @option{--upmaskfile} to give
 NoiseChisel's output (or any a binary map, marking detected pixels, see
 @ref{NoiseChisel output}) as a mask. Otherwise, the footprints may randomly
-fall over detections, giving higly skewed distributions, with wrong
+fall over detections, giving highly skewed distributions, with wrong
 upper-limit distributions. See The description of @option{--upmaskfile} in
 @ref{Upper-limit settings} for more.}.
 
@@ -18068,8 +18196,8 @@ two columns are the position of the first pixel in each 
random sampling of
 this particular object/clump. The the third column is the measured flux
 over that region. If the region overlapped with a detection or masked
 pixel, then its measured value will be a NaN (not-a-number). The total
-number of rows is thus un-known, but you can be sure that the number of
-rows with non-NaN measurements is the number given to the @option{--upnum}
+number of rows is thus unknown, but you can be sure that the number of rows
+with non-NaN measurements is the number given to the @option{--upnum}
 option.
 
 @end table
@@ -18317,7 +18445,7 @@ The magnitude of clumps or objects, see 
@option{--brightness}.
 @itemx --magnitudeerr
 The magnitude error of clumps or objects. The magnitude error is calculated
 from the signal-to-noise ratio (see @option{--sn} and @ref{Quantifying
-measurement limits}). Note that until now this error assumes un-correlated
+measurement limits}). Note that until now this error assumes uncorrelated
 pixel values and also does not include the error in estimating the aperture
 (or error in generating the labeled image).
 
@@ -18374,7 +18502,7 @@ as: @mymath{(\mu-\nu)/\sigma}.
 This can be a good measure to see how much you can trust the random
 measurements, or in other words, how accurately the regions with signal
 have been masked/detected. If the skewness is strong (and to the positive),
-then you can tell that you have a lot of un-detected signal in the dataset,
+then you can tell that you have a lot of undetected signal in the dataset,
 and therefore that the upper-limit measurement (and other measurements) are
 not reliable.
 
@@ -18685,7 +18813,7 @@ this log file.
 calls to Match. Therefore if a separate log is requested in two
 simultaneous calls to Match in the same directory, Match will try to write
 to the same file. This will cause problems like unreasonable log file,
-un-defined behavior, or a crash.
+undefined behavior, or a crash.
 @end cartouche
 
 @table @option
@@ -18716,7 +18844,7 @@ to retrieve your desired information and do the match 
at the same time.
 
 @item -l
 @itemx --logasoutput
-The output file will have the contents of the log file: indexs in the two
+The output file will have the contents of the log file: indexes in the two
 catalogs that match with each other along with their distance. See
 description above. When this option is called, a log file called
 @file{astmatch.txt} will not be created. With this option, the default
@@ -19321,14 +19449,13 @@ the atmospheric and instrument PSF in a continuous 
space and then it
 is sampled on the discrete pixels of the camera.
 
 @cindex PSF over-sample
-In order to more accurately simulate this process, the un-convolved
-image and the PSF are created on a finer pixel grid. In other words,
-the output image is a certain odd-integer multiple of the desired
-size, we can call this `oversampling'. The user can specify this
-multiple as a command-line option. The reason this has to be an odd
-number is that the PSF has to be centered on the center of its
-image. An image with an even number of pixels on each side does not
-have a central pixel.
+In order to more accurately simulate this process, the unconvolved image
+and the PSF are created on a finer pixel grid. In other words, the output
+image is a certain odd-integer multiple of the desired size, we can call
+this `oversampling'. The user can specify this multiple as a command-line
+option. The reason this has to be an odd number is that the PSF has to be
+centered on the center of its image. An image with an even number of pixels
+on each side does not have a central pixel.
 
 The image can then be convolved with the PSF (which should also be
 oversampled on the same scale). Finally, image can be sub-sampled to
@@ -19512,7 +19639,7 @@ $ astmkprof --ccol=RA_CENTER --ccol=DEC_CENTER 
--mode=wcs catalog.txt
 
 ## Make a 1500x1500 merged image (oversampled 500x500) image along
 ## with an individual image for all the profiles in catalog:
-$ astmkprof --individual --oversample 3 --naxis=500,500 catalog.txt
+$ astmkprof --individual --oversample 3 --mergedsize=500,500 cat.txt
 @end example
 
 @noindent
@@ -19538,8 +19665,8 @@ that image are used as the background value for every 
pixel. The flux value
 of each profile pixel will be added to the pixel in that background
 value. In this case, the values to all options relating to the output size
 and WCS will be ignored if specified (for example @option{--oversample},
-@option{--naxis}, and @option{--prepforconv}) on the command-line or in the
-configuration files.
+@option{--mergedsize}, and @option{--prepforconv}) on the command-line or
+in the configuration files.
 
 The sections below discuss the options specific to MakeProfiles based on
 context: the input catalog settings which can have many rows for different
@@ -19961,9 +20088,10 @@ A background image FITS file to build the profiles on. 
The extension that
 contains the image should be specified with the @option{--backhdu} option,
 see below. When a background image is specified, it will be used to derive
 all the information about the output image. Hence, the following options
-will be ignored: @option{--naxis}, @option{--oversample}, @option{--crpix},
-@option{--crval} (generally, all other WCS related parameters) and the
-output's data type (see @option{--type} in @ref{Input output options}).
+will be ignored: @option{--mergedsize}, @option{--oversample},
+@option{--crpix}, @option{--crval} (generally, all other WCS related
+parameters) and the output's data type (see @option{--type} in @ref{Input
+output options}).
 
 The image will act like a canvas to build the profiles on: profile pixel
 values will be summed with the background image pixel values. With the
@@ -20070,14 +20198,15 @@ file (individually) and no ``merged'' image of the 
input profiles is
 created.
 
 @item -x INT,INT
-@itemx --naxis=INT,INT
-The number of pixels along each dimension axis of the output in FITS
-order. This is before over-sampling. For example if you call MakeProfiles
-with @option{--naxis=100,150 --oversample=5} (assuming no shift due for
+@itemx --mergedsize=INT,INT
+The number of pixels along each axis of the output, in FITS order. This is
+before over-sampling. For example if you call MakeProfiles with
+@option{--mergedsize=100,150 --oversample=5} (assuming no shift due for
 later convolution), then the final image size along the first axis will be
 500 by 750 pixels. Fractions are acceptable as values for each dimension,
-however, they must reduce to an integer, so @option{--naxis=150/3,300/3} is
-acceptable but @option{--naxis=150/4,300/4} is not.
+however, they must reduce to an integer, so
+@option{--mergedsize=150/3,300/3} is acceptable but
+@option{--mergedsize=150/4,300/4} is not.
 
 When viewing a FITS image in DS9, the first FITS dimension is in the
 horizontal direction and the second is vertical. As an example, the image
@@ -20135,8 +20264,8 @@ number position: The center of a pixel has fractional 
value
 @item -m
 @itemx --nomerged
 Don't make a merged image. By default after making the profiles, they are
-added to a final image with side lengths specified by @option{--naxis}if
-they overlap with it.
+added to a final image with side lengths specified by @option{--mergedsize}
+if they overlap with it.
 
 @end table
 
@@ -23534,6 +23663,15 @@ Arithmetic program's @option{collapse-number} operator 
(which uses this
 function) in @ref{Arithmetic operators}.
 @end deftypefun
 
+@deftypefun {gal_data_t *} gal_dimension_collapse_minmax (gal_data_t 
@code{*in}, size_t @code{c_dim}, int @code{max1_min0})
+Collapse the input dataset (@code{in}) along the given dimension
+(@code{c_dim}, in C definition: starting from zero, from the slowest
+dimension), by using the largest/smallest non-blank value along that
+dimension. If @code{max1_min0} is non-zero, then the collapsed dataset will
+have the maximum value along the given dimension and if it is zero, the
+minimum.
+@end deftypefun
+
 @deffn {Function-like macro} GAL_DIMENSION_NEIGHBOR_OP (@code{index}, 
@code{ndim}, @code{dsize}, @code{connectivity}, @code{dinc}, @code{operation})
 Parse the neighbors of the element located at @code{index} and do the
 requested operation on them. This is defined as a macro to allow easy
@@ -24402,7 +24540,7 @@ types for reading arrays.
 
 @deftypefun int gal_array_name_recognized_multiext (char @code{*filename})
 Return 1 if the given file name corresponds to one of the recognized file
-types for reading arrays which may contain multiple extesions (for example
+types for reading arrays which may contain multiple extensions (for example
 FITS or TIFF) formats.
 @end deftypefun
 
@@ -24590,7 +24728,7 @@ information includes the following information
 @item
 If the program is run in a Git version controlled directory, Git's
 description is printed (see description under @code{COMMIT} in @ref{Output
-headers}).
+FITS files}).
 @item
 The calendar time that is stored in @code{rawtime} (@code{time_t} is C's
 calendar time format defined in @file{time.h}). You can calculate the time
@@ -24629,7 +24767,7 @@ If @code{filename} is a FITS file, the table extension 
will have the name
 When @code{colinfoinstdout!=0} and @code{filename==NULL} (columns are
 printed in the standard output), the dataset metadata will also printed in
 the standard output. When printing to the standard output, the column
-information can be piped into another program for futher processing and
+information can be piped into another program for further processing and
 thus the meta-data (lines starting with a @code{#}) must be ignored. In
 such cases, you only print the column values by passing @code{0} to
 @code{colinfoinstdout}.
@@ -24999,11 +25137,25 @@ the end of the list. Use this function if you want 
the keywords to be
 written in the same order that you add nodes to the list of keywords.
 @end deftypefun
 
-@deftypefun void gal_fits_key_write_filename (char @code{*keynamebase}, char 
@code{*filename}, gal_fits_list_key_t @code{**list})
+@deftypefun void gal_fits_key_list_reverse (gal_fits_list_key_t @code{**list})
+Reverse the input list of keywords.
+@end deftypefun
+
+@deftypefun void gal_fits_key_write_title_in_ptr (char @code{*title}, fitsfile 
@code{*fptr})
+Add two lines of ``title'' keywords to the given CFITSIO @code{fptr}
+pointer. The first line will be blank and the second will have the string
+in @code{title} roughly in the middle of the line (a fixed distance from
+the start of the keyword line). A title in the list of keywords helps in
+classifying the keywords into groups and inspecting them by eye. If
+@code{title==NULL}, this function won't do anything.
+@end deftypefun
+
+@deftypefun void gal_fits_key_write_filename (char @code{*keynamebase}, char 
@code{*filename}, gal_fits_list_key_t @code{**list}, int @code{top1end0})
 Put @file{filename} into the @code{gal_fits_list_key_t} list (possibly
 broken up into multiple keywords) to later write into a HDU header. The
 @code{keynamebase} string will be appended with a @code{_N} (N>0) and used
-as the keyword name.
+as the keyword name. If @code{top1end0!=0}, then the keywords containing
+the filename will be added to the top of the list.
 
 The FITS standard sets a maximum length for the value of a keyword. This
 creates problems with file names (which include directories). Because file
@@ -25021,17 +25173,29 @@ keyword lines along with a comment @code{WCS 
information} before writing
 each keyword record.
 @end deftypefun
 
-@deftypefun void gal_fits_key_write (fitsfile @code{*fptr}, 
gal_fits_list_key_t @code{**keylist})
-Write the list of keywords in @code{keylist} into the CFITSIO
-@code{fitsfile}.
+@deftypefun void gal_fits_key_write (gal_fits_list_key_t @code{**keylist}, 
char @code{*title}, char @code{*filename}, char @code{*hdu})
+Write the list of keywords in @code{keylist} into the @code{hdu} extension
+of the file called @code{filename} (it must already exist).
+@end deftypefun
+
+@deftypefun void gal_fits_key_write_in_ptr (gal_fits_list_key_t 
@code{**keylist}, fitsfile @code{*fptr})
+Write the list of keywords in @code{keylist} into the given CFITSIO
+@code{fitsfile} pointer.
+@end deftypefun
+
+@deftypefun void gal_fits_key_write_version (gal_fits_list_key_t 
@code{**keylist}, char @code{*title}, char @code{*filename}, char @code{*hdu})
+Write the (optional, when @code{keylist!=NULL}) given list of keywords
+under the optional FITS keyword @code{title}, then print all the important
+version and date information. This is basically, just a wrapper over
+@code{gal_fits_key_write_version_in_ptr}.
 @end deftypefun
 
-@deftypefun void gal_fits_key_write_version (fitsfile @code{*fptr}, 
gal_fits_list_key_t @code{*headers}, char @code{*program_name})
+@deftypefun void gal_fits_key_write_version_in_ptr (gal_fits_list_key_t 
@code{**keylist}, char @code{*title}, fitsfile @code{*fptr})
 Write or update (all the) keyword(s) in @code{headers} into the FITS
 pointer, but also the date, name of your program (@code{program_name}),
 along with the versions of CFITSIO, WCSLIB (when available), GSL, Gnuastro,
 and (the possible) commit information into the header as described in
-@ref{Output headers}.
+@ref{Output FITS files}.
 
 Since the data processing depends on the versions of the libraries you have
 used, it is strongly recommended to include this information in every FITS
@@ -25039,6 +25203,22 @@ output. @code{gal_fits_img_write} and 
@code{gal_fits_tab_write} will
 automatically use this function.
 @end deftypefun
 
+@deftypefun void gal_fits_key_write_config (gal_fits_list_key_t 
@code{**keylist}, char @code{*title}, char @code{*extname}, char 
@code{*filename}, char @code{*hdu})
+Write the given keyword list (@code{keylist}) into the @code{hdu} extension
+of @code{filename}, ending it with version information. This function will
+write @code{extname} as the name of the extension (value to the standard
+@code{EXTNAME} FITS keyword). The list of keywords will then be printed
+under a title called @code{title}.
+
+This function is used by many Gnuastro programs and is primarily intended
+for writing configuration settings of a program into the zero-th extension
+of their FITS outputs (which is empty when the FITS file is created by
+Gnuastro's program and this library).
+@end deftypefun
+
+
+
+
 
 @node FITS arrays, FITS tables, FITS header keywords, FITS files
 @subsubsection FITS arrays (images)
@@ -25355,9 +25535,9 @@ standard output (command-line). When 
@code{colinfoinstdout!=0} and
 @code{filename==NULL} (columns are printed in the standard output), the
 dataset metadata will also printed in the standard output. When printing to
 the standard output, the column information can be piped into another
-program for futher processing and thus the meta-data (lines starting with a
-@code{#}) must be ignored. In such cases, you only print the column values
-by passing @code{0} to @code{colinfoinstdout}.
+program for further processing and thus the meta-data (lines starting with
+a @code{#}) must be ignored. In such cases, you only print the column
+values by passing @code{0} to @code{colinfoinstdout}.
 @end deftypefun
 
 
@@ -25424,7 +25604,7 @@ internet. For more on this file format, and a 
comparison with others,
 please see @ref{Recognized file formats}.
 
 For scientific purposes, the lossy compression and very limited dynamic
-range (8-bit integers) make JPEG very un-attractive for storing of valuable
+range (8-bit integers) make JPEG very unattractive for storing of valuable
 data. However, because of its commonality, it will inevitably be needed in
 some situations. The functions here can be used to read and write JPEG
 images into Gnuastro's @ref{Generic data container}. If the JPEG file has
@@ -27547,11 +27727,11 @@ pixels will have a value of @code{-1}. The total 
number of holes will be
 written where @code{numholes} points to.
 @end deftypefun
 
-@deftypefun void gal_binary_holes_fill (gal_data_t @code{*input}, int 
@code{connectivity})
-Fill all the holes (0 valued pixels surrounded by 1 valued pixels) within a
-region of the binary @code{input} dataset. The connectivity of the holes
-can be set with @code{connectivity}. This function currently only works on
-a 2D dataset.
+@deftypefun void gal_binary_holes_fill (gal_data_t @code{*input}, int 
@code{connectivity}, size_t @code{maxsize})
+Fill all the holes (0 valued pixels surrounded by 1 valued pixels) of the
+binary @code{input} dataset. The connectivity of the holes can be set with
+@code{connectivity}. Holes larger than @code{maxsize} are not filled. This
+function currently only works on a 2D dataset.
 @end deftypefun
 
 @node Labeled datasets, Convolution functions, Binary datasets, Gnuastro 
library
@@ -27625,7 +27805,7 @@ easy (non-confusing) access to the indexs of each 
(meaningful) label.
 value of zero, then the maximum value in the input (largest label) will be
 found and used. Therefore if it is given, but smaller than the actual
 number of labels, this function may/will crash (it will write in
-un-allocated space). @code{numlabs} is therefore useful in a highly
+unallocated space). @code{numlabs} is therefore useful in a highly
 optimized/checked environment.
 
 For example, if the returned array is called @code{indexs}, then
@@ -28100,7 +28280,7 @@ blank. To see if any blank (non-interpolated) elements 
remain, you can use
 @cindex libgit2
 Git is one of the most common tools for version control and it can often be
 useful during development, for example see @code{COMMIT} keyword in
-@ref{Output headers}. At installation time, Gnuastro will also check for
+@ref{Output FITS files}. At installation time, Gnuastro will also check for
 the existence of libgit2, and store the value in the
 @code{GAL_CONFIG_HAVE_LIBGIT2}, see @ref{Configuration information} and
 @ref{Optional dependencies}. @file{gnuastro/git.h} includes
@@ -28115,8 +28295,8 @@ commit description (similar to Gnuastro's unofficial 
version number, see
 directory, it will add a `@code{-dirty}' prefix to the description. When
 there is no tagged point in the previous commit, this function will return
 a uniquely abbreviated commit object as fallback. This function is used for
-generating the value of the @code{COMMIT} keyword in @ref{Output
-headers}. The output string is similar to the output of the following
+generating the value of the @code{COMMIT} keyword in @ref{Output FITS
+files}. The output string is similar to the output of the following
 command:
 
 @example
@@ -29054,7 +29234,7 @@ programming}.
 The last two conventions are not common and might benefit from a short
 discussion here. With a good experience in advanced text editor operations,
 the last two are redundant for a professional developer. However, recall
-that Gnuastro aspires to be friendly to un-familiar, and un-experienced (in
+that Gnuastro aspires to be friendly to unfamiliar, and inexperienced (in
 programming) eyes. In other words, as discussed in @ref{Science and its
 tools}, we want the code to appear welcoming to someone who is completely
 new to coding (and text editors) and only has a scientific curiosity.
@@ -29201,7 +29381,7 @@ parameters while @code{p->threshold} is in the 
program's parameters.
 @cindex Operator, structure de-reference
 With this basic root structure, source code of functions can potentially
 become full of structure de-reference operators (@command{->}) which can
-make the code very un-readable. In order to avoid this, whenever a
+make the code very unreadable. In order to avoid this, whenever a
 structure element is used more than a couple of times in a function, a
 variable of the same type and with the same name (so it can be searched) as
 the desired structure element should be defined with the value of the root
@@ -29571,7 +29751,7 @@ significantly slow down the compilation (the 
@command{make} command). So
 during development it is recommended to configure Gnuastro as follows:
 
 @example
-$ ./configure --enable-debug --disable-shared
+$ ./configure --enable-debug
 @end example
 
 @noindent
@@ -30513,7 +30693,7 @@ popular graphic user interface for GNU/Linux systems), 
version 3. For GNOME
 make it your self (with @command{mkdir}). Using your favorite text editor,
 you can now create @file{~/.local/share/applications/saods9.desktop} with
 the following contents. Just don't forget to correct @file{BINDIR}. If you
-would also like to have ds9's logo/icon in GNOME, download it, un-comment
+would also like to have ds9's logo/icon in GNOME, download it, uncomment
 the @code{Icon} line, and write its address in the value.
 
 @example
diff --git a/doc/release-checklist.txt b/doc/release-checklist.txt
index 76f2660..5a13694 100644
--- a/doc/release-checklist.txt
+++ b/doc/release-checklist.txt
@@ -5,6 +5,13 @@ This file is primarily intended for the Gnuastro maintainer 
and lists the
 set of operations to do for making each release. This should be done after
 all the commits needed for this release have been completed.
 
+ - [STABLE] Run a spell-check (in emacs, with `M-x ispell') on the new
+   parts of the book. You can put them in a test file with this command,
+   just replace X.X with the previous version:
+
+       $ git diff gnuastro_vX.X..HEAD doc/gnuastro.texi | grep ^\+  \
+             > ~/gnuastro_book_new_parts.txt
+
 
  - Build the Debian distribution (just for a test) and correct any build or
    Lintian warnings. This is recommended, even if you don't actually want
@@ -16,16 +23,16 @@ all the commits needed for this release have been completed.
    three branchs with the following command
 
        $ git checkout master
-       $ git reset --hard HEAD~1
+       $ git tag -d debian/$ver-1
+       $ git reset --hard HEAD~1        # To go to the merge with upstream.
+       $ git reset --hard HEAD~1            # To go to last Debian release.
        $ git checkout pristine-tar
        $ git reset --hard HEAD~1
        $ git checkout upstream
        $ git tag -d upstream/$ver
        $ git reset --hard HEAD~1
        $ git checkout master
-
-
- - [STABLE] Run a spell-check (in emacs with `M-x ispell') on the whole book.
+       $ git log --oneline --graph --decorate --all   # For a visual check.
 
 
  - [STABLE] Update the versions in the NEWS file.
@@ -42,10 +49,6 @@ all the commits needed for this release have been completed.
      $ git diff gnuastro_vP.P..HEAD THANKS
 
 
- - [STABLE] Correct the links in the webpage (`doc/gnuastro.en.html' and
-   `doc/gnuastro.fr.html').
-
-
  - Run the following commands to keep the list of people who contributed
    code and those that must be acknowledged for the announcement (`P.P' is
    the previous version).
@@ -54,10 +57,15 @@ all the commits needed for this release have been completed.
      $ cat doc/announce-acknowledge.txt >> ~/people.txt
 
      [STABLE] Clean `doc/announce-acknowledge.txt':
-     $ echo "People who's help must be acknowledged in the next release." \
+     $ echo "Alphabetically ordered list to acknowledge in the next release." \
             > doc/announce-acknowledge.txt
 
 
+ - [STABLE] Correct the version links in the webpage
+   (`doc/gnuastro.en.html' and `doc/gnuastro.fr.html'). Note that this is
+   not for upload at this stage, it is only for the version control.
+
+
  - Commit all these changes:
 
      $ git add -u
@@ -88,11 +96,10 @@ all the commits needed for this release have been completed.
      $ git tag -a gnuastro_vX.X
 
 
- - [STABLE] The tag will cause a change in the tarball version. So clean
-   the build directory, and repeat the steps for the final release:
+ - [STABLE] The tag will cause a change in the tarball version. Run the
+   following commands to build the final tarball.
 
-     $ autoreconf -f
-     $ ./developer-build -c -C -d
+     $ ./developer-build -a -c -C -d
      $ cd build
      $ make dist dist-lzip       # to build `tar.gz' and `tar.lz'.
 
@@ -120,9 +127,10 @@ all the commits needed for this release have been 
completed.
 
  - [STABLE] Build the manual in all the formats and upload everything. Note
    that you will need to configure and build Gnuastro in the main source
-   directory to build the full webpage with this script.
+   directory to build the full webpage with this script. We will build with
+   debug flags so the build completes fast.
 
-       $ ./configure CFLAGS="-g -O0" --disable-shared
+       $ ./configure --enable-debug
        $ make -j8
        $ cd doc
        $ ./forwebpage /path/to/local/copy/of/webpage
@@ -154,7 +162,7 @@ all the commits needed for this release have been completed.
      $ /path/to/gnulib/build-aux/announce-gen --release-type=XXXX          \
               --package-name=gnuastro --previous-version=0.1               \
               --current-version=0.2 --gpg-key-id=$mykeyid                  \
-              --url-directory=https://YYYY.gnu.org/gnu/gnuastro             \
+              --url-directory=https://YYYY.gnu.org/gnu/gnuastro            \
               --archive-suffix=tar.lz > ~/announcement.txt
 
 
@@ -371,11 +379,9 @@ Steps necessary to Package Gnuastro for Debian.
      $ git tag -a debian/$ver-1
 
 
- - Push all the changes to the repository (you can't call `--all' and
-   `--tags' together):
+ - Push all the commits and tags to the repository.
 
-     $ git push --all
-     $ git push --tags
+     $ git push --all --follow-tags
 
 
  - Inform Debian Astro: Ole Streicher (olebole@debian.org) has been
diff --git a/lib/arithmetic.c b/lib/arithmetic.c
index 3e84f95..d2b0f3b 100644
--- a/lib/arithmetic.c
+++ b/lib/arithmetic.c
@@ -494,25 +494,27 @@ arithmetic_from_statistics(int operator, int flags, 
gal_data_t *input)
 /***********************************************************************/
 /***************                  Where                   **************/
 /***********************************************************************/
-
 /* When the `iftrue' dataset only has one element and the element is blank,
    then it will be replaced with the blank value of the type of the output
    data. */
-#define DO_WHERE_OPERATION(ITT, OT) {                                \
-    ITT *it=iftrue->array;                                           \
-    OT b, *o=out->array, *of=o+out->size;                            \
-    if(iftrue->size==1)                                              \
-      {                                                              \
-        if( gal_blank_present(iftrue, 0) )                           \
-          {                                                          \
-            gal_blank_write(&b, out->type);                          \
-            do { *o = *c++ ? b : *o;        } while(++o<of);         \
-          }                                                          \
-        else                                                         \
-          do   { *o = *c++ ? *it : *o;       } while(++o<of);        \
-      }                                                              \
-    else                                                             \
-      do       { *o = *c++ ? *it : *o; ++it; } while(++o<of);        \
+#define DO_WHERE_OPERATION(ITT, OT) {                                   \
+    ITT *it=iftrue->array;                                              \
+    OT b, *o=out->array, *of=o+out->size;                               \
+    gal_blank_write(&b, out->type);                                     \
+    if(iftrue->size==1)                                                 \
+      {                                                                 \
+        if( gal_blank_is(it, iftrue->type) )                            \
+          {                                                             \
+            do{*o = (chb && *c==cb) ? *o : (*c ? b   : *o); ++c;      } \
+            while(++o<of);                                              \
+          }                                                             \
+        else                                                            \
+          do  {*o = (chb && *c==cb) ? *o : (*c ? *it : *o); ++c;      } \
+          while(++o<of);                                                \
+      }                                                                 \
+    else                                                                \
+      do      {*o = (chb && *c==cb) ? *o : (*c ? *it : *o); ++it; ++c;} \
+      while(++o<of);                                                    \
 }
 
 
@@ -545,7 +547,8 @@ static void
 arithmetic_where(int flags, gal_data_t *out, gal_data_t *cond,
                  gal_data_t *iftrue)
 {
-  unsigned char *c=cond->array;
+  int chb;    /* Read as: "Condition-Has-Blank" */
+  unsigned char *c=cond->array, cb=GAL_BLANK_UINT8;
 
   /* The condition operator has to be unsigned char. */
   if(cond->type!=GAL_TYPE_UINT8)
@@ -559,6 +562,9 @@ arithmetic_where(int flags, gal_data_t *out, gal_data_t 
*cond,
     error(EXIT_FAILURE, 0, "%s: the output and condition data sets of the "
           "must be the same size", __func__);
 
+  /* See if the condition array has blank values. */
+  chb=gal_blank_present(cond, 0);
+
   /* Do the operation. */
   switch(out->type)
     {
diff --git a/lib/dimension.c b/lib/dimension.c
index 9b1aea7..ec677cb 100644
--- a/lib/dimension.c
+++ b/lib/dimension.c
@@ -298,6 +298,8 @@ enum dimension_collapse_operation
  DIMENSION_COLLAPSE_INVALID,    /* ==0 by C standard. */
 
  DIMENSION_COLLAPSE_SUM,
+ DIMENSION_COLLAPSE_MAX,
+ DIMENSION_COLLAPSE_MIN,
  DIMENSION_COLLAPSE_MEAN,
  DIMENSION_COLLAPSE_NUMBER,
 };
@@ -371,22 +373,28 @@ dimension_collapse_sizes(gal_data_t *in, size_t c_dim, 
size_t *outndim,
 
 /* Depending on the operator, write the result into the output. */
 #define COLLAPSE_WRITE(OIND,IIND) {                                     \
-    /* We need the sum when number operator is requested. */            \
-    if(farr) farr[ OIND ] += (warr ? warr[w] : 1) * inarr[ IIND ];      \
+    /* Sum */                                                           \
+    if(farr)                                                            \
+      farr[ OIND ] += (warr ? warr[w] : 1) * inarr[ IIND ];             \
                                                                         \
-    /* We don't need the number in some situations. */                  \
+    /* Number */                                                        \
     if(iarr)                                                            \
       {                                                                 \
         if(num->type==GAL_TYPE_UINT8) iarr[ OIND ] = 1;                 \
         else                        ++iarr[ OIND ];                     \
       }                                                                 \
                                                                         \
-    /* If the sum of weights for is needed, add it. */                  \
+    /* Sum of weights. */                                               \
     if(wsumarr) wsumarr[ OIND ] += warr[w];                             \
+                                                                        \
+    /* Minimum or maximum. */                                           \
+    if(mmarr)                                                           \
+      mmarr[OIND] = ( max1_min0                                         \
+                      ? (mmarr[OIND]>inarr[IIND]?mmarr[OIND]:inarr[IIND]) \
+                      : (mmarr[OIND]<inarr[IIND]?mmarr[OIND]:inarr[IIND]) ); \
   }
 
 
-
 /* Deal properly with blanks. */
 #define COLLAPSE_CHECKBLANK(OIND,IIND) {                                \
     if(hasblank)                                                        \
@@ -406,8 +414,18 @@ dimension_collapse_sizes(gal_data_t *in, size_t c_dim, 
size_t *outndim,
 
 
 #define COLLAPSE_DIM(IT) {                                              \
-    IT B, *inarr=in->array;                                             \
+    IT m, B, *inarr=in->array, *mmarr=minmax?minmax->array:NULL;        \
     if(hasblank) gal_blank_write(&B, in->type);                         \
+                                                                        \
+    /* Initialize the array for minimum or maximum. */                  \
+    if(mmarr)                                                           \
+      {                                                                 \
+        if(max1_min0) gal_type_min(in->type, &m);                       \
+        else          gal_type_max(in->type, &m);                       \
+        for(i=0;i<minmax->size;++i) mmarr[i]=m;                         \
+      }                                                                 \
+                                                                        \
+    /* Collapse the dataset. */                                         \
     switch(in->ndim)                                                    \
       {                                                                 \
       /* 1D input dataset. */                                           \
@@ -458,6 +476,10 @@ dimension_collapse_sizes(gal_data_t *in, size_t c_dim, 
size_t *outndim,
               "supported, please contact us at %s to add this feature", \
               __func__, in->ndim, PACKAGE_BUGREPORT);                   \
       }                                                                 \
+                                                                        \
+    /* For minimum or maximum, elements with no input must be blank. */ \
+    if(mmarr && iarr)                                                   \
+      for(i=0;i<minmax->size;++i) if(iarr[i]==0) mmarr[i]=B;            \
   }
 
 
@@ -467,13 +489,14 @@ dimension_collapse_sizes(gal_data_t *in, size_t c_dim, 
size_t *outndim,
 gal_data_t *
 gal_dimension_collapse_sum(gal_data_t *in, size_t c_dim, gal_data_t *weight)
 {
+  int max1_min0=0;
   double *wsumarr=NULL;
   uint8_t *ii, *iarr=NULL;
   size_t a, b, i, j, k, w=-1, cnum=0;
   size_t outdsize[10], slice, outndim;
   int hasblank=gal_blank_present(in, 0);
   double *dd, *df, *warr=NULL, *farr=NULL;
-  gal_data_t *wht=NULL, *sum=NULL, *num=NULL;
+  gal_data_t *sum=NULL, *wht=NULL, *num=NULL, *minmax=NULL;
 
   /* Basic sanity checks. */
   wht=dimension_collapse_sanity_check(in, weight, c_dim, hasblank,
@@ -540,14 +563,15 @@ gal_data_t *
 gal_dimension_collapse_mean(gal_data_t *in, size_t c_dim,
                             gal_data_t *weight)
 {
+  int max1_min0=0;
   double wsum=NAN;
   double *wsumarr=NULL;
   int32_t *ii, *iarr=NULL;
   size_t a, b, i, j, k, w=-1, cnum=0;
   size_t outdsize[10], slice, outndim;
   int hasblank=gal_blank_present(in, 0);
-  gal_data_t *wht=NULL, *sum=NULL, *num=NULL;
   double *dd, *dw, *df, *warr=NULL, *farr=NULL;
+  gal_data_t *sum=NULL, *wht=NULL, *num=NULL, *minmax=NULL;
 
 
   /* Basic sanity checks. */
@@ -640,13 +664,14 @@ gal_dimension_collapse_mean(gal_data_t *in, size_t c_dim,
 gal_data_t *
 gal_dimension_collapse_number(gal_data_t *in, size_t c_dim)
 {
+  int max1_min0=0;
   double *wsumarr=NULL;
   double *warr=NULL, *farr=NULL;
   int32_t *ii, *iif, *iarr=NULL;
   size_t a, b, i, j, k, w, cnum=0;
   size_t outdsize[10], slice, outndim;
   int hasblank=gal_blank_present(in, 0);
-  gal_data_t *weight=NULL, *wht=NULL, *num=NULL;
+  gal_data_t *weight=NULL, *wht=NULL, *num=NULL, *minmax=NULL;
 
   /* Basic sanity checks. */
   wht=dimension_collapse_sanity_check(in, weight, c_dim, hasblank,
@@ -695,3 +720,66 @@ gal_dimension_collapse_number(gal_data_t *in, size_t c_dim)
   if(wht!=weight) gal_data_free(wht);
   return num;
 }
+
+
+
+
+
+gal_data_t *
+gal_dimension_collapse_minmax(gal_data_t *in, size_t c_dim, int max1_min0)
+{
+  uint8_t *iarr=NULL;
+  double *wsumarr=NULL;
+  double *warr=NULL, *farr=NULL;
+  size_t a, b, i, j, k, w, cnum=0;
+  size_t outdsize[10], slice, outndim;
+  int hasblank=gal_blank_present(in, 0);
+  gal_data_t *weight=NULL, *wht=NULL, *num=NULL, *minmax=NULL;
+
+  /* Basic sanity checks. */
+  wht=dimension_collapse_sanity_check(in, weight, c_dim, hasblank,
+                                      &cnum, &warr);
+
+  /* Set the size of the collapsed output. */
+  dimension_collapse_sizes(in, c_dim, &outndim, outdsize);
+
+  /* Allocate the necessary datasets. If there are blank pixels, we'll need
+     to count how many elements whent into the calculation so we can set
+     them to blank. */
+  minmax=gal_data_alloc(NULL, in->type, outndim, outdsize, in->wcs,
+                        0, in->minmapsize, NULL, NULL, NULL);
+  if(hasblank)
+    {
+      num=gal_data_alloc(NULL, GAL_TYPE_UINT8, outndim, outdsize, in->wcs,
+                         1, in->minmapsize, NULL, NULL, NULL);
+      iarr=num->array;
+    }
+
+  /* Parse the input dataset (if necessary). */
+  switch(in->type)
+    {
+    case GAL_TYPE_UINT8:     COLLAPSE_DIM( uint8_t  );   break;
+    case GAL_TYPE_INT8:      COLLAPSE_DIM( int8_t   );   break;
+    case GAL_TYPE_UINT16:    COLLAPSE_DIM( uint16_t );   break;
+    case GAL_TYPE_INT16:     COLLAPSE_DIM( int16_t  );   break;
+    case GAL_TYPE_UINT32:    COLLAPSE_DIM( uint32_t );   break;
+    case GAL_TYPE_INT32:     COLLAPSE_DIM( int32_t  );   break;
+    case GAL_TYPE_UINT64:    COLLAPSE_DIM( uint64_t );   break;
+    case GAL_TYPE_INT64:     COLLAPSE_DIM( int64_t  );   break;
+    case GAL_TYPE_FLOAT32:   COLLAPSE_DIM( float    );   break;
+    case GAL_TYPE_FLOAT64:   COLLAPSE_DIM( double   );   break;
+    default:
+      error(EXIT_FAILURE, 0, "%s: type value (%d) not recognized",
+            __func__, in->type);
+    }
+
+  /* Remove the respective dimension in the WCS structure also (if any
+     exists). Note that `sum->ndim' has already been changed. So we'll use
+     `in->wcs'. */
+  gal_wcs_remove_dimension(minmax->wcs, in->ndim-c_dim);
+
+  /* Clean up and return. */
+  if(wht!=weight) gal_data_free(wht);
+  if(num) gal_data_free(num);
+  return minmax;
+}
diff --git a/lib/fits.c b/lib/fits.c
index 772c621..ad6a854 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -1152,8 +1152,77 @@ gal_fits_key_list_add_end(gal_fits_list_key_t **list, 
uint8_t type,
 
 
 void
+gal_fits_key_list_reverse(gal_fits_list_key_t **list)
+{
+  gal_fits_list_key_t *in=*list, *tmp=in, *reversed=NULL;
+
+  /* Only do the reversal if there is more than one element. */
+  if(in && in->next)
+    {
+      /* Fill the `reversed' list. */
+      while(in!=NULL)
+        {
+          tmp=in->next;
+          in->next=reversed;
+          reversed=in;
+          in=tmp;
+        }
+
+      /* Write the reversed list into the input pointer. */
+      *list=reversed;
+    }
+}
+
+
+
+
+
+/* Write a blank keyword field and a title under it in the specified FITS
+   file pointer. */
+void
+gal_fits_key_write_title_in_ptr(char *title, fitsfile *fptr)
+{
+  size_t i;
+  int status=0;
+  char *cp, *cpf, blankrec[80], titlerec[80];
+
+  /* Just in case title is `NULL'. */
+  if(title)
+    {
+      /* A small sanity check. */
+      if( strlen(title) + strlen(GAL_FITS_KEY_TITLE_START) > 78 )
+        fprintf(stderr, "%s: FITS keyword title `%s' is too long to be fully "
+                "included in the keyword record (80 characters, where the "
+                "title is prefixed with %zu space characters)",
+                __func__, title, strlen(GAL_FITS_KEY_TITLE_START));
+
+      /* Set the last element of the blank array. */
+      cpf=blankrec+79;
+      *cpf='\0';
+      titlerec[79]='\0';
+      cp=blankrec; do *cp=' '; while(++cp<cpf);
+
+      /* Print the blank lines before the title */
+      if(fits_write_record(fptr, blankrec, &status))
+        gal_fits_io_error(status, NULL);
+
+      /* Print the title */
+      sprintf(titlerec, "%s%s", GAL_FITS_KEY_TITLE_START, title);
+      for(i=strlen(titlerec);i<79;++i)
+        titlerec[i]=' ';
+      if(fits_write_record(fptr, titlerec, &status))
+        gal_fits_io_error(status, NULL);
+    }
+}
+
+
+
+
+
+/* Write a filename into keyword values. */
+void
 gal_fits_key_write_filename(char *keynamebase, char *filename,
-                            gal_fits_list_key_t **list)
+                            gal_fits_list_key_t **list, int top1end0)
 {
   char *keyname, *value;
   size_t numkey=1, maxlength;
@@ -1165,6 +1234,7 @@ gal_fits_key_write_filename(char *keynamebase, char 
*filename,
      to take three from it.*/
   maxlength=FLEN_VALUE-3;
 
+  /* Parse the filename and see when it is necessary to break it. */
   i=0;
   while(i<len)
     {
@@ -1174,7 +1244,10 @@ gal_fits_key_write_filename(char *keynamebase, char 
*filename,
       if(keyname==NULL)
         error(EXIT_FAILURE, errno, "%s: %d bytes for `keyname'", __func__,
               FLEN_KEYWORD);
-      sprintf(keyname, "%s_%zu", keynamebase, numkey++);
+      if(len<maxlength)
+        strcpy(keyname, keynamebase);
+      else
+        sprintf(keyname, "%s_%zu", keynamebase, numkey++);
 
       /* Set the keyword value: */
       errno=0;
@@ -1191,8 +1264,12 @@ gal_fits_key_write_filename(char *keynamebase, char 
*filename,
          length was copied. */
       if(value[maxlength-1]=='\0')
         {
-          gal_fits_key_list_add_end(list, GAL_TYPE_STRING, keyname, 1,
-                                    value, 1, NULL, 0, NULL);
+          if(top1end0)
+            gal_fits_key_list_add(list, GAL_TYPE_STRING, keyname, 1,
+                                  value, 1, NULL, 0, NULL);
+          else
+            gal_fits_key_list_add_end(list, GAL_TYPE_STRING, keyname, 1,
+                                      value, 1, NULL, 0, NULL);
           break;
         }
       else
@@ -1207,14 +1284,28 @@ gal_fits_key_write_filename(char *keynamebase, char 
*filename,
                 break;
               }
           if(j==0)
-            error(EXIT_FAILURE, 0, "%s: the filename `%sP has at least one "
-                  "span of %zu characters without a `/`. It cannot be "
-                  "written to the header of the output fits file", __func__,
-                  filename, maxlength);
+            {
+              /* So the loop doesn't continue after this. */
+              i=len+1;
+
+              /* There will only be one keyword, so we'll just use the
+                 basename. */
+              strcpy(keyname, keynamebase);
+
+              /* Let the user know that  */
+              error(0,0, "%s: WARNING: `%s' is too long to fit "
+                    "into a FITS keyword value (max of %zu characters), "
+                    "it will be truncated", __func__, filename,
+                    maxlength);
+            }
 
           /* Convert the last useful character and save the file name.*/
-          gal_fits_key_list_add_end(list, GAL_TYPE_STRING, keyname, 1,
-                                    value, 1, NULL, 0, NULL);
+          if(top1end0)
+            gal_fits_key_list_add(list, GAL_TYPE_STRING, keyname, 1,
+                                  value, 1, NULL, 0, NULL);
+          else
+            gal_fits_key_list_add_end(list, GAL_TYPE_STRING, keyname, 1,
+                                      value, 1, NULL, 0, NULL);
           i+=j+1;
         }
     }
@@ -1228,24 +1319,10 @@ gal_fits_key_write_filename(char *keynamebase, char 
*filename,
 void
 gal_fits_key_write_wcsstr(fitsfile *fptr, char *wcsstr, int nkeyrec)
 {
-  size_t i;
   int h, status=0;
-  char *cp, *cpf, blankrec[80], titlerec[80];
-
-  /* Set the last element of the blank array. */
-  cpf=blankrec+79;
-  *cpf='\0';
-  titlerec[79]='\0';
-  cp=blankrec; do *cp=' '; while(++cp<cpf);
 
-  /* Print the first two lines before the WCS header information. */
-  if(fits_write_record(fptr, blankrec, &status))
-    gal_fits_io_error(status, NULL);
-  sprintf(titlerec, "%sWCS information", GAL_FITS_KEY_TITLE_START);
-  for(i=strlen(titlerec);i<79;++i)
-    titlerec[i]=' ';
-  if(fits_write_record(fptr, titlerec, &status))
-    gal_fits_io_error(status, NULL);
+  /* Write the title. */
+  gal_fits_key_write_title_in_ptr("World Coordinate System (WCS)", fptr);
 
   /* Write the keywords one by one: */
   for(h=0;h<nkeyrec-1;++h)
@@ -1257,11 +1334,35 @@ gal_fits_key_write_wcsstr(fitsfile *fptr, char *wcsstr, 
int nkeyrec)
 
 
 
+/* Write the given list of header keywords into the specified HDU of the
+   specified FITS file. */
+void
+gal_fits_key_write(gal_fits_list_key_t **keylist, char *title,
+                   char *filename, char *hdu)
+{
+  int status=0;
+  fitsfile *fptr=gal_fits_hdu_open(filename, hdu, READWRITE);
+
+  /* Write the title */
+  gal_fits_key_write_title_in_ptr(title, fptr);
+
+  /* Write the keywords into the  */
+  gal_fits_key_write_in_ptr(keylist, fptr);
+
+  /* Close the input FITS file. */
+  fits_close_file(fptr, &status);
+  gal_fits_io_error(status, NULL);
+}
+
+
+
+
+
 /* Write the keywords in the gal_fits_list_key_t linked list to the FITS
    file. Every keyword that is written is freed, that is why we need the
    pointer to the linked list (to correct it after we finish). */
 void
-gal_fits_key_write(fitsfile *fptr, gal_fits_list_key_t **keylist)
+gal_fits_key_write_in_ptr(gal_fits_list_key_t **keylist, fitsfile *fptr)
 {
   int status=0;
   gal_fits_list_key_t *tmp, *ttmp;
@@ -1308,15 +1409,34 @@ gal_fits_key_write(fitsfile *fptr, gal_fits_list_key_t 
**keylist)
 
 
 
+/* Write the given list of header keywords and version info into the give
+   file. */
 void
-gal_fits_key_write_version(fitsfile *fptr, gal_fits_list_key_t *headers,
-                           char *program_name)
+gal_fits_key_write_version(gal_fits_list_key_t **keylist, char *title,
+                           char *filename, char *hdu)
+{
+  int status=0;
+  fitsfile *fptr=gal_fits_hdu_open(filename, hdu, READWRITE);
+
+  /* Write the given keys followed by the versions. */
+  gal_fits_key_write_version_in_ptr(keylist, title, fptr);
+
+  /* Close the input FITS file. */
+  fits_close_file(fptr, &status);
+  gal_fits_io_error(status, NULL);
+}
+
+
+
+
+
+void
+gal_fits_key_write_version_in_ptr(gal_fits_list_key_t **keylist, char *title,
+                                  fitsfile *fptr)
 {
-  size_t i;
   int status=0;
   char *gitdescribe;
   char cfitsioversion[20];
-  char *cp, *cpf, blankrec[80], titlerec[80];
 
   /* Before WCSLIB 5.0, the wcslib_version function was not
      defined. Sometime in the future were everyone has moved to more
@@ -1328,30 +1448,15 @@ gal_fits_key_write_version(fitsfile *fptr, 
gal_fits_list_key_t *headers,
   const char *wcslibversion_const;
 #endif
 
-  /* Set the last element of the blank array. */
-  cpf=blankrec+79;
-  *cpf='\0';
-  titlerec[79]='\0';
-  cp=blankrec; do *cp=' '; while(++cp<cpf);
-
-  /* If any header keywords are specified add them: */
-  if(headers)
+  /* If any header keywords are specified, add them: */
+  if(keylist && *keylist)
     {
-      fits_write_record(fptr, blankrec, &status);
-      sprintf(titlerec, "%s%s", GAL_FITS_KEY_TITLE_START,
-              program_name ? program_name : PACKAGE_NAME);
-      for(i=strlen(titlerec);i<79;++i) titlerec[i]=' ';
-      fits_write_record(fptr, titlerec, &status);
-      gal_fits_key_write(fptr, &headers);
+      gal_fits_key_write_title_in_ptr(title?title:"Specific keys", fptr);
+      gal_fits_key_write_in_ptr(keylist, fptr);
     }
 
-
-  /* Start printing the version information */
-  fits_write_record(fptr, blankrec, &status);
-  sprintf(titlerec, "%sVersions and date", GAL_FITS_KEY_TITLE_START);
-  for(i=strlen(titlerec);i<79;++i) titlerec[i]=' ';
-  fits_write_record(fptr, titlerec, &status);
-  gal_fits_io_error(status, NULL);
+  /* Print `Versions and date' title. */
+  gal_fits_key_write_title_in_ptr("Versions and date", fptr);
 
   /* Set the version of CFITSIO as a string. */
   sprintf(cfitsioversion, "%-.2f", CFITSIO_VERSION);
@@ -1398,6 +1503,43 @@ gal_fits_key_write_version(fitsfile *fptr, 
gal_fits_list_key_t *headers,
 
 
 
+/* Write the given keywords into the given extension of the given file,
+   ending it with version information. This is primarily intended for
+   writing configuration settings of a program into the zero-th extension
+   of the FITS file (which is empty when the FITS file is created by
+   Gnuastro's program and this library). */
+void
+gal_fits_key_write_config(gal_fits_list_key_t **keylist, char *title,
+                          char *extname, char *filename, char *hdu)
+{
+  int status=0;
+  fitsfile *fptr=gal_fits_hdu_open(filename, hdu, READWRITE);
+
+  /* Delete the two extra comment lines describing the FITS standard that
+     CFITSIO puts in when it creates a new extension. We'll set status to 0
+     afterwards so even if they don't exist, the program continues
+     normally. */
+  fits_delete_key(fptr, "COMMENT", &status);
+  fits_delete_key(fptr, "COMMENT", &status);
+  status=0;
+
+  /* Put a name for the zero-th extension. */
+  if(fits_write_key(fptr, TSTRING, "EXTNAME", extname, "", &status))
+    gal_fits_io_error(status, NULL);
+
+  /* Write all the given keywords. */
+  gal_fits_key_write_version_in_ptr(keylist, title, fptr);
+
+  /* Close the FITS file. */
+  if( fits_close_file(fptr, &status) )
+    gal_fits_io_error(status, NULL);
+}
+
+
+
+
+
+
 
 
 
@@ -1838,7 +1980,7 @@ gal_fits_img_write(gal_data_t *data, char *filename,
   fptr=gal_fits_img_write_to_ptr(data, filename);
 
   /* Write all the headers and the version information. */
-  gal_fits_key_write_version(fptr, headers, program_string);
+  gal_fits_key_write_version_in_ptr(&headers, program_string, fptr);
 
   /* Close the FITS file. */
   fits_close_file(fptr, &status);
@@ -1917,7 +2059,7 @@ gal_fits_img_write_corr_wcs_str(gal_data_t *input, char 
*filename,
     }
 
   /* Write all the headers and the version information. */
-  gal_fits_key_write_version(fptr, headers, program_string);
+  gal_fits_key_write_version_in_ptr(&headers, program_string, fptr);
 
   /* Close the file and return. */
   fits_close_file(fptr, &status);
@@ -2874,7 +3016,7 @@ gal_fits_tab_write(gal_data_t *cols, gal_list_str_t 
*comments,
 
 
   /* Write all the headers and the version information. */
-  gal_fits_key_write_version(fptr, NULL, NULL);
+  gal_fits_key_write_version_in_ptr(NULL, NULL, fptr);
 
 
   /* Clean up and close the FITS file. Note that each element in the
diff --git a/lib/gnuastro-internal/options.h b/lib/gnuastro-internal/options.h
index 599702b..ef3ba41 100644
--- a/lib/gnuastro-internal/options.h
+++ b/lib/gnuastro-internal/options.h
@@ -26,6 +26,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <gnuastro/tile.h>
 #include <gnuastro/list.h>
+#include <gnuastro/fits.h>
 
 
 
@@ -204,6 +205,9 @@ struct gal_options_common_params
   uint8_t           setusrconf; /* To write teh user config config file.  */
   uint8_t           lastconfig; /* This is the last configuration file.   */
 
+  /* Output files. */
+  gal_fits_list_key_t  *okeys;  /* Configuration as FITS keys in output.  */
+
   /* For internal (to option processing) purposes. */
   uint8_t                 keep; /* Output file can exist.                 */
   void         *program_struct; /* Host program's main variable struct.   */
@@ -320,4 +324,7 @@ gal_options_read_config_set(struct 
gal_options_common_params *cp);
 void
 gal_options_print_state(struct gal_options_common_params *cp);
 
+void
+gal_options_as_fits_keywords(struct gal_options_common_params *cp);
+
 #endif
diff --git a/lib/gnuastro/dimension.h b/lib/gnuastro/dimension.h
index a0623a2..46e68fa 100644
--- a/lib/gnuastro/dimension.h
+++ b/lib/gnuastro/dimension.h
@@ -109,7 +109,8 @@ gal_dimension_collapse_mean(gal_data_t *in, size_t c_dim,
 gal_data_t *
 gal_dimension_collapse_number(gal_data_t *in, size_t c_dim);
 
-
+gal_data_t *
+gal_dimension_collapse_minmax(gal_data_t *in, size_t c_dim, int max1_min0);
 
 
 
diff --git a/lib/gnuastro/fits.h b/lib/gnuastro/fits.h
index 2960378..c37c6c0 100644
--- a/lib/gnuastro/fits.h
+++ b/lib/gnuastro/fits.h
@@ -185,18 +185,36 @@ gal_fits_key_list_add_end(gal_fits_list_key_t **list, 
uint8_t type,
                           char *comment, int cfree, char *unit);
 
 void
+gal_fits_key_list_reverse(gal_fits_list_key_t **list);
+
+void
+gal_fits_key_write_title_in_ptr(char *title, fitsfile *fptr);
+
+void
 gal_fits_key_write_filename(char *keynamebase, char *filename,
-                            gal_fits_list_key_t **list);
+                            gal_fits_list_key_t **list, int top1end0);
 
 void
 gal_fits_key_write_wcsstr(fitsfile *fptr, char *wcsstr, int nkeyrec);
 
 void
-gal_fits_key_write(fitsfile *fptr, gal_fits_list_key_t **keylist);
+gal_fits_key_write(gal_fits_list_key_t **keylist, char *title,
+                   char *filename, char *hdu);
+
+void
+gal_fits_key_write_in_ptr(gal_fits_list_key_t **keylist, fitsfile *fptr);
+
+void
+gal_fits_key_write_version(gal_fits_list_key_t **keylist, char *title,
+                           char *filename, char *hdu);
+
+void
+gal_fits_key_write_version_in_ptr(gal_fits_list_key_t **keylist, char *title,
+                                  fitsfile *fptr);
 
 void
-gal_fits_key_write_version(fitsfile *fptr, gal_fits_list_key_t *headers,
-                           char *program_string);
+gal_fits_key_write_config(gal_fits_list_key_t **keylist, char *title,
+                          char *extname, char *filename, char *hdu);
 
 
 
diff --git a/lib/options.c b/lib/options.c
index ef10f35..dcb4a3d 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/git.h>
 #include <gnuastro/txt.h>
+#include <gnuastro/fits.h>
 #include <gnuastro/list.h>
 #include <gnuastro/data.h>
 #include <gnuastro/table.h>
@@ -2194,3 +2195,83 @@ gal_options_print_state(struct gal_options_common_params 
*cp)
             "and `setusrconf' options can be called in each run");
     }
 }
+
+
+
+
+
+/* Main working function for common and program specific options. */
+static void
+options_as_fits_keywords_write(gal_fits_list_key_t **keys,
+                               struct argp_option *options,
+                               struct gal_options_common_params *cp)
+{
+  size_t i;
+  void *vptr;
+  uint8_t vtype;
+  char *name, *doc;
+  gal_list_str_t *tmp;
+
+  for(i=0; !gal_options_is_last(&options[i]); ++i)
+    if( options[i].set && option_is_printable(&options[i]) )
+      {
+        /* Linked lists (multiple calls to an option). */
+        if(gal_type_is_list(options[i].type))
+          for(tmp=*(gal_list_str_t **)(options[i].value);
+              tmp!=NULL; tmp=tmp->next)
+            {
+              /* `name' and `doc' have a `const' qualifier. */
+              gal_checkset_allocate_copy(options[i].name, &name);
+              gal_checkset_allocate_copy(options[i].doc,  &doc);
+              gal_fits_key_list_add(keys, GAL_TYPE_STRING, name, 1, tmp->v,
+                                    0, doc, 1, NULL);
+            }
+        /* Normal types. */
+        else
+          {
+            /* If the option is associated with a special function for
+               reading and writing, we'll need to write the value as a
+               string. */
+            if(options[i].func)
+              {
+                vtype=GAL_TYPE_STRING;
+                vptr=options[i].func(&options[i], NULL, NULL, (size_t)(-1),
+                                      cp->program_struct);
+              }
+            else
+              {
+                vtype=options[i].type;
+                vptr = ( vtype==GAL_TYPE_STRING
+                         ? *((char **)(options[i].value))
+                         : options[i].value );
+              }
+
+            /* Write the keyword. Note that `name' and `doc' have a `const'
+               qualifier. */
+            gal_checkset_allocate_copy(options[i].name, &name);
+            if(vtype==GAL_TYPE_STRING && strlen(vptr)>FLEN_KEYWORD)
+              gal_fits_key_write_filename(name, vptr, keys, 1);
+            else
+              {
+                gal_checkset_allocate_copy(options[i].doc,  &doc);
+                gal_fits_key_list_add(keys, vtype, name, 1, vptr, 0, doc, 1,
+                                      NULL);
+              }
+          }
+      }
+}
+
+
+
+
+/* Write all options as FITS keywords. */
+void
+gal_options_as_fits_keywords(struct gal_options_common_params *cp)
+{
+  /* Write all the command and program-specific options. */
+  options_as_fits_keywords_write(&cp->okeys, cp->coptions, cp);
+  options_as_fits_keywords_write(&cp->okeys, cp->poptions, cp);
+
+  /* Reverse the list (its a first-in-first-out list). */
+  gal_fits_key_list_reverse(&cp->okeys);
+}
diff --git a/lib/statistics.c b/lib/statistics.c
index 7d6e2f4..ce77950 100644
--- a/lib/statistics.c
+++ b/lib/statistics.c
@@ -846,6 +846,7 @@ mode_golden_section(struct statistics_mode_params *p)
     /* Set the values at the mirror and at `a' (see above). */          \
     mf=a[m];                                                            \
     af=a[ gal_statistics_quantile_index(2*m+1, MODE_SYM_LOW_Q) ];       \
+    if(mf<=af) return 0;                                                \
                                                                         \
     /* This loop is very similar to that of */                          \
     /* `mode_mirror_max_index_diff'. It will find the index where the */\
@@ -883,7 +884,7 @@ mode_golden_section(struct statistics_mode_params *p)
     /*printf("%zu: %f,%f,%f\n", m, (double)af, (double)mf, (double)bf);*/ \
                                                                         \
     /* For a bad result, return 0 (which will not output any mode). */  \
-    return bf==af ? 0 : (bf-mf)/(mf-af);                                \
+    return bf==af ? 0 : (double)(bf-mf)/(double)(mf-af);                \
   }
 static double
 mode_symmetricity(struct statistics_mode_params *p, size_t m, void *b_val)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a0406e3..81768a5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -51,9 +51,6 @@ endif
 if COND_HASLIBJPEG
   MAYBE_HASLIBJPEG = "yes"
 endif
-if COND_HASGNULIBTOOL
-  MAYBE_HASGNULIBTOOL = "yes"
-endif
 if COND_HASCXX
   MAYBE_CXX_PROGS    = versioncxx
   MAYBE_CXX_TESTS    = lib/versioncxx.sh
@@ -210,7 +207,6 @@ export mkdir_p="$(MKDIR_P)";                             \
 export topsrc=$(top_srcdir);                             \
 export topbuild=$(top_builddir);                         \
 export haslibjpeg=$(MAYBE_HASLIBJPEG);                   \
-export hasgnulibtool=$(MAYBE_HASGNULIBTOOL);             \
 export hasghostscript=$(MAYBE_HASGHOSTSCRIPT);           \
 export check_with_program=$(MAYBE_CHECK_WITH_PROGRAM);
 
diff --git a/tests/buildprog/simpleio.sh b/tests/buildprog/simpleio.sh
index 69baaf8..1f3874c 100755
--- a/tests/buildprog/simpleio.sh
+++ b/tests/buildprog/simpleio.sh
@@ -41,18 +41,10 @@ source=$topsrc/tests/$prog/simpleio.c
 #
 #   - The input data was not made (for example the test that created the
 #     data file failed).
-#
-#   - Gnuastro ships with its own version of Libtool for the building of
-#     the libraries and programs. But here, we want to test the user's
-#     libtool (and how it works with BuildProgram). So if libtool wasn't
-#     found at configure time, we need to skip this test.
 if [ ! -f $execname ]; then echo "$execname not created.";  exit 77; fi
 if [ ! -f $img      ]; then echo "$img does not exist.";    exit 77; fi
 if [ ! -f $source   ]; then echo "$source does not exist."; exit 77; fi
-if [ "x$hasgnulibtool" != "xyes" ];then
-    echo "GNU libtool not present.";
-    exit 77;
-fi
+
 
 
 
diff --git a/tests/mkprof/mosaic1.sh b/tests/mkprof/mosaic1.sh
index 10eafa6..5f52742 100755
--- a/tests/mkprof/mosaic1.sh
+++ b/tests/mkprof/mosaic1.sh
@@ -54,5 +54,5 @@ if [ ! -f $cat      ]; then echo "$cat does not exist.";   
exit 77; fi
 # `check_with_program' can be something like `Valgrind' or an empty
 # string. Such programs will execute the command if present and help in
 # debugging when the developer doesn't have access to the user's system.
-$check_with_program $execname $cat --naxis=100,100 && mv 0_mkprofcat1.fits \
-                              psf.fits
+$check_with_program $execname $cat --mergedsize=100,100      \
+                    && mv 0_mkprofcat1.fits psf.fits
diff --git a/tests/mkprof/mosaic2.sh b/tests/mkprof/mosaic2.sh
index 7aa6b67..d5043e6 100755
--- a/tests/mkprof/mosaic2.sh
+++ b/tests/mkprof/mosaic2.sh
@@ -59,4 +59,5 @@ if [ ! -f $cat      ]; then echo "$cat does not exist.";   
exit 77; fi
 # `check_with_program' can be something like `Valgrind' or an empty
 # string. Such programs will execute the command if present and help in
 # debugging when the developer doesn't have access to the user's system.
-$check_with_program $execname $cat --naxis=100,100 --crpix=-99,1 --individual
+$check_with_program $execname $cat --mergedsize=100,100 --crpix=-99,1 \
+                    --individual
diff --git a/tests/mkprof/mosaic3.sh b/tests/mkprof/mosaic3.sh
index 7de1e43..4d530c4 100755
--- a/tests/mkprof/mosaic3.sh
+++ b/tests/mkprof/mosaic3.sh
@@ -56,4 +56,4 @@ if [ ! -f $cat      ]; then echo "$cat does not exist.";   
exit 77; fi
 # `check_with_program' can be something like `Valgrind' or an empty
 # string. Such programs will execute the command if present and help in
 # debugging when the developer doesn't have access to the user's system.
-$check_with_program $execname $cat --naxis=100,100 --crpix=1,-99
+$check_with_program $execname $cat --mergedsize=100,100 --crpix=1,-99
diff --git a/tests/mkprof/mosaic4.sh b/tests/mkprof/mosaic4.sh
index 64a4013..e894a3e 100755
--- a/tests/mkprof/mosaic4.sh
+++ b/tests/mkprof/mosaic4.sh
@@ -57,4 +57,4 @@ if [ ! -f $cat      ]; then echo "$cat does not exist.";   
exit 77; fi
 # `check_with_program' can be something like `Valgrind' or an empty
 # string. Such programs will execute the command if present and help in
 # debugging when the developer doesn't have access to the user's system.
-$check_with_program $execname $cat --naxis=100,100 --crpix=-99,-99
+$check_with_program $execname $cat --mergedsize=100,100 --crpix=-99,-99
diff --git a/tests/mkprof/radeccat.sh b/tests/mkprof/radeccat.sh
index 83c17fe..7363cf8 100755
--- a/tests/mkprof/radeccat.sh
+++ b/tests/mkprof/radeccat.sh
@@ -53,4 +53,4 @@ if [ ! -f $cat      ]; then echo "$cat does not exist.";   
exit 77; fi
 # string. Such programs will execute the command if present and help in
 # debugging when the developer doesn't have access to the user's system.
 $check_with_program $execname $cat --ccol=RA --ccol=Dec --mode=wcs   \
-                              --naxis=100,100
+                              --mergedsize=100,100



reply via email to

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