[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
- [gnuastro-commits] master a5a7c45 048/125: Correction in Gnuastro text table format, (continued)
- [gnuastro-commits] master a5a7c45 048/125: Correction in Gnuastro text table format, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 7b33afa 043/125: FITS ascii and binary table I/O done with tests, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master beeb995 055/125: Corrected options added for make check, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 0a1036f 025/125: Data structure with name, units, comments and status, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master e5373e0 034/125: Column info read from comments in ASCII tables, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master e8ddf69 058/125: Option description correction in mkprof, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 9bb47f3 051/125: New elements for argp_option for new option management, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 185cafa 045/125: Output type for binary arithmetic corrected, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master c59d66c 064/125: tmpfs-config-make now has the programs that can be built, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 23a541a 056/125: Single correction of string keyword values in FITS tables, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 4c28d13 042/125: Problem in reading blank FITS ASCII table fixed,
Mohammad Akhlaghi <=
- [gnuastro-commits] master 08927b8 044/125: New Table formats section in manual, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master eab25b1 059/125: Option descriptions also printed with values, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 909fa0d 050/125: Table info printing in libraries, updates to Table program, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 36bcedd 066/125: Fixed automatic output checking in Arithmetic, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master d2ed7ea 060/125: Options setdirconf and setusrconf implemented, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 08147ce 062/125: All mandatory options not given are listed with error, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master a9092e9 036/125: The table library can read ASCII inputs, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 77b7910 057/125: Program specific global variables for in options library, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 9e553f0 022/125: All old arithmetic operators are now implemented, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master b470ee4 023/125: More efficient macro implementation for binary operators, Mohammad Akhlaghi, 2017/04/23