gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master 52953e6 2/2: Library (table.h & txt.h): abilit


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 52953e6 2/2: Library (table.h & txt.h): ability to add keywords to text tables
Date: Sat, 22 Aug 2020 21:21:55 -0400 (EDT)

branch: master
commit 52953e64003c05c2e2ef1fb78c1c5ec31f0f0231
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Library (table.h & txt.h): ability to add keywords to text tables
    
    Until now, there was no internal/standard way to write keywords into
    plain-text tables. Most programs that needed to write values in output
    plain-text tables used comments instead. But it is necessary to have a
    parsable/robust structure like FITS keywords in plain-text too.
    
    With this commit, the internal structure to write FITS keywords
    ('gal_fits_list_key_t') is now also usable to write keywords in plain-text
    tables, and is thus a new argument to 'gal_txt_write' and
    'gal_table_write'.
    
    Also within 'gal_fits_list_key_t', it is now possible to add keyword titles
    within the list to help classify them by context.
---
 NEWS                        |   7 ++-
 bin/arithmetic/arithmetic.c |   4 +-
 bin/convertt/convertt.c     |   2 +-
 bin/convolve/convolve.c     |   2 +-
 bin/fits/fits.c             |   2 +-
 bin/match/match.c           |   8 +--
 bin/mkcatalog/mkcatalog.c   |   9 ++--
 bin/mkcatalog/parse.c       |   2 +-
 bin/mkcatalog/ui.c          |   4 +-
 bin/mkcatalog/upperlimit.c  |   2 +-
 bin/noisechisel/threshold.c |   3 +-
 bin/segment/clumps.c        |   2 +-
 bin/segment/segment.c       |   2 +-
 bin/statistics/statistics.c |   3 +-
 bin/statistics/ui.c         |   2 +-
 bin/table/table.c           |   2 +-
 doc/gnuastro.texi           |  27 ++++++++--
 lib/fits.c                  | 117 ++++++++++++++++++++++++++++++++++++--------
 lib/gnuastro/fits.h         |  20 +++++++-
 lib/gnuastro/table.h        |   6 +--
 lib/gnuastro/txt.h          |   4 +-
 lib/table.c                 |  16 +++---
 lib/txt.c                   |  75 +++++++++++++++++++++++++++-
 23 files changed, 259 insertions(+), 62 deletions(-)

diff --git a/NEWS b/NEWS
index 60872c6..19f398d 100644
--- a/NEWS
+++ b/NEWS
@@ -70,6 +70,10 @@ See the end of the file for license conditions.
 
   Library:
    - Spectral lines library: SiIII, OIII, CIV, NV and rest of Lyman series.
+   - GAL_CONFIG_HAVE_WCSLIB_DIS_H: if the host's WCSLIB supports distortions.
+   - GAL_CONFIG_HAVE_WCSLIB_MJDREF: if the host's WCSLIB reads MJDREF keyword.
+   - gal_fits_key_list_title_add: Add a title key word to the list.
+   - gal_fits_key_list_title_add_end: Add a title key word to the list's end.
    - GAL_INTERPOLATE_NEIGHBORS_METRIC_RADIAL: Radial metric for interpolation.
    - GAL_INTERPOLATE_NEIGHBORS_METRIC_MANHATTAN: Mahattan distance.
    - GAL_INTERPOLATE_NEIGHBORS_METRIC_INVALID: For error-handling/completeness.
@@ -77,8 +81,6 @@ See the end of the file for license conditions.
    - GAL_INTERPOLATE_NEIGHBORS_FUNC_MAX: Use maximum for interpolation.
    - GAL_INTERPOLATE_NEIGHBORS_FUNC_MEDIAN: Use median for interpolation.
    - GAL_INTERPOLATE_NEIGHBORS_FUNC_INVALID: for error-handling/completeness.
-   - GAL_CONFIG_HAVE_WCSLIB_DIS_H: if the host's WCSLIB supports distortions.
-   - GAL_CONFIG_HAVE_WCSLIB_MJDREF: if the host's WCSLIB reads MJDREF keyword.
    - gal_statistics_histogram2d: Generate 2D histogram from two columns.
    - GAL_WCS_FLTERROR: Limit to identify a floating point error for WCS.
    - gal_wcs_write: Write the given WCS into a FITS extension with no data.
@@ -109,6 +111,7 @@ See the end of the file for license conditions.
    - gal_statistics_outlier_bydistance: new name for the old
      'gal_statistics_outlier_positive'. It can now use the same algorithm
      for negative outliers with a new argument.
+   - gal_txt_write: Now accepts a new argument for keyword lists.
    - gal_type_string_to_number: Numbers ending in '.' or '.0' will be
      parsed as floating point. Until now, it would only parse numbers as
      floating point if they had non-zero decimals.
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index 080516c..89e2321 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -884,7 +884,7 @@ arithmetic_tofile(struct arithmeticparams *p, char *token, 
int freeflag)
   /* Save it to a file. */
   popped->wcs=p->refdata.wcs;
   if(popped->ndim==1 && p->onedasimage==0)
-    gal_table_write(popped, NULL, p->cp.tableformat, filename,
+    gal_table_write(popped, NULL, NULL, p->cp.tableformat, filename,
                     "ARITHMETIC", 0);
   else
     gal_fits_img_write(popped, filename, NULL, PROGRAM_NAME);
@@ -1314,7 +1314,7 @@ reversepolish(struct arithmeticparams *p)
          will be freed while freeing 'data'. */
       data->wcs=p->refdata.wcs;
       if(data->ndim==1 && p->onedasimage==0)
-        gal_table_write(data, NULL, p->cp.tableformat,
+        gal_table_write(data, NULL, NULL, p->cp.tableformat,
                         p->onedonstdout ? NULL : p->cp.output,
                         "ARITHMETIC", 0);
       else
diff --git a/bin/convertt/convertt.c b/bin/convertt/convertt.c
index 55b806e..517e599 100644
--- a/bin/convertt/convertt.c
+++ b/bin/convertt/convertt.c
@@ -337,7 +337,7 @@ convertt(struct converttparams *p)
     /* Plain text: only one channel is acceptable. */
     case OUT_FORMAT_TXT:
       gal_checkset_writable_remove(p->cp.output, 0, p->cp.dontdelete);
-      gal_txt_write(p->chll, NULL, p->cp.output, 0);
+      gal_txt_write(p->chll, NULL, NULL, p->cp.output, 0);
       break;
 
     /* JPEG: */
diff --git a/bin/convolve/convolve.c b/bin/convolve/convolve.c
index 13b5356..2804ff1 100644
--- a/bin/convolve/convolve.c
+++ b/bin/convolve/convolve.c
@@ -800,7 +800,7 @@ convolve(struct convolveparams *p)
 
   /* Save the output (which is in p->input) array. */
   if(p->input->ndim==1)
-    gal_table_write(p->input, NULL, p->cp.tableformat, p->cp.output,
+    gal_table_write(p->input, NULL, NULL, p->cp.tableformat, p->cp.output,
                     "CONVOLVED", 0);
   else
     gal_fits_img_write_to_type(p->input, cp->output, NULL, PROGRAM_NAME,
diff --git a/bin/fits/fits.c b/bin/fits/fits.c
index 9483355..d0ab3a9 100644
--- a/bin/fits/fits.c
+++ b/bin/fits/fits.c
@@ -244,7 +244,7 @@ fits_print_extension_info(struct fitsparams *p)
       printf(" Column 4: Size of data in HDU.\n");
       printf("-----\n");
     }
-  gal_table_write(cols, NULL, GAL_TABLE_FORMAT_TXT, NULL, NULL, 0);
+  gal_table_write(cols, NULL, NULL, GAL_TABLE_FORMAT_TXT, NULL, NULL, 0);
   gal_list_data_free(cols);
 }
 
diff --git a/bin/match/match.c b/bin/match/match.c
index 7d5d1d6..f556d3b 100644
--- a/bin/match/match.c
+++ b/bin/match/match.c
@@ -259,7 +259,8 @@ match_catalog_read_write_all(struct matchparams *p, size_t 
*permutation,
   else if(cat)
     {
       /* Write the catalog to a file. */
-      gal_table_write(cat, NULL, p->cp.tableformat, outname, extname, 0);
+      gal_table_write(cat, NULL, NULL, p->cp.tableformat, outname,
+                      extname, 0);
 
       /* Correct arrays and sizes (when 'notmatched' was called). The
          'array' element has to be corrected for later freeing.
@@ -340,7 +341,8 @@ match_catalog_write_one(struct matchparams *p, gal_data_t 
*a, gal_data_t *b,
 
   /* Reverse the table and write it out. */
   gal_list_data_reverse(&cat);
-  gal_table_write(cat, NULL, p->cp.tableformat, p->out1name, "MATCHED", 0);
+  gal_table_write(cat, NULL, NULL, p->cp.tableformat, p->out1name,
+                  "MATCHED", 0);
 }
 
 
@@ -423,7 +425,7 @@ match_catalog(struct matchparams *p)
         "from 1).";
 
       /* Write them into the table. */
-      gal_table_write(mcols, NULL, p->cp.tableformat, p->logname,
+      gal_table_write(mcols, NULL, NULL, p->cp.tableformat, p->logname,
                       "LOG_INFO", 0);
 
       /* Set the comment pointer to NULL: they weren't allocated. */
diff --git a/bin/mkcatalog/mkcatalog.c b/bin/mkcatalog/mkcatalog.c
index 5d060d6..1f42887 100644
--- a/bin/mkcatalog/mkcatalog.c
+++ b/bin/mkcatalog/mkcatalog.c
@@ -651,7 +651,7 @@ mkcatalog_write_outputs(struct mkcatalogparams *p)
       /* Reverse the comments list (so it is printed in the same order
          here), write the objects catalog and free the comments. */
       gal_list_str_reverse(&comments);
-      gal_table_write(p->objectcols, comments, p->cp.tableformat,
+      gal_table_write(p->objectcols, NULL, comments, p->cp.tableformat,
                       p->objectsout, "OBJECTS", 0);
       gal_list_str_free(comments, 1);
 
@@ -668,7 +668,7 @@ mkcatalog_write_outputs(struct mkcatalogparams *p)
              Reverse the comments list (so it is printed in the same order
              here), write the objects catalog and free the comments. */
           gal_list_str_reverse(&comments);
-          gal_table_write(p->clumpcols, comments, p->cp.tableformat,
+          gal_table_write(p->clumpcols, NULL, comments, p->cp.tableformat,
                           p->clumpsout, "CLUMPS", 0);
           gal_list_str_free(comments, 1);
         }
@@ -698,7 +698,8 @@ mkcatalog_write_outputs(struct mkcatalogparams *p)
               {
                 /* Write the table. */
                 sprintf(str, "SPECTRUM_%zu", i+1);
-                gal_table_write(&p->spectra[i], NULL, GAL_TABLE_FORMAT_BFITS,
+                gal_table_write(&p->spectra[i], NULL, NULL,
+                                GAL_TABLE_FORMAT_BFITS,
                                 p->objectsout, str, 0);
               }
             else
@@ -706,7 +707,7 @@ mkcatalog_write_outputs(struct mkcatalogparams *p)
                 sprintf(str, "-spec-%zu.txt", i+1);
                 fname=gal_checkset_automatic_output(&p->cp, p->objectsout,
                                                     str);
-                gal_table_write(&p->spectra[i], NULL, GAL_TABLE_FORMAT_TXT,
+                gal_table_write(&p->spectra[i], NULL, NULL, 
GAL_TABLE_FORMAT_TXT,
                                 fname, NULL, 0);
                 free(fname);
               }
diff --git a/bin/mkcatalog/parse.c b/bin/mkcatalog/parse.c
index 4dc665a..b584ffa 100644
--- a/bin/mkcatalog/parse.c
+++ b/bin/mkcatalog/parse.c
@@ -422,7 +422,7 @@ parse_spectrum(struct mkcatalog_passparams *pp, gal_data_t 
*xybin)
   free(tsize);
 
   /* For a check.
-  gal_table_write(pp->spectrum, NULL, GAL_TABLE_FORMAT_BFITS,
+  gal_table_write(pp->spectrum, NULL, NULL, GAL_TABLE_FORMAT_BFITS,
                   "spectrum.fits", "SPECTRUM", 0);
   */
 }
diff --git a/bin/mkcatalog/ui.c b/bin/mkcatalog/ui.c
index dd5d43c..d714a8d 100644
--- a/bin/mkcatalog/ui.c
+++ b/bin/mkcatalog/ui.c
@@ -1582,8 +1582,8 @@ ui_preparations_spectrum_wcs(struct mkcatalogparams *p)
   p->specsliceinfo->next=gal_data_copy_to_new_type(z, GAL_TYPE_FLOAT32);
 
   /* For a final check.
-  gal_table_write(p->specsliceinfo, NULL, GAL_TABLE_FORMAT_BFITS,
-                  "specsliceinfo.fits", "test-debug",0);
+  gal_table_write(p->specsliceinfo, NULL, NULL, GAL_TABLE_FORMAT_BFITS,
+                  "specsliceinfo.fits", "test-debug", 0);
   */
 
   /* Clean up. */
diff --git a/bin/mkcatalog/upperlimit.c b/bin/mkcatalog/upperlimit.c
index 19a2eaf..5d2b426 100644
--- a/bin/mkcatalog/upperlimit.c
+++ b/bin/mkcatalog/upperlimit.c
@@ -446,7 +446,7 @@ upperlimit_write_check(struct mkcatalogparams *p, 
gal_list_sizet_t *check_x,
   if(check_z) { y->next=z; z->next=s; }
   else        { y->next=s;            }
   gal_list_str_reverse(&comments);
-  gal_table_write(x, comments, p->cp.tableformat, p->upcheckout,
+  gal_table_write(x, NULL, comments, p->cp.tableformat, p->upcheckout,
                   "UPPERLIMIT_CHECK", 0);
 
   /* Inform the user. */
diff --git a/bin/noisechisel/threshold.c b/bin/noisechisel/threshold.c
index 868cf60..f318d47 100644
--- a/bin/noisechisel/threshold.c
+++ b/bin/noisechisel/threshold.c
@@ -223,7 +223,8 @@ threshold_write_sn_table(struct noisechiselparams *p, 
gal_data_t *insn,
      because when the output is a FITS table, we want all the tables in one
      FITS file. We have already deleted any existing file with the same
      name in 'ui_set_output_names'.*/
-  gal_table_write(cols, comments, p->cp.tableformat, filename, extname, 0);
+  gal_table_write(cols, NULL, comments, p->cp.tableformat, filename,
+                  extname, 0);
 
 
   /* Clean up (if necessary). */
diff --git a/bin/segment/clumps.c b/bin/segment/clumps.c
index 7114bb9..d860696 100644
--- a/bin/segment/clumps.c
+++ b/bin/segment/clumps.c
@@ -539,7 +539,7 @@ clumps_write_sn_table(struct segmentparams *p, gal_data_t 
*insn,
   gal_table_comments_add_intro(&comments, PROGRAM_STRING, &p->rawtime);
 
   /* write the table. */
-  gal_table_write(cols, comments, p->cp.tableformat, filename,
+  gal_table_write(cols, NULL, comments, p->cp.tableformat, filename,
                   "SKY_CLUMP_SN", 0);
 
   /* Clean up (if necessary). */
diff --git a/bin/segment/segment.c b/bin/segment/segment.c
index 8767c42..bd89d55 100644
--- a/bin/segment/segment.c
+++ b/bin/segment/segment.c
@@ -801,7 +801,7 @@ segment_save_sn_table(struct clumps_params *clprm)
   /* Set the column pointers and write them into a table.. */
   clumpinobj->next=sn;
   objind->next=clumpinobj;
-  gal_table_write(objind, comments, p->cp.tableformat, p->clumpsn_d_name,
+  gal_table_write(objind, NULL, comments, p->cp.tableformat, p->clumpsn_d_name,
                   "DET_CLUMP_SN", 0);
 
 
diff --git a/bin/statistics/statistics.c b/bin/statistics/statistics.c
index 5fbc03a..d28dfa3 100644
--- a/bin/statistics/statistics.c
+++ b/bin/statistics/statistics.c
@@ -634,7 +634,8 @@ write_output_table(struct statisticsparams *p, gal_data_t 
*table,
 
   /* Write the table. */
   gal_checkset_writable_remove(output, 0, p->cp.dontdelete);
-  gal_table_write(table, comments, p->cp.tableformat, output, "TABLE", 0);
+  gal_table_write(table, NULL, comments, p->cp.tableformat, output,
+                  "TABLE", 0);
 
 
   /* Write the configuration information if we have a FITS output. */
diff --git a/bin/statistics/ui.c b/bin/statistics/ui.c
index 08ccb20..25b4cc4 100644
--- a/bin/statistics/ui.c
+++ b/bin/statistics/ui.c
@@ -1008,7 +1008,7 @@ ui_preparations(struct statisticsparams *p)
             {
               gal_checkset_writable_remove(tl->tilecheckname, 0,
                                            cp->dontdelete);
-              gal_table_write(check, NULL, cp->tableformat, tl->tilecheckname,
+              gal_table_write(check, NULL, NULL, cp->tableformat, 
tl->tilecheckname,
                               "TABLE", 0);
             }
           gal_data_free(check);
diff --git a/bin/table/table.c b/bin/table/table.c
index 52aac8c..784e29b 100644
--- a/bin/table/table.c
+++ b/bin/table/table.c
@@ -788,6 +788,6 @@ table(struct tableparams *p)
   if(p->colmetadata) table_colmetadata(p);
 
   /* Write the output. */
-  gal_table_write(p->table, NULL, p->cp.tableformat, p->cp.output,
+  gal_table_write(p->table, NULL, NULL, p->cp.tableformat, p->cp.output,
                   "TABLE", p->colinfoinstdout);
 }
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index b5ba0ce..fd168cb 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -21563,7 +21563,8 @@ this line is ignored.
 @end itemize
 @end deftypefun
 
-@deftypefun void gal_table_write (gal_data_t @code{*cols}, gal_list_str_t 
@code{*comments}, int @code{tableformat}, char @code{*filename}, char 
@code{*extname}, uint8_t @code{colinfoinstdout})
+@deftypefun void gal_table_write (gal_data_t @code{*cols}, struct 
gal_fits_list_key_t @code{**keywords}, gal_list_str_t @code{*comments}, int 
@code{tableformat}, char @code{*filename}, char @code{*extname}, uint8_t 
@code{colinfoinstdout})
+
 Write @code{cols} (a list of datasets, see @ref{List of gal_data_t}) into a
 table stored in @code{filename}. The format of the table can be determined
 with @code{tableformat} that accepts the macros defined above. When
@@ -22002,6 +22003,14 @@ Similar to @code{gal_fits_key_list_add}, but add the 
given keyword to the end of
 Use this function if you want the keywords to be written in the same order 
that you add nodes to the list of keywords.
 @end deftypefun
 
+@deftypefun void gal_fits_key_list_title_add (gal_fits_list_key_t 
@code{**list}, char @code{*title}, int @code{tfree})
+Add a special ``title'' keyword (with the @code{title} string) to the top of 
the keywords list.
+@end deftypefun
+
+@deftypefun void gal_fits_key_list_title_add_end (gal_fits_list_key_t 
@code{**list}, char @code{*title}, int @code{tfree})
+Add a special ``title'' keyword (with the @code{title} string) to the 
end/bottom of the keywords list.
+@end deftypefun
+
 @deftypefun void gal_fits_key_list_reverse (gal_fits_list_key_t @code{**list})
 Reverse the input list of keywords.
 @end deftypefun
@@ -22412,7 +22421,7 @@ We often need to read a text file several times: once 
to count how many columns
 So it easier to keep it all in allocated memory and pass it on from the start 
for each round.
 @end deftypefun
 
-@deftypefun void gal_txt_write (gal_data_t @code{*cols}, gal_list_str_t 
@code{*comment}, char @code{*filename}, uint8_t @code{colinfoinstdout})
+@deftypefun void gal_txt_write (gal_data_t @code{*cols}, struct 
gal_fits_list_key_t @code{**keylist}, gal_list_str_t @code{*comment}, char 
@code{*filename}, uint8_t @code{colinfoinstdout})
 Write @code{cols} in a plain text file @code{filename}.
 @code{cols} may have one or two dimensions which determines the output:
 
@@ -22428,6 +22437,17 @@ So if @code{cols->next!=NULL} the next nodes in the 
list are ignored and will no
 This is a low-level function for tables.
 It is recommended to use @code{gal_table_write} for generic writing of tables 
in a variety of formats, see @ref{Table input output}.
 
+It is possible to add two types of metadata to the printed table: comments and 
keywords.
+Each string in the list given to @code{comments} will be printed into the file 
as a separate line, starting with @code{#}.
+Keywords have a more specific and computer-parsable format and are passed 
through @code{keylist}.
+Each keyword is also printed in one line, but with the format below.
+Because of the various components in a keyword, it is thus necessary to use 
the @code{gal_fits_list_key_t} data structure.
+For more, see @ref{FITS header keywords}.
+
+@example
+# [key] NAME: VALUE / [UNIT] KEYWORD COMMENT.
+@end example
+
 If @code{filename} already exists this function will abort with an error and 
will not write over the existing file.
 Before calling this function make sure if the file exists or not.
 If @code{comments!=NULL}, a @code{#} will be put at the start of each node of 
the list of strings and will be written in the file before the column meta-data 
in @code{filename} (see @ref{List of strings}).
@@ -26149,7 +26169,8 @@ main(void)
   /* Set names for the columns and write them out. */
   c1->name = "COUNTER";
   c2->name = "VALUE";
-  gal_table_write(c1, NULL, GAL_TABLE_FORMAT_BFITS, outname);
+  gal_table_write(c1, NULL, NULL, GAL_TABLE_FORMAT_BFITS, outname,
+                  "MY-COLUMNS", 0);
 
   /* The names weren't allocated, so to avoid cleaning-up problems,
    * we'll set them to NULL. */
diff --git a/lib/fits.c b/lib/fits.c
index 4b8ebdd..c9498f1 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -1279,6 +1279,7 @@ gal_fits_key_list_add(gal_fits_list_key_t **list, uint8_t 
type,
     error(EXIT_FAILURE, errno, "%s: allocating new node", __func__);
 
   /* Write the given values into the key structure. */
+  newnode->title=NULL;
   newnode->type=type;
   newnode->keyname=keyname;
   newnode->value=value;
@@ -1303,7 +1304,7 @@ gal_fits_key_list_add_end(gal_fits_list_key_t **list, 
uint8_t type,
                           char *keyname, int kfree, void *value, int vfree,
                           char *comment, int cfree, char *unit, int ufree)
 {
-  gal_fits_list_key_t *newnode, *tmp;
+  gal_fits_list_key_t *tmp, *newnode;
 
   /* Allocate space for the new node and fill it in. */
   errno=0;
@@ -1312,6 +1313,7 @@ gal_fits_key_list_add_end(gal_fits_list_key_t **list, 
uint8_t type,
     error(EXIT_FAILURE, errno, "%s: allocation of new node", __func__);
 
   /* Write the given values into the key structure. */
+  newnode->title=NULL;
   newnode->type=type;
   newnode->keyname=keyname;
   newnode->value=value;
@@ -1340,6 +1342,67 @@ gal_fits_key_list_add_end(gal_fits_list_key_t **list, 
uint8_t type,
 
 
 
+/* Only set this key to be a title. */
+void
+gal_fits_key_list_title_add(gal_fits_list_key_t **list, char *title, int tfree)
+{
+  gal_fits_list_key_t *newnode;
+
+  /* Allocate space (and initialize to 0/NULL) for the new node and fill it
+     in. */
+  errno=0;
+  newnode=calloc(1, sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno, "%s: allocating new node", __func__);
+
+  /* Set the arguments. */
+  newnode->title=title;
+  newnode->tfree=tfree;
+
+  /* Set the next pointer. */
+  newnode->next=*list;
+  *list=newnode;
+}
+
+
+
+
+/* Put the title keyword in the end. */
+void
+gal_fits_key_list_title_add_end(gal_fits_list_key_t **list, char *title,
+                                int tfree)
+{
+  gal_fits_list_key_t *tmp, *newnode;
+
+  /* Allocate space (and initialize to 0/NULL) for the new node and fill it
+     in. */
+  errno=0;
+  newnode=calloc(1, sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno, "%s: allocating new node", __func__);
+
+  /* Set the arguments. */
+  newnode->title=title;
+  newnode->tfree=tfree;
+
+  /* Set the next pointer. */
+  if(*list)         /* List is already full, add this node to the end */
+    {
+      /* After this line, tmp points to the last node. */
+      tmp=*list; while(tmp->next!=NULL) tmp=tmp->next;
+      tmp->next=newnode;
+      newnode->next=NULL;
+    }
+  else                 /* List is empty */
+    {
+      newnode->next=*list;
+      *list=newnode;
+    }
+}
+
+
+
+
 
 void
 gal_fits_key_list_reverse(gal_fits_list_key_t **list)
@@ -1574,30 +1637,40 @@ gal_fits_key_write_in_ptr(gal_fits_list_key_t 
**keylist, fitsfile *fptr)
   tmp=*keylist;
   while(tmp!=NULL)
     {
-      /* Write the basic key value and comments. */
-      if(tmp->value)
+      /* If a title is requested, only put a title. */
+      if(tmp->title)
         {
-          if( fits_update_key(fptr, gal_fits_type_to_datatype(tmp->type),
-                              tmp->keyname, tmp->value, tmp->comment,
-                              &status) )
-            gal_fits_io_error(status, NULL);
+          gal_fits_key_write_title_in_ptr(tmp->title, fptr);
+          if(tmp->tfree) free(tmp->title);
         }
       else
         {
-          if(fits_update_key_null(fptr, tmp->keyname, tmp->comment, &status))
-            gal_fits_io_error(status, NULL);
-        }
+          /* Write the basic key value and comments. */
+          if(tmp->value)
+            {
+              if( fits_update_key(fptr, gal_fits_type_to_datatype(tmp->type),
+                                  tmp->keyname, tmp->value, tmp->comment,
+                                  &status) )
+                gal_fits_io_error(status, NULL);
+            }
+          else
+            {
+              if(fits_update_key_null(fptr, tmp->keyname, tmp->comment,
+                                      &status))
+                gal_fits_io_error(status, NULL);
+            }
 
-      /* Write the units if it was given. */
-      if( tmp->unit
-          && fits_write_key_unit(fptr, tmp->keyname, tmp->unit, &status) )
-        gal_fits_io_error(status, NULL);
+          /* Write the units if it was given. */
+          if( tmp->unit
+              && fits_write_key_unit(fptr, tmp->keyname, tmp->unit, &status) )
+            gal_fits_io_error(status, NULL);
 
-      /* Free the value pointer if desired: */
-      if(tmp->kfree) free(tmp->keyname);
-      if(tmp->vfree) free(tmp->value);
-      if(tmp->cfree) free(tmp->comment);
-      if(tmp->ufree) free(tmp->unit);
+          /* Free the value pointer if desired: */
+          if(tmp->kfree) free(tmp->keyname);
+          if(tmp->vfree) free(tmp->value);
+          if(tmp->cfree) free(tmp->comment);
+          if(tmp->ufree) free(tmp->unit);
+        }
 
       /* Keep the pointer to the next keyword and free the allocated
          space for this keyword.*/
@@ -3222,7 +3295,8 @@ fits_write_tnull_tcomm(fitsfile *fptr, gal_data_t *col, 
int tableformat,
    table.*/
 void
 gal_fits_tab_write(gal_data_t *cols, gal_list_str_t *comments,
-                   int tableformat, char *filename, char *extname)
+                   int tableformat, char *filename, char *extname,
+                   struct gal_fits_list_key_t **keylist)
 {
   void *blank;
   fitsfile *fptr;
@@ -3306,6 +3380,9 @@ gal_fits_tab_write(gal_data_t *cols, gal_list_str_t 
*comments,
       ++i;
     }
 
+  /* Write the requested keywords. */
+  if(keylist)
+    gal_fits_key_write_in_ptr(keylist, fptr);
 
   /* Write the comments if there were any. */
   for(strt=comments; strt!=NULL; strt=strt->next)
diff --git a/lib/gnuastro/fits.h b/lib/gnuastro/fits.h
index 468587a..5794296 100644
--- a/lib/gnuastro/fits.h
+++ b/lib/gnuastro/fits.h
@@ -47,7 +47,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <gnuastro/list.h>
 #include <gnuastro/data.h>
-#include <gnuastro/table.h>
+/* gnuastro/table.h is included below. */
 
 /* C++ Preparations */
 #undef __BEGIN_C_DECLS
@@ -77,11 +77,13 @@ __BEGIN_C_DECLS  /* From C++ preparations */
 /* To create a linked list of headers. */
 typedef struct gal_fits_list_key_t
 {
+  int                        tfree;   /* ==1, free title string.   */
   int                        kfree;   /* ==1, free keyword name.   */
   int                        vfree;   /* ==1, free keyword value.  */
   int                        cfree;   /* ==1, free comment.        */
   int                        ufree;   /* ==1, free unit.           */
   uint8_t                     type;   /* Keyword value type.       */
+  char                      *title;   /* !=NULL, only print title. */
   char                    *keyname;   /* Keyword Name.             */
   void                      *value;   /* Keyword value.            */
   char                    *comment;   /* Keyword comment.          */
@@ -91,6 +93,11 @@ typedef struct gal_fits_list_key_t
 
 
 
+/* table.h needs 'gal_fits_list_key_t'. */
+#include <gnuastro/table.h>
+
+
+
 
 
 /*************************************************************
@@ -194,6 +201,14 @@ gal_fits_key_list_add_end(gal_fits_list_key_t **list, 
uint8_t type,
                           char *comment, int cfree, char *unit, int ufree);
 
 void
+gal_fits_key_list_title_add(gal_fits_list_key_t **list, char *title,
+                            int tfree);
+
+void
+gal_fits_key_list_title_add_end(gal_fits_list_key_t **list, char *title,
+                                int tfree);
+
+void
 gal_fits_key_list_reverse(gal_fits_list_key_t **list);
 
 void
@@ -292,7 +307,8 @@ gal_fits_tab_read(char *filename, char *hdu, size_t numrows,
 
 void
 gal_fits_tab_write(gal_data_t *cols, gal_list_str_t *comments,
-                   int tableformat, char *filename, char *extname);
+                   int tableformat, char *filename, char *extname,
+                   struct gal_fits_list_key_t **keywords);
 
 
 
diff --git a/lib/gnuastro/table.h b/lib/gnuastro/table.h
index 4b76eb4..61817dc 100644
--- a/lib/gnuastro/table.h
+++ b/lib/gnuastro/table.h
@@ -156,9 +156,9 @@ gal_table_comments_add_intro(gal_list_str_t **comments,
                              char *program_string, time_t *rawtime);
 
 void
-gal_table_write(gal_data_t *cols, gal_list_str_t *comments,
-                int tableformat, char *filename, char *extname,
-                uint8_t colinfoinstdout);
+gal_table_write(gal_data_t *cols, struct gal_fits_list_key_t **keylist,
+                gal_list_str_t *comments, int tableformat, char *filename,
+                char *extname, uint8_t colinfoinstdout);
 
 void
 gal_table_write_log(gal_data_t *logll, char *program_string,
diff --git a/lib/gnuastro/txt.h b/lib/gnuastro/txt.h
index 63b2793..f46b782 100644
--- a/lib/gnuastro/txt.h
+++ b/lib/gnuastro/txt.h
@@ -27,6 +27,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
    must be included before the C++ preparations below */
 
 #include <gnuastro/list.h>
+#include <gnuastro/fits.h>
 
 
 
@@ -102,7 +103,8 @@ gal_list_str_t *
 gal_txt_stdin_read(long timeout_microsec);
 
 void
-gal_txt_write(gal_data_t *input, gal_list_str_t *comment, char *filename,
+gal_txt_write(gal_data_t *input, struct gal_fits_list_key_t **keylist,
+              gal_list_str_t *comment, char *filename,
               uint8_t colinfoinstdout);
 
 
diff --git a/lib/table.c b/lib/table.c
index 003e994..d9aad4f 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -526,9 +526,9 @@ gal_table_comments_add_intro(gal_list_str_t **comments, 
char *program_string,
    table will then be written into 'filename' with a format that is
    specified by 'tableformat'. */
 void
-gal_table_write(gal_data_t *cols, gal_list_str_t *comments,
-                int tableformat, char *filename, char *extname,
-                uint8_t colinfoinstdout)
+gal_table_write(gal_data_t *cols, struct gal_fits_list_key_t **keylist,
+                gal_list_str_t *comments, int tableformat, char *filename,
+                char *extname, uint8_t colinfoinstdout)
 {
   /* If a filename was given, then the tableformat is relevant and must be
      used. When the filename is empty, a text table must be printed on the
@@ -536,13 +536,14 @@ gal_table_write(gal_data_t *cols, gal_list_str_t 
*comments,
   if(filename)
     {
       if(gal_fits_name_is_fits(filename))
-        gal_fits_tab_write(cols, comments, tableformat, filename, extname);
+        gal_fits_tab_write(cols, comments, tableformat, filename, extname,
+                           keylist);
       else
-        gal_txt_write(cols, comments, filename, colinfoinstdout);
+        gal_txt_write(cols, keylist, comments, filename, colinfoinstdout);
     }
   else
     /* Write to standard output. */
-    gal_txt_write(cols, comments, filename, colinfoinstdout);
+    gal_txt_write(cols, keylist, comments, filename, colinfoinstdout);
 }
 
 
@@ -560,7 +561,8 @@ gal_table_write_log(gal_data_t *logll, char *program_string,
   gal_table_comments_add_intro(&comments, program_string, rawtime);
 
   /* Write the log file to disk */
-  gal_table_write(logll, comments, GAL_TABLE_FORMAT_TXT, filename, "LOG", 0);
+  gal_table_write(logll, NULL, comments, GAL_TABLE_FORMAT_TXT,
+                  filename, "LOG", 0);
 
   /* In verbose mode, print the information. */
   if(!quiet)
diff --git a/lib/txt.c b/lib/txt.c
index bcb54f1..9c1977e 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -1457,8 +1457,77 @@ txt_write_metadata(FILE *fp, gal_data_t *datall, char 
**fmts)
 
 
 
+static void
+txt_write_keys(FILE *fp, struct gal_fits_list_key_t **keylist)
+{
+  char *ending;
+  char *valuestr;
+  gal_fits_list_key_t *tmp, *ttmp;
+
+  tmp=*keylist;
+  while(tmp!=NULL)
+    {
+      /* If a title is requested, only put a title. */
+      if(tmp->title)
+        {
+          fprintf(fp, "# -------------\n# %s\n# -------------\n",
+                  tmp->title);
+          if(tmp->tfree) free(tmp->title);
+        }
+      else
+        {
+          /* For a string type, we need to return a pointer to the
+             string. */
+          valuestr = ( tmp->type==GAL_TYPE_STRING
+                       ? tmp->value
+                       : gal_type_to_string(tmp->value, tmp->type, 1) );
+
+          /* If a comment is requested, parepare it. */
+          ending=NULL;
+          if(tmp->unit)
+            {
+              if( asprintf(&ending, " / [%s] %s", tmp->unit,
+                           tmp->comment?tmp->comment:"")==-1 )
+                error(EXIT_FAILURE, errno, "%s: asprintf error for name",
+                      __func__);
+            }
+          else if(tmp->comment)
+            {
+              if( asprintf(&ending, " / %s", tmp->comment)==-1 )
+                error(EXIT_FAILURE, errno, "%s: asprintf error for name",
+                      __func__);
+            }
+
+          /* Write the keyword value. */
+          fprintf(fp, "# [key] %s: %s%s\n", tmp->keyname,
+                  valuestr, ending?ending:"");
+
+          /* Clean up. */
+          if(ending)     free(ending);
+          if(tmp->kfree) free(tmp->keyname);
+          if(tmp->vfree) free(tmp->value);
+          if(tmp->cfree) free(tmp->comment);
+          if(tmp->ufree) free(tmp->unit);
+        }
+
+      /* Keep the pointer to the next keyword and free the allocated
+         space for this keyword.*/
+      ttmp=tmp->next;
+      free(tmp);
+      tmp=ttmp;
+    }
+
+  /* Set it to NULL so it isn't mistakenly used later. */
+  *keylist=NULL;
+}
+
+
+
+
+
 void
-gal_txt_write(gal_data_t *input, gal_list_str_t *comment, char *filename,
+gal_txt_write(gal_data_t *input, struct gal_fits_list_key_t **keylist,
+              gal_list_str_t *comment, char *filename,
               uint8_t colinfoinstdout)
 {
   FILE *fp;
@@ -1529,6 +1598,9 @@ gal_txt_write(gal_data_t *input, gal_list_str_t *comment, 
char *filename,
       /* Write the comments if there were any. */
       for(strt=comment; strt!=NULL; strt=strt->next)
         fprintf(fp, "# %s\n", strt->v);
+
+      /* Write the keywords */
+      if(keylist) txt_write_keys(fp, keylist);
     }
   else
     fp=stdout;
@@ -1581,7 +1653,6 @@ gal_txt_write(gal_data_t *input, gal_list_str_t *comment, 
char *filename,
     }
 
 
-
   /* Clean up. */
   for(i=0;i<num;++i)
     {



reply via email to

[Prev in Thread] Current Thread [Next in Thread]