gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 313d522 099/113: Imported recent work in maste


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 313d522 099/113: Imported recent work in master, minor conflict fixed
Date: Fri, 16 Apr 2021 10:33:59 -0400 (EDT)

branch: master
commit 313d522d9b159f11a342ff3299e0fb744f92922b
Merge: 924787b a516aae
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Imported recent work in master, minor conflict fixed
    
    There was a minor conflict in the book which was fixed by simply using the
    `master' branch version.
---
 NEWS                               |  40 ++++-
 bin/arithmetic/args.h              |  26 ++++
 bin/arithmetic/arithmetic.c        |  67 ++++++--
 bin/arithmetic/astarithmetic.conf  |   3 +
 bin/arithmetic/main.h              |   8 +-
 bin/arithmetic/operands.c          |  25 ++-
 bin/arithmetic/ui.c                | 118 +++++++++++---
 bin/arithmetic/ui.h                |   6 +-
 bin/buildprog/ui.c                 |   1 -
 bin/convertt/args.h                |  16 +-
 bin/convertt/color.c               |  46 ++++--
 bin/convertt/convertt.c            |   4 +-
 bin/convertt/main.h                |   4 +-
 bin/convertt/ui.h                  |   4 +-
 bin/fits/fits.c                    |   1 +
 bin/fits/ui.c                      |   1 -
 bin/match/main.h                   |   2 +
 bin/match/match.c                  | 129 ++++++++++++++--
 bin/match/ui.c                     |   2 +-
 bin/noisechisel/threshold.c        |  91 +++++++----
 bootstrap                          |  12 +-
 bootstrap.conf                     |   2 +
 doc/announce-acknowledge.txt       |   2 +
 doc/gnuastro.texi                  | 306 +++++++++++++++++++++++++++----------
 lib/blank.c                        |  28 ++++
 lib/checkset.c                     |  74 ++++++++-
 lib/fits.c                         |   4 +
 lib/gnuastro-internal/checkset.h   |   5 +-
 lib/gnuastro-internal/commonopts.h |  14 ++
 lib/gnuastro-internal/options.h    |   6 +
 lib/gnuastro/blank.h               |   3 +
 lib/gnuastro/statistics.h          |   5 +
 lib/jpeg.c                         |  10 +-
 lib/options.c                      | 181 +++++++++++++++++++---
 lib/pointer.c                      |  32 +++-
 lib/statistics.c                   | 102 ++++++++++++-
 36 files changed, 1142 insertions(+), 238 deletions(-)

diff --git a/NEWS b/NEWS
index 6ec5a75..b110e67 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,23 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
 
 ** New features
 
+  All programs:
+   --checkconfig: print the names and values given to options as they are
+     parsed on the command-line or in various configuration files (the
+     configuration file name is also printed). This can be very useful in
+     debugging (finding which configuration file is responsible for a given
+     option's value).
+
+  Arithmetic:
+   - The new `tofile-' operator will save the top operand into a file
+     without changing the state of the operand stack (popping the top
+     element). This can greatly help in debugging/understanding an
+     Arithmetic command, especially as it gets longer, or more complicated.
+   --wcsfile and --wcshdu: these two options can be used to specify a
+     different file for reading the WCS of the output. This is useful when
+     the default (theh WCS of the first dataset that is read) is not the
+     required one.
+
   Fits:
    - Add "title" to group FITS keywords with `--write=/,"title name". This
      "title" is composed of two keyword records: a blank one, followed by
@@ -20,18 +37,39 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
      FITS HDU/extension into another (possibly in another file).
    --outhdu: The name/number of the output HDU (for `--copykeys').
 
+  Match:
+   - All the columns from one of the input catalogs can now be merged with
+     any of the columns of the second using the special `_all' name of
+     `--outcols'. For example the output of `--outcols=a_all,b5' will
+     contain all the columns from the first input and the 5th column of the
+     second input. This greatly simplifies the mergining of different table
+     columns into one.
+
   Library:
     GAL_BLANK_LONG: new macro for the `long' type blank value.
     GAL_BLANK_ULONG: new macro for the `unsigned long' type blank value.
+    gal_blank_number: Return the number of blank elements in a dataset.
+    gal_statistics_outlier_cumulative: Uses flatness of the cumulative
+       distribution to find outliers.
 
 ** Removed features
 
 ** Changed features
 
+  ConvertType:
+   --forcemin & --forcemax: until now, `--flminbyte' and `--flmaxbyte' were
+     used to force the range of conversion to color channels (even if the
+     range is beyond the limits of the dataset). With the introduction of
+     color maps in Gnuastro 0.8, it is also necessary to force a range on
+     non-byte datasets. It is thus necessary to use a more generic name.
+
 ** Bugs fixed
   bug #55313: Fits program writing --write values in reverse order
   bug #55333: Fits program crash when --write or --update have no value.
-
+  bug #55439: Arithmetic segmentation fault when reusing dataset name.
+  bug #55478: Memory mapping crashes when .gnuastro is not writable.
+  bug #55491: NoiseChisel crash when no tiles good for quantile thresholding.
+  bug #55544: Arithmetic's output WCS with where operator is not as expected.
 
 
 
diff --git a/bin/arithmetic/args.h b/bin/arithmetic/args.h
index 1ef24dd..987148d 100644
--- a/bin/arithmetic/args.h
+++ b/bin/arithmetic/args.h
@@ -41,6 +41,32 @@ struct argp_option program_options[] =
       GAL_OPTIONS_NOT_MANDATORY,
       GAL_OPTIONS_NOT_SET
     },
+    {
+      "wcsfile",
+      UI_KEY_WCSFILE,
+      "STR",
+      0,
+      "File to use for output's WCS.",
+      GAL_OPTIONS_GROUP_INPUT,
+      &p->wcsfile,
+      GAL_TYPE_STRING,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+    {
+      "wcshdu",
+      UI_KEY_WCSHDU,
+      "STR",
+      0,
+      "HDU/extension to use for output's WCS.",
+      GAL_OPTIONS_GROUP_INPUT,
+      &p->wcshdu,
+      GAL_TYPE_STRING,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
 
 
 
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index a827db7..886d61c 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -781,13 +781,17 @@ arithmetic_collapse(struct arithmeticparams *p, char 
*token, int operator)
     }
 
 
-  /* We'll also need to correct the size of the reference dataset. We'll
-     use `memcpy' to write the new `dsize' values into the old ones. The
-     dimensions have decreased, so we won't be writing outside of allocated
-     space that `p->refdata.dsize' points to. */
-  p->refdata.ndim -= 1;
-  memcpy( p->refdata.dsize, collapsed->dsize,
-           p->refdata.ndim * (sizeof *p->refdata.dsize) );
+  /* We'll also need to correct the size of the reference dataset if it
+     hasn't been corrected yet. We'll use `memcpy' to write the new `dsize'
+     values into the old ones. The dimensions have decreased, so we won't
+     be writing outside of allocated space that `p->refdata.dsize' points
+     to. */
+  if( p->refdata.ndim != collapsed->ndim )
+    {
+      p->refdata.ndim -= 1;
+      memcpy( p->refdata.dsize, collapsed->dsize,
+              p->refdata.ndim * (sizeof *p->refdata.dsize) );
+    }
 
 
   /* Clean up and add the collapsed dataset to the top of the operands. */
@@ -800,6 +804,32 @@ arithmetic_collapse(struct arithmeticparams *p, char 
*token, int operator)
 
 
 
+void
+arithmetic_tofile(struct arithmeticparams *p, char *token)
+{
+  /* Pop the top dataset. */
+  gal_data_t *popped = operands_pop(p, token);
+  char *filename=&token[ OPERATOR_PREFIX_LENGTH_TOFILE ];
+
+  /* Save it to a file. */
+  popped->wcs=p->refdata.wcs;
+  if(popped->ndim==1 && p->onedasimage==0)
+    gal_table_write(popped, NULL, p->cp.tableformat, filename,
+                    "ARITHMETIC", 0);
+  else
+    gal_fits_img_write(popped, filename, NULL, PROGRAM_NAME);
+  if(!p->cp.quiet)
+    printf(" - Write: %s\n", filename);
+
+  /* Reset the WCS to NULL and put it back on the stack. */
+  popped->wcs=NULL;
+  operands_add(p, NULL, popped);
+}
+
+
+
+
+
 
 
 
@@ -844,17 +874,22 @@ reversepolish(struct arithmeticparams *p)
   /* Go over each input token and do the work. */
   for(token=p->tokens;token!=NULL;token=token->next)
     {
-      /* If we have a name or number, then add it to the operands linked
-         list. Otherwise, pull out two members and do the specified
-         operation on them. */
-      if( gal_array_name_recognized(token->v)
+      /* The `tofile-' operator's string can end in a `.fits', similar to a
+         FITS file input file. So, it needs to be checked before checking
+         for a filename. If we have a name or number, then add it to the
+         operands linked list. Otherwise, pull out two members and do the
+         specified operation on them. */
+      if( !strncmp(OPERATOR_PREFIX_TOFILE, token->v,
+                   OPERATOR_PREFIX_LENGTH_TOFILE) )
+        arithmetic_tofile(p, token->v);
+      else if( !strncmp(token->v, OPERATOR_PREFIX_SET,
+                        OPERATOR_PREFIX_LENGTH_SET) )
+        operands_set_name(p, token->v);
+      else if( gal_array_name_recognized(token->v)
           || operands_is_name(p, token->v) )
         operands_add(p, token->v, NULL);
       else if( (d1=gal_data_copy_string_to_number(token->v)) )
         operands_add(p, NULL, d1);
-      else if( !strncmp(token->v, SET_OPERATOR_PREFIX,
-                        SET_OPERATOR_PREFIX_LENGTH) )
-        operands_set_name(p, token->v);
       else
         {
 
@@ -1146,9 +1181,9 @@ reversepolish(struct arithmeticparams *p)
       filename=p->operands->filename;
       if( gal_fits_name_is_fits(filename) )
         {
+          /* Read the data, note that the WCS has already been set. */
           p->operands->data=gal_array_read_one_ch(filename, hdu, NULL,
                                                   p->cp.minmapsize);
-          p->refdata.wcs=gal_wcs_read(filename, hdu, 0, 0, &p->refdata.nwcs);
           if(!p->cp.quiet) printf(" - %s (hdu %s) is read.\n", filename, hdu);
         }
       else
@@ -1182,7 +1217,7 @@ reversepolish(struct arithmeticparams *p)
       else
         gal_fits_img_write(d1, p->cp.output, NULL, PROGRAM_NAME);
       if(!p->cp.quiet)
-        printf(" - Output written to %s\n", p->cp.output);
+        printf(" - Write (final): %s\n", p->cp.output);
     }
 
 
diff --git a/bin/arithmetic/astarithmetic.conf 
b/bin/arithmetic/astarithmetic.conf
index 7b82ea6..ff83a14 100644
--- a/bin/arithmetic/astarithmetic.conf
+++ b/bin/arithmetic/astarithmetic.conf
@@ -16,3 +16,6 @@
 # permitted in any medium without royalty provided the copyright notice and
 # this notice are preserved.  This file is offered as-is, without any
 # warranty.
+
+# Inputs
+ wcshdu        1
\ No newline at end of file
diff --git a/bin/arithmetic/main.h b/bin/arithmetic/main.h
index 2d30c32..d6f6661 100644
--- a/bin/arithmetic/main.h
+++ b/bin/arithmetic/main.h
@@ -40,8 +40,10 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 /* Constants: */
 #define NEG_DASH_REPLACE 11 /* Vertical tab (ASCII=11) for negative dash */
-#define SET_OPERATOR_PREFIX        "set-"
-#define SET_OPERATOR_PREFIX_LENGTH strlen(SET_OPERATOR_PREFIX)
+#define OPERATOR_PREFIX_SET               "set-"
+#define OPERATOR_PREFIX_TOFILE            "tofile-"
+#define OPERATOR_PREFIX_LENGTH_SET        strlen(OPERATOR_PREFIX_SET)
+#define OPERATOR_PREFIX_LENGTH_TOFILE     strlen(OPERATOR_PREFIX_TOFILE)
 
 
 
@@ -71,6 +73,8 @@ struct arithmeticparams
   /* Input: */
   gal_list_str_t     *hdus;  /* List of all given HDU strings.          */
   gal_list_str_t   *tokens;  /* List of all arithmetic tokens.          */
+  char            *wcsfile;  /* File to use for output's WCS.           */
+  char             *wcshdu;  /* Extension to use for output's WCS.      */
   size_t        popcounter;  /* The number of FITS images popped.       */
   gal_data_t       refdata;  /* Container for information of the data.  */
   char          *globalhdu;  /* Single HDU for all inputs.              */
diff --git a/bin/arithmetic/operands.c b/bin/arithmetic/operands.c
index b1062f5..a5071f7 100644
--- a/bin/arithmetic/operands.c
+++ b/bin/arithmetic/operands.c
@@ -141,7 +141,7 @@ void
 operands_set_name(struct arithmeticparams *p, char *token)
 {
   gal_data_t *tmp, *tofree;
-  char *varname=&token[ SET_OPERATOR_PREFIX_LENGTH ];
+  char *varname=&token[ OPERATOR_PREFIX_LENGTH_SET ];
 
   /* If a dataset with this name already exists, it will be removed/deleted
      so we can use the name for the newly designated dataset. */
@@ -150,6 +150,12 @@ operands_set_name(struct arithmeticparams *p, char *token)
       {
         tofree=operands_remove_name(p, varname);
         gal_data_free(tofree);
+
+        /* IMPORTANT: we MUST break here! `tmp' does't point to the right
+           place any more. We can define a `prev' node and modify it on
+           every attempt, but since there is only one dataset with a given
+           name, that is redundant and will just make the program slow. */
+        break;
       }
 
   /* Pop the top operand, then add it to the list of named datasets, but
@@ -298,6 +304,15 @@ operands_add(struct arithmeticparams *p, char *filename, 
gal_data_t *data)
                 gal_checkset_allocate_copy(p->globalhdu, &newnode->hdu);
               else
                 newnode->hdu=gal_list_str_pop(&p->hdus);
+
+              /* If no WCS is set yet, use the WCS of this image. */
+              if(p->refdata.wcs==NULL)
+                {
+                  p->refdata.wcs=gal_wcs_read(filename, newnode->hdu, 0, 0,
+                                              &p->refdata.nwcs);
+                  if(p->refdata.wcs && !p->cp.quiet)
+                    printf(" - WCS: %s (hdu %s).\n", filename, newnode->hdu);
+                }
             }
           else newnode->hdu=NULL;
         }
@@ -343,12 +358,6 @@ operands_pop(struct arithmeticparams *p, char *operator)
          identify variables. */
       if(data->name) { free(data->name); data->name=NULL; }
 
-      /* In case this is the first image that is read, then keep the WCS
-         information in the `refdata' structure.  */
-      if(p->popcounter==0)
-        p->refdata.wcs=gal_wcs_read(filename, hdu, 0, 0,
-                                    &p->refdata.nwcs);
-
       /* When the reference data structure's dimensionality is non-zero, it
          means that this is not the first image read. So, write its basic
          information into the reference data structure for future
@@ -381,7 +390,7 @@ operands_pop(struct arithmeticparams *p, char *operator)
         }
 
       /* Report the read image if desired: */
-      if(!p->cp.quiet) printf(" - %s (hdu %s) is read.\n", filename, hdu);
+      if(!p->cp.quiet) printf(" - Read: %s (hdu %s).\n", filename, hdu);
 
       /* Free the HDU string: */
       if(hdu) free(hdu);
diff --git a/bin/arithmetic/ui.c b/bin/arithmetic/ui.c
index bf41d96..c4baea8 100644
--- a/bin/arithmetic/ui.c
+++ b/bin/arithmetic/ui.c
@@ -28,6 +28,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <stdio.h>
 #include <string.h>
 
+#include <gnuastro/wcs.h>
 #include <gnuastro/list.h>
 #include <gnuastro/fits.h>
 #include <gnuastro/table.h>
@@ -225,14 +226,35 @@ parse_opt(int key, char *arg, struct argp_state *state)
 /**************************************************************/
 /***************       Sanity Check         *******************/
 /**************************************************************/
+static void
+ui_read_check_only_options(struct arithmeticparams *p)
+{
+  if(p->wcsfile)
+    {
+      if(gal_fits_name_is_fits(p->wcsfile)==0)
+        error(EXIT_FAILURE, 0, "%s: file given to `--wcsfile' must be in "
+              "FITS format with a recognizable FITS format suffix.",
+              p->wcsfile);
+      if(p->wcshdu==NULL)
+        error(EXIT_FAILURE, 0, "%s: no HDU/extension specified (file given "
+              "to `--wcsfile')! Please use `--wcshdu' to specify a "
+              "HDU/extension to read from", p->wcsfile);
+    }
+}
+
+
+
+
+
 /* Sanity check on options AND arguments. If only option values are to be
    checked, use `ui_read_check_only_options'. */
 static void
 ui_check_options_and_arguments(struct arithmeticparams *p)
 {
+  char *filename;
   int output_checked=0;
-  size_t nummultiext=0, numhdus=0;
   gal_list_str_t *token, *hdu;
+  size_t nummultiext=0, numhdus=0;
 
   /* First, make sure that any tokens are actually given. */
   if(p->tokens==NULL)
@@ -256,33 +278,51 @@ ui_check_options_and_arguments(struct arithmeticparams *p)
      list. */
   for(token=p->tokens; token!=NULL; token=token->next)
     {
-      /* This token is a file, count how many mult-extension files we haev
-         and use the first to set the output filename (if it has not been
-         set). */
-      if( gal_array_name_recognized(token->v) )
-        {
-          /* Increment the counter for FITS files. */
-          if( gal_array_name_recognized_multiext(token->v) )
-            ++nummultiext;
+      /* Strings given to the `tofile' operator are also considered as
+         outputs and we should delete them before starting the parse. */
+      if( strncmp(OPERATOR_PREFIX_TOFILE, token->v,
+                  OPERATOR_PREFIX_LENGTH_TOFILE) )
 
-          /* If the output filename isn't set yet, then set it. */
-          if(output_checked==0)
+        {
+          /* This token is a file, count how many mult-extension files we
+             haev and use the first to set the output filename (if it has
+             not been set). */
+          if( gal_array_name_recognized(token->v) )
             {
-              if(p->cp.output)
-                gal_checkset_writable_remove(p->cp.output, 0,
-                                             p->cp.dontdelete);
-              else
-                p->cp.output=gal_checkset_automatic_output(&p->cp, token->v,
-                                                           "_arith.fits");
-              output_checked=1;
+              /* Increment the counter for FITS files (if they are
+                 input). Recall that the `tofile' operator can also have
+                 `.fits' suffixes (they are the names of the output
+                 files). */
+              if( gal_array_name_recognized_multiext(token->v)  )
+                ++nummultiext;
+
+              /* If the output filename isn't set yet, then set it. */
+              if(output_checked==0)
+                {
+                  if(p->cp.output)
+                    gal_checkset_writable_remove(p->cp.output, 0,
+                                                 p->cp.dontdelete);
+                  else
+                    p->cp.output=gal_checkset_automatic_output(&p->cp,
+                                                               token->v,
+                                                               "_arith.fits");
+                  output_checked=1;
+                }
             }
+
+          /* This token is a number. Check if a negative dash was present that
+             has been temporarily replaced with `NEG_DASH_REPLACE' before
+             option parsing. */
+          else if(token->v[0]==NEG_DASH_REPLACE && isdigit(token->v[1]) )
+            token->v[0]='-';
         }
 
-      /* This token is a number. Check if a negative dash was present that
-         has been temporarily replaced with `NEG_DASH_REPLACE' before
-         option parsing. */
-      else if(token->v[0]==NEG_DASH_REPLACE && isdigit(token->v[1]) )
-        token->v[0]='-';
+      /* We are on the `tofile' operator. */
+      else
+        {
+          filename=&token->v[ OPERATOR_PREFIX_LENGTH_TOFILE ];
+          gal_checkset_writable_remove(filename, 0, p->cp.dontdelete);
+        }
     }
 
   /* Count the number of HDU values (if globalhdu isn't given) and check if
@@ -308,6 +348,30 @@ ui_check_options_and_arguments(struct arithmeticparams *p)
 
 
 
+static void
+ui_preparations(struct arithmeticparams *p)
+{
+  /* In case a file is specified to read the WCS from (and ignore input
+     datasets), read the WCS prior to starting parsing of the arguments. */
+  if(p->wcsfile)
+    {
+      p->refdata.wcs=gal_wcs_read(p->wcsfile, p->wcshdu, 0, 0,
+                                  &p->refdata.nwcs);
+      if(p->refdata.wcs)
+        {
+          if(!p->cp.quiet)
+            printf(" - WCS: %s (hdu %s).\n", p->wcsfile, p->wcshdu);
+        }
+      else
+        fprintf(stderr, "WARNING: %s (hdu %s) didn't contain a "
+                "(readable by WCSLIB) WCS.", p->wcsfile, p->wcshdu);
+    }
+}
+
+
+
+
+
 
 
 
@@ -373,10 +437,18 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct 
arithmeticparams *p)
   gal_options_print_state(cp);
 
 
+  /* Sanity check only on options. */
+  ui_read_check_only_options(p);
+
+
   /* Check that the options and arguments fit well with each other. Note
      that arguments don't go in a configuration file. So this test should
      be done after (possibly) printing the option values. */
   ui_check_options_and_arguments(p);
+
+
+  /* Initial preparations. */
+  ui_preparations(p);
 }
 
 
diff --git a/bin/arithmetic/ui.h b/bin/arithmetic/ui.h
index 6ee011a..ebd20f8 100644
--- a/bin/arithmetic/ui.h
+++ b/bin/arithmetic/ui.h
@@ -32,14 +32,16 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 /* Available letters for short options:
 
-   a b c d e f i j k l m n p r s t u v w x y z
-   A B C E G H J L Q R W X Y
+   a b c d e f i j k l m n p r s t u v x y z
+   A B C E G H J L Q R X Y
 */
 enum option_keys_enum
 {
   /* With short-option version. */
   UI_KEY_GLOBALHDU       = 'g',
   UI_KEY_ONEDASIMAGE     = 'O',
+  UI_KEY_WCSFILE         = 'w',
+  UI_KEY_WCSHDU          = 'W',
 
   /* Only with long version (start with a value 1000, the rest will be set
      automatically). */
diff --git a/bin/buildprog/ui.c b/bin/buildprog/ui.c
index edb12f3..9d51f20 100644
--- a/bin/buildprog/ui.c
+++ b/bin/buildprog/ui.c
@@ -123,7 +123,6 @@ ui_initialize_options(struct buildprogparams *p,
         case GAL_OPTIONS_KEY_TYPE:
         case GAL_OPTIONS_KEY_SEARCHIN:
         case GAL_OPTIONS_KEY_NUMTHREADS:
-        case GAL_OPTIONS_KEY_MINMAPSIZE:
         case GAL_OPTIONS_KEY_TABLEFORMAT:
         case GAL_OPTIONS_KEY_STDINTIMEOUT:
           cp->coptions[i].flags=OPTION_HIDDEN;
diff --git a/bin/convertt/args.h b/bin/convertt/args.h
index 52f95d6..4618a33 100644
--- a/bin/convertt/args.h
+++ b/bin/convertt/args.h
@@ -161,26 +161,26 @@ struct argp_option program_options[] =
       GAL_OPTIONS_NOT_SET
     },
     {
-      "flminbyte",
-      UI_KEY_FLMINBYTE,
+      "forcemin",
+      UI_KEY_FORCEMIN,
       0,
       0,
-      "Set value of fluxlow as the minimum byte value.",
+      "Force --fluxmin, even when smaller than minimum.",
       UI_GROUP_FLUX,
-      &p->flminbyte,
+      &p->forcemin,
       GAL_OPTIONS_NO_ARG_TYPE,
       GAL_OPTIONS_RANGE_0_OR_1,
       GAL_OPTIONS_NOT_MANDATORY,
       GAL_OPTIONS_NOT_SET
     },
     {
-      "fhmaxbyte",
-      UI_KEY_FHMAXBYTE,
+      "forcemax",
+      UI_KEY_FORCEMAX,
       0,
       0,
-      "Set value of fluxhigh as the maximum byte value.",
+      "Force --fluxmax, even when larger than maximum.",
       UI_GROUP_FLUX,
-      &p->fhmaxbyte,
+      &p->forcemax,
       GAL_OPTIONS_NO_ARG_TYPE,
       GAL_OPTIONS_RANGE_0_OR_1,
       GAL_OPTIONS_NOT_MANDATORY,
diff --git a/bin/convertt/color.c b/bin/convertt/color.c
index a7419b4..72806ee 100644
--- a/bin/convertt/color.c
+++ b/bin/convertt/color.c
@@ -28,6 +28,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <stdlib.h>
 
 #include <gnuastro/data.h>
+#include <gnuastro/statistics.h>
 
 #include "main.h"
 
@@ -40,6 +41,33 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 /***********************************************************************/
 /**************            From mono-channel           *****************/
 /***********************************************************************/
+static void
+color_min_max(struct converttparams *p, float *value, int min0max1)
+{
+  gal_data_t *tmp;
+  gal_data_t *given  = min0max1 ? p->fluxhigh : p->fluxlow;
+  uint8_t fixedlimit = min0max1 ? p->forcemax : p->forcemin;
+
+  /* Find the value to write. */
+  if(fixedlimit && given)
+    tmp=gal_data_copy_to_new_type(given, GAL_TYPE_FLOAT32);
+  else
+    {
+      tmp = ( min0max1
+              ? gal_statistics_maximum(p->chll)
+              : gal_statistics_minimum(p->chll) );
+      tmp=gal_data_copy_to_new_type_free(tmp, GAL_TYPE_FLOAT32);
+    }
+  *value=((float *)(tmp->array))[0];
+
+  /* Clean up. */
+  gal_data_free(tmp);
+}
+
+
+
+
+
 /* This algorithm is a translation of the primary algorithm in this page:
 
https://stackoverflow.com/questions/3018313/algorithm-to-convert-rgb-to-hsv-and-hsv-to-rgb-in-range-0-255-for-both
 */
 void
@@ -66,13 +94,10 @@ color_from_mono_hsv(struct converttparams *p)
     error(EXIT_FAILURE, 0, "the maximum angle (%g) must be smaller than "
           "360", h_max);
 
-  /* Convert the dataset to floating point, then change its range to the
-     given angle values. */
-  gal_type_min(GAL_TYPE_FLOAT32, &max);
-  gal_type_max(GAL_TYPE_FLOAT32, &min);
+  /* Set the range of values and convert the dataset to float. */
+  color_min_max(p, &min, 0);
+  color_min_max(p, &max, 1);
   channel=gal_data_copy_to_new_type_free(p->chll, GAL_TYPE_FLOAT32);
-  fp=(f=channel->array)+channel->size;
-  do {if(*f<min) min=*f; if(*f>max) max=*f;} while(++f<fp);
 
   /* Allocate the three datasets to keep the RGB colors. */
   R=gal_data_alloc(NULL, GAL_TYPE_FLOAT32, channel->ndim,
@@ -155,13 +180,10 @@ color_from_mono_sls(struct converttparams *p)
   gal_data_t *R, *G, *B, *channel;
   float *r, *g, *b, *f, *fp, min, max;
 
-  /* Convert the dataset to floating point, then find its minimum and
-     maximum values. */
-  gal_type_min(GAL_TYPE_FLOAT32, &max);
-  gal_type_max(GAL_TYPE_FLOAT32, &min);
+  /* Set the range, then convert the dataset to floating point. */
+  color_min_max(p, &min, 0);
+  color_min_max(p, &max, 1);
   channel=gal_data_copy_to_new_type_free(p->chll, GAL_TYPE_FLOAT32);
-  fp=(f=channel->array)+channel->size;
-  do {if(*f<min) min=*f; if(*f>max) max=*f;} while(++f<fp);
 
   /* Allocate the three datasets to keep the RGB colors. */
   R=gal_data_alloc(NULL, GAL_TYPE_FLOAT32, channel->ndim,
diff --git a/bin/convertt/convertt.c b/bin/convertt/convertt.c
index 0f22c08..3ffb66d 100644
--- a/bin/convertt/convertt.c
+++ b/bin/convertt/convertt.c
@@ -222,14 +222,14 @@ convertt_scale_to_uchar(struct converttparams *p)
      maximum and minimum values in the image.*/
   if(p->fluxlow || p->fluxhigh)
     {
-      if(p->flminbyte)
+      if(p->forcemin)
         {
           /* Convert the fluxlow value to float and put it in min. */
           copied=gal_data_copy_to_new_type(p->fluxlow, GAL_TYPE_FLOAT32);
           min = *((float *)(copied->array));
           gal_data_free(copied);
         }
-      if(p->fhmaxbyte)
+      if(p->forcemax)
         {
           /* Convert the fluxhigh value to float and put it in min. */
           copied=gal_data_copy_to_new_type(p->fluxhigh, GAL_TYPE_FLOAT32);
diff --git a/bin/convertt/main.h b/bin/convertt/main.h
index efca953..6b69968 100644
--- a/bin/convertt/main.h
+++ b/bin/convertt/main.h
@@ -90,8 +90,8 @@ struct converttparams
   char          *fluxlowstr;  /* Lower flux truncation value.          */
   char         *fluxhighstr;  /* Higher flux truncation value.         */
   uint8_t           maxbyte;  /* Maximum byte value.                   */
-  uint8_t         flminbyte;  /* fluxlow is minimum byte.              */
-  uint8_t         fhmaxbyte;  /* fluxhigh is maximum byte.             */
+  uint8_t          forcemin;  /* fluxlow is minimum.                   */
+  uint8_t          forcemax;  /* fluxhigh is maximum.                  */
   char           *changestr;  /* String of change values.              */
   uint8_t  changeaftertrunc;  /* First convert, then truncate.         */
   uint8_t            invert;  /* ==1: invert the output image.         */
diff --git a/bin/convertt/ui.h b/bin/convertt/ui.h
index 28a523e..c31a8e6 100644
--- a/bin/convertt/ui.h
+++ b/bin/convertt/ui.h
@@ -55,8 +55,8 @@ enum option_keys_enum
   UI_KEY_FLUXLOW             = 'L',
   UI_KEY_FLUXHIGH            = 'H',
   UI_KEY_MAXBYTE             = 'm',
-  UI_KEY_FLMINBYTE           = 'A',
-  UI_KEY_FHMAXBYTE           = 'B',
+  UI_KEY_FORCEMIN            = 'A',
+  UI_KEY_FORCEMAX            = 'B',
   UI_KEY_CHANGE              = 'c',
   UI_KEY_CHANGEAFTERTRUNC    = 'C',
   UI_KEY_INVERT              = 'i',
diff --git a/bin/fits/fits.c b/bin/fits/fits.c
index 2220a9d..24e58ec 100644
--- a/bin/fits/fits.c
+++ b/bin/fits/fits.c
@@ -359,6 +359,7 @@ fits(struct fitsparams *p)
 
     /* HDU, functions defined here. */
     case FITS_MODE_HDU:
+
       /* Options that must be called alone. */
       if(p->numhdus)
         fits_hdu_number(p);
diff --git a/bin/fits/ui.c b/bin/fits/ui.c
index 04defd6..fdbe637 100644
--- a/bin/fits/ui.c
+++ b/bin/fits/ui.c
@@ -121,7 +121,6 @@ ui_initialize_options(struct fitsparams *p,
         case GAL_OPTIONS_KEY_TABLEFORMAT:
         case GAL_OPTIONS_KEY_DONTDELETE:
         case GAL_OPTIONS_KEY_LOG:
-        case GAL_OPTIONS_KEY_MINMAPSIZE:
         case GAL_OPTIONS_KEY_NUMTHREADS:
         case GAL_OPTIONS_KEY_STDINTIMEOUT:
           cp->coptions[i].flags=OPTION_HIDDEN;
diff --git a/bin/match/main.h b/bin/match/main.h
index 728daca..f9a5a85 100644
--- a/bin/match/main.h
+++ b/bin/match/main.h
@@ -66,6 +66,8 @@ struct matchparams
   gal_data_t           *cols2;  /* Column values of second input.       */
   gal_list_str_t       *acols;  /* Output columns from first input.     */
   gal_list_str_t       *bcols;  /* Output columns from second input.    */
+  size_t                 anum;  /* Number of columns in first input.    */
+  size_t                 bnum;  /* Number of columns in second input.   */
   char               *logname;  /* Name of log file.                    */
   char              *out1name;  /* Name of first matched output.        */
   char              *out2name;  /* Name of second matched output.       */
diff --git a/bin/match/match.c b/bin/match/match.c
index cc52129..94132a1 100644
--- a/bin/match/match.c
+++ b/bin/match/match.c
@@ -39,6 +39,62 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 
 
+/* Number of columns in a file. */
+static gal_list_str_t *
+match_add_all_cols(char *filename, char *extname, gal_list_str_t *stdinlines,
+                   gal_list_str_t *incols, size_t *num)
+{
+  char *tstr;
+  int tableformat;
+  gal_data_t *colinfo=NULL;
+  gal_list_str_t *tmp, *finalcols=NULL;
+  size_t i, numrows, numcols=GAL_BLANK_SIZE_T;
+
+  /* Go over all the given input columns. */
+  for(tmp=incols; tmp!=NULL; tmp=tmp->next)
+    {
+      if(!strcmp(tmp->v,"_all"))
+        {
+          /* Read all the column information (if it hasn't been read until
+             now). */
+          if( numcols == GAL_BLANK_SIZE_T )
+            {
+              colinfo=gal_table_info(filename, extname,
+                                     filename ? NULL : stdinlines, &numcols,
+                                     &numrows, &tableformat);
+              gal_data_array_free(colinfo, numcols, 1);
+            }
+
+          /* Add each column number to the list of columns. */
+          for(i=0;i<numcols;++i)
+            {
+              errno=0;
+              if( asprintf(&tstr, "%zu", i+1)<0 )
+                error(EXIT_FAILURE, errno, "asprintf allocation");
+              gal_list_str_add(&finalcols, tstr, 0);
+            }
+        }
+      else
+        gal_list_str_add(&finalcols, tmp->v, 1);
+    }
+
+  /* If a new list of columns is ready, re-order tham and write
+     them in. Note that there may be multiple `_all' terms, so we
+     need to do this after parsing all the requested columns. */
+  gal_list_str_reverse(&finalcols);
+
+  /* For a check.
+  gal_list_str_print(finalcols);
+  exit(1);
+  */
+
+  /* Clean up and return. */
+  *num=numcols;
+  return finalcols;
+}
+
+
+
 
 
 /* Read the catalog in the given file and use the given permutation to keep
@@ -48,24 +104,53 @@ match_catalog_read_write_all(struct matchparams *p, size_t 
*permutation,
                              size_t nummatched, int f1s2,
                              size_t **numcolmatch)
 {
+  int hasall=0;
   size_t origsize;
   gal_data_t *tmp, *cat;
+  gal_list_str_t *cols, *tcol;
   gal_list_void_t *arrays=NULL;
 
-  char *hdu            = (f1s2==1) ? p->cp.hdu     : p->hdu2;
-  gal_list_str_t *cols = (f1s2==1) ? p->acols      : p->bcols;
-  char *extname        = (f1s2==1) ? "INPUT_1"     : "INPUT_2";
-  char *outname        = (f1s2==1) ? p->out1name   : p->out2name;
-  char *filename       = (f1s2==1) ? p->input1name : p->input2name;
+  char *hdu              = (f1s2==1) ? p->cp.hdu     : p->hdu2;
+  gal_list_str_t *incols = (f1s2==1) ? p->acols      : p->bcols;
+  size_t *numcols        = (f1s2==1) ? &p->anum      : &p->bnum;
+  char *extname          = (f1s2==1) ? "INPUT_1"     : "INPUT_2";
+  char *outname          = (f1s2==1) ? p->out1name   : p->out2name;
+  char *filename         = (f1s2==1) ? p->input1name : p->input2name;
 
-  /* When the output contains columns from both inputs, we need to keep the
-     number of columns matched against each column identifier. */
+  /* If special columns are requested. */
   if(p->outcols)
-    *numcolmatch=gal_pointer_allocate(GAL_TYPE_SIZE_T,
-                                      gal_list_str_number(cols), 0,
-                                      __func__, "numcolmatch");
+    {
+      /* As a special situation, the user can ask to incude all of the
+         columns from one of the inputs with the special `_all' name. So,
+         we'll check if that is the case and write in all the columns where
+         they are requested.*/
+      for(tcol=incols; tcol!=NULL; tcol=tcol->next)
+        if(!strcmp(tcol->v,"_all")) { hasall=1; break; }
+
+      /* If atleast one instance of `_all' is present, then reset the list
+         of columns to include in output. */
+      if(hasall)
+        {
+          cols=match_add_all_cols(filename, hdu, p->stdinlines, incols,
+                                  numcols);
+          if(f1s2==1) { gal_list_str_free(p->acols, 0); p->acols=cols; }
+          else        { gal_list_str_free(p->bcols, 0); p->bcols=cols; }
+        }
+      else
+        cols=incols;
+
+
+      /* When the output contains columns from both inputs, we need to keep
+         the number of columns matched against each column identifier. */
+      *numcolmatch=gal_pointer_allocate(GAL_TYPE_SIZE_T,
+                                        gal_list_str_number(cols), 0,
+                                        __func__, "numcolmatch");
+    }
+  else cols=incols;
 
-  /* Read the full table. */
+
+  /* Read the full table and free the `cols' array if it was allocated
+     here. */
   cat=gal_table_read(filename, hdu, filename ? NULL : p->stdinlines, cols,
                      p->cp.searchin, p->cp.ignorecase, p->cp.minmapsize,
                      *numcolmatch);
@@ -99,7 +184,6 @@ match_catalog_read_write_all(struct matchparams *p, size_t 
*permutation,
         else
           tmp->size=tmp->dsize[0]=nummatched;
       }
-
   /* If no match was found (`permutation==NULL'), and the matched columns
      are requested, empty all the columns that are to be written (only
      keeping the meta-data). */
@@ -158,7 +242,7 @@ match_catalog_write_one(struct matchparams *p, gal_data_t 
*a, gal_data_t *b,
                         size_t *acolmatch, size_t *bcolmatch)
 {
   gal_data_t *cat=NULL;
-  size_t i, j, ac=0, bc=0;
+  size_t i, j, k, ac=0, bc=0, npop;
   char **strarr=p->outcols->array;
 
   /* Go over the initial list of strings. */
@@ -167,13 +251,21 @@ match_catalog_write_one(struct matchparams *p, gal_data_t 
*a, gal_data_t *b,
       {
       case 'a':
         for(j=0;j<acolmatch[ac];++j)
-          gal_list_data_add(&cat, gal_list_data_pop(&a));
+          {
+            npop = strcmp(strarr[i]+1,"_all") ? 1 : p->anum;
+            for(k=0;k<npop;++k)
+              gal_list_data_add(&cat, gal_list_data_pop(&a));
+          }
         ac++;
         break;
 
       case 'b':
         for(j=0;j<bcolmatch[bc];++j)
-          gal_list_data_add(&cat, gal_list_data_pop(&b));
+          {
+            npop = strcmp(strarr[i]+1,"_all") ? 1 : p->bnum;
+            for(k=0;k<npop;++k)
+              gal_list_data_add(&cat, gal_list_data_pop(&b));
+          }
         bc++;
         break;
 
@@ -183,6 +275,13 @@ match_catalog_write_one(struct matchparams *p, gal_data_t 
*a, gal_data_t *b,
               PACKAGE_BUGREPORT, i, strarr[i][0]);
       }
 
+  /* A small sanity check. */
+  if(a || b)
+    error(EXIT_FAILURE, 0, "%s: a bug! Please contact us to fix the problem. "
+          "The two `a' and `b' arrays must be NULL by this point: "
+          "`a' %s NULL, `b' %s NULL", __func__, a?"is not":"is",
+          b?"is not":"is");
+
   /* Reverse the table and write it out. */
   gal_list_data_reverse(&cat);
   gal_table_write(cat, NULL, p->cp.tableformat, p->out1name, "MATCHED", 0);
diff --git a/bin/match/ui.c b/bin/match/ui.c
index 8c7fe8d..df1fb9b 100644
--- a/bin/match/ui.c
+++ b/bin/match/ui.c
@@ -547,7 +547,7 @@ ui_read_columns_to_double(struct matchparams *p, char 
*filename, char *hdu,
     "Please give more specific values to `--ccol1' (column "
     "numberes are the only identifiers guaranteed to be unique).";
 
-  /* Read the columns. Note that the first input's name can be NULL (it the
+  /* Read the columns. Note that the first input's name can be NULL (if the
      user intended to use the standrad input). Also note that this function
      is called more than one time, so if the Standard input is already read
      once, we don't want to write a blank list over it (the Standard input
diff --git a/bin/noisechisel/threshold.c b/bin/noisechisel/threshold.c
index 1132742..11a56a6 100644
--- a/bin/noisechisel/threshold.c
+++ b/bin/noisechisel/threshold.c
@@ -518,13 +518,72 @@ qthresh_on_tile(void *in_prm)
 
 
 
+static void
+threshold_good_error(size_t number, int before0_after1, size_t interpnumngb)
+{
+  before0_after1=1;
+
+  /* Set the differing strings. */
+  char *in1 = ( before0_after1
+                ? "after removing outliers"
+                : "for defining a quantile threshold" );
+  char *in2 = ( before0_after1
+                ? ""
+                : "NOTE that this is happening *BEFORE* outlier rejection "
+                  "(where the number may decrease even further).");
+  char *in3 = ( before0_after1
+                ? "\n"
+                  "  - (slightly) Increase `--outliersclip' to reject less "
+                  "as outliers.\n"
+                  "  - (slightly) Increase `--outliersigma' to reject less "
+                  "as outliers.\n"
+                : "\n");
+
+  /* Print the error message and abort. */
+  error(EXIT_FAILURE, 0, "%zu tiles usable %s!\n\n"
+
+        "This is smaller than the requested minimum value of %zu (value to "
+        "the `--interpnumngb' option). %s\n\n"
+
+        "There are several ways to address the problem. The best and most "
+        "highly recommended is to use a larger input if possible (when the "
+        "input is a crop from a larger dataset). If this is not the case, "
+        "or it doesn't solve the problem, you need to loosen the "
+        "parameters mentioned below in the respective order (and therefore "
+        "cause scatter/inaccuracy in the final result). Hence its best to "
+        "not loosen them too much (recall that you can see all the option "
+        "values to Gnuastro's programs by appending `-P' to the end of your "
+        "command).\n"
+        "  - (slightly) Decrease `--tilesize' so your tile-grid has more "
+        "tiles.\n"
+        "  - (slightly) Increase `--meanmedqdiff' to accept more tiles.%s"
+        "  - (slightly) Decrease `--interpnumngb' to be less than %zu.\n\n"
+
+        "---- Tip ----\n"
+        "Append your command with `--checkqthresh' to see the "
+        "successful tiles in relation with this dataset's contents "
+        "before this crash. A visual inspection will greatly help in "
+        "finding the cause/solution for this particular dataset (note "
+        "that the output of `--checkqthresh' is a multi-extension FITS "
+        "file).\n\n"
+        "To better understand this important step, please run the "
+        "following command (press `SPACE'/arrow-keys to navigate and "
+        "`Q' to return back to the command-line):\n\n"
+        "    $ info gnuastro \"Quantifying signal in a tile\"\n", number,
+        in1, interpnumngb, in2, in3, number);
+}
+
+
+
+
+
 void
 threshold_quantile_find_apply(struct noisechiselparams *p)
 {
   char *msg;
-  size_t nval;
   gal_data_t *num;
   struct timeval t1;
+  size_t nval, nblank;
   struct qthreshparams qprm;
   struct gal_options_common_params *cp=&p->cp;
   struct gal_tile_two_layer_params *tl=&cp->tl;
@@ -601,6 +660,10 @@ threshold_quantile_find_apply(struct noisechiselparams *p)
         }
     }
 
+  /* A small sanity check. */
+  nblank=gal_blank_number(qprm.erode_th, 1);
+  if( nblank > qprm.erode_th->size-cp->interpnumngb )
+    threshold_good_error(qprm.erode_th->size-nblank, 0, cp->interpnumngb);
 
   /* Remove outliers if requested. */
   if(p->outliersigma!=0.0)
@@ -616,31 +679,7 @@ threshold_quantile_find_apply(struct noisechiselparams *p)
   num=gal_statistics_number(qprm.erode_th);
   nval=((size_t *)(num->array))[0];
   if( nval < cp->interpnumngb )
-    error(EXIT_FAILURE, 0, "%zu tile(s) can be used for interpolation of the "
-          "quantile threshold values over the full dataset. This is smaller "
-          "than the requested minimum value of %zu (value to the "
-          "`--interpnumngb' option).\n\n"
-          "There are several ways to address the problem. The best and most "
-          "highly recommended is to use a larger input if possible (when the "
-          "input is a crop from a larger dataset). If that is not the case, "
-          "or it doesn't solve the problem, you need to loosen the "
-          "parameters (and therefore cause scatter in the final result). "
-          "Thus don't loosen them too much. Recall that you can see all the "
-          "option values to Gnuastro's programs by appending `-P' to the "
-          "end of your command.\n\n"
-          "  * Slightly decrease `--tilesize' to have more tiles.\n"
-          "  * Slightly increase `--meanmedqdiff' to accept more tiles.\n"
-          "  * Decrease `--outliersigma' to reject less tiles as outliers.\n"
-          "  * Decrease `--interpnumngb' to be smaller than %zu.\n\n"
-          "Append the previous command with `--checkqthresh' to see the "
-          "successful tiles and which were discarded as outliers. This will "
-          "help you find the cause/solution. Note that the output is a "
-          "multi-extension FITS file).\n\n"
-          "To better understand this important step, please run the "
-          "following command (press `SPACE'/arrow-keys to navigate and "
-          "`Q' to return back to the command-line):\n\n"
-          "    $ info gnuastro \"Quantifying signal in a tile\"\n",
-          nval, cp->interpnumngb, cp->interpnumngb);
+    threshold_good_error(nval, 1, cp->interpnumngb);
 
 
   /* Interpolate and smooth the derived values. */
diff --git a/bootstrap b/bootstrap
index c13b486..5b08e7e 100755
--- a/bootstrap
+++ b/bootstrap
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Print a version string.
-scriptversion=2018-10-13.05; # UTC
+scriptversion=2019-01-04.17; # UTC
 
 # Bootstrap this package from checked-out sources.
 
@@ -963,6 +963,16 @@ fi
 bootstrap_post_import_hook \
   || die "bootstrap_post_import_hook failed"
 
+# Don't proceed if there are uninitialized submodules.  In particular,
+# the next step will remove dangling links, which might be links into
+# uninitialized submodules.
+#
+# Uninitialized submodules are listed with an initial dash.
+if $use_git && git submodule | grep '^-' >/dev/null; then
+  die "some git submodules are not initialized. "     \
+      "Run 'git submodule init' and bootstrap again."
+fi
+
 # Remove any dangling symlink matching "*.m4" or "*.[ch]" in some
 # gnulib-populated directories.  Such .m4 files would cause aclocal to fail.
 # The following requires GNU find 4.2.3 or newer.  Considering the usual
diff --git a/bootstrap.conf b/bootstrap.conf
index 4112a1c..82baa12 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -215,6 +215,7 @@ gnulib_modules="
     func
     math
     argp
+    fcntl
     regex
     error
     nproc
@@ -226,6 +227,7 @@ gnulib_modules="
     gpl-3.0
     mbstok_r
     inttypes
+    faccessat
     system-posix
     secure_getenv
     git-version-gen
diff --git a/doc/announce-acknowledge.txt b/doc/announce-acknowledge.txt
index 3e63c06..d690df8 100644
--- a/doc/announce-acknowledge.txt
+++ b/doc/announce-acknowledge.txt
@@ -1 +1,3 @@
 Alphabetically ordered list to acknowledge in the next release.
+
+Raúl Infante Sainz
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 1cd4de0..1b24a08 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -3631,21 +3631,22 @@ columns (see below for why we have requested an 
aperture of 0.35
 arcseconds, or less than 6 HST pixels).
 
 The @option{--outcols} is a very convenient feature in Match: you can use
-it to specify which columns from the two catalogs you want in the
-output. If the first character is an `@key{a}', the respective matched
-column (number or name, similar to Table above) in the first catalog will
-be written in the output table. When the first character is a `@key{b}',
-the respective column from the second catalog will be written in the
-output. You can use this to mix the desired matched columns from both
-catalogs in the output.
+it to specify which columns from the two catalogs you want in the output
+(merge two input catalogs into one). If the first character is an
+`@key{a}', the respective matched column (number or name, similar to Table
+above) in the first catalog will be written in the output table. When the
+first character is a `@key{b}', the respective column from the second
+catalog will be written in the output. Also, if the first character is
+followed by @code{_all}, then all the columns from the respective catalog
+will be put in the output.
 
 @example
 $ astmatch cat/xdf-f160w.fits           cat/xdf-f105w.fits         \
            --hdu=CLUMPS                 --hdu2=CLUMPS              \
            --ccol1=RA,DEC               --ccol2=RA,DEC             \
-           --aperture=0.35/3600                                    \
-           --outcols=a1,a2,aRA,aDEC,aMAGNITUDE,aSN,bMAGNITUDE,bSN  \
-           --log --output=cat/xdf-f160w-f105w.fits
+           --aperture=0.35/3600 --log                              \
+           --outcols=a_all,bMAGNITUDE,bSN                          \
+           --output=cat/xdf-f160w-f105w.fits
 @end example
 
 By default (when @option{--quiet} isn't called), the Match program will
@@ -7040,7 +7041,7 @@ your linker to look in this directory. To do so, 
configure Gnuastro like
 this:
 
 @example
-$ ./configure LDFLAGS="-I/usr/local/lib"
+$ ./configure LDFLAGS="-L/usr/local/lib"
 @end example
 
 If you want to use the libraries for your other programming projects, then
@@ -7699,9 +7700,15 @@ The minimum size (in bytes) to store the contents of 
each main processing
 array of a program as a file (on the non-volatile HDD/SSD), not in
 RAM. This can be very useful for large datasets which can be very memory
 intensive such that your RAM will not be sufficient to keep/process them. A
-random filename is assigned to the array (in a @file{.gnuastro} directory
-within the running directory) which will keep the contents of the array as
-long as it is necessary.
+random filename is assigned to the array which will keep the contents of
+the array as long as it is necessary.
+
+If the @file{.gnuastro} directory exists and is writable, then the random
+file will be placed there. Otherwise, the @file{.gnuastro_mmap} directory
+will be checked. If @file{.gnuastro_mmap} does not exist, or is not
+writable also, the random file will be directly written in the current
+directory with the @file{.gnuastro_mmap_} prefix (followed by some random
+characters).
 
 When this option has a value of @code{0} (zero), all arrays that use this
 option in a program will actually be in a file (not in RAM). When the value
@@ -7722,8 +7729,8 @@ The random file will be deleted once it is no longer 
needed by the
 program. The @file{.gnuastro} directory will also be deleted if it has no
 other contents (you may also have configuration files in this directory,
 see @ref{Configuration files}). If you see randomly named files remaining
-in this directory, please send us a bug report so we address the problem,
-see @ref{Report a bug}.
+in this directory when the program finishes normally, please send us a bug
+report so we address the problem, see @ref{Report a bug}.
 
 @item -Z INT[,INT[,...]]
 @itemx --tilesize=[,INT[,...]]
@@ -7917,11 +7924,26 @@ command-line or in the configuration files. In any 
case, it will be
 immediately read (before parsing the rest of the options on the
 command-line, or lines in a configuration file).
 
-Note that by definition, later calls to a single-valued option on the
-command-line still take precedence over those of any configuration file,
-including the file(s) given to this option. Also see @option{--lastconfig}
-and @option{--onlyversion} for how this option can be used for reproducible
-results.
+Note that by definition, options on the command-line still take precedence
+over those in any configuration file, including the file(s) given to this
+option if they are called before it. Also see @option{--lastconfig} and
+@option{--onlyversion} on how this option can be used for reproducible
+results. You can use @option{--checkconfig} (below) to check/confirm the
+parsing of configuration files.
+
+@item --checkconfig
+Print options and their values, within the command-line or configuration
+files, as they are parsed (see @ref{Configuration file precedence}). If an
+option has already been set, or is ignored by the program, this option will
+also inform you with special values like @code{--ALREADY-SET--}. Only
+options that are parsed after this option are printed, so to see the
+parsing of all input options, it is recommended to put this option
+immediately after the program name before any other options.
+
+@cindex Debug
+This is a very good option to confirm where the value of each option is has
+been defined in scenarios where there are multiple configuration files (for
+debugging).
 
 @item -S
 @itemx --setdirconf
@@ -8257,21 +8279,8 @@ The option values in all the programs of Gnuastro will 
be filled in the
 following order. If an option only takes one value which is given in an
 earlier step, any value for that option in a later step will be
 ignored. Note that if the @option{lastconfig} option is specified in any
-step below, all later files will be ignored (see @ref{Operating mode
-options}). The basic idea behind setting this progressive state of checking
-for parameter values is that separate users of a computer or separate
-folders in a user's file system might need different values for some
-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 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
-@option{--setusrconf} options will also write the common options they have
-read in their produced @file{astprogname.conf}.}.
+step below, no other configuration files will be parsed (see @ref{Operating
+mode options}).
 
 @enumerate
 @item
@@ -8305,6 +8314,29 @@ system-wide installation directory (see @ref{System 
wide} for
 
 @end enumerate
 
+The basic idea behind setting this progressive state of checking for
+parameter values is that separate users of a computer or separate folders
+in a user's file system might need different values for some
+parameters.
+
+@cartouche
+@noindent
+@strong{Checking the order:} You can confirm/check the order of parsing
+configuration files using the @option{--checkconfig} option with any
+Gnuastro program, see @ref{Operating mode options}. Just be sure to place
+this option immediately after the program name, before any other option.
+@end cartouche
+
+As you see above, 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 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
+@option{--setusrconf} options will also write the common options they have
+read in their produced @file{astprogname.conf}.}.
+
 @cartouche
 @noindent
 @strong{Manipulating the order:} You can manipulate this order or add new
@@ -11052,17 +11084,18 @@ the maximum value. By doing so you will decrease the 
dynamic range. It can
 be useful if you plan to use those values for other purposes.
 
 @item -A INT
-@itemx --flminbyte=INT
-If the lowest pixel value in the input channels is larger than the value to
-@option{--fluxlow}, then that input value will be redundant. In some
-situations it might be necessary to set the minimum byte value (0) to
-correspond to that flux even if the data do not reach that value. With this
-option you can do this. Note that if the minimum pixel value is smaller
-than @option{--fluxlow}, then this option is redundant.
+@itemx --forcemin=INT
+Enforce the value of @option{--fluxlow} (when its given), even if its
+smaller than the minimum of the dataset and the output is format supporting
+color. This is particularly useful when you are converting a number of
+images to a common image format like JPEG or PDF with a single command and
+want them all to have the same range of colors, independent of the contents
+of the dataset. Note that if the minimum value is smaller than
+@option{--fluxlow}, then this option is redundant.
 
 @item -B INT
-@itemx --fhmaxbyte=INT
-See @option{--flminbyte}.
+@itemx --forcemax=INT
+Similar to @option{--forcemin}, but for the maximum.
 
 
 @item -i
@@ -12697,6 +12730,25 @@ But with this operator you can simply give 
@file{image.fits} the name
 $ astarithmetic image.fits set-i   i i 5 gt nan where
 @end example
 
+@item tofile-AAA
+Write the top oprand on the operands stack into a file called @code{AAA}
+(can be any FITS file name) without changing the operands stack (no operand
+will be operand).
+
+Any file that is given to this operator is deleted before Arithmetic
+actually starts working on the input datasets. The deletion can be
+deactivated with the @option{--dontdelete} option (as in all Gnuastro
+programs, see @ref{Input output options}). If the same FITS file is given
+to this operator multiple times, it will contain multiple extensions (in
+the same order that it was called.
+
+For example the operator @command{tofile-check.fits} will write the top
+operand to @file{check.fits}. Since it doesn't modify the operands stack,
+this operator is very convenient when you want to debug, or understanding,
+a string of operators and operands given to Arithmetic: simply put
+@command{tofile-AAA} anywhere in the process to see what is happening
+behind the scenes without modifying the overall process.
+
 @end table
 
 @cartouche
@@ -12767,15 +12819,21 @@ $ astarithmetic img1.fits img2.fits img3.fits median  
              \
                 -h0 -h1 -h2 --out=median.fits
 @end example
 
-If the output is not a single number, and the @option{--output} option is
-not given, automatic output will use the name of the first FITS image
-encountered to generate an output file name, see @ref{Automatic
-output}. Also, output WCS information will be taken from the first input
-image encountered. When the output is a single number, that number will be
-printed in the standard output and no output file will be
-created. Arithmetic's notation for giving operands to operators is
-described in @ref{Reverse polish notation}. To ignore certain pixels, set
-them as blank, see @ref{Blank pixels}, for example with the @command{where}
+The output is last remaining operand on the stack, see @ref{Reverse polish
+notation}. When its a single number, it will be printed on the
+command-line. When the output is an array, it will be stored as a file. The
+name of the file can be specified with the @option{--output} option, but if
+its not given, Arithmetic will use ``automatic output'' on the name of the
+first FITS image encountered to generate an output file name, see
+@ref{Automatic output}.
+
+By default, the world coordinate system (WCS) information will be taken
+from the first input image (that contains a WCS) on the command-line. This
+can be modified with the @option{--wcsfile} option described below.
+
+Arithmetic's notation for giving operands to operators is fully described
+in @ref{Reverse polish notation}. To ignore certain pixels, set them as
+blank, see @ref{Blank pixels}, for example with the @command{where}
 operator (see @ref{Arithmetic operators}). See @ref{Common options} for a
 review of the options in all Gnuastro programs. Arithmetic just redefines
 the @option{--hdu} option as explained below.
@@ -12824,6 +12882,30 @@ interest is in the same HDU of all the files. When 
this option is called,
 any values given to the @option{--hdu} option (explained above) are ignored
 and will not be used.
 
+@item -w STR
+@itemx --wcsfile STR
+FITS Filename containing the WCS structure that must be written to the
+output. The HDU/extension should be specified with @option{--wcshdu}.
+
+When this option is used, the respective WCS will be read before any
+processing is done on the command-line and directly used in the final
+output. If the given file doesn't have any WCS, then the default WCS (first
+file on the command-line with WCS) will be used in the output.
+
+This option will mostly be used when the default file (first of the set of
+inputs) is not the one containing your desired WCS. But with this option,
+you can also use Arithmetic to rewrite/chage the WCS of an existing FITS
+dataset from another file:
+
+@example
+$ astarithmetic data.fits --wcsfile=other.fits -ofinal.fits
+@end example
+
+@item -W STR
+@itemx --wcshdu STR
+HDU/extension to read the WCS within the file given to
+@option{--wcsfile}. For more, see the description of @option{--wcsfile}.
+
 @item -O
 @itemx --onedasimage
 When final dataset to write as output only has one dimension, write it as a
@@ -19737,10 +19819,10 @@ default, the output file(s) will be the re-arranged 
input tables such that
 the rows match each other: both output tables will have the same number of
 rows which are matched with each other. If @option{--outcols} is called,
 the output is a single table with rows chosen from either of the two inputs
-in any order, see the description of @option{--outcols}. If the
-@option{--logasoutput} option is called, the output will be a single table
-with the contents of the log file, see below. If no matches are found, the
-columns of the output table(s) will have zero rows (with proper meta-data).
+in any order. If the @option{--logasoutput} option is called, the output
+will be a single table with the contents of the log file, see below. If no
+matches are found, the columns of the output table(s) will have zero rows
+(with proper meta-data).
 
 If no output file name is given with the @option{--output} option, then
 automatic output @ref{Automatic output} will be used to determine the
@@ -19783,23 +19865,38 @@ FITS file, this option's value is ignored. For the 
first input, the common
 option @option{--hdu} must be used.
 
 @item --outcols=STR
-Columns from both inputs to write into a single matched table output. The
-value to @code{--outcols} must be a comma-separated list of strings, for
-example @option{--outcols=a1,bRA,bDEC}. The first character of each string
-specifies the input catalog: @option{a} for the first and @option{b} for
-the second. The rest of the characters of the string will be directly used
-to identify the proper column(s) in the respective table. See
-@ref{Selecting table columns} for how columns can be specified in
-Gnuastro. In this example, the output will have three columns: the first
-column of the first input and the @option{RA} and @option{DEC} columns of
-the second input.
+Columns (from both inputs) to write into a single matched table output. The
+value to @code{--outcols} must be a comma-separated list of strings. The
+first character of each string specifies the input catalog: @option{a} for
+the first and @option{b} for the second. The rest of the characters of the
+string will be directly used to identify the proper column(s) in the
+respective table. See @ref{Selecting table columns} for how columns can be
+specified in Gnuastro.
+
+For example the output of @option{--outcols=a1,bRA,bDEC} will have three
+columns: the first column of the first input, along with the @option{RA}
+and @option{DEC} columns of the second input.
+
+If the string after @option{a} or @option{b} is @option{_all}, then all the
+columns of the respective input file will be written in the output. For
+example the command below will print all the input columns from the first
+catalog along with the 5th column from the second:
+
+@example
+$ astmatch a.fits b.fits --outcols=a_all,b5
+@end example
+
+@code{_all} can be used multiple times, possibly on both inputs. Tip: if an
+input's column is called @code{_all} (an unlikely name!) and you don't want
+all the columns from that table the output, use its column number to avoid
+confusion.
 
 Another example is given in the one-line examples above. Compared to the
-default case (where two tables with all their columns) are printed, using
-this option is much faster: it will only read and re-arrange the necessary
-columns and it will write a single output table. Combined with regular
-expressions in large tables, this can be a very powerful and convenient way
-to retrieve your desired information and do the match at the same time.
+default case (where two tables with all their columns) are saved
+separately, using this option is much faster: it will only read and
+re-arrange the necessary columns and it will write a single output
+table. Combined with regular expressions in large tables, this can be a
+very powerful and convenient way to merge various tables into one.
 
 @item -l
 @itemx --logasoutput
@@ -24057,6 +24154,14 @@ input->flags &= ~GAL_DATA_FLAG_BLANK_CH;
 @end example
 @end deftypefun
 
+@deftypefun size_t gal_blank_number (gal_data_t @code{*input}, int 
@code{updateflag})
+Return the number of blank elements in @code{input}. If
+@code{updateflag!=0}, then the dataset blank keyword flags will be
+updated. See the description of @code{gal_blank_present} (above) for more
+on these flags. If @code{input==NULL}, then this function will return
+@code{GAL_BLANK_SIZE_T}.
+@end deftypefun
+
 
 @deftypefun {gal_data_t *} gal_blank_flag (gal_data_t @code{*input})
 Create a dataset of the the same size as the input, but with an
@@ -24235,10 +24340,11 @@ value of this variable is @code{NULL}, then the 
contents of @code{array}
 are actually stored in RAM, not in a file on the HDD/SSD. See the
 description of @code{minmapsize} below for more.
 
-If a file is used, it will be kept in the hidden @file{.gnuastro} directory
-with a randomly selected name to allow multiple arrays to be kept there at
-the same time. When @code{gal_data_free} is called the randomly named file
-will be deleted.
+If a file is used, it will be kept in the hidden @file{.gnuastro}, or
+@file{.gnuastro_mmap} directories with a randomly selected name to allow
+multiple arrays to be kept there at the same time, see description of
+@option{--minmapsize} in @ref{Processing options}. When
+@code{gal_data_free} is called the randomly named file will be deleted.
 
 @item size_t minmapsize
 The minimum size of an array (in bytes) to store the contents of
@@ -24406,11 +24512,12 @@ necessary allocations. If they aren't @code{NULL}, 
all input arrays
 separately copied (allocated) by this function for usage in @code{data}, so
 you can safely use one value to initialize many datasets or use statically
 allocated variables in this function call. Once you are done with the
-dataset, you can clean all the allocated spaces with
+dataset, you can free all the allocated spaces with
 @code{gal_data_free_contents}.
 
 If @code{array} is not @code{NULL}, it will be directly copied into
-@code{data->array} and no new space will be allocated for the array of this
+@code{data->array} (based on the total number of elements calculated from
+@code{dsize}) and no new space will be allocated for the array of this
 dataset, this has many low-level advantages and can be used to work on
 regions of a dataset instead of the whole allocated array (see the
 description under @code{block} in @ref{Generic data container} for one
@@ -25680,7 +25787,7 @@ should be used for the @code{searchin} variables of the 
functions.
 @end deffn
 
 @deftypefun {gal_data_t *} gal_table_info (char @code{*filename}, char 
@code{*hdu}, gal_list_str_t @code{*lines}, size_t @code{*numcols}, size_t 
@code{*numrows}, int @code{*tableformat})
-Store the information of each column in a table into an array of data
+Store the information of each column of a table into an array of data
 structures with @code{numcols} datasets (one data structure for each
 column). The number of rows is stored in @code{numrows}. The format of the
 table (e.g., ASCII text file, or FITS binary or ASCII table) will be put in
@@ -28674,7 +28781,46 @@ difference between the third and fourth, divided by 
the fifth.
 
 @end deftypefun
 
+@deftypefun {gal_data_t *} gal_statistics_outlier_flat_cfp (gal_data_t 
@code{*input}, size_t @code{dist}, float @code{thresh}, float @code{width}, int 
@code{inplace}, int @code{quiet}, size_t @code{*index})
 
+Return the first element in the given dataset where the cumulative
+frequency plot first becomes flat (below a given threshold on the slope)
+for a sufficient width (percentage of whole dataset's range). The returned
+dataset only has one element (with the same type as the input). If
+@code{index!=NULL}, the index (counting from zero, after sorting dataset
+and removing any blanks) is written in the space that @code{index} points
+to. If no sufficiently flat portion is found, the returned pointer will be
+@code{NULL}.
+
+The operation of this function can be best visualized using the cumulative
+frequency plot (CFP, see @ref{Histogram and Cumulative Frequency
+Plot}). Imagine setting the horizontal axis of the input's CFP to a range
+of 0 to 100, and finding the first part where its slope is
+constantly/contiguously flat for a certain fraction/width of the whole
+dataset's range. Below we'll descibe this in more detail.
+
+This function will first remove all the blank elements and sort the
+remaining elements. If @code{inplace} is non-zero this step will be done in
+place: re-organizing/permuting the input dataset. Using @code{inplace} can
+result in faster processing and less RAM consumption, but only when the
+input dataset is no longer needed in its original permutation.
+
+The input dataset will then be internally scaled from 0 to 100 (so
+@code{thresh} and @code{width} can be in units of percent). For each
+element, this function will then estimate the slope of the cumulative
+distribution function by using the @code{dist} elements before and after
+it. In other words, if @mymath{d} is the value of @code{dist}, then the
+slope over the @mymath{i}'th element (@mymath{a_i}) is estimated using this
+formula: @mymath{1/(a_{i+d}-a_{i-d})}. Therefore, when this slope is larger
+than 1, the distance between the two checked points is smaller than
+@mymath{1\%} of the dataset's range.
+
+All points that have a slope less than @code{thresh} are then marked. The
+first (parsing from the smallest to the largest values) contiguous patch of
+marked elements that is larger than @code{width} wide (in units of
+percentage of the dataset's range) will be considered as the boundary
+region of outliers and the first element in that patch will be returned.
+@end deftypefun
 
 
 @node Binary datasets, Labeled datasets, Statistical operations, Gnuastro 
library
diff --git a/lib/blank.c b/lib/blank.c
index cbf5658..4445d5d 100644
--- a/lib/blank.c
+++ b/lib/blank.c
@@ -33,6 +33,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <gnuastro/tile.h>
 #include <gnuastro/blank.h>
 #include <gnuastro/pointer.h>
+#include <gnuastro/statistics.h>
 
 #include <gnuastro-internal/checkset.h>
 
@@ -462,6 +463,33 @@ gal_blank_present(gal_data_t *input, int updateflag)
 
 
 
+/* Return the number of blank elements in the dataset. */
+size_t
+gal_blank_number(gal_data_t *input, int updateflag)
+{
+  gal_data_t *number;
+  size_t num_not_blank;
+
+  if(input)
+    {
+      if( gal_blank_present(input, updateflag) )
+        {
+          number=gal_statistics_number(input);
+          num_not_blank=((size_t *)(number->array))[0];
+          gal_data_free(number);
+          return input->size - num_not_blank;
+        }
+      else
+        return 0;
+    }
+  else
+    return GAL_BLANK_SIZE_T;
+}
+
+
+
+
+
 
 
 /* Create a dataset of the the same size as the input, but with an uint8_t
diff --git a/lib/checkset.c b/lib/checkset.c
index 1ec0684..0cc2098 100644
--- a/lib/checkset.c
+++ b/lib/checkset.c
@@ -29,6 +29,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <string.h>
 #include <unistd.h>
 #include <sys/stat.h>
+#include <sys/fcntl.h>
 
 #include <gnuastro/data.h>
 
@@ -291,7 +292,7 @@ gal_checkset_not_dir_part(char *filename)
 
 
 
-/* Check if a file exists and report if it doesn't: */
+/* Check if a file exists and report if it doesn't. */
 void
 gal_checkset_check_file(char *filename)
 {
@@ -333,6 +334,59 @@ gal_checkset_check_file_return(char *filename)
 
 
 
+/* If a file doesn't exist and its directory is writable, return
+   1. Otherwise, return 0. */
+int
+gal_checkset_writable_notexist(char *filename)
+{
+  int out=1;
+  char *dir;
+  FILE *tmpfile;
+
+  /* If the filename is `NULL' everything is ok (it doesn't exist)! In some
+     cases, a NULL filename is interpretted to mean standard output. */
+  if(filename==NULL) return 1;
+
+  /* We want to make sure that we can open and write to this file. But
+     the user might have asked to not delete the file, so the
+     contents should not be changed. Therefore we have to open it with
+     `r+`. */
+  errno=0;
+  tmpfile=fopen(filename, "r+");
+  if (tmpfile)                        /* The file opened. */
+    {
+      /* Close the file. */
+      errno=0;
+      if(fclose(tmpfile))
+        error(EXIT_FAILURE, errno, "%s", filename);
+
+      /* The file exists, return 0. */
+      out=0;
+    }
+
+  /* If the file doesn't exist, we just need to make sure if we have write
+     permissions to its host directory. */
+  else
+    {
+      /* Separate the directory part of the filename. */
+      dir=gal_checkset_dir_part(filename);
+
+      /* See if this directory is writable by this user. */
+      errno=0;
+      if( access(dir, W_OK) ) out=0;
+
+      /* Clean up. */
+      free(dir);
+    }
+
+  /* Return the final value. */
+  return out;
+}
+
+
+
+
+
 /* Check if a file exists and can be opened. If the `keep' value is
    non-zero, then the file will remain untouched, otherwise, it will be
    deleted (since most programs need to make a clean output). When the file
@@ -591,16 +645,26 @@ gal_checkset_check_dir_write_add_slash(char **dirname)
 
 
 
-/* If the given directory exists, then nothing is done, if it doesn't, it
-   will be created. */
-void
+/* If the given directory exists and is writable, then nothing is done. If
+   it doesn't, it will be created. If it fails at creating the file, or the
+   file isn't writable it returns a non-zero value: the errno, which can be
+   directly used in `error'. */
+int
 gal_checkset_mkdir(char *dirname)
 {
+  int errnum=0;
   struct stat st={0};
   if( stat(dirname, &st) == -1 )
     {
       errno=0;
       if( mkdir(dirname, 0700) == -1 )
-        error(EXIT_FAILURE, errno, "making %s", dirname);
+        errnum=errno;
+    }
+  else
+    {
+      errno=0;
+      if( faccessat(AT_FDCWD, dirname, W_OK, AT_EACCESS) == -1 )
+        errnum=errno;
     }
+  return errnum;
 }
diff --git a/lib/fits.c b/lib/fits.c
index 671b828..994a619 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -1833,6 +1833,10 @@ gal_fits_img_write_to_ptr(gal_data_t *input, char 
*filename)
   int nkeyrec, hasblank, status=0, datatype=0;
   gal_data_t *i64data, *towrite, *block=gal_tile_block(input);
 
+  /* Small sanity check. */
+  if( gal_fits_name_is_fits(filename)==0 )
+    error(EXIT_FAILURE, 0, "%s: not a FITS suffix", filename);
+
   /* If the input is a tile (isn't a contiguous region of memory), then
      copy it into a contiguous region. */
   towrite = input==block ? input : gal_data_copy(input);
diff --git a/lib/gnuastro-internal/checkset.h b/lib/gnuastro-internal/checkset.h
index 93eec4f..35e1085 100644
--- a/lib/gnuastro-internal/checkset.h
+++ b/lib/gnuastro-internal/checkset.h
@@ -104,6 +104,9 @@ gal_checkset_check_file(char *filename);
 int
 gal_checkset_check_file_return(char *filename);
 
+int
+gal_checkset_writable_notexist(char *filename);
+
 void    /* keep==0 && dontdelete==0: file will be deleted if exists.*/
 gal_checkset_writable_remove(char *filename, int keep, int dontdelete);
 
@@ -117,7 +120,7 @@ gal_checkset_automatic_output(struct 
gal_options_common_params *cp,
 void
 gal_checkset_check_dir_write_add_slash(char **dirname);
 
-void
+int
 gal_checkset_mkdir(char *dirname);
 
 
diff --git a/lib/gnuastro-internal/commonopts.h 
b/lib/gnuastro-internal/commonopts.h
index 1939e69..4420947 100644
--- a/lib/gnuastro-internal/commonopts.h
+++ b/lib/gnuastro-internal/commonopts.h
@@ -395,6 +395,20 @@ struct argp_option gal_commonopts_options[] =
       gal_options_call_parse_config_file
     },
     {
+      "checkconfig",
+      GAL_OPTIONS_KEY_CHECKCONFIG,
+      0,
+      0,
+      "List all config files and variables read.",
+      GAL_OPTIONS_GROUP_OPERATING_MODE,
+      &cp->checkconfig,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET,
+      gal_options_check_config
+    },
+    {
       "setdirconf",
       GAL_OPTIONS_KEY_SETDIRCONF,
       0,
diff --git a/lib/gnuastro-internal/options.h b/lib/gnuastro-internal/options.h
index 1e813a5..294e96f 100644
--- a/lib/gnuastro-internal/options.h
+++ b/lib/gnuastro-internal/options.h
@@ -115,6 +115,7 @@ enum options_common_keys
   GAL_OPTIONS_KEY_CONFIG,
   GAL_OPTIONS_KEY_SEARCHIN,
   GAL_OPTIONS_KEY_LASTCONFIG,
+  GAL_OPTIONS_KEY_CHECKCONFIG,
   GAL_OPTIONS_KEY_TABLEFORMAT,
   GAL_OPTIONS_KEY_ONLYVERSION,
   GAL_OPTIONS_KEY_WORKOVERCH,
@@ -206,6 +207,7 @@ struct gal_options_common_params
   uint8_t           setdirconf; /* To write the directory config file.    */
   uint8_t           setusrconf; /* To write teh user config config file.  */
   uint8_t           lastconfig; /* This is the last configuration file.   */
+  uint8_t          checkconfig; /* Check config files and values.         */
 
   /* Output files. */
   gal_fits_list_key_t  *okeys;  /* Configuration as FITS keys in output.  */
@@ -258,6 +260,10 @@ gal_options_print_citation(struct argp_option *option, 
char *arg,
                            char *filename, size_t lineno, void *pa);
 
 void *
+gal_options_check_config(struct argp_option *option, char *arg,
+                         char *filename, size_t lineno, void *junk);
+
+void *
 gal_options_read_type(struct argp_option *option, char *arg,
                       char *filename, size_t lineno, void *junk);
 
diff --git a/lib/gnuastro/blank.h b/lib/gnuastro/blank.h
index 3ccc206..2e2490d 100644
--- a/lib/gnuastro/blank.h
+++ b/lib/gnuastro/blank.h
@@ -109,6 +109,9 @@ gal_blank_is(void *pointer, uint8_t type);
 int
 gal_blank_present(gal_data_t *input, int updateflag);
 
+size_t
+gal_blank_number(gal_data_t *input, int updateflag);
+
 gal_data_t *
 gal_blank_flag(gal_data_t *data);
 
diff --git a/lib/gnuastro/statistics.h b/lib/gnuastro/statistics.h
index ded7540..7eeff6a 100644
--- a/lib/gnuastro/statistics.h
+++ b/lib/gnuastro/statistics.h
@@ -178,6 +178,11 @@ gal_statistics_outlier_positive(gal_data_t *input, size_t 
window_size,
                                 float sigma, float sigclip_multip,
                                 float sigclip_param, int inplace, int quiet);
 
+gal_data_t *
+gal_statistics_outlier_flat_cfp(gal_data_t *input, size_t dist, float thresh,
+                                float width, int inplace, int quiet,
+                                size_t *index);
+
 
 
 __END_C_DECLS    /* From C++ preparations */
diff --git a/lib/jpeg.c b/lib/jpeg.c
index c7c5151..34dc71b 100644
--- a/lib/jpeg.c
+++ b/lib/jpeg.c
@@ -35,7 +35,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <gnuastro/list.h>
 #include <gnuastro/jpeg.h>
 
-
+#include <gnuastro-internal/checkset.h>
 
 
 
@@ -404,6 +404,14 @@ gal_jpeg_write(gal_data_t *in, char *filename, uint8_t 
quality,
     error(EXIT_FAILURE, 0, "%s: input has a `%s' type, but JPEG images can "
           "only have a `uint8' type", __func__, gal_type_name(in->type, 1));
 
+  /* Make sure the file doesn't exist and that we have write
+     permission. Note that the JPEG standard doesn't have multple
+     extensions.*/
+  if( gal_checkset_writable_notexist(filename)==0 )
+    error(EXIT_FAILURE, 0, "%s: already exists or its directory doesn't "
+          "write permssion. Note that the JPEG standard only allows one "
+          "image per file", filename);
+
   /* Make sure the JSAMPLE is 8bits, then allocate the necessary space
      based on the number of channels. */
   if(sizeof *jsr!=1)
diff --git a/lib/options.c b/lib/options.c
index 59c52c0..5e286e9 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -340,6 +340,62 @@ gal_options_print_citation(struct argp_option *option, 
char *arg,
 
 
 void *
+gal_options_check_config(struct argp_option *option, char *arg,
+                          char *filename, size_t lineno, void *junk)
+{
+  char *str;
+
+  /* First see if we are reading or writing. */
+  if(lineno==-1)
+    {
+      gal_checkset_allocate_copy("1", &str);
+      return str;
+    }
+
+  /* Check if the given value is different from this version. */
+  else
+    {
+      /* If its already set then ignore it. */
+      if(option->set) return NULL;
+
+      /* Activate the option and let the user know its activated. */
+      (*(uint8_t *)(option->value)) = 1;
+      printf("-----------------\n"
+             "Parsing of options AFTER `--checkconfig'.\n\n"
+             "IMPORTANT: Any option that was parsed before encountering "
+             "`--checkconfig', on the command-line or in a configuration "
+             "file, is not shown here. It is thus recommended to use this "
+             "option before calling any other option.\n"
+             "-----------------\n");
+
+      /* Print where this option was first seen: if `checkconfig' is called
+         within a configuration file, `filename!=NULL' and has an argument
+         (=="1"). But on the command-line, it has no argument or
+         filename. */
+      if(filename)
+        printf("%s:\n", filename);
+      else
+        {
+          if(arg)
+            error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to "
+                  "fix the problem. `filename==NULL', but `arg!=NULL'",
+                  __func__, PACKAGE_BUGREPORT);
+          else
+            printf("Command-line:\n");
+        }
+
+      /* Just to avoid compiler warnings for unused variables. The program
+         will never reach this point! */
+      arg=filename=NULL; lineno=0; option=NULL; junk=NULL;
+    }
+  return NULL;
+}
+
+
+
+
+
+void *
 gal_options_read_type(struct argp_option *option, char *arg,
                       char *filename, size_t lineno, void *junk)
 {
@@ -1203,6 +1259,12 @@ gal_options_read_check(struct argp_option *option, char 
*arg, char *filename,
          unset). */
       option->func(option, arg, filename, lineno, topass);
       if(option->key!=GAL_OPTIONS_KEY_CONFIG) option->set=GAL_OPTIONS_SET;
+
+      /* The `--config' option is printed for `--checkconfig' by its
+         function (`gal_options_call_parse_config_file'), so must be
+         ignored here. */
+      if(cp->checkconfig && option->key!=GAL_OPTIONS_KEY_CONFIG)
+        printf("  %-25s%s\n", option->name, arg?arg:"ACTIVATED");
       return;
     }
 
@@ -1216,7 +1278,12 @@ gal_options_read_check(struct argp_option *option, char 
*arg, char *filename,
       else
         {
           /* If the option is already set, ignore the given value. */
-          if(option->set==GAL_OPTIONS_SET) return;
+          if(option->set==GAL_OPTIONS_SET)
+            {
+              if(cp->checkconfig)
+                printf("  %-25s--ALREADY-SET--\n", option->name);
+              return;
+            }
 
           /* Read the string argument into the value. */
           if( gal_type_from_string(&option->value, arg, option->type) )
@@ -1244,7 +1311,12 @@ gal_options_read_check(struct argp_option *option, char 
*arg, char *filename,
   else
     {
       /* If the option is already set, ignore the given value. */
-      if(option->set==GAL_OPTIONS_SET) return;
+      if(option->set==GAL_OPTIONS_SET)
+        {
+          if(cp->checkconfig)
+            printf("  %-25s--ALREADY-SET--\n", option->name);
+          return;
+        }
 
       /* Make sure the option has the type set for options with no
          argument. So, give it a value of 1. */
@@ -1260,6 +1332,12 @@ gal_options_read_check(struct argp_option *option, char 
*arg, char *filename,
     }
 
 
+  /* If the user wanted to check the value. */
+  if(cp->checkconfig)
+    printf("  %-25s%s\n", option->name,
+           (arg && option->type!=GAL_OPTIONS_NO_ARG_TYPE)?arg:"ACTIVATED");
+
+
   /* Flip the `set' flag to `GAL_OPTIONS_SET'. */
   option->set=GAL_OPTIONS_SET;
 }
@@ -1536,7 +1614,13 @@ options_set_from_name(char *name, char *arg,  struct 
argp_option *options,
           if( options[i].flags==OPTION_HIDDEN
               || ( options[i].set
                    && !gal_type_is_list(options[i].type ) ) )
-            return 0;
+            {
+              if(cp->checkconfig)
+                printf("  %-25s%s\n", name, ( options[i].flags==OPTION_HIDDEN
+                                              ? "--IGNORED--"
+                                              : "--ALREADY-SET--" ) );
+              return 0;
+            }
 
           /* Read the value into the option and do a sanity check. */
           gal_options_read_check(&options[i], arg, filename, lineno, cp);
@@ -1595,18 +1679,16 @@ options_parse_file(char *filename,  struct 
gal_options_common_params *cp,
     return;
 
 
-  /* Open the file. If the file doesn't exist, then just ignore the
-     configuration file and return. */
+  /* Open the file. If the file doesn't exist or can't be opened, then just
+     ignore the configuration file and return. */
   errno=0;
   fp=fopen(filename, "r");
-  if(fp==NULL)
-    {
-      if(errno==ENOENT && enoent_abort==0)
-        return;
-      else
-        error(EXIT_FAILURE, errno, "%s: to be read as a configuration file",
-              filename);
-    }
+  if(fp==NULL) return;
+
+
+  /* If necessary, print the configuration file name. */
+  if(cp->checkconfig)
+    printf("%s:\n", filename);
 
 
   /* Allocate the space necessary to keep a copy of each line as we parse
@@ -1660,11 +1742,26 @@ options_parse_file(char *filename,  struct 
gal_options_common_params *cp,
 /* This function will be used when the `--config' option is called. */
 void *
 gal_options_call_parse_config_file(struct argp_option *option, char *arg,
-                                   char *filename, size_t lineno, void *cp)
+                                   char *filename, size_t lineno, void *c)
 {
+  struct gal_options_common_params *cp=(struct gal_options_common_params *)c;
+
+  /* The `--config' option is a special function when it comes to
+     `--checkconfig': we'll have to write its value before interpretting
+     it. */
+  if(cp->checkconfig)
+    {
+      printf("  %-25s%s\n", option->name, arg);
+      printf("............................\n");
+    }
+
   /* Call the confguration file parser. */
   options_parse_file(arg, cp, 1);
 
+  /* Ending boundary of this file's options. */
+  if(cp->checkconfig)
+      printf("............................\n");
+
   /* Just to avoid compiler warnings, then return, note that all pointers
      are just copies. */
   option=NULL; filename=NULL; lineno=0;
@@ -1769,6 +1866,51 @@ options_reverse_lists_check_mandatory(struct 
gal_options_common_params *cp,
 
 
 
+void
+gal_options_read_low_level_checks(struct gal_options_common_params *cp)
+{
+  size_t suggested_mmap=10000000;
+
+  /* If `numthreads' is 0, use the number of threads available to the
+     system. */
+  if(cp->numthreads==0)
+    cp->numthreads=gal_threads_number();
+
+  /* If `minmapsize==0' and quiet isn't given, print a warning. */
+  if(cp->minmapsize==0)
+    {
+      fprintf(stderr, "\n\n"
+              "========= WARNING =========\n"
+              "Minimum size to map an allocated space outside of RAM is "
+              "not set, or set to zero. This can greatly slow down the "
+              "processing of a program or cause strange crashes (recall "
+              "that the number of files that can be memory-mapped is "
+              "limited).\n\n"
+
+              "On modern systems (with RAM larger than a giga-byte), it "
+              "should be fine to set it to %zu (10 million bytes or 10Mb) "
+              "with the command below. In this manner, only arrays that "
+              "are larger than this will be memory-mapped and smaller "
+              "arrays (which are much more numerous) will be allocated and "
+              "freed in the RAM.\n\n"
+
+              "     --minmapsize=%zu\n\n"
+
+              "[This warning can be disabled with the `--quiet' (or `-q') "
+              "option.]\n"
+              "===========================\n\n", suggested_mmap,
+              suggested_mmap);
+    }
+
+  /* If the user wanted to check the parsing of configuration files, then
+     the program must stop here. */
+  if(cp->checkconfig) exit(0);
+}
+
+
+
+
+
 /* Read all configuration files and set common options */
 void
 gal_options_read_config_set(struct gal_options_common_params *cp)
@@ -1785,10 +1927,8 @@ gal_options_read_config_set(struct 
gal_options_common_params *cp)
   /* Abort if any of the mandatory options are not set. */
   gal_options_abort_if_mandatory_missing(cp);
 
-  /* If `numthreads' is 0, use the number of threads available to the
-     system. */
-  if(cp->numthreads==0)
-    cp->numthreads=gal_threads_number();
+  /* Low-level/basic checks before passing control back to program. */
+  gal_options_read_low_level_checks(cp);
 }
 
 
@@ -2060,6 +2200,7 @@ options_print_all(struct gal_options_common_params *cp, 
char *dirname,
 {
   size_t i;
   FILE *fp;
+  int errnum;
   time_t rawtime;
   char *topicstr, *filename;
   gal_list_i32_t *group=NULL;
@@ -2072,7 +2213,9 @@ options_print_all(struct gal_options_common_params *cp, 
char *dirname,
   if(dirname)
     {
       /* Make the host directory if it doesn't already exist. */
-      gal_checkset_mkdir(dirname);
+      if( (errnum=gal_checkset_mkdir(dirname)) )
+        error(EXIT_FAILURE, errnum, "making %s for configuration files",
+              dirname);
 
       /* Prepare the full filename: */
       if( asprintf(&filename, "%s/%s.conf", dirname, cp->program_exec)<0 )
diff --git a/lib/pointer.c b/lib/pointer.c
index 3e09cd1..c467217 100644
--- a/lib/pointer.c
+++ b/lib/pointer.c
@@ -111,16 +111,36 @@ gal_pointer_allocate_mmap(uint8_t type, size_t size, int 
clear,
   void *out;
   int filedes;
   uint8_t uc=0;
+  char *dirname=NULL;
   size_t bsize=size*gal_type_sizeof(type);
 
 
   /* Check if the .gnuastro folder exists, write the file there. If it
-     doesn't exist, then make the .gnuastro directory.*/
-  gal_checkset_mkdir(".gnuastro");
+     doesn't exist, then make the .gnuastro directory. If it can't be
+     built, we'll make a randomly named directory. */
+  gal_checkset_allocate_copy("./.gnuastro/", &dirname);
+  if( gal_checkset_mkdir(dirname) )
+    {
+      /* Free the old name. */
+      free(dirname);
+
+      /* Try `.gnuastro_mmap' (to avoid making a separate directory for
+         each memory mapping if possible). */
+      gal_checkset_allocate_copy("./.gnuastro_mmap/", &dirname);
+      if( gal_checkset_mkdir(dirname) )
+        {
+          free(dirname);
+          dirname=NULL;
+        }
+    }
 
 
-  /* Set the filename */
-  gal_checkset_allocate_copy("./.gnuastro/mmap_XXXXXX", filename);
+  /* Set the filename. If `dirname' couldn't be allocated, directly make
+     the memory map file in the current directory (just as a hidden
+     file). */
+  if( asprintf(filename, "%smmap_XXXXXX", dirname?dirname:"./.gnuastro_")<0 )
+    error(EXIT_FAILURE, 0, "%s: asprintf allocation", __func__);
+  if(dirname) free(dirname);
 
 
   /* Create a zero-sized file and keep its descriptor.  */
@@ -128,8 +148,8 @@ gal_pointer_allocate_mmap(uint8_t type, size_t size, int 
clear,
   /*filedes=open(filename, O_RDWR | O_CREAT | O_EXCL | O_TRUNC );*/
   filedes=mkstemp(*filename);
   if(filedes==-1)
-    error(EXIT_FAILURE, errno, "%s: %s couldn't be created",
-          __func__, *filename);
+    error(EXIT_FAILURE, errno, "%s: %s couldn't be created", __func__,
+          *filename);
 
 
   /* Make the necessary space on the file. */
diff --git a/lib/statistics.c b/lib/statistics.c
index 61888e1..5ba3c19 100644
--- a/lib/statistics.c
+++ b/lib/statistics.c
@@ -1421,9 +1421,14 @@ gal_statistics_no_blank_sorted(gal_data_t *input, int 
inplace)
       else
         sorted=noblank;
     }
-  /* When the input's size is zero, just return the actual input. */
+
+  /* Input's size was zero. Note that we cannot simply copy the zero-sized
+     input dataset, we'll have to allocate it here. */
   else
-    sorted = inplace ? input : gal_data_copy(input);
+    sorted = ( inplace
+               ? input
+               : gal_data_alloc(NULL, input->type, 0, NULL, input->wcs, 0,
+                                input->minmapsize, NULL, NULL, NULL) );
 
   /* Set the blank and sorted flags if the dataset has zero-elements. Even
      if having blank values or being sorted is not defined on a
@@ -1439,7 +1444,6 @@ gal_statistics_no_blank_sorted(gal_data_t *input, int 
inplace)
       sorted->flag &= ~GAL_DATA_FLAG_SORTED_D;
     }
 
-
   /* Return final array. */
   return sorted;
 }
@@ -2145,6 +2149,9 @@ gal_statistics_outlier_positive(gal_data_t *input, size_t 
window_size,
   /* Remove all blanks and sort the dataset. */
   nbs=gal_statistics_no_blank_sorted(input, inplace);
 
+  /* If all elements are blank, simply return the default (NULL) output. */
+  if(nbs->size==0) return out;
+
   /* Only continue if the window size is more than 2 elements (out
      "outlier" is hard to define on smaller datasets). */
   if(window_size>2)
@@ -2192,3 +2199,92 @@ gal_statistics_outlier_positive(gal_data_t *input, 
size_t window_size,
   if(nbs!=input) gal_data_free(nbs);
   return out;
 }
+
+
+
+
+
+
+/* Find the outliers using the first flat portion of the cumulative
+   frequency plot. A good value for window and thresh are 5 and 1.0. */
+#define OUTLIER_FLAT_CFP_BYTYPE(IT) {                                   \
+    IT m, n, *a=nbs->array, *p=a+dist, *pp=a+nbs->size-dist;            \
+    min=a[0]; max=a[nbs->size-1];                                       \
+    do                                                                  \
+      {                                                                 \
+        m=( *(p-dist)-min ) / (max-min) * 100.0f;                       \
+        n=( *(p+dist)-min ) / (max-min) * 100.0f;                       \
+        check=1/(n-m);                                                  \
+        if(!quiet) printf("%-6zu%-15g%-15g\n", p-a, (float)(*p), check); \
+        if( check<thresh && start==GAL_BLANK_SIZE_T )                   \
+          { start=p-a; if(!quiet) printf("\t---start\n"); }             \
+        if( check>thresh && start!=GAL_BLANK_SIZE_T )                   \
+          {                                                             \
+             widthcheck=100.0 * (double)(*p-a[start])/(max-min);        \
+             if(!quiet) printf("\t----end: %f\n", widthcheck);          \
+             if( widthcheck > width ) { flatind=start; break; }         \
+             start=GAL_BLANK_SIZE_T;                                    \
+          }                                                             \
+      }                                                                 \
+    while(++p<pp);                                                      \
+    if( pp==p && start!=GAL_BLANK_SIZE_T )                              \
+      {                                                                 \
+        widthcheck=100.0 * (double)(*(p-1)-a[start])/(max-min);         \
+        if(!quiet) printf("\t----end: %f\n", widthcheck);               \
+        if( widthcheck > width ) flatind=start;                         \
+      }                                                                 \
+  }
+
+gal_data_t *
+gal_statistics_outlier_flat_cfp(gal_data_t *input, size_t dist,
+                                float thresh, float width, int inplace,
+                                int quiet, size_t *index)
+{
+  gal_data_t  *nbs, *out=NULL;
+  double min, max, check, widthcheck;
+  size_t one=1, flatind=GAL_BLANK_SIZE_T, start=GAL_BLANK_SIZE_T;
+
+  /* Sanity checks. */
+  if(thresh<=0 || width<=0)
+    error(EXIT_FAILURE, 0, "%s: the values to `thresh' (%g) and `width' (%g) "
+          "must be positive", __func__, thresh, width);
+  if(width==0)
+    error(EXIT_FAILURE, 0, "%s: `dist' (%zu) cannot be zero", __func__,
+          dist);
+
+  /* Remove all blanks and sort the dataset. */
+  nbs=gal_statistics_no_blank_sorted(input, inplace);
+
+  /* Find the index where the distribution becomes sufficiently flat. */
+  switch(nbs->type)
+    {
+    case GAL_TYPE_UINT8:   OUTLIER_FLAT_CFP_BYTYPE( uint8_t  ); break;
+    case GAL_TYPE_INT8:    OUTLIER_FLAT_CFP_BYTYPE( int8_t   ); break;
+    case GAL_TYPE_UINT16:  OUTLIER_FLAT_CFP_BYTYPE( uint16_t ); break;
+    case GAL_TYPE_INT16:   OUTLIER_FLAT_CFP_BYTYPE( int16_t  ); break;
+    case GAL_TYPE_UINT32:  OUTLIER_FLAT_CFP_BYTYPE( uint32_t ); break;
+    case GAL_TYPE_INT32:   OUTLIER_FLAT_CFP_BYTYPE( int32_t  ); break;
+    case GAL_TYPE_UINT64:  OUTLIER_FLAT_CFP_BYTYPE( uint64_t ); break;
+    case GAL_TYPE_INT64:   OUTLIER_FLAT_CFP_BYTYPE( int64_t  ); break;
+    case GAL_TYPE_FLOAT32: OUTLIER_FLAT_CFP_BYTYPE( float    ); break;
+    case GAL_TYPE_FLOAT64: OUTLIER_FLAT_CFP_BYTYPE( double   ); break;
+    default:
+      error(EXIT_FAILURE, 0, "%s: type code %d not recognized",
+            __func__, nbs->type);
+    }
+
+  /* Write the output dataset. */
+  if(flatind!=GAL_BLANK_SIZE_T)
+    {
+      out=gal_data_alloc(NULL, input->type, 1, &one, NULL, 0, -1,
+                         NULL, NULL, NULL);
+      memcpy(out->array,
+             gal_pointer_increment(nbs->array, flatind, nbs->type),
+             gal_type_sizeof(nbs->type));
+    }
+
+  /* Clean up and return. */
+  if(nbs!=input) gal_data_free(nbs);
+  if(index) *index=flatind;
+  return out;
+}



reply via email to

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