gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 7356f18 2/2: Fixed 32-bit check errors and fre


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 7356f18 2/2: Fixed 32-bit check errors and freeing empty WCS
Date: Sun, 25 Jun 2017 08:54:57 -0400 (EDT)

branch: master
commit 7356f18436b9c2c2555b86edbfea122d7be54348
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Fixed 32-bit check errors and freeing empty WCS
    
    After Gnuastro 0.3.7 was uploaded to the Debian server and tested on many
    systems, it was found that two tests fail (one in CosmicCalculator) and
    another in MakeCatalog. So after installing an i386 Debian as a virtual
    machine and testing it, the causes of the problem were found and corrected:
    
     - The CosmicCalculator test was corrected by defining a `sum' variable to
       be the sum of the different densities and using that for a check. I
       guess this is a compiler issue. But using that variable, also helped in
       several places where this sum was necessary in the function. Also, since
       users might use scripts to generate the densities, we now allow for
       small floating point errors also.
    
     - The problem in MakeCatalog was due to not being able to read the
       `NUMLABS' keyword in the clumps image. The problem was that on 32-bit
       systems, `long' and `int' have the same length of 32-bits. But the
       CFITSIO manual is silent on the length of its `TINT' (or `TUINT')
       lengths. So on a 32-bit system, when trying to read a number into
       `TUINT' it would give an overflow error. As a result, when converting
       Gnuastro's types to CFITSIO's types, for 32-bit integers, CFITSIO's LONG
       types are preferred.
    
    Also with this commit, the work done in `gal_wcs_read_fitsptr' of the last
    commit was cleaned and some bugs in it were corrected, for example the
    `altlin' variable is now only checked when a WCS structure was actually
    read.
---
 bin/cosmiccal/ui.c     | 16 ++++++++-------
 bin/mkcatalog/ui.c     |  8 ++++++--
 lib/fits.c             | 17 +++++++++------
 lib/wcs.c              | 56 +++++++++++++++++++++++++++++++++++---------------
 tests/arithmetic/or.sh |  2 +-
 5 files changed, 67 insertions(+), 32 deletions(-)

diff --git a/bin/cosmiccal/ui.c b/bin/cosmiccal/ui.c
index c2864de..a7d8d98 100644
--- a/bin/cosmiccal/ui.c
+++ b/bin/cosmiccal/ui.c
@@ -195,16 +195,18 @@ parse_opt(int key, char *arg, struct argp_state *state)
 static void
 ui_read_check_only_options(struct cosmiccalparams *p)
 {
-  /* Check if the density fractions add up to 1. */
-  if( (p->olambda + p->omatter + p->oradiation) != 1.0f )
-    error(EXIT_FAILURE, 0, "sum of fractional densities is not 1, but %f. "
+  double sum=p->olambda + p->omatter + p->oradiation;
+
+  /* Check if the density fractions add up to 1 (within floating point
+     error). */
+  if( sum > (1+1e-8) || sum < (1-1e-8) )
+    error(EXIT_FAILURE, 0, "sum of fractional densities is not 1, but %.8f. "
           "The cosmological constant (`olambda'), matter (`omatter') "
-          "and radiation (`oradiation') densities are given as %f, %f, %f",
-          p->olambda + p->omatter + p->oradiation, p->olambda, p->omatter,
-          p->oradiation);
+          "and radiation (`oradiation') densities are given as %.8f, %.8f, "
+          "%.8f", sum, p->olambda, p->omatter, p->oradiation);
 
   /* The curvature fractional density: */
-  p->ocurv=1-(p->olambda+p->omatter+p->oradiation);
+  p->ocurv=1-sum;
 
   /* Convert H0 from km/sec/Mpc to 1/sec: */
   p->H0s=p->H0/1000/GSL_CONST_MKSA_PARSEC;
diff --git a/bin/mkcatalog/ui.c b/bin/mkcatalog/ui.c
index 7096feb..87f95a1 100644
--- a/bin/mkcatalog/ui.c
+++ b/bin/mkcatalog/ui.c
@@ -500,6 +500,7 @@ ui_preparations_read_inputs(struct mkcatalogparams *p)
 static void
 ui_preparations_read_keywords(struct mkcatalogparams *p)
 {
+  char *msg;
   gal_data_t *tmp;
   gal_data_t *keys=gal_data_array_calloc(2);
   char *stdfile=p->stdfile ? p->stdfile : p->inputname;
@@ -575,8 +576,11 @@ ui_preparations_read_keywords(struct mkcatalogparams *p)
       gal_fits_key_read(clumpsfile, p->clumpshdu, keys, 0, 0);
       if(keys[0].status) p->clumpsn=NAN;
       if(keys[1].status)
-        error(EXIT_FAILURE, 0, "couldn't find NCLUMPS in the header of "
-              "%s (hdu: %s).", p->clumpsfile, p->clumpshdu);
+        {
+          asprintf(&msg, "couldn't find/read NUMLABS in the header of "
+                   "%s (hdu: %s), see error above", clumpsfile, p->clumpshdu);
+          gal_fits_io_error(keys[1].status, msg);
+        }
     }
 
 
diff --git a/lib/fits.c b/lib/fits.c
index d5f555d..ef1f328 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -308,17 +308,22 @@ gal_fits_type_to_datatype(uint8_t type)
       else if( sizeof(int)      == w )   return TINT;
       break;
 
+    /* On 32-bit systems, the length of `int' and `long' are both
+       32-bits. But CFITSIO's LONG type is preferred because it is designed
+       to be 32-bit. Its `INT' type is not clearly defined and caused
+       problems when reading keywords.*/
     case GAL_TYPE_UINT32:
       w=4;
-      if     ( sizeof(int)      == w )   return TUINT;
-      else if( sizeof(long)     == w )   return TULONG;
+      if     ( sizeof(long)     == w )   return TULONG;
+      else if( sizeof(int)      == w )   return TUINT;
       else if( sizeof(short)    == w )   return TUSHORT;
       break;
 
+    /* Similar to UINT32 above. */
     case GAL_TYPE_INT32:
       w=4;
-      if     ( sizeof(int)      == w )   return TINT;
-      else if( sizeof(long)     == w )   return TLONG;
+      if     ( sizeof(long)     == w )   return TLONG;
+      else if( sizeof(int)      == w )   return TINT;
       else if( sizeof(short)    == w )   return TSHORT;
       break;
 
@@ -1322,8 +1327,8 @@ gal_fits_img_info(fitsfile *fptr, int *type, size_t 
*ndim, size_t **dsize,
         {
         switch(i)
           {
-          case 4: if(unit) {str = key->array; *unit = *str;}   break;
-          case 3: if(name) {str = key->array; *name = *str;}   break;
+          case 4: if(unit) {str = key->array; *unit = *str; *str=NULL;} break;
+          case 3: if(name) {str = key->array; *name = *str; *str=NULL;} break;
           case 2: bscale = *(double *)(key->array);    break;
           case 1: bzero  = *(double *)(key->array);    break;
           default:
diff --git a/lib/wcs.c b/lib/wcs.c
index eb566e9..f99eea0 100644
--- a/lib/wcs.c
+++ b/lib/wcs.c
@@ -70,8 +70,8 @@ gal_wcs_read_fitsptr(fitsfile *fptr, size_t hstartwcs, size_t 
hendwcs,
                      int *nwcs)
 {
   /* Declaratins: */
-  struct wcsprm *wcs;
   int nkeys=0, status=0;
+  struct wcsprm *wcs=NULL;
   char *fullheader, *to, *from;
   int relax    = WCSHDR_all; /* Macro: use all informal WCS extensions. */
   int ctrl     = 0;          /* Don't report why a keyword wasn't used. */
@@ -111,7 +111,8 @@ gal_wcs_read_fitsptr(fitsfile *fptr, size_t hstartwcs, 
size_t hendwcs,
       /*******************************************************/
     }
 
-  /* WCSlib function */
+
+  /* WCSlib function to parse the FITS headers. */
   status=wcspih(fullheader, nkeys, relax, ctrl, &nreject, nwcs, &wcs);
   if(status)
     {
@@ -125,22 +126,45 @@ gal_wcs_read_fitsptr(fitsfile *fptr, size_t hstartwcs, 
size_t hendwcs,
     gal_fits_io_error(status, "problem in fitsarrayvv.c for freeing "
                            "the memory used to keep all the headers");
 
+
   /* Set the internal structure: */
-  status=wcsset(wcs);
-  if(status)
+  if(wcs)
     {
-      fprintf(stderr, "\n##################\n"
-              "WCSLIB Warning: wcsset ERROR %d: %s.\n"
-              "##################\n",
-            status, wcs_errmsg[status]);
-      wcs=NULL; *nwcs=0;
+      /* CTYPE is a mandatory WCS keyword, so if it hasn't been given (its
+         '\0'), then the headers didn't have a WCS structure. However,
+         WCSLIB still fills in the basic information (for example the
+         dimensionality of the dataset). */
+      if(wcs->ctype[0][0]=='\0')
+        {
+          wcsfree(wcs);
+          wcs=NULL;
+          *nwcs=0;
+        }
+      else
+        {
+          /* Set the WCS structure. */
+          status=wcsset(wcs);
+          if(status)
+            {
+              fprintf(stderr, "\n##################\n"
+                      "WCSLIB Warning: wcsset ERROR %d: %s.\n"
+                      "##################\n",
+                      status, wcs_errmsg[status]);
+              wcsfree(wcs);
+              wcs=NULL;
+              *nwcs=0;
+            }
+          else
+            /* A correctly useful WCS is present. When no PC matrix
+               elements were present in the header, the default PC matrix
+               (a unity matrix) is used. In this case WCSLIB doesn't set
+               `altlin' (and gives it a value of 0). In Gnuastro, later on,
+               we might need to know the type of the matrix used, so in
+               such a case, we will set `altlin' to 1. */
+            if(wcs->altlin==0) wcs->altlin=1;
+        }
     }
 
-  /* Initialize the wcsprm struct
-  if ((status = wcsset(*wcs)))
-    error(EXIT_FAILURE, 0, "%s: wcsset ERROR %d: %s.\n", __func__,
-          status, wcs_errmsg[status]);
-  */
 
   /* Return the WCS structure. */
   return wcs;
@@ -294,13 +318,13 @@ gal_wcs_warp_matrix(struct wcsprm *wcs)
           __func__, size*sizeof *out);
 
   /* Fill in the array. */
-  if(wcs->altlin & 0x1)        /* Has a PCi_j array. */
+  if(wcs->altlin & 0x1)          /* Has a PCi_j array. */
     {
       for(i=0;i<wcs->naxis;++i)
         for(j=0;j<wcs->naxis;++j)
           out[i*wcs->naxis+j] = wcs->cdelt[i] * wcs->pc[i*wcs->naxis+j];
     }
-  else if(wcs->altlin & 0x2)     /* Has CDi_j array */
+  else if(wcs->altlin & 0x2)     /* Has CDi_j array.   */
     {
       for(i=0;i<size;++i)
         out[i]=wcs->cd[i];
diff --git a/tests/arithmetic/or.sh b/tests/arithmetic/or.sh
index eb08426..263dcbf 100755
--- a/tests/arithmetic/or.sh
+++ b/tests/arithmetic/or.sh
@@ -49,4 +49,4 @@ if [ ! -f $img      ]; then echo "$img does not exist.";   
exit 77; fi
 
 # Actual test script
 # ==================
-$execname $img 6 eq $img 3 eq or -h1 -h1 --output=or.fits
+$execname $img 6 eq $img 3 eq or -h2 -h2 --output=or.fits



reply via email to

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