gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master e33704e4 2/2: Fits: more generic implementatio


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master e33704e4 2/2: Fits: more generic implementation of --copykeys for names
Date: Tue, 19 Apr 2022 15:03:09 -0400 (EDT)

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

    Fits: more generic implementation of --copykeys for names
    
    Until now (in the previous commit), the newly added feature where
    '--copykeys' could take keyword names had several problems that are
    described below.
    
    With this commit, the following issues have been addressed:
    
     - It had effectively re-written the existing implementation of the
       '--copykeys'. Both in the user-interface ('ui.c') and in the actual
       implementation of the job. This is not good practice in coding, because
       the re-write can introduce new bugs. It is always good to try to
       implement a new feature as an extension of the existing implementation,
       rather than fully re-write it. A full re-write should only be considered
       when adding something will un-necessarily complicate the final version.
    
       For example in 'ui.c' of the previous commit, the old 'case' feature was
       replaced with many nested if-else statements. However, if-else is both
       harder to read, and has lower efficiency at run time. In the new
       implementation, the original 'case' is kept, and the check for
       'isalpha()' is added in the 'default' part (thus not touching the
       original implementation or making it more complex). Also, to parse the
       comma-separated list of names, I used
       'gal_options_parse_csv_strings_raw'. Finally, the debuging statement for
       names was taken inside the "For a check" commented part.
    
       Also, in the previous commit, the 'keywords_copykeys' function just
       called the two new 'keywords_copykeys_name' and
       'keywords_copykeys_range' functions. However, many of the jobs in both
       those functions was repetition. So the repetative parts of the two
       functions was brought into the higher-level 'keywords_copykeys', and
       each one of the range or name functions does only what they should (copy
       the inputs to the outputs).
    
       Another problem that was caused by the full re-write of the previous
       commit was that the input dataset's keywords were re-read into memory
       from scratch! However, the user may have modified the input's keywords
       with other options (hence why we had simply read the list of keywords as
       a long string). So with this commit, the 'keywords_copykeys_name'
       function uses the same 'inkeys' string that was read before, and doesn't
       re-read the keywords from the input file (which may have changed by this
       point).
    
     - In the previous commit, the 'struct fitsparams' element keeping the
       keyword names to copy was called 'keystocopy'! This is very bad in
       regards to code readability: what is the difference between
       'copykeysrnage' and 'keystocopy'? Simply reversing the order of the name
       components will just confuse any reader of the code, and make it hard to
       search for related variables. In this commit, the previous convention is
       followed and a clear name is used, which states the difference between
       this variable and the one based on range: 'copykeysname'.
    
     - Some stylistic issues:
       - Only define variables at the top of the function.
       - The indentation of large blocks was not correct!
       - A space should be placed after commas in function arguments.
       - The 'if' should touch the following parenthesis.
---
 NEWS                |  10 +++
 bin/fits/args.h     |   2 +-
 bin/fits/keywords.c | 227 +++++++++++++++++++++++++---------------------------
 bin/fits/main.h     |   2 +-
 bin/fits/ui.c       | 205 ++++++++++++++++++++++++++---------------------
 doc/gnuastro.texi   |  35 ++++++--
 6 files changed, 260 insertions(+), 221 deletions(-)

diff --git a/NEWS b/NEWS
index a2a3c0b5..93a519c3 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,16 @@ See the end of the file for license conditions.
 
 ** New features
 
+  Fits:
+   --copykeys: can now take any number of keyword names also. For example
+     '--copykeys=KEYNAME1,KEYNAME2,KEYNAME3'. Until now, it was only
+     possible to give this option a range of keyword positions (for example
+     '--copykeys=10:13' to copy the 10th to 13th keywords (inclusive). But
+     now, you can also select non-contiguous set of keywords to copy from
+     one HDU into another HDU (possibly in another file). This was
+     suggested by Juan Antonio Fernández Ontiveros and implemented with the
+     help of Jash Shah.
+
   MakeProfiles:
    - It is now possible to insert a custom image as a new (10th)
      'custom-img' profile. This is useful when you have no-noise FITS
diff --git a/bin/fits/args.h b/bin/fits/args.h
index 24cb3594..d4e81eae 100644
--- a/bin/fits/args.h
+++ b/bin/fits/args.h
@@ -386,7 +386,7 @@ struct argp_option program_options[] =
       UI_KEY_COPYKEYS,
       "INT:INT/STR,STR",
       0,
-      "Range/List of keywords to copy to output HDU.",
+      "Range/Names of keywords to copy to output HDU.",
       UI_GROUP_KEYWORD,
       &p->copykeys,
       GAL_TYPE_STRING,
diff --git a/bin/fits/keywords.c b/bin/fits/keywords.c
index 3a12ded0..6f3bca2d 100644
--- a/bin/fits/keywords.c
+++ b/bin/fits/keywords.c
@@ -372,66 +372,57 @@ keywords_verify(struct fitsparams *p, fitsfile **fptr)
 
 
 
-/* To copy keys to output file when --copykeys are given in STR,STR,STR
-    format. */
+/* To copy keys to output file when '--copykeys' is given in 'STR,STR,STR'
+   format. */
 static void
-keywords_copykeys_str(struct fitsparams *p)
+keywords_copykeys_name(struct fitsparams *p, fitsfile *fptr,
+                       char *inkeys, size_t numinkeys,
+                       int *updatechecksum)
 {
-  fitsfile *infptr, *outfptr;
-  gal_list_str_t *input, *tmp;
-  int status=0, updatechecksum=0, checksumexists=0;
-
-  /* Print Keys to Copy. */
-  if (!p->cp.quiet)
-    {
-        printf("Keys to Copy :\n");
-        gal_list_str_print(p->keystocopy);
-    }
-
-  /* Parse  input file, read the keywords and put them in the output
-      (keysll) list. */
-  input=p->input;
-
-  /* Open the input FITS file. */
-  infptr=gal_fits_hdu_open(input->v, p->cp.hdu, READONLY);
-
-  /* Open the output HDU. */
-  outfptr=gal_fits_hdu_open(p->cp.output, p->outhdu, READWRITE);
-
-  /* See if a 'CHECKSUM' key exists in the HDU or not (to update in case
-     we wrote anything). */
-  checksumexists=gal_fits_key_exists_fptr(outfptr, "CHECKSUM");
+  size_t i, j;
+  int status=0, found;
+  char **strarr=p->copykeysname->array;
 
   /* Copy the requested headers into the output files header. */
-  for(tmp=p->keystocopy; tmp!=NULL; tmp=tmp->next)
+  for(i=0; i<p->copykeysname->size; ++i)
     {
-      char inkey[80];
-      char *keyname = tmp->v;
-
-      if(fits_read_card(infptr,keyname, inkey, &status))
-        gal_fits_io_error(status,NULL);
-
-      if( fits_write_record(outfptr, inkey, &status ) )
-        gal_fits_io_error(status, NULL);
-      else updatechecksum=1;
+      /* Find the requested key from the set of input keywords that were
+         read before. The FITS standard does specify that the keyword
+         should only have upper-case letters, but CFITSIO does accept small
+         case (and write upper-case), so we'll also ignore case when
+         comparing.*/
+      found=0;
+      for(j=0;j<numinkeys-1;++j) /* numkeys-1: it includes 'END'. */
+        {
+          /* First check the first few characters, if they don't match, see
+             if it stars with 'HIERARCH' (which is placed before long
+             keyword names). */
+          if( !strncasecmp(strarr[i], &inkeys[j*80], strlen(strarr[i])) )
+            found=1;
+          else
+            {
+              if( !strncasecmp("HIERARCH", &inkeys[j*80], 8)
+                  && !strncasecmp(strarr[i], &inkeys[j*80+9],
+                                  strlen(strarr[i])) )
+                found=1;
+            }
 
+          /* Write the keyword if it was found. */
+          if(found==1)
+            {
+              if(fits_write_record(fptr, &inkeys[j*80], &status))
+                gal_fits_io_error(status, NULL);
+              else { *updatechecksum=1; break; }
+            }
+          }
+
+      /* If the key wasn't found after a full parsing of the keywords,
+         print an error message. */
+      if(found==0)
+        error(EXIT_FAILURE, 0, "%s: no keyword with name '%s' found",
+              gal_fits_name_save_as_string(p->input->v, p->cp.hdu),
+              strarr[i]);
     }
-
-  /* Close the input FITS file. */
-  status=0;
-  if(fits_close_file(infptr, &status))
-    gal_fits_io_error(status, NULL);
-
-  /* If a checksum existed, and we made changes in the file, we should
-     update the checksum. */
-  if(checksumexists && updatechecksum)
-    if( fits_write_chksum(outfptr, &status) )
-      gal_fits_io_error(status, NULL);
-
-  /* Close the output FITS file. */
-  status=0;
-  if(fits_close_file(outfptr, &status))
-    gal_fits_io_error(status, NULL);
 }
 
 
@@ -441,71 +432,55 @@ keywords_copykeys_str(struct fitsparams *p)
 /* To copy keys to output file when --copykeys are given in INT:INT
     format. */
 static void
-keywords_copykeys_range(struct fitsparams *p,char *inkeys,
-                                            size_t numinkeys)
+keywords_copykeys_range(struct fitsparams *p, fitsfile *fptr,
+                        char *inkeys, size_t numinkeys,
+                        int *updatechecksum)
 {
-  fitsfile *fptr;
   size_t i;
   long initial;
-  int status=0, updatechecksum=0, checksumexists=0;
-  /* Initial sanity check. Since 'numinkeys' includes 'END' (counting from
-          1, as we do here), the first keyword must not be larger OR EQUAL to
-          'numinkeys'. */
-      if(p->copykeysrange[0]>=numinkeys)
-        error(EXIT_FAILURE, 0, "%s (hdu %s): first keyword number give "
-              "to '--copykeys' (%ld) is larger than the number of "
-              "keywords in this header (%zu, including the 'END' "
-              "keyword)", p->input->v, p->cp.hdu, p->copykeysrange[0],
-              numinkeys);
-
-      /* If the user wanted to count from the end (by giving a negative value),
-        then do that. */
-      if(p->copykeysrange[1]<0)
-        {
-          /* Set the last keyword requested. */
-          initial=p->copykeysrange[1];
-          p->copykeysrange[1] += numinkeys;
-
-          /* Sanity check. */
-          if(p->copykeysrange[0]>=p->copykeysrange[1])
-            error(EXIT_FAILURE, 0, "%s (hdu %s): the last keyword given to "
-                  "'--copykeys' (%ld, or %ld after counting from the bottom) "
-                  "is earlier than the first (%ld)", p->input->v, p->cp.hdu,
-                  initial, p->copykeysrange[1], p->copykeysrange[0]);
-        }
-
-      /* Final sanity check (on range limit). */
-      if(p->copykeysrange[1]>=numinkeys)
-        error(EXIT_FAILURE, 0, "%s (hdu %s): second keyword number give to "
-              "'--copykeys' (%ld) is larger than the number of keywords in "
-              "this header (%zu, including the 'END' keyword)", p->input->v,
-              p->cp.hdu, p->copykeysrange[1], numinkeys);
-
-      /* Open the output HDU. */
-      fptr=gal_fits_hdu_open(p->cp.output, p->outhdu, READWRITE);
+  int status=0;
 
-      /* See if a 'CHECKSUM' key exists in the HDU or not (to update in case we
-        wrote anything). */
-      checksumexists=gal_fits_key_exists_fptr(fptr, "CHECKSUM");
+  /* Initial sanity check. Since 'numinkeys' includes 'END' (counting from
+     1, as we do here), the first keyword must not be larger OR EQUAL to
+     'numinkeys'. */
+  if(p->copykeysrange[0]>=numinkeys)
+    error(EXIT_FAILURE, 0, "%s (hdu %s): first keyword number give "
+          "to '--copykeys' (%ld) is larger than the number of "
+          "keywords in this header (%zu, including the 'END' "
+          "keyword)", p->input->v, p->cp.hdu, p->copykeysrange[0],
+          numinkeys);
+
+  /* If the user wanted to count from the end (by giving a negative value),
+     then do that. */
+  if(p->copykeysrange[1]<0)
+    {
+      /* Set the last keyword requested. */
+      initial=p->copykeysrange[1];
+      p->copykeysrange[1] += numinkeys;
+
+      /* Sanity check. */
+      if(p->copykeysrange[0]>=p->copykeysrange[1])
+        error(EXIT_FAILURE, 0, "%s (hdu %s): the last keyword given to "
+              "'--copykeys' (%ld, or %ld after counting from the bottom) "
+              "is earlier than the first (%ld)", p->input->v, p->cp.hdu,
+              initial, p->copykeysrange[1], p->copykeysrange[0]);
+    }
 
-      /* Copy the requested headers into the output. */
-      for(i=p->copykeysrange[0]-1; i<=p->copykeysrange[1]-1; ++i)
-        {
-          if( fits_write_record(fptr, &inkeys[i*80], &status ) )
-            gal_fits_io_error(status, NULL);
-          else updatechecksum=1;
-        }
+  /* Final sanity check (on range limit). */
+  if(p->copykeysrange[1]>=numinkeys)
+    error(EXIT_FAILURE, 0, "%s (hdu %s): second keyword number give to "
+          "'--copykeys' (%ld) is larger than the number of keywords in "
+          "this header (%zu, including the 'END' keyword)", p->input->v,
+          p->cp.hdu, p->copykeysrange[1], numinkeys);
 
-      /* If a checksum existed, and we made changes in the file, we should
-        update the checksum. */
-      if(checksumexists && updatechecksum)
-        if( fits_write_chksum(fptr, &status) )
-          gal_fits_io_error(status, NULL);
 
-      /* Close the output FITS file. */
-      status=0;
-      if(fits_close_file(fptr, &status))
+  /* Copy the requested headers into the output. */
+  for(i=p->copykeysrange[0]-1; i<=p->copykeysrange[1]-1; ++i)
+    {
+      if( fits_write_record(fptr, &inkeys[i*80], &status ) )
         gal_fits_io_error(status, NULL);
+      else *updatechecksum=1;
+    }
 }
 
 
@@ -515,19 +490,33 @@ keywords_copykeys_range(struct fitsparams *p,char *inkeys,
 static void
 keywords_copykeys(struct fitsparams *p, char *inkeys, size_t numinkeys)
 {
-  /* File pointer used for accessing input and output files*/
+  int status=0;
   fitsfile *fptr;
+  int updatechecksum=0, checksumexists=0;
+
+  /* Open the output HDU. */
+  fptr=gal_fits_hdu_open(p->cp.output, p->outhdu, READWRITE);
+
+  /* See if a 'CHECKSUM' key exists in the HDU or not (to update in case we
+     wrote anything). */
+  checksumexists=gal_fits_key_exists_fptr(fptr, "CHECKSUM");
 
   /* Call different functions depending on whether a list or range of
       keywords is given. */
-  if (p->keystocopy)
-    {
-      keywords_copykeys_str(p);
-    }
+  if(p->copykeysname)
+    keywords_copykeys_name(p, fptr, inkeys, numinkeys, &updatechecksum);
   else
-    {
-        keywords_copykeys_range(p,inkeys,numinkeys);
-    }
+    keywords_copykeys_range(p, fptr, inkeys, numinkeys, &updatechecksum);
+
+  /* If a checksum existed, and we made changes in the file, we should
+     update the checksum. */
+  if(checksumexists && updatechecksum)
+    if( fits_write_chksum(fptr, &status) )
+      gal_fits_io_error(status, NULL);
+
+  /* Close the output FITS file. */
+  if(fits_close_file(fptr, &status))
+    gal_fits_io_error(status, NULL);
 }
 
 
@@ -1171,7 +1160,7 @@ keywords(struct fitsparams *p)
 
 
   /* If a list/range of keywords must be copied, get all the keywords as a
-      single string. */
+     single string. */
   if(p->copykeys)
     {
       keywords_open(p, &fptr, READONLY);
diff --git a/bin/fits/main.h b/bin/fits/main.h
index da65cf73..7bfd2af8 100644
--- a/bin/fits/main.h
+++ b/bin/fits/main.h
@@ -95,7 +95,7 @@ struct fitsparams
   int                 distortionid;  /* ID of desired distortion.       */
   int               updatechecksum;  /* If CHECKSUM should be update.   */
   long            copykeysrange[2];  /* Start and end of copy.          */
-  gal_list_str_t       *keystocopy;  /* Keyword strings list, to copy.  */
+  gal_data_t         *copykeysname;  /* Keyword names to copy.          */
   gal_fits_list_key_t  *write_keys;  /* Keys to write in the header.    */
   gal_fits_list_key_t *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 daca2e2c..4a8be610 100644
--- a/bin/fits/ui.c
+++ b/bin/fits/ui.c
@@ -234,106 +234,125 @@ ui_check_copykeys(struct fitsparams *p)
   /* Initialize the values. */
   p->copykeysrange[0]=p->copykeysrange[1]=GAL_BLANK_LONG;
 
-    /* Parse the string: 'forl': "first-or-last". */
-    while(*pt!='\0')
-      {
-        /* If any alphabet is found then, a list of string keywords
-            are considered. */
-        if (isalpha(*pt))
-          {
-            /* Parse the copykeys string and store name of each keyword
-                in keystocopy list. */
-            char *first = strtok(p->copykeys, ",");
-
-            while(first != NULL)
-              {
-                gal_list_str_add(&p->keystocopy, first, 0);
-                first = strtok(NULL,",");
-              }
-            break;
-          }
-        else if (*pt == ':')
-          {
-            forl='l';
-            ++pt;
-          }
-        else if (*pt == '.')
-          {
-              error(EXIT_FAILURE, 0, "the numbers in the argument to "
-                      "'--section' ('-s') have to be integers. You input "
-                      "includes a float number: %s", p->copykeys);
-          }
-        else if (*pt == ' ' || *pt == '\t')
-          {
-              ++pt;
-          }
+  /* Parse the string: 'forl': "first-or-last". */
+  while(*pt!='\0')
+    {
+      switch(*pt)
+        {
+        case ':':
+          forl='l';
+          ++pt;
+          break;
+        case '.':
+          error(EXIT_FAILURE, 0, "the numbers in the argument to "
+                "'--section' ('-s') have to be integers. You input "
+                "includes a float number: %s", p->copykeys);
+          break;
+        case ' ': case '\t':
+          ++pt;
+          break;
+
         /* Numerical characters signify the start of a number, so we don't
-              need to increment the pointer and can just break out. */
-        else if (isdigit(*pt))
-          {
-              /* Read the number: */
-              read=strtol(pt, &tailptr, 0);
-
-              /* Check the progress.
-              printf("\n\n------\n%c: %ld (%s)\n", *pt, read, tailptr);
-              */
-
-              /* Make sure if a number was read at all? */
-              if(tailptr==pt) continue;   /* No number was read!        */
-
-              /* Put it in the correct place. */
-              p->copykeysrange[ forl=='f' ? 0 : 1 ]=read;
-              pt=tailptr;
-          }
-        /* else if (*pt == ',')
+           need to increment the pointer and can just break out. */
+        case '0': case '1': case '2': case '3': case '4': case '5':
+        case '6': case '7': case '8': case '9': case '-':
+          break;
+
+        /* Identifier for next group of ranges. However, For the time
+           being, we just support one group. So we are commenting the break
+           here for it to follow onto default.
+        case ',':
+          ++group;
+          forl='f';
+          ++pt;
+          break;
+          */
+        default:
+
+          /* If a name is given, it will start with an alphabetic
+             character, a hyphen, or an underscore (we already know that
+             the key doesn't start with a digit, since it would break out
+             of the 'switch'). Recall that according to the FITS standard,
+             a keyword name can only contain digits, alphabetic characters,
+             '-', or '_'. See "Section 4.1.2.1. Keyword name" of the FITS
+             4.0 standard.*/
+          if( isalpha(*pt) || *pt=='-' || *pt=='_' ) break;
+
+          /* Print an error if control reaches here because  */
+          error(EXIT_FAILURE, 0, "value to '--copykeys' must either be a "
+                "range of numbers (for example '--copykeys=10:20') or a "
+                "set of names (for example '--copykeys=KEY1,KEY2', for "
+                "any number of names, note that the first keyword name "
+                "should not contain only digits, thus get interpreted "
+                "as a number). However, your given value ('%s') couldn't "
+                "be interpreted as any of the two (the first "
+                "non-acceptable character is '%c'). If this seems to be "
+                "a problem on the programming side, please report the "
+                "issue to us at '%s'", p->copykeys, *pt,
+                PACKAGE_BUGREPORT);
+          break;
+        }
+
+      /* Read the number: */
+      read=strtol(pt, &tailptr, 0);
+
+      /* Check the progress.
+      printf("\n\n------\n%c: %ld (%s)\n", *pt, read, tailptr);
+      */
+
+      /* If the value couldn't be read as a number, and the first element
+         hasn't been read as a number, parse it as a set of comma-separated
+         strings and break out of the parsing overall. */
+      if(tailptr==pt)
         {
-              ++group;
-              forl='f';
-              ++pt;
-         } */
-        else
-          {
-            error(EXIT_FAILURE, 0, "value to '--copykeys' must only "
-                      "contain integer numbers and these special "
-                      "characters between them: ':' when necessary. "
-                      "But it is '%s' (the first non-acceptable character"
-                       " is '%c').\n", p->copykeys, *pt);
-          }
-    }
+          if(p->copykeysrange[0]==GAL_BLANK_LONG)
+            {
+              p->copykeysname=gal_options_parse_csv_strings_raw(pt,
+                                                                NULL, 0);
+              break;
+            }
+          else continue;
+        }
 
+      /* Put it in the correct place. */
+      p->copykeysrange[ forl=='f' ? 0 : 1 ]=read;
+      pt=tailptr;
+    }
 
-    /* Basic sanity checks. */
-    if (!p->keystocopy)
-      {
-        if( p->copykeysrange[1]==GAL_BLANK_LONG )
-          error(EXIT_FAILURE, 0, "no ending keyword number given to "
-                "'--copykeys'. If you want to copy all the keywords after "
-                " a certain one (without worrying about how many there are)"
-                ", you can use '-1'.\n\nFor example if you want to copy "
-                "all the keywords after the 20th, you can use "
-                "'--copykeys=20,-1'. Generally, you can use negative"
-                "numbers for the last keyword number to "
-                "count from the end.");
-        if( p->copykeysrange[0]<=0 )
-          error(EXIT_FAILURE, 0, "the first number given to "
-                "'--copykeys' must be positive");
-        if( p->copykeysrange[1]>=0 &&
-            p->copykeysrange[0]>=p->copykeysrange[1] )
-          error(EXIT_FAILURE, 0, "the first number (%ld) given to "
-                "'--copykeys' must be smaller than the second (%ld)",
-                p->copykeysrange[0], p->copykeysrange[1]);
-      }
-    else
-      {
-          gal_list_str_reverse(&p->keystocopy);
-      }
+  /* Basic sanity checks. */
+  if( p->copykeysname==NULL )
+    {
+      if( p->copykeysrange[1]==GAL_BLANK_LONG )
+        error(EXIT_FAILURE, 0, "no ending keyword number given to "
+              "'--copykeys'. If you want to copy all the keywords after "
+              "a certain one (without worrying about how many there "
+              "are), you can use '-1'.\n\n"
+              "For example if you want to copy all the keywords after "
+              "the 20th, you can use '--copykeys=20,-1'. Generally, "
+              "you can use negative numbers for the last keyword "
+              "number to count from the end.");
+      if( p->copykeysrange[0]<=0 )
+        error(EXIT_FAILURE, 0, "the first number given to '--copykeys' "
+              "must be positive");
+      if( p->copykeysrange[1]>=0
+          && p->copykeysrange[0]>=p->copykeysrange[1] )
+        error(EXIT_FAILURE, 0, "the first number (%ld) given to "
+              "'--copykeys' must be smaller than the second (%ld)",
+              p->copykeysrange[0], p->copykeysrange[1]);
+    }
 
   /* For a check:
-  printf("copykeys: %ld, %ld\n", p->copykeysrange[0],
-              p->copykeysrange[1]);
+  if( p->copykeysname )
+    {
+      size_t i;
+      char **strarr=p->copykeysname->array;
+      printf("copykeys: ");
+      for(i=0;i<p->copykeysname->size;++i)
+        printf("%s ", strarr[i]);
+    }
+  else
+    printf("copykeys: %ld, %ld\n", p->copykeysrange[0], p->copykeysrange[1]);
   exit(0);
-  printf("Keys To Copy:\n");
-  gal_list_str_print(p->keystocopy);
   */
 }
 
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 33143c31..6f8de99b 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -11189,11 +11189,13 @@ In the latter case (when the keyword values exist but 
can't be verified), the Fi
 By default this function will also print a short description of the 
@code{DATASUM} AND @code{CHECKSUM} keywords.
 You can suppress this extra information with @code{--quiet} option.
 
-@item --copykeys=INT:INT/STR,STR
-Copy the input's keyword records, which can be given as a range (inclusive) or 
a list of Keyword names as comma-separated strings to the output HDU (specified 
with the @option{--output} and @option{--outhdu}
-options, for the filename and HDU/extension respectively).
+@item --copykeys=INT:INT/STR,STR[,STR]
+Copy the desired set of the input's keyword records, to the to the output 
(specified with the @option{--output} and @option{--outhdu} for the filename 
and HDU/extension respectively).
+The keywords to copy can be given either as a range (in the format of 
@code{INT:INT}, inclusive) or a list of keyword names as comma-separated 
strings (@code{STR,STR}), the list can have any number of keyword names.
+More details and examples of the two forms are given below:
 
-If a range of Keywords is to be given :
+@table @asis
+@item Range
 The given string to this option must be two integers separated by a colon 
(@key{:}).
 The first integer must be positive (counting of the keyword records starts 
from 1).
 The second integer may be negative (zero is not acceptable) or an integer 
larger than the first.
@@ -11207,13 +11209,32 @@ To see the header keywords of the input with a number 
before them, you can pipe
 $ astfits input.fits -h1 | cat -n
 @end example
 
-If a list of keywords is to be given:
-The given string to this option must be a comma separated list of Keywords.
+@item List of names
+The given string to this option must be a comma separated list of keyword 
names.
+For example, see the command below:
 
 @example
-$ astfits input.fits --copykeys=BITPIX,NAXIS -h0 --output=output.fits 
--outhdu=0
+$ astfits input.fits -h1 --copykeys=KEY1,KEY2 \
+          --output=output.fits --outhdu=1
 @end example
 
+Please consider the notes below when copying keywords with names:
+@itemize
+@item
+If the number of characters in the name is more than 8, CFITSIO will place a 
@code{HIERARCH} before it.
+In this case simply give the name and don't give the @code{HIERARCH} (which is 
a constant and not considered part of the keyword name).
+@item
+If your keyword name is composed only of digits, don't give it as the first 
name given to @option{--copykeys}.
+Otherwise, it will be confused with the range format above.
+You can safely give an only-digit keyword name as the second, or third 
requested keywords.
+@item
+If the keyword is repeated more than once in the header, currently only the 
first instance will be copied.
+In other words, even if you call @option{--copykeys} multiple times with the 
same keyword name, its first instance will be copied.
+If you need to copy multiple instances of the same keyword, please get in 
touch with us at @code{bug-gnuastro@@gnu.org}.
+@end itemize
+
+@end table
+
 @item --outhdu
 The HDU/extension to write the output keywords of @option{--copykeys}.
 



reply via email to

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