gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master d02c999 079/113: Recent work in master importe


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master d02c999 079/113: Recent work in master imported, conflicts fixed
Date: Fri, 16 Apr 2021 10:33:52 -0400 (EDT)

branch: master
commit d02c9998aaad8c87d77deabfd7f5311497450d14
Merge: 4021652 388c6be
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Recent work in master imported, conflicts fixed
    
    Conflicts due to the new minimum and maximum position columns of
    MakeCatalog were fixed and are now merged into this branch.
---
 NEWS                        |  14 ++-
 bin/arithmetic/arithmetic.c |  19 +++-
 bin/arithmetic/main.h       |   5 +-
 bin/arithmetic/operands.c   | 211 ++++++++++++++++++++++++++++++++++++++++----
 bin/arithmetic/operands.h   |   5 ++
 bin/arithmetic/ui.c         |  40 +++++----
 bin/buildprog/Makefile.am   |  35 +++++---
 bin/mkcatalog/args.h        |  56 ++++++++++++
 bin/mkcatalog/columns.c     | 113 ++++++++++++++++++++++++
 bin/mkcatalog/main.h        |   4 +
 bin/mkcatalog/parse.c       |  28 +++++-
 bin/mkcatalog/ui.c          |   4 +
 bin/mkcatalog/ui.h          |   4 +
 doc/gnuastro.en.html        |   5 +-
 doc/gnuastro.fr.html        |   8 +-
 doc/gnuastro.texi           |  80 +++++++++++++++--
 lib/array.c                 |  20 ++++-
 lib/gnuastro/array.h        |   3 +
 18 files changed, 590 insertions(+), 64 deletions(-)

diff --git a/NEWS b/NEWS
index 07b2347..a0c9680 100644
--- a/NEWS
+++ b/NEWS
@@ -9,14 +9,24 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
     --enable-check-with-valgrind: Run `make check' tests within Valgrind.
 
   Arithmetic:
+    - `set-A': Set a name (`A' in this case) for the popped dataset. This
+               allows only reading the dataset it into memory once and
+               possibly using it many times.
     - `collapse-sum': collapse/remove a dimension by summing over it.
     - `collapse-mean': collapse/remove a dimension by averaging over it.
     - `collapse-number': Number of elements included in the collapse.
 
+  MakeCatalog:
+    --minx: minimum position along first FITS axis.
+    --maxx: maximum position along first FITS axis.
+    --miny: minimum position along second FITS axis.
+    --maxy: maximum position along second FITS axis.
+
   Table:
     --colinfoinstdout: column information when writing to standard output.
 
   Library:
+    - gal_array_name_recognized_multiext: If format contains multiple datasets.
     - gal_dimension_collapse_sum: collapse/remove a dimension by summing.
     - gal_dimension_collapse_mean: collapse/remove a dimension by averaging.
     - gal_dimension_collapse_number: collapse/remove a dimension by number.
@@ -43,13 +53,13 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
   bug #54063: Match tests in make check fail randomly.
   bug #54186: MakeCatalog's --checkupperlimit not keeping output's name.
   bug #54188: MakeCatalog's Upperlimit not being sigma-clipped properly.
-  bug #54284: Crop segrault when catalog contains no data.
+  bug #54284: Crop segfault when catalog contains no data.
   bug #54285: make check fails if g++ not present.
   bug #54286: BuildProgram's configuration file, not built by default.
   bug #54297: No Match output when --notmatched called and no match.
   bug #54298: Table not writing array when there are no rows.
   bug #54312: Crash when CFITSIO doesn't have fits_is_reentrant function.
-
+  bug #54346: Non '-I' or non '-L' strings in CPPFLAGS or LDFLAGS cause crash.
 
 
 
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index f83e461..ba8ef38 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -817,10 +817,14 @@ reversepolish(struct arithmeticparams *p)
       /* If we have a name or number, then add it to the operands linked
          list. Otherwise, pull out two members and do the specified
          operation on them. */
-      if(gal_array_name_recognized(token->v))
+      if( gal_array_name_recognized(token->v)
+          || operands_is_name(p, token->v) )
         operands_add(p, token->v, NULL);
       else if( (d1=gal_data_copy_string_to_number(token->v)) )
         operands_add(p, NULL, d1);
+      else if( !strncmp(token->v, SET_OPERATOR_PREFIX,
+                        SET_OPERATOR_PREFIX_LENGTH) )
+        operands_set_name(p, token->v);
       else
         {
 
@@ -969,7 +973,7 @@ reversepolish(struct arithmeticparams *p)
           /* Finished checks with known operators */
           else
             error(EXIT_FAILURE, 0, "the argument \"%s\" could not be "
-                  "interpretted as a recognized input file name, number, or "
+                  "interpretted as a file name, named dataset, number, or "
                   "operator", token->v);
 
 
@@ -1069,8 +1073,18 @@ reversepolish(struct arithmeticparams *p)
                 }
             }
         }
+
+      /* Increment the token counter. */
+      ++p->tokencounter;
     }
 
+
+  /* If there aren't any more operands (a variable has been set but not
+     used), then there is nothing to create. */
+  if(p->operands==NULL)
+    error(EXIT_FAILURE, 0, "no operands on the stack to write (as output)");
+
+
   /* If there is more than one node in the operands stack then the user has
      given too many operands which is an error. */
   if(p->operands->next!=NULL)
@@ -1130,6 +1144,7 @@ reversepolish(struct arithmeticparams *p)
      into `d1', so it is freed when freeing d1. */
   gal_data_free(d1);
   free(p->refdata.dsize);
+  gal_list_data_free(p->named);
 
   /* Clean up. Note that the tokens were taken from the command-line
      arguments, so the string within each token linked list must not be
diff --git a/bin/arithmetic/main.h b/bin/arithmetic/main.h
index c0c2a1d..652f7e8 100644
--- a/bin/arithmetic/main.h
+++ b/bin/arithmetic/main.h
@@ -38,9 +38,10 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 
 
-
 /* Constants: */
 #define NEG_DASH_REPLACE 11 /* Vertical tab (ASCII=11) for negative dash */
+#define SET_OPERATOR_PREFIX        "set-"
+#define SET_OPERATOR_PREFIX_LENGTH strlen(SET_OPERATOR_PREFIX)
 
 
 
@@ -73,6 +74,8 @@ struct arithmeticparams
   size_t        popcounter;  /* The number of FITS images popped.       */
   gal_data_t       refdata;  /* Container for information of the data.  */
   char          *globalhdu;  /* Single HDU for all inputs.              */
+  gal_data_t        *named;  /* List containing variables.              */
+  size_t      tokencounter;  /* Counter for finding place in tokens.    */
 
   /* Operating mode: */
 
diff --git a/bin/arithmetic/operands.c b/bin/arithmetic/operands.c
index 8329b5e..a4914ae 100644
--- a/bin/arithmetic/operands.c
+++ b/bin/arithmetic/operands.c
@@ -58,6 +58,162 @@ operands_num(struct arithmeticparams *p)
 
 
 
+static int
+operands_name_is_used_later(struct arithmeticparams *p, char *name)
+{
+  size_t counter=0;
+  gal_list_str_t *token;
+
+  /* If the name indeed exists afterwards, then just return 1. */
+  for(token=p->tokens;token!=NULL;token=token->next)
+    if( counter++ > p->tokencounter && !strcmp(token->v, name) )
+      return 1;
+
+  /* If we get to this point, it means that the name doesn't exist. */
+  return 0;
+}
+
+
+
+
+
+/* Pop a dataset and keep it in the `named' list for later use. */
+void
+operands_set_name(struct arithmeticparams *p, char *token)
+{
+  gal_data_t *tmp;
+  char *varname=&token[ SET_OPERATOR_PREFIX_LENGTH ];
+
+  /* Make sure the variable name hasn't been set before. */
+  for(tmp=p->named; tmp!=NULL; tmp=tmp->next)
+    if( !strcmp(varname, tmp->name) )
+      error(EXIT_FAILURE, 0, "`%s' was previously set as a name",
+            varname);
+
+  /* Pop the top operand, then add it to the list of named datasets, but
+     only if it is used in later tokens. If it isn't, free the popped
+     dataset. The latter case (to define a name, but not use it), is
+     obviously a redundant operation, but that is upto the user, we
+     shouldn't worry about it here. We should just have everything in
+     place, so no crashes occur or no extra memory is consumed. */
+  if( operands_name_is_used_later(p, varname) )
+    {
+      /* Add the top popped operand to the list of names. */
+      gal_list_data_add(&p->named, operands_pop(p, "set"));
+
+      /* Write the requested name into this dataset. But note that `name'
+         MUST be already empty. So to be safe, we'll do a sanity check. */
+      if(p->named->name)
+        error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix "
+              "the problem. The `name' element should be NULL at this "
+              "point, but it isn't", __func__, PACKAGE_BUGREPORT);
+      gal_checkset_allocate_copy(varname, &p->named->name);
+    }
+  else
+    {
+      /* Pop the top operand, then free it. */
+      tmp=operands_pop(p, "set");
+      gal_data_free(tmp);
+    }
+}
+
+
+
+
+
+/* See if a given token is the name of a variable. */
+int
+operands_is_name(struct arithmeticparams *p, char *token)
+{
+  gal_data_t *tmp;
+
+  /* Make sure the variable name hasn't been set before. */
+  for(tmp=p->named; tmp!=NULL; tmp=tmp->next)
+    if( !strcmp(token, tmp->name) )
+      return 1;
+
+  /* If control reaches here, then there was no match*/
+  return 0;
+}
+
+
+
+
+
+/* Remove a name from the list of names and retrun the dataset it points
+   to. */
+static gal_data_t *
+operands_remove_name(struct arithmeticparams *p, char *name)
+{
+  gal_data_t *tmp, *removed=NULL, *prev=NULL;
+
+  /* Go over all the given names. */
+  for(tmp=p->named;tmp!=NULL;tmp=tmp->next)
+    {
+      if( !strcmp(tmp->name, name) )
+        {
+          removed=tmp;
+          if(prev) prev->next = tmp->next;
+          else     p->named   = tmp->next;
+        }
+
+      /* Set this node as the `prev' pointer. */
+      prev=tmp;
+    }
+
+  /* A small sanity check. */
+  if(removed==NULL)
+    error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
+          "problem. `removed' must not be NULL at this point", __func__,
+          PACKAGE_BUGREPORT);
+
+  /* Nothing in the list points to it now. So we can safely modify and
+     return it. */
+  free(removed->name);
+  removed->name=NULL;
+  return removed;
+}
+
+
+
+
+
+/* Return a copy of the named dataset. */
+static gal_data_t *
+operands_copy_named(struct arithmeticparams *p, char *name)
+{
+  gal_data_t *out=NULL, *tmp;
+
+  /* Find the proper named element to use. */
+  for(tmp=p->named;tmp!=NULL;tmp=tmp->next)
+    if( !strcmp(tmp->name, name) )
+      {
+        /* If the named operand is used later, then copy it into the
+           output. */
+        if( operands_name_is_used_later(p, name) )
+          {
+            out=gal_data_copy(tmp);
+            free(out->name);
+            out->name=NULL;
+          }
+        /* The named operand is not used any more. Remove it from the list
+           of named datasets and continue. */
+        else out=operands_remove_name(p, name);
+      }
+
+  /* A small sanity check. */
+  if(out==NULL)
+    error(EXIT_FAILURE, 0, "%s: a bug! please contact us at %s to fix the "
+          "problem. The requested name `%s' couldn't be found in the list",
+          __func__, PACKAGE_BUGREPORT, name);
+
+  /* Return. */
+  return out;
+}
+
+
+
+
 void
 operands_add(struct arithmeticparams *p, char *filename, gal_data_t *data)
 {
@@ -75,22 +231,32 @@ operands_add(struct arithmeticparams *p, char *filename, 
gal_data_t *data)
         error(EXIT_FAILURE, errno, "%s: allocating %zu bytes for `newnode'",
               __func__, sizeof *newnode);
 
-      /* Fill in the values. */
-      newnode->data=data;
-      newnode->filename=filename;
-
-      /* See if a HDU must be read or not. */
-      if(filename != NULL
-         && ( gal_fits_name_is_fits(filename)
-              || gal_tiff_name_is_tiff(filename) ) )
+      /* If the `filename' is the name of a dataset, then use a copy of it.
+         otherwise, do the basic analysis. */
+      if( filename && operands_is_name(p, filename) )
+        {
+          newnode->filename=NULL;
+          newnode->data=operands_copy_named(p, filename);
+        }
+      else
         {
-          /* Set the HDU for this filename. */
-          if(p->globalhdu)
-            gal_checkset_allocate_copy(p->globalhdu, &newnode->hdu);
-          else
-            newnode->hdu=gal_list_str_pop(&p->hdus);
+          /* Set the basic parameters. */
+          newnode->data=data;
+          newnode->filename=filename;
+
+          /* See if a HDU must be read or not. */
+          if(filename != NULL
+             && ( gal_fits_name_is_fits(filename)
+                  || gal_tiff_name_is_tiff(filename) ) )
+            {
+              /* Set the HDU for this filename. */
+              if(p->globalhdu)
+                gal_checkset_allocate_copy(p->globalhdu, &newnode->hdu);
+              else
+                newnode->hdu=gal_list_str_pop(&p->hdus);
+            }
+          else newnode->hdu=NULL;
         }
-      else newnode->hdu=NULL;
 
       /* Make the link to the previous list. */
       newnode->next=p->operands;
@@ -116,21 +282,28 @@ operands_pop(struct arithmeticparams *p, char *operator)
     error(EXIT_FAILURE, 0, "not enough operands for the \"%s\" operator",
           operator);
 
-
   /* Set the dataset. If filename is present then read the file
      and fill in the array, if not then just set the array. */
   if(operands->filename)
     {
+      /* Set the HDU and filename */
       hdu=operands->hdu;
       filename=operands->filename;
 
       /* Read the dataset. */
       data=gal_array_read_one_ch(filename, hdu, p->cp.minmapsize);
 
+      /* Arithmetic changes the contents of a dataset, so the existing name
+         (in the FITS `EXTNAME' keyword) should not be passed on beyond
+         this point. Also, in Arithmetic, the `name' element is used to
+         identify variables. */
+      if(data->name) { free(data->name); data->name=NULL; }
+
       /* In case this is the first image that is read, then keep the WCS
          information in the `refdata' structure.  */
       if(p->popcounter==0)
-        p->refdata.wcs=gal_wcs_read(filename, hdu, 0, 0, &p->refdata.nwcs);
+        p->refdata.wcs=gal_wcs_read(filename, hdu, 0, 0,
+                                    &p->refdata.nwcs);
 
       /* When the reference data structure's dimensionality is non-zero, it
          means that this is not the first image read. So, write its basic
@@ -151,7 +324,8 @@ operands_pop(struct arithmeticparams *p, char *operator)
 
           /* Allocate the dsize array. */
           errno=0;
-          p->refdata.dsize=malloc(p->refdata.ndim * sizeof *p->refdata.dsize);
+          p->refdata.dsize=malloc(p->refdata.ndim
+                                  * sizeof *p->refdata.dsize);
           if(p->refdata.dsize==NULL)
             error(EXIT_FAILURE, errno, "%s: allocating %zu bytes for "
                   "p->refdata.dsize", __func__,
@@ -166,7 +340,7 @@ operands_pop(struct arithmeticparams *p, char *operator)
       if(!p->cp.quiet) printf(" - %s (hdu %s) is read.\n", filename, hdu);
 
       /* Free the HDU string: */
-      free(hdu);
+      if(hdu) free(hdu);
 
       /* Add to the number of popped FITS images: */
       ++p->popcounter;
@@ -174,6 +348,7 @@ operands_pop(struct arithmeticparams *p, char *operator)
   else
     data=operands->data;
 
+
   /* Remove this node from the queue, return the data structure. */
   p->operands=operands->next;
   free(operands);
diff --git a/bin/arithmetic/operands.h b/bin/arithmetic/operands.h
index ae487f5..e784f6d 100644
--- a/bin/arithmetic/operands.h
+++ b/bin/arithmetic/operands.h
@@ -32,5 +32,10 @@ operands_add(struct arithmeticparams *p, char *filename, 
gal_data_t *data);
 gal_data_t *
 operands_pop(struct arithmeticparams *p, char *operator);
 
+void
+operands_set_name(struct arithmeticparams *p, char *token);
+
+int
+operands_is_name(struct arithmeticparams *p, char *token);
 
 #endif
diff --git a/bin/arithmetic/ui.c b/bin/arithmetic/ui.c
index 8c57feb..3824f3b 100644
--- a/bin/arithmetic/ui.c
+++ b/bin/arithmetic/ui.c
@@ -26,10 +26,12 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <errno.h>
 #include <error.h>
 #include <stdio.h>
+#include <string.h>
 
 #include <gnuastro/list.h>
 #include <gnuastro/fits.h>
 #include <gnuastro/table.h>
+#include <gnuastro/array.h>
 
 #include <gnuastro-internal/timing.h>
 #include <gnuastro-internal/options.h>
@@ -229,7 +231,7 @@ static void
 ui_check_options_and_arguments(struct arithmeticparams *p)
 {
   int output_checked=0;
-  size_t numfits=0, numhdus=0;
+  size_t nummultiext=0, numhdus=0;
   gal_list_str_t *token, *hdu;
 
   /* First, make sure that any tokens are actually given. */
@@ -247,19 +249,21 @@ ui_check_options_and_arguments(struct arithmeticparams *p)
      was done in `gal_options_read_config_set'. */
   gal_list_str_reverse(&p->tokens);
 
-  /* Set the output file name (if any is needed). Note that since the
-     lists are already reversed, the first FITS file encountered, is
-     the first FITS file given by teh user. Also, notet that these
-     file name operations are only necessary for the first FITS file
-     in the token list. */
+  /* Set the output file name (if any is needed). Note that since the lists
+     are already reversed, the first FITS file encountered, is the first
+     FITS file given by the user. Also, note that these file name
+     operations are only necessary for the first FITS file in the token
+     list. */
   for(token=p->tokens; token!=NULL; token=token->next)
     {
-      /* This token is a FITS file, count them and use it to set the output
-         filename if it has not been set. */
-      if(gal_fits_name_is_fits(token->v))
+      /* This token is a file, count how many mult-extension files we haev
+         and use the first to set the output filename (if it has not been
+         set). */
+      if( gal_array_name_recognized(token->v) )
         {
           /* Increment the counter for FITS files. */
-          ++numfits;
+          if( gal_array_name_recognized_multiext(token->v) )
+            ++nummultiext;
 
           /* If the output filename isn't set yet, then set it. */
           if(output_checked==0)
@@ -288,13 +292,15 @@ ui_check_options_and_arguments(struct arithmeticparams *p)
   else
     {
       for(hdu=p->hdus; hdu!=NULL; hdu=hdu->next) ++numhdus;
-      if(numhdus<numfits)
-        error(EXIT_FAILURE, 0, "not enough HDUs. There are %zu input FITS "
-              "files, so the `--hdu' (`-h') option must be called %zu "
-              "times (once for each FITS file). If the HDU value is the "
-              "same for all the files, you may use `--globalhdu' (`-g') to "
-              "specify a single HDU to be used for any number of input "
-              "files", numfits, numfits);
+      if(numhdus<nummultiext)
+        error(EXIT_FAILURE, 0, "not enough HDUs. There are %zu input "
+              "files in formats that may contain multiple extensions (for "
+              "example FITS or TIFF). Therefore, the `--hdu' (`-h') option "
+              "must be called atleaset %zu times (once for each "
+              "multi-extension file). If the HDU value is the same for all "
+              "the files, you may use `--globalhdu' (`-g') to specify a "
+              "single HDU to be used for any number of input files",
+              nummultiext, nummultiext);
     }
 }
 
diff --git a/bin/buildprog/Makefile.am b/bin/buildprog/Makefile.am
index 446186e..58d9b03 100644
--- a/bin/buildprog/Makefile.am
+++ b/bin/buildprog/Makefile.am
@@ -51,26 +51,37 @@ EXTRA_DIST = main.h authors-cite.h args.h ui.h buildprog.h 
astbuildprog.conf.in
 # directories in order to compile its programs. With the rule below, the
 # directories in these variables will be written into the final
 # BuildProgram configuration file.
+#
+# The user might give non-`-I' arguments to CPPFLAGS and non-`-L' arguments
+# to LDFLAGS (see bug #54346). But here, we only want these two options,
+# and nothing else. To make the check, we'll see if `$i' (the input string)
+# is the same as `$v' or not. If the string starts with `-I' or `-L', it
+# will change between the two (the `-I' or `-L' have been removed), so it
+# shouldn't be the same.
 astbuildprog.conf: $(top_srcdir)/bin/buildprog/astbuildprog.conf.in
        cp $< $@
        infoadded="no";                                \
        for i in $(CPPFLAGS); do                       \
-         if test $$infoadded = "no"; then             \
-           echo "" >> $@;                             \
-           echo "# Installation information" >> $@;   \
-           infoadded="yes";                           \
+         v=$$(echo $$i | sed -e 's/^-I//');           \
+         if test $$i != $$v; then                     \
+           if test $$infoadded = "no"; then           \
+             echo "" >> $@;                           \
+             echo "# Installation information" >> $@; \
+             infoadded="yes";                         \
+           fi;                                        \
+           echo " includedir $$v" >> $@;              \
          fi;                                          \
-         v=$$(echo $$i | sed -e 's/-I//');            \
-         echo " includedir $$v" >> $@;                \
        done;                                          \
        for i in $(LDFLAGS); do                        \
-         if test $$infoadded = "no"; then             \
-           echo "" >> $@;                             \
-           echo "# Installation information" >> $@;   \
-           infoadded="yes";                           \
+         v=$$(echo $$i | sed -e 's/^-L//');           \
+         if test $$i != $$v; then                     \
+           if test $$infoadded = "no"; then           \
+             echo "" >> $@;                           \
+             echo "# Installation information" >> $@; \
+             infoadded="yes";                         \
+           fi;                                        \
+           echo " linkdir $$v" >> $@;                 \
          fi;                                          \
-         v=$$(echo $$i | sed -e 's/-L//');            \
-         echo " linkdir $$v" >> $@;                   \
        done
 
 
diff --git a/bin/mkcatalog/args.h b/bin/mkcatalog/args.h
index cfdfb5e..1cd79fd 100644
--- a/bin/mkcatalog/args.h
+++ b/bin/mkcatalog/args.h
@@ -511,6 +511,62 @@ struct argp_option program_options[] =
       ui_column_codes_ll
     },
     {
+      "minx",
+      UI_KEY_MINX,
+      0,
+      0,
+      "Minimum first FITS axis position.",
+      UI_GROUP_COLUMNS_POSITION_PIXEL,
+      0,
+      GAL_TYPE_INVALID,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET,
+      ui_column_codes_ll
+    },
+    {
+      "maxx",
+      UI_KEY_MAXX,
+      0,
+      0,
+      "Maximum first FITS axis position.",
+      UI_GROUP_COLUMNS_POSITION_PIXEL,
+      0,
+      GAL_TYPE_INVALID,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET,
+      ui_column_codes_ll
+    },
+    {
+      "miny",
+      UI_KEY_MINY,
+      0,
+      0,
+      "Minimum second FITS axis position.",
+      UI_GROUP_COLUMNS_POSITION_PIXEL,
+      0,
+      GAL_TYPE_INVALID,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET,
+      ui_column_codes_ll
+    },
+    {
+      "maxy",
+      UI_KEY_MAXY,
+      0,
+      0,
+      "Maximum second FITS axis position.",
+      UI_GROUP_COLUMNS_POSITION_PIXEL,
+      0,
+      GAL_TYPE_INVALID,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET,
+      ui_column_codes_ll
+    },
+    {
       "clumpsx",
       UI_KEY_CLUMPSX,
       0,
diff --git a/bin/mkcatalog/columns.c b/bin/mkcatalog/columns.c
index 49ee9d3..7a6db1e 100644
--- a/bin/mkcatalog/columns.c
+++ b/bin/mkcatalog/columns.c
@@ -655,6 +655,57 @@ columns_define_alloc(struct mkcatalogparams *p)
           disp_width     = 10;
           disp_precision = 3;
           oiflag[ OCOL_C_GZ ] = 1;
+
+        case UI_KEY_MINX:
+          name           = "MIN_X";
+          unit           = "pixel";
+          ocomment       = "Minimum X axis pixel position.";
+          ccomment       = ocomment;
+          otype          = GAL_TYPE_UINT32;
+          ctype          = GAL_TYPE_UINT32;
+          disp_fmt       = 0;
+          disp_width     = 10;
+          disp_precision = 0;
+          ciflag[ CCOL_MINX ] = 1;
+          break;
+
+        case UI_KEY_MAXX:
+          name           = "MAX_X";
+          unit           = "pixel";
+          ocomment       = "Maximum X axis pixel position.";
+          ccomment       = ocomment;
+          otype          = GAL_TYPE_UINT32;
+          ctype          = GAL_TYPE_UINT32;
+          disp_fmt       = 0;
+          disp_width     = 10;
+          disp_precision = 0;
+          ciflag[ CCOL_MAXX ] = 1;
+          break;
+
+        case UI_KEY_MINY:
+          name           = "MIN_Y";
+          unit           = "pixel";
+          ocomment       = "Minimum Y axis pixel position.";
+          ccomment       = ocomment;
+          otype          = GAL_TYPE_UINT32;
+          ctype          = GAL_TYPE_UINT32;
+          disp_fmt       = 0;
+          disp_width     = 10;
+          disp_precision = 0;
+          ciflag[ CCOL_MINY ] = 1;
+          break;
+
+        case UI_KEY_MAXY:
+          name           = "MAX_Y";
+          unit           = "pixel";
+          ocomment       = "Maximum Y axis pixel position.";
+          ccomment       = ocomment;
+          otype          = GAL_TYPE_UINT32;
+          ctype          = GAL_TYPE_UINT32;
+          disp_fmt       = 0;
+          disp_width     = 10;
+          disp_precision = 0;
+          ciflag[ CCOL_MAXY ] = 1;
           break;
 
         case UI_KEY_W1:
@@ -1638,6 +1689,46 @@ columns_clump_brightness(double *ci)
 
 
 
+/* Measure the minimum and maximum positions. */
+static uint32_t
+columns_xy_extrema(struct mkcatalog_passparams *pp, size_t *coord, int key)
+{
+  gal_data_t *tile=pp->tile, *block=tile->block;
+
+  /* We only want to do the coordinate estimation once: in `columns_fill',
+     we initialized the coordinates with `GAL_BLANK_SIZE_T'. When the
+     coordinate has already been measured already, it won't have this value
+     any more. */
+  if(coord[0]==GAL_BLANK_SIZE_T)
+    gal_dimension_index_to_coord(gal_pointer_num_between(block->array,
+                                                         tile->array,
+                                                         block->type),
+                                 block->ndim, block->dsize, coord);
+
+  /* Return the proper value: note that `coord' is in C standard: starting
+     from the slowest dimension and counting from zero.*/
+  switch(key)
+    {
+    case UI_KEY_MINX: return coord[1] + 1;              break;
+    case UI_KEY_MAXX: return coord[1] + tile->dsize[1]; break;
+    case UI_KEY_MINY: return coord[0] + 1;              break;
+    case UI_KEY_MAXY: return coord[0] + tile->dsize[0]; break;
+    default:
+      error(EXIT_FAILURE, 0, "%s: a bug! Please contact us to fix the "
+            "problem. The value %d is not a recognized value", __func__,
+            key);
+    }
+
+  /* Control should not reach here. */
+  error(EXIT_FAILURE, 0, "%s: a bug! please contact us to fix the problem. "
+        "Control should not reach the end of this function", __func__);
+  return GAL_BLANK_UINT32;
+}
+
+
+
+
+
 /* The magnitude error is directly derivable from the S/N:
 
    To derive the error in measuring the magnitude from the S/N, let's take
@@ -1692,6 +1783,8 @@ columns_fill(struct mkcatalog_passparams *pp)
   void *colarr;
   gal_data_t *column;
   double *ci, *oi=pp->oi;
+  size_t coord[2]={GAL_BLANK_SIZE_T, GAL_BLANK_SIZE_T};
+
   size_t sr=pp->clumpstartindex, cind, coind;
   size_t oind=pp->object-1; /* IDs start from 1, indexs from 0. */
   double **vo=NULL, **vc=NULL, **go=NULL, **gc=NULL, **vcc=NULL, **gcc=NULL;
@@ -1802,6 +1895,12 @@ columns_fill(struct mkcatalog_passparams *pp)
         case UI_KEY_CLUMPSGEOZ:
           ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_C_GZ],
                                                oi[OCOL_C_NUMALL] );
+
+        case UI_KEY_MINX:
+        case UI_KEY_MAXX:
+        case UI_KEY_MINY:
+        case UI_KEY_MAXY:
+          ((uint32_t *)colarr)[oind]=columns_xy_extrema(pp, coord, key);
           break;
 
         case UI_KEY_W1:
@@ -2046,6 +2145,20 @@ columns_fill(struct mkcatalog_passparams *pp)
           case UI_KEY_GEOZ:
             ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_GZ],
                                                  ci[CCOL_NUMALL] );
+          case UI_KEY_MINX:
+            ((uint32_t *)colarr)[cind] = ci[CCOL_MINX];
+            break;
+
+          case UI_KEY_MAXX:
+            ((uint32_t *)colarr)[cind] = ci[CCOL_MAXX];
+            break;
+
+          case UI_KEY_MINY:
+            ((uint32_t *)colarr)[cind] = ci[CCOL_MINY];
+            break;
+
+          case UI_KEY_MAXY:
+            ((uint32_t *)colarr)[cind] = ci[CCOL_MAXY];
             break;
 
           case UI_KEY_W1:
diff --git a/bin/mkcatalog/main.h b/bin/mkcatalog/main.h
index 9376d7d..94cb2d3 100644
--- a/bin/mkcatalog/main.h
+++ b/bin/mkcatalog/main.h
@@ -140,6 +140,10 @@ enum clumpcols
     CCOL_GXX,            /* Second order geometric moment.            */
     CCOL_GYY,            /* Second order geometric moment.            */
     CCOL_GXY,            /* Second order geometric moment.            */
+    CCOL_MINX,           /* Minimum X value of clump.                 */
+    CCOL_MAXX,           /* Maximum X value of clump.                 */
+    CCOL_MINY,           /* Minimum Y value of clump.                 */
+    CCOL_MAXY,           /* Maximum Y value of clump.                 */
     CCOL_UPPERLIMIT_B,   /* Upper limit brightness.                   */
     CCOL_UPPERLIMIT_S,   /* Upper limit one-sigma value.              */
     CCOL_UPPERLIMIT_Q,   /* Quantile of object in random distribution.*/
diff --git a/bin/mkcatalog/parse.c b/bin/mkcatalog/parse.c
index 95ccfc0..a593308 100644
--- a/bin/mkcatalog/parse.c
+++ b/bin/mkcatalog/parse.c
@@ -362,6 +362,19 @@ parse_objects(struct mkcatalog_passparams *pp)
 
 
 
+/* Macro to help in finding the minimum and maximum coordinates. */
+#define CMIN(COL, DIM) ( ci[ CCOL_NUMALL ]==1.0f                        \
+                         ? (c[ DIM ]+1)                                 \
+                         : ( (c[ DIM ]+1) < ci[ COL ]                   \
+                             ? (c[ DIM ]+1) : ci[ COL ] ) )
+#define CMAX(COL, DIM) ( ci[ CCOL_NUMALL ]==1.0f                        \
+                         ? (c[ DIM ]+1)                                 \
+                         : ( (c[ DIM ]+1) > ci[ COL ]                   \
+                             ? (c[ DIM ]+1) : ci[ COL ] ) )
+
+
+
+
 /* Parse over the clumps within an object.  */
 void
 parse_clumps(struct mkcatalog_passparams *pp)
@@ -397,6 +410,10 @@ parse_clumps(struct mkcatalog_passparams *pp)
                   || cif[ CCOL_VX ]
                   || cif[ CCOL_VY ]
                   || cif[ CCOL_VZ ]
+                  || cif[ CCOL_MINX ]
+                  || cif[ CCOL_MAXX ]
+                  || cif[ CCOL_MINY ]
+                  || cif[ CCOL_MAXY ]
                   || sc
                   || tid==GAL_BLANK_SIZE_T )
                 ? gal_pointer_allocate(GAL_TYPE_SIZE_T, ndim, 0, __func__,
@@ -451,7 +468,10 @@ parse_clumps(struct mkcatalog_passparams *pp)
                   ci=&pp->ci[ (*C-1) * CCOL_NUMCOLS ];
 
                   /* Add to the area of this object. */
-                  if(cif[ CCOL_NUMALL   ]) ci[ CCOL_NUMALL ]++;
+                  if( cif[ CCOL_NUMALL ]
+                      || cif[ CCOL_MINX ] || cif[ CCOL_MAXX ]
+                      || cif[ CCOL_MINY ] || cif[ CCOL_MAXY ] )
+                    ci[ CCOL_NUMALL ]++;
                   if(cif[ CCOL_NUMALLXY ])
                     ((uint8_t *)(xybin[*C-1].array))[ pind ] = 1;
 
@@ -461,6 +481,12 @@ parse_clumps(struct mkcatalog_passparams *pp)
                       /* Get "C" the coordinates of this point. */
                       gal_dimension_index_to_coord(O-objects, ndim, dsize, c);
 
+                      /* Position extrema measurements. */
+                      if(cif[ CCOL_MINX ]) ci[CCOL_MINX]=CMIN(CCOL_MINX, 1);
+                      if(cif[ CCOL_MAXX ]) ci[CCOL_MAXX]=CMAX(CCOL_MAXX, 1);
+                      if(cif[ CCOL_MINY ]) ci[CCOL_MINY]=CMIN(CCOL_MINY, 0);
+                      if(cif[ CCOL_MAXY ]) ci[CCOL_MAXY]=CMAX(CCOL_MAXY, 0);
+
                       /* If we need tile-ID, get the tile ID now. */
                       if(tid!=GAL_BLANK_SIZE_T)
                         tid=gal_tile_full_id_from_coord(&p->cp.tl, c);
diff --git a/bin/mkcatalog/ui.c b/bin/mkcatalog/ui.c
index e418f68..10d1595 100644
--- a/bin/mkcatalog/ui.c
+++ b/bin/mkcatalog/ui.c
@@ -774,6 +774,10 @@ ui_necessary_inputs(struct mkcatalogparams *p, int 
*values, int *sky,
           case CCOL_GXX:              /* Only clump labels. */     break;
           case CCOL_GYY:              /* Only clump labels. */     break;
           case CCOL_GXY:              /* Only clump labels. */     break;
+          case CCOL_MINX:             /* Only clump labels. */     break;
+          case CCOL_MAXX:             /* Only clump labels. */     break;
+          case CCOL_MINY:             /* Only clump labels. */     break;
+          case CCOL_MAXY:             /* Only clump labels. */     break;
           case CCOL_UPPERLIMIT_B:     *values        = 1;          break;
           case CCOL_UPPERLIMIT_S:     *values        = 1;          break;
           case CCOL_UPPERLIMIT_Q:     *values        = 1;          break;
diff --git a/bin/mkcatalog/ui.h b/bin/mkcatalog/ui.h
index 6004fc6..86a4cc2 100644
--- a/bin/mkcatalog/ui.h
+++ b/bin/mkcatalog/ui.h
@@ -116,6 +116,10 @@ enum option_keys_enum
   UI_KEY_CLUMPSGEOX,
   UI_KEY_CLUMPSGEOY,
   UI_KEY_CLUMPSGEOZ,
+  UI_KEY_MINX,
+  UI_KEY_MAXX,
+  UI_KEY_MINY,
+  UI_KEY_MAXY,
   UI_KEY_W1,
   UI_KEY_W2,
   UI_KEY_W3,
diff --git a/doc/gnuastro.en.html b/doc/gnuastro.en.html
index 323e152..b19f9da 100644
--- a/doc/gnuastro.en.html
+++ b/doc/gnuastro.en.html
@@ -122,7 +122,10 @@ review of the Gnuastro's building and installation 
commands.</p>
 <p>Gnuastro only has three mandatory
 dependencies: <a href="manual/html_node/GNU-Scientific-Library.html">GNU
 Scientific
-Library</a>, <a href="manual/html_node/CFITSIO.html">CFITSIO</a>, <a 
href="manual/html_node/WCSLIB.html">WCSLIB</a>.</p>
+Library</a>, <a href="manual/html_node/CFITSIO.html">CFITSIO</a>, <a 
href="manual/html_node/WCSLIB.html">WCSLIB</a>.<br />See <a 
href="manual/html_node/Dependencies-from-package-managers.html">Dependencies
+from package managers</a> for easy installation of Gnuastro's dependencies
+using tools like <code>apt-get</code>, <code>dnf</code>
+(or <code>yum</code>), <code>pacman</code> or <code>brew</code>.</p>
 
 <p>For a more detailed description, see
 the <a href="manual/html_node/Installation.html">Installation</a> chapter
diff --git a/doc/gnuastro.fr.html b/doc/gnuastro.fr.html
index 5705db3..62ba52e 100644
--- a/doc/gnuastro.fr.html
+++ b/doc/gnuastro.fr.html
@@ -118,7 +118,13 @@ h3 { clear: both; }
 <p>Gnuastro n'a que trois dépendances obligatoires&nbsp;:
   <a href="manual/html_node/GNU-Scientific-Library.html">GNU Scientific
   Library</a>, <a href="manual/html_node/CFITSIO.html">CFITSIO</a> et
-  <a href="manual/html_node/WCSLIB.html">WCSLIB</a>.</p>
+  <a href="manual/html_node/WCSLIB.html">WCSLIB</a>.<br />Dans le
+  chapitre <a 
href="manual/html_node/Dependencies-from-package-managers.html">Dépendances
+  des gestionnaires de paquets</a> vous trouverez les commandes pour une
+  installation facile des dépendances de Gnuastro en utilisant des
+  logiciels comme <code>apt-get</code>, <code>dnf</code>
+  (ou <code>yum</code>),
+  <code>pacman</code> ou <code>brew</code>.</p>
 
 <p>Dans le chapitre <cite><a href="manual/html_node/Installation.html">
   Installation</a></cite>, vous trouverez des explications complètes sur
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 8fbbcf8..061dab9 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -11811,6 +11811,52 @@ Convert the type of the popped operand to 64-bit 
(double precision)
 floating point (see @ref{Numeric data types}). The internal conversion of C
 will be used.
 
+@item set-AAA
+Set a name (all characters after the dash, @code{AAA} in the case shown
+here) for the first popped operand on the stack. The name can be any
+string, but avoid strings ending with standard filename suffixes (for
+example @file{.fits})@footnote{A dataset name like @file{a.fits} (which can
+be set with @command{set-a.fits}) will cause confusion in the the initial
+parser of Arithmetic. It will assume this name is a FITS file, and if it is
+used multiple times, Arithmetic will abort, complaining that you haven't
+provided enough HDUs.}. The named dataset will be freed from memory as soon
+as it is no longer needed in the rest of the command. This operator thus
+enables re-usability of a dataset without having to re-read it from a file
+everytime its necessary during a process.
+
+The name to give the popped dataset is part of the operator's name. For
+example the @code{set-a} operator of the command below, gives the name of
+``@code{a}'' to the contents of @file{image.fits}. This name is then used
+instead of the actual filename to multiply the dataset by two.
+
+@example
+$ astarithmetic image.fits set-a a 2 x
+@end example
+
+This is a unique operator, because it doesn't actually do anything to the
+contents of the popped dataset, it just assigns a name to the dataset. This
+makes it very easy to use a single dataset on the command-line multiple
+times and avoid extra attempts at reading it into memory.
+
+One example of the usefulness of this operator is in the @code{where}
+operator. For example, let's assume you want to mask all pixels larger than
+@code{5} in @file{image.fits} (extension number 1) with a NaN
+value. Without using this operator, you have to run
+
+@example
+$ astarithmetic image.fits image.fits 5 gt nan where -g1
+@end example
+
+But with this operator you can simply give @file{image.fits} the name
+@code{i} and simplify the command above:
+
+@example
+$ astarithmetic image.fits set-i   i i 5 gt nan where
+@end example
+
+This operator can thus help simplify reading/writing on the command-line
+(avoid potential bugs), while also speeding up your processing.
+
 @end table
 
 @cartouche
@@ -18092,6 +18138,18 @@ their pixel values.
 The geometric center of all objects and clumps along the second FITS axis
 axis, see @option{--geox}.
 
+@item --minx
+The minimum position of all objects and clumps along the first FITS axis.
+
+@item --maxx
+The maximum position of all objects and clumps along the first FITS axis.
+
+@item --miny
+The minimum position of all objects and clumps along the second FITS axis.
+
+@item --maxy
+The maximum position of all objects and clumps along the second FITS axis.
+
 @item --clumpsx
 [Objects] The flux weighted center of all the clumps in this object along
 the first FITS axis. See @option{--x}.
@@ -22394,10 +22452,10 @@ are fixed width types, these types are portable to 
all systems and are
 defined in the standard C header @file{stdint.h}. You don't need to include
 this header, it is included by any Gnuastro header that deals with the
 different types. However, the most commonly used types in a C (or C++)
-program (for example @code{int} or @code{long} are not defined by their
-exact width (storage), but by their minimum storage. So for example on some
-systems, @code{int} may be 2 bytes (16-bits, the minimum required by the
-standard) and on others it may be 4 bytes (32-bits, common in modern
+program (for example @code{int} or @code{long}) are not defined by their
+exact width (storage size), but by their minimum storage. So for example on
+some systems, @code{int} may be 2 bytes (16-bits, the minimum required by
+the standard) and on others it may be 4 bytes (32-bits, common in modern
 systems).
 
 With every type, a unique ``blank'' value (or place holder showing the
@@ -24342,6 +24400,12 @@ Return 1 if the given file name corresponds to one of 
the recognized file
 types for reading arrays.
 @end deftypefun
 
+@deftypefun int gal_array_name_recognized_multiext (char @code{*filename})
+Return 1 if the given file name corresponds to one of the recognized file
+types for reading arrays which may contain multiple extesions (for example
+FITS or TIFF) formats.
+@end deftypefun
+
 @deftypefun gal_data_t gal_array_read (char @code{*filename}, char 
@code{*extension}, size_t @code{minmapsize})
 Read the array within the given extension (@code{extension}) of
 @code{filename}. If the array is larger than @code{minmapsize} bytes, then
@@ -24677,9 +24741,9 @@ One important issue to consider is that CFITSIO's types 
are not fixed width
 (for example @code{long} may be 32-bits or 64-bits on different
 systems). However, Gnuastro's types are defined by their width. These
 functions will use information on the host system to do the proper
-conversion, so it strongly recommended to use these functions for
-portability of your code and not to assume a fixed correspondence between
-CFITSIO and Gnuastro's types.
+conversion. To have a portable (usable on different systems) code, is thus
+recommended to use these functions and not to assume a fixed correspondence
+between CFITSIO and Gnuastro's types.
 
 @deftypefun uint8_t gal_fits_bitpix_to_type (int @code{bitpix})
 Return the Gnuastro type identifier that corresponds to CFITSIO's
@@ -28693,7 +28757,7 @@ language, but it can be considered one of the 
lowest-level languages among
 all high-level languages.} (closer to the hardware), it is much less
 complex for both the human reader @emph{and} the computer. The benefits of
 simplicity for a human were discussed above. Simplicity for the computer
-translates into more efficiently (faster) programs. This creates a much
+translates into more efficient (faster) programs. This creates a much
 closer relation between the scientist/programmer (or their program) and the
 actual data and processing. The GNU coding
 standards@footnote{@url{http://www.gnu.org/prep/standards/}} also encourage
diff --git a/lib/array.c b/lib/array.c
index 0aa708e..6c63afc 100644
--- a/lib/array.c
+++ b/lib/array.c
@@ -48,9 +48,27 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 int
 gal_array_name_recognized(char *name)
 {
+  if( gal_array_name_recognized_multiext(name) ) return 1;
+  else if ( gal_jpeg_name_is_jpeg(name)        ) return 1;
+  else                                           return 0;
+
+  /* Control should not get to here, but just to avoid compiler warnings,
+     we'll return a NULL. */
+  error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to solve the "
+        "problem. Control must not reach the end of this function", __func__,
+        PACKAGE_BUGREPORT);
+  return 0;
+}
+
+
+
+
+
+int
+gal_array_name_recognized_multiext(char *name)
+{
   if(       gal_fits_name_is_fits(name) ) return 1;
   else if ( gal_tiff_name_is_tiff(name) ) return 1;
-  else if ( gal_jpeg_name_is_jpeg(name) ) return 1;
   else                                    return 0;
 
   /* Control should not get to here, but just to avoid compiler warnings,
diff --git a/lib/gnuastro/array.h b/lib/gnuastro/array.h
index aaff1fd..faff5f2 100644
--- a/lib/gnuastro/array.h
+++ b/lib/gnuastro/array.h
@@ -55,6 +55,9 @@ __BEGIN_C_DECLS  /* From C++ preparations */
 int
 gal_array_name_recognized(char *name);
 
+int
+gal_array_name_recognized_multiext(char *name);
+
 gal_data_t *
 gal_array_read(char *filename, char *extension, size_t minmapsize);
 



reply via email to

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