gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 42f0405 2/3: Position in upperlimit distributi


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 42f0405 2/3: Position in upperlimit distribution (sigma and quantile)
Date: Tue, 6 Mar 2018 09:20:21 -0500 (EST)

branch: master
commit 42f040597d9748c083b0fde3d6fa336029ed470a
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Position in upperlimit distribution (sigma and quantile)
    
    Three new options are now added to MakeCatalog: two will allow identifying
    the position of an object or clump within the upper-limit distribution, and
    another can be used to identify the upper limit distribution irrespective
    of the `--upnsigma' value.
    
    Also, while working on the quantile position, I noticed that the fact that
    `gal_statistics_quantile_function' only returned a NaN when the value was
    out of range was not too meaningful (is it smaller than the minimum or
    larger than the maximum for example). So now, it returns `inf' or `-inf' to
    specify in which direction the value is out of range.
---
 NEWS                       |  11 +++++
 bin/mkcatalog/args.h       |  42 +++++++++++++++++
 bin/mkcatalog/columns.c    | 114 +++++++++++++++++++++++++++++++++++---------
 bin/mkcatalog/main.h       |   8 +++-
 bin/mkcatalog/mkcatalog.c  |   2 +-
 bin/mkcatalog/mkcatalog.h  |   4 +-
 bin/mkcatalog/ui.h         |   3 ++
 bin/mkcatalog/upperlimit.c | 115 +++++++++++++++++++++++++++++++++++++--------
 doc/gnuastro.texi          |  33 +++++++++++--
 lib/statistics.c           |  88 +++++++++++++++++++++++++++-------
 10 files changed, 350 insertions(+), 70 deletions(-)

diff --git a/NEWS b/NEWS
index 24a1aaa..0fd4fd6 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,13 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
   MakeCatalog: The new `--mean' and `--median' options will calculate the
   mean and median pixel value within an object or clump respectively.
 
+  MakeCatalog: The new `--upperlimitsigma' and `--upperlimitquantile'
+  columns will report the postion of the object's brightness with respect
+  to the distribution of randomly measured values. The former as a multiple
+  of sigma and the latter as a quantile. Also, `--upperlimitonesigma' will
+  return the 1-sigma value of the randomly placed upper limit magnitudes
+  (irrespective of the value given to `--upnsigma').
+
   NoiseChisel: a value of `none' to the `--kernel' option will disable
   convolution.
 
@@ -19,6 +26,10 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
 
 ** Changed features
 
+  Libraries: `gal_statistics_quantile_function' returns `inf' or `-inf' if
+  the given value is smaller than the minimum or larger than the maximum of
+  the input dataset's range.
+
 ** Bug fixes
 
   Many unused result warnings for asprintf in some compilers (bug #52979).
diff --git a/bin/mkcatalog/args.h b/bin/mkcatalog/args.h
index c3a4a04..3a547fe 100644
--- a/bin/mkcatalog/args.h
+++ b/bin/mkcatalog/args.h
@@ -801,6 +801,48 @@ struct argp_option program_options[] =
       ui_column_codes_ll
     },
     {
+      "upperlimitonesigma",
+      UI_KEY_UPPERLIMITONESIGMA,
+      0,
+      0,
+      "Upper-limit one sigma value.",
+      UI_GROUP_COLUMNS_BRIGHTNESS,
+      0,
+      GAL_TYPE_INVALID,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET,
+      ui_column_codes_ll
+    },
+    {
+      "upperlimitsigma",
+      UI_KEY_UPPERLIMITSIGMA,
+      0,
+      0,
+      "Place in upperlimit distribution (sigma multiple).",
+      UI_GROUP_COLUMNS_BRIGHTNESS,
+      0,
+      GAL_TYPE_INVALID,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET,
+      ui_column_codes_ll
+    },
+    {
+      "upperlimitquantile",
+      UI_KEY_UPPERLIMITQUANTILE,
+      0,
+      0,
+      "Quantile in random distribution (max 1).",
+      UI_GROUP_COLUMNS_BRIGHTNESS,
+      0,
+      GAL_TYPE_INVALID,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET,
+      ui_column_codes_ll
+    },
+    {
       "riverave",
       UI_KEY_RIVERAVE,
       0,
diff --git a/bin/mkcatalog/columns.c b/bin/mkcatalog/columns.c
index bb539a7..aa354e5 100644
--- a/bin/mkcatalog/columns.c
+++ b/bin/mkcatalog/columns.c
@@ -275,9 +275,9 @@ columns_define_alloc(struct mkcatalogparams *p)
      smaller domain of raw measurements. So to avoid having to calculate
      something multiple times, each parameter will flag the intermediate
      parameters it requires in these arrays. */
-  oiflag = p->oiflag = gal_data_malloc_array(GAL_TYPE_UINT8, OCOL_NUMCOLS,
+  oiflag = p->oiflag = gal_data_calloc_array(GAL_TYPE_UINT8, OCOL_NUMCOLS,
                                              __func__, "oiflag");
-  ciflag = p->ciflag = gal_data_malloc_array(GAL_TYPE_UINT8, CCOL_NUMCOLS,
+  ciflag = p->ciflag = gal_data_calloc_array(GAL_TYPE_UINT8, CCOL_NUMCOLS,
                                              __func__, "ciflag");
 
   /* Allocate the columns. */
@@ -770,6 +770,45 @@ columns_define_alloc(struct mkcatalogparams *p)
           p->hasmag      = 1;   /* Doesn't need per-pixel calculations. */
           break;
 
+        case UI_KEY_UPPERLIMITONESIGMA:
+          name           = "UPPERLIMIT_ONE_SIGMA";
+          unit           = p->input->unit;
+          ocomment       = "One sigma value of all random measurements.";
+          ccomment       = ocomment;
+          otype          = GAL_TYPE_FLOAT32;
+          ctype          = GAL_TYPE_FLOAT32;
+          disp_fmt       = GAL_TABLE_DISPLAY_FMT_GENERAL;
+          disp_width     = 8;
+          disp_precision = 3;
+          p->upperlimit  = 1;
+          break;
+
+        case UI_KEY_UPPERLIMITSIGMA:
+          name           = "UPPERLIMIT_SIGMA";
+          unit           = "frac";
+          ocomment       = "Place in upperlimit distribution (sigma 
multiple).";
+          ccomment       = ocomment;
+          otype          = GAL_TYPE_FLOAT32;
+          ctype          = GAL_TYPE_FLOAT32;
+          disp_fmt       = GAL_TABLE_DISPLAY_FMT_GENERAL;
+          disp_width     = 8;
+          disp_precision = 3;
+          p->upperlimit  = 1;
+          break;
+
+        case UI_KEY_UPPERLIMITQUANTILE:
+          name           = "UPPERLIMIT_QUANTILE";
+          unit           = "quantile";
+          ocomment       = "Quantile of brightness in random distribution.";
+          ccomment       = ocomment;
+          otype          = GAL_TYPE_FLOAT32;
+          ctype          = GAL_TYPE_FLOAT32;
+          disp_fmt       = GAL_TABLE_DISPLAY_FMT_GENERAL;
+          disp_width     = 8;
+          disp_precision = 3;
+          p->upperlimit  = 1;
+          break;
+
         case UI_KEY_RIVERAVE:
           name           = "RIVER_AVE";
           unit           = p->input->unit ? p->input->unit : "pixelunit";
@@ -1227,6 +1266,27 @@ columns_second_order(struct mkcatalog_passparams *pp, 
double *row,
 
 
 
+/* The clump brightness is needed in several places, so we've defined this
+   function to have an easier code. */
+static double
+columns_clump_brightness(double *ci)
+{
+  double tmp;
+  /* Calculate the river flux over the clump area. But only when rivers are
+     present. When grown clumps are requested, the clumps can fully cover a
+     detection (that has one or no clumps). */
+  tmp = ( ci[ CCOL_RIV_NUM ]>0.0f
+          ? ci[ CCOL_RIV_SUM ]/ci[ CCOL_RIV_NUM ]*ci[ CCOL_NUM ]
+          : 0 );
+
+  /* Subtract it from the clump's brightness. */
+  return ci[ CCOL_NUM ]>0.0f ? (ci[ CCOL_SUM ] - tmp) : NAN;
+}
+
+
+
+
+
 /* 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
@@ -1425,6 +1485,20 @@ columns_fill(struct mkcatalog_passparams *pp)
           ((float *)colarr)[oind] = MKC_MAG(oi[ OCOL_UPPERLIMIT_B ]);
           break;
 
+        case UI_KEY_UPPERLIMITONESIGMA:
+          ((float *)colarr)[oind] = oi[ OCOL_UPPERLIMIT_S ];
+          break;
+
+        case UI_KEY_UPPERLIMITSIGMA:
+          ((float *)colarr)[oind] = ( ( oi[ OCOL_NUM ]>0.0f
+                                        ? oi[ OCOL_SUM ] : NAN )
+                                      / oi[ OCOL_UPPERLIMIT_S ] );
+          break;
+
+        case UI_KEY_UPPERLIMITQUANTILE:
+          ((float *)colarr)[oind] = oi[ OCOL_UPPERLIMIT_Q ];
+          break;
+
         case UI_KEY_SN:
           ((float *)colarr)[oind] = columns_sn(p, oi, 0);
           break;
@@ -1545,17 +1619,7 @@ columns_fill(struct mkcatalog_passparams *pp)
             break;
 
           case UI_KEY_BRIGHTNESS:
-            /* Calculate the river flux over the clump area. But only when
-               rivers are present. When grown clumps are requested, the
-               clumps can fully cover a detection (that has one or no
-               clumps). */
-            tmp = ( ci[ CCOL_RIV_NUM ]>0.0f
-                    ? ci[ CCOL_RIV_SUM ]/ci[ CCOL_RIV_NUM ]*ci[ CCOL_NUM ]
-                    : 0 );
-
-            /* Subtract it from the clump's brightness. */
-            ((float *)colarr)[cind] = ( ci[ CCOL_NUM ]>0.0f
-                                        ? (ci[ CCOL_SUM ] - tmp) : NAN );
+            ((float *)colarr)[cind] = columns_clump_brightness(ci);
             break;
 
           case UI_KEY_NORIVERBRIGHTNESS:
@@ -1564,16 +1628,8 @@ columns_fill(struct mkcatalog_passparams *pp)
             break;
 
           case UI_KEY_MEAN:
-            /* Similar to brightness. */
-            tmp = ( ci[ CCOL_RIV_NUM ]>0.0f
-                    ? ci[ CCOL_RIV_SUM ]/ci[ CCOL_RIV_NUM ]
-                    : 0 );
-
-            /* Subtract it from the clump's mean. */
-            ((float *)colarr)[cind] = ( ci[ CCOL_NUM ]>0.0f
-                                        ? (ci[CCOL_SUM]/ci[CCOL_NUM] - tmp)
-                                        : NAN );
-
+            ((float *)colarr)[cind] = ( columns_clump_brightness(ci)
+                                        /ci[CCOL_NUM] );
             break;
 
           case UI_KEY_MEDIAN:
@@ -1600,6 +1656,18 @@ columns_fill(struct mkcatalog_passparams *pp)
             ((float *)colarr)[cind] = MKC_MAG(ci[ CCOL_UPPERLIMIT_B ]);
             break;
 
+          case UI_KEY_UPPERLIMITONESIGMA:
+            ((float *)colarr)[cind] = ci[ CCOL_UPPERLIMIT_S ];
+            break;
+
+          case UI_KEY_UPPERLIMITSIGMA:
+            ((float *)colarr)[cind] = ( columns_clump_brightness(ci)
+                                        / ci[ CCOL_UPPERLIMIT_S ] );
+
+          case UI_KEY_UPPERLIMITQUANTILE:
+            ((float *)colarr)[cind] = ci[ CCOL_UPPERLIMIT_Q ];
+            break;
+
           case UI_KEY_RIVERAVE:
             ((float *)colarr)[cind] = ( ci[ CCOL_RIV_NUM]
                                         ? ci[ CCOL_RIV_SUM ]/ci[ CCOL_RIV_NUM]
diff --git a/bin/mkcatalog/main.h b/bin/mkcatalog/main.h
index 0792db4..5fb5ed0 100644
--- a/bin/mkcatalog/main.h
+++ b/bin/mkcatalog/main.h
@@ -86,7 +86,9 @@ enum objectcols
     OCOL_GXX,            /* Second order geometric variable: X*X.     */
     OCOL_GYY,            /* Second order geometric variable: Y*Y.     */
     OCOL_GXY,            /* Second order geometric variable: X*Y.     */
-    OCOL_UPPERLIMIT_B,   /* Upper limit magnitude.                    */
+    OCOL_UPPERLIMIT_B,   /* Upper limit brightness.                   */
+    OCOL_UPPERLIMIT_S,   /* Upper limit one-sigma value.              */
+    OCOL_UPPERLIMIT_Q,   /* Quantile of object in random distribution.*/
     OCOL_C_NUMALL,       /* Value independent no. of pixels in clumps.*/
     OCOL_C_NUM,          /* Area of clumps in this object.            */
     OCOL_C_SUM,          /* Brightness in object clumps.              */
@@ -122,7 +124,9 @@ enum clumpcols
     CCOL_GXX,            /* Second order geometric moment.            */
     CCOL_GYY,            /* Second order geometric moment.            */
     CCOL_GXY,            /* Second order geometric moment.            */
-    CCOL_UPPERLIMIT_B,   /* Upper limit magnitude.                    */
+    CCOL_UPPERLIMIT_B,   /* Upper limit brightness.                   */
+    CCOL_UPPERLIMIT_S,   /* Upper limit one-sigma value.              */
+    CCOL_UPPERLIMIT_Q,   /* Quantile of object in random distribution.*/
 
     CCOL_NUMCOLS,        /* SHOULD BE LAST: total number of columns.  */
   };
diff --git a/bin/mkcatalog/mkcatalog.c b/bin/mkcatalog/mkcatalog.c
index 517e8ce..29e0ae7 100644
--- a/bin/mkcatalog/mkcatalog.c
+++ b/bin/mkcatalog/mkcatalog.c
@@ -612,7 +612,7 @@ mkcatalog_single_object(void *in_prm)
       mkcatalog_first_pass(&pp);
 
       /* Currently the second pass is only necessary when there is a clumps
-         image or the median is requested. */
+         image. */
       if(p->clumps)
         {
           /* Allocate space for the properties of each clump. */
diff --git a/bin/mkcatalog/mkcatalog.h b/bin/mkcatalog/mkcatalog.h
index 959b309..4e93c35 100644
--- a/bin/mkcatalog/mkcatalog.h
+++ b/bin/mkcatalog/mkcatalog.h
@@ -33,11 +33,11 @@ struct mkcatalog_passparams
   gal_data_t          *tile;    /* The tile to pass-over.               */
   float               *st_i;    /* Starting pointer for input image.    */
   int32_t             *st_o;    /* Starting pointer for objects image.  */
-  int32_t             *st_c;    /* Starting pointer for objects image.  */
+  int32_t             *st_c;    /* Starting pointer for clumps image.   */
   float             *st_sky;    /* Starting pointer for input image.    */
   float             *st_std;    /* Starting pointer for input image.    */
   size_t   start_end_inc[2];    /* Starting and ending indexs.          */
-  size_t             *shift;    /* Shift coordinates for coordinates.   */
+  size_t             *shift;    /* Shift coordinates.                   */
   gsl_rng              *rng;    /* Random number generator.             */
   size_t    clumpstartindex;    /* Clump starting row in final catalog. */
   gal_data_t       *up_vals;    /* Container for upper-limit values.    */
diff --git a/bin/mkcatalog/ui.h b/bin/mkcatalog/ui.h
index 4586527..c161970 100644
--- a/bin/mkcatalog/ui.h
+++ b/bin/mkcatalog/ui.h
@@ -119,6 +119,9 @@ enum option_keys_enum
   UI_KEY_MEDIAN,
   UI_KEY_CLUMPSMAGNITUDE,
   UI_KEY_UPPERLIMIT,
+  UI_KEY_UPPERLIMITONESIGMA,
+  UI_KEY_UPPERLIMITSIGMA,
+  UI_KEY_UPPERLIMITQUANTILE,
   UI_KEY_RIVERAVE,
   UI_KEY_RIVERNUM,
   UI_KEY_SKY,
diff --git a/bin/mkcatalog/upperlimit.c b/bin/mkcatalog/upperlimit.c
index c767888..645f695 100644
--- a/bin/mkcatalog/upperlimit.c
+++ b/bin/mkcatalog/upperlimit.c
@@ -34,6 +34,8 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <gnuastro/statistics.h>
 
 #include "main.h"
+
+#include "ui.h"
 #include "mkcatalog.h"
 
 
@@ -263,17 +265,103 @@ upperlimit_random_position(struct mkcatalog_passparams 
*pp, gal_data_t *tile,
 
 
 
-static double
+/* Given the distribution of values, do the upper-limit calculations. */
+static void
+upperlimit_measure(struct mkcatalog_passparams *pp, int32_t clumplab,
+                   int do_measurement)
+{
+  float *scarr;
+  gal_data_t *column;
+  size_t init_size, col, one=1;
+  struct mkcatalogparams *p=pp->p;
+  gal_data_t *sigclip=NULL, *sum, *qfunc;
+  double *o = ( clumplab
+                ? &pp->ci[ (clumplab-1) * CCOL_NUMCOLS ]
+                : pp->oi );
+
+  /* If the random distribution exsits, then fill it in. */
+  if(do_measurement)
+    {
+      /* These columns are for both objects and clumps, so if they are
+         requested in objects, they will also be written for clumps here
+         (the order is irrelevant here). */
+      for(column=p->objectcols; column!=NULL; column=column->next)
+        {
+          switch(column->status)
+            {
+            /* Columns that depend on the sigma of the distribution. */
+            case UI_KEY_UPPERLIMIT:
+            case UI_KEY_UPPERLIMITMAG:
+            case UI_KEY_UPPERLIMITONESIGMA:
+
+              /* We only need to do this once. */
+              if(sigclip==NULL)
+                {
+                  /* Calculate the sigma-clipped standard deviation. Since
+                     it is done in place, the size will change, so we'll
+                     keep the size here and put it back after we are
+                     done. */
+                  init_size=pp->up_vals->size;
+                  sigclip=gal_statistics_sigma_clip(pp->up_vals,
+                                                    p->upsigmaclip[0],
+                                                    p->upsigmaclip[1], 1, 1);
+                  pp->up_vals->size=pp->up_vals->dsize[0]=init_size;
+                  scarr=sigclip->array;
+
+                  /* Write the raw sigma. */
+                  col = clumplab ? CCOL_UPPERLIMIT_S : OCOL_UPPERLIMIT_S;
+                  o[col] = scarr[3];
+
+                  /* Write the multiple of `upnsigma'. */
+                  col = clumplab ? CCOL_UPPERLIMIT_B : OCOL_UPPERLIMIT_B;
+                  o[col] = scarr[3] * p->upnsigma;
+
+                  /* Clean up. */
+                  gal_data_free(sigclip);
+                }
+              break;
+
+            /* Quantile column. */
+            case UI_KEY_UPPERLIMITQUANTILE:
+
+              /* Similar to the case for sigma-clipping, we'll need to keep
+                 the size here also. */
+              init_size=pp->up_vals->size;
+              sum=gal_data_alloc(NULL, GAL_TYPE_FLOAT32, 1, &one, NULL, 0,
+                                 -1, NULL, NULL, NULL);
+              ((float *)(sum->array))[0]=o[clumplab ? CCOL_SUM : OCOL_SUM];
+              qfunc=gal_statistics_quantile_function(pp->up_vals, sum, 1);
+
+              /* Fill in the column. */
+              col = clumplab ? CCOL_UPPERLIMIT_Q : OCOL_UPPERLIMIT_Q;
+              pp->up_vals->size=pp->up_vals->dsize[0]=init_size;
+              o[col] = ((double *)(qfunc->array))[0];
+              break;
+            }
+        }
+    }
+  else
+    {
+      o[ clumplab ? CCOL_UPPERLIMIT_S : OCOL_UPPERLIMIT_S ] = NAN;
+      o[ clumplab ? CCOL_UPPERLIMIT_B : OCOL_UPPERLIMIT_B ] = NAN;
+      o[ clumplab ? CCOL_UPPERLIMIT_Q : OCOL_UPPERLIMIT_Q ] = NAN;
+    }
+}
+
+
+
+
+
+static void
 upperlimit_one_tile(struct mkcatalog_passparams *pp, gal_data_t *tile,
                     unsigned long seed, int32_t clumplab)
 {
   struct mkcatalogparams *p=pp->p;
   size_t ndim=p->input->ndim, *dsize=p->input->dsize;
 
+  double sum;
   void *tarray;
-  double sum, out;
   int continueparse;
-  gal_data_t *sigclip;
   uint8_t *M=NULL, *st_m=NULL;
   float *uparr=pp->up_vals->array;
   float *I, *II, *SK, *st_i, *st_sky;
@@ -375,19 +463,12 @@ upperlimit_one_tile(struct mkcatalog_passparams *pp, 
gal_data_t *tile,
       ++tcounter;
     }
 
-  /* Calculate the standard deviation of this distribution. */
-  if(counter==p->upnum)
-    {
-      sigclip=gal_statistics_sigma_clip(pp->up_vals, p->upsigmaclip[0],
-                                        p->upsigmaclip[1], 1, 1);
-      out = ((float *)(sigclip->array))[3] * p->upnsigma;
-    }
-  else out=NAN;
+  /* Do the measurement on the random distribution. */
+  upperlimit_measure(pp, clumplab, counter==p->upnum);
 
   /* Reset the tile's array pointer, clean up and return. */
   tile->array=tarray;
   free(rcoord);
-  return out;
 }
 
 
@@ -416,16 +497,14 @@ void
 upperlimit_calculate(struct mkcatalog_passparams *pp)
 {
   size_t i;
-  double *ci;
   unsigned long seed;
   gal_data_t *clumptiles;
   struct mkcatalogparams *p=pp->p;
 
   /* First find the upper limit magnitude for this object. */
-  pp->oi[OCOL_UPPERLIMIT_B] = upperlimit_one_tile(pp, pp->tile,
-                                                  p->seed+pp->object, 0);
+  upperlimit_one_tile(pp, pp->tile, p->seed+pp->object, 0);
 
-  /* If a clumps image is present (a clump catalog is requested( and this
+  /* If a clumps image is present (a clump catalog is requested) and this
      object has clumps, then find the upper limit magnitude for the clumps
      within this object. */
   if(p->clumps && pp->clumpsinobj)
@@ -440,10 +519,8 @@ upperlimit_calculate(struct mkcatalog_passparams *pp)
          IDs. */
       for(i=0;i<pp->clumpsinobj;++i)
         {
-          ci=&pp->ci[ i * CCOL_NUMCOLS ];
           seed = p->seed + p->numobjects + p->numclumps * pp->object + i;
-          ci[CCOL_UPPERLIMIT_B] = upperlimit_one_tile(pp, &clumptiles[i],
-                                                          seed, i+1);
+          upperlimit_one_tile(pp, &clumptiles[i], seed, i+1);
         }
 
       /* Clean up the clump tiles. */
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 137b2ba..c7c15fd 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -15669,13 +15669,34 @@ magnitude settings} for a complete explanation. This 
is very important for
 the fainter and smaller objects in the image where the measured magnitudes
 are not reliable.
 
-
 @item --upperlimitmag
 The upper limit magnitude for this object or clump. See @ref{Quantifying
 measurement limits} and @ref{Upper-limit magnitude settings} for a complete
 explanation. This is very important for the fainter and smaller objects in
 the image where the measured magnitudes are not reliable.
 
address@hidden --upperlimitonesigma
+The @mymath{1\sigma} upper limit value (in units of the input image) for
+this object or clump. See @ref{Quantifying measurement limits} and
address@hidden magnitude settings} for a complete explanation. When
address@hidden, this column's values will be the same as
address@hidden
+
address@hidden --upperlimitsigma
+The position of the total brightness measured within the distribution of
+randomly placed upperlimit measurements in units of the distribution's
address@hidden or standard deviation. See @ref{Quantifying measurement
+limits} and @ref{Upper-limit magnitude settings} for a complete
+explanation.
+
address@hidden --upperlimitquantile
+The position of the total brightness measured within the distribution of
+randomly placed upperlimit measurements as a quantile (value between 0 or
+1). See @ref{Quantifying measurement limits} and @ref{Upper-limit magnitude
+settings} for a complete explanation. If the object is brighter than the
+brightest randomly placed profile, a value of @code{inf} is returned. If it
+is less than the minimum, a value of @code{-inf} is reported.
+
 @item --riverave
 [Clumps] The average brightness of the river pixels around this
 clump. River pixels were defined in Akhlaghi and Ichikawa 2015. In
@@ -23551,16 +23572,18 @@ datatype of the output is the same as @code{input}. 
See
 Return the index of the quantile function (inverse quantile) of
 @code{input} at @code{value}. In other words, this function will return the
 index of the nearest element (of a sorted and non-blank) @code{input} to
address@hidden See @code{gal_statistics_median} for a description of
address@hidden
address@hidden If the value is outside the range of the input, then this
+function will return @code{GAL_BLANK_SIZE_T}.
 @end deftypefun
 
 @deftypefun {gal_data_t *} gal_statistics_quantile_function (gal_data_t 
@code{*input}, gal_data_t @code{*value}, int @code{inplace})
 Return a single-element (@code{double} or @code{float64}) dataset
 containing the quantile function of the non-blank values in @code{input} at
 @code{value}. In other words, this function will return the quantile of
address@hidden in @code{input}. See @code{gal_statistics_median} for a
-description of @code{inplace}.
address@hidden in @code{input}. If the value is smaller than the input's
+smallest element, the returned value will be zero. If the value is larger
+than the input's largest element, then the returned value is 1. See
address@hidden for a description of @code{inplace}.
 @end deftypefun
 
 @deftypefun {gal_data_t *} gal_statistics_mode (gal_data_t @code{*input}, 
float @code{mirrordist}, int @code{inplace})
diff --git a/lib/statistics.c b/lib/statistics.c
index ce71667..6c19f36 100644
--- a/lib/statistics.c
+++ b/lib/statistics.c
@@ -353,29 +353,44 @@ gal_statistics_quantile(gal_data_t *input, double 
quantile, int inplace)
 /* Return the index of the (first) point in the sorted dataset that has the
    closest value to `value' (which has to be the same type as the `input'
    dataset). */
-#define STATS_QFUNC(IT) {                                               \
+#define STATS_QFUNC_IND(IT) {                                           \
     IT *r, *a=nbs->array, *af=a+nbs->size, v=*((IT *)(value->array));   \
                                                                         \
-    /* For a reference. Since we are comparing with the previous. */    \
+    /* For a reference. Since we are comparing with the previous */     \
     /* element, we need to start with the second element.*/             \
     r=a++;                                                              \
                                                                         \
     /* Increasing array: */                                             \
     if( *a < *(a+1) )                                                   \
-      do if(*a>v) { if( v - *(a-1) < *a - v ) --a; break; } while(++a<af); \
+      {                                                                 \
+        if( v>=*r )                                                     \
+          {                                                             \
+            do if(*a>v) { if( v - *(a-1) < *a - v ) --a; break; }       \
+            while(++a<af);                                              \
+            parsed=1;                                                   \
+          }                                                             \
+      }                                                                 \
                                                                         \
     /* Decreasing array. */                                             \
     else                                                                \
-      do if(*a<v) { if( *(a-1) - v < v - *a ) --a; break; } while(++a<af); \
+      {                                                                 \
+        if(v<=*r)                                                       \
+          {                                                             \
+            do if(*a<v) { if( *(a-1) - v < v - *a ) --a; break; }       \
+            while(++a<af);                                              \
+            parsed=1;                                                   \
+          }                                                             \
+      }                                                                 \
                                                                         \
-    /* Set the difference. */                                           \
-    if(a<af) index=a-r;                                                 \
+    /* Set the difference if the value is actually in the range. */     \
+    if(parsed && a<af) index = a-r;                                     \
   }
 size_t
 gal_statistics_quantile_function_index(gal_data_t *input, gal_data_t *value,
                                        int inplace)
 {
-  size_t index=-1;
+  int parsed=0;
+  size_t index=GAL_BLANK_SIZE_T;
   gal_data_t *nbs=gal_statistics_no_blank_sorted(input, inplace);
 
   /* A sanity check. */
@@ -386,16 +401,16 @@ gal_statistics_quantile_function_index(gal_data_t *input, 
gal_data_t *value,
   /* Find the result: */
   switch(nbs->type)
     {
-    case GAL_TYPE_UINT8:     STATS_QFUNC( uint8_t  );     break;
-    case GAL_TYPE_INT8:      STATS_QFUNC( int8_t   );     break;
-    case GAL_TYPE_UINT16:    STATS_QFUNC( uint16_t );     break;
-    case GAL_TYPE_INT16:     STATS_QFUNC( int16_t  );     break;
-    case GAL_TYPE_UINT32:    STATS_QFUNC( uint32_t );     break;
-    case GAL_TYPE_INT32:     STATS_QFUNC( int32_t  );     break;
-    case GAL_TYPE_UINT64:    STATS_QFUNC( uint64_t );     break;
-    case GAL_TYPE_INT64:     STATS_QFUNC( int64_t  );     break;
-    case GAL_TYPE_FLOAT32:   STATS_QFUNC( float    );     break;
-    case GAL_TYPE_FLOAT64:   STATS_QFUNC( double   );     break;
+    case GAL_TYPE_UINT8:     STATS_QFUNC_IND( uint8_t  );     break;
+    case GAL_TYPE_INT8:      STATS_QFUNC_IND( int8_t   );     break;
+    case GAL_TYPE_UINT16:    STATS_QFUNC_IND( uint16_t );     break;
+    case GAL_TYPE_INT16:     STATS_QFUNC_IND( int16_t  );     break;
+    case GAL_TYPE_UINT32:    STATS_QFUNC_IND( uint32_t );     break;
+    case GAL_TYPE_INT32:     STATS_QFUNC_IND( int32_t  );     break;
+    case GAL_TYPE_UINT64:    STATS_QFUNC_IND( uint64_t );     break;
+    case GAL_TYPE_INT64:     STATS_QFUNC_IND( int64_t  );     break;
+    case GAL_TYPE_FLOAT32:   STATS_QFUNC_IND( float    );     break;
+    case GAL_TYPE_FLOAT64:   STATS_QFUNC_IND( double   );     break;
     default:
       error(EXIT_FAILURE, 0, "%s: type code %d not recognized",
             __func__, nbs->type);
@@ -411,12 +426,24 @@ gal_statistics_quantile_function_index(gal_data_t *input, 
gal_data_t *value,
 
 
 /* Return the quantile function of the given value as float64. */
+#define STATS_QFUNC(IT) {                                               \
+    IT *a=nbs->array, v=*((IT *)(value->array));                        \
+                                                                        \
+    /* Increasing array: */                                             \
+    if( *a < *(a+1) )                                                   \
+      d[0] = v<*a ? -INFINITY : INFINITY;                               \
+                                                                        \
+    /* Decreasing array. */                                             \
+    else                                                                \
+      d[0] = v>*a ? INFINITY : -INFINITY;                               \
+  }
 gal_data_t *
 gal_statistics_quantile_function(gal_data_t *input, gal_data_t *value,
                                  int inplace)
 {
   double *d;
   size_t dsize=1;
+  gal_data_t *nbs=gal_statistics_no_blank_sorted(input, inplace);
   gal_data_t *out=gal_data_alloc(NULL, GAL_TYPE_FLOAT64, 1, &dsize,
                                  NULL, 1, -1, NULL, NULL, NULL);
   size_t ind=gal_statistics_quantile_function_index(input, value, inplace);
@@ -424,7 +451,32 @@ gal_statistics_quantile_function(gal_data_t *input, 
gal_data_t *value,
   /* Note that counting of the index starts from 0, so for the quantile we
      should divided by (size - 1). */
   d=out->array;
-  d[0] = ( ind==-1 ? NAN : ((double)ind) / ((double)(input->size - 1)) );
+  if(ind==GAL_BLANK_SIZE_T)
+    {
+      /* See if the value is larger or smaller than the input's minimum or
+         maximum. */
+      switch(nbs->type)
+        {
+        case GAL_TYPE_UINT8:     STATS_QFUNC( uint8_t  );     break;
+        case GAL_TYPE_INT8:      STATS_QFUNC( int8_t   );     break;
+        case GAL_TYPE_UINT16:    STATS_QFUNC( uint16_t );     break;
+        case GAL_TYPE_INT16:     STATS_QFUNC( int16_t  );     break;
+        case GAL_TYPE_UINT32:    STATS_QFUNC( uint32_t );     break;
+        case GAL_TYPE_INT32:     STATS_QFUNC( int32_t  );     break;
+        case GAL_TYPE_UINT64:    STATS_QFUNC( uint64_t );     break;
+        case GAL_TYPE_INT64:     STATS_QFUNC( int64_t  );     break;
+        case GAL_TYPE_FLOAT32:   STATS_QFUNC( float    );     break;
+        case GAL_TYPE_FLOAT64:   STATS_QFUNC( double   );     break;
+        default:
+          error(EXIT_FAILURE, 0, "%s: type code %d not recognized",
+                __func__, nbs->type);
+        }
+    }
+  else
+    d[0] = (double)ind / ((double)(nbs->size - 1));
+
+  /* Clean up and return. */
+  if(nbs!=input) gal_data_free(nbs);
   return out;
 }
 



reply via email to

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