gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 0dbf34e: Library (interpolate): Ability to def


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 0dbf34e: Library (interpolate): Ability to define the nearest-ngb metric
Date: Fri, 22 Feb 2019 22:36:18 -0500 (EST)

branch: master
commit 0dbf34e8125d4abb2d7a381281bacd1de3d44549
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Library (interpolate): Ability to define the nearest-ngb metric
    
    Until now, the nearest neighbor interpolation library would only use the
    Manhattan/taxicab distance between two points. But this could cause small
    `x'-like artifacts in the final result.
    
    With this commit, its also possible to ask for a radial metric. As a
    result, the programs that use this function (Arithmetic, NoiseChisel and
    Statistics) also needed a new option and thus the `interpmetric' was added
    as a tessellation option.
    
    This solution was implemented after a discussion with Ignacio Trujillo.
---
 NEWS                               | 15 +++++++++++-
 bin/arithmetic/arithmetic.c        |  5 ++--
 bin/gnuastro.conf                  |  1 +
 bin/noisechisel/threshold.c        |  5 ++--
 bin/noisechisel/ui.c               |  1 +
 bin/statistics/sky.c               |  5 ++--
 bin/statistics/statistics.c        |  1 +
 bin/statistics/ui.c                |  8 +++---
 doc/gnuastro.texi                  | 21 ++++++++++++++++
 lib/dimension.c                    | 14 ++++++++++-
 lib/gnuastro-internal/commonopts.h | 14 +++++++++++
 lib/gnuastro-internal/options.h    |  6 +++++
 lib/gnuastro/dimension.h           |  5 ++--
 lib/gnuastro/interpolate.h         | 17 +++++++++++--
 lib/interpolate.c                  | 28 +++++++++++++++++----
 lib/options.c                      | 50 ++++++++++++++++++++++++++++++++++++++
 16 files changed, 175 insertions(+), 21 deletions(-)

diff --git a/NEWS b/NEWS
index 92021bd..398d8fb 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,9 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
      different file for reading the WCS of the output. This is useful when
      the default (theh WCS of the first dataset that is read) is not the
      required one.
+   --interpmetric: new option that is necessary with the
+     `interpolate-medianngb' operator. For more, see the description of
+     this option in NoiseChisel.
 
   Fits:
    - Add "title" to group FITS keywords with `--write=/,"title name". This
@@ -51,7 +54,13 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
      columns into one.
 
   NoiseChisel:
-
+   --interpmetric: Set the metric to use to identify the nearest neighbors
+     for tile interpolation (quantile threshold, initial Sky, and final
+     Sky). Until now only the manhattan/taxicab metric was available, which
+     is fast, but could cause 45-degree lines in the interpolation. From
+     this version, with this option, its also possible to use the radial
+     distance (which is now the default). Just note that if there are many
+     tiles over the image, the radial distance will be slower.
    --snthresh: Manually set the signal-to-noise ratio of true
      pseudo-detections. With this option, NoiseChisel will not attempt to
      find pseudo-detections over the noisy regions of the dataset, but will
@@ -67,10 +76,14 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
      --dopening: The number of openings to do after applying `--dthresh'.
      --dopeningngb: The connectivity (4 or 8) to use for `--dopening'.
 
+  Statistics:
+   --interpmetric: Similar to NoiseChisel.
+
   Library:
     GAL_BLANK_LONG: new macro for the `long' type blank value.
     GAL_BLANK_ULONG: new macro for the `unsigned long' type blank value.
     gal_blank_number: Return the number of blank elements in a dataset.
+    gal_dimension_dist_radial: Radial distance between two coordinates.
     gal_statistics_outlier_cumulative: Uses flatness of the cumulative
        distribution to find outliers.
 
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index 68e3912..46ca143 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -728,8 +728,9 @@ arithmetic_interpolate(struct arithmeticparams *p, char 
*token)
   num_int = *((int32_t *)(num->array));
 
   /* Call the interpolation function. */
-  interpolated=gal_interpolate_close_neighbors(in, NULL, num_int,
-                                               p->cp.numthreads, 1, 0);
+  interpolated=gal_interpolate_close_neighbors(in, NULL, p->cp.interpmetric,
+                                               num_int, p->cp.numthreads,
+                                               1, 0);
 
   /* Clean up and push the interpolated array onto the stack. */
   gal_data_free(in);
diff --git a/bin/gnuastro.conf b/bin/gnuastro.conf
index 3652e6a..a901b99 100644
--- a/bin/gnuastro.conf
+++ b/bin/gnuastro.conf
@@ -28,6 +28,7 @@
  numchannels      1,1
  remainderfrac    0.1
  workoverch       0
+ interpmetric     radial
  interpnumngb     9
  interponlyblank  0
 
diff --git a/bin/noisechisel/threshold.c b/bin/noisechisel/threshold.c
index 47dcd19..4fe408a 100644
--- a/bin/noisechisel/threshold.c
+++ b/bin/noisechisel/threshold.c
@@ -282,8 +282,9 @@ threshold_interp_smooth(struct noisechiselparams *p, 
gal_data_t **first,
   /* Do the interpolation of both arrays. */
   (*first)->next = *second;
   if(third) (*second)->next = *third;
-  tmp=gal_interpolate_close_neighbors(*first, tl, cp->interpnumngb,
-                                      cp->numthreads, cp->interponlyblank, 1);
+  tmp=gal_interpolate_close_neighbors(*first, tl, cp->interpmetric,
+                                      cp->interpnumngb, cp->numthreads,
+                                      cp->interponlyblank, 1);
   gal_data_free(*first);
   gal_data_free(*second);
   if(third) gal_data_free(*third);
diff --git a/bin/noisechisel/ui.c b/bin/noisechisel/ui.c
index 318963a..6248748 100644
--- a/bin/noisechisel/ui.c
+++ b/bin/noisechisel/ui.c
@@ -135,6 +135,7 @@ ui_initialize_options(struct noisechiselparams *p,
         case GAL_OPTIONS_KEY_TILESIZE:
         case GAL_OPTIONS_KEY_MINMAPSIZE:
         case GAL_OPTIONS_KEY_NUMCHANNELS:
+        case GAL_OPTIONS_KEY_INTERPMETRIC:
         case GAL_OPTIONS_KEY_INTERPNUMNGB:
         case GAL_OPTIONS_KEY_REMAINDERFRAC:
           cp->coptions[i].mandatory=GAL_OPTIONS_MANDATORY;
diff --git a/bin/statistics/sky.c b/bin/statistics/sky.c
index 6d6a3fe..865cfc4 100644
--- a/bin/statistics/sky.c
+++ b/bin/statistics/sky.c
@@ -220,8 +220,9 @@ sky(struct statisticsparams *p)
   /* Interpolate the Sky and its standard deviation. */
   if(!cp->quiet) gettimeofday(&t1, NULL);
   p->sky_t->next=p->std_t;
-  tmp=gal_interpolate_close_neighbors(p->sky_t, tl, cp->interpnumngb,
-                                      cp->numthreads, cp->interponlyblank, 1);
+  tmp=gal_interpolate_close_neighbors(p->sky_t, tl, cp->interpmetric,
+                                      cp->interpnumngb, cp->numthreads,
+                                      cp->interponlyblank, 1);
   gal_data_free(p->sky_t);
   gal_data_free(p->std_t);
   p->sky_t=tmp;
diff --git a/bin/statistics/statistics.c b/bin/statistics/statistics.c
index c92ca8b..333b432 100644
--- a/bin/statistics/statistics.c
+++ b/bin/statistics/statistics.c
@@ -251,6 +251,7 @@ statistics_interpolate_and_write(struct statisticsparams *p,
       && !(p->cp.interponlyblank && gal_blank_present(values, 1)==0) )
     {
       interpd=gal_interpolate_close_neighbors(values, &cp->tl,
+                                              cp->interpmetric,
                                               cp->interpnumngb,
                                               cp->numthreads,
                                               cp->interponlyblank, 0);
diff --git a/bin/statistics/ui.c b/bin/statistics/ui.c
index dfa3c21..4e1c7d4 100644
--- a/bin/statistics/ui.c
+++ b/bin/statistics/ui.c
@@ -418,10 +418,10 @@ ui_read_check_only_options(struct statisticsparams *p)
     {
       /* Mandatory options. */
       if( isnan(p->meanmedqdiff) || isnan(p->sclipparams[0])
-          || p->cp.interpnumngb==0 )
-        error(EXIT_FAILURE, 0, "`--meanmedqdiff', `--sclipparams' and "
-              "`--interpnumngb' are mandatory when requesting Sky "
-              "measurement (`--sky')");
+          || p->cp.interpmetric==0 || p->cp.interpnumngb==0 )
+        error(EXIT_FAILURE, 0, "`--meanmedqdiff', `--sclipparams', "
+              "`--interpmetric' and `--interpnumngb' are mandatory when "
+              "requesting Sky measurement (`--sky')");
 
       /* If mode and median distance is a reasonable value. */
       if(p->meanmedqdiff>0.5)
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 1469ede..4c90c2a 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -7816,6 +7816,22 @@ is desirable).
 When values are to be interpolated, only change the values of the blank
 elements, keep the non-blank elements untouched.
 
address@hidden --interpmetric=STR
address@hidden Radial metric
address@hidden Taxicab metric
address@hidden Manhattan metric
address@hidden Metric: Manhattan, Taxicab, Radial
+The metric to use for finding nearest neighbors. Currently it only accepts
+the Manhattan (or taxicab) metric with @code{manhattan}, or the radial
+metric with @code{radial}.
+
+The Manhattan distance between two points is defined with
address@hidden|\Delta{x}|+|\Delta{y}|}. Thus the Manhattan metric has the
+advantage of being fast, but at the expense of being less accurate. The
+radial distance is the standard definition of distance in a Euclidean
+space: @mymath{\sqrt{\Delta{x}^2+\Delta{y}^2}}. It is accurate, but the
+multiplication and square root can slow down the processing.
+
 @item --interpnumngb=INT
 The number of nearby non-blank neighbors to use for interpolation.
 @end table
@@ -24497,6 +24513,11 @@ the two coordinates @code{a} and @code{b} (each an 
array of @code{ndim}
 elements).
 @end deftypefun
 
address@hidden float gal_dimension_dist_radial (size_t @code{*a}, size_t 
@code{*b}, size_t @code{ndim})
+Return the radial distance between the two coordinates @code{a} and
address@hidden (each an array of @code{ndim} elements).
address@hidden deftypefun
+
 @deftypefun {gal_data_t *} gal_dimension_collapse_sum (gal_data_t @code{*in}, 
size_t @code{c_dim}, gal_data_t @code{*weight})
 Collapse the input dataset (@code{in}) along the given dimension
 (@code{c_dim}, in C definition: starting from zero, from the slowest
diff --git a/lib/dimension.c b/lib/dimension.c
index 070265e..310b5cb 100644
--- a/lib/dimension.c
+++ b/lib/dimension.c
@@ -263,7 +263,7 @@ gal_dimension_index_to_coord(size_t index, size_t ndim, 
size_t *dsize,
 /************************************************************************/
 /********************           Distances          **********************/
 /************************************************************************/
-size_t
+float
 gal_dimension_dist_manhattan(size_t *a, size_t *b, size_t ndim)
 {
   size_t i, out=0;
@@ -275,6 +275,18 @@ gal_dimension_dist_manhattan(size_t *a, size_t *b, size_t 
ndim)
 
 
 
+float
+gal_dimension_dist_radial(size_t *a, size_t *b, size_t ndim)
+{
+  size_t i, out=0;
+  for(i=0;i<ndim;++i) out += (a[i]-b[i])*(a[i]-b[i]);
+  return sqrt(out);
+}
+
+
+
+
+
 
 
 
diff --git a/lib/gnuastro-internal/commonopts.h 
b/lib/gnuastro-internal/commonopts.h
index 4420947..96046c2 100644
--- a/lib/gnuastro-internal/commonopts.h
+++ b/lib/gnuastro-internal/commonopts.h
@@ -199,6 +199,20 @@ struct argp_option gal_commonopts_options[] =
       GAL_OPTIONS_NOT_SET
     },
     {
+      "interpmetric",
+      GAL_OPTIONS_KEY_INTERPMETRIC,
+      "INT",
+      0,
+      "Interpolation metric (radial, manhattan).",
+      GAL_OPTIONS_GROUP_TESSELLATION,
+      &cp->interpmetric,
+      GAL_TYPE_STRING,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET,
+      gal_options_read_interpmetric
+    },
+    {
       "interpnumngb",
       GAL_OPTIONS_KEY_INTERPNUMNGB,
       "INT",
diff --git a/lib/gnuastro-internal/options.h b/lib/gnuastro-internal/options.h
index ba22bd3..2584ea9 100644
--- a/lib/gnuastro-internal/options.h
+++ b/lib/gnuastro-internal/options.h
@@ -121,6 +121,7 @@ enum options_common_keys
   GAL_OPTIONS_KEY_CHECKTILES,
   GAL_OPTIONS_KEY_ONEELEMPERTILE,
   GAL_OPTIONS_KEY_INTERPONLYBLANK,
+  GAL_OPTIONS_KEY_INTERPMETRIC,
   GAL_OPTIONS_KEY_INTERPNUMNGB,
 };
 
@@ -179,6 +180,7 @@ struct gal_options_common_params
   /* Tessellation. */
   struct gal_tile_two_layer_params tl; /* Two layer tessellation params.  */
   uint8_t      interponlyblank; /* Only interpolate over blank values.    */
+  uint8_t         interpmetric; /* Metric to use for nearest-ngb interp.  */
   size_t          interpnumngb; /* Number of neighbors for interpolation. */
 
   /* Input. */
@@ -274,6 +276,10 @@ void *
 gal_options_read_tableformat(struct argp_option *option, char *arg,
                              char *filename, size_t lineno, void *junk);
 
+void *
+gal_options_read_interpmetric(struct argp_option *option, char *arg,
+                              char *filename, size_t lineno, void *junk);
+
 gal_data_t *
 gal_options_parse_list_of_numbers(char *string, char *filename,
                                   size_t lineno);
diff --git a/lib/gnuastro/dimension.h b/lib/gnuastro/dimension.h
index 205820a..2bdc9c4 100644
--- a/lib/gnuastro/dimension.h
+++ b/lib/gnuastro/dimension.h
@@ -89,10 +89,11 @@ gal_dimension_index_to_coord(size_t index, size_t ndim, 
size_t *dsize,
 /************************************************************************/
 /********************           Distances          **********************/
 /************************************************************************/
-size_t
+float
 gal_dimension_dist_manhattan(size_t *a, size_t *b, size_t ndim);
 
-
+float
+gal_dimension_dist_radial(size_t *a, size_t *b, size_t ndim);
 
 
 
diff --git a/lib/gnuastro/interpolate.h b/lib/gnuastro/interpolate.h
index 1c72730..5f1ec26 100644
--- a/lib/gnuastro/interpolate.h
+++ b/lib/gnuastro/interpolate.h
@@ -46,6 +46,18 @@ __BEGIN_C_DECLS  /* From C++ preparations */
 
 
 
+
+/* Metrics to use for nearest-neighbor  */
+enum gal_interpolate_close_metric
+{
+ GAL_INTERPOLATE_CLOSE_METRIC_INVALID,
+
+ GAL_INTERPOLATE_CLOSE_METRIC_RADIAL,
+ GAL_INTERPOLATE_CLOSE_METRIC_MANHATTAN,
+};
+
+
+
 /* Types of interpolation. */
 enum gal_interpolate_1D_types
 {
@@ -65,8 +77,9 @@ enum gal_interpolate_1D_types
 gal_data_t *
 gal_interpolate_close_neighbors(gal_data_t *input,
                                 struct gal_tile_two_layer_params *tl,
-                                size_t numneighbors, size_t numthreads,
-                                int onlyblank, int aslinkedlist);
+                                uint8_t metric, size_t numneighbors,
+                                size_t numthreads, int onlyblank,
+                                int aslinkedlist);
 
 gsl_spline *
 gal_interpolate_1d_make_gsl_spline(gal_data_t *X, gal_data_t *Y, int type_1d);
diff --git a/lib/interpolate.c b/lib/interpolate.c
index 8277afc..bdc4f50 100644
--- a/lib/interpolate.c
+++ b/lib/interpolate.c
@@ -67,6 +67,8 @@ struct interpolate_params
   uint8_t                *thread_flags;
   int                        onlyblank;
   gal_list_void_t            *ngb_vals;
+  float (*metric)(size_t *, size_t *, size_t );
+
   struct gal_tile_two_layer_params *tl;
 };
 
@@ -87,11 +89,11 @@ interpolate_close_neighbors_on_thread(void *in_prm)
 
   /* Rest of variables. */
   void *nv;
-  float pdist;
+  float dist, pdist;
   uint8_t *b, *bf, *bb;
   gal_list_void_t *tvll;
   gal_list_dosizet_t *lQ, *sQ;
-  size_t ngb_counter, dist, pind, *dinc;
+  size_t ngb_counter, pind, *dinc;
   size_t i, index, fullind, chstart=0, ndim=input->ndim;
   gal_data_t *median, *tin, *tout, *tnear, *nearest=NULL;
   size_t size = (correct_index ? tl->tottilesinch : input->size);
@@ -233,7 +235,7 @@ interpolate_close_neighbors_on_thread(void *in_prm)
                  gal_dimension_index_to_coord(nind, ndim, dsize, ncoord);
 
                  /* Distance of this neighbor to the one to be filled. */
-                 dist=gal_dimension_dist_manhattan(icoord, ncoord, ndim);
+                 dist=prm->metric(icoord, ncoord, ndim);
 
                  /* Add this neighbor to the list. */
                  gal_list_dosizet_add(&lQ, &sQ, nind, dist);
@@ -328,8 +330,9 @@ interpolate_copy_input(gal_data_t *input, int aslinkedlist)
 gal_data_t *
 gal_interpolate_close_neighbors(gal_data_t *input,
                                 struct gal_tile_two_layer_params *tl,
-                                size_t numneighbors, size_t numthreads,
-                                int onlyblank, int aslinkedlist)
+                                uint8_t metric, size_t numneighbors,
+                                size_t numthreads, int onlyblank,
+                                int aslinkedlist)
 {
   gal_data_t *tin, *tout;
   struct interpolate_params prm;
@@ -354,6 +357,21 @@ gal_interpolate_close_neighbors(gal_data_t *input,
   prm.num          = aslinkedlist ? gal_list_data_number(input) : 1;
 
 
+  /* Set the metric. */
+  switch(metric)
+    {
+    case GAL_INTERPOLATE_CLOSE_METRIC_RADIAL:
+      prm.metric=gal_dimension_dist_radial;
+      break;
+    case GAL_INTERPOLATE_CLOSE_METRIC_MANHATTAN:
+      prm.metric=gal_dimension_dist_manhattan;
+      break;
+    default:
+      error(EXIT_FAILURE, 0, "%s: %d is not a valid metric identifier",
+            __func__, metric);
+    }
+
+
   /* Flag the blank values. */
   prm.blanks=gal_blank_flag(input);
 
diff --git a/lib/options.c b/lib/options.c
index db728ff..2e176ed 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -38,6 +38,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <gnuastro/threads.h>
 #include <gnuastro/pointer.h>
 #include <gnuastro/arithmetic.h>
+#include <gnuastro/interpolate.h>
 
 #include <gnuastro-internal/timing.h>
 #include <gnuastro-internal/options.h>
@@ -511,6 +512,55 @@ gal_options_read_tableformat(struct argp_option *option, 
char *arg,
 
 
 
+void *
+gal_options_read_interpmetric(struct argp_option *option, char *arg,
+                              char *filename, size_t lineno, void *junk)
+{
+  char *str;
+  if(lineno==-1)
+    {
+      switch(*(uint8_t *)(option->value))
+        {
+        case GAL_INTERPOLATE_CLOSE_METRIC_RADIAL:
+          gal_checkset_allocate_copy("radial", &str);
+          break;
+        case GAL_INTERPOLATE_CLOSE_METRIC_MANHATTAN:
+          gal_checkset_allocate_copy("manhattan", &str);
+          break;
+        default:
+          error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix 
the "
+                "problem. The code %u is not recognized as a nearest-neighbor "
+                "interpolation metric", __func__, PACKAGE_BUGREPORT,
+                *(uint8_t *)(option->value));
+        }
+      return str;
+    }
+  else
+    {
+      /* If the option is already set, just return. */
+      if(option->set) return NULL;
+
+      /* Set the value. */
+      if(       !strcmp(arg, "radial") )
+        *(uint8_t *)(option->value) = GAL_INTERPOLATE_CLOSE_METRIC_RADIAL;
+      else if ( !strcmp(arg, "manhattan") )
+        *(uint8_t *)(option->value) = GAL_INTERPOLATE_CLOSE_METRIC_MANHATTAN;
+      else
+        error_at_line(EXIT_FAILURE, 0, filename, lineno, "`%s' (value to `%s' "
+                      "option) isn't valid. Currently only `radial' and "
+                      "`manhattan' metrics are recognized for nearest neighbor 
"
+                      "interpolation", arg, option->name);
+
+      /* For no un-used variable warning. This function doesn't need the
+         pointer. */
+      return junk=NULL;
+    }
+}
+
+
+
+
+
 /* The input to this function is a string of any number of numbers
    separated by a comma (`,') and possibly containing fractions, for
    example: `1,2/3, 4.95'. The output `gal_data_t' contains the array of



reply via email to

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