gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 5fa37eb 096/125: HDU modification now fully im


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 5fa37eb 096/125: HDU modification now fully implemented in Fits program
Date: Sun, 23 Apr 2017 22:36:46 -0400 (EDT)

branch: master
commit 5fa37ebb14bfb5a04b35dc845ba2557525deebaf
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    HDU modification now fully implemented in Fits program
    
    The Fits program now fully implements HDU modification options `--copy',
    `--cut' and `--remove'. The Fits program section of the book has also been
    completely re-written to accommodate these changes. Also, by default, the
    Fits program will now print the extension information when no option is
    specified. There is a new `--printallkeys' (`-p') option to print all the
    keywords in one HDU. A test was also written to check the `--copy' option.
    
    In the process, the `gal_checkset_check_remove_file' now accepts a `keep'
    argument. This was done because unlike all the other programs until now,
    the Fits program must not delete the output file if it is specified: we
    want to add the HDU as an extension to the output file, not delete the
    file.
---
 bin/arithmetic/ui.c               |   2 +-
 bin/convertt/eps.c                |   4 +-
 bin/convertt/ui.c                 |   2 +-
 bin/crop/onecrop.c                |   4 +-
 bin/fits/Makefile.am              |   4 +-
 bin/fits/args.h                   |  59 +++++-
 bin/fits/fits.c                   | 156 +++++++++++++-
 bin/fits/fits.h                   |  19 ++
 bin/fits/{header.c => keywords.c} |  95 +++------
 bin/fits/{header.h => keywords.h} |   2 +-
 bin/fits/main.h                   |   7 +-
 bin/fits/ui.c                     |  53 +++--
 bin/fits/ui.h                     |   9 +-
 bin/mknoise/ui.c                  |   2 +-
 bin/mkprof/mkprof.c               |   2 +-
 bin/warp/ui.c                     |   2 +-
 doc/gnuastro.texi                 | 416 ++++++++++++++++++++++++++++----------
 lib/checkset.c                    |  35 ++--
 lib/checkset.h                    |   2 +-
 lib/commonopts.h                  |   2 +-
 lib/fits.c                        |  52 ++++-
 lib/gnuastro/fits.h               |   2 +
 lib/options.c                     |   2 +-
 lib/options.h                     |   1 +
 lib/txt.c                         |   2 +-
 tests/Makefile.am                 |   3 +-
 tests/fits/copyhdu.sh             |  54 +++++
 27 files changed, 746 insertions(+), 247 deletions(-)

diff --git a/bin/arithmetic/ui.c b/bin/arithmetic/ui.c
index cbe233c..633551b 100644
--- a/bin/arithmetic/ui.c
+++ b/bin/arithmetic/ui.c
@@ -243,7 +243,7 @@ ui_check_options_and_arguments(struct imgarithparams *p)
           if(output_checked==0)
             {
               if(p->cp.output)
-                gal_checkset_check_remove_file(p->cp.output,
+                gal_checkset_check_remove_file(p->cp.output, 0,
                                                p->cp.dontdelete);
               else
                 p->cp.output=gal_checkset_automatic_output(&p->cp, token->v,
diff --git a/bin/convertt/eps.c b/bin/convertt/eps.c
index 292e022..e764837 100644
--- a/bin/convertt/eps.c
+++ b/bin/convertt/eps.c
@@ -387,11 +387,11 @@ eps_write_eps_or_pdf(struct converttparams *p)
   if(p->outformat==OUT_FORMAT_EPS)
     {
       epsfilename=p->cp.output;
-      gal_checkset_check_remove_file(epsfilename, p->cp.dontdelete);
+      gal_checkset_check_remove_file(epsfilename, 0, p->cp.dontdelete);
     }
   else if (p->outformat==OUT_FORMAT_PDF)
     {
-      gal_checkset_check_remove_file(p->cp.output, p->cp.dontdelete);
+      gal_checkset_check_remove_file(p->cp.output, 0, p->cp.dontdelete);
       epsfilename=gal_checkset_automatic_output(&p->cp, p->cp.output, ".ps");
     }
   else
diff --git a/bin/convertt/ui.c b/bin/convertt/ui.c
index 770d1be..2371ff4 100644
--- a/bin/convertt/ui.c
+++ b/bin/convertt/ui.c
@@ -712,7 +712,7 @@ ui_set_output(struct converttparams *p)
     }
 
   /* Check if the output already exists. */
-  gal_checkset_check_remove_file(cp->output, cp->dontdelete);
+  gal_checkset_check_remove_file(cp->output, 0, cp->dontdelete);
 }
 
 
diff --git a/bin/crop/onecrop.c b/bin/crop/onecrop.c
index b9508ca..e5fbea2 100644
--- a/bin/crop/onecrop.c
+++ b/bin/crop/onecrop.c
@@ -456,7 +456,7 @@ cropname(struct onecropparams *crp)
                  p->suffix);
 
       /* Make sure the file doesn't exist. */
-      gal_checkset_check_remove_file(crp->name, cp->dontdelete);
+      gal_checkset_check_remove_file(crp->name, 0, cp->dontdelete);
     }
   else
     {
@@ -464,7 +464,7 @@ cropname(struct onecropparams *crp)
       if(p->outnameisfile)            /* An output file was specified. */
         {
           crp->name=cp->output;
-          gal_checkset_check_remove_file(crp->name, cp->dontdelete);
+          gal_checkset_check_remove_file(crp->name, 0, cp->dontdelete);
         }
       else          /* The output was a directory, use automatic output. */
         crp->name=gal_checkset_automatic_output(cp,
diff --git a/bin/fits/Makefile.am b/bin/fits/Makefile.am
index 3bb2dfd..5ef0f60 100644
--- a/bin/fits/Makefile.am
+++ b/bin/fits/Makefile.am
@@ -30,9 +30,9 @@ bin_PROGRAMS = astfits
 
 astfits_LDADD = -lgnuastro
 
-astfits_SOURCES = main.c ui.c extension.c fits.c header.c
+astfits_SOURCES = main.c ui.c extension.c fits.c keywords.c
 
-EXTRA_DIST = main.h authors-cite.h args.h ui.h extension.c fits.c header.h
+EXTRA_DIST = main.h authors-cite.h args.h ui.h extension.c fits.c keywords.h
 
 
 ## The configuration file (distribute and install).
diff --git a/bin/fits/args.h b/bin/fits/args.h
index 9e8ae45..3f1c3ad 100644
--- a/bin/fits/args.h
+++ b/bin/fits/args.h
@@ -34,7 +34,54 @@ struct argp_option program_options[] =
 
     {
       0, 0, 0, 0,
-      "Header keywords:",
+      "HDUs (extensions):",
+      ARGS_GROUP_EXTENSION
+    },
+    {
+      "remove",
+      ARGS_OPTION_KEY_REMOVE,
+      "STR",
+      0,
+      "Remove extension from input file.",
+      ARGS_GROUP_EXTENSION,
+      &p->remove,
+      GAL_DATA_TYPE_STRLL,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+    {
+      "copy",
+      ARGS_OPTION_KEY_COPY,
+      "STR",
+      0,
+      "Copy extension to output file.",
+      ARGS_GROUP_EXTENSION,
+      &p->copy,
+      GAL_DATA_TYPE_STRLL,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+    {
+      "cut",
+      ARGS_OPTION_KEY_CUT,
+      "STR",
+      0,
+      "Copy extension to output and remove from input.",
+      ARGS_GROUP_EXTENSION,
+      &p->cut,
+      GAL_DATA_TYPE_STRLL,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+
+
+
+    {
+      0, 0, 0, 0,
+      "Keywords (in one HDU):",
       ARGS_GROUP_KEYWORD
     },
     {
@@ -142,13 +189,13 @@ struct argp_option program_options[] =
       GAL_OPTIONS_NOT_SET
     },
     {
-      "printall",
-      ARGS_OPTION_KEY_PRINTALL,
+      "printallkeys",
+      ARGS_OPTION_KEY_PRINTALLKEYS,
       0,
       0,
-      "Print all keywords in the desired HDU.",
-      GAL_OPTIONS_GROUP_OPERATING_MODE,
-      &p->printall,
+      "Print all keywords in the selected HDU.",
+      ARGS_GROUP_KEYWORD,
+      &p->printallkeys,
       GAL_OPTIONS_NO_ARG_TYPE,
       GAL_OPTIONS_RANGE_0_OR_1,
       GAL_OPTIONS_NOT_MANDATORY,
diff --git a/bin/fits/fits.c b/bin/fits/fits.c
index 63d6a9b..bbce9d9 100644
--- a/bin/fits/fits.c
+++ b/bin/fits/fits.c
@@ -24,6 +24,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include <errno.h>
 #include <error.h>
+#include <string.h>
 
 #include <gnuastro/fits.h>
 #include <gnuastro/blank.h>
@@ -33,7 +34,46 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include "main.h"
 
-#include "header.h"
+#include "fits.h"
+#include "keywords.h"
+
+
+
+int
+fits_has_error(struct fitsparams *p, int actioncode, char *string, int status)
+{
+  char *action;
+  int r=EXIT_SUCCESS;
+
+  switch(actioncode)
+    {
+    case FITS_ACTION_DELETE:        action="deleted";      break;
+    case FITS_ACTION_RENAME:        action="renamed";      break;
+    case FITS_ACTION_UPDATE:        action="updated";      break;
+    case FITS_ACTION_WRITE:         action="written";      break;
+    case FITS_ACTION_COPY:          action="copied";       break;
+    case FITS_ACTION_REMOVE:        action="renoved";      break;
+
+    default:
+      error(EXIT_FAILURE, 0, "a bug! Please contact us at `%s' so we can fix "
+            "this problem. In `header.c'. The value of actionid in "
+            "`haserror' must not be %d", PACKAGE_BUGREPORT, actioncode);
+    }
+
+  if(p->quitonerror)
+    {
+      fits_report_error(stderr, status);
+      error(EXIT_FAILURE, 0, "not %s: %s\n", action, string);
+    }
+  else
+    {
+      fprintf(stderr, "Not %s: %s\n", action, string);
+      r=EXIT_FAILURE;
+    }
+  return r;
+}
+
+
 
 
 
@@ -192,7 +232,6 @@ fits_print_extension_info(struct fitsparams *p)
       printf("-----\n");
     }
   gal_table_write(cols, NULL, GAL_TABLE_FORMAT_TXT, NULL, 0);
-  if(!p->cp.quiet) printf("-----\n");
   gal_data_free_ll(cols);
 }
 
@@ -200,13 +239,116 @@ fits_print_extension_info(struct fitsparams *p)
 
 
 
+static void
+fits_hdu_remove(struct fitsparams *p, int *r)
+{
+  char *hdu;
+  fitsfile *fptr;
+  int status=0, hdutype;
+
+  while(p->remove)
+    {
+      /* Pop-out the top element. */
+      gal_linkedlist_pop_from_stll(&p->remove, &hdu);
+
+      /* Open the FITS file at the specified HDU. */
+      fptr=gal_fits_hdu_open(p->filename, hdu, READWRITE);
+
+      /* Delete the extension. */
+      if( fits_delete_hdu(fptr, &hdutype, &status) )
+        *r=fits_has_error(p, FITS_ACTION_REMOVE, hdu, status);
+
+      /* Close the file. */
+      fits_close_file(fptr, &status);
+    }
+}
+
+
+
+
+
+static void
+fits_hdu_copy(struct fitsparams *p, int cut1_copy0, int *r)
+{
+  char *hdu;
+  fitsfile *in, *out;
+  int status=0, hdutype;
+  struct gal_linkedlist_stll *list = cut1_copy0 ? p->cut : p->copy;
+
+  /* Open the output file. */
+  out=gal_fits_open_to_write(p->cp.output);
+
+  /* Copy all the given extensions. */
+  while(list)
+    {
+      /* Pop-out the top element. */
+      gal_linkedlist_pop_from_stll(&list, &hdu);
+
+      /* Open the FITS file at the specified HDU. */
+      in=gal_fits_hdu_open(p->filename, hdu, READWRITE);
+
+      /* Copy to the extension. */
+      if( fits_copy_hdu(in, out, 0, &status) )
+        *r=fits_has_error(p, FITS_ACTION_COPY, hdu, status);
+
+      /* If this is a `cut' operation, then remove the extension. */
+      if(cut1_copy0)
+        if( fits_delete_hdu(in, &hdutype, &status) )
+          *r=fits_has_error(p, FITS_ACTION_REMOVE, hdu, status);
+
+      /* Close the input file. */
+      fits_close_file(in, &status);
+    }
+
+  /* Close the output file. */
+  fits_close_file(out, &status);
+}
+
+
+
+
+
 int
 fits(struct fitsparams *p)
 {
-  int r=EXIT_SUCCESS;
-  if(p->mode==FITS_MODE_KEY)
-    r=header(p);
-  else
-    fits_print_extension_info(p);
+  int r=EXIT_SUCCESS, printhduinfo=1;;
+
+  switch(p->mode)
+    {
+    /* Keywords, we have a separate set of functions in `keywords.c'. */
+    case FITS_MODE_KEY:
+      r=keywords(p);
+      break;
+
+    /* HDU, functions defined here. */
+    case FITS_MODE_HDU:
+      if(p->copy)
+        {
+          fits_hdu_copy(p, 0, &r);
+          printhduinfo=0;
+        }
+      if(p->cut)
+        {
+          fits_hdu_copy(p, 1, &r);
+          printhduinfo=0;
+        }
+      if(p->remove)
+        {
+          fits_hdu_remove(p, &r);
+          printhduinfo=0;
+        }
+
+      if(printhduinfo)
+        fits_print_extension_info(p);
+      break;
+
+    /* Not recognized. */
+    default:
+      error(EXIT_FAILURE, 0, "a bug! please contact us at %s to address "
+            "the problem. The code %d is not recognized for p->mode in the "
+            "`fits' function of the Fits program", PACKAGE_BUGREPORT,
+            p->mode);
+    }
+
   return r;
 }
diff --git a/bin/fits/fits.h b/bin/fits/fits.h
index dbcf2fc..0564af1 100644
--- a/bin/fits/fits.h
+++ b/bin/fits/fits.h
@@ -23,6 +23,25 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #ifndef FITS_H
 #define FITS_H
 
+
+
+enum fits_action_ids
+  {
+    FITS_ACTION_INVALID,        /* ==0: by C standard. */
+
+    FITS_ACTION_DELETE,
+    FITS_ACTION_RENAME,
+    FITS_ACTION_UPDATE,
+    FITS_ACTION_WRITE,
+
+    FITS_ACTION_COPY,
+    FITS_ACTION_REMOVE,
+  };
+
+int
+fits_has_error(struct fitsparams *p, int actioncode, char *string,
+               int status);
+
 int
 fits(struct fitsparams *p);
 
diff --git a/bin/fits/header.c b/bin/fits/keywords.c
similarity index 78%
rename from bin/fits/header.c
rename to bin/fits/keywords.c
index 93baf36..bfdaffe 100644
--- a/bin/fits/header.c
+++ b/bin/fits/keywords.c
@@ -35,7 +35,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 #include "main.h"
 
-
+#include "fits.h"
 
 
 
@@ -48,7 +48,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 /******************           Preparations          ********************/
 /***********************************************************************/
 static void
-header_open(struct fitsparams *p, fitsfile **fptr, int iomode)
+keywords_open(struct fitsparams *p, fitsfile **fptr, int iomode)
 {
   if(*fptr==NULL)
     *fptr=gal_fits_hdu_open(p->filename, p->cp.hdu, iomode);
@@ -58,49 +58,6 @@ header_open(struct fitsparams *p, fitsfile **fptr, int 
iomode)
 
 
 
-int
-haserror(struct fitsparams *p, int actionid, char *string, int status)
-{
-  char action[20];
-  int r=EXIT_SUCCESS;
-
-  switch(actionid)
-    {
-    case 1:
-      strcpy(action, "deleted");
-      break;
-    case 2:
-      strcpy(action, "renamed");
-      break;
-    case 3:
-      strcpy(action, "updated");
-      break;
-    case 4:
-      strcpy(action, "written");
-      break;
-    default:
-      error(EXIT_FAILURE, 0, "a bug! Please contact us at `%s' so we can fix "
-            "this problem. In `header.c'. The value of actionid in "
-            "`haserror' must not be %d", PACKAGE_BUGREPORT, actionid);
-    }
-
-  if(p->quitonerror)
-    {
-      fits_report_error(stderr, status);
-      error(EXIT_FAILURE, 0, "not deleted: %s\n", string);
-    }
-  else
-    {
-      fprintf(stderr, "Not deleted: %s\n", string);
-      r=EXIT_FAILURE;
-    }
-  return r;
-}
-
-
-
-
-
 
 
 
@@ -120,13 +77,13 @@ haserror(struct fitsparams *p, int actionid, char *string, 
int status)
 /******************        File manipulation        ********************/
 /***********************************************************************/
 static void
-header_rename_keys(struct fitsparams *p, fitsfile **fptr, int *r)
+keywords_rename_keys(struct fitsparams *p, fitsfile **fptr, int *r)
 {
   int status=0;
   char *copy, *str, *from, *to;
 
   /* Set the FITS file pointer. */
-  header_open(p, fptr, READWRITE);
+  keywords_open(p, fptr, READWRITE);
 
   /* Tokenize the */
   while(p->rename!=NULL)
@@ -152,7 +109,7 @@ header_rename_keys(struct fitsparams *p, fitsfile **fptr, 
int *r)
 
       /* Rename the keyword */
       fits_modify_name(*fptr, from, to, &status);
-      if(status) *r=haserror(p, 2, from, status);
+      if(status) *r=fits_has_error(p, FITS_ACTION_RENAME, from, status);
 
       /* Clean up the user's input string. Note that `strtok' just changes
          characters within the allocated string, no extra allocation is
@@ -167,14 +124,14 @@ header_rename_keys(struct fitsparams *p, fitsfile **fptr, 
int *r)
 
 
 static void
-header_write_update(struct fitsparams *p, fitsfile **fptr,
+keywords_write_update(struct fitsparams *p, fitsfile **fptr,
                     struct gal_fits_key_ll *keyll, int u1w2)
 {
   int status=0;
   struct gal_fits_key_ll *tmp;
 
   /* Open the FITS file if it hasn't been opened yet. */
-  header_open(p, fptr, READWRITE);
+  keywords_open(p, fptr, READWRITE);
 
   /* Go through each key and write it in the FITS file. */
   while(keyll!=NULL)
@@ -246,14 +203,14 @@ header_write_update(struct fitsparams *p, fitsfile **fptr,
 
 
 static void
-header_print_all_keys(struct fitsparams *p, fitsfile **fptr)
+keywords_print_all_keys(struct fitsparams *p, fitsfile **fptr)
 {
-  size_t i;
+  size_t i=0;
   int nkeys, status=0;
   char *fullheader, *c, *cf;
 
   /* Open the FITS file. */
-  header_open(p, fptr, READONLY);
+  keywords_open(p, fptr, READONLY);
 
   /* Conver the header into a contiguous string. */
   if( fits_hdr2str(*fptr, 0, NULL, 0, &fullheader, &nkeys, &status) )
@@ -302,46 +259,40 @@ header_print_all_keys(struct fitsparams *p, fitsfile 
**fptr)
 /******************           Main function         ********************/
 /***********************************************************************/
 int
-header(struct fitsparams *p)
+keywords(struct fitsparams *p)
 {
   int status=0;
   int r=EXIT_SUCCESS;
   fitsfile *fptr=NULL;
   struct gal_linkedlist_stll *tstll;
 
-  /* Open the requested extension. */
-  if(!p->cp.hdu)
-    error(EXIT_FAILURE, 0, "to modify keywords in a header data unit (HDU) "
-          "the extension in the FITS file is necessary, but none has been "
-          "specified, please use the `--hdu' (or `-h') option to specify "
-          "one");
-
 
   /* Delete the requested keywords. */
   if(p->delete)
     {
-      header_open(p, &fptr, READWRITE);
+      keywords_open(p, &fptr, READWRITE);
       for(tstll=p->delete; tstll!=NULL; tstll=tstll->next)
         {
           fits_delete_key(fptr, tstll->v, &status);
-          if(status) r=haserror(p, 1, tstll->v, status);
+          if(status)
+            r=fits_has_error(p, FITS_ACTION_DELETE, tstll->v, status);
         }
     }
 
 
   /* Rename the requested keywords. */
   if(p->rename)
-    header_rename_keys(p, &fptr, &r);
+    keywords_rename_keys(p, &fptr, &r);
 
 
   /* Update the requested keywords. */
   if(p->update)
-    header_write_update(p, &fptr, p->update_keys, 1);
+    keywords_write_update(p, &fptr, p->update_keys, 1);
 
 
   /* Write the requested keywords. */
   if(p->write)
-    header_write_update(p, &fptr, p->write_keys, 2);
+    keywords_write_update(p, &fptr, p->write_keys, 2);
 
 
   /* Put in any full line of keywords as-is. */
@@ -349,7 +300,7 @@ header(struct fitsparams *p)
     for(tstll=p->asis; tstll!=NULL; tstll=tstll->next)
       {
         fits_write_record(fptr, tstll->v, &status);
-        if(status) r=haserror(p, 1, tstll->v, status);
+        if(status) r=fits_has_error(p, FITS_ACTION_WRITE, tstll->v, status);
       }
 
 
@@ -357,7 +308,7 @@ header(struct fitsparams *p)
   if(p->history)
     {
       fits_write_history(fptr, p->history, &status);
-      if(status) r=haserror(p, 4, "HISTORY", status);
+      if(status) r=fits_has_error(p, FITS_ACTION_WRITE, "HISTORY", status);
     }
 
 
@@ -365,7 +316,7 @@ header(struct fitsparams *p)
   if(p->comment)
     {
       fits_write_comment(fptr, p->comment, &status);
-      if(status) r=haserror(p, 4, "COMMENT", status);
+      if(status) r=fits_has_error(p, FITS_ACTION_WRITE, "COMMENT", status);
     }
 
 
@@ -373,14 +324,14 @@ header(struct fitsparams *p)
   if(p->date)
     {
       fits_write_date(fptr, &status);
-      if(status) r=haserror(p, 4, "DATE", status);
+      if(status) r=fits_has_error(p, FITS_ACTION_WRITE, "DATE", status);
     }
 
 
   /* If nothing was requested, then print all the keywords in this
      extension. */
-  if(p->printall)
-    header_print_all_keys(p, &fptr);
+  if(p->printallkeys)
+    keywords_print_all_keys(p, &fptr);
 
 
   /* Close the FITS file */
diff --git a/bin/fits/header.h b/bin/fits/keywords.h
similarity index 97%
rename from bin/fits/header.h
rename to bin/fits/keywords.h
index 2c0cd0a..2850929 100644
--- a/bin/fits/header.h
+++ b/bin/fits/keywords.h
@@ -24,6 +24,6 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #define HEADER_H
 
 int
-header(struct fitsparams *p);
+keywords(struct fitsparams *p);
 
 #endif
diff --git a/bin/fits/main.h b/bin/fits/main.h
index cbb394e..142ab00 100644
--- a/bin/fits/main.h
+++ b/bin/fits/main.h
@@ -54,7 +54,10 @@ struct fitsparams
   /* From the environment. */
   struct gal_options_common_params cp;  /* Common parameters.              */
   char                      *filename;  /* Name of input file.             */
-  uint8_t                    printall;  /* Print all the header keywords.  */
+  struct gal_linkedlist_stll  *remove;  /* Remove extensions from a file.  */
+  struct gal_linkedlist_stll    *copy;  /* Copy extensions to output.      */
+  struct gal_linkedlist_stll     *cut;  /* Copy ext. to output and remove. */
+  uint8_t                printallkeys;  /* Print all the header keywords.  */
   uint8_t                        date;  /* Set DATE to current time.       */
   char                       *comment;  /* COMMENT value.                  */
   char                       *history;  /* HISTORY value.                  */
@@ -66,7 +69,7 @@ struct fitsparams
   uint8_t                 quitonerror;  /* Quit if an error occurs.        */
 
   /* Internal: */
-  int                            mode;
+  int                            mode;  /* Operating on HDUs or keywords.  */
   struct gal_fits_key_ll  *write_keys;  /* Keys to write in the header.    */
   struct gal_fits_key_ll *update_keys;  /* Keys to update in the header.   */
   time_t                      rawtime;  /* Starting time of the program.   */
diff --git a/bin/fits/ui.c b/bin/fits/ui.c
index b2a2672..6ce9363 100644
--- a/bin/fits/ui.c
+++ b/bin/fits/ui.c
@@ -106,6 +106,7 @@ ui_initialize_options(struct fitsparams *p,
   struct gal_options_common_params *cp=&p->cp;
 
   /* Set the necessary common parameters structure. */
+  cp->keep               = 1;
   cp->poptions           = program_options;
   cp->program_name       = PROGRAM_NAME;
   cp->program_exec       = PROGRAM_EXEC;
@@ -114,7 +115,7 @@ ui_initialize_options(struct fitsparams *p,
   cp->coptions           = gal_commonopts_options;
 
   /* For clarity and non-zero initializations. */
-  p->mode=FITS_MODE_INVALID;
+  p->mode                = FITS_MODE_INVALID;
 
   /* Don't show the unused options. */
   for(i=0; !gal_options_is_last(&cp->coptions[i]); ++i)
@@ -122,12 +123,18 @@ ui_initialize_options(struct fitsparams *p,
       {
       case GAL_OPTIONS_KEY_SEARCHIN:
       case GAL_OPTIONS_KEY_IGNORECASE:
-      case GAL_OPTIONS_KEY_OUTPUT:
       case GAL_OPTIONS_KEY_TYPE:
       case GAL_OPTIONS_KEY_TABLEFORMAT:
       case GAL_OPTIONS_KEY_DONTDELETE:
-      case GAL_OPTIONS_KEY_KEEPINPUTDIR:
+      case GAL_OPTIONS_KEY_LOG:
+      case GAL_OPTIONS_KEY_MINMAPSIZE:
+      case GAL_OPTIONS_KEY_NUMTHREADS:
         cp->coptions[i].flags=OPTION_HIDDEN;
+        break;
+
+      case GAL_OPTIONS_KEY_OUTPUT:
+        cp->coptions[i].doc="Output file name (only for writing HDUs).";
+        break;
       }
 
 }
@@ -214,16 +221,39 @@ ui_read_check_only_options(struct fitsparams *p)
   /* If any of the keyword manipulation options are requested, then set the
      mode flag to keyword-mode. */
   if( p->date || p->comment || p->history || p->asis || p->delete
-      || p->rename || p->rename || p->update || p->write )
-    p->mode=FITS_MODE_KEY;
+      || p->rename || p->rename || p->update || p->write || p->printallkeys )
+    {
+      /* Set the mode. */
+      p->mode=FITS_MODE_KEY;
+
+      /* Check if a HDU is given. */
+      if(p->cp.hdu==NULL)
+        error(EXIT_FAILURE, 0, "a HDU (extension) is necessary for keywrod "
+              "related options but none was defined. Please use the "
+              "`--hdu' (or `-h') option to select one");
+    }
 
-  /* If any of the extension keywords are given, then set the mode.
-    error(EXIT_FAILURE, 0, "extension and keyword manipulation options "
-          "cannot be called together");
-  */
+  /* Same for the extension-related options */
+  if( p->remove || p->copy || p->cut )
+    {
+      /* A small sanity check. */
+      if(p->mode!=FITS_MODE_INVALID)
+        error(EXIT_FAILURE, 0, "extension and keyword manipulation options "
+              "cannot be called together");
+
+      /* Set the mode and turn on the `needshdu' flag. */
+      p->mode=FITS_MODE_HDU;
+
+      /* Make sure the output name is set. */
+      if(p->cp.output)
+        gal_checkset_check_remove_file(p->filename, 1, p->cp.dontdelete);
+      else
+        p->cp.output=gal_checkset_automatic_output(&p->cp, p->filename,
+                                                   "_ext.fits");
+    }
 
-  /* If no mode-specifying options are given, then go into extension
-     mode. */
+  /* If no options are given, go into HDU mode, which will print the HDU
+     information when nothing is asked. */
   if(p->mode==FITS_MODE_INVALID)
     p->mode=FITS_MODE_HDU;
 }
@@ -495,6 +525,5 @@ void
 ui_free_and_report(struct fitsparams *p)
 {
   /* Free the allocated arrays: */
-  free(p->cp.hdu);
   free(p->cp.output);
 }
diff --git a/bin/fits/ui.h b/bin/fits/ui.h
index be2fed0..6bceab3 100644
--- a/bin/fits/ui.h
+++ b/bin/fits/ui.h
@@ -29,14 +29,17 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 /* Available letters for short options:
 
-   b e f g j k l m n s v x y z
-   A B C E F G J L M O R W X Y Z
+   b e f g j l m n s v x y z
+   A B E F G J L M O W X Y Z
 
 */
 enum option_keys_enum
 {
   /* With short-option version. */
-  ARGS_OPTION_KEY_PRINTALL     = 'p',
+  ARGS_OPTION_KEY_REMOVE       = 'R',
+  ARGS_OPTION_KEY_COPY         = 'C',
+  ARGS_OPTION_KEY_CUT          = 'k',
+  ARGS_OPTION_KEY_PRINTALLKEYS = 'p',
   ARGS_OPTION_KEY_ASIS         = 'a',
   ARGS_OPTION_KEY_DELETE       = 'd',
   ARGS_OPTION_KEY_RENAME       = 'r',
diff --git a/bin/mknoise/ui.c b/bin/mknoise/ui.c
index 077622a..78d7c5d 100644
--- a/bin/mknoise/ui.c
+++ b/bin/mknoise/ui.c
@@ -263,7 +263,7 @@ ui_preparations(struct mknoiseparams *p)
 
   /* Set the output name: */
   if(p->cp.output)
-    gal_checkset_check_remove_file(p->cp.output, p->cp.dontdelete);
+    gal_checkset_check_remove_file(p->cp.output, 0, p->cp.dontdelete);
   else
     p->cp.output=gal_checkset_automatic_output(&p->cp, p->inputname,
                                                "_noised.fits");
diff --git a/bin/mkprof/mkprof.c b/bin/mkprof/mkprof.c
index 6b5d77b..df0584d 100644
--- a/bin/mkprof/mkprof.c
+++ b/bin/mkprof/mkprof.c
@@ -130,7 +130,7 @@ saveindividual(struct mkonthread *mkp)
 
   /* Write the name and remove a similarly named file. */
   asprintf(&filename, "%s%zu_%s", outdir, ibq->id, p->basename);
-  gal_checkset_check_remove_file(filename, p->cp.dontdelete);
+  gal_checkset_check_remove_file(filename, 0, p->cp.dontdelete);
 
   /* Put the array into a data structure */
   data=gal_data_alloc(ibq->img, GAL_DATA_TYPE_FLOAT32, 2, dsize, NULL, 0,
diff --git a/bin/warp/ui.c b/bin/warp/ui.c
index 4d46e3a..3760929 100644
--- a/bin/warp/ui.c
+++ b/bin/warp/ui.c
@@ -850,7 +850,7 @@ ui_preparations(struct warpparams *p)
      which we will need to determine the suffix if no output name is
      specified. */
   if(p->cp.output)
-    gal_checkset_check_remove_file(p->cp.output, p->cp.dontdelete);
+    gal_checkset_check_remove_file(p->cp.output, 0, p->cp.dontdelete);
   else
     p->cp.output=gal_checkset_automatic_output(&p->cp, p->inputname,
                                                ui_set_suffix(p));
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 98265bf..53b0b43 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -191,7 +191,7 @@ sub-component to a title is present.
 * Tutorials::                   Tutorials or Cookbooks.
 * Installation::                Requirements and installation.
 * Common program behavior::     Common behavior in all programs.
-* Extensions and Tables::       Tools to operate on extensions and tables.
+* Data containers::             Tools to operate on extensions and tables.
 * Data manipulation::           Tools for basic image manipulation.
 * Data analysis::               Analyze images.
 * Modeling and fittings::       Make and fit models.
@@ -293,8 +293,8 @@ Command-line
 
 Arguments and options
 
-* Arguments::
-* Options::
+* Arguments::                   For specifying the main input files/operations.
+* Options::                     For configuring the behavior of the program.
 
 Common options
 
@@ -331,7 +331,7 @@ Getting help
 * Info::                        View complete book in terminal.
 * help-gnuastro mailing list::  Contacting experienced users.
 
-Extensions and Tables
+Data containers
 
 * Fits::                        View and manipulate extensions and keywords.
 * ConvertType::                 Convert data to various formats.
@@ -341,6 +341,11 @@ Fits
 
 * Invoking astfits::            Arguments and options to Header.
 
+Invoking Fits
+
+* HDU manipulation::            Manipulate HDUs within a FITS file.
+* Keyword manipulation::        Manipulate metadata keywords in a HDU
+
 ConvertType
 
 * Recognized file formats::     Recognized file formats
@@ -3946,7 +3951,7 @@ If your problem was not listed above, please file a bug 
report
 
 
 
address@hidden Common program behavior, Extensions and Tables, Installation, Top
address@hidden Common program behavior, Data containers, Installation, Top
 @chapter Common program behavior
 
 All the programs in Gnuastro share a set of common behavior mainly to do
@@ -4076,8 +4081,8 @@ double quotes are much more easier, elegant and readable.
 
 
 @menu
-* Arguments::
-* Options::
+* Arguments::                   For specifying the main input files/operations.
+* Options::                     For configuring the behavior of the program.
 @end menu
 
 @node Arguments, Options, Arguments and options, Arguments and options
@@ -6072,32 +6077,45 @@ END
 
 
 
address@hidden Extensions and Tables, Data manipulation, Common program 
behavior, Top
address@hidden Extensions and Tables
address@hidden Data containers, Data manipulation, Common program behavior, Top
address@hidden Data containers
 
 @cindex File operations
 @cindex Operations on files
 @cindex General file operations
-This chapter documents those Gnuastro programs that don't directly operate
-on the contents of the data file, they just print information, or convert
-from different data types, there is no further processing. Before working
-on a FITS file, it is commonly the case that you are not sure how many
-extensions it has within it and also what each extension is (image, table
-or blank). In such cases, Fits (see @ref{Fits}) can be handy by printing
-the information for all the extensions in a FITS file, or all the keywords
-in an extension of a FITS file to the terminal for easy inspection. You can
-also add/remove extensions/keywords with it.
-
-In other cases you want to use the data in a FITS file in other programs
-(for example in reports) that don't recognize the FITS format, for example
-converting a FITS image into a Jpeg, or PDF format image. ConvertType (see
address@hidden) was built for such situations. Finally, the FITS format
-is not just for images, it can also store tables. Binary tables in
-particular can be very useful in storing very large catalogs or tables
-compared to a plain text file. Table (see @ref{Table}) can be used to
-choose certain table columns in a FITS table and see them as a human
-readable output on the terminal, or to save them in another plain text or
-FITS table.
+The most low-level and basic property of a dataset is how it is stored. To
+process, archive and transmit the data you need a container to store it
+first. From the start of the computer age, different formats have been
+difined to store data, optimized for pariticular applications, one
+format/container can never be useful for all applications. In astronomy,
+FITS is the most common format of data storage and transmission. It has
+many useful features, for example multiple data containers (also known as
+extensions or header data units, HDUs) within one file. Each HDU can store
+independent data and its corresponding meta-data. Therefore, Gnuastro has
+one program (see @ref{Fits}) specifically designed to manipulate FITS HDUs
+and the meta-data (header keywords) in each HDU.
+
+Your astronomical research does not just involve data analysis (where the
+FITS format is very useful). For example you want to demonstrate your raw
+and processed FITS images or spectra as figures within slides, reports, or
+papers. The FITS format is not defined for such applications. Thus,
+Gnuastro also comes with the ConvertType program (see @ref{ConvertType})
+which can be used to convert a FITS image to and from (where possible)
+other formats like plain text and JPEG which allow two way conversion,
+along with EPS and PDF (which can only be created from FITS, not the other
+way round).
+
+Finally, the FITS format is not just for images, it can also store
+tables. Binary tables in particular can be very useful in storing very
+large catalogs or tables compared to a plain text file. However, unlike
+images (where all elements/pixels have one data type), tables contain
+multiple columns and each column can have different properties (numerical
+types, or even character based columns, like names). In practice, each
+column can be viewed a separate data-container that is grouped with others
+in the table. To allow easy manipulation/viewing of table columns, Gnuastro
+has the Table program (see @ref{Table}). It can be used to choose certain
+table columns in a FITS table and see them as a human readable output on
+the command-line, or to save them into another plain text or FITS table.
 
 @menu
 * Fits::                        View and manipulate extensions and keywords.
@@ -6109,17 +6127,85 @@ FITS table.
 
 
 
address@hidden Fits, ConvertType, Extensions and Tables, Extensions and Tables
address@hidden Fits, ConvertType, Data containers, Data containers
 @section Fits
 
-The FITS standard requires each extension of a FITS file to have a
-header, giving basic information about what is in that extension. Each
-line in the header is for one keyword, specifying its name, value and
-a short comment string. Besides the basic information, the headers
-also contain vital information about the data, how they were
-processed, the instrument specifications that took the image and also
-the World Coordinate System that is used to translate pixel
-coordinates to sky or spectrum coordinates on the image or table.
+The ``Flexible Image Transport System'', or FITS, is by far the most common
+data container format in astronomy. Although the full name of the standard
+invokes the idea that it is only for images, it also contains very complete
+and robust features for tables. It started off in the 1970s and was
+formally published as a standard in 1981, it was adopted by the
+International Astronomical Union (IAU) in 1982 and an IAU working group to
+maintain its future was defined in 1988. The FITS 2.0 and 3.0 standards
+were approved in 2000 and 2008 respectively, and the 4.0 draft has also
+been released recently, please see the
address@hidden://fits.gsfc.nasa.gov/fits_standard.html, FITS standard document
+webpage} for the full text of all versions. Also see the
address@hidden://doi.org/10.1051/0004-6361/201015362, FITS 3.0 standard paper}
+for a nice introduction and history along with the full standard.
+
address@hidden Meta-data
+Other formats, for example a JPEG image, only have one image/dataset per
+file, however one great advantage of the FITS standard is that it allows
+you to keep multiple datasets (images or tables along with their meta-data)
+in one file. Each data + metadata is known as an extension, or more
+formally a header data unit or HDU, in the FITS standard. In theory the
+HDUs can be completely independent: you can have multiple images of
+different dimensions/sizes or tables as separate extensions in one
+file. However, while the standard doesn't impose any constraints on the
+relation between the datasets, it is strongly encouraged to group data that
+are contextually related with each other in one file. For example an image
+and the table/catalog of objects and their measured properties in that
+image. Another example can be multiple images of one patch of sky in
+different colors (filters).
+
+The extensions can be completely independent, to keep some information
+(meta-data) about the group of extensions in the FITS file, the community
+has adopted the following convension: put no data in the first extension,
+so it is just meta-data). Meta-data regarding the whole file (grouping of
+extensions) can then be put there. All of Gnuastro's programs also follow
+this convention: the main dataset (image or table) is in the second
+extension. See the example list of extension properties in @ref{Invoking
+astfits}.
+
+While your data (image or table) may contain information about some
+galaxies for example, the meta-data contain information about the data, for
+example which region of the sky it corresponds to, the units of the data,
+what telescope, camera, and filter the data were taken with and which
+software the data were prepared with, or at which date. Hence without the
+meta-data, the raw dataset is practically just a collection of numbers and
+really hard to understand. It is thus strongly encouraged to supplement
+your data (at any level of processing) with as much meta-data about your
+processing/science as possible.
+
+The meta-data of a FITS file is in ASCII format, which can be easily viewed
+or edited with a text editor or on the command-line. Each meta-data element
+(known as a keyword generally) is composed of a name, value, units and
+comments (the last two are optional), for example these are three FITS
+meta-data keywords for specifying the world coordinate system (WCS, or its
+location in the sky) of a dataset:
+
address@hidden
+LATPOLE =           -27.805089 / [deg] Native latitude of celestial pole
+RADESYS = 'FK5'                / Equatorial coordinate system
+EQUINOX =               2000.0 / [yr] Equinox of equatorial coordinates
address@hidden example
+
+However, there are some limitations which discourage viewing/editing the
+keywords with text editors. For example there is a fixed length of 80
+characters for each keyword (its name, value, units and comments) and there
+are no new-line characters, so on a text editor all the keywords are seen
+in one line. Also, the meta-data keywords are immediately followed by the
+data which are commonly in binary format and will show up as strange
+looking characters on a text editor, and significantly slowing down the
+processor.
+
+Gnuastro's Fits program was designed to allow easy manipulation of FITS
+extensions and meta-data keywords on the command-line while conforming
+fully with the FITS standard. For example you can copy, remove, or cut
+(copy and remove) HDUs (extensions containing data and metadata) from one
+FITS file to another. It also has features to print all the keywords in a
+HDU, or modify the keywords, add new kewords or delete some others.
 
 @menu
 * Invoking astfits::            Arguments and options to Header.
@@ -6128,12 +6214,12 @@ coordinates to sky or spectrum coordinates on the image 
or table.
 @node Invoking astfits,  , Fits, Fits
 @subsection Invoking Fits
 
-Fits can print or manipulate the header information in an extension of an
-astronomical data file. The executable name is @file{astheader} with the
-following general template
+Fits can print or manipulate the FITS file HDUs (extensions), or print an
+manipulate the meta-data keywords in a given HDU. The executable name is
address@hidden with the following general template
 
 @example
-$ astheader [OPTION...] ASTRdata
+$ astfits [OPTION...] ASTRdata
 @end example
 
 
@@ -6141,45 +6227,140 @@ $ astheader [OPTION...] ASTRdata
 One line examples:
 
 @example
-$ astheader image.fits
-$ astheader --update=OLDKEY,153.034,"Old keyword comment"
-$ astheader --remove=COMMENT --comment="Anything you like ;-)."
-$ astheader --write=MYKEY1,20.00,"An example keyword" --write=MYKEY2,fd
+$ astfits image.fits
+$ astfits image.fits --printall
+$ astfits image.fits --printall | grep NAXIS
+$ astfits input.fits --copy=hdu-name --output=out.fits
+$ astfits --update=OLDKEY,153.034,"Old keyword comment"
+$ astfits --delete=COMMENT --comment="Anything you like ;-)."
+$ astfits --write=MYKEY1,20.00,"An example keyword" --write=MYKEY2,fd
 @end example
 
 @cindex HDU
-If no keyword modification options are given, the full header of the given
-HDU will be printed on the command-line. If any of the keywords are to be
-modified, the headers of the input file will be changed. If you want to
-keep the original FITS file, it is easiest to create a copy first and then
+When no paritcular HDU or keyword options are given, Fits will print a list
+of information about the extension(s) in the file. This information
+includes the HDU number, name, along with the type, and size the data it
+contains (dimension and size along each dimension). You can use this to get
+a general idea of the contents of the FITS file and what HDU to use for
+further processing, either with the Fits program or any other Gnuastro
+program.
+
+Here is one example of information about a FITS file with four exensions:
+the first extension has no data, it is just meta-data (commonly used to
+keep meta-data about the whole file, or grouping of extensions, see
address@hidden). The second extension is an image with name @code{IMAGE} and
+single precision floating point type (@code{float32}, see @ref{Numeric data
+types}), it has 4287 pixels along its first (horizontal) axis and 4286
+pixels along its second (vertical) axis. The third extension is also an
+image with name @code{MASK}. It is in 2-byte integer format (@code{int16})
+which is commonly used to keep information about pixels (for example to
+identify which ones were saturated, or which ones had cosmic rays and so
+on), note how it has the same size as the @code{IMAGE} extension. The third
+extension is a binary table called @code{CATALOG} which has 12371 rows and
+5 columns (it probably contains information about the sources in the
+image).
+
address@hidden
+GNU Astronomy Utilities X.X
+Run on Day Month DD HH:MM:SS YYYY
+-----
+HDU (extension) information: `image.fits'.
+ Column 1: Index (counting from 0).
+ Column 2: Name (`EXTNAME' in FITS standard).
+ Column 3: Image data type or `table' format (ASCII or binary).
+ Column 4: Size of data in HDU.
+-----
+0      n/a             uint8           0
+1      IMAGE           float32         4287x4286
+2      MASK            int16           4287x4286
+3      CATALOG         table_binary    12371x5
address@hidden example
+
+The operating mode and input/output options to Fits are similar to the
+other programs and fully described in @ref{Common options}. The options
+particular to Fits can be divided into two groups: 1) those related to
+modifying HDUs or extensions (see @ref{HDU manipulation}), and 2) those
+related to viewing/modifying meta-data keywords (see @ref{Keyword
+manipulation}). These two classes of options cannot be called together in
+one run: you can either work on the extensions or meta-data keywords in any
+instance of Fits.
+
address@hidden
+* HDU manipulation::            Manipulate HDUs within a FITS file.
+* Keyword manipulation::        Manipulate metadata keywords in a HDU
address@hidden menu
+
+
+
+
+
address@hidden HDU manipulation, Keyword manipulation, Invoking astfits, 
Invoking astfits
address@hidden HDU manipulation
+Each header data unit, or HDU (also known as an extension), in a FITS file
+is an independent dataset (data + meta-data). Multiple HDUs can be stored
+in one FITS file, see @ref{Fits}. The HDU modifying options to the Fits
+program are listed below.
+
+These options may be called multiple times in one run. If so, the
+extensions will be copied from the input FITS file to the output FITS file
+in the given order (on the command-line and also in configuration files,
+see @ref{Configuration file precedence}). If the separate classes are
+called together in one run of Fits, then first @option{--copy} is run (on
+all specified HDUs), followed @option{--cut} (again on all specified HDUs),
+and then @option{--remove} (on all specified HDUs).
+
+The @option{--copy} and @option{--cut} options need an output FITS file
+(specified with the @option{--output} option). If the output file exists,
+then the specified HDU will be copied following the last extension of the
+output file (its existing in it HDUs will be untouched). Thus after Fits
+finishes, the copied HDU will be the last HDU of the output file. If no
+output file name is given, then automatic output will be used to store the
+HDUs given to this option (see @ref{Automatic output}).
+
address@hidden @option
+
address@hidden -C STR
address@hidden --copy=STR
+Copy the specified extension into the output file, see explanations above.
+
address@hidden -k STR
address@hidden --cut=STR
+Cut (copy to output, remove from input) the specified extension into the
+output file, see explanations above.
+
address@hidden -R STR
address@hidden --remove=STR
+Remove the specified HDU from the input file.
+
address@hidden table
+
+
address@hidden Keyword manipulation,  , HDU manipulation, Invoking astfits
address@hidden Keyword manipulation
+The meta-data in each header data unit, or HDU (also known as extension,
+see @ref{Fits}) is stored as ``keyword''s. Each keyword consists of a name,
+value, unit, and comments. The Fits program (see @ref{Fits}) options
+related to viewing and manipulating keywords in a FITS HDU are described
+below.
+
+To see the full list of keywords in a FITS HDU, you can use the
address@hidden option. If any of the keywords are to be modified,
+the headers of the input file will be changed. If you want to keep the
+original FITS file or HDU, it is easiest to create a copy first and then
 run Fits on that. In the FITS standard, keywords are always uppercase. So
 case does not matter in the input or output keyword names you specify.
 
 Most of the options can accept multiple instances in one command. For
-example you can add multiple keywords to delete by calling delete
-multiple times, since repeated keywords are allowed, you can even
-delete the same keyword multiple times. The action of such options
+example you can add multiple keywords to delete by calling
address@hidden multiple times, since repeated keywords are allowed, you
+can even delete the same keyword multiple times. The action of such options
 will start from the top most keyword.
 
address@hidden
address@hidden
address@hidden STANDARD KEYWORDS:} Some header keywords are necessary
-for later operations on a FITS file, for example BITPIX or NAXIS, see
-the FITS standard for their full list. If you modify (for example
-remove or rename) such keywords, the FITS file extension might not be
-usable any more. Also be careful for the world coordinate system
-keywords, if you modify or change their values, any future world
-coordinate system (like RA and Dec) measurements on the image will
-also change.
address@hidden cartouche
-
address@hidden
address@hidden
address@hidden:} The order of operations are as follows. Note that
-while the order within each class of actions is preserved, the order
-of individual actions is not. So irrespective of what order you called
address@hidden and @option{--update}. First all the delete
-operations are going to take effect then the update operations.
+The precedence of operations are described below. Note that while the order
+within each class of actions is preserved, the order of individual actions
+is not. So irrespective of what order you called @option{--delete} and
address@hidden First, all the delete operations are going to take
+effect then the update operations.
 @enumerate
 @item
 @option{--delete}
@@ -6198,30 +6379,41 @@ operations are going to take effect then the update 
operations.
 @item
 @option{--date}
 @item
address@hidden
address@hidden
 @end enumerate
 @noindent
 All possible syntax errors will be reported before the keywords are
 actually written. FITS errors during any of these actions will be reported,
 but Fits won't stop until all the operations are complete. If
address@hidden is called, then Fits will immediately stop upon the
address@hidden is called, then Fits will immediately stop upon the
 first error.
address@hidden cartouche
 
 @cindex GNU Grep
-If only a certain set of header keywords are desired, it is easiest to pipe
-the output of Fits to GNU Grep. Grep is a very powerful and advanced tool
-to search strings which is precisely made for such situations. For example
-if you only want to check the size of an image FITS HDU, you can run:
+If you want to inspect only a certain set of header keywords, it is easiest
+to pipe the output of the Fits program to GNU Grep. Grep is a very powerful
+and advanced tool to search strings which is precisely made for such
+situations. For example if you only want to check the size of an image FITS
+HDU, you can run:
 
 @example
-$ astheader input.fits | grep NAXIS
+$ astfits input.fits | grep NAXIS
 @end example
 
address@hidden
 @noindent
-The options particular to Fits can be seen below. See @ref{Common options}
-for a list of the options that are common to all Gnuastro programs, they
-are not repeated here.
address@hidden STANDARD KEYWORDS:} Some header keywords are necessary
+for later operations on a FITS file, for example BITPIX or NAXIS, see
+the FITS standard for their full list. If you modify (for example
+remove or rename) such keywords, the FITS file extension might not be
+usable any more. Also be careful for the world coordinate system
+keywords, if you modify or change their values, any future world
+coordinate system (like RA and Dec) measurements on the image will
+also change.
address@hidden cartouche
+
+
address@hidden
+The keyword related options to the Fits program are fully described below.
 @table @option
 
 @item -a STR
@@ -6233,32 +6425,32 @@ define the keyword from scratch, it is best to use the 
@option{--write}
 option (see below) and let CFITSIO worry about the standards. The best way
 to use this option is when you want to add a keyword from one FITS file to
 another unchanged and untouched. Below is an example of such a case that
-can be very useful sometimes:
+can be very useful sometimes (on the command-line or in scripts):
 
 @example
-$ key=$(astheader firstimage.fits | grep KEYWORD)
-$ astheader --asis="$key" secondimage.fits
+$ key=$(astfits firstimage.fits | grep KEYWORD)
+$ astfits --asis="$key" secondimage.fits
 @end example
 
 @cindex GNU Bash
 In particular note the double quotation signs (@key{"}) around the
-reference to the @command{key} shell variable (@command{$key}), since
-FITS keywords usually have lots of space characters, if this variable
-is not enclosed within double quotation marks, the shell will only
-give the first word in the full keyword to this option, which will
-definitely be a non-standard FITS keyword and will make it hard to
-work on the file afterwords. See the ``Quoting'' section of the GNU
-Bash manual for more information if your keyword has the special
+reference to the @command{key} shell variable (@command{$key}), since FITS
+keywords usually have lots of space characters, if this variable is not
+quoted, the shell will only give the first word in the full keyword to this
+option, which will definitely be a non-standard FITS keyword and will make
+it hard to work on the file afterwords. See the ``Quoting'' section of the
+GNU Bash manual for more information if your keyword has the special
 characters @key{$}, @key{`}, or @key{\}.
 
 @item -d STR
 @itemx --delete=STR
 Delete one instance of the @option{STR} keyword from the FITS
 header. Multiple instances of @option{--delete} can be given (possibly even
-for the same keyword). All keywords given will be removed from the headers
-in the opposite order (last given keyword will be deleted first). If the
-keyword doesn't exist, Fits will give a warning and return with a
-non-zero value, but will not stop.
+for the same keyword, when its repeated in the meta-data). All keywords
+given will be removed from the headers in the same given order. If the
+keyword doesn't exist, Fits will give a warning and return with a non-zero
+value, but will not stop. To stop as soon as an error occurs, run with
address@hidden
 
 @item -r STR
 @itemx --rename=STR
@@ -6268,7 +6460,9 @@ space character. Note that if you use a space character, 
you have to put
 the value to this option within double quotation marks (@key{"}) so the
 space character is not interpreted as an option separator. Multiple
 instances of @option{--rename} can be given in one command. The keywords
-will be renamed in the specified order.
+will be renamed in the specified order. If the keyword doesn't exist, Fits
+will give a warning and return with a non-zero value, but will not stop. To
+stop as soon as an error occurs, run with @option{--quitonerror}.
 
 @item -u STR
 @itemx --update=STR
@@ -6285,6 +6479,10 @@ example:
 --update=KEYWORD,value,"comments for this keyword",unit
 @end example
 
+If there is a writing error, Fits will give a warning and return with a
+non-zero value, but will not stop. To stop as soon as an error occurs, run
+with @option{--quitonerror}.
+
 @noindent
 The value can be any numerical or string address@hidden tricky
 situations arise with values like address@hidden', if this was intended
@@ -6318,17 +6516,25 @@ comments and units for the keyword, see the 
@option{--update} option above.
 Add a @code{HISTORY} keyword to the header. The string given to this
 keyword will be separated into multiple keyword cards if it is longer than
 70 characters. With each run only one value for the @option{--history}
-option will be read. If there are multiple, it is the last one.
+option will be read. If there are multiple, it is the last one. If there is
+an error, Fits will give a warning and return with a non-zero value, but
+will not stop. To stop as soon as an error occurs, run with
address@hidden
 
 @item -c STR
 @itemx --comment STR
 Add a @code{COMMENT} keyword to the header. Similar to the explanation for
address@hidden above.
address@hidden above. If there is a writing error, Fits will give a
+warning and return with a non-zero value, but will not stop. To stop as
+soon as an error occurs, run with @option{--quitonerror}.
 
 @item -t
 @itemx --date
-Put the current date and time in the header. If the @code{DATE}
-keyword already exists in the header, it will be updated.
+Put the current date and time in the header. If the @code{DATE} keyword
+already exists in the header, it will be updated. If there is a writing
+error, Fits will give a warning and return with a non-zero value, but will
+not stop. To stop as soon as an error occurs, run with
address@hidden
 
 @item -p
 @itemx --printall
@@ -6356,7 +6562,7 @@ continue with the rest of actions.
 
 
 
address@hidden ConvertType, Table, Fits, Extensions and Tables
address@hidden ConvertType, Table, Fits, Data containers
 @section ConvertType
 
 @cindex Data format conversion
@@ -6849,7 +7055,7 @@ want a color image, the colors are going to be mixed up.
 
 @end table
 
address@hidden Table,  , ConvertType, Extensions and Tables
address@hidden Table,  , ConvertType, Data containers
 @section Table
 
 Tables are the products of processing astronomical images and spectra. For
@@ -7008,7 +7214,7 @@ it is possible to output one column more than once.
 
 
 
address@hidden Data manipulation, Data analysis, Extensions and Tables, Top
address@hidden Data manipulation, Data analysis, Data containers, Top
 @chapter Data manipulation
 
 Images are one of the major formats of data that is used in astronomy. The
diff --git a/lib/checkset.c b/lib/checkset.c
index 5c9ef53..8ceec6b 100644
--- a/lib/checkset.c
+++ b/lib/checkset.c
@@ -193,9 +193,14 @@ gal_checkset_check_file_report(char *filename)
 
 
 
-/* Check if a file exists. If so, remove it. */
+/* Check if a file exists and can be opened. If the `keep' value is
+   non-zero, then the file will remain untouched, otherwise, it will be
+   deleted (since most programs need to make a clean output). When the file
+   is to be deleted and `dontdelete' has a non-zero value, then the file
+   won't be deleted, but the program will abort with an error, informing
+   the user that the output can't be made. */
 void
-gal_checkset_check_remove_file(char *filename, int dontdelete)
+gal_checkset_check_remove_file(char *filename, int keep, int dontdelete)
 {
   FILE *tmpfile;
 
@@ -216,15 +221,21 @@ gal_checkset_check_remove_file(char *filename, int 
dontdelete)
       errno=0;
       if(fclose(tmpfile))
         error(EXIT_FAILURE, errno, "%s", filename);
-      if(dontdelete)
-        error(EXIT_FAILURE, 0, "%s already exists and you have "
-              "asked to not remove it with the `--dontdelete` "
-              "(`-D`) option", filename);
 
-      /* Delete the file: */
-      errno=0;
-      if(unlink(filename))
-        error(EXIT_FAILURE, errno, "%s", filename);
+      /* See if the file should be deleted. */
+      if(keep==0)
+        {
+          /* Make sure it is ok to delete the file. */
+          if(dontdelete)
+            error(EXIT_FAILURE, 0, "%s already exists and you have "
+                  "asked to not remove it with the `--dontdelete` "
+                  "(`-D`) option", filename);
+
+          /* Delete the file: */
+          errno=0;
+          if(unlink(filename))
+            error(EXIT_FAILURE, errno, "%s", filename);
+        }
     }
   /* If the file doesn't exist, there is no problem, we wanted to
      remove it any way! Any other kind of error should not be
@@ -282,7 +293,7 @@ gal_checkset_dir_0_file_1(char *name, int dontdelete)
     return 0;
   else if (S_ISREG(nameinfo.st_mode))  /* It is a file, GOOD. */
     {
-      gal_checkset_check_remove_file(name, dontdelete);
+      gal_checkset_check_remove_file(name, 0, dontdelete);
       return 1;
     }
   else                                 /* Not a file or a dir, ABORT */
@@ -369,7 +380,7 @@ gal_checkset_automatic_output(struct 
gal_options_common_params *cp,
     }
 
   /* Remove the created filename if it already exits. */
-  gal_checkset_check_remove_file(out, cp->dontdelete);
+  gal_checkset_check_remove_file(out, cp->keep, cp->dontdelete);
 
   /* Return the resulting filename. */
   return out;
diff --git a/lib/checkset.h b/lib/checkset.h
index 1f33bdc..ec45dfd 100644
--- a/lib/checkset.h
+++ b/lib/checkset.h
@@ -92,7 +92,7 @@ int
 gal_checkset_check_file_report(char *filename);
 
 void
-gal_checkset_check_remove_file(char *filename, int dontdelete);
+gal_checkset_check_remove_file(char *filename, int keep, int dontdelete);
 
 int
 gal_checkset_dir_0_file_1(char *name, int dontdelete);
diff --git a/lib/commonopts.h b/lib/commonopts.h
index 521748e..10f1eb8 100644
--- a/lib/commonopts.h
+++ b/lib/commonopts.h
@@ -96,7 +96,7 @@ struct argp_option gal_commonopts_options[] =
       GAL_OPTIONS_KEY_OUTPUT,
       "STR",
       0,
-      "Output file or directory name.",
+      "Output name.",
       GAL_OPTIONS_GROUP_OUTPUT,
       &cp->output,
       GAL_DATA_TYPE_STRING,
diff --git a/lib/fits.c b/lib/fits.c
index 6c8bd1d..caf50e8 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -476,6 +476,44 @@ gal_fits_datatype_to_type(int datatype, int 
is_table_column)
 /**************************************************************/
 /**********                  HDU                   ************/
 /**************************************************************/
+fitsfile *
+gal_fits_open_to_write(char *filename)
+{
+  int status=0;
+  long naxes=0;
+  fitsfile *fptr;
+
+  /* When the file exists just open it. Otherwise, create the file. But we
+     want to leave the first extension as a blank extension and put the
+     image in the next extension to be consistent between tables and
+     images. */
+  if(access(filename,F_OK) == -1 )
+    {
+      /* Create the file. */
+      if( fits_create_file(&fptr, filename, &status) )
+        gal_fits_io_error(status, NULL);
+
+      /* Create blank extension. */
+      if( fits_create_img(fptr, BYTE_IMG, 0, &naxes, &status) )
+        gal_fits_io_error(status, NULL);
+
+      /* Close the blank extension. */
+      if( fits_close_file(fptr, &status) )
+        gal_fits_io_error(status, NULL);
+    }
+
+  /* Open the file, ready for later steps. */
+  if( fits_open_file(&fptr,filename, READWRITE, &status) )
+    gal_fits_io_error(status, NULL);
+
+  /* Return the pointer. */
+  return fptr;
+}
+
+
+
+
+
 void
 gal_fits_hdu_num(char *filename, int *numhdu)
 {
@@ -1362,20 +1400,12 @@ gal_fits_img_write_to_ptr(gal_data_t *data, char 
*filename)
                                  ? GAL_DATA_TYPE_INT64
                                  : GAL_DATA_TYPE_INT32 ), data->ndim);
 
-  /* When the file exists, add this image as an extension. Otherwise,
-     create the file. But we want to leave the first extension as a blank
-     extension and put the image in the next extension. */
-  if(access(filename,F_OK) == -1 )
-    {
-      fits_create_file(&fptr, filename, &status);
-      fits_create_img(fptr, SHORT_IMG, 0, naxes, &status);
-      fits_close_file(fptr, &status);
-    }
+  /* Open the file for writing */
+  fptr=gal_fits_open_to_write(filename);
 
   /* Fill the `naxes' array (in opposite order, and `long' type): */
   for(i=0;i<data->ndim;++i)
     naxes[data->ndim-1-i]=data->dsize[i];
-  fits_open_file(&fptr,filename, READWRITE, &status);
 
   /* Create the FITS file. */
   fits_create_img(fptr, gal_fits_type_to_bitpix(data->type),
@@ -2234,7 +2264,7 @@ gal_fits_tab_write(gal_data_t *cols, struct 
gal_linkedlist_stll *comments,
 
 
   /* Remove the output if it already exists. */
-  gal_checkset_check_remove_file(filename, dontdelete);
+  gal_checkset_check_remove_file(filename, 0, dontdelete);
 
 
   /* Create the FITS file */
diff --git a/lib/gnuastro/fits.h b/lib/gnuastro/fits.h
index 57d2a99..c54e8e8 100644
--- a/lib/gnuastro/fits.h
+++ b/lib/gnuastro/fits.h
@@ -144,6 +144,8 @@ gal_fits_datatype_to_type(int datatype, int 
is_table_column);
 /**************************************************************/
 /**********                  HDU                   ************/
 /**************************************************************/
+fitsfile *
+gal_fits_open_to_write(char *filename);
 
 void
 gal_fits_hdu_num(char *filename, int *numhdu);
diff --git a/lib/options.c b/lib/options.c
index 08ef4b0..1953a3b 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -1531,7 +1531,7 @@ options_print_all(struct gal_options_common_params *cp, 
char *dirname,
       asprintf(&filename, "%s/%s.conf", dirname, cp->program_exec);
 
       /* Remove the file if it already exists. */
-      gal_checkset_check_remove_file(filename, 0);
+      gal_checkset_check_remove_file(filename, 0, 0);
 
       /* Open the file for writing */
       errno=0;
diff --git a/lib/options.h b/lib/options.h
index 21b1871..d19b401 100644
--- a/lib/options.h
+++ b/lib/options.h
@@ -177,6 +177,7 @@ struct gal_options_common_params
   uint8_t           lastconfig; /* This is the last configuration file.  */
 
   /* For internal (to option processing) purposes. */
+  uint8_t                 keep; /* Output file can exist.                */
   void         *program_struct; /* Host program's main variable struct.  */
   char           *program_name; /* Official name to be used in text.     */
   char           *program_exec; /* Program's executable name.            */
diff --git a/lib/txt.c b/lib/txt.c
index 4d7d68b..450fb46 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -1177,7 +1177,7 @@ txt_open_file_write_info(gal_data_t *datall, char **fmts,
 
 
   /* Check the file and open it. */
-  gal_checkset_check_remove_file(filename, dontdelete);
+  gal_checkset_check_remove_file(filename, 0, dontdelete);
   errno=0;
   fp=fopen(filename, "w");
   if(fp==NULL)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 263d17c..a1837d2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -101,12 +101,13 @@ if COND_CROP
 endif
 if COND_FITS
   MAYBE_FITS_TESTS = fits/write.sh fits/print.sh fits/update.sh        \
-  fits/delete.sh
+  fits/delete.sh fits/copyhdu.sh
 
   fits/write.sh: mkprof/mosaic1.sh.log
   fits/print.sh: fits/write.sh.log
   fits/update.sh: fits/write.sh.log
   fits/delete.sh: fits/write.sh.log
+  fits/copyhdu.sh: fits/write.sh.log mkprof/mosaic2.sh.log
 endif
 if COND_MKCATALOG
   MAYBE_MKCATALOG_TESTS = mkcatalog/simple.sh mkcatalog/aperturephot.sh
diff --git a/tests/fits/copyhdu.sh b/tests/fits/copyhdu.sh
new file mode 100755
index 0000000..b76f7ee
--- /dev/null
+++ b/tests/fits/copyhdu.sh
@@ -0,0 +1,54 @@
+# Copy an extension from one file to another.
+#
+# See the Tests subsection of the manual for a complete explanation
+# (in the Installing gnuastro section).
+#
+# Original author:
+#     Mohammad Akhlaghi <address@hidden>
+# Contributing author(s):
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.  This file is offered as-is,
+# without any warranty.
+
+
+
+
+
+# Preliminaries
+# =============
+#
+# Set the variabels (The executable is in the build tree). Do the
+# basic checks to see if the executable is made or if the defaults
+# file exists (basicchecks.sh is in the source tree).
+prog=fits
+img1=fitstest.fits
+img2=mkprofcat2.fits
+execname=../bin/$prog/ast$prog
+
+
+
+
+
+# Skip?
+# =====
+#
+# If the dependencies of the test don't exist, then skip it. There are two
+# types of dependencies:
+#
+#   - The executable was not made (for example due to a configure option),
+#
+#   - The input data was not made (for example the test that created the
+#     data file failed).
+if [ ! -f $execname ]; then echo "$execname doesn't exist."; exit 77; fi
+if [ ! -f $img1     ]; then echo "$img1 doesn't exist.";     exit 77; fi
+if [ ! -f $img2     ]; then echo "$img2 doesn't exist.";     exit 77; fi
+
+
+
+
+
+# Actual test script
+# ==================
+$execname $img2 --copy="Mock profiles" --output=$img1



reply via email to

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