[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnuastro-commits] master 6d68470 033/125: Column info format for writin
From: |
Mohammad Akhlaghi |
Subject: |
[gnuastro-commits] master 6d68470 033/125: Column info format for writing ASCII tables |
Date: |
Sun, 23 Apr 2017 22:36:31 -0400 (EDT) |
branch: master
commit 6d68470dec359c527c5747970bff498f0a4ad227
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>
Column info format for writing ASCII tables
The old ASCII column information was very rudimentary and included the
exact `printf' formatting for that column. However, for all numerical types
this detailed information is irrelevant and for strings, we only need the
width. So now, the column information follows this format (where all the
values written in capital letters can be randomly set).
# Column NUM: NAME [UNIT, TYPE] COMMENT
`NAME', `UNIT', and `COMMENT' are just strings and can have any ASCII
characters except the new-line and `[' for NAME, and `,' for UNIT (which
specify the limits of the respective field in the last two cases). Also,
any number of spaces between each element and the next separator is
acceptable.
During the process the following two issues were also addressed:
* A notice was put in `gal_fits_table_write' to inform the user that this
function is not ready/implemented yet.
* Report an error if the user asks for column number 0. The column
numbering starts from one in Gnuastro. Until now, the numberical value
was stored in the same `if' statement, so when the input value was `0',
it would fail and go onto making an exact match check. Now, the long
type value is read before the check, so if it is zero, control goes into
the numerical/integer branch.
* In making an exact match, until now there was no check, so if there was
no exact match, it would just ignore it. But now if there is at least
not one match, there will be an error.
* In `configure.ac', the result for `HAVE_BIN_OP_LONGLONG', was mistakenly
written as `HAVE_BIN_OP_LONG', so in the output `lib/config.h', it would
be blank. This is now corrected.
---
configure.ac | 2 +-
lib/fits.c | 2 +-
lib/table.c | 101 ++++++++++++++++++++++++++++++++++++++---------------------
lib/txt.c | 80 +++++++++++++++++++++++++++++++---------------
4 files changed, 123 insertions(+), 62 deletions(-)
diff --git a/configure.ac b/configure.ac
index 36cda35..d61293e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -396,7 +396,7 @@ AC_ARG_ENABLE([bin-op-longlong],
AS_IF([test "x$binop_longlong" != x0], [binoptprint=yes], [binoptprint=no])
AC_DEFINE_UNQUOTED([GAL_CONFIG_BIN_OP_LONGLONG], [$binop_longlong],
[Native binary operations on LONGLONG data.])
-AC_SUBST(HAVE_BIN_OP_LONG, [$binop_longlong])
+AC_SUBST(HAVE_BIN_OP_LONGLONG, [$binop_longlong])
AC_MSG_RESULT($binoptprint)
AC_MSG_CHECKING(whether to compile float native binary data operators)
diff --git a/lib/fits.c b/lib/fits.c
index 44b4cd8..e5efd59 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -1917,5 +1917,5 @@ void
gal_fits_table_write(gal_data_t *cols, char *comments, int tabletype,
char *filename, int dontdelete)
{
-
+ error(EXIT_FAILURE, 0, "writing FITS tables is not implemented yet!");
}
diff --git a/lib/table.c b/lib/table.c
index deaf460..80f0efb 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -174,16 +174,17 @@ make_list_of_indexs(struct gal_linkedlist_stll *cols,
gal_data_t *allcols,
size_t numcols, int searchin, int ignorecase,
char *filename, char *hdu)
{
- size_t i;
long tlong;
int regreturn;
regex_t *regex;
+ size_t i, numexact;
char *str, *strcheck, *tailptr;
struct gal_linkedlist_stll *tmp;
struct gal_linkedlist_sll *indexll=NULL;
for(tmp=cols; tmp!=NULL; tmp=tmp->next)
{
+
/* REGULAR EXPRESSION: When the first and last characters are `/'. */
if( tmp->v[0]=='/' && tmp->v[strlen(tmp->v)-1]=='/' )
{
@@ -234,46 +235,76 @@ make_list_of_indexs(struct gal_linkedlist_stll *cols,
gal_data_t *allcols,
regfree(regex);
}
- /* INTEGER: If the string is an integer, then tailptr should point to
- the null character. If it points to anything else, it shows that
- we are not dealing with an integer (usable as a column number). So
- floating point values are also not acceptable. */
- else if( (tlong=strtol(tmp->v, &tailptr, 0)) && *tailptr=='\0')
+
+ /* Not regular expression. */
+ else
{
- /* Make sure we are not dealing with a negative number! */
- if(tlong<0)
- error(EXIT_FAILURE, 0, "the column numbers given to the "
- "must not be negative, you have asked for `%ld'", tlong);
-
- /* Check if the given value is not larger than the number of
- columns in the input catalog (note that the user is counting
- from 1, not 0!) */
- if(tlong>numcols)
+ tlong=strtol(tmp->v, &tailptr, 0);
+
+ /* INTEGER: If the string is an integer, then tailptr should
+ point to the null character. If it points to anything else, it
+ shows that we are not dealing with an integer (usable as a
+ column number). So floating point values are also not
+ acceptable. Since it is possible for the users to give zero
+ for the column number, we need to read the string as a number
+ first, then check it here. */
+ if(*tailptr=='\0')
{
- if(gal_fits_name_is_fits(filename))
- error(EXIT_FAILURE, 0, "%s (hdu %s): has %zu columns, but "
- "you have asked for column number %zu", filename,
- hdu, numcols, tlong);
- else
- error(EXIT_FAILURE, 0, "%s: has %zu columns, but you have "
- "asked for column number %zu", filename,
- numcols, tlong);
+ /* Make sure the number is larger than zero! */
+ if(tlong<=0)
+ error(EXIT_FAILURE, 0, "the column numbers given to the "
+ "must not be zero, or negative. You have asked for "
+ "column %ld", tlong);
+
+ /* Check if the given value is not larger than the number of
+ columns in the input catalog (note that the user is
+ counting from 1, not 0!) */
+ if(tlong>numcols)
+ {
+ if(gal_fits_name_is_fits(filename))
+ error(EXIT_FAILURE, 0, "%s (hdu %s): has %zu columns, "
+ "but you have asked for column number %zu",
+ filename, hdu, numcols, tlong);
+ else
+ error(EXIT_FAILURE, 0, "%s: has %zu columns, but you "
+ "have asked for column number %zu", filename,
+ numcols, tlong);
+ }
+
+ /* Everything seems to be fine, put this column number in the
+ output column numbers linked list. Note that internally,
+ the column numbers start from 0, not 1.*/
+ gal_linkedlist_add_to_sll(&indexll, tlong-1);
}
- /* Everything seems to be fine, put this column number in the
- output column numbers linked list. Note that internally, the
- column numbers start from 0, not 1.*/
- gal_linkedlist_add_to_sll(&indexll, tlong-1);
- }
- /* EXACT MATCH: */
- else
- {
- for(i=0;i<numcols;++i)
+
+ /* EXACT MATCH: */
+ else
{
- SET_STRCHECK;
- if(strcheck && strcmp(tmp->v, strcheck)==0)
- gal_linkedlist_add_to_sll(&indexll, i);
+ /* Go through all the desired column information and add the
+ column number when there is a match.*/
+ numexact=0;
+ for(i=0;i<numcols;++i)
+ {
+ SET_STRCHECK;
+ if(strcheck && strcmp(tmp->v, strcheck)==0 )
+ {
+ ++numexact;
+ gal_linkedlist_add_to_sll(&indexll, i);
+ }
+ }
+
+ /* If there was no match, then report an error. */
+ if(numexact==0)
+ error(EXIT_FAILURE, 0, "`%s' didn't match exactly with any "
+ "of the column %s in %s (hdu: %s). To search in the "
+ "columns, or match multiple of them, enclose your "
+ "string in slashes (e.g., `/%s/') to use regular "
+ "expressions", tmp->v,
+ ( searchin==GAL_TABLE_SEARCH_NAME ? "names"
+ : ( searchin==GAL_TABLE_SEARCH_UNIT ? "units"
+ : "comments") ), filename, hdu, tmp->v );
}
}
}
diff --git a/lib/txt.c b/lib/txt.c
index 0b23069..478d8ed 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -156,15 +156,17 @@ gal_txt_table_info(char *filename, size_t *numcols)
/************************************************************************/
/*************** Write a txt table ***************/
/************************************************************************/
+/* Make an array of two strings for each column (in practice a two
+ dimensional array with 2 columns and a row for each input column). */
static char **
make_fmts_for_printf(gal_data_t *cols, size_t numcols, int leftadjust,
size_t *len)
{
- size_t i=0;
char **fmts;
gal_data_t *tmp;
- char *fmt=NULL, *lng;
int width=0, precision=0;
+ size_t i=0, j, maxstrlen=0;
+ char *fmt=NULL, *lng, **strarr;
/* Allocate space for the output. */
errno=0;
@@ -185,10 +187,11 @@ make_fmts_for_printf(gal_data_t *cols, size_t numcols,
int leftadjust,
/* First allocate the necessary space to keep the string. */
errno=0;
fmts[i*2]=malloc(GAL_TXT_MAX_FMT_LENGTH*sizeof *fmts[i*2]);
- if(fmts[i*2]==NULL)
- error(EXIT_FAILURE, errno, "%zu bytes for fmts[%zu] in "
- "`make_fmts_for_printf' of txt.c",
- GAL_TXT_MAX_FMT_LENGTH*sizeof *fmts[i], i);
+ fmts[i*2+1]=malloc(GAL_TXT_MAX_FMT_LENGTH*sizeof *fmts[i*2+1]);
+ if(fmts[i*2]==NULL || fmts[i*2+1]==NULL)
+ error(EXIT_FAILURE, errno, "%zu bytes for fmts[%zu] or fmts[%zu] "
+ "in `make_fmts_for_printf' of txt.c",
+ GAL_TXT_MAX_FMT_LENGTH*sizeof *fmts[i], i*2, i*2+1);
/* Write the proper format. */
switch(tmp->type)
@@ -200,11 +203,21 @@ make_fmts_for_printf(gal_data_t *cols, size_t numcols,
int leftadjust,
break;
case GAL_DATA_TYPE_STRING:
+ /* Set the basic information. */
fmt="s";
width=( tmp->disp_width<0 ? GAL_TABLE_DEF_STR_WIDTH
: tmp->disp_width );
precision=( tmp->disp_precision<0 ? GAL_TABLE_DEF_STR_PRECISION
: tmp->disp_precision );
+
+ /* For strings, we also need the maximum length of all the
+ columns, so go through all the strings in the column and find
+ the maximum length. */
+ strarr=tmp->array;
+ for(j=0;j<tmp->size;++j)
+ maxstrlen = ( strlen(strarr[j]) > maxstrlen
+ ? strlen(strarr[j])
+ : maxstrlen );
break;
@@ -282,13 +295,21 @@ make_fmts_for_printf(gal_data_t *cols, size_t numcols,
int leftadjust,
"column %zu (counting from 1)", tmp->type, i+1);
}
- /* Print the result into the allocated string. The space in the end
- here is to ensure that if the printed string is larger than the
- expected width, it the columns will not merger and at least one
- space character will be put between them.*/
+ /* 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. */
*len += 1 + sprintf(fmts[i*2], "%%%s%d.%d%s%s ", leftadjust ? "-" : "",
width, precision, lng, fmt);
- fmts[i*2+1] = gal_data_type_string(tmp->type, 0);
+
+ /* Set the string for the Gnuastro type. For strings, we also need to
+ write the maximum number of characters.*/
+ if(tmp->type==GAL_DATA_TYPE_STRING)
+ sprintf(fmts[i*2+1], "%s%zu", gal_data_type_string(tmp->type, 0),
+ maxstrlen);
+ else
+ strcpy(fmts[i*2+1], gal_data_type_string(tmp->type, 0));
+
/* Increment the column counter. */
++i;
@@ -309,21 +330,30 @@ gal_txt_write(gal_data_t *cols, char *comment, char
*filename,
FILE *fp;
char **fmts;
gal_data_t *tmp;
+ int iw=0, nw=0, uw=0, tw=0;
size_t i, j, numcols=0, fmtlen;
- int iw=0, fw=0, nw=0, uw=0, tw=0;
/* Find the number of columns, do a small sanity check, and get the
maximum width of the name and unit string if they are present. */
for(tmp=cols;tmp!=NULL;tmp=tmp->next)
{
+ /* Count. */
++numcols;
+
+ /* Make sure the columns are 1 dimensional. */
+ if(cols->ndim!=1)
+ error(EXIT_FAILURE, 0, "columns to print as an ASCII file must have "
+ "only one dimension. column %zu of the given set has %zu "
+ "dimensions", numcols, cols->ndim);
+
+ /* Make sure sizes match. */
if(cols->size!=tmp->size)
- error(EXIT_FAILURE, 0, "to print a set of columns, into a file, they "
- "must all have the same number of elements/rows. The inputs to "
- "`gal_txt_write' have different sizes: the first column has "
- "%zu, while column %zu as %zu elements", cols->size, numcols,
- tmp->size);
+ error(EXIT_FAILURE, 0, "to print a set of columns, as an ASCII "
+ "table, they must currently all have the same number of "
+ "elements/rows. The inputs to `gal_txt_write' have different "
+ "sizes: the first column has %zu, while column %zu as %zu "
+ "elements", cols->size, numcols, tmp->size);
if( tmp->name && strlen(tmp->name)>nw ) nw=strlen(tmp->name);
if( tmp->unit && strlen(tmp->unit)>uw ) uw=strlen(tmp->unit);
}
@@ -348,13 +378,10 @@ gal_txt_write(gal_data_t *cols, char *comment, char
*filename,
for the full list and concatenate all the separate input into it. */
fmts=make_fmts_for_printf(cols, numcols, 1, &fmtlen);
for(i=0;i<numcols;++i)
- {
- fw = strlen( fmts[ i*2 ] ) > fw ? strlen( fmts[ i*2 ] ) : fw;
- tw = strlen( fmts[ i*2+1 ] ) > tw ? strlen( fmts[ i*2+1 ] ) : tw;
- }
+ tw = strlen( fmts[ i*2+1 ] ) > tw ? strlen( fmts[ i*2+1 ] ) : tw;
- /* Write the comments if there as any */
+ /* Write the comments if there are any */
if(comment) fprintf(fp, "%s\n", comment);
@@ -363,12 +390,11 @@ gal_txt_write(gal_data_t *cols, char *comment, char
*filename,
iw=log10(numcols)+1;
for(tmp=cols;tmp!=NULL;tmp=tmp->next)
{
- fprintf(fp, "# Column %-*zu %-*s [ %-*s , %-*s , %-*s] %s\n",
+ fprintf(fp, "# Column %-*zu: %-*s [%-*s, %-*s] %s\n",
iw, i+1,
nw, tmp->name ? tmp->name : "",
uw, tmp->unit ? tmp->unit : "",
tw, fmts[i*2+1],
- fw, fmts[i*2],
tmp->comment ? tmp->comment : "");
++i;
}
@@ -432,7 +458,11 @@ gal_txt_write(gal_data_t *cols, char *comment, char
*filename,
/* Clean up, close the input file and return. For the fmts[i*2] elements,
the reason is that fmts[i*2+1] are literal strings, not allocated. So
they don't need freeing.*/
- for(i=0;i<numcols;++i) free(fmts[i*2]);
+ for(i=0;i<numcols;++i)
+ {
+ free(fmts[i*2]);
+ free(fmts[i*2+1]);
+ }
free(fmts);
if(filename)
{
- [gnuastro-commits] master 2dea9a7 011/125: All binary operator types set at configure time, (continued)
- [gnuastro-commits] master 2dea9a7 011/125: All binary operator types set at configure time, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master ff0b76d 018/125: New Data types section in book, bitwise not added, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master c62b01e 031/125: Corrected incrementation issue with and and or operators, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 0a32a82 027/125: Any number of searched columns from FITS are read, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master d0aa78e 005/125: Arithmetic operation on data structures in library, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 0ad0906 014/125: Bitwise operators available in arithmetic operations, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 3ad83a4 010/125: data-arithmetic and data-copy separated from data.c, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 6c6382a 013/125: Use of function instead of macros for binary operators, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master ce73959 030/125: Reading FITS keywords into linked list not array, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master e0e8679 017/125: Removed `anyblank' from datastructure, several new operators, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 6d68470 033/125: Column info format for writing ASCII tables,
Mohammad Akhlaghi <=
- [gnuastro-commits] master 0fd75fe 040/125: With no columns, Table program will print all columns, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 8090e6d 038/125: Corrections to FITS table reading, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 1156793 035/125: ASCII table information fully ready for selection, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 3c7773f 037/125: Table library prints ASCII columns with blanks, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 1dca684 047/125: Minor corrections to Gnuastro plain text table format, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 620146e 028/125: Library function for writing columns to txt file, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master 9ec7556 039/125: Table's output file type set common sense, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master de80e97 046/125: Further explanations on Gnuastro's plain text tables, Mohammad Akhlaghi, 2017/04/23
- [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