gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master d7e0037 047/113: Brought in recent work in mas


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master d7e0037 047/113: Brought in recent work in master
Date: Fri, 16 Apr 2021 10:33:42 -0400 (EDT)

branch: master
commit d7e0037fda20777da245dc1bd079b17f2bc28f13
Merge: 737a0cd cfdde16
Author: Mohammad Akhlaghi <akhlaghi@gnu.org>
Commit: Mohammad Akhlaghi <akhlaghi@gnu.org>

    Brought in recent work in master
    
    Recent work in master is now merged into this branch.
---
 NEWS                        |   4 +
 bin/crop/ui.c               |   2 +-
 bin/match/args.h            |  30 ++++++-
 bin/match/main.h            |   4 +
 bin/match/match.c           | 149 ++++++++++++++++++++++++++++++----
 bin/match/ui.c              | 191 +++++++++++++++++++++++++++++++++-----------
 bin/match/ui.h              |  10 ++-
 bin/mkprof/ui.c             |   4 +-
 bin/statistics/ui.c         |   2 +-
 bin/table/ui.c              |   2 +-
 doc/gnuastro.texi           | 177 ++++++++++++++++++++++++++--------------
 lib/gnuastro/table.h        |   3 +-
 lib/match.c                 |  69 +++++++++-------
 lib/table.c                 |  13 ++-
 tests/Makefile.am           |   3 +-
 tests/match/merged-cols.sh  |  53 ++++++++++++
 tests/match/positions-1.txt |   3 +
 tests/match/positions-2.txt |   3 +
 18 files changed, 552 insertions(+), 170 deletions(-)

diff --git a/NEWS b/NEWS
index 5429b65..e674196 100644
--- a/NEWS
+++ b/NEWS
@@ -92,6 +92,10 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
   the library (declared in `gnuastro/cosmology.h'). These functions are
   also used in the CosmicCalculator program.
 
+  `gal_table_read' can now return the number of columns matched with each
+  input column (for example with regular expressions), a new argument has
+  been added to allow this feature.
+
   `gal_fits_key_img_blank': returns the value that must be used in the
   BLANK keyword for the given type as defined by the FITS standard.
 
diff --git a/bin/crop/ui.c b/bin/crop/ui.c
index 3fda416..0eb083c 100644
--- a/bin/crop/ui.c
+++ b/bin/crop/ui.c
@@ -599,7 +599,7 @@ ui_read_cols(struct cropparams *p)
 
   /* Read the desired columns from the file. */
   cols=gal_table_read(p->catname, p->cathdu, colstrs, p->cp.searchin,
-                      p->cp.ignorecase, p->cp.minmapsize);
+                      p->cp.ignorecase, p->cp.minmapsize, NULL);
 
 
   /* Set the number of objects (rows in each column). */
diff --git a/bin/match/args.h b/bin/match/args.h
index f2b46a1..71f426b 100644
--- a/bin/match/args.h
+++ b/bin/match/args.h
@@ -34,7 +34,7 @@ struct argp_option program_options[] =
     /* Input file parameters. */
     {
       "hdu2",
-      GAL_OPTIONS_KEY_HDU,
+      UI_KEY_HDU2,
       "STR/INT",
       0,
       "Extension name or number of second input.",
@@ -63,6 +63,33 @@ struct argp_option program_options[] =
       GAL_OPTIONS_NOT_MANDATORY,
       GAL_OPTIONS_NOT_SET
     },
+    {
+      "notmatched",
+      UI_KEY_NOTMATCHED,
+      0,
+      0,
+      "Output is rows that don't match.",
+      GAL_OPTIONS_GROUP_OUTPUT,
+      &p->notmatched,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+    {
+      "outcols",
+      UI_KEY_OUTCOLS,
+      "STR",
+      0,
+      "Out cols in CSV, `a': first, `b': second input.",
+      GAL_OPTIONS_GROUP_OUTPUT,
+      &p->outcols,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET,
+      gal_options_parse_csv_strings
+    },
 
 
 
@@ -117,6 +144,7 @@ struct argp_option program_options[] =
     },
 
 
+
     {0}
   };
 
diff --git a/bin/match/main.h b/bin/match/main.h
index 6d065f7..3bd8a34 100644
--- a/bin/match/main.h
+++ b/bin/match/main.h
@@ -55,13 +55,17 @@ struct matchparams
   char                  *hdu2;  /* Second input's HDU.                  */
   gal_data_t           *ccol1;  /* Array of firs input column names.    */
   gal_data_t           *ccol2;  /* Array of second input column names.  */
+  gal_data_t         *outcols;  /* Array of second input column names.  */
   gal_data_t        *aperture;  /* Acceptable matching aperture.        */
   uint8_t         logasoutput;  /* Don't rearrange inputs, out is log.  */
+  uint8_t          notmatched;  /* Output is rows that don't match.     */
 
   /* Internal */
   int                    mode;  /* Mode of operation: image or catalog. */
   gal_data_t           *cols1;  /* Column values of first input.        */
   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.    */
   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 403c625..c963479 100644
--- a/bin/match/match.c
+++ b/bin/match/match.c
@@ -42,16 +42,33 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 /* Read the catalog in the given file and use the given permutation to keep
    the proper columns. */
-static void
-match_catalog_write(struct matchparams *p, char *filename, char *hdu,
-                    size_t *permutation, size_t nummatched, char *outname,
-                    char *extname)
+static gal_data_t *
+match_catalog_read_write_all(struct matchparams *p, size_t *permutation,
+                             size_t nummatched, int f1s2,
+                             size_t **numcolmatch)
 {
+  size_t origsize;
   gal_data_t *tmp, *cat;
+  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;
+
+  /* When the output contains columns from both inputs, we need to keep the
+     number of columns matched against each column identifier. */
+  if(p->outcols)
+    *numcolmatch=gal_data_malloc_array(GAL_TYPE_SIZE_T,
+                                       gal_list_str_number(cols), __func__,
+                                       "numcolmatch");
 
   /* Read the full table. */
-  cat=gal_table_read(filename, hdu, NULL,p->cp.searchin, p->cp.ignorecase,
-                     p->cp.minmapsize);
+  cat=gal_table_read(filename, hdu, cols, p->cp.searchin, p->cp.ignorecase,
+                     p->cp.minmapsize, *numcolmatch);
+  origsize=cat->size;
+
 
   /* Go over each column and permute its contents. */
   for(tmp=cat; tmp!=NULL; tmp=tmp->next)
@@ -62,14 +79,97 @@ match_catalog_write(struct matchparams *p, char *filename, 
char *hdu,
       /* Correct the size of the array so only the matching columns are
          saved as output. This is only Gnuastro's convention, it has no
          effect on later freeing of the array in the memory. */
-      tmp->size=tmp->dsize[0]=nummatched;
+      if(p->notmatched)
+        {
+          /* Add the original array pointer to a list (we need to reset it
+             later). */
+          gal_list_void_add(&arrays, tmp->array);
+
+          /* Reset the data structure's array element to start where the
+             non-matched elements start. */
+          tmp->array=gal_data_ptr_increment(tmp->array, nummatched,
+                                            tmp->type);
+
+          /* Correct the size of the tile. */
+          tmp->size = tmp->dsize[0] = tmp->size - nummatched;
+        }
+      else
+        tmp->size=tmp->dsize[0]=nummatched;
     }
 
+
   /* Write the catalog to the output. */
-  gal_table_write(cat, NULL, p->cp.tableformat, outname, extname);
+  if(p->outcols)
+    return cat;
+  else
+    {
+      /* Write the catalog to a file. */
+      gal_table_write(cat, NULL, p->cp.tableformat, outname, extname);
+
+      /* Correct arrays and sizes (when `notmatched' was called). The
+         `array' element has to be corrected for later freeing.
 
-  /* Clean up. */
-  gal_list_data_free(cat);
+         IMPORTANT: `--notmatched' cannot be called with `--outcols'. So
+         you don't have to worry about the checks here being done later. */
+      if(p->notmatched)
+        {
+          /* Reverse the list of array pointers to write them back in. */
+          gal_list_void_reverse(&arrays);
+
+          /* Correct the array and size pointers. */
+          for(tmp=cat; tmp!=NULL; tmp=tmp->next)
+            {
+              tmp->array=gal_list_void_pop(&arrays);
+              tmp->size=tmp->dsize[0]=origsize;
+              tmp->block=NULL;
+            }
+        }
+
+      /* Clean up. */
+      gal_list_data_free(cat);
+      return NULL;
+    }
+}
+
+
+
+
+
+/* When specific columns from both inputs are requested, this function
+   will write them out into a single table. */
+static void
+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;
+  char **strarr=p->outcols->array;
+
+  /* Go over the initial list of strings. */
+  for(i=0; i<p->outcols->size; ++i)
+    switch(strarr[i][0])
+      {
+      case 'a':
+        for(j=0;j<acolmatch[ac];++j)
+          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));
+        bc++;
+        break;
+
+      default:
+        error(EXIT_FAILURE, 0, "a bug! Please contact us at %s to fix the "
+              "problem. the value to strarr[%zu][0] (%c) is not recognized",
+              PACKAGE_BUGREPORT, i, strarr[i][0]);
+      }
+
+  /* Reverse the table and write it out. */
+  gal_list_data_reverse(&cat);
+  gal_table_write(cat, NULL, p->cp.tableformat, p->cp.output, "MATCHED");
 }
 
 
@@ -80,8 +180,9 @@ static void
 match_catalog(struct matchparams *p)
 {
   uint32_t *u, *uf;
-  size_t nummatched;
   gal_data_t *tmp, *mcols;
+  gal_data_t *a=NULL, *b=NULL;
+  size_t nummatched, *acolmatch, *bcolmatch;
 
   /* Find the matching coordinates. We are doing the processing in
      place, */
@@ -94,10 +195,28 @@ match_catalog(struct matchparams *p)
       /* Read all the first catalog columns. */
       if(p->logasoutput==0)
         {
-          match_catalog_write(p, p->input1name, p->cp.hdu, mcols->array,
-                              nummatched, p->out1name, "INPUT_1");
-          match_catalog_write(p, p->input2name, p->hdu2, mcols->next->array,
-                              nummatched, p->out2name, "INPUT_2");
+          /* Read (and possibly write) the outputs. Note that we only need
+             to read the table when it is necessary for the output (the
+             user user might have asked for `--outcols', only with columns
+             of one of the two inputs. */
+          if(p->outcols==NULL || p->acols)
+            a=match_catalog_read_write_all(p, mcols->array, nummatched,
+                                           1, &acolmatch);
+          if(p->outcols==NULL || p->bcols)
+            b=match_catalog_read_write_all(p, mcols->next->array, nummatched,
+                                           2, &bcolmatch);
+
+          /* If one catalog (with specific columns from either of the two
+             inputs) was requested, then write it out. */
+          if(p->outcols)
+            {
+              /* Arrange the columns and write the output. */
+              match_catalog_write_one(p, a, b, acolmatch, bcolmatch);
+
+              /* Clean up. */
+              if(acolmatch) free(acolmatch);
+              if(bcolmatch) free(bcolmatch);
+            }
         }
 
       /* Write the raw information in a log file if necessary.  */
diff --git a/bin/match/ui.c b/bin/match/ui.c
index eebb680..edc8fd9 100644
--- a/bin/match/ui.c
+++ b/bin/match/ui.c
@@ -213,13 +213,17 @@ parse_opt(int key, char *arg, struct argp_state *state)
 static void
 ui_read_check_only_options(struct matchparams *p)
 {
-
+  if(p->outcols && p->notmatched)
+    error(EXIT_FAILURE, 0, "`--outcols' and `--notmatched' cannot be called "
+          "at the same time. The former is only for cases when the matches "
+          "are required");
 }
 
 
 
 
 
+
 static void
 ui_check_options_and_arguments(struct matchparams *p)
 {
@@ -516,6 +520,59 @@ ui_read_columns_aperture_3d(struct matchparams *p)
 
 
 
+/* We want to keep the columns as double type. So what-ever their original
+   type is, convert it. */
+static gal_data_t *
+ui_read_columns_to_double(struct matchparams *p, char *filename, char *hdu,
+                          gal_list_str_t *cols, size_t numcols)
+{
+  gal_data_t *tmp, *ttmp, *tout, *out=NULL;
+  struct gal_options_common_params *cp=&p->cp;
+  char *diff_cols_error="%s: the number of columns matched (%zu) "
+    "differs from the number of usable calls to `--ccol1' (%zu). "
+    "Please give more specific values to `--ccol1' (column "
+    "numberes are the only identifiers guaranteed to be unique).";
+
+  /* Read the columns. */
+  tout=gal_table_read(filename, hdu, cols, cp->searchin, cp->ignorecase,
+                      cp->minmapsize, NULL);
+
+  /* A small sanity check. */
+  if(gal_list_data_number(tout)!=numcols)
+    error(EXIT_FAILURE, 0, diff_cols_error,
+          gal_checkset_dataset_name(filename, hdu),
+          gal_list_data_number(tout), numcols);
+
+  /* Go over the columns and see if they are double or not. To keep things
+     simple, we'll keep a new list even if all the types are float64.*/
+  tmp=tout;
+  while(tmp!=NULL)
+    {
+      /* We need ot set the `next' pointer  */
+      ttmp=tmp->next;
+      tmp->next=NULL;
+
+      /* Correct the type if necessary. */
+      if(tmp->type==GAL_TYPE_FLOAT64)
+        gal_list_data_add(&out, tmp);
+      else
+        gal_list_data_add(&out,
+                          gal_data_copy_to_new_type_free(tmp,
+                                                         GAL_TYPE_FLOAT64) );
+
+      /* Set `tmp' to the initial `next pointer. */
+      tmp=ttmp;
+    }
+
+  /* The `out' above is in reverse, so correct it and return */
+  gal_list_data_reverse(&out);
+  return out;
+}
+
+
+
+
+
 /* Read catalog columns */
 static void
 ui_read_columns(struct matchparams *p)
@@ -524,12 +581,7 @@ ui_read_columns(struct matchparams *p)
   size_t ccol1n=p->ccol1->size;
   size_t ccol2n=p->ccol2->size;
   gal_list_str_t *cols1=NULL, *cols2=NULL;
-  struct gal_options_common_params *cp=&p->cp;
   char **strarr1=p->ccol1->array, **strarr2=p->ccol2->array;
-  char *diff_cols_error="%s: the number of columns matched (%zu) "
-    "differs from the number of usable calls to `--ccol1' (%zu). "
-    "Please give more specific values to `--ccol1' (column "
-    "numberes are the only identifiers guaranteed to be unique).";
 
   /* Make sure the same number of columns is given to both. */
   if(ccol1n!=ccol2n)
@@ -577,23 +629,13 @@ ui_read_columns(struct matchparams *p)
 
 
   /* Read the columns. */
-  if(cp->searchin)
+  if(p->cp.searchin)
     {
       /* Read the first dataset. */
-      p->cols1=gal_table_read(p->input1name, cp->hdu, cols1,
-                              cp->searchin, cp->ignorecase, cp->minmapsize);
-      if(gal_list_data_number(p->cols1)!=ccol1n)
-        error(EXIT_FAILURE, 0, diff_cols_error,
-              gal_checkset_dataset_name(p->input1name, cp->hdu),
-              gal_list_data_number(p->cols1), ccol1n);
-
-      /* Read the second dataset. */
-      p->cols2=gal_table_read(p->input2name, p->hdu2, cols2,
-                              cp->searchin, cp->ignorecase, cp->minmapsize);
-      if(gal_list_data_number(p->cols2)!=ccol2n)
-        error(EXIT_FAILURE, 0, diff_cols_error,
-              gal_checkset_dataset_name(p->input2name, p->hdu2),
-              gal_list_data_number(p->cols2), ccol2n);
+      p->cols1=ui_read_columns_to_double(p, p->input1name, p->cp.hdu,
+                                         cols1, ccol1n);
+      p->cols2=ui_read_columns_to_double(p, p->input2name, p->hdu2,
+                                         cols2, ccol2n);
     }
   else
     error(EXIT_FAILURE, 0, "no `--searchin' option specified. Please run "
@@ -613,6 +655,40 @@ ui_read_columns(struct matchparams *p)
 
 
 static void
+ui_preparations_out_cols(struct matchparams *p)
+{
+  size_t i;
+  char **strarr=p->outcols->array;
+
+  /* Go over all the values and put the respective column identifier in the
+     proper list. */
+  for(i=0;i<p->outcols->size;++i)
+    switch(strarr[i][0])
+      {
+      case 'a': gal_list_str_add(&p->acols, strarr[i]+1, 0); break;
+      case 'b': gal_list_str_add(&p->bcols, strarr[i]+1, 0); break;
+      default:
+        error(EXIT_FAILURE, 0, "`%s' is not a valid value for `--outcols'. "
+              "The first character of each value to this option must be "
+              "either `a' or `b'. The former specifies a column from the "
+              "first input and the latter a column from the second. The "
+              "characters after them can be any column identifier (number, "
+              "name, or regular expression). For more on column selection, "
+              "please run this command:\n\n"
+              "    $ info gnuastro \"Selecting table columns\"\n",
+              strarr[i]);
+      }
+
+  /* Revere the lists so they correspond to the input order. */
+  gal_list_str_reverse(&p->acols);
+  gal_list_str_reverse(&p->bcols);
+}
+
+
+
+
+
+static void
 ui_preparations_out_name(struct matchparams *p)
 {
   if(p->logasoutput)
@@ -635,42 +711,58 @@ ui_preparations_out_name(struct matchparams *p)
     }
   else
     {
-      /* Set `p->out1name' and `p->out2name'. */
-      if(p->cp.output)
+      if(p->outcols)
         {
-          if( gal_fits_name_is_fits(p->cp.output) )
-            {
-              gal_checkset_allocate_copy(p->cp.output, &p->out1name);
-              gal_checkset_allocate_copy(p->cp.output, &p->out2name);
-            }
-          else
-            {
-              p->out1name=gal_checkset_automatic_output(&p->cp, p->cp.output,
-                                                        "_matched_1.txt");
-              p->out2name=gal_checkset_automatic_output(&p->cp, p->cp.output,
-                                                        "_matched_2.txt");
-            }
+          if(p->cp.output==NULL)
+            p->cp.output = gal_checkset_automatic_output(&p->cp,
+                 p->input1name, ( p->cp.tableformat==GAL_TABLE_FORMAT_TXT
+                                  ? "_matched.txt" : "_matched.fits") );
+          gal_checkset_writable_remove(p->cp.output, 0, p->cp.dontdelete);
         }
       else
         {
-          if(p->cp.tableformat==GAL_TABLE_FORMAT_TXT)
+          /* Set `p->out1name' and `p->out2name'. */
+          if(p->cp.output)
             {
-              p->out1name=gal_checkset_automatic_output(&p->cp, p->input1name,
-                                                        "_matched_1.txt");
-              p->out2name=gal_checkset_automatic_output(&p->cp, p->input2name,
-                                                        "_matched_2.txt");
+              if( gal_fits_name_is_fits(p->cp.output) )
+                {
+                  gal_checkset_allocate_copy(p->cp.output, &p->out1name);
+                  gal_checkset_allocate_copy(p->cp.output, &p->out2name);
+                }
+              else
+                {
+                  p->out1name=gal_checkset_automatic_output(&p->cp,
+                                                            p->cp.output,
+                                                            "_matched_1.txt");
+                  p->out2name=gal_checkset_automatic_output(&p->cp,
+                                                            p->cp.output,
+                                                            "_matched_2.txt");
+                }
             }
           else
             {
-              p->out1name=gal_checkset_automatic_output(&p->cp, p->input1name,
-                                                        "_matched.fits");
-              gal_checkset_allocate_copy(p->out1name, &p->out2name);
+              if(p->cp.tableformat==GAL_TABLE_FORMAT_TXT)
+                {
+                  p->out1name=gal_checkset_automatic_output(&p->cp,
+                                                            p->input1name,
+                                                            "_matched_1.txt");
+                  p->out2name=gal_checkset_automatic_output(&p->cp,
+                                                            p->input2name,
+                                                            "_matched_2.txt");
+                }
+              else
+                {
+                  p->out1name=gal_checkset_automatic_output(&p->cp,
+                                                            p->input1name,
+                                                            "_matched.fits");
+                  gal_checkset_allocate_copy(p->out1name, &p->out2name);
+                }
             }
-        }
 
-      /* Make sure no file with these names exists. */
-      gal_checkset_writable_remove(p->out1name, 0, p->cp.dontdelete);
-      gal_checkset_writable_remove(p->out2name, 0, p->cp.dontdelete);
+          /* Make sure no file with these names exists. */
+          gal_checkset_writable_remove(p->out1name, 0, p->cp.dontdelete);
+          gal_checkset_writable_remove(p->out2name, 0, p->cp.dontdelete);
+        }
 
       /* If a log file is necessary, set its name here. */
       if(p->cp.log)
@@ -698,7 +790,10 @@ ui_preparations(struct matchparams *p)
     error(EXIT_FAILURE, 0, "currently Match only works on catalogs, we will "
           "implement the WCS matching routines later");
   else
-    ui_read_columns(p);
+    {
+      ui_read_columns(p);
+      if(p->outcols) ui_preparations_out_cols(p);
+    }
 
   /* Set the output filename. */
   ui_preparations_out_name(p);
diff --git a/bin/match/ui.h b/bin/match/ui.h
index d5d9d7e..e56730a 100644
--- a/bin/match/ui.h
+++ b/bin/match/ui.h
@@ -40,8 +40,8 @@ enum program_args_groups
 
 /* Available letters for short options:
 
-   b c d e f g i j k m n p r s t u v w x y z
-   A B C E G J L O Q R W X Y
+   b d e f g i j k m n p r s t u v w x y z
+   A B E G J L O Q R W X Y
 */
 enum option_keys_enum
 {
@@ -49,11 +49,13 @@ enum option_keys_enum
   UI_KEY_HDU2            = 'H',
   UI_KEY_APERTURE        = 'a',
   UI_KEY_LOGASOUTPUT     = 'l',
+  UI_KEY_CCOL1           = 'c',
+  UI_KEY_CCOL2           = 'C',
 
   /* Only with long version (start with a value 1000, the rest will be set
      automatically). */
-  UI_KEY_CCOL1           = 1000,
-  UI_KEY_CCOL2,
+  UI_KEY_NOTMATCHED      = 1000,
+  UI_KEY_OUTCOLS,
 };
 
 
diff --git a/bin/mkprof/ui.c b/bin/mkprof/ui.c
index a6b2dcd..07da299 100644
--- a/bin/mkprof/ui.c
+++ b/bin/mkprof/ui.c
@@ -668,7 +668,7 @@ ui_read_cols_2d(struct mkprofparams *p)
 
   /* Read the desired columns from the file. */
   cols=gal_table_read(p->catname, p->cp.hdu, colstrs, p->cp.searchin,
-                      p->cp.ignorecase, p->cp.minmapsize);
+                      p->cp.ignorecase, p->cp.minmapsize, NULL);
 
   /* Set the number of objects. */
   p->num=cols->size;
@@ -876,7 +876,7 @@ ui_read_cols_3d(struct mkprofparams *p)
 
   /* Read the desired columns from the file. */
   cols=gal_table_read(p->catname, p->cp.hdu, colstrs, p->cp.searchin,
-                      p->cp.ignorecase, p->cp.minmapsize);
+                      p->cp.ignorecase, p->cp.minmapsize, NULL);
 
   /* Set the number of objects. */
   p->num=cols->size;
diff --git a/bin/statistics/ui.c b/bin/statistics/ui.c
index 4626f54..4187afc 100644
--- a/bin/statistics/ui.c
+++ b/bin/statistics/ui.c
@@ -719,7 +719,7 @@ ui_read_columns(struct statisticsparams *p)
 
   /* Read the desired column(s). */
   cols=gal_table_read(p->inputname, p->cp.hdu, column, p->cp.searchin,
-                      p->cp.ignorecase, p->cp.minmapsize);
+                      p->cp.ignorecase, p->cp.minmapsize, NULL);
 
   /* Put the columns into the proper gal_data_t. */
   size=cols->size;
diff --git a/bin/table/ui.c b/bin/table/ui.c
index f60e708..860d4ad 100644
--- a/bin/table/ui.c
+++ b/bin/table/ui.c
@@ -319,7 +319,7 @@ ui_preparations(struct tableparams *p)
 
   /* Read in the table columns. */
   p->table=gal_table_read(p->filename, cp->hdu, p->columns, cp->searchin,
-                          cp->ignorecase, cp->minmapsize);
+                          cp->ignorecase, cp->minmapsize, NULL);
 
   /* If there was no actual data in the file, then inform the user and
      abort. */
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 05c50b1..868a993 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -2340,8 +2340,14 @@ analysis. Here, we will use Gnuastro's programs to 
detect objects in a
 Hubble Space Telescope (HST) image and measure their colors. We will use
 the @url{https://archive.stsci.edu/prepds/xdf, eXtreme Deep Field}
 dataset. Like almost all astronomical surveys, this dataset is free for
-download and usable by the public. You will need the following tools in
-this tutorial: Gnuastro, SAO DS9 @footnote{See @ref{SAO ds9}, available at
+download and usable by the public. This tutorial was first prepared for the
+``Exploring the Ultra-Low Surface Brightness Universe'' workshop (November
+2017) at the International Space Science Institute (ISSI) in Bern,
+Switzerland. We would like to thank them and the attendees for a very
+fruiteful week.
+
+You will need the following tools in this tutorial: Gnuastro, SAO DS9
+@footnote{See @ref{SAO ds9}, available at
 @url{http://ds9.si.edu/site/Home.html}.}, GNU
 Wget@footnote{@url{https://www.gnu.org/software/wget}.}, and AWK (most
 common implementation is GNU
@@ -15790,6 +15796,13 @@ $ astmatch --aperture=5e-10 --ccol1=5 --ccol2=10 
in1.fits in2.txt
 ##  The number of values to these determines the dimensionality).
 $ astmatch --aperture=2 input1.txt input2.fits
 
+## Similar to before, but the output is created by merging various
+## columns from the two inputs: columns 1, RA, DEC from the first
+## input, followed by all columns starting with MAG and the 8th
+## column from second input and finaly the 10th from first input.
+$ astmatch --aperture=2 input1.txt input2.fits                   \
+           --outcols=a1,aRA,aDEC,b/^MAG/,bBRG,a10
+
 ## Match the two catalogs within an elliptical aperture of 1 and 2
 ## arcseconds along RA and Dec respectively.
 $ astmatch --aperture=1/3600,2/3600 in1.fits in2.txt
@@ -15805,31 +15818,32 @@ $ astmatch --ccol1=2,3,4 --ccol2=2,3,4 
-a0.5/3600,0.5/3600,5e-10 \
 @end example
 
 Two inputs are necessary for Match to start processing. The inputs can be
-plain text tables or FITS tables, see @ref{Tables}. When @option{--quiet}
-is not called, Match will print the number of matches found in standard
-output (on the command-line). If no match was found, no output file will be
-created (table or log file). When matches are found, 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 the @option{--logasoutput} option is called, the output will
-be a single table with the contents of the log file, see below.
-
-Match follows the same basic behavior of all Gnuastro programs as fully
-described in @ref{Common program behavior}. If the first input is a FITS
-file, the common @option{--hdu} option (see @ref{Input output options})
-should be used to identify the extension. When the second input is FITS,
-the extension can be specified with @option{--hdu2}.
+plain text tables or FITS tables, see @ref{Tables}. Match follows the same
+basic behavior of all Gnuastro programs as fully described in @ref{Common
+program behavior}. If the first input is a FITS file, the common
+@option{--hdu} option (see @ref{Input output options}) should be used to
+identify the extension. When the second input is FITS, the extension must
+be specified with @option{--hdu2}.
+
+When @option{--quiet} is not called, Match will print the number of matches
+found in standard output (on the command-line). If no match was found, no
+output file will be created (table or log file). When matches are found, by
+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 output file name is given with the @option{--output} option, then
 automatic output @ref{Automatic output} will be used to determine the
-output names. Depending on @option{--tableformat} (see @ref{Input output
-options}), the output will then be a multi-extension FITS file or two plain
-text files.
-
-When @option{--output} is a FITS file (and @option{--logasoutput} is not
-called, see below), the re-arranged inputs will be two extensions of the
-output FITS file. If the output name is a text file, then two files will be
-created with a @file{_matched_1.txt} and @file{_matched_2.txt} suffix.
+output name(s). Depending on @option{--tableformat} (see @ref{Input output
+options}), the output will then be a (possibly multi-extension) FITS file
+or (possibly two) plain text file(s). When the output is a FITS file, the
+default re-arranged inputs will be two extensions of the output FITS
+file. With @option{--outcols} and @option{--logasoutput}, the FITS output
+will be a single table (in one extension).
 
 When the @option{--log} option is called (see @ref{Operating mode
 options}), Match will also create a file named @file{astmatch.fits} (or
@@ -15851,6 +15865,25 @@ The extension/HDU of the second input if it is a FITS 
file. When it isn't a
 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.
+
+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 outputtable. 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.
+
 @item -l
 @itemx --logasoutput
 The output file will have the contents of the log file: indexs in the two
@@ -15859,14 +15892,24 @@ description above. When this option is called, a log 
file called
 @file{astmatch.txt} will not be created. With this option, the default
 output behavior (two tables containing the re-arranged inputs) will be
 
-@item --ccol1=INT/STR[,INT/STR]
+@item --notmatched
+Write the non-matching rows into the outputs, not the matched ones. Note
+that with this option, the two output tables will not necessarily have the
+same number of rows. Therefore, this option cannot be called with
+@option{--outcols}. @option{--outcols} prints mixed columns from both
+inputs, so they must all have the same number of elements and must
+correspond to each other.
+
+@item -c INT/STR[,INT/STR]
+@itemx --ccol1=INT/STR[,INT/STR]
 The coordinate columns of the first input. The number of dimensions for the
 match is determined by the number of comma-separated values given to this
 option. The values can be the column number (counting from 1), exact column
 name or a regular expression. For more, see @ref{Selecting table
 columns}. See the one-line examples above for some usages of this option.
 
-@item --ccol2=INT/STR
+@item -C INT/STR[,INT/STR]
+@itemx --ccol2=INT/STR[,INT/STR]
 The coordinate columns of the second input. See the example in
 @option{--ccol1} for more.
 
@@ -21287,8 +21330,11 @@ linked list and thus any number of tiles can be 
represented with one
 variable.
 
 @deftypefun void gal_list_data_add (gal_data_t @code{**list}, gal_data_t 
@code{*newnode})
-Add an already allocated dataset (@code{newnode}) to top of @code{list}. In
-this example multiple images are linked together as a list:
+Add an already allocated dataset (@code{newnode}) to top of
+@code{list}. Note that if @code{newnode->next!=NULL} (@code{newnode} is
+itself a list), then @code{list} will be added to its end.
+
+In this example multiple images are linked together as a list:
 @example
 size_t minmapsize=-1;
 gal_data_t *tmp, *list=NULL;
@@ -22259,7 +22305,7 @@ $ asttable --info table.fits
 @end example
 @end deftypefun
 
-@deftypefun {gal_data_t *} gal_table_read (char @code{*filename}, char 
@code{*hdu}, gal_list_str_t @code{*cols}, int @code{searchin}, int 
@code{ignorecase}, int @code{minmapsize})
+@deftypefun {gal_data_t *} gal_table_read (char @code{*filename}, char 
@code{*hdu}, gal_list_str_t @code{*cols}, int @code{searchin}, int 
@code{ignorecase}, int @code{minmapsize}, size_t @code{colmatch})
 Read the specified columns in a text file (named @code{filename}) into a
 linked list of data structures. If the file is FITS, then @code{hdu} will
 also be used, otherwise, @code{hdu} is ignored.
@@ -22280,6 +22326,10 @@ example from regular expressions), in this case, the 
order of output
 columns that correspond to that one input, are in order of the table (which
 column was read first). So the first requested column is the first popped
 data structure and so on.
+
+if @code{colmatch!=NULL}, it is assumed to be an array that has atleast the
+same number of elements as nodes in the @code{cols} list. The number of
+columns that matched each input column will be sored in each element.
 @end deftypefun
 
 @cindex Git
@@ -24600,7 +24650,7 @@ main(void)
 
   /* Read the desired columns. */
   columns = gal_table_read(inname, hdu, column_ids,
-                           GAL_TABLE_SEARCH_NAME, 1, -1);
+                           GAL_TABLE_SEARCH_NAME, 1, -1, NULL);
 
   /* Go over the columns, we'll assume that you don't know their type
    * a-priori, so we'll check  */
@@ -24777,26 +24827,26 @@ complicated, the speed of Python scripts 
significantly decrease. So when
 the program doesn't change too often and is widely used in a large
 community, mostly on large data sets (like astronomical images), using
 Python will waste a lot of valuable research-hours. It is possible to wrap
-C or C++ functions with Python to fix the speed issue. But this adds to
-complexity, because the interested scientist will now have to master two
+C or C++ functions with Python to fix the speed issue. But this creates
+further complexity, because the interested scientist has to master two
 programming languages and their connection (which is not trivial).
 
 Like C++, Python is object oriented, so as explained above, it needs a high
-level of experience with that particular program to fully understand its
-inner workings. To make things worse, since it is mainly for fast and on
-the go programming@footnote{Note that Python is good for fast programming,
-not fast programs.}, it can undergo significant changes. One recent example
-is how Python 2.x and Python 3.x are not compatible. Lots of research teams
+level of experience with that particular program to reasonably understand
+its inner workings. To make things worse, since it is mainly for on-the-go
+programming@footnote{Note that Python is good for fast programming, not
+fast programs.}, it can undergo significant changes. One recent example is
+how Python 2.x and Python 3.x are not compatible. Lots of research teams
 that invested heavily in Python 2.x cannot benefit from Python 3.x or
 future versions any more. Some converters are available, but since they are
-automatic, lots of complications might arise in the conversion. Thus,
-re-writing all the changes would be the only truly reliable option. If a
-research project begins using Python 3.x today, there is no telling how
-compatible their investments will be when Python 4.x or 5.x will come
-out. This stems from the core principles of Python, which are very useful
-when you look in the `on the go' basis as described before and not future
-usage. Future-proof code (as long as current operating systems will be
-used) is written in C.
+automatic, lots of complications might arise in the conversion@footnote{For
+example see @url{https://arxiv.org/abs/1712.00461, Jenness (2017)} which
+describes how LSST is managing the transition.}. If a research project
+begins using Python 3.x today, there is no telling how compatible their
+investments will be when Python 4.x or 5.x will come out. This stems from
+the core principles of Python, which are very useful when you look in the
+`on the go' basis as described before and not future usage. Future-proof
+code (as long as current operating systems will be used) is written in C.
 
 The portability of C is best demonstrated by the fact that both C++ and
 Python are part of the C-family of programming languages which also include
@@ -24851,11 +24901,14 @@ anything particular to the GNU C library is used in 
the processing
 functions, it is explained in the comments in between the code.
 
 @cindex GNU Coreutils
-Similar to GNU Coreutils, all the Gnuastro programs provide very low level
-operations. This enables you to use shell scripting languages (for example
-GNU Bash) to operate on a large number of files or do very complex things
-through the creative combinations of these tools that the authors had never
-dreamed of. We have put a few simple examples in @ref{Tutorials}.
+All the Gnuastro programs provide very low level and modular operations
+(modeled on GNU Coreutils). Almost all the basic command-line programs like
+@command{ls}, @command{cp} or @command{rm} on GNU/Linux operting systems
+are part of GNU Coreutils. This enables you to use shell scripting
+languages (for example GNU Bash) to operate on a large number of files or
+do very complex things through the creative combinations of these tools
+that the authors had never dreamed of. We have put a few simple examples in
+@ref{Tutorials}.
 
 @cindex @LaTeX{}
 @cindex GNU Bash
@@ -24869,24 +24922,24 @@ check your results. If you want to include the plots 
in a document, you can
 use the PGFplots package within @LaTeX{}, no attempt is made to include
 such operations in Gnuastro. In short, Bash can act as a glue to connect
 the inputs and outputs of all these various Gnuastro programs (and other
-programs) in any fashion you please. Of course, Gnuastro's programs are just
+programs) in any fashion. Of course, Gnuastro's programs are just
 front-ends to the main workhorse (@ref{Gnuastro library}), allowing a user
 to create their own programs (for example with @ref{BuildProgram}). So once
 the functions within programs become mature enough, they will be moved
-within the libraries for more general applications.
+within the libraries for even more general applications.
 
 The advantage of this architecture is that the programs become small and
 transparent: the starting and finishing point of every program is clearly
-demarcated. For nearly all operations on a modern computer, the read/write
-speed is very insignificant compared to the actual processing a program
-does. Therefore the complexity which arises from sharing memory in a large
-application is simply not worth the speed gain. Gnuastro's design is
-heavily influenced from Eric Raymond's ``The Art of Unix
-Programming''@footnote{Eric S. Raymond, 2004, @emph{The Art of Unix
-Programming}, Addison-Wesley Professional Computing Series.}  which
-beautifully describes the design philosophy and practice which lead to the
-success of Unix-based operating systems@footnote{KISS principle: Keep It
-Simple, Stupid!}.
+demarcated. For nearly all operations on a modern computer (fast file
+input-output) with a modest level of complexity, the read/write speed is
+insignificant compared to the actual processing a program does. Therefore
+the complexity which arises from sharing memory in a large application is
+simply not worth the speed gain. Gnuastro's design is heavily influenced
+from Eric Raymond's ``The Art of Unix Programming''@footnote{Eric
+S. Raymond, 2004, @emph{The Art of Unix Programming}, Addison-Wesley
+Professional Computing Series.}  which beautifully describes the design
+philosophy and practice which lead to the success of Unix-based operating
+systems@footnote{KISS principle: Keep It Simple, Stupid!}.
 
 
 
diff --git a/lib/gnuastro/table.h b/lib/gnuastro/table.h
index c080d4f..aea96c9 100644
--- a/lib/gnuastro/table.h
+++ b/lib/gnuastro/table.h
@@ -138,7 +138,8 @@ gal_table_print_info(gal_data_t *allcols, size_t numcols, 
size_t numrows);
 /************************************************************************/
 gal_data_t *
 gal_table_read(char *filename, char *hdu, gal_list_str_t *cols,
-               int searchin, int ignorecase, int minmapsize);
+               int searchin, int ignorecase, int minmapsize,
+               size_t *colmatch);
 
 
 
diff --git a/lib/match.c b/lib/match.c
index d64373c..98da33a 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -115,16 +115,23 @@ match_coordinate_pop_from_sfll(struct 
match_coordinate_sfll **list,
 /* Since these checks are repetative, its easier to have a separate
    function for both inputs. */
 static void
-match_coordinate_sanity_check_columns(gal_data_t *coord, char *info)
+match_coordinate_sanity_check_columns(gal_data_t *coord, char *info,
+                                      int inplace, int *allf64)
 {
   gal_data_t *tmp;
 
   for(tmp=coord; tmp!=NULL; tmp=tmp->next)
     {
       if(tmp->type!=GAL_TYPE_FLOAT64)
-        error(EXIT_FAILURE, 0, "%s: the input coordinates must have "
-              "`float64' type. At least one node of the %s list has type "
-              "of `%s'", __func__, info, gal_type_name(tmp->type, 1));
+        {
+          if(inplace)
+            error(EXIT_FAILURE, 0, "%s: when `inplace' is activated, the "
+                  "input coordinates must have `float64' type. At least "
+                  "one node of the %s list has type of `%s'", __func__, info,
+                  gal_type_name(tmp->type, 1));
+          else
+            *allf64=0;
+        }
 
       if(tmp->ndim!=1)
         error(EXIT_FAILURE, 0, "%s: each input coordinate column must have "
@@ -146,7 +153,7 @@ match_coordinate_sanity_check_columns(gal_data_t *coord, 
char *info)
 /* To keep the main function clean, we'll do the sanity checks here. */
 static void
 match_coordinaes_sanity_check(gal_data_t *coord1, gal_data_t *coord2,
-                              double *aperture)
+                              double *aperture, int inplace, int *allf64)
 {
   size_t ncoord1=gal_list_data_number(coord1);
 
@@ -165,8 +172,8 @@ match_coordinaes_sanity_check(gal_data_t *coord1, 
gal_data_t *coord2,
           "dimensions", __func__, ncoord1);
 
   /* Check the column properties. */
-  match_coordinate_sanity_check_columns(coord1, "first");
-  match_coordinate_sanity_check_columns(coord2, "second");
+  match_coordinate_sanity_check_columns(coord1, "first", inplace, allf64);
+  match_coordinate_sanity_check_columns(coord2, "second", inplace, allf64);
 
   /* Check the aperture values. */
   if(aperture[0]<=0)
@@ -232,7 +239,7 @@ match_coordinates_prepare_sort(gal_data_t *coords, size_t 
minmapsize)
 /* Do the preparations for matching of coordinates. */
 static void
 match_coordinates_prepare(gal_data_t *coord1, gal_data_t *coord2,
-                          int sorted_by_first, int inplace,
+                          int sorted_by_first, int inplace, int allf64,
                           gal_data_t **A_out, gal_data_t **B_out,
                           size_t **A_perm, size_t **B_perm,
                           size_t minmapsize)
@@ -241,10 +248,21 @@ match_coordinates_prepare(gal_data_t *coord1, gal_data_t 
*coord2,
 
   /* Sort the datasets if they aren't sorted. If the dataset is already
      sorted, then `inplace' is irrelevant. */
-  if(!sorted_by_first)
+  if(sorted_by_first && allf64)
+    {
+      *A_out=coord1;
+      *B_out=coord2;
+    }
+  else
     {
-      /* Allocating a new list is only necessary when  */
-      if(!inplace)
+      /* Allocating a new list is only necessary when `inplace==0' or all
+         the columns are double. */
+      if( inplace && allf64 )
+        {
+          *A_out=coord1;
+          *B_out=coord2;
+        }
+      else
         {
           /* Copy the first list. */
           for(tmp=coord1; tmp!=NULL; tmp=tmp->next)
@@ -270,21 +288,11 @@ match_coordinates_prepare(gal_data_t *coord1, gal_data_t 
*coord2,
           *A_out=A;
           *B_out=B;
         }
-      else
-        {
-          *A_out=coord1;
-          *B_out=coord2;
-        }
 
       /* Sort each dataset by the first coordinate. */
       *A_perm = match_coordinates_prepare_sort(*A_out, minmapsize);
       *B_perm = match_coordinates_prepare_sort(*B_out, minmapsize);
     }
-  else
-    {
-      *A_out=coord1;
-      *B_out=coord2;
-    }
 }
 
 
@@ -780,17 +788,18 @@ gal_match_coordinates_output(gal_data_t *A, gal_data_t 
*B, size_t *A_perm,
           /* Note that the permutation keeps the original indexs. */
           match_coordinate_pop_from_sfll(&bina[ai], &bi, &r);
           rval[ match_i   ] = r;
-          aind[ match_i   ] = A_perm[ai];
-          bind[ match_i++ ] = B_perm[bi];
+          aind[ match_i   ] = A_perm ? A_perm[ai] : ai;
+          bind[ match_i++ ] = B_perm ? B_perm[bi] : bi;
 
           /* Set a `1' for this object in the second catalog. This will
              later be used to find which rows didn't match to fill in the
              output.. */
-          Bmatched[ B_perm[bi] ] = 1;
+          Bmatched[ B_perm ? B_perm[bi] : bi ] = 1;
         }
+
       /* No match found. At this stage, we can only fill the indexs of the
          first input. The second input needs to be matched afterwards.*/
-      else aind[ nomatch_i++ ] = A_perm[ai];
+      else aind[ nomatch_i++ ] = A_perm ? A_perm[ai] : ai;
     }
 
 
@@ -861,14 +870,16 @@ gal_match_coordinates(gal_data_t *coord1, gal_data_t 
*coord2,
                       double *aperture, int sorted_by_first,
                       int inplace, size_t minmapsize, size_t *nummatched)
 {
+  int allf64=1;
   gal_data_t *A, *B, *out;
   size_t *A_perm=NULL, *B_perm=NULL;
   struct match_coordinate_sfll **bina;
 
   /* Do a small sanity check and make the preparations. After this point,
      we'll call the two arrays `a' and `b'.*/
-  match_coordinaes_sanity_check(coord1, coord2, aperture);
-  match_coordinates_prepare(coord1, coord2, sorted_by_first, inplace,
+  match_coordinaes_sanity_check(coord1, coord2, aperture, inplace,
+                                &allf64);
+  match_coordinates_prepare(coord1, coord2, sorted_by_first, inplace, allf64,
                             &A, &B, &A_perm, &B_perm, minmapsize);
 
 
@@ -897,13 +908,13 @@ gal_match_coordinates(gal_data_t *coord1, gal_data_t 
*coord2,
 
   /* Clean up. */
   free(bina);
-  free(A_perm);
-  free(B_perm);
   if(A!=coord1)
     {
       gal_list_data_free(A);
       gal_list_data_free(B);
     }
+  if(A_perm) free(A_perm);
+  if(B_perm) free(B_perm);
 
 
   /* Set `nummatched' and return output. */
diff --git a/lib/table.c b/lib/table.c
index 71112e5..c917669 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -213,14 +213,14 @@ table_set_strcheck(gal_data_t *col, int searchin)
 static gal_list_sizet_t *
 make_list_of_indexs(gal_list_str_t *cols, gal_data_t *allcols,
                     size_t numcols, int searchin, int ignorecase,
-                    char *filename, char *hdu)
+                    char *filename, char *hdu, size_t *colmatch)
 {
   long tlong;
   int regreturn;
   regex_t *regex;
   gal_list_str_t *tmp;
-  size_t i, nummatch, len;
   gal_list_sizet_t *indexll=NULL;
+  size_t i, nummatch, colcount=0, len;
   char *str, *strcheck, *tailptr, *errorstring;
 
   /* Go over the given columns.  */
@@ -362,6 +362,10 @@ make_list_of_indexs(gal_list_str_t *cols, gal_data_t 
*allcols,
                      tmp->v, gal_tableintern_searchin_as_string(searchin));
             gal_tableintern_error_col_selection(filename, hdu, errorstring);
           }
+
+
+        /* Keep the value of `nummatch' if the user requested it. */
+        if(colmatch) colmatch[colcount++]=nummatch;
       }
 
   /* cols==NULL */
@@ -398,7 +402,8 @@ make_list_of_indexs(gal_list_str_t *cols, gal_data_t 
*allcols,
    on. */
 gal_data_t *
 gal_table_read(char *filename, char *hdu, gal_list_str_t *cols,
-               int searchin, int ignorecase, int minmapsize)
+               int searchin, int ignorecase, int minmapsize,
+               size_t *colmatch)
 {
   int tableformat;
   gal_list_sizet_t *indexll;
@@ -413,7 +418,7 @@ gal_table_read(char *filename, char *hdu, gal_list_str_t 
*cols,
 
   /* Get the list of indexs in the same order as the input list */
   indexll=make_list_of_indexs(cols, allcols, numcols, searchin,
-                              ignorecase, filename, hdu);
+                              ignorecase, filename, hdu, colmatch);
 
   /* Depending on the table format, read the columns into the output
      structure. Note that the functions here pop each index, read/store the
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 21a0461..9943b6c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -123,9 +123,10 @@ if COND_FITS
   fits/copyhdu.sh: fits/write.sh.log mkprof/mosaic2.sh.log
 endif
 if COND_MATCH
-  MAYBE_MATCH_TESTS = match/positions.sh
+  MAYBE_MATCH_TESTS = match/positions.sh match/merged-cols.sh
 
   match/positions.sh: prepconf.sh.log
+  match/merged-cols.sh: prepconf.sh.log
 endif
 if COND_MKCATALOG
   MAYBE_MKCATALOG_TESTS = mkcatalog/simple.sh mkcatalog/simple-3d.sh \
diff --git a/tests/match/merged-cols.sh b/tests/match/merged-cols.sh
new file mode 100755
index 0000000..2af07da
--- /dev/null
+++ b/tests/match/merged-cols.sh
@@ -0,0 +1,53 @@
+# Match the two input catalogs and return merged output
+#
+# See the Tests subsection of the manual for a complete explanation
+# (in the Installing gnuastro section).
+#
+# Original author:
+#     Mohammad Akhlaghi <akhlaghi@gnu.org>
+# Contributing author(s):
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.  This file is offered as-is,
+# without any warranty.
+
+
+
+
+
+# Preliminaries
+# =============
+#
+# Set the variables (The executable is in the build tree). Do the
+# basic checks to see if the executable is made or if the defaults
+# file exists (basicchecks.sh is in the source tree).
+prog=match
+execname=../bin/$prog/ast$prog
+cat1=$topsrc/tests/$prog/positions-1.txt
+cat2=$topsrc/tests/$prog/positions-2.txt
+
+
+
+
+
+# Skip?
+# =====
+#
+# If the dependencies of the test don't exist, then skip it. There are two
+# types of dependencies:
+#
+#   - The executable was not made (for example due to a configure option),
+#
+#   - The input data was not made (for example the test that created the
+#     data file failed).
+if [ ! -f $execname ]; then echo "$execname not created."; exit 77; fi
+
+
+
+
+
+# Actual test script
+# ==================
+$execname $cat1 $cat2 --aperture=0.5 --log --output=match-positions.fits \
+          --outcols=a1,aEFGH,bACCU1,aIJKL,bACCU2 -omatch-merged-cols.txt
diff --git a/tests/match/positions-1.txt b/tests/match/positions-1.txt
index 5964218..b7e71b7 100644
--- a/tests/match/positions-1.txt
+++ b/tests/match/positions-1.txt
@@ -1,3 +1,6 @@
+# Column 1: ABCD
+# Column 2: EFGH
+# Column 3: IJKL
 1   1   1
 2   2   2
 3   3   3
diff --git a/tests/match/positions-2.txt b/tests/match/positions-2.txt
index 820dac8..cd41cbc 100644
--- a/tests/match/positions-2.txt
+++ b/tests/match/positions-2.txt
@@ -1,3 +1,6 @@
+# Column 1: ABCD
+# Column 2: ACCU1
+# Column 3: ACCU2
 1   8.20    7.90
 2   20.1    2.80
 3   4.80    5.20



reply via email to

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