gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 9b95bddc: Library (fits.h): NaN keys printed a


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 9b95bddc: Library (fits.h): NaN keys printed as largest value with warning
Date: Thu, 15 Jun 2023 12:03:11 -0400 (EDT)

branch: master
commit 9b95bddca60981c23151387ed0061025f5c9d658
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Library (fits.h): NaN keys printed as largest value with warning
    
    Until now, when the 'gal_fits_key_write_in_ptr' function was given a
    keyword with a NaN value, it would print a warning and let CFITSIO crash
    (because a NaN is not supported in the FITS standard). However, it can
    sometime happen that an analysis produces a NaN and the keyword needs to be
    written.
    
    With this commit, to deal with such cases, this function now writes the
    largest possible number for the respective floating point type and will
    also print a warning on the terminal, informing the user that this swapping
    of values was done.
    
    This bug was reported by Sepideh Eskandarlou.
    
    This fixes bug #64303.
---
 NEWS                        |  2 ++
 bin/statistics/statistics.c |  2 ++
 configure.ac                |  2 +-
 doc/gnuastro.texi           |  9 +++++++--
 lib/fits.c                  | 29 ++++++++++++++++++++++-------
 5 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/NEWS b/NEWS
index 41bdc391..d25b8643 100644
--- a/NEWS
+++ b/NEWS
@@ -91,6 +91,8 @@ See the end of the file for license conditions.
   bug #64250: astscript-fits-view: no message printed when input file did
               not exist. Reported by Ryan Begley.
   bug #64274: MakeProfiles crash for points in 3D. Found by Teet Kuumta.
+  bug #64303: Statistics fit --fitestimate crash when covariance matrix has
+              NaN. Reported Sepideh Eskandarlou.
 
 
 
diff --git a/bin/statistics/statistics.c b/bin/statistics/statistics.c
index 71ec832e..e4e3e5ec 100644
--- a/bin/statistics/statistics.c
+++ b/bin/statistics/statistics.c
@@ -1179,6 +1179,8 @@ print_sigma_clip(struct statisticsparams *p)
 /*******************************************************************/
 /**************                Fitting               ***************/
 /*******************************************************************/
+/* 'redchisq' is taken as a pointer so we don't need to allocate it here
+   when the FITS file gets written. */
 static struct gal_fits_list_key_t *
 statistics_fit_params_to_keys(struct statisticsparams *p, gal_data_t *fit,
                               char *whtnat, double *redchisq)
diff --git a/configure.ac b/configure.ac
index 60b275ea..98d0d6ae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -52,7 +52,7 @@ AC_CONFIG_MACRO_DIRS([bootstrapped/m4])
 
 # Library version, see the GNU Libtool manual ("Library interface versions"
 # section for the exact definition of each) for
-GAL_CURRENT=18
+GAL_CURRENT=19
 GAL_REVISION=0
 GAL_AGE=0
 GAL_LT_VERSION="${GAL_CURRENT}:${GAL_REVISION}:${GAL_AGE}"
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 807ea736..7b687d93 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -24167,10 +24167,15 @@ When nothing is given to @option{--output}, the 
independent column and the estim
 @item
 If a file name is given to @option{--output}, the estimated table above is 
saved in that file.
 It can have any of the formats in @ref{Recognized table formats}.
-As a FITS file, all the fitted numbers (coefficients, covariance matrix and 
reduced @mymath{\chi^2} are kept as FITS keywords in the same HDU of the 
estimated table.
+As a FITS file, all the fit outputs (coefficients, covariance matrix and 
reduced @mymath{\chi^2}) are kept as FITS keywords in the same HDU of the 
estimated table.
 For a complete example, see @ref{Least squares fitting}.
+
+When the covariance matrix (and thus the @mymath{\chi^2}) cannot be calculated 
(for example if you only have two rows!), the printed values on the terminal 
will be NaN.
+However, the FITS standard does not allow NaN values in keyword values!
+Therefore, when writing the @mymath{\chi^2} and covariance matrix elements 
into the output FITS keywords, the largest value of the 64-bit floating point 
type will be written: @mymath{1.79769313486232\times10^{308}}; see @ref{Numeric 
data types}.
+
 @item
-When @option{--quiet} is given with @option{--fitestimate}, the fitted 
parameters are no longer printed on the standard output (they will be available 
as FITS keywords in the file given to @option{--output}).
+When @option{--quiet} is given with @option{--fitestimate}, the fitted 
parameters are no longer printed on the standard output; they are available as 
FITS keywords in the file given to @option{--output}.
 @end itemize
 
 @item --fitestimatehdu=STR/INT
diff --git a/lib/fits.c b/lib/fits.c
index db74727d..53a38a2d 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -2042,9 +2042,10 @@ gal_fits_key_write(gal_fits_list_key_t **keylist, char 
*title,
 /* Fits doesn't allow NaN values, so if the type of float or double, we'll
    just check to see if its NaN or not and let the user know the keyword
    name (to help them fix it). */
-static void
+static void *
 gal_fits_key_write_in_ptr_nan_check(gal_fits_list_key_t *tmp)
 {
+  void *out=NULL;
   int nanwarning=0;
 
   /* Check the value. */
@@ -2060,9 +2061,21 @@ gal_fits_key_write_in_ptr_nan_check(gal_fits_list_key_t 
*tmp)
 
   /* Print the warning. */
   if(nanwarning)
-    error(EXIT_SUCCESS, 0, "%s: (WARNING) value of '%s' is NaN "
-          "and FITS doesn't recognize a NaN key value", __func__,
-          tmp->keyname);
+    {
+      out=gal_pointer_allocate(tmp->type, 1, 0, __func__, "out");
+      gal_type_max(tmp->type, out);
+      error(EXIT_SUCCESS, 0, "%s: (WARNING) value of '%s' is NaN "
+            "and FITS doesn't recognize a NaN key value; instead, "
+            "the following value (largest value of the %d-bit "
+            "floating point type) will be written: %g", __func__,
+            tmp->keyname, tmp->type==GAL_TYPE_FLOAT32 ? 32 : 64,
+            ( tmp->type==GAL_TYPE_FLOAT32
+              ? ((float  *)(out))[0]
+              : ((double *)(out))[0] ) );
+    }
+
+  /* Return the allocated array.*/
+  return out;
 }
 
 
@@ -2076,6 +2089,7 @@ void
 gal_fits_key_write_in_ptr(gal_fits_list_key_t **keylist, fitsfile *fptr)
 {
   int status=0;
+  void *ifnan=NULL;
   gal_fits_list_key_t *tmp, *ttmp;
 
   tmp=*keylist;
@@ -2099,14 +2113,15 @@ gal_fits_key_write_in_ptr(gal_fits_list_key_t 
**keylist, fitsfile *fptr)
           if(tmp->value)
             {
               /* Print a warning if the value is NaN. */
-              gal_fits_key_write_in_ptr_nan_check(tmp);
+              ifnan=gal_fits_key_write_in_ptr_nan_check(tmp);
 
               /* Write/Update the keyword value. */
               if( fits_update_key(fptr,
                                   gal_fits_type_to_datatype(tmp->type),
-                                  tmp->keyname, tmp->value, tmp->comment,
-                                  &status) )
+                                  tmp->keyname, ifnan?ifnan:tmp->value,
+                                  tmp->comment, &status) )
                 gal_fits_io_error(status, NULL);
+              if(ifnan) free(ifnan);
             }
           else
             {



reply via email to

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