gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master b57d408: Copying of a range of keywords from o


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master b57d408: Copying of a range of keywords from one HDU to another with Fits
Date: Tue, 1 Jan 2019 21:12:42 -0500 (EST)

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

    Copying of a range of keywords from one HDU to another with Fits
    
    With this commit, the Fits program can copy a range of keyword records from
    one HDU to another (possibly in another file).
    
    To do this, we also had to define a blank macro for the `long' and
    `unsigned long' types. Finally, since this involved a change in the library
    (a start of many to come in future commits), the library Soname was
    incremented to 7 (from 6).
---
 NEWS                 |   7 ++++
 bin/crop/onecrop.c   |   2 +-
 bin/fits/args.h      |  35 +++++++++++++++++-
 bin/fits/keywords.c  |  88 ++++++++++++++++++++++++++++++++++++++++++--
 bin/fits/main.h      |   3 ++
 bin/fits/ui.c        | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 bin/fits/ui.h        |   2 +
 configure.ac         |   2 +-
 doc/gnuastro.texi    |  36 ++++++++++++++++++
 lib/gnuastro/blank.h |   8 ++++
 10 files changed, 277 insertions(+), 7 deletions(-)

diff --git a/NEWS b/NEWS
index d995c91..6ec5a75 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,13 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
      `--write=datasum' (only for `DATASUM').
    --verify: confirm if the `DATASUM' and `CHECKSUM' keyword values agree
      with the specified HDU's content and/or data.
+   --copykeys: Copy several keyword records (in a given range) from one
+     FITS HDU/extension into another (possibly in another file).
+   --outhdu: The name/number of the output HDU (for `--copykeys').
+
+  Library:
+    GAL_BLANK_LONG: new macro for the `long' type blank value.
+    GAL_BLANK_ULONG: new macro for the `unsigned long' type blank value.
 
 ** Removed features
 
diff --git a/bin/crop/onecrop.c b/bin/crop/onecrop.c
index 7dcefc7..c605677 100644
--- a/bin/crop/onecrop.c
+++ b/bin/crop/onecrop.c
@@ -98,7 +98,7 @@ onecrop_parse_section(struct cropparams *p, size_t *dsize,
     }
 
 
-  /* Parse the string. */
+  /* Parse the string: `forl': "first-or-last". */
   while(*pt!='\0')
     {
       add=0;
diff --git a/bin/fits/args.h b/bin/fits/args.h
index b2ecfe0..81a7570 100644
--- a/bin/fits/args.h
+++ b/bin/fits/args.h
@@ -31,7 +31,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 /* Array of acceptable options. */
 struct argp_option program_options[] =
   {
-
+    /* Input options */
     {
       0, 0, 0, 0,
       "HDUs (extensions):",
@@ -227,9 +227,42 @@ struct argp_option program_options[] =
       GAL_OPTIONS_NOT_MANDATORY,
       GAL_OPTIONS_NOT_SET
     },
+    {
+      "copykeys",
+      UI_KEY_COPYKEYS,
+      "STR",
+      0,
+      "Range of keywords to copy to output HDU.",
+      UI_GROUP_KEYWORD,
+      &p->copykeys,
+      GAL_TYPE_STRING,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+
+
+
+
+
+    /* Output options. */
+    {
+      "outhdu",
+      UI_KEY_OUTHDU,
+      "STR",
+      0,
+      "HDU/extension in output for --copykeys.",
+      GAL_OPTIONS_GROUP_OUTPUT,
+      &p->outhdu,
+      GAL_TYPE_STRING,
+      GAL_OPTIONS_RANGE_ANY,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
 
 
 
+    /* Operating mode options. */
     {
       "quitonerror",
       UI_KEY_QUITONERROR,
diff --git a/bin/fits/keywords.c b/bin/fits/keywords.c
index fbda9c4..98682ee 100644
--- a/bin/fits/keywords.c
+++ b/bin/fits/keywords.c
@@ -324,9 +324,9 @@ keywords_verify(struct fitsparams *p, fitsfile **fptr)
 
   /* Print the verification result. */
   printf("DATASUM:  %s\n",
-         dataok==1 ? "Verified" : ( dataok==0 ? "NOT-PRESENT" : "INCORRECT") );
+         dataok==1 ? "Verified" : (dataok==0 ? "NOT-PRESENT" : "INCORRECT"));
   printf("CHECKSUM: %s\n",
-         hduok==1  ? "Verified" : ( hduok==0  ? "NOT-PRESENT" : "INCORRECT") );
+         hduok==1  ? "Verified" : (hduok==0  ? "NOT-PRESENT" : "INCORRECT"));
 
   /* Return failure if any of the keywords are not verified. */
   return (dataok==-1 || hduok==-1) ? EXIT_FAILURE : EXIT_SUCCESS;
@@ -337,6 +337,68 @@ keywords_verify(struct fitsparams *p, fitsfile **fptr)
 
 
 
+static void
+keywords_copykeys(struct fitsparams *p, char *inkeys, size_t numinkeys)
+{
+  size_t i;
+  int status=0;
+  long initial;
+  fitsfile *fptr;
+
+  /* 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 (%ld, including the `END' keyword)", p->filename, 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->filename, 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 (%ld, including the `END' keyword)", p->filename, p->cp.hdu,
+          p->copykeysrange[1], numinkeys);
+
+
+  /* Open the output HDU. */
+  fptr=gal_fits_hdu_open(p->cp.output, p->outhdu, READWRITE);
+
+
+  /* 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);
+
+  /* Close the output FITS file. */
+  status=0;
+  if(fits_close_file(fptr, &status))
+    gal_fits_io_error(status, NULL);
+}
+
+
+
+
+
+
+
 
 
 
@@ -365,10 +427,11 @@ keywords_verify(struct fitsparams *p, fitsfile **fptr)
 int
 keywords(struct fitsparams *p)
 {
-  int status=0;
+  char *inkeys=NULL;
   int r=EXIT_SUCCESS;
   fitsfile *fptr=NULL;
   gal_list_str_t *tstll;
+  int status=0, numinkeys;
 
 
   /* Delete the requested keywords. */
@@ -479,11 +542,30 @@ keywords(struct fitsparams *p)
     }
 
 
+  /* If a range of keywords must be copied, get all the keywords as a
+     single string. */
+  if(p->copykeys)
+    {
+      keywords_open(p, &fptr, READONLY);
+      if( fits_convert_hdr2str(fptr, 0, NULL, 0, &inkeys, &numinkeys,
+                               &status) )
+        gal_fits_io_error(status, NULL);
+      status=0;
+    }
+
+
   /* Close the FITS file */
   if(fits_close_file(fptr, &status))
     gal_fits_io_error(status, NULL);
 
 
+  /* Write desired keywords into output. */
+  if(p->copykeys)
+    {
+      keywords_copykeys(p, inkeys, numinkeys);
+      free(inkeys);
+    }
+
   /* Return. */
   return r;
 }
diff --git a/bin/fits/main.h b/bin/fits/main.h
index 78f0054..299ff71 100644
--- a/bin/fits/main.h
+++ b/bin/fits/main.h
@@ -56,6 +56,7 @@ struct fitsparams
   struct gal_options_common_params cp;  /* Common parameters.           */
   int  hdu_in_commandline;     /* HDU wasn't given in config. file.     */
   char          *filename;     /* Name of input file.                   */
+  char            *outhdu;     /* HDU of output (only when necessary).  */
   gal_list_str_t  *remove;     /* Remove extensions from a file.        */
   gal_list_str_t    *copy;     /* Copy extensions to output.            */
   gal_list_str_t     *cut;     /* Copy ext. to output and remove.       */
@@ -70,10 +71,12 @@ struct fitsparams
   gal_list_str_t *history;     /* HISTORY value.                        */
   gal_list_str_t *comment;     /* COMMENT value.                        */
   uint8_t         *verify;     /* Verify the CHECKSUM and DATASUM keys. */
+  char          *copykeys;     /* Range of keywords to copy in output.  */
   uint8_t     quitonerror;     /* Quit if an error occurs.              */
 
   /* Internal: */
   int                         mode;  /* Operating on HDUs or keywords.  */
+  long            copykeysrange[2];  /* Start and end of 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 1674865..25da309 100644
--- a/bin/fits/ui.c
+++ b/bin/fits/ui.c
@@ -217,6 +217,100 @@ parse_opt(int key, char *arg, struct argp_state *state)
 /**************************************************************/
 /***************       Sanity Check         *******************/
 /**************************************************************/
+static void
+ui_check_copykeys(struct fitsparams *p)
+{
+  long read;
+  char *tailptr;
+  size_t group=0;
+  char forl='f', *pt=p->copykeys;
+
+  /* Initialize the values. */
+  p->copykeysrange[0]=p->copykeysrange[1]=GAL_BLANK_LONG;
+
+  /* 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. */
+        case '0': case '1': case '2': case '3': case '4': case '5':
+        case '6': case '7': case '8': case '9': case '-':
+          break;
+
+        /* An un-recognized character should crash the program. */
+        case ',':
+          ++group;
+          forl='f';
+          ++pt;
+
+          /* For the time being, we just support one group. So we are
+             commenting the break here for it to follow onto default.
+          break;
+          */
+        default:
+          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);
+          break;
+        }
+
+      /* 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;
+    }
+
+  /* Basic sanity checks. */
+  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]);
+  exit(0);
+  */
+}
+
+
+
+
+
 /* Read and check ONLY the options. When arguments are involved, do the
    check in `ui_check_options_and_arguments'. */
 static void
@@ -225,7 +319,8 @@ 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->update || p->write || p->verify || p->printallkeys )
+      || p->rename || p->update || p->write || p->verify || p->printallkeys
+      || p->copykeys )
     {
       /* Set the mode. */
       p->mode=FITS_MODE_KEY;
@@ -235,6 +330,10 @@ ui_read_check_only_options(struct fitsparams *p)
         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 Copy keys has been given, read it and make sure its setup. */
+      if(p->copykeys)
+        ui_check_copykeys(p);
     }
 
   /* Same for the extension-related options */
diff --git a/bin/fits/ui.h b/bin/fits/ui.h
index 3df455a..f96dce6 100644
--- a/bin/fits/ui.h
+++ b/bin/fits/ui.h
@@ -69,6 +69,8 @@ enum option_keys_enum
   /* Only with long version (start with a value 1000, the rest will be set
      automatically). */
   UI_KEY_TITLE        = 1000,
+  UI_KEY_OUTHDU,
+  UI_KEY_COPYKEYS,
 };
 
 
diff --git a/configure.ac b/configure.ac
index 6313a4d..068070f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,7 +50,7 @@ AC_CONFIG_MACRO_DIRS([bootstrapped/m4])
 
 # Library version, see the GNU Libtool manual ("Library interface versions"
 # section for the exact definition of each) for
-GAL_CURRENT=6
+GAL_CURRENT=7
 GAL_REVISION=0
 GAL_AGE=0
 GAL_LT_VERSION="${GAL_CURRENT}:${GAL_REVISION}:${GAL_AGE}"
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 53e2900..9f14ed4 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -10146,6 +10146,8 @@ effect then the update operations.
 @option{--printallkeys}
 @item
 @option{--verify}
address@hidden
address@hidden
 @end enumerate
 @noindent
 All possible syntax errors will be reported before the keywords are
@@ -10405,6 +10407,30 @@ By default this function will also print a short 
description of the
 @code{DATASUM} AND @code{CHECKSUM} keywords. You can supress this extra
 information with @code{--quiet} option.
 
address@hidden --copykeys=INT:INT
+Copy the input's keyword records in the given range (inclusive) to the
+output HDU (specified with the @option{--output} and @option{--outhdu}
+options, for the filename and HDU/extension respectively).
+
+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.
+
+A negative second integer means counting from the end. So @code{-1} is the
+last copy-able keyword (not including the @code{END} keyword).
+
+To see the header keywords of the input with a number before them, you can
+pipe the output of the FITS program (when it prints all the keywords in an
+extension) into the @command{cat} program like below:
+
address@hidden
+$ astfits input.fits -h1 | cat -n
address@hidden example
+
address@hidden --outhdu
+The HDU/extension to write the output keywords of @option{--copykeys}.
+
 @item -Q
 @itemx --quitonerror
 Quit if any of the operations above are not successful. By default if
@@ -23570,6 +23596,16 @@ Blank value for an unsigned, 64-bit integer.
 Blank value for a signed, 64-bit integer.
 @end deffn
 
address@hidden {Global integer}  GAL_BLANK_LONG
+Blank value for @code{long} type (@code{int32_t} or @code{int64_t} in
+32-bit or 64-bit systems).
address@hidden deffn
+
address@hidden {Global integer}  GAL_BLANK_ULONG
+Blank value for @code{unsigned long} type (@code{uint32_t} or
address@hidden in 32-bit or 64-bit systems).
address@hidden deffn
+
 @deffn {Global integer}  GAL_BLANK_SIZE_T
 Blank value for @code{size_t} type (@code{uint32_t} or @code{uint64_t} in
 32-bit or 64-bit systems).
diff --git a/lib/gnuastro/blank.h b/lib/gnuastro/blank.h
index 7e36214..ba92425 100644
--- a/lib/gnuastro/blank.h
+++ b/lib/gnuastro/blank.h
@@ -81,6 +81,14 @@ __BEGIN_C_DECLS  /* From C++ preparations */
 #define GAL_BLANK_SIZE_T     GAL_BLANK_UINT64
 #endif
 
+#if GAL_CONFIG_SIZEOF_LONG == 4
+#define GAL_BLANK_LONG  GAL_BLANK_INT32
+#define GAL_BLANK_ULONG GAL_BLANK_UINT32
+#elif GAL_CONFIG_SIZEOF_LONG == 8
+#define GAL_BLANK_LONG  GAL_BLANK_INT64
+#define GAL_BLANK_ULONG GAL_BLANK_UINT64
+#endif
+
 
 /* Functions. */
 void



reply via email to

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