[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnuastro-commits] master d09e850 04/16: FITS table column information p
From: |
Mohammad Akhlaghi |
Subject: |
[gnuastro-commits] master d09e850 04/16: FITS table column information printed by Table |
Date: |
Wed, 24 Aug 2016 22:27:44 +0000 (UTC) |
branch: master
commit d09e85055ea4ca4a57e6821b542000d8eee40b8d
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>
FITS table column information printed by Table
Table can now print the basic column information of a given FITS ASCII or
Binary table (so far only tested on a binary table). This is far from
complete for this utility, but for the time being it is a significant step
(it actually prints something useful!).
The type of the `gal_fits_read_hdu' function was changed from the exact
CFITSIO macro to an image or table binary value so we could use this
function in reading tables too.
---
Makefile.am | 2 +-
lib/fits.c | 99 ++++++++++++++++++++++++++++---
lib/gnuastro/fits.h | 12 +++-
src/imgcrop/imgcrop.c | 4 +-
src/imgcrop/ui.c | 2 +-
src/table/args.h | 32 +++++-----
src/table/main.h | 19 +++++-
src/table/table.c | 76 +++++++++++++++++++++++-
src/table/ui.c | 157 ++++++++++++++++++++++++++++++++++++++++++++-----
9 files changed, 353 insertions(+), 50 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index fae1bf4..1c819fa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -108,7 +108,7 @@ SUBDIRS = bootstrapped/lib $(MAYBE_GNULIBCHECK) lib
$(MAYBE_ARITHMETIC) \
$(MAYBE_CONVERTT) $(MAYBE_CONVOLVE) $(MAYBE_COSMICCAL) $(MAYBE_HEADER) \
$(MAYBE_IMGCROP) $(MAYBE_IMGSTAT) $(MAYBE_IMGWARP) $(MAYBE_MKCATALOG) \
$(MAYBE_MKNOISE) $(MAYBE_MKPROF) $(MAYBE_NOISECHISEL) $(MAYBE_SUBTRACTSKY) \
-$(MAYBE_TEMPLATE) doc tests
+$(MAYBE_TABLE) $(MAYBE_TEMPLATE) doc tests
diff --git a/lib/fits.c b/lib/fits.c
index 1168bd3..922ba9a 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -733,7 +733,7 @@ hdutypestring(int hdutype)
/* Check the desired HDU in a FITS image and also if it has the
desired type. */
void
-gal_fits_read_hdu(char *filename, char *hdu, int desiredtype,
+gal_fits_read_hdu(char *filename, char *hdu, unsigned char img0_tab1,
fitsfile **outfptr)
{
size_t len;
@@ -758,11 +758,24 @@ gal_fits_read_hdu(char *filename, char *hdu, int
desiredtype,
if (fits_get_hdu_type(fptr, &hdutype, &status) )
gal_fits_io_error(status, NULL);
- if(hdutype!=desiredtype)
- error(EXIT_FAILURE, 0, "%s: HDU %s is %s, not %s",
- filename, hdu, hdutypestring(hdutype),
- hdutypestring(desiredtype));
+ /* Check if the type of the HDU is the expected type. We could have
+ written these as && conditions, but this is easier to read, it makes
+ no meaningful difference to the compiler. */
+ if(img0_tab1)
+ {
+ if(hdutype==IMAGE_HDU)
+ error(EXIT_FAILURE, 0, "%s: HDU %s is an image, not a table",
+ filename, hdu);
+ }
+ else
+ {
+ if(hdutype!=IMAGE_HDU)
+ error(EXIT_FAILURE, 0, "%s: HDU %s is %s, not an image",
+ filename, hdu, hdutypestring(hdutype));
+ }
+
+ /* Clean up. */
free(ffname);
}
@@ -1309,7 +1322,7 @@ gal_fits_read_wcs(char *filename, char *hdu, size_t
hstartwcs,
fitsfile *fptr;
/* Check HDU for realistic conditions: */
- gal_fits_read_hdu(filename, hdu, IMAGE_HDU, &fptr);
+ gal_fits_read_hdu(filename, hdu, 0, &fptr);
/* Read the WCS information: */
gal_fits_read_wcs_from_pointer(fptr, nwcs, wcs, hstartwcs, hendwcs);
@@ -1332,7 +1345,7 @@ gal_fits_read_wcs(char *filename, char *hdu, size_t
hstartwcs,
the macros in fitsarrayvv.h and depends on the type of the data.*/
int
gal_fits_hdu_to_array(char *filename, char *hdu, int *bitpix,
- void **array, size_t *s0, size_t *s1)
+ void **array, size_t *s0, size_t *s1)
{
void *bitblank;
fitsfile *fptr;
@@ -1340,7 +1353,7 @@ gal_fits_hdu_to_array(char *filename, char *hdu, int
*bitpix,
long naxes[2], fpixel[]={1,1};
/* Check HDU for realistic conditions: */
- gal_fits_read_hdu(filename, hdu, IMAGE_HDU, &fptr);
+ gal_fits_read_hdu(filename, hdu, 0, &fptr);
/* Get the bitpix and size of the image: */
gal_fits_img_bitpix_size(fptr, bitpix, naxes);
@@ -1516,6 +1529,76 @@ gal_fits_atof_correct_wcs(char *filename, char *hdu, int
bitpix,
/**************************************************************/
+/********** Table ************/
+/**************************************************************/
+/* The values to the TFORM header keyword are single letter capital
+ letters, but that is useless in identifying the data type of the
+ column. So this function will do the conversion based on the CFITSIO
+ manual.*/
+int
+gal_fits_tform_to_dtype(char tform)
+{
+ switch(tform)
+ {
+ case 'X':
+ return TBIT;
+ case 'B':
+ return TBYTE;
+ case 'L':
+ return TLOGICAL;
+ case 'A':
+ return TSTRING;
+ case 'I':
+ return TSHORT;
+ case 'J':
+ return TLONG;
+ case 'K':
+ return TLONGLONG;
+ case 'E':
+ return TFLOAT;
+ case 'D':
+ return TDOUBLE;
+ case 'C':
+ return TCOMPLEX;
+ case 'M':
+ return TDBLCOMPLEX;
+ case 'S':
+ return TSBYTE;
+ case 'V':
+ return TUINT;
+ case 'U':
+ return TUSHORT;
+ default:
+ error(EXIT_FAILURE, 0, "'%c' is not a recognized CFITSIO value for "
+ "the TFORMn header keyword(s).", tform);
+ }
+
+ error(EXIT_FAILURE, 0, "A bug! Please contact us so we can fix this. "
+ "For some reason, control has reached to the end of the "
+ "gal_fits_tform_to_dtype function in fits.c.");
+ return -1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**************************************************************/
/********** Check prepare file ************/
/**************************************************************/
/* We have the name of the input file. But in most cases, the files
diff --git a/lib/gnuastro/fits.h b/lib/gnuastro/fits.h
index a0456a4..216fdb4 100644
--- a/lib/gnuastro/fits.h
+++ b/lib/gnuastro/fits.h
@@ -172,7 +172,7 @@ void
gal_fits_img_bitpix_size(fitsfile *fptr, int *bitpix, long *naxis);
void
-gal_fits_read_hdu(char *filename, char *hdu, int desiredtype,
+gal_fits_read_hdu(char *filename, char *hdu, unsigned char img0_tab1,
fitsfile **outfptr);
void *
@@ -213,6 +213,16 @@ gal_fits_atof_correct_wcs(char *filename, char *hdu, int
bitpix,
/**************************************************************/
+/********** Table ************/
+/**************************************************************/
+int
+gal_fits_tform_to_dtype(char tform);
+
+
+
+
+
+/**************************************************************/
/********** Check prepare file ************/
/**************************************************************/
void
diff --git a/src/imgcrop/imgcrop.c b/src/imgcrop/imgcrop.c
index 849ed75..2f17b09 100644
--- a/src/imgcrop/imgcrop.c
+++ b/src/imgcrop/imgcrop.c
@@ -90,7 +90,7 @@ imgmodecrop(void *inparam)
/* The whole catalog is from one image, so you can get the
information here:*/
img=&p->imgs[crp->imgindex];
- gal_fits_read_hdu(img->name, cp->hdu, IMAGE_HDU, &crp->infits);
+ gal_fits_read_hdu(img->name, cp->hdu, 0, &crp->infits);
/* Go over all the outputs that are assigned to this thread: */
for(i=0;crp->indexs[i]!=GAL_THREADS_NON_THRD_INDEX;++i)
@@ -181,7 +181,7 @@ wcsmodecrop(void *inparam)
if(radecoverlap(crp))
{
gal_fits_read_hdu(p->imgs[crp->imgindex].name, p->cp.hdu,
- IMAGE_HDU, &crp->infits);
+ 0, &crp->infits);
if(log->name==NULL) cropname(crp);
diff --git a/src/imgcrop/ui.c b/src/imgcrop/ui.c
index 82679ff..c10e2ac 100644
--- a/src/imgcrop/ui.c
+++ b/src/imgcrop/ui.c
@@ -621,7 +621,7 @@ preparearrays(struct imgcropparams *p)
status=0;
img=&p->imgs[i];
gal_linkedlist_pop_from_stll(&p->up.gal_linkedlist_stll, &img->name);
- gal_fits_read_hdu(img->name, p->cp.hdu, IMAGE_HDU, &tmpfits);
+ gal_fits_read_hdu(img->name, p->cp.hdu, 0, &tmpfits);
gal_fits_img_bitpix_size(tmpfits, &p->bitpix, img->naxes);
gal_fits_read_wcs_from_pointer(tmpfits, &img->nwcs, &img->wcs,
p->hstartwcs, p->hendwcs);
diff --git a/src/table/args.h b/src/table/args.h
index 74fa061..0583dcd 100644
--- a/src/table/args.h
+++ b/src/table/args.h
@@ -155,39 +155,35 @@ parse_opt(int key, char *arg, struct argp_state *state)
/* Operating modes: */
case 'i':
p->information=1;
- p->informationset=1;
+ p->up.informationset=1;
break;
/* Read the non-option arguments: */
case ARGP_KEY_ARG:
- /* See what type of input value it is and put it in. */
- if( gal_fits_name_is_fits(arg) )
- {
- if(p->up.inputname)
- argp_error(state, "only one input image should be given");
- else
- p->up.inputname=arg;
- }
- else
- argp_error(state, "%s is not a valid file type", arg);
- break;
+ /* Table gets only one input argument. */
+ if(p->up.inputset)
+ argp_error(state, "only one input file should be given");
+ /* This is the first (and must be only) argument. */
+ p->up.inputset=1;
+ /* See what type of input this is, and save the value. */
+ if( gal_fits_name_is_fits(arg) )
+ p->up.fitsname=arg;
+ else
+ p->up.txtname=arg;
+ break;
/* The command line options and arguments are finished. */
case ARGP_KEY_END:
if(p->cp.setdirconf==0 && p->cp.setusrconf==0
&& p->cp.printparams==0)
- {
- if(state->arg_num==0)
- argp_error(state, "no argument given");
- if(p->up.inputname==NULL)
- argp_error(state, "no input FITS image(s) provided");
- }
+ if(state->arg_num==0)
+ argp_error(state, "no argument given");
break;
diff --git a/src/table/main.h b/src/table/main.h
index 0f3c1fb..7a15c05 100644
--- a/src/table/main.h
+++ b/src/table/main.h
@@ -36,9 +36,16 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
+
+
+
+/* User interface structure. */
struct uiparams
{
- char *inputname; /* Name of input file. */
+ char *fitsname; /* Name of input FITS file. */
+ char *txtname; /* Name of input text file. */
+
+ int inputset;
int informationset;
};
@@ -46,6 +53,7 @@ struct uiparams
+/* Main program parameters structure */
struct tableparams
{
/* Other structures: */
@@ -54,6 +62,15 @@ struct tableparams
/* Input: */
int information; /* ==1: only print information. */
+ fitsfile *fitsptr; /* FITS pointer (input or output). */
+
+ /* FITS table */
+ size_t nrows; /* Number of rows in table. */
+ size_t ncols; /* Number of columns in table. */
+ int *typecode; /* Type of data in column. */
+ char **tform; /* TFORM (another format for type). */
+ char **ttype; /* Column name (one word). */
+ char **tunit; /* Unit of values in column. */
/* Internal: */
int onlyview;
diff --git a/src/table/table.c b/src/table/table.c
index ab560f2..eb742f5 100644
--- a/src/table/table.c
+++ b/src/table/table.c
@@ -29,14 +29,86 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#include <stdlib.h>
#include <gnuastro/fits.h>
-#include <gnuastro/linkedlist.h>
#include "main.h"
+
+/* Print all the column information: */
void
-table(struct tableparams *p)
+printinfo(struct tableparams *p)
{
+ size_t i;
+ char *typestring=NULL;
+
+ printf("%s (hdu: %s)\n", p->up.fitsname, p->cp.hdu);
+ printf("Number of rows: %lu\n", p->nrows);
+ printf("Column information\n");
+ printf("------------------\n");
+ for(i=1;i<=p->ncols;++i)
+ {
+ switch(p->typecode[i])
+ {
+ case TBIT:
+ typestring="bit";
+ break;
+ case TBYTE:
+ typestring="byte";
+ break;
+ case TLOGICAL:
+ typestring="logicals";
+ break;
+ case TSTRING:
+ typestring="string";
+ break;
+ case TSHORT:
+ typestring="short";
+ break;
+ case TLONG:
+ typestring="long";
+ break;
+ case TLONGLONG:
+ typestring="longlong";
+ break;
+ case TFLOAT:
+ typestring="float";
+ break;
+ case TDOUBLE:
+ typestring="double";
+ break;
+ case TCOMPLEX:
+ typestring="complex";
+ break;
+ case TDBLCOMPLEX:
+ typestring="dblcomplex";
+ break;
+ case TSBYTE:
+ typestring="signed byte";
+ break;
+ case TUINT:
+ typestring="unsigned int";
+ break;
+ case TUSHORT:
+ typestring="unsigned short";
+ break;
+ default:
+ error(EXIT_FAILURE, 0, "%d (from TFORM%lu='%c') is not a "
+ "recognized CFITSIO datatype.",
+ p->typecode[i], i, p->tform[i][0]);
+ }
+ printf("%-3lu %-25s %-20s %s\n", i, p->ttype[i], typestring,
+ p->tunit[i]);
+ }
+
+}
+
+
+
+/* Top level function */
+void
+table(struct tableparams *p)
+{
+ if(p->information) printinfo(p);
}
diff --git a/src/table/ui.c b/src/table/ui.c
index 4903278..bdd75f4 100644
--- a/src/table/ui.c
+++ b/src/table/ui.c
@@ -102,30 +102,23 @@ readconfig(char *filename, struct tableparams *p)
/* Inputs: */
if(strcmp(name, "hdu")==0)
- {
- if(cp->hduset) continue;
- errno=0;
- cp->hdu=malloc(strlen(value)+1);
- if(cp->hdu==NULL)
- error(EXIT_FAILURE, errno, "space for HDU");
- strcpy(cp->hdu, value);
- cp->hduset=1;
- }
+ gal_checkset_allocate_copy_set(value, &cp->hdu, &cp->outputset);
/* Outputs */
-
+ else if(strcmp(name, "output")==0)
+ gal_checkset_allocate_copy_set(value, &cp->output, &cp->outputset);
/* Operating modes: */
else if (strcmp(name, "information")==0)
{
- if(up->informationset) continue;
+ if(p->up.informationset) continue;
gal_checkset_int_zero_or_one(value, &p->information, name,
key, SPACK, filename, lineno);
- up->informationset=1;
+ p->up.informationset=1;
}
@@ -210,10 +203,138 @@ checkifset(struct tableparams *p)
/**************************************************************/
/*************** Sanity Check *******************/
/**************************************************************/
+/* This function will read all the table information from a FITS table HDU
+ and store them in arrays for use later. It is mainly good for getting
+ all the information in a FITS table HDU. This function will only go
+ through the header keywords once and does not depend on the ordering of
+ the keywords, so it is much more efficient than having to ask for each
+ column's information separately.*/
+void
+readallcolinfo(char *filename, char *hdu, size_t *nrows,
+ size_t *ncols, int **otypecode, char ***otform,
+ char ***ottype, char ***otunit, fitsfile **outfptr)
+{
+ long lnrows;
+ size_t index;
+ char *tailptr, **c, **fc;
+ char **tform, **ttype, **tunit;
+ int i, status=0, incols, *typecode;
+ char keyname[FLEN_KEYWORD]="XXXXXXXXXXXXX", value[FLEN_VALUE];
+
+ /* Set the FITS pointer and check the HDU type. */
+ gal_fits_read_hdu(filename, hdu, 1, outfptr);
+
+ /* Get the size of the table. incols is incremented because the indexs of
+ the FITS keywords start from 1, not zero. */
+ fits_get_num_rows(*outfptr, &lnrows, &status);
+ fits_get_num_cols(*outfptr, &incols, &status);
+ *ncols=incols++;
+ *nrows=lnrows;
+
+ /* Allocate the arrays to keep the column information. Initialize the
+ arrays with a NULL pointer to make sure that they are all found in the
+ end if they are necessary.*/
+ errno=0; typecode=*otypecode=malloc(incols * sizeof *typecode);
+ if(typecode==NULL)
+ error(EXIT_FAILURE, errno, "%lu bytes for typecode",
+ incols * sizeof *typecode);
+ errno=0; tform=*otform=malloc(incols * sizeof *tform);
+ if(tform==NULL)
+ error(EXIT_FAILURE, errno, "%lu bytes for tform",
+ incols * sizeof *tform);
+ fc=(c=tform)+incols; do *c++=NULL; while(c<fc);
+ errno=0; ttype=*ottype=malloc(incols * sizeof *ttype);
+ if(ttype==NULL)
+ error(EXIT_FAILURE, errno, "%lu bytes for ttype",
+ incols * sizeof *ttype);
+ fc=(c=ttype)+incols; do *c++=NULL; while(c<fc);
+ errno=0; tunit=*otunit=malloc(incols * sizeof *tunit);
+ if(tunit==NULL)
+ error(EXIT_FAILURE, errno, "%lu bytes for tunit",
+ incols * sizeof *tunit);
+ fc=(c=tunit)+incols; do *c++=NULL; while(c<fc);
+
+ /* Read all the keywords one by one and if they match, then put them in
+ the correct value. Note that we are starting from keyword 9 because
+ according to the FITS standard, the first 8 keys in a FITS table are
+ reserved. */
+ for(i=9; strcmp(keyname, "END"); ++i)
+ {
+ /* Read the next keyword. */
+ fits_read_keyn(*outfptr, i, keyname, value, NULL, &status);
+
+ /* Check the type of the keyword. */
+ if(strncmp(keyname, "TFORM", 5)==0)
+ {
+ /* The values to TFORM are only a single character, so start the
+ pointer to copy at 1 and put the string terminator at 3. */
+ value[2]='\0';
+ index=strtoul(&keyname[5], &tailptr, 10);
+ if(index<incols)
+ {
+ gal_checkset_allocate_copy(&value[1], &tform[index] );
+ typecode[index]=gal_fits_tform_to_dtype(value[1]);
+ }
+ }
+ else if(strncmp(keyname, "TTYPE", 5)==0)
+ {
+ /* All strings in CFITSIO start and finish with single quotation
+ marks, CFITSIO puts them in itsself, so if we don't remove
+ them here, we might have duplicates later, its easier to just
+ remove them to have a simple string that might be used else
+ where too (without the single quotes). */
+ value[strlen(value)-1]='\0';
+ index=strtoul(&keyname[5], &tailptr, 10);
+ if(index<incols)
+ gal_checkset_allocate_copy(&value[1], &ttype[index] );
+ }
+ else if(strncmp(keyname, "TUNIT", 5)==0)
+ {
+ /* similar to ttype, see above.*/
+ value[strlen(value)-1]='\0';
+ index=strtoul(&keyname[5], &tailptr, 10);
+ if(index<incols)
+ gal_checkset_allocate_copy(&value[1], &tunit[index] );
+ }
+ }
+
+ /* Check if all values were set: */
+ for(i=1;i<=*ncols;++i)
+ {
+ if(!tform[i])
+ error(EXIT_FAILURE, 0, "TFORM%d could not be found in header", i);
+ if(!ttype[i])
+ error(EXIT_FAILURE, 0, "TTYPE%d could not be found in header", i);
+ if(!tunit[i])
+ error(EXIT_FAILURE, 0, "TUNIT%d could not be found in header", i);
+ }
+
+
+ /* For a checkup:
+ for(i=1;i<=*ncols;++i)
+ printf("%d: %s, %s, %s\n", i, tform[i], ttype[i], tunit[i]);
+ */
+
+}
+
+
+
+
+
void
sanitycheck(struct tableparams *p)
{
+ /* Set the FITS pointer and check the type of the fits file. */
+ if(p->up.fitsname)
+ readallcolinfo(p->up.fitsname, p->cp.hdu, &p->nrows,
+ &p->ncols, &p->typecode, &p->tform,
+ &p->ttype, &p->tunit, &p->fitsptr);
+ else
+ error(EXIT_FAILURE, 0, "Table is a new addition to Gnuastro and "
+ "and under heavy development, it currently doesn't support "
+ "anything other than a FITS binary table.");
+
}
@@ -267,6 +388,7 @@ preparearrays(struct tableparams *p)
void
setparams(int argc, char *argv[], struct tableparams *p)
{
+ struct uiparams *up=&p->up;
struct gal_commonparams *cp=&p->cp;
/* Set the non-zero initial values, the structure was initialized to
@@ -276,6 +398,9 @@ setparams(int argc, char *argv[], struct tableparams *p)
cp->numthreads = num_processors(NPROC_CURRENT);
cp->removedirinfo = 1;
+ /* Initialize this utility's special variables. */
+ up->txtname=up->fitsname=NULL;
+
/* Read the arguments. */
errno=0;
if(argp_parse(&thisargp, argc, argv, 0, 0, p))
@@ -323,13 +448,13 @@ setparams(int argc, char *argv[], struct tableparams *p)
void
freeandreport(struct tableparams *p)
{
+ int status=0;
+
/* Free the allocated arrays: */
free(p->cp.hdu);
free(p->cp.output);
- /* Close the FITS file:
- if(fits_close_file(p->fptr, &status))
+ /* Close the FITS file: */
+ if(p->up.fitsname && fits_close_file(p->fitsptr, &status))
gal_fits_io_error(status, NULL);
- */
-
}
- [gnuastro-commits] master updated (a1e40c8 -> b78b0c7), Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master 474db42 07/16: Table and TEMPLATE added to the genauthors, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master 56bd4e5 03/16: checkset func for some option value allocations, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master c113fc3 09/16: Allocation for FITS types by datatype, not bitpix, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master 9c7d9a0 10/16: Blank replacement function now accepts datatype, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master 2071999 08/16: Blank CFITSIO pointers set by datatype, not bitpix, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master 01dfb1b 05/16: Some code management in Table, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master d09e850 04/16: FITS table column information printed by Table,
Mohammad Akhlaghi <=
- [gnuastro-commits] master 5606978 11/16: Configuration file in tests/during-dev.sh, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master c719806 06/16: Table accepts specified column number, name and regex, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master 647406f 02/16: Table utility bare minimum structure in place, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master ad16c2a 12/16: Cosmetic changes in fits and txtarray libraries, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master b16c7a4 15/16: New Section added to the book for Table, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master cd5b5cf 13/16: Table prints contents of a FITS table, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master b553085 01/16: Template for creating a new utility added, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master ce08c34 14/16: FITS (binary) tables <--> plain text in Table, Mohammad Akhlaghi, 2016/08/24
- [gnuastro-commits] master b78b0c7 16/16: New Table utility merged, Mohammad Akhlaghi, 2016/08/24