[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnuastro-commits] master 909fa0d 050/125: Table info printing in librar
From: |
Mohammad Akhlaghi |
Subject: |
[gnuastro-commits] master 909fa0d 050/125: Table info printing in libraries, updates to Table program |
Date: |
Sun, 23 Apr 2017 22:36:35 -0400 (EDT) |
branch: master
commit 909fa0d5b995dee3271ed1c83670c1ae73c66016
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>
Table info printing in libraries, updates to Table program
Printing the information of a given table on the command line in a nicely
formatted manner is now defined as the library function
`gal_table_print_info'. Previously, it was only usable within the Table
program. This was done because it is a very convenient feature and will
certainly be useful for checks or debugging in many program or library
development scenarios.
As part of this process, the width of the columns when printing column
information is not a hard-coded value any more, `gal_table_print_info' will
check the values before hand and set the width based on the values.
Another major change in this commit is that when the output of
`gal_txt_table_write' is not a file (to be sent to `stdout'), the column
information and comments will not be printed. This was done to allow easy
piping to other programs like AWK, or sort. The book was also corrected to
fully explain this change in the Table program.
---
bin/table/ui.c | 103 ++++++++++++++-------------------------------------
doc/gnuastro.texi | 54 +++++++++++++++------------
lib/gnuastro/table.h | 3 ++
lib/table.c | 55 +++++++++++++++++++++++++++
lib/txt.c | 102 +++++++++++++++++++++++++++++++++-----------------
5 files changed, 183 insertions(+), 134 deletions(-)
diff --git a/bin/table/ui.c b/bin/table/ui.c
index 4bfd1b9..8168572 100644
--- a/bin/table/ui.c
+++ b/bin/table/ui.c
@@ -304,72 +304,6 @@ sanitycheck(struct tableparams *p)
/**************************************************************/
-/*************** Information *****************/
-/**************************************************************/
-void
-print_information_exit(struct tableparams *p)
-{
- int tabletype;
- gal_data_t *allcols;
- size_t i, numcols, numrows;
- char *name, *unit, *comment;
-
- allcols=gal_table_info(p->up.filename, p->cp.hdu, &numcols, &numrows,
- &tabletype);
-
- /* Print the legend */
- 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");
- printf("%-8s%-25s%-20s%-18s%s\n", "---", "----", "-----", "----",
- "-------");
-
- /* For each column, print the information, then free them. */
- for(i=0;i<numcols;++i)
- {
- name = allcols[i].name; /* Just defined for easier */
- 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 : GAL_DATA_BLANK_STRING ,
- unit ? unit : GAL_DATA_BLANK_STRING ,
- gal_data_type_as_string(allcols[i].type, 1),
- comment ? comment : GAL_DATA_BLANK_STRING);
- if(name) free(name);
- if(unit) free(unit);
- if(comment) free(comment);
- }
-
- /* Clean everything else up and return successfully. */
- free(allcols);
- freeandreport(p);
- exit(EXIT_SUCCESS);
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**************************************************************/
/*************** Preparations *******************/
/**************************************************************/
void
@@ -390,20 +324,41 @@ preparearrays(struct tableparams *p)
/* If there was no actual data in the file, then inform the user */
if(allcols==NULL)
- error(EXIT_FAILURE, 0, "%s: no usable data rows (non-commented and "
- "non-blank lines)", p->up.filename);
+ error(EXIT_FAILURE, 0, "%s: no usable data rows", p->up.filename);
+
+ /* If the user just wanted information, then print it. */
+ if(p->information)
+ {
+ /* Print the file information. */
+ printf("--------\n");
+ printf("%s", p->up.filename);
+ if(gal_fits_name_is_fits(p->up.filename))
+ printf(" (hdu: %s)\n", p->cp.hdu);
+ else
+ printf("\n");
+
+ /* Print each column's information. */
+ gal_table_print_info(allcols, numcols, numrows);
+ }
/* Free the information from all the columns. */
for(i=0;i<numcols;++i)
gal_data_free(&allcols[i], 1);
free(allcols);
- /* Add the number of columns to the list. */
- for(i=1;i<=numcols;++i)
+ /* Add the number of columns to the list if the user wanted to print
+ the columns (didn't just want their information. */
+ if(p->information)
{
- asprintf(&numstr, "%zu", i);
- gal_linkedlist_add_to_stll(&p->columns, numstr);
+ freeandreport(p);
+ exit(EXIT_SUCCESS);
}
+ else
+ for(i=1;i<=numcols;++i)
+ {
+ asprintf(&numstr, "%zu", i);
+ gal_linkedlist_add_to_stll(&p->columns, numstr);
+ }
}
/* Reverse the list of column search criteria that we are looking for
@@ -481,10 +436,6 @@ setparams(int argc, char *argv[], struct tableparams *p)
/* Do a sanity check. */
sanitycheck(p);
- /* If the user just wanted the information, just print them and exit. */
- if(p->information)
- print_information_exit(p);
-
/* Make the array of input images. */
preparearrays(p);
}
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index fe4677e..ba84e4b 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -6588,7 +6588,7 @@ some simple examples.
Table will read/write, select, convert, or show the information of the
columns in FITS ASCII table, FITS binary table and plain text table files,
see @ref{Table formats}. Output columns can also be determined by number or
-regular expression matching of column names, units or comments. The
+regular expression matching of column names, units, or comments. The
executable name is @file{asttable} with the following general template
@example
@@ -6606,48 +6606,56 @@ $ asttable bintab.fits --information
$ asttable bintab.fits --column=/^MAG_/
## Only print the 2nd column, and the third column multiplied by 5
-$ asttable bintab.fits | awk '!/^#/@{print $2, address@hidden'
+$ asttable bintab.fits | awk '@{print $2, address@hidden'
## Only print those rows with a value in the 10th column above 100000
-$ asttable bintab.fits | awk '!/^#/$10>10e5 @address@hidden'
+$ asttable bintab.fits | awk '$10>10e5 @address@hidden'
## Sort the output columns by the third column, save output
-$ asttable bintab.fits | awk '!/^#/ | 'sort -k3 > output.txt
+$ asttable bintab.fits | 'sort -k3 > output.txt
## Convert a plain text table to a binary FITS table
$ asttable plaintext.txt --output=table.fits --tabletype=fits-binary
@end example
-In the absence of an output file, the selected columns will be printed on
-the command-line. In the absence of selected columns, all columns will be
-output. For the full list of options common to all Gnuastro programs please
-see @ref{Common options}. Options can also be stored in directory, user or
address@hidden GNU AWK
+In the absence of selected columns, all the input file's columns will be
+output. If the specified output is a FITS file, the type of FITS table
+(binary or ASCII) will be determined from the @option{--tabletype}
+option. If the output is not a FITS file, it will be printed as a plain
+text table (with space characters between the columns). When the columns
+are accompanied by meta-data (like column name, units, or comments), this
+information will also printed in the plain text file before the table, as
+described in @ref{Gnuastro text table format}.
+
+For the full list of options common to all Gnuastro programs please see
address@hidden options}. Options can also be stored in directory, user or
system-wide configuration files to avoid repeating on the command-line, see
address@hidden files}.
-
-Table does not follow Automatic output that is common in most Gnuastro, see
address@hidden output}. If no value is given to the @option{--output}
-option, the desired columns will be printed to the standard output (on the
-command-line). This feature makes it very useful to directly pipe the
-output as input to other programs as the examples above demonstrate.
address@hidden files}. Table does not follow Automatic output that is
+common in most Gnuastro programs, see @ref{Automatic output}. Thus, in the
+absence of an output file, the selected columns will be printed on the
+command-line with no column information, ready for redirecting to other
+tools like AWK or sort, similar to the examples above.
@table @option
@item -i
@itemx --information
-Print the information for each column and abort. The information for each
-column will be printed as a row on the command-line. The column name (if
-present), units (if present) and datatype will printed. Note that the FITS
-standard does not require a name or units for columns, only the datatype is
-mandatory. For plain text files, even types aren't mandatory, and all
-columns with no type will show a @code{double} type (see @ref{Gnuastro text
-table format})
+Only print the column information in the specified table on the
+command-line and exit. Each columns information (number, name, units, data
+type, and comments) will be printed as a row on the command-line. Note that
+the FITS standard only requires the data type (see @ref{Data types}) and in
+plain text tables, no meta-data/information is mandatory. Gnuastro has its
+own convention in the comments of a plain text table to store and transfer
+this information as described in @ref{Gnuastro text table format}. Note
+that if columns have been requested with the @option{--column} option
+(below), this option will be ignored if given.
@cindex AWK
@cindex GNU AWK
@item -c
@itemx --column
-(@option{=STR} or @option{=INT}) Specify the columns to output for this
+(@option{=STR}, or @option{=INT}) Specify the columns to output for this
table. If the value to this option is an integer number, the column number
will be used (counting from 1, Table will abort with an error if zero or
negative values are given). When the value can't be interpretted as an a
diff --git a/lib/gnuastro/table.h b/lib/gnuastro/table.h
index 6acc21a..419e84d 100644
--- a/lib/gnuastro/table.h
+++ b/lib/gnuastro/table.h
@@ -122,6 +122,9 @@ int
gal_table_string_to_searchin(char *string);
void
+gal_table_print_info(gal_data_t *allcols, size_t numcols, size_t numrows);
+
+void
gal_table_col_print_info(gal_data_t *col, int tabletype,
char *fmt, char *lng);
diff --git a/lib/table.c b/lib/table.c
index f28a919..62be3c2 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -122,6 +122,61 @@ gal_table_string_to_searchin(char *string)
/************************************************************************/
/*************** Printing information ***************/
/************************************************************************/
+void
+gal_table_print_info(gal_data_t *allcols, size_t numcols, size_t numrows)
+{
+ size_t i;
+ int Nw=3, nw=4, uw=5, tw=4; /* Initial width from label's width */
+ char *name, *unit, *comment;
+
+ /* Set the widths to print the column information. The width for the
+ column number can easily be identified from the logarithm of the
+ number of columns. */
+ Nw=log10(numcols)+1;
+ for(i=0;i<numcols;++i)
+ {
+ if(allcols[i].name && strlen(allcols[i].name)>nw)
+ nw=strlen(allcols[i].name);
+ if(allcols[i].unit && strlen(allcols[i].unit)>uw)
+ uw=strlen(allcols[i].unit);
+ if(allcols[i].type
+ && strlen(gal_data_type_as_string(allcols[i].type, 1))>tw)
+ tw=strlen(gal_data_type_as_string(allcols[i].type, 1));
+ }
+
+ /* We want one column space between the columns for readability, not the
+ exact length, so increment all the numbers. */
+ Nw+=2; nw+=2; uw+=2; tw+=2;
+
+ /* Print these column names. */
+ printf("%-*s%-*s%-*s%-*s%s\n", Nw, "---", nw, "----", uw,
+ "-----", tw, "----", "-------");
+ printf("%-*s%-*s%-*s%-*s%s\n", Nw, "No.", nw, "Name", uw,
+ "Units", tw, "Type", "Comment");
+ printf("%-*s%-*s%-*s%-*s%s\n", Nw, "---", nw, "----", uw,
+ "-----", tw, "----", "-------");
+
+ /* For each column, print the information, then free them. */
+ for(i=0;i<numcols;++i)
+ {
+ name = allcols[i].name; /* Just defined for easier */
+ unit = allcols[i].unit; /* readability. The compiler */
+ comment = allcols[i].comment; /* optimizer will remove them. */
+ printf("%-*zu%-*s%-*s%-*s%s\n", Nw, i+1,
+ nw, name ? name : GAL_DATA_BLANK_STRING ,
+ uw, unit ? unit : GAL_DATA_BLANK_STRING ,
+ tw, gal_data_type_as_string(allcols[i].type, 1),
+ comment ? comment : GAL_DATA_BLANK_STRING);
+ }
+
+ /* Print the number of rows. */
+ printf("--------\nNumber of rows: %zu\n--------\n", numrows);
+}
+
+
+
+
+
/* 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
diff --git a/lib/txt.c b/lib/txt.c
index 1a4becc..1f52917 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -933,10 +933,11 @@ gal_txt_table_write(gal_data_t *cols, char *comment, char
*filename,
int dontdelete)
{
FILE *fp;
+ char *nstr;
gal_data_t *col;
char **fmts, *tmp;
size_t i, j, numcols=0, fmtlen;
- int iw=0, nw=0, uw=0, tw=0, bw=0;
+ int nlen, nw=0, uw=0, tw=0, bw=0;
/* Find the number of columns, do a small sanity check, and get the
@@ -964,21 +965,6 @@ gal_txt_table_write(gal_data_t *cols, char *comment, char
*filename,
}
- /* Set the output FILE pointer: if it isn't NULL, its an actual file,
- otherwise, its the standard output. */
- if(filename)
- {
- gal_checkset_check_remove_file(filename, dontdelete);
- errno=0;
- fp=fopen(filename, "w");
- if(fp==NULL)
- error(EXIT_FAILURE, errno, "%s: couldn't be open to write text "
- "table", filename);
- }
- else
- fp=stdout;
-
-
/* Prepare the necessary formats for each column, then allocate the space
for the full list and concatenate all the separate inputs into it. */
fmts=make_fmts_for_printf(cols, numcols, 1, &fmtlen);
@@ -991,24 +977,68 @@ gal_txt_table_write(gal_data_t *cols, char *comment, char
*filename,
}
- /* Write the comments if there are any */
- if(comment) fprintf(fp, "%s\n", comment);
+ /* Set the output FILE pointer: if it isn't NULL, its an actual file,
+ otherwise, its the standard output. */
+ if(filename)
+ {
+ gal_checkset_check_remove_file(filename, dontdelete);
+ errno=0;
+ fp=fopen(filename, "w");
+ if(fp==NULL)
+ error(EXIT_FAILURE, errno, "%s: couldn't be open to write text "
+ "table", filename);
- /* Write the information for each column */
- i=0;
- iw=log10(numcols)+1;
- for(col=cols;col!=NULL;col=col->next)
- {
- fprintf(fp, "# Column %-*zu: %-*s [%-*s,%-*s,%-*s] %s\n",
- iw, i+1,
- nw, col->name ? col->name : "",
- uw, col->unit ? col->unit : "",
- tw, fmts[i*FMTS_COLS+1] ? fmts[i*FMTS_COLS+1] : "",
- bw, fmts[i*FMTS_COLS+2] ? fmts[i*FMTS_COLS+2] : "",
- col->comment ? col->comment : "");
- ++i;
+ /* Write the comments if there were any. */
+ if(comment) fprintf(fp, "%s\n", comment);
+
+
+ /* Write the column information if the output is a file. When the
+ output is directed to standard output (the command-line), it is
+ most probably intended for piping into another program (for
+ example AWK for further processing, or sort, or anything) so the
+ user already has the column information and is probably going to
+ change them, so they are just a nuisance.
+
+ When there are more than 9 columns, we don't want to have cases
+ like `# Column 1 :' (note the space between `1' and `:', this
+ space won't exist for the 2 digit colum numbers).
+
+ To do this, we are first allocating and printing a string long
+ enough to keep the final column's `N:'. Then, for each column, we
+ print only the number into the allocated space and put the `:' in
+ manually immediately after the number. Note that the initial
+ `asprintf' put a `\0' in the allocated space, so we can safely
+ over-write the one that `sprintf' puts with a `:' for the columns
+ that have the same number of digits as the final column. */
+ i=0;
+ asprintf(&nstr, "%zu:", numcols);
+ nlen=strlen(nstr);
+ for(col=cols; col!=NULL; col=col->next)
+ {
+ /* Print the number into the number string, then add the `:'
+ immediately after the number. */
+ sprintf(nstr, "%zu", i+1);
+ for(j=1;j<nlen;++j)
+ if(!isdigit(nstr[j])) nstr[j] = isdigit(nstr[j-1]) ? ':' : ' ';
+
+ /* Now print the full column information. */
+ fprintf(fp, "# Column %s %-*s [%-*s,%-*s,%-*s] %s\n",
+ nstr,
+ nw, col->name ? col->name : "",
+ uw, col->unit ? col->unit : "",
+ tw, fmts[i*FMTS_COLS+1] ? fmts[i*FMTS_COLS+1] : "",
+ bw, fmts[i*FMTS_COLS+2] ? fmts[i*FMTS_COLS+2] : "",
+ col->comment ? col->comment : "");
+ ++i;
+ }
+
+
+ /* Clean up */
+ free(nstr);
}
+ else /* Output wasn't a file, so set it to standard output */
+ fp=stdout;
/* Print the output */
@@ -1019,7 +1049,8 @@ gal_txt_table_write(gal_data_t *cols, char *comment, char
*filename,
{
switch(col->type)
{
- /* Integer types */
+
+ /* Numerical types. */
case GAL_DATA_TYPE_UCHAR:
fprintf(fp, fmts[j*FMTS_COLS],
((unsigned char *)col->array)[i]);
@@ -1085,9 +1116,7 @@ gal_txt_table_write(gal_data_t *cols, char *comment, char
*filename,
}
- /* Clean up, close the input file and return. For the fmts[i*FMTS_COLS]
- elements, the reason is that fmts[i*FMTS_COLS+1] are literal strings,
- not allocated. So they don't need freeing.*/
+ /* Clean up. */
for(i=0;i<numcols;++i)
{
free(fmts[i*FMTS_COLS]);
@@ -1095,6 +1124,9 @@ gal_txt_table_write(gal_data_t *cols, char *comment, char
*filename,
free(fmts[i*FMTS_COLS+2]);
}
free(fmts);
+
+
+ /* Close the output file. */
if(filename)
{
errno=0;
- [gnuastro-commits] master 0a1036f 025/125: Data structure with name, units, comments and status, (continued)
- [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, 2017/04/23
- [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 <=
- [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
- [gnuastro-commits] master 6b51397 077/125: Added -j8 to make examples in book, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master b5c9a64 063/125: Science and its tools and ImageCrop corrections in book, Mohammad Akhlaghi, 2017/04/23
- [gnuastro-commits] master edd5612 053/125: Single function to read all configuration files, Mohammad Akhlaghi, 2017/04/23