gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 8edc804 092/113: Imported recent work in maste


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 8edc804 092/113: Imported recent work in master, minor conflic fixed
Date: Fri, 16 Apr 2021 10:33:57 -0400 (EDT)

branch: master
commit 8edc804268ab21468c220b94aad6d525f232db9d
Merge: 0eaf0dc 6d69bf8
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Imported recent work in master, minor conflic fixed
    
    Two minor conflicts came up in Convolve's `ui.c' and were fixed. Also, a
    third came up in MakeProfiles (where we read 3D catalogs, it needed to be
    adjusted for the new name parameter in `gal_options_check_stdin').
---
 NEWS                              |  29 ++-
 bin/convertt/ui.c                 |   9 +-
 bin/convolve/args.h               |  28 ++-
 bin/convolve/astconvolve.conf     |   1 -
 bin/convolve/convolve.c           |  31 ++-
 bin/convolve/main.h               |   7 +-
 bin/convolve/ui.c                 | 426 +++++++++++++++++++++++++++-----------
 bin/convolve/ui.h                 |   8 +-
 bin/cosmiccal/args.h              |   6 +-
 bin/cosmiccal/cosmiccal.c         |   9 +-
 bin/crop/onecrop.c                |  16 ++
 bin/match/ui.c                    |   3 +-
 bin/mkprof/ui.c                   |   4 +-
 bin/statistics/ui.c               |   2 +-
 bin/table/ui.c                    |   4 +-
 configure.ac                      |  16 +-
 doc/announce-acknowledge.txt      |   2 +
 doc/gnuastro.texi                 | 194 +++++++++--------
 doc/release-checklist.txt         |  10 +-
 lib/fits.c                        |   2 +
 lib/gnuastro-internal/config.h.in |  11 -
 lib/gnuastro-internal/options.h   |   4 +-
 lib/gnuastro/statistics.h         |   6 +-
 lib/options.c                     |  26 +--
 lib/statistics.c                  |  18 +-
 lib/tile-internal.c               |  15 +-
 tests/statistics/stdin-input.txt  |   9 +
 27 files changed, 606 insertions(+), 290 deletions(-)

diff --git a/NEWS b/NEWS
index cb24499..a46813a 100644
--- a/NEWS
+++ b/NEWS
@@ -9,13 +9,20 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
      of output when it is FITS. This is only relevant for some programs,
      (for example not the Fits or Table programs).
    - Standard input (for example from pipes) is now available to feed input
-     to all programs that accept plain text input (ConvertType, Match,
-     MakeProfiles, Statistics, Table).
+     to all programs that accept plain text input (ConvertType, Convolve,
+     Match, MakeProfiles, Statistics, Table).
    - Updated acknowledgement statement (output of `--cite' option).
 
   Arithmetic:
     --onedasimage: write output as an image if it has one dimension, not table.
 
+  Convolve:
+    - Convolves 1D arrays (table columns, for example spectra)
+      also. Therefore two new options have been added to it: `--column'
+      (`-c', similar to other programs that read table columns), and
+      `--kernelcolumn' (to specify the column of the kernel in its own
+      file/extension).
+
   Fits:
     --numhdus: prints the number of HDUs in the given FITS file.
 
@@ -90,6 +97,11 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
       FITS image/array. This can be changed with the new `--onedasimage'
       option.
 
+  Convolve:
+    - The short option for `--numchannels' is now `-n'. Until now, it was
+      `-c', but that would conflict with the short option used for
+      `--column' in all the other programs that also read from a table.
+
   MakeProfiles:
     --mergedsize: new name for the old `--naxis' option. Since the option
           names and values are now written into the FITS header of the
@@ -107,14 +119,15 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
     --meanmedqdiff: new name for `--modmedqdiff'. Similar to NoiseChisel.
 
   Library:
-    - gal_data_copy_to_allocated: Also copies string metadata (e.g., name).
-    - gal_fits_key_write: filename and hdu instead of FITS pointer.
-    - gal_fits_key_write_version: filename and hdu instead of FITS pointer.
-    - gal_fits_key_write_filename: write at the top or end of the input list.
     - gal_array_read: list of strings (from standard input) acceptable.
     - gal_array_read_to_type: list of strings (from stin) acceptable.
     - gal_array_read_one_ch: list of strings (from stdin) acceptable.
     - gal_array_read_one_ch_to_type: list of strings (from stdin) acceptable.
+    - gal_data_copy_to_allocated: Also copies string metadata (e.g., name).
+    - gal_fits_key_write: filename and hdu instead of FITS pointer.
+    - gal_fits_key_write_version: filename and hdu instead of FITS pointer.
+    - gal_fits_key_write_filename: write at the top or end of the input list.
+    - gal_statistics_outlier_positive: Window-size is now adjustable (new 
argument).
     - gal_table_info: list of strings (from stdin) acceptable.
     - gal_table_read: list of strings (from stdin) acceptable.
     - gal_txt_table_info: list of strings (from stdin) acceptable.
@@ -129,6 +142,10 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
   bug #54782: Segment's check image not removing sky clumps some tiles.
   bug #54810: Arithmetic crash when previously named operand renamed.
   bug #55025: MakeCatalog's `--prepforconv' option being ignored.
+  bug #55079: Blank EPS or PDF page when width options not given.
+  bug #55157: No sanity check on values given to Crop's --section.
+
+
 
 
 
diff --git a/bin/convertt/ui.c b/bin/convertt/ui.c
index 47b2194..e9a3afd 100644
--- a/bin/convertt/ui.c
+++ b/bin/convertt/ui.c
@@ -513,7 +513,8 @@ ui_make_channels_ll(struct converttparams *p)
 
   /* If there weren't any channels, abort with an error. */
   if(p->numch==0)
-    error(EXIT_FAILURE, 0, gal_options_stdin_error(p->cp.stdintimeout, 0));
+    error(EXIT_FAILURE, 0, "%s",
+          gal_options_stdin_error(p->cp.stdintimeout, 0, "input"));
 
   /* Reverse the list of channels into the input order. */
   gal_list_data_reverse(&p->chll);
@@ -702,6 +703,9 @@ ui_set_output(struct converttparams *p)
   /* EPS */
   else if(gal_eps_name_is_eps(cp->output))
     {
+      if(p->borderwidth==0 && p->widthincm==0)
+        error(EXIT_FAILURE, 0, "at least one of `--widthincm' (`-u'), or "
+              "`--borderwidth (`-b') options are necessary for an EPS output");
       p->outformat=OUT_FORMAT_EPS;
       if( gal_eps_suffix_is_eps(cp->output) )
         ui_add_dot_use_automatic_output(p);
@@ -710,6 +714,9 @@ ui_set_output(struct converttparams *p)
   /* PDF */
   else if(gal_pdf_name_is_pdf(cp->output))
     {
+      if(p->borderwidth==0 && p->widthincm==0)
+        error(EXIT_FAILURE, 0, "at least one of `--widthincm' (`-u'), or "
+              "`--borderwidth (`-b') options are necessary for a PDF output");
       p->outformat=OUT_FORMAT_PDF;
       if( gal_pdf_suffix_is_pdf(cp->output) )
         ui_add_dot_use_automatic_output(p);
diff --git a/bin/convolve/args.h b/bin/convolve/args.h
index f8a17dd..8e03ea6 100644
--- a/bin/convolve/args.h
+++ b/bin/convolve/args.h
@@ -42,7 +42,20 @@ struct argp_option program_options[] =
       &p->kernelname,
       GAL_TYPE_STRING,
       GAL_OPTIONS_RANGE_ANY,
-      GAL_OPTIONS_MANDATORY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+    {
+      "column",
+      UI_KEY_COLUMN,
+      "STR",
+      0,
+      "Column name or number if input is a table.",
+      GAL_OPTIONS_GROUP_INPUT,
+      &p->column,
+      GAL_TYPE_STRING,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
       GAL_OPTIONS_NOT_SET
     },
     {
@@ -59,6 +72,19 @@ struct argp_option program_options[] =
       GAL_OPTIONS_NOT_SET
     },
     {
+      "kernelcolumn",
+      UI_KEY_KERNELCOLUMN,
+      "STR",
+      0,
+      "Column name or number if kernel is a table.",
+      GAL_OPTIONS_GROUP_INPUT,
+      &p->kernelcolumn,
+      GAL_TYPE_STRING,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+    {
       "nokernelflip",
       UI_KEY_NOKERNELFLIP,
       0,
diff --git a/bin/convolve/astconvolve.conf b/bin/convolve/astconvolve.conf
index 46f5965..1ff2e7d 100644
--- a/bin/convolve/astconvolve.conf
+++ b/bin/convolve/astconvolve.conf
@@ -18,7 +18,6 @@
 # warranty.
 
 # Input:
- kernel             kernel.fits
  khdu               1
 
 # Output:
diff --git a/bin/convolve/convolve.c b/bin/convolve/convolve.c
index fae4a18..4e05635 100644
--- a/bin/convolve/convolve.c
+++ b/bin/convolve/convolve.c
@@ -761,6 +761,7 @@ void
 convolve(struct convolveparams *p)
 {
   gal_data_t *out, *check;
+  int multidim=p->input->ndim>1;
   struct gal_options_common_params *cp=&p->cp;
 
 
@@ -768,10 +769,10 @@ convolve(struct convolveparams *p)
   if(p->domain==CONVOLVE_DOMAIN_SPATIAL)
     {
       /* Prepare the mesh structure. */
-      gal_tile_full_two_layers(p->input, &cp->tl);
+      if(multidim) gal_tile_full_two_layers(p->input, &cp->tl);
 
       /* Save the tile IDs if they are requested. */
-      if(cp->tl.tilecheckname)
+      if(multidim && cp->tl.tilecheckname)
         {
           check=gal_tile_block_check_tiles(cp->tl.tiles);
           gal_fits_img_write(check, cp->tl.tilecheckname, NULL, PROGRAM_NAME);
@@ -782,12 +783,14 @@ convolve(struct convolveparams *p)
          want to do spatial domain convolution with this Convolve program
          is edge correction. So by default we assume it and will only
          ignore it if the user asks.*/
-      out=gal_convolve_spatial(cp->tl.tiles, p->kernel, cp->numthreads,
-                               !p->noedgecorrection, cp->tl.workoverch);
+      out=gal_convolve_spatial(multidim ? cp->tl.tiles : p->input, p->kernel,
+                               cp->numthreads,
+                               multidim ? !p->noedgecorrection : 1,
+                               multidim ? cp->tl.workoverch : 1 );
 
       /* Clean up: free the actual input and replace it's pointer with the
          convolved dataset to save as output. */
-      gal_tile_full_free_contents(&cp->tl);
+      if(&cp->tl) gal_tile_full_free_contents(&cp->tl);
       gal_data_free(p->input);
       p->input=out;
     }
@@ -795,12 +798,20 @@ convolve(struct convolveparams *p)
     convolve_frequency(p);
 
   /* Save the output (which is in p->input) array. */
-  gal_fits_img_write_to_type(p->input, cp->output, NULL, PROGRAM_NAME,
-                             cp->type);
+  if(p->input->ndim==1)
+    gal_table_write(p->input, NULL, p->cp.tableformat, p->cp.output,
+                    "CONVOLVED", 0);
+  else
+    gal_fits_img_write_to_type(p->input, cp->output, NULL, PROGRAM_NAME,
+                               cp->type);
 
   /* Write Convolve's parameters as keywords into the first extension of
      the output. */
-  gal_fits_key_write_filename("input", p->filename, &cp->okeys, 1);
-  gal_fits_key_write_config(&cp->okeys, "Convolve configuration",
-                            "CONVOLVE-CONFIG", cp->output, "0");
+  if( gal_fits_name_is_fits(p->cp.output) )
+    {
+      gal_fits_key_write_filename("input", p->filename, &cp->okeys, 1);
+      gal_fits_key_write_config(&cp->okeys, "Convolve configuration",
+                                "CONVOLVE-CONFIG", cp->output, "0");
+    }
+  printf("  - Output: %s\n", p->cp.output);
 }
diff --git a/bin/convolve/main.h b/bin/convolve/main.h
index 11c0f53..f3b8812 100644
--- a/bin/convolve/main.h
+++ b/bin/convolve/main.h
@@ -39,7 +39,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 /* Macros */
 #define CONVFLOATINGPOINTERR 1e-10
-
+#define INPUT_USE_TYPE       GAL_TYPE_FLOAT32
 
 
 
@@ -54,7 +54,6 @@ enum complex_to_real
   COMPLEX_TO_REAL_REAL,
 };
 
-
 enum domain_codes
 {
   CONVOLVE_DOMAIN_INVALID,           /* ==0 by C standard. */
@@ -73,8 +72,10 @@ struct convolveparams
   /* From command-line */
   struct gal_options_common_params cp; /* Common parameters.              */
   char             *filename;  /* Name of input file.                     */
+  char               *column;  /* Name of column if input is a table.     */
   char           *kernelname;  /* File name of kernel.                    */
   char                 *khdu;  /* HDU of kernel.                          */
+  char         *kernelcolumn;  /* Column to read the input kernel.        */
   uint8_t       nokernelflip;  /* Do not flip the kernel.                 */
   uint8_t       nokernelnorm;  /* Do not normalize the kernel.            */
   double        minsharpspec;  /* Deconvolution: min spect. of sharp img. */
@@ -84,6 +85,8 @@ struct convolveparams
   uint8_t   noedgecorrection;  /* Do not correct spatial edge effects.    */
 
   /* Internal */
+  int                 isfits;  /* Input is a FITS file.                   */
+  int               hdu_type;  /* Type of HDU (image or table).           */
   int                 domain;  /* Frequency or spatial domain conv.       */
   gal_data_t          *input;  /* Input image array.                      */
   gal_data_t         *kernel;  /* Input Kernel array.                     */
diff --git a/bin/convolve/ui.c b/bin/convolve/ui.c
index b67aec2..47f7f95 100644
--- a/bin/convolve/ui.c
+++ b/bin/convolve/ui.c
@@ -129,10 +129,7 @@ ui_initialize_options(struct convolveparams *p,
         break;
 
       case GAL_OPTIONS_KEY_LOG:
-      case GAL_OPTIONS_KEY_SEARCHIN:
       case GAL_OPTIONS_KEY_IGNORECASE:
-      case GAL_OPTIONS_KEY_TABLEFORMAT:
-      case GAL_OPTIONS_KEY_STDINTIMEOUT:
       case GAL_OPTIONS_KEY_INTERPNUMNGB:
       case GAL_OPTIONS_KEY_INTERPONLYBLANK:
         cp->coptions[i].flags=OPTION_HIDDEN;
@@ -213,11 +210,6 @@ ui_read_check_only_options(struct convolveparams *p)
 {
   struct gal_options_common_params *cp=&p->cp;
 
-  /* Make sure the kernel name is a FITS file and a HDU is given. */
-  if( gal_fits_name_is_fits(p->kernelname)==0 )
-    error(EXIT_FAILURE, 0, "`%s' is not a recognized FITS file name",
-          p->kernelname);
-
 
   /* Read the domain from a string into an integer. */
   if( !strcmp("spatial", p->domainstr) )
@@ -255,15 +247,53 @@ ui_read_check_only_options(struct convolveparams *p)
 static void
 ui_check_options_and_arguments(struct convolveparams *p)
 {
-  /* Make sure an input file name was given and if it was a FITS file, that
-     a HDU is also given. */
-  if(p->filename==NULL)
-    error(EXIT_FAILURE, 0, "no input file is specified");
-
-  /* Make sure the input name is a FITS file name. */
-  if( gal_fits_name_is_fits(p->filename)==0 )
-    error(EXIT_FAILURE, 0, "`%s' is not a recognized FITS file name",
-          p->filename);
+  int kernel_type;
+
+  if(p->filename)
+    {
+      /* If input is FITS. */
+      if( (p->isfits=gal_fits_name_is_fits(p->filename)) )
+        {
+          /* Check if a HDU is given. */
+          if( p->cp.hdu==NULL )
+            error(EXIT_FAILURE, 0, "no HDU specified. When the input is a "
+                  "FITS file, a HDU must also be specified, you can use "
+                  "the `--hdu' (`-h') option and give it the HDU number "
+                  "(starting from zero), extension name, or anything "
+                  "acceptable by CFITSIO");
+
+          /* If its an image, make sure column isn't given (in case the
+             user confuses an image with a table). */
+          p->hdu_type=gal_fits_hdu_format(p->filename, p->cp.hdu);
+          if(p->hdu_type==IMAGE_HDU && p->column)
+            error(EXIT_FAILURE, 0, "%s (hdu: %s): is a FITS image "
+                  "extension. The `--column' option is only applicable "
+                  "to tables.", p->filename, p->cp.hdu);
+        }
+    }
+
+  if(p->kernelname)
+    {
+      /* If input is FITS. */
+      if( gal_fits_name_is_fits(p->kernelname) )
+        {
+          /* Check if a HDU is given. */
+          if( p->khdu==NULL )
+            error(EXIT_FAILURE, 0, "no HDU specified. When the kernel is a "
+                  "FITS file, a HDU must also be specified, you can use "
+                  "the `--khdu' (`-u') option and give it the HDU number "
+                  "(starting from zero), extension name, or anything "
+                  "acceptable by CFITSIO");
+
+          /* If its an image, make sure column isn't given (in case the
+             user confuses an image with a table). */
+          kernel_type=gal_fits_hdu_format(p->kernelname, p->khdu);
+          if(kernel_type==IMAGE_HDU && p->kernelcolumn)
+            error(EXIT_FAILURE, 0, "%s (hdu: %s): is a FITS image "
+                  "extension. The `--kernelcolumn' option is only "
+                  "applicable to tables.", p->kernelname, p->khdu);
+        }
+    }
 }
 
 
@@ -288,27 +318,158 @@ ui_check_options_and_arguments(struct convolveparams *p)
 /**************************************************************/
 /***************       Preparations         *******************/
 /**************************************************************/
+static gal_data_t *
+ui_read_column(struct convolveparams *p, int i0k1)
+{
+  int tformat;
+  char *source;
+  gal_data_t *out, *cinfo;
+  gal_list_str_t *column=NULL;
+  size_t ncols, nrows, counter=0;
+  char *hdu        = i0k1==0 ? p->cp.hdu   : p->khdu;
+  char *name       = i0k1==0 ? "input"     : "kernel";
+  char *filename   = i0k1==0 ? p->filename : p->kernelname;
+  char *columnname = i0k1==0 ? p->column   : p->kernelcolumn;
+  gal_list_str_t *lines = gal_options_check_stdin(filename,
+                                                  p->cp.stdintimeout, name);
+
+  /* If no column is specified, Convolve will abort and an error will be
+     printed when the table has more than one column. If there is only one
+     column, there is no need to specify any, so Convolve will use it. */
+  if(columnname==NULL)
+    {
+      /* Get the basic table information. */
+      cinfo=gal_table_info(filename, hdu, lines, &ncols, &nrows, &tformat);
+      gal_data_array_free(cinfo, ncols, 1);
+
+      /* See how many columns it has and take the proper action. */
+      switch(ncols)
+        {
+        case 0:
+          error(EXIT_FAILURE, 0, "%s contains no usable information",
+                ( filename
+                  ? gal_checkset_dataset_name(filename, hdu)
+                  : "Standard input" ));
+        case 1:
+          gal_checkset_allocate_copy("1", &columnname);
+          break;
+        default:
+          error(EXIT_FAILURE, 0, "%s is a table containing more than one "
+                "column. However, the specific column to work on isn't "
+                "specified.\n\n"
+                "Please use the `--column' (`-c') or `--kernelcolumn' "
+                "options (depending on which dataset it is) to specify a "
+                "column. You can either give it the column number "
+                "(couting from 1), or a match/search in its meta-data (e.g., "
+                "column names).\n\n"
+                "For more information, please run the following command "
+                "(press the `SPACE' key to go down and `q' to return to the "
+                "command-line):\n\n"
+                "    $ info gnuastro \"Selecting table columns\"\n",
+                ( filename
+                  ? gal_checkset_dataset_name(filename, hdu)
+                  : "Standard input" ));
+        }
+
+    }
+  gal_list_str_add(&column, columnname, 0);
+
+  /* Read the desired column(s). */
+  out=gal_table_read(filename, hdu, lines, column, p->cp.searchin,
+                     p->cp.ignorecase, p->cp.minmapsize, NULL);
+  gal_list_str_free(lines, 1);
+
+  /* Confirm if only one column was read (it is possible to match more than
+     one column). */
+  if(out->next!=NULL)
+    {
+      if(filename)
+        gal_checkset_dataset_name(filename, hdu);
+      else
+        source="standard-input";
+      error(EXIT_FAILURE, 0, "%s: more than one column in input table mached "
+            "the search criteria. Please limit the match by specifying the "
+            "exact name (if its unique) or column number", source);
+    }
+
+  /* Make sure it is a usable datatype. */
+  switch(out->type)
+    {
+    case GAL_TYPE_BIT:
+    case GAL_TYPE_STRLL:
+    case GAL_TYPE_STRING:
+    case GAL_TYPE_COMPLEX32:
+    case GAL_TYPE_COMPLEX64:
+      error(EXIT_FAILURE, 0, " read column number %zu has a %s type, "
+            "which is not currently supported by %s", counter,
+            gal_type_name(out->type, 1), PROGRAM_NAME);
+    }
+  out=gal_data_copy_to_new_type_free(out, INPUT_USE_TYPE);
+
+  /* If the input was from standard input, we can actually write this into
+     it (for future reporting). */
+  if(filename==NULL)
+    gal_checkset_allocate_copy("standard-input",
+                               ( i0k1==0 ? &p->filename : &p->kernelname ));
+
+  /* Clean up and return. */
+  gal_list_str_free(column, 0);
+  return out;
+}
+
+
+
+
+
+/* Read the input dataset. */
+static void
+ui_read_input(struct convolveparams *p)
+{
+  /* To see if we should read it as a table. */
+  p->input=NULL;
+
+  /* If the input is a FITS image or any recognized array file format, then
+     read it as an array, otherwise, as a table. */
+  if( p->filename && gal_array_name_recognized(p->filename) )
+    if (p->isfits && p->hdu_type==IMAGE_HDU)
+      {
+        p->input=gal_array_read_one_ch_to_type(p->filename, p->cp.hdu, NULL,
+                                               INPUT_USE_TYPE,
+                                               p->cp.minmapsize);
+        p->input->wcs=gal_wcs_read(p->filename, p->cp.hdu, 0, 0,
+                                   &p->input->nwcs);
+      }
+
+  /* The input isn't an image (wasn't read yet), so we'll read it as a
+     column. */
+  if(p->input==NULL)
+    p->input=ui_read_column(p, 0);
+}
+
+
+
+
+
 /* Read the kernel. VERY IMPORTANT: We can't use the `fits_img_read_kernel'
    because the Convolve program also does de-convolution. */
 static void
 ui_read_kernel(struct convolveparams *p)
 {
-  float *f, *ff;
-
   /* Read the image into file. */
-  p->kernel = gal_array_read_one_ch_to_type(p->kernelname, p->khdu,
-                                            NULL, GAL_TYPE_FLOAT32,
-                                            p->cp.minmapsize);
+  if( p->kernelname
+      && p->input->ndim>1
+      && gal_array_name_recognized(p->kernelname)  )
+    p->kernel = gal_array_read_one_ch_to_type(p->kernelname, p->khdu,
+                                              NULL, INPUT_USE_TYPE,
+                                              p->cp.minmapsize);
+  else
+    p->kernel=ui_read_column(p, 1);
 
-  /* Convert all the NaN pixels to zero if the kernel contains blank
-     pixels, also update the flags so it is not checked any more. */
-  if(gal_blank_present(p->kernel, 1))
-    {
-      ff = (f=p->kernel->array) + p->kernel->size;
-      do *f = isnan(*f) ? 0.0f : *f; while(++f<ff);
-      p->kernel->flag |= GAL_DATA_FLAG_BLANK_CH;
-      p->kernel->flag &= ~GAL_DATA_FLAG_HASBLANK;
-    }
+  /* Make sure that the kernel and input have the same number of
+     dimensions. */
+  if(p->kernel->ndim!=p->input->ndim)
+    error(EXIT_FAILURE, 0, "input datasets must have the same number of "
+          "dimensions");
 }
 
 
@@ -318,38 +479,28 @@ ui_read_kernel(struct convolveparams *p)
 static void
 ui_preparations(struct convolveparams *p)
 {
+  int check=0;
+  double sumv=0;
   size_t i, size;
   gal_data_t *sum;
-  float *kernel, tmp;
+  float *f, *fp, tmp, *kernel;
   struct gal_options_common_params *cp=&p->cp;
   char *outsuffix = p->makekernel ? "_kernel.fits" : "_convolved.fits";
 
-  /* Set the output name if the user hasn't set it. */
-  if(cp->output==NULL)
-    cp->output=gal_checkset_automatic_output(cp, p->filename, outsuffix);
-  gal_checkset_writable_remove(cp->output, 0, cp->dontdelete);
-  if(p->checkfreqsteps)
-    {
-      p->freqstepsname=gal_checkset_automatic_output(cp, p->filename,
-                                                     "_freqsteps.fits");
-      gal_checkset_writable_remove(p->freqstepsname, 0, cp->dontdelete);
-    }
-  if(cp->tl.checktiles)
-    {
-      cp->tl.tilecheckname=gal_checkset_automatic_output(cp, p->filename,
-                                                         "_tiled.fits");
-      gal_checkset_writable_remove(cp->tl.tilecheckname, 0,
-                                   cp->dontdelete);
-    }
 
+  /* Read the input dataset. */
+  ui_read_input(p);
 
-  /* Read the input image as a float64 array. */
-  p->input=gal_array_read_one_ch_to_type(p->filename, cp->hdu, NULL,
-                                         GAL_TYPE_FLOAT32, cp->minmapsize);
-  p->input->wcs=gal_wcs_read(p->filename, cp->hdu, 0, 0, &p->input->nwcs);
 
+  /* Currently Convolve only works on 1D and 2D datasets. */
+  if(p->input->ndim>2)
+    error(EXIT_FAILURE, 0, "%s (hdu %s) has %zu dimensions. Currently "
+          "Convolve only operates on 1D (table column, spectrum), 2D "
+          "(image), and 3D (data cube) datasets", p->filename, cp->hdu,
+          p->input->ndim);
 
-  /* Domain specific checks. */
+
+  /* Domain-specific checks. */
   if(p->domain==CONVOLVE_DOMAIN_FREQUENCY)
     {
       /* Check the dimensionality. */
@@ -371,17 +522,17 @@ ui_preparations(struct convolveparams *p)
                 "----------------------------------------\n\n",
                 PROGRAM_NAME, p->filename, cp->hdu, cp->output,
                 PROGRAM_NAME);
+
+      /* Frequency domain is only implemented in 2D. */
+      if( p->input->ndim==1 )
+        error(EXIT_FAILURE, 0, "Frequency domain convolution is currently "
+              "not implemented on 1D datasets. Please use `--domain=spatial' "
+              "to convolve this dataset");
     }
   else
     {
-      /* Check the dimensionality. */
-      if(p->input->ndim!=2 && p->input->ndim!=3)
-        error(EXIT_FAILURE, 0, "%s (hdu %s) has %zu dimensions. Spatial "
-              "domain convolution currently only operates on 2D images or "
-              "3D cubes", p->filename, cp->hdu, p->input->ndim);
-
-      /* Tessellation checks. */
-      gal_tile_full_sanity_check(p->filename, cp->hdu, p->input, &cp->tl);
+      if(p->input->ndim>1)
+        gal_tile_full_sanity_check(p->filename, cp->hdu, p->input, &cp->tl);
     }
 
 
@@ -390,31 +541,39 @@ ui_preparations(struct convolveparams *p)
      argument) is the blurry image. */
   if(p->makekernel)
     {
-      /* Read in the kernel array. */
-      ui_read_kernel(p);
+      /* Currently this is not implemented in 1D. */
+      if(p->kernel->ndim==1)
+        error(EXIT_FAILURE, 0, "`--makekernel' is currently not available "
+              "on 1D datasets");
+      else
+        {
+          /* Read in the kernel array. */
+          ui_read_kernel(p);
 
-      /* Make sure the size of the kernel is the same as the input */
-      if( p->input->dsize[0]!=p->kernel->dsize[0]
-          || p->input->dsize[1]!=p->kernel->dsize[1] )
-        error(EXIT_FAILURE, 0, "with the `--makekernel' (`-m') option, "
-              "the input image and the image specified with the `--kernel' "
-              "(`-k') option should have the same size. The lower resolution "
-              "input image (%s) has %zux%zu pixels while the sharper image "
-              "(%s) specified with the kernel option has %zux%zu pixels",
-              p->filename, p->input->dsize[1], p->input->dsize[0],
-              p->kernelname, p->kernel->dsize[1], p->kernel->dsize[0]);
-
-      /* Divide both images by their sum so their lowest frequency becomes
-         1 and their division (in the frequency domain) would be
-         meaningful. */
-      sum=gal_statistics_sum(p->input);
-      sum=gal_data_copy_to_new_type_free(sum, GAL_TYPE_FLOAT32);
-      p->input = gal_arithmetic(GAL_ARITHMETIC_OP_DIVIDE,
-                                GAL_ARITHMETIC_FLAGS_ALL, p->input, sum);
-      sum=gal_statistics_sum(p->kernel);
-      sum=gal_data_copy_to_new_type_free(sum, GAL_TYPE_FLOAT32);
-      p->kernel = gal_arithmetic(GAL_ARITHMETIC_OP_DIVIDE,
-                                GAL_ARITHMETIC_FLAGS_ALL, p->kernel, sum);
+          /* Make sure the size of the kernel is the same as the input */
+          if( p->input->dsize[0]!=p->kernel->dsize[0]
+              || p->input->dsize[1]!=p->kernel->dsize[1] )
+            error(EXIT_FAILURE, 0, "with the `--makekernel' (`-m') option, "
+                  "the input image and the image specified with the "
+                  "`--kernel' (`-k') option should have the same size. The "
+                  "lower resolution input image (%s) has %zux%zu pixels "
+                  "while the sharper image (%s) specified with the kernel "
+                  "option has %zux%zu pixels", p->filename,
+                  p->input->dsize[1], p->input->dsize[0], p->kernelname,
+                  p->kernel->dsize[1], p->kernel->dsize[0]);
+
+          /* Divide both images by their sum so their lowest frequency becomes
+             1 and their division (in the frequency domain) would be
+             meaningful. */
+          sum=gal_statistics_sum(p->input);
+          sum=gal_data_copy_to_new_type_free(sum, GAL_TYPE_FLOAT32);
+          p->input = gal_arithmetic(GAL_ARITHMETIC_OP_DIVIDE,
+                                    GAL_ARITHMETIC_FLAGS_ALL, p->input, sum);
+          sum=gal_statistics_sum(p->kernel);
+          sum=gal_data_copy_to_new_type_free(sum, GAL_TYPE_FLOAT32);
+          p->kernel = gal_arithmetic(GAL_ARITHMETIC_OP_DIVIDE,
+                                     GAL_ARITHMETIC_FLAGS_ALL, p->kernel, sum);
+        }
     }
 
   /* Read the kernel. If there is anything particular to Convolve, then
@@ -424,44 +583,71 @@ ui_preparations(struct convolveparams *p)
      into one loop. */
   else
     {
-      if(p->nokernelnorm || p->nokernelflip)
-        {
-          /* Read in the kernel array: */
-          ui_read_kernel(p);
-
-          /* Check its size (must be odd). */
-          if(p->kernel->dsize[0]%2==0 || p->kernel->dsize[1]%2==0)
-            error(EXIT_FAILURE, 0, "the kernel image has to have an odd "
-                  "number of pixels on both sides (there has to be on pixel "
-                  "in the center). %s (hdu: %s) is %zu by %zu",
-                  p->kernelname, p->khdu, p->kernel->dsize[1],
-                  p->kernel->dsize[0]);
+      /* Read in the kernel array: */
+      ui_read_kernel(p);
 
-          /* Normalize the kernel: */
-          if( !p->nokernelnorm )
+      /* Check if the size along each dimension of the kernel is an odd
+         number. If they are all an odd number, then the for each dimension,
+         check will be incremented once. */
+      for(i=0;i<p->kernel->ndim;++i)
+        check += p->kernel->dsize[i]%2;
+      if(check!=p->kernel->ndim)
+        error(EXIT_FAILURE, 0, "%s: the kernel has to have an odd number of "
+              "elements in all dimensions (there has to be one element/pixel "
+              "in the center). At least one of the dimensions of doesn't "
+              "have an odd number of pixels",
+              gal_checkset_dataset_name(p->kernelname, p->khdu));
+
+
+      /* If there are any NaN pixels, set them to zero and normalize it. A
+         blank pixel in a kernel is going to make a completely blank
+         output.*/
+      if( !p->nokernelnorm )
+        {
+          sumv=0;
+          fp=(f=p->kernel->array)+p->kernel->size;
+          do
             {
-              sum=gal_statistics_sum(p->kernel);
-              p->kernel = gal_arithmetic(GAL_ARITHMETIC_OP_DIVIDE,
-                                         GAL_ARITHMETIC_FLAGS_ALL,
-                                         p->kernel, sum);
+              if(isnan(*f)) *f=0.0f;
+              else          sumv+=*f;
             }
+          while(++f<fp);
+          p->kernel->flag |= GAL_DATA_FLAG_BLANK_CH;
+          p->kernel->flag &= ~GAL_DATA_FLAG_HASBLANK;
+          f=p->kernel->array; do *f++ *= 1/sumv; while(f<fp);
+        }
 
-          /* Flip the kernel: */
-          if( !p->nokernelflip )
+      /* Flip the kernel: */
+      if( !p->nokernelflip )
+        {
+          size=p->kernel->size;
+          kernel=p->kernel->array;
+          for(i=0;i<p->kernel->size/2;++i)
             {
-              size=p->kernel->size;
-              kernel=p->kernel->array;
-              for(i=0;i<p->kernel->size/2;++i)
-                {
-                  tmp                     = kernel[ i            ];
-                  kernel[ i             ] = kernel[ size - i - 1 ];
-                  kernel[ size -  i - 1 ] = tmp;
-                }
+              tmp                     = kernel[ i            ];
+              kernel[ i             ] = kernel[ size - i - 1 ];
+              kernel[ size -  i - 1 ] = tmp;
             }
         }
-      else
-        p->kernel = gal_fits_img_read_kernel(p->kernelname, p->khdu,
-                                             cp->minmapsize);
+    }
+
+
+  /* Set the output name if the user hasn't set it. */
+  if(cp->output==NULL)
+    cp->output=gal_checkset_automatic_output(cp, p->filename, outsuffix);
+  gal_checkset_writable_remove(cp->output, 0, cp->dontdelete);
+  if(p->checkfreqsteps)
+    {
+      p->freqstepsname=gal_checkset_automatic_output(cp, p->filename,
+                                                     "_freqsteps.fits");
+      gal_checkset_writable_remove(p->freqstepsname, 0, cp->dontdelete);
+    }
+  if(cp->tl.checktiles)
+    {
+      cp->tl.tilecheckname=gal_checkset_automatic_output(cp, p->filename,
+                                                         "_tiled.fits");
+      gal_checkset_writable_remove(cp->tl.tilecheckname, 0,
+                                   cp->dontdelete);
     }
 }
 
@@ -491,8 +677,10 @@ ui_print_intro(struct convolveparams *p)
 {
   printf("%s started on %s", PROGRAM_NAME, ctime(&p->rawtime));
   printf("  - Using %zu CPU threads.\n", p->cp.numthreads);
-  printf("  - Input: %s (hdu: %s)\n", p->filename, p->cp.hdu);
-  printf("  - Kernel: %s (hdu: %s)\n", p->kernelname, p->khdu);
+  printf("  - Input: %s\n",
+         gal_checkset_dataset_name(p->filename, p->cp.hdu));
+  printf("  - Kernel: %s\n",
+         gal_checkset_dataset_name(p->kernelname, p->khdu));
 }
 
 
diff --git a/bin/convolve/ui.h b/bin/convolve/ui.h
index 947e1a3..81e67f9 100644
--- a/bin/convolve/ui.h
+++ b/bin/convolve/ui.h
@@ -42,7 +42,7 @@ enum program_args_groups
 
 /* Available letters for short options:
 
-   a b e f g i j l n p s v w x y z
+   a b e f g i j l p s v w x y z
    A B E G J L O Q R W X Y
 */
 enum option_keys_enum
@@ -53,14 +53,16 @@ enum option_keys_enum
   UI_KEY_MINSHARPSPEC   = 'H',
   UI_KEY_CHECKFREQSTEPS = 'C',
   UI_KEY_TILESIZE       = 't',
-  UI_KEY_NUMCHANNELS    = 'c',
+  UI_KEY_COLUMN         = 'c',
+  UI_KEY_NUMCHANNELS    = 'n',
   UI_KEY_REMAINDERFRAC  = 'r',
   UI_KEY_DOMAIN         = 'd',
   UI_KEY_MAKEKERNEL     = 'm',
 
   /* Only with long version (start with a value 1000, the rest will be set
      automatically). */
-  UI_KEY_NOKERNELFLIP = 1000,
+  UI_KEY_KERNELCOLUMN = 1000,
+  UI_KEY_NOKERNELFLIP,
   UI_KEY_NOKERNELNORM,
   UI_KEY_NOEDGECORRECTION,
 };
diff --git a/bin/cosmiccal/args.h b/bin/cosmiccal/args.h
index 6c7d5cd..12d7c57 100644
--- a/bin/cosmiccal/args.h
+++ b/bin/cosmiccal/args.h
@@ -110,7 +110,7 @@ struct argp_option program_options[] =
       UI_KEY_AGENOW,
       0,
       0,
-      "Age of universe now (Gyr).",
+      "Age of universe now (Ga: Giga Annum).",
       UI_GROUP_SPECIFIC,
       &p->specific,
       GAL_OPTIONS_NO_ARG_TYPE,
@@ -222,7 +222,7 @@ struct argp_option program_options[] =
       UI_KEY_AGE,
       0,
       0,
-      "Age of universe at z (Gyr).",
+      "Age of universe at z (Ga: Giga Annum).",
       UI_GROUP_SPECIFIC,
       &p->specific,
       GAL_OPTIONS_NO_ARG_TYPE,
@@ -236,7 +236,7 @@ struct argp_option program_options[] =
       UI_KEY_LOOKBACKTIME,
       0,
       0,
-      "Look back time to z (Gyr).",
+      "Look back time to z (Ga: Giga Annum).",
       UI_GROUP_SPECIFIC,
       &p->specific,
       GAL_OPTIONS_NO_ARG_TYPE,
diff --git a/bin/cosmiccal/cosmiccal.c b/bin/cosmiccal/cosmiccal.c
index 1ce4ad2..49a4929 100644
--- a/bin/cosmiccal/cosmiccal.c
+++ b/bin/cosmiccal/cosmiccal.c
@@ -113,7 +113,7 @@ cosmiccal_printall(struct cosmiccalparams *p)
 
   printf("\n\n Universe now\n");
   printf(    " ------------\n");
-  printf(FLTFORMAT, "Age of Universe now (Gyr):", curage);
+  printf(FLTFORMAT, "Age of Universe now (Ga*):", curage);
   printf(EXPFORMAT, "Critical density now (g/cm^3):",  ccritd);
   printf(FLTFORMAT, "Proper distance to z (Mpc):", pd);
   printf(FLTFORMAT, "Angular diameter distance to z (Mpc):", ad);
@@ -127,13 +127,16 @@ cosmiccal_printall(struct cosmiccalparams *p)
 
   printf("\n\n Universe at desired redshift z\n");
   printf(    " ------------------------------\n");
-  printf(FLTFORMAT, "Age of Universe at z (Gyr):", outage);
-  printf(FLTFORMAT, "Look-back time to z (Gyr):", curage-outage);
+  printf(FLTFORMAT, "Age of Universe at z (Ga*):", outage);
+  printf(FLTFORMAT, "Look-back time to z (Ga*):", curage-outage);
   printf(EXPFORMAT, "Critical density at z (g/cm^3):",  zcritd);
 
   printf("\n\n Comoving universe (time independent)\n");
   printf(    " ------------------------------------\n");
   printf(FLTFORMAT, "Comoving volume over 4pi stradian to z (Mpc^3):", vz);
+
+  printf("\n-------\n");
+  printf("*: Ga is short for Giga Annum, or billion years (IAU standard).\n");
 }
 
 
diff --git a/bin/crop/onecrop.c b/bin/crop/onecrop.c
index 6f3152f..330a153 100644
--- a/bin/crop/onecrop.c
+++ b/bin/crop/onecrop.c
@@ -129,7 +129,23 @@ onecrop_parse_section(struct cropparams *p, size_t *dsize,
           add=1;                /* If it is an asterisk, then add the */
           ++pt;                 /* given value to the maximum size of */
           break;                /* the image. */
+
+        /* Numerical characters signify the start of a number, so we don't
+           need to increment the pointer and can just break out. */
+        case '0': case '1': case '2': case '3': case '4': case '5':
+        case '6': case '7': case '8': case '9': case '-':
+          break;
+
+        /* An un-recognized character should crash the program. */
         default:
+          error(EXIT_FAILURE, 0, "value to `--section' must only contain "
+                "integer numbers and these special characters between them: "
+                "`,', `:', `*' when necessary. But it is `%s' (the first "
+                "non-acceptable character is `%c').\n\n"
+                "Please run the command below to learn more about this "
+                "option in Gnuastro's Crop program:\n\n"
+                "    $ info gnuastro \"Crop section syntax\"\n", p->section,
+                *pt);
           break;
         }
 
diff --git a/bin/match/ui.c b/bin/match/ui.c
index 74de816..c0d48d4 100644
--- a/bin/match/ui.c
+++ b/bin/match/ui.c
@@ -553,7 +553,8 @@ ui_read_columns_to_double(struct matchparams *p, char 
*filename, char *hdu,
      once, we don't want to write a blank list over it (the Standard input
      will be empty after being read). */
   if(p->stdinlines==NULL)
-    p->stdinlines=gal_options_check_stdin(filename, p->cp.stdintimeout);
+    p->stdinlines=gal_options_check_stdin(filename, p->cp.stdintimeout,
+                                          "input");
   tout=gal_table_read(filename, hdu, filename ? NULL : p->stdinlines,
                       cols, cp->searchin, cp->ignorecase, cp->minmapsize,
                       NULL);
diff --git a/bin/mkprof/ui.c b/bin/mkprof/ui.c
index f5da30e..515760f 100644
--- a/bin/mkprof/ui.c
+++ b/bin/mkprof/ui.c
@@ -653,7 +653,7 @@ ui_read_cols_2d(struct mkprofparams *p)
   gal_list_str_reverse(&colstrs);
 
   /* Read the desired columns from the file. */
-  lines=gal_options_check_stdin(p->catname, p->cp.stdintimeout);
+  lines=gal_options_check_stdin(p->catname, p->cp.stdintimeout, "input");
   cols=gal_table_read(p->catname, p->cp.hdu, lines, colstrs, p->cp.searchin,
                       p->cp.ignorecase, p->cp.minmapsize, NULL);
   gal_list_str_free(lines, 1);
@@ -873,7 +873,7 @@ ui_read_cols_3d(struct mkprofparams *p)
   gal_list_str_reverse(&colstrs);
 
   /* Read the desired columns from the file. */
-  lines=gal_options_check_stdin(p->catname, p->cp.stdintimeout);
+  lines=gal_options_check_stdin(p->catname, p->cp.stdintimeout, "input");
   cols=gal_table_read(p->catname, p->cp.hdu, lines, colstrs, p->cp.searchin,
                       p->cp.ignorecase, p->cp.minmapsize, NULL);
   gal_list_str_free(lines, 1);
diff --git a/bin/statistics/ui.c b/bin/statistics/ui.c
index 295753e..2774022 100644
--- a/bin/statistics/ui.c
+++ b/bin/statistics/ui.c
@@ -701,7 +701,7 @@ ui_read_columns(struct statisticsparams *p)
   gal_data_t *cols, *tmp, *cinfo;
   size_t size, ncols, nrows, counter=0;
   gal_list_str_t *lines=gal_options_check_stdin(p->inputname,
-                                                p->cp.stdintimeout);
+                                                p->cp.stdintimeout, "input");
 
   /* If a reference column is also given, add it to the list of columns to
      read. */
diff --git a/bin/table/ui.c b/bin/table/ui.c
index b94cc96..1612aa2 100644
--- a/bin/table/ui.c
+++ b/bin/table/ui.c
@@ -276,7 +276,7 @@ ui_print_info_exit(struct tableparams *p)
   size_t i, numcols, numrows;
 
   /* Read the table information for the number of columns and rows. */
-  lines=gal_options_check_stdin(p->filename, p->cp.stdintimeout);
+  lines=gal_options_check_stdin(p->filename, p->cp.stdintimeout, "input");
   allcols=gal_table_info(p->filename, p->cp.hdu, lines, &numcols,
                          &numrows, &tableformat);
   if(p->filename==NULL) p->filename="Standard-input";
@@ -374,7 +374,7 @@ ui_preparations(struct tableparams *p)
   ui_columns_prepare(p);
 
   /* Read in the table columns. */
-  lines=gal_options_check_stdin(p->filename, p->cp.stdintimeout);
+  lines=gal_options_check_stdin(p->filename, p->cp.stdintimeout, "input");
   p->table=gal_table_read(p->filename, cp->hdu, lines, p->columns,
                           cp->searchin, cp->ignorecase, cp->minmapsize,
                           NULL);
diff --git a/configure.ac b/configure.ac
index b2ca04e..6313a4d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -275,8 +275,13 @@ AC_SEARCH_LIBS([gsl_integration_qng], [gsl], [],
 # no problem for Gnuastro either. So there is no need to stop the configure
 # script if libcurl isn't found.
 #
-# For static builds, libcurl depends on linking with zlib. So we'll need to
-# also search for that.
+# For static builds, linking libcurl (also built in static-only mode) will
+# depend on linking with zlib. So we'll need to also search for that
+# also. But if libcurl isn't built in static-only mode, then it will have
+# undefined symbols for many libraries (for example libpsl, libidn2,
+# librtmp, libldap). So if you intend to make Gnuastro statically, then
+# build Libcurl in static-only mode so you won't have to check for all
+# these extra libraries here.
 AC_SEARCH_LIBS([deflateInit_], [z], [], [])
 AC_SEARCH_LIBS([curl_global_init], [curl], [], [])
 AC_SEARCH_LIBS([ffopen], [cfitsio], [],
@@ -341,7 +346,12 @@ AM_CONDITIONAL([COND_HASLIBJPEG], [test "x$has_libjpeg" = 
"xyes"])
 
 
 
-# Check libtiff:
+# Check libtiff: If an LZMA libray (part of the XZ Utils) is present,
+# libtiff has probably been built with it. So we'll also need to link with
+# the LZMA library. But if libtiff hasn't been linked with it and its
+# present, there is no problem, the linker will just pass over it. So we
+# don't need to stop the build if this fails.
+AC_SEARCH_LIBS([lzma_stream_decoder], [lzma], [], [])
 AC_SEARCH_LIBS([TIFFOpen], [tiff],
                [has_libtiff=yes], [has_libtiff=no; missing_optional_lib=yes])
 AS_IF([test "x$has_libtiff" = "xyes"],
diff --git a/doc/announce-acknowledge.txt b/doc/announce-acknowledge.txt
index cffd52c..2a42585 100644
--- a/doc/announce-acknowledge.txt
+++ b/doc/announce-acknowledge.txt
@@ -3,7 +3,9 @@ Alphabetically ordered list to acknowledge in the next release.
 Fernando Buitrago
 Pierre-Alain Duc
 Gaspar Galaz
+Raúl Infante Sainz
 Johan Knapen
 Mamta Pommier
 Michael Stein
 Ignacio Trujillo
+David Valls-Gabaud
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 04dc62b..73aae45 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -982,7 +982,7 @@ results. Before he actually saw the moons of Jupiter, the 
mountains on the
 Moon or the crescent of Venus, Galileo was “evasive”@footnote{Galileo
 G. (Translated by Maurice A. Finocchiaro). @emph{The essential
 Galileo}. Hackett publishing company, first edition, 2008.} to
-Kepler. Science is defined by its tools/methods, @emph{not} its
+Kepler. Science is defined by its tools/methods, @emph{not} its raw
 results@footnote{For example, take the following two results on the age of
 the universe: roughly 14 billion years (suggested by the current consensus
 of the standard model of cosmology) and less than 10,000 years (suggested
@@ -990,22 +990,24 @@ from some interpretations of the Bible). Both these 
numbers are
 @emph{results}. What distinguishes these two results, is the tools/methods
 that were used to derive them. Therefore, as the term ``Scientific method''
 also signifies, a scientific statement it defined by its @emph{method}, not
-its result.}
+its result.}.
 
 The same is true today: science cannot progress with a black box, or poorly
-released code. Technical knowledge and experience (to experiment on its
-tools, or software in this context@footnote{Of course, this also applies to
-hardware.}), is critical to scientific vitality. Scientific research are
-only considered for peer review and publication if they have a sufficiently
-high standard of English style. A similar level of quality assessment is
-necessary regarding the codes/methods scientists use to derive their
-results. Therefore, when a scientist says ``software is not my specialty, I
-am not a software engineer. So the quality of my code/processing doesn't
-matter. Why should I master good coding style, or release my code, when I
-am hired to do Astronomy/Biology?''. This statement is akin to a French
-scientist saying that "English is not my language, I am not Shakespeare. So
-the quality of my English writing doesn't matter. Why should I master good
-English style, when I am hired to do Astronomy/Biology?"
+released code. The source code of a research is the new (abstractified)
+communication language in science, understandable by humans @emph{and}
+computers. Source code (in any programming language) is a language/notation
+designed to express all the details that would be too
+tedious/long/frustrating to report in spoken languages like English,
+similar to mathematic notation.
+
+Today, the quality of the source code that goes into a scientific result
+(and the distribution of that code) is as critical to scientific vitality
+and integrity, as the quality of its written language/English used in
+publishing/distributing its paper. A scientific paper will not even be
+reviewed by any respectable journal if its written in a poor
+language/English. A similar level of quality assessment is thus
+increasingly becoming necessary regarding the codes/methods used to derive
+the results of a scientific paper.
 
 @cindex Ken Thomson
 @cindex Stroustrup, Bjarne
@@ -1692,7 +1694,7 @@ Gnuastro would not have been possible without 
scholarships and grants from
 several funding institutions. We thus ask that if you used Gnuastro in any
 of your papers/reports, please add the proper citation and acknowledge this
 instrumental support. For details of which papers to cite (may be different
-for different programs) and get the acknowledgement statement to include in
+for different programs) and get the acknowledgment statement to include in
 your paper, please run the relevant programs with the common
 @option{--cite} option like the example commands below (for more on
 @option{--cite}, please see @ref{Operating mode options}).
@@ -2600,7 +2602,7 @@ small number).
 This is the deepest image we currently have of the sky. The first thing
 that comes to mind may be this: ``How large is this field?''. The FITS
 world coordinate system (WCS) meta data standard contains the key to
-ansering this question: the @code{CDELT} keyword@footnote{In the FITS
+answering this question: the @code{CDELT} keyword@footnote{In the FITS
 standard, the @code{CDELT} keywords (@code{CDELT1} and @code{CDELT2} in a
 2D image) specify the scales of each coordinate. In the case of this image
 it is in units of degrees-per-pixel. See Section 8 of the
@@ -2610,7 +2612,7 @@ standard} for more. In short, with the @code{CDELT} 
convention, rotation
 separated. In the FITS standard the @code{CDELT} keywords are
 optional. When @code{CDELT} keywords aren't present, the @code{PC} matrix
 is assumed to contain @emph{both} the coordinate rotation and scales. Note
-that not all FITS writers use the @code{CDELT} convension. So you might not
+that not all FITS writers use the @code{CDELT} convention. So you might not
 find the @code{CDELT} keywords in the WCS meta data of some FITS
 files. However, all Gnuastro programs (which use the default FITS keyword
 writing format of WCSLIB), the @code{CDELT} convention is used, even if the
@@ -3185,7 +3187,7 @@ objects. This shows that we have dug in too deep, and 
that we are following
 correlated noise.
 
 Correlated noise is created when we warp datasets from individual exposures
-(that are each slightly offest compared to each other) into the same pixel
+(that are each slightly offset compared to each other) into the same pixel
 grid, then add them to form the final result. Because it mixes nearby pixel
 values, correlated noise is a form of convolution and it smooths the
 image. In terms of the number of exposures (and thus correlated noise), the
@@ -3200,7 +3202,7 @@ purely routine matter, and generally calls for more than 
one pass through
 the computer}'' (Anscombe 1973, see @ref{Science and its tools}). A good
 scientist must have a good understanding of her tools to make a meaningful
 analysis. So don't hesitate in playing with the default configuration and
-reviewing the manual when you have a new dataset infront of you. Robust
+reviewing the manual when you have a new dataset in front of you. Robust
 data analysis is an art, therefore a good scientist must first be a good
 artist.
 
@@ -3238,7 +3240,7 @@ NoiseChisel. We see these thin connections between 
smaller points are
 already present here (a relatively early stage in the processing). Such
 connections at the lowest surface brightness limits usually occur when the
 dataset is too smoothed. Because of correlated noise, the dataset is
-already artificially smoothed, therefore futher smoothing it with the
+already artificially smoothed, therefore further smoothing it with the
 default kernel may be the problem. Therefore, one solution is to use a
 sharper kernel (NoiseChisel's first step in its processing).
 
@@ -3274,7 +3276,7 @@ can see that there aren't too many pseudo-detections 
because of all those
 extended filled holes. If you look closely, you can see the number of
 pseudo-detections in the result NoiseChisel prints (around 4000). This is
 another side-effect of correlated noise. To address it, we should slightly
-increase the pseudo-detection threhold (@option{--dthresh}, run with
+increase the pseudo-detection threshold (@option{--dthresh}, run with
 @option{-P} to see its default value):
 
 @example
@@ -3328,7 +3330,7 @@ signal-to-noise quantile @option{--snquant} is 0.99. In 
effect with this
 option you specify the purity level you want (contamination by false
 detections). With the @command{aststatistics} command above, you see that a
 small number of extra false detections (impurity) in the final result
-causes a big change in completness (you can detect more lower
+causes a big change in completeness (you can detect more lower
 signal-to-noise true detections). So let's loosen-up our desired purity
 level and then mask the detected pixels like before to see if we have
 missed anything.
@@ -4157,7 +4159,7 @@ generally calls for more than one pass through the 
computer}'' (Anscombe
 1973, see @ref{Science and its tools}). A good scientist must have a good
 understanding of her tools to make a meaningful analysis. So don't hesitate
 in playing with the default configuration and reviewing the manual when you
-have a new dataset infront of you. Robust data analysis is an art,
+have a new dataset in front of you. Robust data analysis is an art,
 therefore a good scientist must first be a good artist.
 
 The first extension of @file{r_qthresh.fits} (@code{CONVOLVED}) is the
@@ -4184,7 +4186,7 @@ you play with the color-bar, you see that the faintest 
parts of the galaxy
 outskirts still remain. Therefore have two strategies for approaching this
 problem: 1) Increase the tile size to get more accurate measurements of
 skewness. 2) Strengthen the outlier rejection parameters to discard more of
-the tiles with signal. Fortunately in this image we have a sufficently
+the tiles with signal. Fortunately in this image we have a sufficiently
 large region on the right of the image that the galaxy doesn't extend
 to. So we can use the more robust first solution. In situations where this
 doesn't happen (for example if the field of view in this image was shifted
@@ -4290,7 +4292,7 @@ further configuration for a more accurate detection to 
you as an exercise.
 
 In this shallow image, this extent may seem too far deep into the noise for
 visual confirmation. Therefore, if the statistical argument above, to
-justify the reality of this extented structure, hasn't convinced you, see
+justify the reality of this extended structure, hasn't convinced you, see
 the deep images of this system in @url{https://arxiv.org/abs/1501.04599,
 Watkins et al. [2015]}, or a 12 hour deep image of this system (with a
 12-inch telescope): @url{https://i.redd.it/jfqgpqg0hfk11.jpg}@footnote{The
@@ -4310,7 +4312,7 @@ $ astarithmetic r_detected.fits 2 connected-components 
-hDETECTIONS \
                 -olabeled.fits
 @end example
 
-Ofcourse, you can find the the label of the main galaxy visually, but to
+Of course, you can find the the label of the main galaxy visually, but to
 have a little more fun, lets do this automatically. The M51 group detection
 is by far the largest detection in this image. We can thus easily find the
 ID/label that corresponds to it. We'll first run MakeCatalog to find the
@@ -4386,7 +4388,7 @@ The outer wings where therefore non-parametrically 
detected until
 @cindex Surface brightness
 This is very good! But the signal-to-noise ratio is a relative measurement.
 Let's also measure the depth of our detection in absolute surface
-brighntess units; or magnitudes per square arcseconds. To find out, we'll
+brightness units; or magnitudes per square arcseconds. To find out, we'll
 first need to calculate how many pixels of this image are in one
 arcsecond-squared. Fortunately the world coordinate system (or WCS) meta
 data of Gnuastro's output FITS files (in particular the @code{CDELT}
@@ -6862,7 +6864,7 @@ or sending to colleagues who don't use Git for an easy 
build and manual.
 @item --upload STR
 Activate the @option{--dist} (@option{-D}) option, then use secure copy
 (@command{scp}, part of the SSH tools) to copy the tarball and PDF to the
-@file{src} and @file{pdf} subdirectories of the specified server and its
+@file{src} and @file{pdf} sub-directories of the specified server and its
 directory (value to this option). For example @command{--upload
 my-server:dir}, will copy the tarball in the @file{dir/src}, and the PDF
 manual in @file{dir/pdf} of @code{my-server} server. It will then make a
@@ -6972,7 +6974,7 @@ this line:
 @end example
 
 @noindent
-In Texinfo, a line is commented with @code{@@c}. Therefore, uncomment this
+In Texinfo, a line is commented with @code{@@c}. Therefore, un-comment this
 line by deleting the first two characters such that it changes to:
 
 @example
@@ -7193,13 +7195,13 @@ datasets: setting the proper type for the usage 
context@footnote{For
 example if the values in your dataset can only be integers between 0 or
 65000, store them in a unsigned 16-bit type, not 64-bit floating point type
 (which is the default in most systems). It takes four times less space and
-is much faster to process.} can grealy improve the file size and also speed
+is much faster to process.} can greatly improve the file size and also speed
 of reading, writing or processing them.
 
 We'll then look into the recognized table formats in @ref{Tables} and how
 large datasets are broken into tiles, or mesh grid in
 @ref{Tessellation}. Finally, we'll take a look at the behavior regarding
-output files: @ref{Automatic output} discribes how the programs set a
+output files: @ref{Automatic output} describes how the programs set a
 default name for their output when you don't give one explicitly (using
 @option{--output}). When the output is a FITS file, all the programs also
 store some very useful information in the header that is discussed in
@@ -7249,7 +7251,7 @@ this manual for some examples of commands with each 
program, like
 @ref{Invoking asttable}, @ref{Invoking astfits}, or @ref{Invoking
 aststatistics}.
 
-The shell then brokes up your string into separate @emph{tokens} or
+The shell then brakes up your string into separate @emph{tokens} or
 @emph{words} using any @emph{metacharacters} (like white-space, tab,
 @command{|}, @command{>} or @command{;}) that are in the string. On the
 command-line, the first thing you usually enter is the name of the program
@@ -7863,11 +7865,11 @@ Print all necessary information to cite and acknowledge 
Gnuastro in your
 published papers. With this option, the programs will print the Bib@TeX{}
 entry to include in your paper for Gnuastro in general, and the particular
 program's paper (if that program comes with a separate paper). It will also
-print the necessary acknowledgement statement to add in the respective
+print the necessary acknowledgment statement to add in the respective
 section of your paper and it will abort. For a more complete explanation,
 please see @ref{Acknowledgments}.
 
-Citations and acknowledgements are vital for the continued work on
+Citations and acknowledgments are vital for the continued work on
 Gnuastro. Gnuastro started, and is continued, based on separate research
 projects. So if you find any of the tools offered in Gnuastro to be useful
 in your research, please use the output of this command to cite and
@@ -8067,7 +8069,7 @@ To solve the problem, the founders of Unix defined pipes 
to directly feed
 the output of one program (its ``Standard output'' stream) into the
 ``standard input'' of a next program. This removes the need to make
 temporary files between separate processes and became one of the best
-demonstrations of the Unix-way, or Unix philosopy.
+demonstrations of the Unix-way, or Unix philosophy.
 
 Every program has three streams identifying where it reads/writes non-file
 inputs/outputs: @emph{Standard input}, @emph{Standard output}, and
@@ -13509,7 +13511,7 @@ averages the signal it receives over that area, not a 
mathematical point as
 the Dirac @mymath{\delta} function defines. However, as long as the
 variation in the signal over one detector pixel is not significant, this
 can be a good approximation. Having put this issue to the side, we can now
-try to find the relation between the Fourier transforms of the unsampled
+try to find the relation between the Fourier transforms of the un-sampled
 @mymath{f(l)} and the sampled @mymath{f_s(l)}. For a more clear notation,
 let's define:
 
@@ -13929,8 +13931,9 @@ value.
 @node Invoking astconvolve,  , Convolution kernel, Convolve
 @subsection Invoking Convolve
 
-Convolve an input image with a known kernel or make the kernel necessary to
-match two PSFs. The general template for Convolve is:
+Convolve an input dataset (2D image or 1D spectrum for example) with a
+known kernel, or make the kernel necessary to match two PSFs. The general
+template for Convolve is:
 
 @example
 $ astconvolve [OPTION...] ASTRdata
@@ -13949,15 +13952,27 @@ $ astconvolve observedimg.fits --kernel=psf.fits 
--domain=spatial
 ## Find the kernel to match sharper and blurry PSF images:
 $ astconvolve --kernel=sharperimage.fits --makekernel=10           \
               blurryimage.fits
+
+## Convolve a Spectrum (column 14 in the FITS table below) with a
+## custom kernel (the kernel will be normalized internally, so only
+## the ratios are important). Sed is used to replace the spaces with
+## new line characters so Convolve sees them as values in one column.
+$ echo "1 3 10 3 1" | sed 's/ /\n/g' | astconvolve spectra.fits -c14
 @end example
 
 The only argument accepted by Convolve is an input image file. Some of the
 options are the same between Convolve and some other Gnuastro
 programs. Therefore, to avoid repetition, they will not be repeated
 here. For the full list of options shared by all Gnuastro programs, please
-see @ref{Common options}. In particular, in the spatial domain convolve
-uses Gnuastro's tessellation, see @ref{Tessellation} and the common options
-related to that in @ref{Processing options}.
+see @ref{Common options}. In particular, in the spatial domain, on a
+multi-dimensional datasets, convolve uses Gnuastro's tessellation to speed
+up the run, see @ref{Tessellation}. Common options related to tessellation
+are described in in @ref{Processing options}.
+
+1-dimensional datasets (for example spectra) are only read as columns
+within a table (see @ref{Tables} for more on how Gnuastro programs read
+tables). Note that currently 1D convolution is only implemented in the
+spatial domain and thus kernel-matching is also not supported.
 
 Here we will only explain the options particular to Convolve. Run Convolve
 with @option{--help} in order to see the full list of options Convolve
@@ -13965,6 +13980,11 @@ accepts, irrespective of where they are explained in 
this book.
 
 @table @option
 
+@item --kernelcolumn
+Column containing the 1D kernel. When the input dataset is a 1-dimensional
+column, and the host table has more than one column, use this option to
+specify which column should be used.
+
 @item --nokernelflip
 Do not flip the kernel after reading it the spatial domain
 convolution. This can be useful if the flipping has already been
@@ -14081,6 +14101,8 @@ direction, so crop the central pixel of the warped 
image to have a
 clean image for the de-convolution.
 @end itemize
 
+Note that this feature is not yet supported in 1-dimensional datasets.
+
 @item -c
 @itemx --minsharpspec
 (@option{=FLT}) The minimum frequency spectrum (or coefficient, or pixel
@@ -16677,7 +16699,7 @@ only one pixel will be used for each tile (see 
@ref{Processing options}).
 
 @item -s FLT,FLT
 @itemx --sigmaclip=FLT,FLT
-The @mymath{\sigma}-clipping parameters for measuing the initial and final
+The @mymath{\sigma}-clipping parameters for measuring the initial and final
 Sky values from the undetected pixels, see @ref{Sigma clipping}.
 
 This option takes two values which are separated by a comma (@key{,}). Each
@@ -16698,7 +16720,7 @@ undetected regions on the unconvolved image. The 
background pixels that are
 completely engulfed in a 4-connected foreground region are converted to
 background (holes are filled) and one opening (depth of 1) is applied over
 both the initially detected and undetected regions. The Signal to noise
-ratio of the resulting `psudo-detections' are used to identify true
+ratio of the resulting `pseudo-detections' are used to identify true
 vs. false detections. See Section 3.1.5 and Figure 7 in Akhlaghi and
 Ichikawa (2015) for a very complete explanation.
 
@@ -16715,16 +16737,16 @@ complete dataset and thus not create enough 
pseudo-detections.
 @item -m INT
 @itemx --snminarea=INT
 The minimum area to calculate the Signal to noise ratio on the
-psudo-detections of both the initially detected and undetected
-regions. When the area in a psudo-detection is too small, the Signal to
+pseudo-detections of both the initially detected and undetected
+regions. When the area in a pseudo-detection is too small, the Signal to
 noise ratio measurements will not be accurate and their distribution will
 be heavily skewed to the positive. So it is best to ignore any
-psudo-detection that is smaller than this area. Use
+pseudo-detection that is smaller than this area. Use
 @option{--detsnhistnbins} to check if this value is reasonable or not.
 
 @item --checksn
 Save the S/N values of the pseudo-detections (and possibly grown detections
-if @option{--cleangrowndet} is called) into seprate tables. If
+if @option{--cleangrowndet} is called) into separate tables. If
 @option{--tableformat} is a FITS table, each table will be written into a
 separate extension of one file suffixed with @file{_detsn.fits}. If it is
 plain text, a separate file will be made for each table (ending in
@@ -16742,7 +16764,7 @@ better understanding of the distribution (for example 
through a histogram).
 The minimum number of `pseudo-detections' over the undetected regions to
 identify a Signal-to-Noise ratio threshold. The Signal to noise ratio (S/N)
 of false pseudo-detections in each tile is found using the quantile of the
-S/N distribution of the psudo-detections over the undetected pixels in each
+S/N distribution of the pseudo-detections over the undetected pixels in each
 mesh. If the number of S/N measurements is not large enough, the quantile
 will not be accurate (can have large scatter). For example if you set
 @option{--snquant=0.99} (or the top 1 percent), then it is best to have at
@@ -16751,10 +16773,10 @@ least 100 S/N measurements.
 @item -c FLT
 @itemx --snquant=FLT
 The quantile of the Signal to noise ratio distribution of the
-psudo-detections in each mesh to use for filling the large mesh grid. Note
+pseudo-detections in each mesh to use for filling the large mesh grid. Note
 that this is only calculated for the large mesh grids that satisfy the
 minimum fraction of undetected pixels (value of @option{--minbfrac}) and
-minimum number of psudo-detections (value of @option{--minnumfalse}).
+minimum number of pseudo-detections (value of @option{--minnumfalse}).
 
 @item -d FLT
 @itemx --detgrowquant=FLT
@@ -17533,13 +17555,13 @@ this size is set to a small value, the Signal to 
noise ratio of false
 clumps will not be accurately found. It is recommended that this value be
 larger than the value to NoiseChisel's @option{--snminarea}. Because the
 clumps are found on the convolved (smoothed) image while the
-psudo-detections are found on the input image. You can use
+pseudo-detections are found on the input image. You can use
 @option{--checksn} and @option{--checksegmentation} to see if your chosen
 value is reasonable or not.
 
 @item --checksn
 Save the S/N values of the clumps over the sky and detected regions into
-seprate tables. If @option{--tableformat} is a FITS format, each table will
+separate tables. If @option{--tableformat} is a FITS format, each table will
 be written into a separate extension of one file suffixed with
 @file{_clumpsn.fits}. If it is plain text, a separate file will be made for
 each table (ending in @file{_clumpsn_sky.txt} and
@@ -17859,7 +17881,7 @@ the pixels covering one galaxy in an image, get the 
same label.
 
 The requested measurements are then done on similarly labeled pixels. The
 final result is a catalog where each row corresponds to the measurements on
-pixels with a specfic label. For example the flux weighted average position
+pixels with a specific label. For example the flux weighted average position
 of all the pixels with a label of 42 will be written into the 42nd row of
 the output catalog/table's central position column@footnote{See
 @ref{Measuring elliptical parameters} for a discussion on this and the
@@ -19481,7 +19503,7 @@ $ astmatch --ccol1=2,3,4 --ccol2=2,3,4 
-a0.5/3600,0.5/3600,5e-10 \
 
 Two inputs are necessary for Match to start processing. The inputs can be
 plain text tables or FITS tables, see @ref{Tables}. If only one argument is
-provided, Match will assume look for the first input in Stanard input (see
+provided, Match will assume look for the first input in Standard input (see
 @ref{Standard input}).
 
 Match follows the same basic behavior of all Gnuastro programs as fully
@@ -21302,15 +21324,15 @@ reading right now, run to the nearest bookstore, and 
buy
 it''@footnote{For students, running to the library might be more
 affordable!}!
 
-@cindex Psudo-random numbers
-@cindex Numbers, psudo-random
-Using only software, we can only produce what is called a psudo-random
+@cindex Psuedo-random numbers
+@cindex Numbers, psuedo-random
+Using only software, we can only produce what is called a psuedo-random
 sequence of numbers. A true random number generator is a hardware (let's
 assume we have made sure it has no systematic biases), for example
 throwing dice or flipping coins (which have remained from the ancient
 times). More modern hardware methods use atmospheric noise, thermal
 noise or other types of external electromagnetic or quantum
-phenomena. All psudo-random number generators (software) require a
+phenomena. All pseudo-random number generators (software) require a
 seed to be the basis of the generation. The advantage of having a seed
 is that if you specify the same seed for multiple runs, you will get
 an identical sequence of random numbers which allows you to reproduce
@@ -21585,7 +21607,7 @@ difficult to visualize (a curved 3D space embedded in 
4D).
 To start, let's assume a static (not expanding or shrinking), flat 2D
 surface similar to @ref{flatplane} and that the 2D creature is observing
 its universe from point @mymath{A}. One of the most basic ways to
-parametrize this space is through the Cartesian coordinates (@mymath{x},
+parameterize this space is through the Cartesian coordinates (@mymath{x},
 @mymath{y}). In @ref{flatplane}, the basic axes of these two coordinates
 are plotted. An infinitesimal change in the direction of each axis is
 written as @mymath{dx} and @mymath{dy}. For each point, the infinitesimal
@@ -21777,7 +21799,7 @@ very similar to that of light in vacuum, see
 @url{https://arxiv.org/abs/1710.05834, arXiv:1710.05834}.}) in a
 vacuum. This speed is postulated to be constant@footnote{In @emph{natural
 units}, speed is measured in units of the speed of light in vacuum.} and is
-almost always written as @mymath{c}. We can thus parametrize the change in
+almost always written as @mymath{c}. We can thus parameterize the change in
 distance on an expanding 2D surface as
 
 @dispmath{ds^2=c^2dt^2-a^2(t)ds_s^2 = c^2dt^2-a^2(t)(d\chi^2+r^2d\phi^2).}
@@ -21993,8 +22015,8 @@ option which has the units along with a short 
description.
 
 @item -G
 @itemx --agenow
-The current age of the universe (given the input parameters) in Giga-years
-(Gyr).
+The current age of the universe (given the input parameters) in Ga (Giga
+annum, or billion years).
 
 @item -C
 @itemx --criticaldensitynow
@@ -22037,14 +22059,14 @@ the apparent magnitude to give the object's absolute 
magnitude.
 
 @item -g
 @itemx --age
-Age of the universe at given redshift in Giga-years (Gyr).
+Age of the universe at given redshift in Ga (Giga annum, or billion years).
 
 @item -b
 @itemx --lookbacktime
-The look-back time to given redshift in Giga-years (Gyr). The look-back
-time at a given redshift is defined as the current age of the universe
-(@option{--agenow}) subtracted by the age of the universe at the given
-redshift.
+The look-back time to given redshift in Ga (Giga annum, or billion
+years). The look-back time at a given redshift is defined as the current
+age of the universe (@option{--agenow}) subtracted by the age of the
+universe at the given redshift.
 
 @item -c
 @itemx --criticaldensity
@@ -28374,7 +28396,7 @@ above.
 @end deftypefun
 
 
-@deftypefun {gal_data_t *} gal_statistics_outlier_positive (gal_data_t 
@code{*input}, float @code{sigma}, float @code{sigclip_multip}, float 
@code{sigclip_param}, int @code{inplace}, int @code{quiet})
+@deftypefun {gal_data_t *} gal_statistics_outlier_positive (gal_data_t 
@code{*input}, size_t @code{window_size}, float @code{sigma}, float 
@code{sigclip_multip}, float @code{sigclip_param}, int @code{inplace}, int 
@code{quiet})
 Find the first positive outlier in the @code{input} distribution. The
 returned dataset contains a single element: the first positive outlier. It
 is one of the dataset's elements, in the same type as the input. If the
@@ -28382,23 +28404,22 @@ process fails for any reason (for example no outlier 
was found), a
 @code{NULL} pointer will be returned.
 
 All (possibly existing) blank elements are first removed from the input
-dataset, then it is sorted. A sliding window equal to half the width of the
-dataset elements is parsed over the dataset. Starting from the middle of
-the dataset (median) in the direction of increasing values. This window is
-used as a reference. The first element where the distance to the previous
+dataset, then it is sorted. A sliding window of @code{window_size} elements
+is parsed over the dataset. Starting from the @code{window_size}-th element
+of the dataset, in the direction of increasing values. This window is used
+as a reference. The first element where the distance to the previous
 (sorted) element is @code{sigma} units away from the distribution of
 distances in its window is considered an outlier and returned by this
 function.
 
 Formally, if we assume there are @mymath{N} non-blank elements. They are
-first sorted. Searching for the outlier starts on element @mymath{N/2}
-(integer division). Let's take @mymath{v_i} to be the @mymath{i}-th element
-of the sorted input (with no blank values) and @mymath{m} and
-@mymath{\sigma} as the @mymath{\sigma}-clipped median and standard
-deviation from the distances of the previous @mymath{N/2} elements (not
-including @mymath{v_i}). If the value given to @code{sigma} is displayed
-with @mymath{s}, the @mymath{i}-th element is considered as an outlier when
-the condition below is true.
+first sorted. Searching for the outlier starts on element @mymath{W}. Let's
+take @mymath{v_i} to be the @mymath{i}-th element of the sorted input (with
+no blank values) and @mymath{m} and @mymath{\sigma} as the
+@mymath{\sigma}-clipped median and standard deviation from the distances of
+the previous @mymath{W} elements (not including @mymath{v_i}). If the value
+given to @code{sigma} is displayed with @mymath{s}, the @mymath{i}-th
+element is considered as an outlier when the condition below is true.
 
 @dispmath{{(v_i-v_{i-1})-m\over \sigma}>s}
 
@@ -28414,10 +28435,13 @@ done within the input dataset's allocated space. 
Otherwise, this function
 will internally allocate (and later free) the necessary space to keep the
 intermediate space that this process requires.
 
-If @code{quiet!=0}, this function will report a warning when the moving
-window size is not much smaller than the number of non-blank elements. In
-such cases, the outlier estimation may be wrong: the outlier point may lie
-before the first checked element.
+If @code{quiet!=0}, this function will report the parameters every time it
+moves the window as a separate line with several columns. The first column
+is the value, the second (in square brackets) is the sorted index, the
+third is the distance of this element from the previous one. The Fourth and
+fifth (in parenthesis) are the median and standard deviation of the
+sigma-clipped distribution within the window and the last column is the
+difference between the third and fourth, divided by the fifth.
 
 @end deftypefun
 
diff --git a/doc/release-checklist.txt b/doc/release-checklist.txt
index 1ffa2de..f08dc05 100644
--- a/doc/release-checklist.txt
+++ b/doc/release-checklist.txt
@@ -41,10 +41,10 @@ all the commits needed for this release have been completed.
  - Check if README includes all the recent updates and important features.
 
 
- - Check if THANKS and the book's Acknowledgments section have everyone in
-   `doc/announce-acknowledge.txt' in them. To see who has been added in the
-   `THANKS' file since the last stable release (to add in the book), you
-   can use this command:
+ - [STABLE] Check if THANKS, and the book's Acknowledgments section have
+   everyone in `doc/announce-acknowledge.txt' in them. To see who has been
+   added in the `THANKS' file since the last stable release (to add in the
+   book), you can use this command:
 
      $ git diff gnuastro_vP.P..HEAD THANKS
 
@@ -100,7 +100,7 @@ all the commits needed for this release have been completed.
 
    - Set the key-ID as a variable for easy steps later:
 
-       $ mykeyid=1849814357EFB73A
+       $ mykeyid=XXXXXXXXXXXXXXXXX
 
    - For an alpha upload:
 
diff --git a/lib/fits.c b/lib/fits.c
index 9e6f77e..5f724c0 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -1781,6 +1781,8 @@ gal_fits_img_read_kernel(char *filename, char *hdu, 
size_t minmapsize)
       else          sum+=*f;
     }
   while(++f<fp);
+  kernel->flag |= GAL_DATA_FLAG_BLANK_CH;
+  kernel->flag &= ~GAL_DATA_FLAG_HASBLANK;
   f=kernel->array; do *f++ *= 1/sum; while(f<fp);
 
   /* Flip the kernel about the center (necessary for non-symmetric
diff --git a/lib/gnuastro-internal/config.h.in 
b/lib/gnuastro-internal/config.h.in
index 67c1383..1964fb3 100644
--- a/lib/gnuastro-internal/config.h.in
+++ b/lib/gnuastro-internal/config.h.in
@@ -43,17 +43,6 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #define GAL_CONFIG_HAVE_PTHREAD_BARRIER     @HAVE_PTHREAD_BARRIER@
 
-#define GAL_CONFIG_BIN_OP_UINT8             @HAVE_BIN_OP_UINT8@
-#define GAL_CONFIG_BIN_OP_INT8              @HAVE_BIN_OP_INT8@
-#define GAL_CONFIG_BIN_OP_UINT16            @HAVE_BIN_OP_UINT16@
-#define GAL_CONFIG_BIN_OP_INT16             @HAVE_BIN_OP_INT16@
-#define GAL_CONFIG_BIN_OP_UINT32            @HAVE_BIN_OP_UINT32@
-#define GAL_CONFIG_BIN_OP_INT32             @HAVE_BIN_OP_INT32@
-#define GAL_CONFIG_BIN_OP_UINT64            @HAVE_BIN_OP_UINT64@
-#define GAL_CONFIG_BIN_OP_INT64             @HAVE_BIN_OP_INT64@
-#define GAL_CONFIG_BIN_OP_FLOAT32           @HAVE_BIN_OP_FLOAT32@
-#define GAL_CONFIG_BIN_OP_FLOAT64           @HAVE_BIN_OP_FLOAT64@
-
 #define GAL_CONFIG_SIZEOF_LONG              @SIZEOF_LONG@
 #define GAL_CONFIG_SIZEOF_SIZE_T            @SIZEOF_SIZE_T@
 
diff --git a/lib/gnuastro-internal/options.h b/lib/gnuastro-internal/options.h
index 3f6ea09..5c524be 100644
--- a/lib/gnuastro-internal/options.h
+++ b/lib/gnuastro-internal/options.h
@@ -305,10 +305,10 @@ error_t
 gal_options_common_argp_parse(int key, char *arg, struct argp_state *state);
 
 char *
-gal_options_stdin_error(long stdintimeout, int precedence);
+gal_options_stdin_error(long stdintimeout, int precedence, char *name);
 
 gal_list_str_t *
-gal_options_check_stdin(char *inputname, long stdintimeout);
+gal_options_check_stdin(char *inputname, long stdintimeout, char *name);
 
 
 
diff --git a/lib/gnuastro/statistics.h b/lib/gnuastro/statistics.h
index 2b84756..ec3ecd2 100644
--- a/lib/gnuastro/statistics.h
+++ b/lib/gnuastro/statistics.h
@@ -174,9 +174,9 @@ gal_statistics_sigma_clip(gal_data_t *input, float multip, 
float param,
                           int inplace, int quiet);
 
 gal_data_t *
-gal_statistics_outlier_positive(gal_data_t *input, float sigma,
-                                float sigclip_multip, float sigclip_param,
-                                int inplace, int quiet);
+gal_statistics_outlier_positive(gal_data_t *input, size_t window_size,
+                                float sigma, float sigclip_multip,
+                                float sigclip_param, int inplace, int quiet);
 
 
 
diff --git a/lib/options.c b/lib/options.c
index a0f768f..4e70df9 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -1363,20 +1363,19 @@ gal_options_common_argp_parse(int key, char *arg, 
struct argp_state *state)
 
 
 char *
-gal_options_stdin_error(long stdintimeout, int precedence)
+gal_options_stdin_error(long stdintimeout, int precedence, char *name)
 {
   char *out;
 
-  if( asprintf(&out, "no input!\n\n"
-               "The (first) input dataset can be read from a file "
-               "(specified as an argument), or the standard input.%s "
-               "Standard input can come from a pipe (output of another "
-               "program) or typed on the command-line before %ld "
-               "micro-seconds (configurable with the `--stdintimeout' "
-               "option).", ( precedence
-                             ? "If both are provided, a file takes precedence"
-                             : " " ),
-               stdintimeout )<0 )
+  if( asprintf(&out, "no %s!\n\n"
+               "The %s can be read from a file (specified as an argument), "
+               "or the standard input.%s Standard input can come from a "
+               "pipe (output of another program) or typed on the "
+               "command-line before %ld micro-seconds (configurable with "
+               "the `--stdintimeout' option).", name, name,
+               ( precedence
+                 ? " If both are provided, a file takes precedence."
+                 : "" ), stdintimeout )<0 )
     error(EXIT_FAILURE, 0, "%s: `asprintf' allocation error", __func__);
 
   return out;
@@ -1389,13 +1388,14 @@ gal_options_stdin_error(long stdintimeout, int 
precedence)
 /* Make the notice that is printed before program terminates, when no input
    is given and Standard input is also available. */
 gal_list_str_t *
-gal_options_check_stdin(char *inputname, long stdintimeout)
+gal_options_check_stdin(char *inputname, long stdintimeout, char *name)
 {
   gal_list_str_t *lines=inputname ? NULL : gal_txt_stdin_read(stdintimeout);
 
   /* See if atleast one of the two inputs is given. */
   if(inputname==NULL && lines==NULL)
-    error( EXIT_FAILURE, 0,  gal_options_stdin_error(stdintimeout,1));
+    error( EXIT_FAILURE, 0, "%s", gal_options_stdin_error(stdintimeout,
+                                                          1, name));
 
   /* Return the output. */
   return lines;
diff --git a/lib/statistics.c b/lib/statistics.c
index 11a04d1..dbe0326 100644
--- a/lib/statistics.c
+++ b/lib/statistics.c
@@ -2097,7 +2097,7 @@ gal_statistics_sigma_clip(gal_data_t *input, float 
multip, float param,
 /* Find the first outlier in a distribution. */
 #define OUTLIER_BYTYPE(IT) {                                            \
     IT *arr=nbs->array;                                                 \
-    for(i=nbs->size/2;i<nbs->size;++i)                                  \
+    for(i=window_size;i<nbs->size;++i)                                  \
       {                                                                 \
         /* Fill in the distance array. */                               \
         for(j=0; j<wtakeone; ++j)                                       \
@@ -2109,9 +2109,10 @@ gal_statistics_sigma_clip(gal_data_t *input, float 
multip, float param,
         sarr=sclip->array;                                              \
                                                                         \
         /* For a check */                                               \
-        /*printf("%f: %f (%f, %f) %f\n", (float)(arr[i]),          */   \
-        /*       (float)(arr[i]-arr[i-1]), sarr[1], sarr[3],       */   \
-        /*       (((double)(arr[i]-arr[i-1])) - sarr[1])/sarr[3]); */  \
+        if(quiet==0)                                                    \
+          printf("%f [%zu]: %f (%f, %f) %f\n", (float)(arr[i]), i,      \
+                 (float)(arr[i]-arr[i-1]), sarr[1], sarr[3],            \
+                 (((double)(arr[i]-arr[i-1])) - sarr[1])/sarr[3]);      \
                                                                         \
         /* Terminate the loop if the dist. is larger than requested. */ \
         /* This shows we have reached the first outlier's position. */  \
@@ -2132,18 +2133,17 @@ gal_statistics_sigma_clip(gal_data_t *input, float 
multip, float param,
       }                                                                 \
   }
 gal_data_t *
-gal_statistics_outlier_positive(gal_data_t *input, float sigma,
-                                float sigclip_multip, float sigclip_param,
-                                int inplace, int quiet)
+gal_statistics_outlier_positive(gal_data_t *input, size_t window_size,
+                                float sigma, float sigclip_multip,
+                                float sigclip_param, int inplace, int quiet)
 {
   float *sarr;
   double *darr;
-  size_t i, j, one=1, wtakeone, window_size;
+  size_t i, j, one=1, wtakeone;
   gal_data_t *dist, *sclip, *nbs, *out=NULL;
 
   /* Remove all blanks and sort the dataset. */
   nbs=gal_statistics_no_blank_sorted(input, inplace);
-  window_size=nbs->size/2;
 
   /* Only continue if the window size is more than 2 elements (out
      "outlier" is hard to define on smaller datasets). */
diff --git a/lib/tile-internal.c b/lib/tile-internal.c
index 114b02d..7e51fe2 100644
--- a/lib/tile-internal.c
+++ b/lib/tile-internal.c
@@ -44,7 +44,7 @@ tileinternal_no_outlier_work(gal_data_t *first, gal_data_t 
*second,
                              size_t tottilesinch, double *outliersclip,
                              float outliersigma)
 {
-  gal_data_t *outlier;
+  gal_data_t *outlier, *nbs;
   size_t i, osize=first->size;
   size_t start=tottilesinch*channelid;
   float *oa1=NULL, *oa2=NULL, *oa3=NULL;
@@ -82,9 +82,11 @@ tileinternal_no_outlier_work(gal_data_t *first, gal_data_t 
*second,
   /* Find the quantile and remove all tiles that are more than it in the
      first array. */
   arr1=first->array;
-  outlier=gal_statistics_outlier_positive(first, outliersigma,
+  nbs=gal_statistics_no_blank_sorted(first, 0);
+  outlier=gal_statistics_outlier_positive(nbs, nbs->size/2, outliersigma,
                                           outliersclip[0], outliersclip[1],
                                           0, 1);
+  gal_data_free(nbs);
   if(outlier)
     {
       o = *((float *)(outlier->array));
@@ -101,9 +103,11 @@ tileinternal_no_outlier_work(gal_data_t *first, gal_data_t 
*second,
      on each dataset to later remove any tile that is blank in atleast one
      of them. */
   arr2=second->array;
-  outlier=gal_statistics_outlier_positive(second, outliersigma,
+  nbs=gal_statistics_no_blank_sorted(second, 0);
+  outlier=gal_statistics_outlier_positive(nbs, nbs->size, outliersigma,
                                           outliersclip[0], outliersclip[1],
                                           0, 0);
+  gal_data_free(nbs);
   if(outlier)
     {
       o = *((float *)(outlier->array));
@@ -116,9 +120,12 @@ tileinternal_no_outlier_work(gal_data_t *first, gal_data_t 
*second,
   if(third)
     {
       arr3=third->array;
-      outlier=gal_statistics_outlier_positive(third, outliersigma,
+      nbs=gal_statistics_no_blank_sorted(third, 0);
+      outlier=gal_statistics_outlier_positive(nbs, nbs->size/2,
+                                              outliersigma,
                                               outliersclip[0],
                                               outliersclip[1], 0, 0);
+      gal_data_free(nbs);
       if(outlier)
         {
           o = *((float *)(outlier->array));
diff --git a/tests/statistics/stdin-input.txt b/tests/statistics/stdin-input.txt
new file mode 100644
index 0000000..9b92619
--- /dev/null
+++ b/tests/statistics/stdin-input.txt
@@ -0,0 +1,9 @@
+5.3932774677668
+4.7389534611694
+4.6367278925857
+4.9336122599431
+4.5610196897253
+4.4582019512818
+4.4601551641468
+5.4839550970881
+5.5289562129159



reply via email to

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