gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 5c1860f 1/3: MakeCatalog can calculate the med


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 5c1860f 1/3: MakeCatalog can calculate the median value
Date: Fri, 23 Feb 2018 10:00:24 -0500 (EST)

branch: master
commit 5c1860f969e3988962c55a41e907847163e26743
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    MakeCatalog can calculate the median value
    
    For calculating the surface brightness limit of extended and diffuse
    objects, the average (brightness/area) can be too strongly affected by
    outliers. So MakeCatalogs will now also calculate the median of pixel
    values.
---
 NEWS                      |   3 ++
 bin/mkcatalog/args.h      |  16 +++++-
 bin/mkcatalog/columns.c   |  29 +++++++++++
 bin/mkcatalog/main.h      |   6 ++-
 bin/mkcatalog/mkcatalog.c | 125 +++++++++++++++++++++++++++++++++++++++++++++-
 bin/mkcatalog/ui.h        |   1 +
 doc/gnuastro.texi         |  37 +++++++-------
 7 files changed, 196 insertions(+), 21 deletions(-)

diff --git a/NEWS b/NEWS
index 19c3ca3..b0ae1d5 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,9 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
   cumulative frequency plots to be set outside the minimum or maximum
   values of the dataset.
 
+  MakeCatalog: The new `--median' option will calculate the median pixel
+  value within an object or clump.
+
 ** Removed features
 
 ** Changed features
diff --git a/bin/mkcatalog/args.h b/bin/mkcatalog/args.h
index 53b67ae..7bd1cb1 100644
--- a/bin/mkcatalog/args.h
+++ b/bin/mkcatalog/args.h
@@ -703,6 +703,20 @@ struct argp_option program_options[] =
       ui_column_codes_ll
     },
     {
+      "median",
+      UI_KEY_MEDIAN,
+      0,
+      0,
+      "Median of values in object/clump.",
+      UI_GROUP_COLUMNS_BRIGHTNESS,
+      0,
+      GAL_TYPE_INVALID,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET,
+      ui_column_codes_ll
+    },
+    {
       "magnitude",
       UI_KEY_MAGNITUDE,
       0,
@@ -846,7 +860,7 @@ struct argp_option program_options[] =
 
 
 
-    /* Morphology/shapre related columns. */
+    /* Morphology/shape related columns. */
     {
       0, 0, 0, 0,
       "Morphology/shape related columns",
diff --git a/bin/mkcatalog/columns.c b/bin/mkcatalog/columns.c
index fcfa30c..3cdb618 100644
--- a/bin/mkcatalog/columns.c
+++ b/bin/mkcatalog/columns.c
@@ -660,6 +660,24 @@ columns_define_alloc(struct mkcatalogparams *p)
           ciflag[ CCOL_SUM ] = 1;
           break;
 
+        case UI_KEY_MEDIAN:
+          name           = "MEDIAN";
+          unit           = p->input->unit ? p->input->unit : "pixelunit";
+          ocomment       = "Median of sky subtracted values.";
+          ccomment       = "Median of pixels subtracted by rivers.";
+          otype          = GAL_TYPE_FLOAT32;
+          ctype          = GAL_TYPE_FLOAT32;
+          disp_fmt       = GAL_TABLE_DISPLAY_FMT_GENERAL;
+          disp_width     = 10;
+          disp_precision = 4;
+          oiflag[ OCOL_MEDIAN  ] = 1;
+          oiflag[ OCOL_NUMALL  ] = 1;
+          ciflag[ CCOL_MEDIAN  ] = 1;
+          ciflag[ CCOL_NUMALL  ] = 1;
+          ciflag[ CCOL_RIV_NUM ] = 1;
+          ciflag[ CCOL_RIV_SUM ] = 1;
+          break;
+
         case UI_KEY_MAGNITUDE:
           name           = "MAGNITUDE";
           unit           = "log";
@@ -1357,6 +1375,12 @@ columns_fill(struct mkcatalog_passparams *pp)
                                       : NAN );
           break;
 
+        case UI_KEY_MEDIAN:
+          ((float *)colarr)[oind] = ( oi[ OCOL_NUM ]>0.0f
+                                      ? oi[ OCOL_MEDIAN ]
+                                      : NAN );
+          break;
+
         case UI_KEY_MAGNITUDE:
           ((float *)colarr)[oind] = MKC_MAG(oi[ OCOL_SUM ]);
           break;
@@ -1515,6 +1539,11 @@ columns_fill(struct mkcatalog_passparams *pp)
                                         ? ci[ CCOL_SUM ] : NAN );
             break;
 
+          case UI_KEY_MEDIAN:
+            ((float *)colarr)[cind] = ( ci[ CCOL_NUM ]>0.0f
+                                        ? ci[ CCOL_MEDIAN ] : NAN );
+            break;
+
           case UI_KEY_MAGNITUDE: /* Similar: brightness for clumps */
             tmp = ( ci[ CCOL_RIV_NUM ]
                     ? ci[ CCOL_RIV_SUM ]/ci[ CCOL_RIV_NUM ]*ci[ CCOL_NUM ]
diff --git a/bin/mkcatalog/main.h b/bin/mkcatalog/main.h
index 477cc7f..0792db4 100644
--- a/bin/mkcatalog/main.h
+++ b/bin/mkcatalog/main.h
@@ -69,6 +69,7 @@ enum objectcols
     OCOL_NUMALL,         /* Number of all pixels with this label.     */
     OCOL_NUM,            /* Number of pixels above threshold.         */
     OCOL_SUM,            /* Sum of (value-sky) in object.             */
+    OCOL_MEDIAN,         /* Median of value in object.                */
     OCOL_VX,             /* Sum of (value-sky) * x.                   */
     OCOL_VY,             /* Sum of (value-sky) * y.                   */
     OCOL_SX,             /* Shift along X axis.                       */
@@ -88,7 +89,7 @@ enum objectcols
     OCOL_UPPERLIMIT_B,   /* Upper limit magnitude.                    */
     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.             */
+    OCOL_C_SUM,          /* Brightness in object clumps.              */
     OCOL_C_VX,           /* Sum of (value-sky)*x on clumps.           */
     OCOL_C_VY,           /* Sum of (value-sky)*y on obj. clumps.      */
     OCOL_C_GX,           /* Geometric center of clumps in object X.   */
@@ -109,6 +110,7 @@ enum clumpcols
     CCOL_VYY,            /* Sum of flux*y*y of this clump.            */
     CCOL_VXY,            /* Sum of flux*x*y of this clump.            */
     CCOL_SUM,            /* River subtracted brightness.              */
+    CCOL_MEDIAN,         /* Median of values in clump.                */
     CCOL_RIV_SUM,        /* Sum of rivers around clump.               */
     CCOL_RIV_NUM,        /* Num river pixels around this clump.       */
     CCOL_SUMSKY,         /* Sum of sky value on this object.          */
@@ -156,7 +158,7 @@ struct mkcatalogparams
   char            *upmaskfile;  /* Name of upper limit mask file.       */
   char             *upmaskhdu;  /* HDU of upper limit mask file.        */
   size_t                upnum;  /* Number of upper-limit random samples.*/
-  size_t             *uprange;  /* Range of random positions about target. */
+  size_t             *uprange;  /* Range of random positions about target.*/
   uint8_t             envseed;  /* Use the environment for random seed. */
   double       upsigmaclip[2];  /* Sigma clip to measure upper limit.   */
   float              upnsigma;  /* Multiple of sigma to define up-lim.  */
diff --git a/bin/mkcatalog/mkcatalog.c b/bin/mkcatalog/mkcatalog.c
index 08cdded..3f9ea99 100644
--- a/bin/mkcatalog/mkcatalog.c
+++ b/bin/mkcatalog/mkcatalog.c
@@ -37,6 +37,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <gnuastro/fits.h>
 #include <gnuastro/threads.h>
 #include <gnuastro/dimension.h>
+#include <gnuastro/statistics.h>
 
 #include <gnuastro-internal/timing.h>
 
@@ -405,6 +406,124 @@ mkcatalog_second_pass(struct mkcatalog_passparams *pp)
 
 
 
+static void
+mkcatalog_median_pass(struct mkcatalog_passparams *pp)
+{
+  struct mkcatalogparams *p=pp->p;
+  size_t ndim=p->input->ndim, *dsize=p->input->dsize;
+
+  double *ci;
+  gal_data_t *median;
+  int32_t *O, *C=NULL;
+  gal_data_t **clumpsmed=NULL;
+  float ss, *I, *II, *SK, *ST;
+  size_t i, increment=0, num_increment=1;
+  size_t counter=0, *ccounter=NULL, tsize=pp->oi[OCOL_NUMALL];
+  gal_data_t *objmed=gal_data_alloc(NULL, p->input->type, 1, &tsize, NULL, 0,
+                                    p->cp.minmapsize, NULL, NULL, NULL);
+
+  /* A small sanity check. */
+  if(p->input->type!=GAL_TYPE_FLOAT32)
+    error(EXIT_FAILURE, 0, "%s: the input has to be float32 type", __func__);
+
+
+  /* Allocate space for the clump medians. */
+  if(p->clumps)
+    {
+      errno=0;
+      clumpsmed=malloc(pp->clumpsinobj * sizeof *clumpsmed);
+      if(clumpsmed==NULL)
+        error(EXIT_FAILURE, errno, "%s: couldn't allocate `clumpsmed' for "
+              "%zu clumps", __func__, pp->clumpsinobj);
+
+
+      /* Allocate the array necessary to keep the values of each clump. */
+      ccounter=gal_data_calloc_array(GAL_TYPE_SIZE_T, pp->clumpsinobj,
+                                     __func__, "ccounter");
+      for(i=0;i<pp->clumpsinobj;++i)
+        {
+          tsize=pp->ci[ i * CCOL_NUMCOLS + CCOL_NUMALL ];
+          clumpsmed[i]=gal_data_alloc(NULL, p->input->type, 1, &tsize, NULL,
+                                      0, p->cp.minmapsize, NULL, NULL, NULL);
+        }
+    }
+
+
+  /* Parse each contiguous patch of memory covered by this object. */
+  while( pp->start_end_inc[0] + increment <= pp->start_end_inc[1] )
+    {
+      /* Set the contiguous range to parse, we will check the count
+         over the `I' pointer and just increment the rest. */
+      O  = pp->st_o   + increment;
+      SK = pp->st_sky + increment;
+      ST = pp->st_std + increment;
+      if(p->clumps) C = pp->st_c + increment;
+      II = ( I = pp->st_i + increment ) + pp->tile->dsize[ndim-1];
+
+      /* Parse the next contiguous region of this tile. */
+      do
+        {
+          /* If this pixel belongs to the requested object, is a clumps and
+             isn't NAN, then do the processing. `hasblank' is constant, so
+             when the input doesn't have any blank values, the `isnan' will
+             never be checked. */
+          if( *O==pp->object && !isnan(*I) )
+            {
+              /* Copy the value for the whole object. */
+              ss = *I - *SK;
+              memcpy( gal_data_ptr_increment(objmed->array, counter++,
+                                             p->input->type),
+                      &ss, gal_type_sizeof(p->input->type) );
+
+              /* We are also on a clump. */
+              if(p->clumps && *C>0)
+                memcpy( gal_data_ptr_increment(clumpsmed[*C-1]->array,
+                                               ccounter[*C-1]++,
+                                               p->input->type),
+                        &ss, gal_type_sizeof(p->input->type) );
+            }
+
+          /* Increment the other pointers. */
+          ++O; ++SK; ++ST; if(p->clumps) ++C;
+        }
+      while(++I<II);
+
+      /* Increment to the next contiguous region of this tile. */
+      increment += ( gal_tile_block_increment(p->input, dsize,
+                                              num_increment++, NULL) );
+    }
+
+
+  /* Calculate the final medians for objects. */
+  median=gal_data_copy_to_new_type_free(gal_statistics_median(objmed, 1),
+                                        GAL_TYPE_FLOAT64);
+  pp->oi[OCOL_MEDIAN]=*((double *)(median->array));
+  gal_data_free(objmed);
+  gal_data_free(median);
+
+
+  /* Calculate the median for clumps. */
+  if(p->clumps)
+    {
+      for(i=0;i<pp->clumpsinobj;++i)
+        {
+          ci=&pp->ci[ i * CCOL_NUMCOLS ];
+          median=gal_statistics_median(clumpsmed[i], 1);
+          median=gal_data_copy_to_new_type_free(median, GAL_TYPE_FLOAT64);
+          ci[ CCOL_MEDIAN ] = ( *((double *)(median->array))
+                                - (ci[ CCOL_RIV_SUM ]/ci[ CCOL_RIV_NUM ]) );
+          gal_data_free(clumpsmed[i]);
+          gal_data_free(median);
+        }
+      free(clumpsmed);
+      free(ccounter);
+    }
+}
+
+
+
+
+
 
 
 
@@ -492,7 +611,7 @@ mkcatalog_single_object(void *in_prm)
       mkcatalog_first_pass(&pp);
 
       /* Currently the second pass is only necessary when there is a clumps
-         image. */
+         image or the median is requested. */
       if(p->clumps)
         {
           /* Allocate space for the properties of each clump. */
@@ -509,6 +628,10 @@ mkcatalog_single_object(void *in_prm)
           mkcatalog_second_pass(&pp);
         }
 
+      /* If the median is requested, another pass is necessary. */
+      if( p->oiflag[ OCOL_MEDIAN ] )
+        mkcatalog_median_pass(&pp);
+
       /* Calculate the upper limit magnitude (if necessary). */
       if(p->upperlimit) upperlimit_calculate(&pp);
 
diff --git a/bin/mkcatalog/ui.h b/bin/mkcatalog/ui.h
index e5f6d15..27da86c 100644
--- a/bin/mkcatalog/ui.h
+++ b/bin/mkcatalog/ui.h
@@ -115,6 +115,7 @@ enum option_keys_enum
   UI_KEY_CLUMPSGEOW2,
   UI_KEY_CLUMPSBRIGHTNESS,
   UI_KEY_NORIVERBRIGHTNESS,
+  UI_KEY_MEDIAN,
   UI_KEY_CLUMPSMAGNITUDE,
   UI_KEY_UPPERLIMIT,
   UI_KEY_RIVERAVE,
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index a4b380d..58d61f3 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -15046,7 +15046,7 @@ variable to the @code{mkcatalogparams} structure.
 
 @item ui.h
 The @code{option_keys_enum} associates a unique value for each option to
-MakeProfiles. The options that have a short option version, the single
+MakeCatalog. The options that have a short option version, the single
 character short comment is used for the value. Those that don't have a
 short option version, get a large integer automatically. You should add a
 variable here to identify your desired column.
@@ -15066,15 +15066,14 @@ sanity checks and preparations for it here. 
Otherwise, you can ignore this
 file.
 
 @item columns.c
-This file will contain the main definition and high-level calculation of
-your new column through the @code{columns_define_alloc} and
address@hidden functions. In the first, you specify the basic
-information about the column: its name, units, comments, type (see
address@hidden data types}) and how it should be printed if the output is a
-text file. You should also specify the raw/internal columns that are
-necessary for this column here as the many existing examples show. Through
-the types for objects and rows, you can specify if this column is only for
-clumps, objects or both.
+This file contains the main definition and high-level calculation of your
+new column through the @code{columns_define_alloc} and @code{columns_fill}
+functions. In the first, you specify the basic information about the
+column: its name, units, comments, type (see @ref{Numeric data types}) and
+how it should be printed if the output is a text file. You should also
+specify the raw/internal columns that are necessary for this column here as
+the many existing examples show. Through the types for objects and rows,
+you can specify if this column is only for clumps, objects or both.
 
 The second main function (@code{columns_fill}) writes the final value into
 the appropriate column for each object and clump. As you can see in the
@@ -15595,6 +15594,11 @@ usable pixels (blank or below the threshold) are 
present over the clump or
 object, the stored value will be NaN, because zero (note that zero is
 meaningful).
 
address@hidden --median
+The median sky subtracted value of pixels within the object or clump. For
+clumps, the average river flux is subtracted from the sky subtracted
+median.
+
 @item --noriverbrightness
 [Clumps] The Sky (not river) subtracted clump brightness. By definition,
 for the clumps, the average brightness of the rivers surrounding it are
@@ -22707,15 +22711,14 @@ use to access an element of the @code{OTHER} dataset 
(if
 (similar to @code{itype} and @code{INPUT} discussed above). If
 @code{PARSE_OTHER} is non-zero, then @code{o} will also be incremented to
 the same index element but in the other array. You can use these along with
-any other variable you define before this macro to process the input and
-store it in the other.
+any other variable you define before this macro to process the input and/or
+the other.
 
 All variables within this function-like macro begin with @code{tpo_} except
-for the three variables listed above. So as long as you don't start the
-names of your variables with this prefix everything will be fine. Note that
address@hidden (and possibly @code{o}) will be incremented once by this
-function-like macro, so don't increment them within @code{OP}. As a
-summary, the three variables you have access to within @code{OP} are:
+for the three variables listed below. Therefore, as long as you don't start
+the names of your variables with this prefix everything will be fine. Note
+that @code{i} (and possibly @code{o}) will be incremented once by this
+function-like macro, so don't increment them within @code{OP}.
 
 @table @code
 @item i



reply via email to

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