[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnuastro-commits] master 620146e 028/125: Library function for writing
From: |
Mohammad Akhlaghi |
Subject: |
[gnuastro-commits] master 620146e 028/125: Library function for writing columns to txt file |
Date: |
Sun, 23 Apr 2017 22:36:30 -0400 (EDT) |
branch: master
commit 620146e4c0fd7f3152cea732d52f492257995958
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>
Library function for writing columns to txt file
It is now possible to write a linked list of data structure columns into an
ASCII text file with the `gal_txt_write' function. This function is also
called by `gal_table_write' function which (in the next commits) will also
functions for writing FITS tables.
---
bin/table/args.h | 8 +-
bin/table/asttable.conf | 1 -
bin/table/main.h | 4 +-
bin/table/table.c | 4 +-
bin/table/ui.c | 97 ++++++++++----
doc/gnuastro.texi | 18 ++-
lib/data-arithmetic-other.c | 4 +-
lib/data.c | 40 +++---
lib/fits.c | 28 +++-
lib/gnuastro/data.h | 3 +-
lib/gnuastro/fits.h | 8 +-
lib/gnuastro/table.h | 30 ++++-
lib/gnuastro/txt.h | 11 +-
lib/table.c | 77 +++++++++--
lib/txt.c | 314 ++++++++++++++++++++++++++++++++++++++++++++
15 files changed, 557 insertions(+), 90 deletions(-)
diff --git a/bin/table/args.h b/bin/table/args.h
index b1e9255..913c083 100644
--- a/bin/table/args.h
+++ b/bin/table/args.h
@@ -123,11 +123,11 @@ static struct argp_option options[] =
2
},
{
- "fitstabletype",
+ "outtabletype",
't',
"STR",
0,
- "Only `ascii', or `binary' are acceptable.",
+ "Type of output: `txt', `fits-ascii', `fits-binary'.",
2
},
@@ -203,8 +203,8 @@ parse_opt(int key, char *arg, struct argp_state *state)
/* Output: */
case 't':
- gal_checkset_allocate_copy(arg, &p->up.fitstabletype);
- p->up.fitstabletypeset=1;
+ gal_checkset_allocate_copy(arg, &p->up.outtabletype);
+ p->up.outtabletypeset=1;
break;
diff --git a/bin/table/asttable.conf b/bin/table/asttable.conf
index d76b989..5d82e1d 100644
--- a/bin/table/asttable.conf
+++ b/bin/table/asttable.conf
@@ -22,4 +22,3 @@
searchin name
# Output:
- fitstabletype binary
diff --git a/bin/table/main.h b/bin/table/main.h
index 9225956..9939d62 100644
--- a/bin/table/main.h
+++ b/bin/table/main.h
@@ -40,14 +40,14 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
struct uiparams
{
char *filename;
- char *fitstabletype;
+ char *outtabletype;
gal_data_t *allcolinfo;
char *searchin;
/* If values are set: */
int informationset;
int ignorecaseset;
- int fitstabletypeset;
+ int outtabletypeset;
int searchinset;
};
diff --git a/bin/table/table.c b/bin/table/table.c
index 98d2fb9..222e8d5 100644
--- a/bin/table/table.c
+++ b/bin/table/table.c
@@ -30,6 +30,7 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#include <unistd.h>
#include <gnuastro/fits.h>
+#include <gnuastro/table.h>
#include "main.h"
@@ -43,5 +44,6 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
void
table(struct tableparams *p)
{
-
+ gal_table_write(p->table, NULL, p->outtabletype, p->cp.output,
+ p->cp.dontdelete);
}
diff --git a/bin/table/ui.c b/bin/table/ui.c
index 11d5e4d..c3f8c29 100644
--- a/bin/table/ui.c
+++ b/bin/table/ui.c
@@ -133,11 +133,11 @@ readconfig(char *filename, struct tableparams *p)
else if(strcmp(name, "output")==0)
gal_checkset_allocate_copy_set(value, &cp->output, &cp->outputset);
- else if (strcmp(name, "fitstabletype")==0)
+ else if (strcmp(name, "outtabletype")==0)
{
- if(p->up.fitstabletypeset) continue;
- gal_checkset_allocate_copy_set(value, &p->up.fitstabletype,
- &p->up.fitstabletypeset);
+ if(p->up.outtabletypeset) continue;
+ gal_checkset_allocate_copy_set(value, &p->up.outtabletype,
+ &p->up.outtabletypeset);
}
@@ -192,8 +192,8 @@ printvalues(FILE *fp, struct tableparams *p)
fprintf(fp, "\n# Output:\n");
- if(up->fitstabletypeset)
- fprintf(fp, CONF_SHOWFMT"%s\n", "fitstabletype", p->up.fitstabletype);
+ if(up->outtabletypeset)
+ fprintf(fp, CONF_SHOWFMT"%s\n", "outtabletype", p->up.outtabletype);
/* For the operating mode, first put the macro to print the common
@@ -224,8 +224,6 @@ checkifset(struct tableparams *p)
if(cp->hduset==0)
GAL_CONFIGFILES_REPORT_NOTSET("hdu");
- if(up->fitstabletypeset==0)
- GAL_CONFIGFILES_REPORT_NOTSET("fitstabletype");
if(up->searchinset==0)
GAL_CONFIGFILES_REPORT_NOTSET("searchin");
@@ -257,29 +255,78 @@ checkifset(struct tableparams *p)
void
sanitycheck(struct tableparams *p)
{
+ char *suffix=NULL;
struct uiparams *up=&p->up;
- /* If we had a FITS filename, the output table type is automatically set
- with the `--fitstabletype' option. However, when the file is a text
- file, that option should be ignored and outtype should be set to
- the text file macro.*/
- if(gal_fits_name_is_fits(up->filename))
+
+ /* Set the searchin integer value. */
+ p->searchin=gal_table_searchin_from_str(p->up.searchin);
+
+
+ /* If the outtabletype option was given, then convert it to an easiy
+ usable integer. Note we cannot do this in the output filename check
+ below, since it is also necessary when there is an output file.*/
+ if(up->outtabletypeset)
{
- if( !strcmp(up->fitstabletype, "ascii") )
+ if( !strcmp(up->outtabletype, "txt") )
+ p->outtabletype=GAL_TABLE_TYPE_TXT;
+ else if( !strcmp(up->outtabletype, "fits-ascii") )
p->outtabletype=GAL_TABLE_TYPE_AFITS;
- else if( !strcmp(up->fitstabletype, "binary") )
+ else if( !strcmp(up->outtabletype, "fits-binary") )
p->outtabletype=GAL_TABLE_TYPE_BFITS;
else
- error(EXIT_FAILURE, 0, "the value to the `--fitstabletype' "
+ error(EXIT_FAILURE, 0, "the value to the `--outtabletype' "
"option on the command line or `fitstabletype' variable in "
- "any of the configuration files must be either `ascii', or "
- "`binary'. You have given `%s'", up->fitstabletype);
+ "any of the configuration files must be either `txt', "
+ "`fits-ascii' or `fits-binary'. You have given `%s'",
+ up->outtabletype);
}
- else
- p->outtabletype=GAL_TABLE_TYPE_TXT;
- /* Set the searchin integer value. */
- p->searchin=gal_table_searchin_from_str(p->up.searchin);
+
+ /* Set the output name if it wasn't given. */
+ if(p->cp.output==NULL)
+ {
+ /* Only set the output filename automatically if the output type is
+ given. A `NULL' output filename will indicate that the table
+ should be printed in STDOUT.*/
+ if(up->outtabletypeset)
+ {
+ /* Set the filename based on the type of table desired. For the
+ time being, there is only txt and FITS table formats, but we
+ might add other formats in the future, so the structure below
+ is defined to account for those future types.
+
+ Note that `p->outtabletype' is set above internally, so we
+ don't need a `default' case here.*/
+ switch(p->outtabletype)
+ {
+ case GAL_TABLE_TYPE_TXT:
+ suffix="_table.txt";
+ break;
+
+ case GAL_TABLE_TYPE_AFITS:
+ case GAL_TABLE_TYPE_BFITS:
+ suffix="_table.fits";
+ break;
+ }
+
+ /* Set the output name */
+ if(suffix)
+ gal_checkset_automatic_output(p->up.filename, suffix,
+ p->cp.removedirinfo,
+ p->cp.dontdelete, &p->cp.output);
+ }
+ }
+ /* If the output name was set and is a FITS file, make sure that the type
+ of the table is not a `txt'. */
+ else
+ {
+ if( gal_fits_name_is_fits(p->cp.output)
+ && p->outtabletype==GAL_TABLE_TYPE_TXT)
+ error(EXIT_FAILURE, 0, "desired output table is a FITS file, but "
+ "`outtabletype' is not a FITS table type. Please set it to "
+ "`fits-ascii', or `fits-binary'");
+ }
}
@@ -332,7 +379,7 @@ print_information_exit(struct tableparams *p)
printf("%-8zu%-25s%-20s%-18s%s\n", i+1,
name ? name : "N/A" ,
unit ? unit : "N/A" ,
- gal_data_type_string(allcols[i].type),
+ gal_data_type_string(allcols[i].type, 1),
comment ? comment : "N/A");
if(name) free(name);
if(unit) free(unit);
@@ -375,8 +422,8 @@ preparearrays(struct tableparams *p)
elements were added to the list is the reverse of the order that they
will be popped). */
gal_linkedlist_reverse_stll(&p->columns);
- p->table=gal_table_read_cols(p->up.filename, p->cp.hdu, p->columns,
- p->searchin, p->ignorecase, p->cp.minmapsize);
+ p->table=gal_table_read(p->up.filename, p->cp.hdu, p->columns,
+ p->searchin, p->ignorecase, p->cp.minmapsize);
}
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 3c75a6b..f770892 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -6429,12 +6429,18 @@ single precision floating point numbers.
(@option{=INT}) The number of digits to print after the floating point for
double precision floating point numbers.
address@hidden --fitstabletype
-(@option{=STR}) The type of FITS table when a FITS file is specified as the
-output. This option can only have two values: @option{binary}, or
address@hidden However, currently ASCII FITS table outputs are not yet
-implemented due to lack of need. If you need it, please get in touch with
-so we implement it.
address@hidden --outtabletype
+(@option{=STR}) The output table type (for example plain text, FITS ascii,
+or FITS binary). If this option is not called on the command-line or any of
+the configuration files and no output filename is given with the
address@hidden option (see @ref{Common options}), then the columns that
+are read will be printed in the standard output (on the command-line).
+However, if it is called, it can only have one of these values:
address@hidden, @option{fits-ascii}, @option{fits-binary} for the current
+types of recognized output table types. If the output is a FITS file, this
+option is necessary because there are two types of FITS tables.
+
+
@end table
diff --git a/lib/data-arithmetic-other.c b/lib/data-arithmetic-other.c
index bb26b2d..0478c2a 100644
--- a/lib/data-arithmetic-other.c
+++ b/lib/data-arithmetic-other.c
@@ -281,7 +281,7 @@ check_float_input(gal_data_t *in, int operator, char
*numstr)
"after it so it is directly read into the proper precision "
"floating point number (based on the number of non-zero "
"decimals it has)", gal_data_operator_string(operator), numstr,
- gal_data_type_string(in->type));
+ gal_data_type_string(in->type, 1));
}
}
@@ -786,7 +786,7 @@ data_arithmetic_where(unsigned char flags, gal_data_t *out,
error(EXIT_FAILURE, 0, "the condition operand to "
"`data_arithmetic_where' must be an `unsigned char' type, but "
"the given condition operator has a `%s' type",
- gal_data_type_string(cond->type));
+ gal_data_type_string(cond->type, 1));
/* The dimension and sizes of the out and condition data sets must be the
same. */
diff --git a/lib/data.c b/lib/data.c
index 548f70b..6bad8af 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -35,6 +35,7 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#include <sys/mman.h>
#include <gnuastro/data.h>
+#include <gnuastro/table.h>
#include <checkset.h>
#include <data-copy.h>
@@ -387,7 +388,9 @@ gal_data_initialize(gal_data_t *data, void *array, int type,
size_t i;
gal_data_t in;
- /* Do the simple copying cases. */
+ /* Do the simple copying cases. For the display elements, set them all to
+ impossible (negative) values so if not explicitly set by later steps,
+ the default values are used if/when printing.*/
data->status=0;
data->next=NULL;
data->ndim=ndim;
@@ -396,6 +399,7 @@ gal_data_initialize(gal_data_t *data, void *array, int type,
gal_checkset_allocate_copy(unit, &data->unit);
gal_checkset_allocate_copy(name, &data->name);
gal_checkset_allocate_copy(comment, &data->comment);
+ data->disp_fmt=data->disp_width=data->disp_precision=-1;
/* Copy the WCS structure. Note that the `in' data structure was just
@@ -1361,57 +1365,57 @@ gal_data_flag_blank(gal_data_t *data)
************** Types and copying ***************
*************************************************************/
char *
-gal_data_type_string(int type)
+gal_data_type_string(int type, int long_name)
{
switch(type)
{
case GAL_DATA_TYPE_BIT:
- return "bit";
+ if(long_name) return "bit"; else return "b";
case GAL_DATA_TYPE_UCHAR:
- return "unsigned char";
+ if(long_name) return "unsigned char"; else return "uc";
/* CFITSIO says "int for keywords, char for table columns". Here we
are only assuming table columns. So in practice this also applies
to TSBYTE.*/
case GAL_DATA_TYPE_CHAR: case GAL_DATA_TYPE_LOGICAL:
- return "char";
+ if(long_name) return "char"; else return "c";
case GAL_DATA_TYPE_STRING:
- return "string";
+ if(long_name) return "string"; else return "str";
case GAL_DATA_TYPE_USHORT:
- return "unsigned short";
+ if(long_name) return "unsigned short"; else return "us";
case GAL_DATA_TYPE_SHORT:
- return "short";
+ if(long_name) return "short"; else return "s";
case GAL_DATA_TYPE_UINT:
- return "unsigned int";
+ if(long_name) return "unsigned int"; else return "ui";
case GAL_DATA_TYPE_INT:
- return "int";
+ if(long_name) return "int"; else return "i";
case GAL_DATA_TYPE_ULONG:
- return "unsigned long";
+ if(long_name) return "unsigned long"; else return "ul";
case GAL_DATA_TYPE_LONG:
- return "long";
+ if(long_name) return "long"; else return "l";
case GAL_DATA_TYPE_LONGLONG:
- return "LONGLONG";
+ if(long_name) return "LONGLONG"; else return "L";
case GAL_DATA_TYPE_FLOAT:
- return "float";
+ if(long_name) return "float"; else return "f";
case GAL_DATA_TYPE_DOUBLE:
- return "double";
+ if(long_name) return "double"; else return "d";
case GAL_DATA_TYPE_COMPLEX:
- return "complex float";
+ if(long_name) return "complex float"; else return "cf";
case GAL_DATA_TYPE_DCOMPLEX:
- return "complex double";
+ if(long_name) return "complex double"; else return "cd";
default:
error(EXIT_FAILURE, 0, "type value of %d not recognized in "
@@ -1922,7 +1926,7 @@ data_arithmetic_convert_to_compiled_type(gal_data_t *in,
unsigned char flags)
}
else
{
- typestring=gal_data_type_string(in->type);
+ typestring=gal_data_type_string(in->type, 1);
error(EXIT_FAILURE, 0, "The given %s type data given to "
"binary operators is not compiled for native operation "
"and no larger types are compiled either.\n\nThe "
diff --git a/lib/fits.c b/lib/fits.c
index f7166ad..41e2ce0 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -1651,12 +1651,16 @@ static void
set_display_format(char *tdisp, gal_data_t *data, char *filename, char *hdu,
char *keyname)
{
- int isanint;
+ int isanint=0;
char *tailptr;
/* First, set the general display format */
switch(tdisp[0])
{
+ case 'A':
+ data->disp_fmt=GAL_TABLE_DISPLAY_FMT_STRING;
+ break;
+
case 'I':
isanint=1;
data->disp_fmt=GAL_TABLE_DISPLAY_FMT_DECIMAL;
@@ -1673,18 +1677,15 @@ set_display_format(char *tdisp, gal_data_t *data, char
*filename, char *hdu,
break;
case 'F':
- isanint=0;
data->disp_fmt=GAL_TABLE_DISPLAY_FMT_FLOAT;
break;
case 'E':
case 'D':
- isanint=0;
data->disp_fmt=GAL_TABLE_DISPLAY_FMT_EXP;
break;
case 'G':
- isanint=0;
data->disp_fmt=GAL_TABLE_DISPLAY_FMT_GENERAL;
break;
@@ -1709,7 +1710,7 @@ set_display_format(char *tdisp, gal_data_t *data, char
*filename, char *hdu,
case '\0': /* No precision given, use a default value. */
data->disp_precision = ( isanint
- ? GAL_TABLE_DEF_FLT_PRECISION
+ ? GAL_TABLE_DEF_INT_PRECISION
: GAL_TABLE_DEF_FLT_PRECISION );
break;
@@ -1863,8 +1864,8 @@ gal_fits_table_info(char *filename, char *hdu, size_t
*numcols,
low-level function, so the output data linked list is the inverse of the
input indexs linked list. You can use */
gal_data_t *
-gal_fits_read_cols(char *filename, char *hdu, gal_data_t *colinfo,
- struct gal_linkedlist_sll *indexll, int minmapsize)
+gal_fits_table_read(char *filename, char *hdu, gal_data_t *colinfo,
+ struct gal_linkedlist_sll *indexll, int minmapsize)
{
size_t ind;
void *blank;
@@ -1906,3 +1907,16 @@ gal_fits_read_cols(char *filename, char *hdu, gal_data_t
*colinfo,
gal_fits_io_error(status, NULL);
return out;
}
+
+
+
+
+
+/* Write the given columns (a linked list of `gal_data_t') into a FITS
+ table.*/
+void
+gal_fits_table_write(gal_data_t *cols, char *comments, int tabletype,
+ char *filename, int dontdelete)
+{
+
+}
diff --git a/lib/gnuastro/data.h b/lib/gnuastro/data.h
index deeea19..c0155df 100644
--- a/lib/gnuastro/data.h
+++ b/lib/gnuastro/data.h
@@ -103,7 +103,6 @@ __BEGIN_C_DECLS /* From C++ preparations */
-
/* Macros to identify the type of data. The macros in the comment
parenthesis is the equivalent macro in CFITSIO. */
enum gal_data_types
@@ -324,7 +323,7 @@ gal_data_flag_blank(gal_data_t *data);
************** Types and copying ***************
*************************************************************/
char *
-gal_data_type_string(int type);
+gal_data_type_string(int type, int long_name);
gal_data_t *
gal_data_copy(gal_data_t *in);
diff --git a/lib/gnuastro/fits.h b/lib/gnuastro/fits.h
index 8ccd595..21b1251 100644
--- a/lib/gnuastro/fits.h
+++ b/lib/gnuastro/fits.h
@@ -46,6 +46,7 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#include <gnuastro/data.h>
#include <gnuastro/table.h>
+#include <gnuastro/linkedlist.h>
/* C++ Preparations */
#undef __BEGIN_C_DECLS
@@ -258,9 +259,12 @@ gal_fits_table_info(char *filename, char *hdu, size_t
*numcols,
int *tabletype);
gal_data_t *
-gal_fits_read_cols(char *filename, char *hdu, gal_data_t *colinfo,
- struct gal_linkedlist_sll *indexll, int minmapsize);
+gal_fits_table_read(char *filename, char *hdu, gal_data_t *colinfo,
+ struct gal_linkedlist_sll *indexll, int minmapsize);
+void
+gal_fits_table_write(gal_data_t *cols, char *comments, int tabletype,
+ char *filename, int dontdelete);
diff --git a/lib/gnuastro/table.h b/lib/gnuastro/table.h
index ab620b6..56564e7 100644
--- a/lib/gnuastro/table.h
+++ b/lib/gnuastro/table.h
@@ -55,9 +55,18 @@ __BEGIN_C_DECLS /* From C++ preparations */
/* Macros: */
+#define GAL_TABLE_DEF_STR_WIDTH 10
+#define GAL_TABLE_DEF_INT_WIDTH 6
+#define GAL_TABLE_DEF_LINT_WIDTH 10
+#define GAL_TABLE_DEF_FLT_WIDTH 10
+#define GAL_TABLE_DEF_DBL_WIDTH 15
+
+#define GAL_TABLE_DEF_STR_PRECISION 0
+#define GAL_TABLE_DEF_INT_PRECISION 0
+#define GAL_TABLE_DEF_FLT_PRECISION 6
+#define GAL_TABLE_DEF_DBL_PRECISION 14
+
-#define GAL_TABLE_DEF_INT_PRECISION 0
-#define GAL_TABLE_DEF_FLT_PRECISION 8
@@ -93,7 +102,9 @@ enum gal_table_where_to_search
data.*/
enum gal_table_diplay_formats
{
- GAL_TABLE_DISPLAY_FMT_DECIMAL, /* Integers: decimal. */
+ GAL_TABLE_DISPLAY_FMT_STRING, /* String/Character. */
+ GAL_TABLE_DISPLAY_FMT_DECIMAL, /* Integers: signed decimal. */
+ GAL_TABLE_DISPLAY_FMT_UDECIMAL, /* Integers: unsigned decimal. */
GAL_TABLE_DISPLAY_FMT_OCTAL, /* Integers: octal. */
GAL_TABLE_DISPLAY_FMT_HEX, /* Integers: hexadecimal. */
GAL_TABLE_DISPLAY_FMT_FLOAT, /* Floats: with decimal point. */
@@ -106,6 +117,7 @@ enum gal_table_diplay_formats
/* Functions */
+
gal_data_t *
gal_table_info(char *filename, char *hdu, size_t *numcols, int *tabletype);
@@ -113,9 +125,15 @@ int
gal_table_searchin_from_str(char *searchin_str);
gal_data_t *
-gal_table_read_cols(char *filename, char *hdu,
- struct gal_linkedlist_stll *cols, int searchin,
- int ignorecase, int minmapsize);
+gal_table_read(char *filename, char *hdu, struct gal_linkedlist_stll *cols,
+ int searchin, int ignorecase, int minmapsize);
+
+void
+gal_table_write(gal_data_t *cols, char *comments, int tabletype,
+ char *filename, int dontdelete);
+
+
+
__END_C_DECLS /* From C++ preparations */
diff --git a/lib/gnuastro/txt.h b/lib/gnuastro/txt.h
index 68c3698..277d8c4 100644
--- a/lib/gnuastro/txt.h
+++ b/lib/gnuastro/txt.h
@@ -26,7 +26,7 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
/* Include other headers if necessary here. Note that other header files
must be included before the C++ preparations below */
-#include <gnuastro/fits.h> /* Includes `gnuastro/data.h' and `fitsio.h' */
+#include <gnuastro/data.h>
@@ -53,10 +53,19 @@ __BEGIN_C_DECLS /* From C++ preparations */
+/* Macros */
+#define GAL_TXT_MAX_FMT_LENGTH 20
+
+/* Functions */
gal_data_t *
gal_txt_table_info(char *filename, size_t *numcols);
+void
+gal_txt_write(gal_data_t *cols, char *comment, char *filename,
+ int dontdelete);
+
+
diff --git a/lib/table.c b/lib/table.c
index b81402c..deaf460 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -33,6 +33,14 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#include <gnuastro/table.h>
+
+
+
+
+
+
+
+
/************************************************************************/
/*************** Information about a table ***************/
/************************************************************************/
@@ -283,23 +291,21 @@ make_list_of_indexs(struct gal_linkedlist_stll *cols,
gal_data_t *allcols,
linked list of data structures. If the file is FITS, then `hdu' will
also be used, otherwise, `hdu' is ignored. The information to search for
columns should be specified by the `cols' linked list as string values
- in each node of the list. The `tosearch' value comes from the
+ in each node of the list, the strings in each node can be a number, an
+ exact match to a column name, or a regular expression (in GNU AWK
+ format) enclosed in `/ /'. The `tosearch' value comes from the
`gal_table_where_to_search' enumerator and has to be one of its given
types. If `cols' is NULL, then this function will read the full table.
The output is a linked list with the same order of the cols linked
- list. If all the columns are to be read, the output will be the in the
- order of the table, so the first column is the first popped data
- structure and so on.
-
- Recall that linked lists are last-in-first-out, so the last element you
- add to the list is the first one that this function will pop. If you
- want to reverse this order, you can call the
- `gal_linkedlist_reverse_stll' function in `linkedlist.h'.*/
+ list. Note that one column node in the `cols' list might give multiple
+ columns, in this case, the order of output columns that correspond to
+ that one input, are in order of the table (which column was read first).
+ So the first requested column is the first popped data structure and so
+ on. */
gal_data_t *
-gal_table_read_cols(char *filename, char *hdu,
- struct gal_linkedlist_stll *cols, int searchin,
- int ignorecase, int minmapsize)
+gal_table_read(char *filename, char *hdu, struct gal_linkedlist_stll *cols,
+ int searchin, int ignorecase, int minmapsize)
{
int tabletype;
size_t i, numcols;
@@ -332,7 +338,7 @@ gal_table_read_cols(char *filename, char *hdu,
case GAL_TABLE_TYPE_AFITS:
case GAL_TABLE_TYPE_BFITS:
- out=gal_fits_read_cols(filename, hdu, allcols, indexll, minmapsize);
+ out=gal_fits_table_read(filename, hdu, allcols, indexll, minmapsize);
break;
default:
@@ -352,3 +358,48 @@ gal_table_read_cols(char *filename, char *hdu,
/* Return the final linked list. */
return out;
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/************************************************************************/
+/*************** Write a table ***************/
+/************************************************************************/
+void
+gal_table_write(gal_data_t *cols, char *comments, int tabletype,
+ char *filename, int dontdelete)
+{
+ /* If a filename was given, then the tabletype is relevant and must be
+ used. When the filename is empty, a text table must be printed on the
+ standard output (on the command-line). */
+ if(filename)
+ switch(tabletype)
+ {
+ case GAL_TABLE_TYPE_TXT:
+ gal_txt_write(cols, comments, filename, dontdelete);
+ break;
+
+ case GAL_TABLE_TYPE_AFITS:
+ case GAL_TABLE_TYPE_BFITS:
+ gal_fits_table_write(cols, comments, tabletype, filename, dontdelete);
+ break;
+ }
+ else
+ gal_txt_write(cols, comments, filename, dontdelete);
+}
diff --git a/lib/txt.c b/lib/txt.c
index 696e18b..7272238 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -22,12 +22,17 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
**********************************************************************/
#include <config.h>
+#include <math.h>
#include <stdio.h>
#include <errno.h>
#include <error.h>
+#include <string.h>
#include <stdlib.h>
#include <gnuastro/txt.h>
+#include <gnuastro/table.h>
+
+#include <checkset.h>
/************************************************************************/
@@ -39,3 +44,312 @@ gal_txt_table_info(char *filename, size_t *numcols)
return NULL;
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/************************************************************************/
+/*************** Write a txt table ***************/
+/************************************************************************/
+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;
+
+ /* Allocate space for the output. */
+ errno=0;
+ fmts=malloc(2*numcols*sizeof *fmts);
+ if(fmts==NULL)
+ error(EXIT_FAILURE, errno, "%zu bytes for fmts in `gal_txt_write'",
+ numcols*sizeof *fmts);
+
+ /* Initialize the length to 0. */
+ *len=0;
+
+ /* Go over all the columns and make their formats. */
+ for(tmp=cols;tmp!=NULL;tmp=tmp->next)
+ {
+ /* Initialize */
+ lng="";
+
+ /* 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);
+
+ /* Write the proper format. */
+ switch(tmp->type)
+ {
+
+ case GAL_DATA_TYPE_BIT:
+ error(EXIT_FAILURE, 0, "printing of bit types is currently "
+ "not supported");
+ break;
+
+ case GAL_DATA_TYPE_STRING:
+ 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 );
+ break;
+
+
+ case GAL_DATA_TYPE_UCHAR:
+ case GAL_DATA_TYPE_USHORT:
+ case GAL_DATA_TYPE_UINT:
+ case GAL_DATA_TYPE_ULONG:
+
+ /* If we have a long type, then make changes. */
+ if(tmp->type==GAL_DATA_TYPE_ULONG)
+ {
+ lng="l";
+ width=( tmp->disp_width<0 ? GAL_TABLE_DEF_LINT_WIDTH
+ : tmp->disp_width );
+ }
+ else width=( tmp->disp_width<0 ? GAL_TABLE_DEF_INT_WIDTH
+ : tmp->disp_width );
+ precision=( tmp->disp_precision<0 ? GAL_TABLE_DEF_INT_PRECISION
+ : tmp->disp_precision );
+
+ /* Set the final printing format. */
+ switch(tmp->disp_fmt)
+ {
+ case GAL_TABLE_DISPLAY_FMT_UDECIMAL: fmt="u"; break;
+ case GAL_TABLE_DISPLAY_FMT_OCTAL: fmt="o"; break;
+ case GAL_TABLE_DISPLAY_FMT_HEX: fmt="X"; break;
+ default: fmt="u";
+ }
+ break;
+
+
+ case GAL_DATA_TYPE_CHAR:
+ case GAL_DATA_TYPE_LOGICAL:
+ case GAL_DATA_TYPE_SHORT:
+ case GAL_DATA_TYPE_INT:
+ fmt="d";
+ width=( tmp->disp_width<0 ? GAL_TABLE_DEF_INT_WIDTH
+ : tmp->disp_width );
+ precision=( tmp->disp_precision<0 ? GAL_TABLE_DEF_INT_PRECISION
+ : tmp->disp_precision );
+ break;
+
+
+ case GAL_DATA_TYPE_LONG:
+ case GAL_DATA_TYPE_LONGLONG:
+ fmt="d";
+ lng = tmp->type==GAL_DATA_TYPE_LONG ? "l" : "ll";
+ width=( tmp->disp_width<0 ? GAL_TABLE_DEF_LINT_WIDTH
+ : tmp->disp_width );
+ precision=( tmp->disp_precision<0 ? GAL_TABLE_DEF_INT_PRECISION
+ : tmp->disp_precision );
+ break;
+
+
+ case GAL_DATA_TYPE_FLOAT:
+ case GAL_DATA_TYPE_DOUBLE:
+ switch(tmp->disp_fmt)
+ {
+ case GAL_TABLE_DISPLAY_FMT_FLOAT: fmt="f"; break;
+ case GAL_TABLE_DISPLAY_FMT_EXP: fmt="e"; break;
+ case GAL_TABLE_DISPLAY_FMT_GENERAL: fmt="g"; break;
+ default: fmt="f";
+ }
+ width=( tmp->disp_width<0
+ ? ( tmp->type==GAL_DATA_TYPE_FLOAT
+ ? GAL_TABLE_DEF_FLT_WIDTH
+ : GAL_TABLE_DEF_DBL_WIDTH )
+ : tmp->disp_width );
+ precision=( tmp->disp_precision<0 ? GAL_TABLE_DEF_FLT_PRECISION
+ : tmp->disp_precision );
+ break;
+
+ default:
+ error(EXIT_FAILURE, 0, "type code %d not recognized for output "
+ "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.*/
+ *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);
+
+ /* Increment the column counter. */
+ ++i;
+ }
+
+ /* Return the array. */
+ return fmts;
+}
+
+
+
+
+
+void
+gal_txt_write(gal_data_t *cols, char *comment, char *filename,
+ int dontdelete)
+{
+ FILE *fp;
+ char **fmts;
+ gal_data_t *tmp;
+ 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)
+ {
+ ++numcols;
+ 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);
+ if( tmp->name && strlen(tmp->name)>nw ) nw=strlen(tmp->name);
+ if( tmp->unit && strlen(tmp->unit)>uw ) uw=strlen(tmp->unit);
+ }
+
+
+ /* 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 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;
+ }
+
+
+ /* Write the comments if there as any */
+ if(comment) fprintf(fp, "%s\n", comment);
+
+
+ /* Write the given information. */
+ i=0;
+ iw=log10(numcols)+1;
+ for(tmp=cols;tmp!=NULL;tmp=tmp->next)
+ {
+ fprintf(fp, "# Column %-*zu %-*s [ %-*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;
+ }
+
+
+ /* Print the output */
+ for(i=0;i<cols->size;++i) /* Loop over each row. */
+ {
+ j=0;
+ for(tmp=cols;tmp!=NULL;tmp=tmp->next) /* Loop over each column. */
+ {
+ switch(tmp->type)
+ {
+ case GAL_DATA_TYPE_UCHAR:
+ fprintf(fp, fmts[j*2], ((unsigned char *)tmp->array)[i]);
+ break;
+ case GAL_DATA_TYPE_CHAR:
+ case GAL_DATA_TYPE_LOGICAL:
+ fprintf(fp, fmts[j*2], ((char *)tmp->array)[i]);
+ break;
+ case GAL_DATA_TYPE_STRING:
+ fprintf(fp, fmts[j*2], ((char **)tmp->array)[i]);
+ break;
+ case GAL_DATA_TYPE_USHORT:
+ fprintf(fp, fmts[j*2], ((unsigned short *)tmp->array)[i]);
+ break;
+ case GAL_DATA_TYPE_SHORT:
+ fprintf(fp, fmts[j*2], ((short *)tmp->array)[i]);
+ break;
+ case GAL_DATA_TYPE_UINT:
+ fprintf(fp, fmts[j*2], ((unsigned int *)tmp->array)[i]);
+ break;
+ case GAL_DATA_TYPE_INT:
+ fprintf(fp, fmts[j*2], ((int *)tmp->array)[i]);
+ break;
+ case GAL_DATA_TYPE_ULONG:
+ fprintf(fp, fmts[j*2], ((unsigned long *)tmp->array)[i]);
+ break;
+ case GAL_DATA_TYPE_LONG:
+ fprintf(fp, fmts[j*2], ((long *)tmp->array)[i]);
+ break;
+ case GAL_DATA_TYPE_LONGLONG:
+ fprintf(fp, fmts[j*2], ((LONGLONG *)tmp->array)[i]);
+ break;
+ case GAL_DATA_TYPE_FLOAT:
+ fprintf(fp, fmts[j*2], ((float *)tmp->array)[i]);
+ break;
+ case GAL_DATA_TYPE_DOUBLE:
+ fprintf(fp, fmts[j*2], ((double *)tmp->array)[i]);
+ break;
+ default:
+ error(EXIT_FAILURE, 0, "type code %d not recognized for "
+ "tmp->type in `gal_txt_write'", tmp->type);
+ }
+ ++j;
+ }
+ fprintf(fp, "\n");
+ }
+
+
+ /* 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]);
+ free(fmts);
+ if(filename)
+ {
+ errno=0;
+ if(fclose(fp))
+ error(EXIT_FAILURE, errno, "%s: couldn't close file after writing "
+ "of text table", filename);
+ }
+}
- [gnuastro-commits] master 3ad83a4 010/125: data-arithmetic and data-copy separated from data.c, (continued)
- [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, 2017/04/23
- [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 <=
- [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
- [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