gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 4c28d13 042/125: Problem in reading blank FITS


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 4c28d13 042/125: Problem in reading blank FITS ASCII table fixed
Date: Sun, 23 Apr 2017 22:36:33 -0400 (EDT)

branch: master
commit 4c28d13889c47c36b31f27f204a479a5939b3c7d
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Problem in reading blank FITS ASCII table fixed
    
    With the great help and guidance of William Pence (autor of CFITSIO) the
    problems in FITS ASCII tables discussed in commit 232e059 (First draft of
    FITS table writing function complete) were corrected. The main issues can
    be summarized as bellow:
    
     - In the ASCII format, we need the `TNULLn' keyword for all types as a
       string. While in the binary format, we just need the `TNULLn' keywords
       for the integer and string types. Previously I had confused the two and
       didn't put the `TNULLn' keyword for floating types in ASCII tables.
    
     - All columns that need a `TNULLn' (integer and string types) must have it
       as long as at least one column has a blank value. So for the time being
       we are simply including the `TNULLn's for all integer and string type
       columns, not just those that have a blank value.
    
    William Pence pointed to an important point: that `nan' values cannot be
    robustly readed on many machines/compilers, so he suggested to use numbers
    that are greatly out of range instead of a `NaN' value. This is an
    important issue and must be addressed, but I currently don't have time. So
    for the time being, Gnuastro also imports Gnulib's `strtod' module which
    accounts for many of those failures in other systems. So atleast as long as
    people use Gnuastro on those systems, they won't have any problem.
    
    For the time being, if users need the ASCII tables (FITS or plain text) for
    programs on systems that can't read NaN values properly, they can simply
    use a `sed' command or a search and replace to change all the `nan' values
    into some absurd numerical value. This will also change the plain text
    comment, or FITS ASCII table `TNULLn' keyword, so the table is still
    exactly readable in Gnuastro.
    
    Work has also started on a generic table (which contains blank columns,
    string columns and missing information), but it is not yet finished.
    
    Some further modifications during this commit:
    
     - When printing table information, we use `GAL_DATA_BLANK_STRING', not the
       `N/A' string.
    
     - Since `strtod' is much more robust than `strtof' (and is supported in
       Gnulib), all invokations of `strtof' have been replaced with `strtod'.
    
     - `gal_data_blank_as_string' now also gets a `width' argument to write the
       blank value in. This is currently necessary for the FITS ASCII tables as
       discussed above.
    
     - When CFITSIO doesn't recognize certain table column types, an error will
       be printed. Since Gnuastro's table reading/writing is more general than
       FITS, we need those types and can't simply remove them.
    
     - `gal_table_col_print_info' now keeps the width and precision values it
       finds into the actual data structure for easy use and access at later
       times.
---
 THANKS                                             |   1 +
 bin/convertt/ui.c                                  |   4 +-
 bin/table/ui.c                                     |  12 +-
 bootstrap.conf                                     |   1 +
 lib/checkset.c                                     |   8 +-
 lib/data.c                                         |  69 +++++++--
 lib/fits.c                                         | 171 +++++++++++++--------
 lib/gnuastro/data.h                                |   2 +-
 lib/gnuastro/table.h                               |   4 +-
 lib/table.c                                        |  61 ++++----
 lib/txt.c                                          |  35 ++---
 tests/Makefile.am                                  |  10 +-
 tests/table/asciitobinary.txt                      |   2 -
 .../{binarytoascii.sh => fits-binary-to-txt.sh}    |   4 +-
 tests/table/table.txt                              |  39 +++++
 .../{asciitobinary.sh => txt-to-fits-binary.sh}    |   4 +-
 16 files changed, 278 insertions(+), 149 deletions(-)

diff --git a/THANKS b/THANKS
index 6a0f8c7..cd57d12 100644
--- a/THANKS
+++ b/THANKS
@@ -24,6 +24,7 @@ support in Gnuastro. The list is ordered alphabetically.
     Mohammad-Reza Khellat                address@hidden
     Alan Lefor                           address@hidden
     Francesco Montanari                  address@hidden
+    William Pence                        address@hidden
     Yahya Sefidbakht                     address@hidden
     Richard Stallman                     address@hidden
     Ole Streicher                        address@hidden
diff --git a/bin/convertt/ui.c b/bin/convertt/ui.c
index 60f5bbd..02c53fd 100644
--- a/bin/convertt/ui.c
+++ b/bin/convertt/ui.c
@@ -300,7 +300,7 @@ makechangestruct(char *arg)
       c=malloc(sizeof *c);
       if(c==NULL) error(EXIT_FAILURE, 0, "%zu bytes for struct change",
                         sizeof *c);
-      c->from=strtof(p, &p);
+      c->from=strtod(p, &p);
       while(*p==' ') {++p; continue;}
       if(*p==':') ++p;
       else
@@ -310,7 +310,7 @@ makechangestruct(char *arg)
                   "have given a '%c': %s\n", *p, arg);
           exit(EXIT_FAILURE);
         }
-      c->to=strtof(p, &p);
+      c->to=strtod(p, &p);
       while(*p==' ') {++p; continue;}
       if(*p==',') p++;
       else if(*p!='\0')
diff --git a/bin/table/ui.c b/bin/table/ui.c
index 4464efa..ff9a1d7 100644
--- a/bin/table/ui.c
+++ b/bin/table/ui.c
@@ -318,8 +318,10 @@ print_information_exit(struct tableparams *p)
                          &tabletype);
 
   /* Print the legend */
-  printf("Information for\n");
-  printf("%s (hdu: %s)\n", p->up.filename, p->cp.hdu);
+  if(gal_fits_name_is_fits(p->up.filename))
+    printf("%s (hdu: %s):\n", p->up.filename, p->cp.hdu);
+  else
+    printf("%s:\n", p->up.filename);
   printf("Number of rows: %zu\n", numrows);
   printf("%-8s%-25s%-20s%-18s%s\n", "No.", "Name", "Units", "Type",
          "Comment");
@@ -333,10 +335,10 @@ print_information_exit(struct tableparams *p)
       unit    = allcols[i].unit;       /* readability. The compiiler  */
       comment = allcols[i].comment;    /* optimizer will remove them. */
       printf("%-8zu%-25s%-20s%-18s%s\n", i+1,
-             name ? name : "N/A" ,
-             unit ? unit : "N/A" ,
+             name ? name : GAL_DATA_BLANK_STRING ,
+             unit ? unit : GAL_DATA_BLANK_STRING ,
              gal_data_type_as_string(allcols[i].type, 1),
-             comment ? comment : "N/A");
+             comment ? comment : GAL_DATA_BLANK_STRING);
       if(name)    free(name);
       if(unit)    free(unit);
       if(comment) free(comment);
diff --git a/bootstrap.conf b/bootstrap.conf
index 18f8e9d..8f977bd 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -164,6 +164,7 @@ gnulib_modules="
     regex
     error
     nproc
+    strtod
     getline
     strcase
     gendocs
diff --git a/lib/checkset.c b/lib/checkset.c
index a0ac9b1..02d3e68 100644
--- a/lib/checkset.c
+++ b/lib/checkset.c
@@ -347,7 +347,7 @@ gal_checkset_float_l_0(char *optarg, float *var, char *lo, 
char so,
 {
   float tmp;
   char *tailptr;
-  *var=tmp=strtof(optarg, &tailptr);
+  *var=tmp=strtod(optarg, &tailptr);
 
   CHECKFULLNUMBER;
   if(tmp<=0)
@@ -371,7 +371,7 @@ gal_checkset_float_l_0_s_1(char *optarg, float *var, char 
*lo, char so,
 {
   float tmp;
   char *tailptr;
-  *var=tmp=strtof(optarg, &tailptr);
+  *var=tmp=strtod(optarg, &tailptr);
 
   CHECKFULLNUMBER;
   if(tmp>1.0f || tmp<0)
@@ -393,7 +393,7 @@ gal_checkset_any_float(char *optarg, float *var, char *lo, 
char so,
                        char *spack, char *filename, size_t lineno)
 {
   char *tailptr;
-  *var=strtof(optarg, &tailptr);
+  *var=strtod(optarg, &tailptr);
 
   CHECKFULLNUMBER;
 }
@@ -456,7 +456,7 @@ gal_checkset_double_l_value(char *optarg, double *var, char 
*lo, char so,
 {
   float tmp;
   char *tailptr;
-  *var=tmp=strtof(optarg, &tailptr);
+  *var=tmp=strtod(optarg, &tailptr);
 
   CHECKFULLNUMBER;
   if(tmp<=value)
diff --git a/lib/data.c b/lib/data.c
index a4a512e..b6d6990 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -884,63 +884,98 @@ gal_data_alloc_blank(int type)
 
 /* Print the blank value as a string. */
 char *
-gal_data_blank_as_string(int type)
+gal_data_blank_as_string(int type, int width)
 {
   char *blank;
   switch(type)
     {
-    case GAL_DATA_TYPE_STRING:
-      error(EXIT_FAILURE, 0, "`gal_data_blank_as_string' can't print the "
-            "blank value for a string, it is for other types.");
-      break;
-
     case GAL_DATA_TYPE_BIT:
       error(EXIT_FAILURE, 0, "bit types are not implemented in "
             "`gal_data_blank_as_string' yet.");
       break;
 
+    case GAL_DATA_TYPE_STRING:
+      if(width)
+        asprintf(&blank, "%*s", width, GAL_DATA_BLANK_STRING);
+      else
+        asprintf(&blank, "%s", GAL_DATA_BLANK_STRING);
+      break;
+
     case GAL_DATA_TYPE_UCHAR:
-      asprintf(&blank, "%u", (unsigned char)GAL_DATA_BLANK_UCHAR);
+      if(width)
+        asprintf(&blank, "%*u", width, (unsigned char)GAL_DATA_BLANK_UCHAR);
+      else
+        asprintf(&blank, "%u",         (unsigned char)GAL_DATA_BLANK_UCHAR);
       break;
 
     case GAL_DATA_TYPE_CHAR:
-      asprintf(&blank, "%d", (char)GAL_DATA_BLANK_CHAR);
+      if(width)
+        asprintf(&blank, "%*d", width, (char)GAL_DATA_BLANK_CHAR);
+      else
+        asprintf(&blank, "%d",         (char)GAL_DATA_BLANK_CHAR);
       break;
 
     case GAL_DATA_TYPE_USHORT:
-      asprintf(&blank, "%u", (unsigned short)GAL_DATA_BLANK_USHORT);
+      if(width)
+        asprintf(&blank, "%*u", width, (unsigned short)GAL_DATA_BLANK_USHORT);
+      else
+        asprintf(&blank, "%u",         (unsigned short)GAL_DATA_BLANK_USHORT);
       break;
 
     case GAL_DATA_TYPE_SHORT:
-      asprintf(&blank, "%d", (short)GAL_DATA_BLANK_SHORT);
+      if(width)
+        asprintf(&blank, "%*d", width, (short)GAL_DATA_BLANK_SHORT);
+      else
+        asprintf(&blank, "%d",         (short)GAL_DATA_BLANK_SHORT);
       break;
 
     case GAL_DATA_TYPE_UINT:
-      asprintf(&blank, "%u", (unsigned int)GAL_DATA_BLANK_UINT);
+      if(width)
+        asprintf(&blank, "%*u", width, (unsigned int)GAL_DATA_BLANK_UINT);
+      else
+        asprintf(&blank, "%u",         (unsigned int)GAL_DATA_BLANK_UINT);
       break;
 
     case GAL_DATA_TYPE_INT:
-      asprintf(&blank, "%d", (int)GAL_DATA_BLANK_INT);
+      if(width)
+        asprintf(&blank, "%*d", width, (int)GAL_DATA_BLANK_INT);
+      else
+        asprintf(&blank, "%d",         (int)GAL_DATA_BLANK_INT);
       break;
 
     case GAL_DATA_TYPE_ULONG:
-      asprintf(&blank, "%lu", (unsigned long)GAL_DATA_BLANK_ULONG);
+      if(width)
+        asprintf(&blank, "%*lu", width, (unsigned long)GAL_DATA_BLANK_ULONG);
+      else
+        asprintf(&blank, "%lu",         (unsigned long)GAL_DATA_BLANK_ULONG);
       break;
 
     case GAL_DATA_TYPE_LONG:
-      asprintf(&blank, "%ld", (long)GAL_DATA_BLANK_LONG);
+      if(width)
+        asprintf(&blank, "%*ld", width, (long)GAL_DATA_BLANK_LONG);
+      else
+        asprintf(&blank, "%ld",         (long)GAL_DATA_BLANK_LONG);
       break;
 
     case GAL_DATA_TYPE_LONGLONG:
-      asprintf(&blank, "%lld", (LONGLONG)GAL_DATA_BLANK_LONGLONG);
+      if(width)
+        asprintf(&blank, "%*lld", width, (LONGLONG)GAL_DATA_BLANK_LONGLONG);
+      else
+        asprintf(&blank, "%lld",         (LONGLONG)GAL_DATA_BLANK_LONGLONG);
       break;
 
     case GAL_DATA_TYPE_FLOAT:
-      asprintf(&blank, "%f", GAL_DATA_BLANK_FLOAT);
+      if(width)
+        asprintf(&blank, "%*f", width, (float)GAL_DATA_BLANK_FLOAT);
+      else
+        asprintf(&blank, "%f",         (float)GAL_DATA_BLANK_FLOAT);
       break;
 
     case GAL_DATA_TYPE_DOUBLE:
-      asprintf(&blank, "%f", GAL_DATA_BLANK_DOUBLE);
+      if(width)
+        asprintf(&blank, "%*f", width, (double)GAL_DATA_BLANK_DOUBLE);
+      else
+        asprintf(&blank, "%f",         (double)GAL_DATA_BLANK_DOUBLE);
       break;
 
     default:
diff --git a/lib/fits.c b/lib/fits.c
index c061ab3..9088f87 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -267,20 +267,29 @@ gal_fits_type_to_bin_tform(int type)
 {
   switch(type)
     {
+    case GAL_DATA_TYPE_STRING:
+      return 'A';
+
     case GAL_DATA_TYPE_BIT:
       return 'X';
     case GAL_DATA_TYPE_UCHAR:
       return 'B';
     case GAL_DATA_TYPE_CHAR: case GAL_DATA_TYPE_LOGICAL:
       return 'S';
-    case GAL_DATA_TYPE_STRING:
-      return 'A';
-    case GAL_DATA_TYPE_UINT:
-      return 'V';
     case GAL_DATA_TYPE_USHORT:
       return 'U';
     case GAL_DATA_TYPE_SHORT:
       return 'I';
+    case GAL_DATA_TYPE_UINT:
+      return 'V';
+    case GAL_DATA_TYPE_INT:
+      error(EXIT_FAILURE, 0, "CFITSIO doesn't support integer table "
+            "columns");
+      break;
+    case GAL_DATA_TYPE_ULONG:
+      error(EXIT_FAILURE, 0, "CFITSIO doesn't support unsigned long table "
+            "columns");
+      break;
     case GAL_DATA_TYPE_LONG:
       return 'J';
     case GAL_DATA_TYPE_LONGLONG:
@@ -1961,7 +1970,6 @@ fits_table_prepare_arrays(gal_data_t *cols, size_t 
numcols, int tabletype,
   size_t i=0;
   gal_data_t *col;
   char fmt[2], lng[3];
-  size_t width, precision;
   char *blank, **tform, **ttype, **tunit;
 
 
@@ -1987,22 +1995,8 @@ fits_table_prepare_arrays(gal_data_t *cols, size_t 
numcols, int tabletype,
   for(col=cols; col!=NULL; col=col->next)
     {
       /* Set the `ttype' and `tunit' values: */
-      ttype[i]=col->name;
-      tunit[i]=col->unit;
-
-
-      /* Set the blank value. */
-      if( gal_data_has_blank(col) && ( col->type!=GAL_DATA_TYPE_FLOAT
-                                       || col->type!=GAL_DATA_TYPE_DOUBLE ))
-        {
-          /* Set the blank value. */
-          if(col->type==GAL_DATA_TYPE_STRING)
-            gal_checkset_allocate_copy(GAL_DATA_BLANK_STRING, &blank);
-          else
-            blank=gal_data_blank_as_string(col->type);
-        }
-      else
-        blank=NULL;
+      asprintf(&ttype[i], "%s", col->name ? col->name : "");
+      asprintf(&tunit[i], "%s", col->unit ? col->unit : "");
 
 
       /* FITS's TFORM depends on the type of FITS table, so work
@@ -2013,12 +2007,23 @@ fits_table_prepare_arrays(gal_data_t *cols, size_t 
numcols, int tabletype,
         case GAL_TABLE_TYPE_AFITS:
 
             /* Fill the printing format. */
-            gal_table_col_print_info(col, GAL_TABLE_TYPE_AFITS, &width,
-                                     &precision, fmt, lng);
+            gal_table_col_print_info(col, GAL_TABLE_TYPE_AFITS, fmt, lng);
+
+            /* We need to check if the blank value needs is larger than the
+               expected width or not. Its initial width is set the output
+               of the function above, but if the value is larger,
+               `asprintf' (which is used) will make it wider. */
+            blank = ( gal_data_has_blank(col)
+                      ? gal_data_blank_as_string(col->type, col->disp_width)
+                      : NULL );
 
             /* Adjust the width. */
             if(blank)
-              width = ( strlen(blank)>width ? strlen(blank) : width );
+              {
+                col->disp_width = ( strlen(blank) > col->disp_width
+                                    ? strlen(blank) : col->disp_width );
+                free(blank);
+              }
 
             /* Print the value to be used as TFORMn:  */
             switch(col->type)
@@ -2033,12 +2038,13 @@ fits_table_prepare_arrays(gal_data_t *cols, size_t 
numcols, int tabletype,
               case GAL_DATA_TYPE_ULONG:
               case GAL_DATA_TYPE_LONG:
               case GAL_DATA_TYPE_LONGLONG:
-                asprintf(&tform[i], "%c%zu", fmt[0], width);
+                asprintf(&tform[i], "%c%d", fmt[0], col->disp_width);
                 break;
 
               case GAL_DATA_TYPE_FLOAT:
               case GAL_DATA_TYPE_DOUBLE:
-                asprintf(&tform[i], "%c%zu.%zu", fmt[0], width, precision);
+                asprintf(&tform[i], "%c%d.%d", fmt[0], col->disp_width,
+                         col->disp_precision);
                 break;
 
               default:
@@ -2053,10 +2059,10 @@ fits_table_prepare_arrays(gal_data_t *cols, size_t 
numcols, int tabletype,
 
           /* If this is a string column, set all the strings to same size,
              then write the value of tform depending on the type. */
-          width=gal_data_string_fixed_alloc_size(col);
+          col->disp_width=gal_data_string_fixed_alloc_size(col);
           fmt[0]=gal_fits_type_to_bin_tform(col->type);
           if( col->type==GAL_DATA_TYPE_STRING )
-            asprintf(&tform[i], "%zu%c", width, fmt[0]);
+            asprintf(&tform[i], "%d%c", col->disp_width, fmt[0]);
           else
             asprintf(&tform[i], "%c", fmt[0]);
           break;
@@ -2067,8 +2073,7 @@ fits_table_prepare_arrays(gal_data_t *cols, size_t 
numcols, int tabletype,
         }
 
 
-      /* Clean up and increment the column index. */
-      if(blank) free(blank);
+      /* Increment the column index. */
       ++i;
     }
 }
@@ -2077,6 +2082,66 @@ fits_table_prepare_arrays(gal_data_t *cols, size_t 
numcols, int tabletype,
 
 
 
+/* Write the TNULLn keywords into the FITS file. Note that this depends on
+   the type of the table: for an ASCII table, all the columns need it. For
+   a binary table, only the non-floating point ones (even if they don't
+   have NULL values) must have it. */
+static void
+fits_write_tnull_tcomm(fitsfile *fptr, gal_data_t *col, int tabletype,
+                        size_t colnum)
+{
+  void *blank;
+  int status=0;
+  char *keyname, *bcomment;
+
+  switch(tabletype)
+    {
+    case GAL_TABLE_TYPE_AFITS:
+      asprintf(&keyname, "TNULL%zu", colnum);
+      blank=gal_data_blank_as_string(col->type, col->disp_width);
+      fits_write_key(fptr, TSTRING, keyname, blank,
+                     "blank value for this column", &status);
+      free(keyname);
+      free(blank);
+      break;
+
+    case GAL_TABLE_TYPE_BFITS:
+      if( col->type!=GAL_DATA_TYPE_FLOAT
+          && col->type!=GAL_DATA_TYPE_DOUBLE )
+        {
+          asprintf(&keyname, "TNULL%zu", colnum);
+          blank=gal_data_alloc_blank(col->type);
+          fits_write_key(fptr, gal_fits_type_to_datatype(col->type),
+                         keyname, blank, "blank value for this column",
+                         &status);
+          gal_fits_io_error(status, NULL);
+          free(keyname);
+          free(blank);
+        }
+      break;
+
+    default:
+      error(EXIT_FAILURE, 0, "tabletype code %d not recognized in "
+            "`fits_write_tnulls_tcomms'", tabletype);
+    }
+
+  /* Write the comments if there is any. */
+  if(col->comment)
+    {
+      asprintf(&keyname, "TCOMM%zu", colnum);
+      asprintf(&bcomment, "comment for field %zu", colnum);
+      fits_write_key(fptr, TSTRING, keyname, col->comment,
+                     bcomment, &status);
+      gal_fits_io_error(status, NULL);
+      free(keyname);
+      free(bcomment);
+    }
+}
+
+
+
+
+
 /* Write the given columns (a linked list of `gal_data_t') into a FITS
    table.*/
 void
@@ -2087,7 +2152,6 @@ gal_fits_table_write(gal_data_t *cols, char *comments, 
int tabletype,
   fitsfile *fptr;
   gal_data_t *col;
   size_t i, numrows=-1;
-  char *keyname, *bcomment;
   char **ttype, **tform, **tunit;
   int tbltype, numcols=0, status=0;
 
@@ -2125,41 +2189,23 @@ gal_fits_table_write(gal_data_t *cols, char *comments, 
int tabletype,
                   "table", &status);
   gal_fits_io_error(status, NULL);
 
+
   /* Write the columns into the file and also write the blank values into
      the header when necessary. */
   i=0;
   for(col=cols; col!=NULL; col=col->next)
     {
-      /* Write the blank value into the header if we are not dealing with a
-         floating point. */
-      if( gal_data_has_blank(col)
-          && ( col->type!=GAL_DATA_TYPE_FLOAT
-               && col->type!=GAL_DATA_TYPE_DOUBLE ) )
-        {
-          /* Write the keyword. */
-          asprintf(&keyname, "TNULL%zu", i+1);
-          blank=gal_data_alloc_blank(col->type);
-          fits_write_key(fptr, gal_fits_type_to_datatype(col->type),
-                         keyname, blank, "blank value for this column",
-                         &status);
-          gal_fits_io_error(status, NULL);
-          free(keyname);
-        }
-      else
+      /* Write the blank value into the header and return a pointer to
+         it. Otherwise, */
+      fits_write_tnull_tcomm(fptr, col, tabletype, i+1);
+
+      /* Set the blank pointer if its necessary, note that strings don't
+         need a blank pointer in a FITS ASCII table.*/
+      blank = ( gal_data_has_blank(col)
+                ? gal_data_alloc_blank(col->type) : NULL );
+      if(tabletype==GAL_TABLE_TYPE_AFITS && col->type==GAL_DATA_TYPE_STRING)
         blank=NULL;
 
-      /* Write the comments if there is any. */
-      if(col->comment)
-        {
-          asprintf(&keyname, "TCOMM%zu", i+1);
-          asprintf(&bcomment, "comment for field %zu", i+1);
-          fits_write_key(fptr, TSTRING, keyname, col->comment,
-                         bcomment, &status);
-          gal_fits_io_error(status, NULL);
-          free(keyname);
-          free(bcomment);
-        }
-
       /* Write the full column into the table. */
       fits_write_colnull(fptr, gal_fits_type_to_datatype(col->type),
                          i+1, 1, 1, col->size, col->array, blank, &status);
@@ -2179,7 +2225,12 @@ gal_fits_table_write(gal_data_t *cols, char *comments, 
int tabletype,
      `ttype' and `tunit' arrays just points to the respective string in the
      column data structure, the space for each element of the array wasn't
      allocated.*/
-  for(i=0;i<numcols;++i) if(tform[i]) free(tform[i]);
+  for(i=0;i<numcols;++i)
+    {
+      free(tform[i]);
+      free(ttype[i]);
+      free(tunit[i]);
+    }
   free(tform);
   free(ttype);
   free(tunit);
diff --git a/lib/gnuastro/data.h b/lib/gnuastro/data.h
index 76bc83e..4cbb55b 100644
--- a/lib/gnuastro/data.h
+++ b/lib/gnuastro/data.h
@@ -277,7 +277,7 @@ void *
 gal_data_alloc_blank(int type);
 
 char *
-gal_data_blank_as_string(int type);
+gal_data_blank_as_string(int type, int width);
 
 void
 gal_data_apply_mask(gal_data_t *in, gal_data_t *mask);
diff --git a/lib/gnuastro/table.h b/lib/gnuastro/table.h
index 075bc5d..1df6e5a 100644
--- a/lib/gnuastro/table.h
+++ b/lib/gnuastro/table.h
@@ -122,8 +122,8 @@ int
 gal_table_string_to_searchin(char *string);
 
 void
-gal_table_col_print_info(gal_data_t *col, int tabletype, size_t *width,
-                         size_t *precision, char *fmt, char *lng);
+gal_table_col_print_info(gal_data_t *col, int tabletype,
+                         char *fmt, char *lng);
 
 void
 gal_table_read_blank(gal_data_t *col, char *blank);
diff --git a/lib/table.c b/lib/table.c
index b8bbb56..ca2febe 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -122,17 +122,22 @@ gal_table_string_to_searchin(char *string)
 /************************************************************************/
 /***************          Printing information            ***************/
 /************************************************************************/
-/* Fill in the basic information necessary to print a column. This
+/* Fill in/adjust the basic information necessary to print a column. This
    information can be used for printing a plain text file or for FITS ASCII
    tables. The `fmt' and `lng' should point to pre-allocated arrays. The
-   best way is: `char fmt[2], lng[3];' in the same function calling this.*/
+   best way is: `char fmt[2], lng[3];' in the same function calling this.
+
+   The width and precision, which are also necessary for printing, are
+   updated in the data structure's `disp_width' and `disp_precision'
+   elements.
+*/
 void
-gal_table_col_print_info(gal_data_t *col, int tabletype, size_t *width,
-                         size_t *precision, char *fmt, char *lng)
+gal_table_col_print_info(gal_data_t *col, int tabletype, char *fmt, char *lng)
 {
   size_t j;
-  int maxstrlen;
   char **strarr;
+  int maxstrlen, width, precision;
+
 
   /* First do a sanity check, so we can safly stop checking in the steps
      below. */
@@ -143,7 +148,7 @@ gal_table_col_print_info(gal_data_t *col, int tabletype, 
size_t *width,
       break;
     default:
       error(EXIT_FAILURE, 0, "tabletype code %d not recognized in "
-            "`set_col_print_info'", tabletype);
+            "`gal_table_col_print_info'", tabletype);
     }
 
 
@@ -174,9 +179,9 @@ gal_table_col_print_info(gal_data_t *col, int tabletype, 
size_t *width,
       maxstrlen=0;
       strarr=col->array;
       for(j=0;j<col->size;++j)
-        maxstrlen = ( strlen(strarr[j]) > maxstrlen
-                      ? strlen(strarr[j]) : maxstrlen );
-      *width = col->disp_width>maxstrlen ? col->disp_width : maxstrlen;
+        maxstrlen = ( (int)strlen(strarr[j]) > maxstrlen
+                      ? (int)strlen(strarr[j]) : maxstrlen );
+      width = col->disp_width>maxstrlen ? col->disp_width : maxstrlen;
       break;
 
 
@@ -204,12 +209,12 @@ gal_table_col_print_info(gal_data_t *col, int tabletype, 
size_t *width,
       if(col->type==GAL_DATA_TYPE_ULONG)
         {
           lng[0]='l';
-          *width=( col->disp_width<=0 ? GAL_TABLE_DEF_LINT_WIDTH
-                   : col->disp_width );
+          width=( col->disp_width<=0 ? GAL_TABLE_DEF_LINT_WIDTH
+                  : col->disp_width );
         }
-      else *width=( col->disp_width<=0 ? GAL_TABLE_DEF_INT_WIDTH
+      else width=( col->disp_width<=0 ? GAL_TABLE_DEF_INT_WIDTH
                     : col->disp_width );
-      *precision=( col->disp_precision<=0 ? GAL_TABLE_DEF_INT_PRECISION
+      precision=( col->disp_precision<=0 ? GAL_TABLE_DEF_INT_PRECISION
                   : col->disp_precision );
       break;
 
@@ -221,10 +226,10 @@ gal_table_col_print_info(gal_data_t *col, int tabletype, 
size_t *width,
     case GAL_DATA_TYPE_SHORT:
     case GAL_DATA_TYPE_INT:
       fmt[0] = tabletype==GAL_TABLE_TYPE_TXT ? 'd' : 'I';
-      *width = ( col->disp_width<=0 ? GAL_TABLE_DEF_INT_WIDTH
-                 : col->disp_width );
-      *precision = ( col->disp_precision<=0 ? GAL_TABLE_DEF_INT_PRECISION
-                     : col->disp_precision );
+      width = ( col->disp_width<=0 ? GAL_TABLE_DEF_INT_WIDTH
+                : col->disp_width );
+      precision = ( col->disp_precision<=0 ? GAL_TABLE_DEF_INT_PRECISION
+                    : col->disp_precision );
       break;
 
 
@@ -235,9 +240,9 @@ gal_table_col_print_info(gal_data_t *col, int tabletype, 
size_t *width,
       lng[0] = 'l';
       fmt[0] = tabletype==GAL_TABLE_TYPE_TXT ? 'd' : 'I';
       lng[1] = col->type==GAL_DATA_TYPE_LONGLONG ? 'l' : '\0';
-      *width=( col->disp_width<=0 ? GAL_TABLE_DEF_LINT_WIDTH
+      width=( col->disp_width<=0 ? GAL_TABLE_DEF_LINT_WIDTH
               : col->disp_width );
-      *precision=( col->disp_precision<=0 ? GAL_TABLE_DEF_INT_PRECISION
+      precision=( col->disp_precision<=0 ? GAL_TABLE_DEF_INT_PRECISION
                   : col->disp_precision );
       break;
 
@@ -257,13 +262,13 @@ gal_table_col_print_info(gal_data_t *col, int tabletype, 
size_t *width,
         default:
           fmt[0] = tabletype==GAL_TABLE_TYPE_TXT ? 'f' : 'F'; break;
         }
-      *width = ( col->disp_width<=0
-                 ? ( col->type==GAL_DATA_TYPE_FLOAT
-                     ? GAL_TABLE_DEF_FLT_WIDTH
-                     : GAL_TABLE_DEF_DBL_WIDTH )
-                 : col->disp_width );
-      *precision = ( col->disp_precision<=0 ? GAL_TABLE_DEF_FLT_PRECISION
-                     : col->disp_precision );
+      width = ( col->disp_width<=0
+                ? ( col->type==GAL_DATA_TYPE_FLOAT
+                    ? GAL_TABLE_DEF_FLT_WIDTH
+                    : GAL_TABLE_DEF_DBL_WIDTH )
+                : col->disp_width );
+      precision = ( col->disp_precision<=0 ? GAL_TABLE_DEF_FLT_PRECISION
+                    : col->disp_precision );
       break;
 
 
@@ -272,6 +277,10 @@ gal_table_col_print_info(gal_data_t *col, int tabletype, 
size_t *width,
       error(EXIT_FAILURE, 0, "type code %d not recognized in "
             "`gal_table_col_print_info'", col->type);
     }
+
+  /* Write the final width and precision into the column's data structure. */
+  col->disp_width=width;
+  col->disp_precision=precision;
 }
 
 
diff --git a/lib/txt.c b/lib/txt.c
index 7c31544..fdc31ac 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -611,7 +611,7 @@ txt_fill_columns(char *line, char **tokens, size_t 
maxcolnum,
            compare the values. */
         case GAL_DATA_TYPE_FLOAT:
           f=col->array;
-          f[lineind]=strtof(tokens[col->status], &tailptr);
+          f[lineind]=strtod(tokens[col->status], &tailptr);
           if( (fb=colinfo[col->status-1].array)
               && ( (isnan(*fb) && isnan(f[lineind])) || *fb==f[lineind] ) )
             f[lineind]=GAL_DATA_BLANK_FLOAT;
@@ -755,7 +755,6 @@ make_fmts_for_printf(gal_data_t *cols, size_t numcols, int 
leftadjust,
   char **fmts;
   gal_data_t *col;
   char fmt[2], lng[3];
-  size_t width, precision;
 
 
   /* Allocate space for the output. */
@@ -795,49 +794,43 @@ make_fmts_for_printf(gal_data_t *cols, size_t numcols, 
int leftadjust,
             gal_checkset_allocate_copy(GAL_DATA_BLANK_STRING,
                                        &fmts[i*FMTS_COLS+2]);
           else
-            fmts[i*FMTS_COLS+2]=gal_data_blank_as_string(col->type);
+            fmts[i*FMTS_COLS+2]=gal_data_blank_as_string(col->type, 0);
         }
 
 
       /* Fill in the printing paramters. */
-      gal_table_col_print_info(col, GAL_TABLE_TYPE_TXT, &width,
-                               &precision, fmt, lng);
+      gal_table_col_print_info(col, GAL_TABLE_TYPE_TXT, fmt, lng);
 
 
       /* Adjust the width if a blank string was defined. */
       if(fmts[i*FMTS_COLS+2])
-        width = ( strlen(fmts[i*FMTS_COLS+2])>width
-                  ? strlen(fmts[i*FMTS_COLS+2])
-                  : width );
+        col->disp_width = ( strlen(fmts[i*FMTS_COLS+2]) > col->disp_width
+                            ? strlen(fmts[i*FMTS_COLS+2])
+                            : col->disp_width );
 
 
       /* Print the result into the allocated string and add its length to
          the final length of the overall format statement. The space in the
          end of `fmts[i*2]' is to ensure that the columns don't merge, even
          if the printed string is larger than the expected width. */
-      if(precision<=0)
-        *len += 1 + sprintf(fmts[i*FMTS_COLS], "%%%s%zu.%zu%s%s ",
-                            leftadjust ? "-" : "", width, precision,
-                            lng, fmt);
+      if(col->disp_precision > 0)
+        *len += 1 + sprintf(fmts[i*FMTS_COLS], "%%%s%d.%d%s%s ",
+                            leftadjust ? "-" : "", col->disp_width,
+                            col->disp_precision, lng, fmt);
       else
-        *len += 1 + sprintf(fmts[i*FMTS_COLS], "%%%s%zu%s%s ",
-                            leftadjust ? "-" : "", width, lng, fmt);
+        *len += 1 + sprintf(fmts[i*FMTS_COLS], "%%%s%d%s%s ",
+                            leftadjust ? "-" : "", col->disp_width, lng, fmt);
 
 
       /* Set the string for the Gnuastro type. For strings, we also need to
          write the maximum number of characters.*/
       if(col->type==GAL_DATA_TYPE_STRING)
-        sprintf(fmts[i*FMTS_COLS+1], "%s%zu",
-                gal_data_type_as_string(col->type, 0), width);
+        sprintf(fmts[i*FMTS_COLS+1], "%s%d",
+                gal_data_type_as_string(col->type, 0), col->disp_width);
       else
         strcpy(fmts[i*FMTS_COLS+1], gal_data_type_as_string(col->type, 0));
 
 
-      /* Update the column width and precision: */
-      col->disp_width = width;
-      col->disp_precision = precision;
-
-
       /* Increment the column counter. */
       ++i;
     }
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 162eafe..e4b3113 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -78,8 +78,8 @@ TESTS = $(check_PROGRAMS) prepconf.sh mkprof/mosaic1.sh 
mkprof/mosaic2.sh    \
   header/delete.sh imgstat/basicstats.sh subtractsky/subtractsky.sh          \
   noisechisel/noisechisel.sh mkcatalog/simple.sh mkcatalog/aperturephot.sh   \
   arithmetic/snimage.sh arithmetic/onlynumbers.sh arithmetic/where.sh        \
-  arithmetic/or.sh cosmiccal/simpletest.sh table/asciitobinary.sh            \
-  table/binarytoascii.sh
+  arithmetic/or.sh cosmiccal/simpletest.sh table/txt-to-fits-binary.sh       \
+  table/fits-binary-to-txt.sh
 
 
 
@@ -89,7 +89,7 @@ TESTS = $(check_PROGRAMS) prepconf.sh mkprof/mosaic1.sh 
mkprof/mosaic2.sh    \
 EXTRA_DIST = $(TESTS) during-dev.sh mkprof/mkprofcat1.txt                   \
   mkprof/ellipticalmasks.txt mkprof/inputascanvas.txt                       \
   mkprof/mkprofcat2.txt mkprof/mkprofcat3.txt mkprof/mkprofcat4.txt         \
-  mkprof/radeccat.txt imgcrop/cat.txt table/asciitobinary.txt
+  mkprof/radeccat.txt imgcrop/cat.txt table/table.txt
 
 
 
@@ -128,8 +128,8 @@ mkprof/mosaic2.sh: prepconf.sh.log
 mkprof/mosaic3.sh: prepconf.sh.log
 mkprof/mosaic4.sh: prepconf.sh.log
 mkprof/radeccat.sh: prepconf.sh.log
-table/asciitobinary.sh: prepconf.sh.log
-table/binarytoascii.sh: table/asciitobinary.sh.log
+table/txt-to-fits-binary.sh: prepconf.sh.log
+table/fits-binary-to-txt.sh: table/txt-to-fits-binary.sh.log
 imgcrop/imgcat.sh: mkprof/mosaic1.sh.log
 imgcrop/wcscat.sh: mkprof/mosaic1.sh.log mkprof/mosaic2.sh.log     \
                    mkprof/mosaic3.sh.log mkprof/mosaic4.sh.log
diff --git a/tests/table/asciitobinary.txt b/tests/table/asciitobinary.txt
deleted file mode 100644
index c4533a0..0000000
--- a/tests/table/asciitobinary.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-1 2.323 43.34
-2 3213  1232
diff --git a/tests/table/binarytoascii.sh b/tests/table/fits-binary-to-txt.sh
similarity index 93%
rename from tests/table/binarytoascii.sh
rename to tests/table/fits-binary-to-txt.sh
index 650ac0c..faf807d 100755
--- a/tests/table/binarytoascii.sh
+++ b/tests/table/fits-binary-to-txt.sh
@@ -24,7 +24,7 @@
 # file exists (basicchecks.sh is in the source tree).
 prog=table
 execname=../bin/$prog/ast$prog
-table=asciitobinary.fits
+table=binary-table.fits
 
 
 
@@ -48,4 +48,4 @@ if [ ! -f $execname ] || [ ! -f $img ]; then exit 77; fi
 
 # Actual test script
 # ==================
-$execname $table --output=binarytoascii.txt -h1
+$execname $table --output=from-binary-table.txt -h1
diff --git a/tests/table/table.txt b/tests/table/table.txt
new file mode 100644
index 0000000..7538dd2
--- /dev/null
+++ b/tests/table/table.txt
@@ -0,0 +1,39 @@
+# A single table to test the reading and writing functions.
+#
+#  - It contains all the types.
+#  - String columns, names, and units have space characters.
+#  - Blank values in all the columns.
+#  - Empty lines (not comment or data.
+#  - Column information comments are not in the same order as data.
+#  - A column with no information.
+#  - Columns with missing information
+#  - Some blank values different from the internal blank values.
+
+# Column 10: DOUBLE      [no units, d]  Column with double values
+
+# Column 1:  UCHAR_DATA  [no units, uc, 255]  Column with unsigned char values
+# Column 2:              [no-units, c, -5] Column with char values
+# Column 3:  STRING data [, str21, no data]          Column with string values
+# Column 4:  USHORT data [,us] Column with unsigned short values
+# Column 5:              [no units, s]  Column with short values
+# Column 7:  LONG        [no units, l]  Column with long values
+# Column 8: LONGLONG    [no units, L]  Column with LONGLONG values
+# Column 9: FLOAT       [no units, f,-99]  Column with float values
+
+# Column 6:  UINT [,ui]
+
+
+
+
+1    -1    The vertical lines     3455    -3455  1  -1   9     2.3e4   
8.39133434352355
+2    -2    are only for easy      3466    -3466  2  -2   10    2300    
893.3497e50
+3    -3    identification of the  3467    -3467  3  -3   12    2.4     
93487.3473234343
+4    -4    limits of this string  3468    -3468  4  -4   800   894.83  8.2e8
+5    -5    |column. Characters |  3469    -3469  5  -5   8923  99.232  
-7.3238473343e4
+6    -6    |beyond this will be|  20821  -20821  6  -6   9823  8874.2  
769387424234234
+7    -7    read as a number.      20822  -20822  7  -7   7232  1E10    
8.3343e-5
+8    -8    no data                20823  -20823  8  -8   921   -8.4e2  
934892734.82
+9    -9    address@hidden@    60983  -25722  9  -9   8127  -99.0   
3474924.489252
+10  -10    Characters%^&*()~      62182  -30100 10  -10  8287  7.3e-9  
-3467.3432e10
+11  -127   no data                65500  -32700 11  -11  999   8.73e2  
897234.34897
+255 -12    -- Last Line :-) --    65501  -32701 12  -12  8282  892.23  
89750298.3653
diff --git a/tests/table/asciitobinary.sh b/tests/table/txt-to-fits-binary.sh
similarity index 91%
rename from tests/table/asciitobinary.sh
rename to tests/table/txt-to-fits-binary.sh
index 3093d3a..e20bc0e 100755
--- a/tests/table/asciitobinary.sh
+++ b/tests/table/txt-to-fits-binary.sh
@@ -24,7 +24,7 @@
 # file exists (basicchecks.sh is in the source tree).
 prog=table
 execname=../bin/$prog/ast$prog
-table=$topsrc/tests/$prog/asciitobinary.txt
+table=$topsrc/tests/$prog/table.txt
 
 
 
@@ -48,4 +48,4 @@ if [ ! -f $execname ] || [ ! -f $img ]; then exit 77; fi
 
 # Actual test script
 # ==================
-$execname $table --output=asciitobinary.fits
+$execname $table --output=binary-table.fits --tabletype=fits-binary



reply via email to

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