gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master ffc7608: Fits: four new options to find image/


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master ffc7608: Fits: four new options to find image/table HDUs
Date: Sat, 1 May 2021 15:38:31 -0400 (EDT)

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

    Fits: four new options to find image/table HDUs
    
    Until now, when a user wanted to see if at least on table/image HDU exists
    in a FITS file, they would have to look at the full list of HDUs. For a
    human eye that is fine, but for a script, this was annoying and slow. In
    particular, as part of current effort to add shell auto-complete features
    in Gnuastro. The same goes for scenarios when you want the list of image or
    table HDUs.
    
    With this commit, four new options have been added to the Fits program to
    greatly simplify these jobs: '--hastablehdu', '--hasimagehdu',
    'listtablehdu', '--listimagehdu'. The first two will only parse enough HDUs
    to see if atleast one exists and the other two will print each
    corresponding HDU name or number in a separate line.
---
 NEWS              |   5 ++-
 bin/fits/args.h   |  53 +++++++++++++++++++++++
 bin/fits/fits.c   | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 bin/fits/main.h   |   4 ++
 bin/fits/ui.c     |  27 +++++++-----
 bin/fits/ui.h     |   4 ++
 doc/gnuastro.texi |  22 ++++++++++
 7 files changed, 227 insertions(+), 14 deletions(-)

diff --git a/NEWS b/NEWS
index 3b56f80..7ee4179 100644
--- a/NEWS
+++ b/NEWS
@@ -82,7 +82,10 @@ See the end of the file for license conditions.
      you had three input FITS files with input in the same HDU.
 
   Fits:
-
+   --hastablehdu: print 1 if at least one table HDU exists in file.
+   --hasimagehdu: print 1 if at least one image HDU exists in file.
+   --listtablehdus: print table HDU names (or numbers when no name exists).
+   --listimagehdus: print image HDU names (or numbers when no name exists).
    --wcscoordsys: convert the WCS coordinate system of the input into any
      recognized coordinate system. It currently supports: equatorial
      (J2000, B1950), ecliptic (J2000, B1950), Galactic and
diff --git a/bin/fits/args.h b/bin/fits/args.h
index ffe56a9..1a2777f 100644
--- a/bin/fits/args.h
+++ b/bin/fits/args.h
@@ -88,6 +88,59 @@ struct argp_option program_options[] =
       GAL_OPTIONS_NOT_MANDATORY,
       GAL_OPTIONS_NOT_SET
     },
+    {
+      "hastablehdu",
+      UI_KEY_HASTABLEHDU,
+      0,
+      0,
+      "File has at least one table HDU.",
+      UI_GROUP_EXTENSION_INFORMATION,
+      &p->hastablehdu,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+    {
+      "hasimagehdu",
+      UI_KEY_HASIMAGEHDU,
+      0,
+      0,
+      "File has at least one image HDU.",
+      UI_GROUP_EXTENSION_INFORMATION,
+      &p->hasimagehdu,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+    {
+      "listtablehdus",
+      UI_KEY_LISTTABLEHDUS,
+      0,
+      0,
+      "List all table HDUs within the file.",
+      UI_GROUP_EXTENSION_INFORMATION,
+      &p->listtablehdus,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+    {
+      "listimagehdus",
+      UI_KEY_LISTIMAGEHDUS,
+      0,
+      0,
+      "List all image HDUs within the file.",
+      UI_GROUP_EXTENSION_INFORMATION,
+      &p->listimagehdus,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
+
 
 
 
diff --git a/bin/fits/fits.c b/bin/fits/fits.c
index 718d50c..b3de42a 100644
--- a/bin/fits/fits.c
+++ b/bin/fits/fits.c
@@ -495,6 +495,122 @@ fits_skycoverage(struct fitsparams *p)
 
 
 
+static char *
+fits_list_certain_hdu_string(fitsfile *fptr, int hduindex)
+{
+  size_t i;
+  int status=0;
+  char *out, extname[80];
+
+  /* See if an 'EXTNAME' keyword exists for this HDU. */
+  fits_read_keyword(fptr, "EXTNAME", extname, NULL, &status);
+
+  /* If EXTNAME doesn't exist, write the HDU index (counting from zero),
+     but if it does, remove the ending single quotes and possible extra
+     space characters (the staring single quote will be removed when
+     copying the name into 'out'). */
+  if(status) sprintf(extname, "%d", hduindex);
+  else
+    {
+      for(i=strlen(extname)-1; i>0; --i)
+        if(extname[i]!='\'' && extname[i]!=' ')
+          { extname[i+1]='\0'; break; }
+    }
+
+  /* Put the value into the allocated 'out' string. */
+  gal_checkset_allocate_copy(status ? extname : extname+1, &out);
+  return out;
+}
+
+
+
+
+static void
+fits_certain_hdu(struct fitsparams *p, int list1has0,
+                 int table1image0)
+{
+  fitsfile *fptr;
+  gal_list_str_t *names=NULL;
+  int has=0, naxis, hducounter=1, hdutype, status=0;
+
+  /* Open the FITS file. */
+  fits_open_file(&fptr, p->input->v, READONLY, &status);
+  gal_fits_io_error(status, NULL);
+
+  /* Start by moving to the first HDU (counting from 1) and then parsing
+     through them. */
+  fits_movabs_hdu(fptr, hducounter, &hdutype, &status);
+  while(status==0)
+    {
+      /* Check the HDU type. */
+      switch(hdutype)
+        {
+
+        /* Tables are easy. */
+        case BINARY_TBL:
+        case ASCII_TBL:
+          if(table1image0)
+            {
+              if(list1has0)
+                gal_list_str_add(&names,
+                                 fits_list_certain_hdu_string(fptr,
+                                                              hducounter-1),
+                                 0);
+              else has=1;
+            }
+          break;
+
+        /* For images, we need to check there is actually any data. */
+        case IMAGE_HDU:
+          if(table1image0==0)
+            {
+              fits_get_img_dim(fptr, &naxis, &status);
+              gal_fits_io_error(status, NULL);
+              if(naxis>0)
+                {
+                  if(list1has0)
+                    gal_list_str_add(&names,
+                                     fits_list_certain_hdu_string(fptr,
+                                                                  
hducounter-1),
+                                     0);
+                  else has=1;
+                }
+            }
+          break;
+
+        /* Just to avoid bad bugs. */
+        default:
+          error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s "
+                "to fix the problem. The value %d is not recognized "
+                "for 'hdutype'", __func__, PACKAGE_BUGREPORT, hdutype);
+        }
+
+      /* Move to the next HDU. */
+      fits_movabs_hdu(fptr, ++hducounter, &hdutype, &status);
+
+      /* If we are in "has" mode and the first HDU has already been found,
+         then there is no need to continue parsing the HDUs, so set
+         'status' to 1 to stop the 'while' above. */
+      if( list1has0==0 && has==1 ) status=1;
+    }
+
+  /* Close the file. */
+  status=0;
+  fits_close_file(fptr, &status);
+
+  /* Print the result. */
+  if( list1has0 )
+    {
+      gal_list_str_print(names);
+      gal_list_str_free(names, 1);
+    }
+  else printf("%d\n", has);
+}
+
+
+
+
+
 static void
 fits_hdu_remove(struct fitsparams *p, int *r)
 {
@@ -623,9 +739,13 @@ fits(struct fitsparams *p)
 
       /* Options that must be called alone. */
       if(p->numhdus) fits_hdu_number(p);
-      else if(p->datasum) fits_datasum(p);
-      else if(p->pixelscale) fits_pixelscale(p);
-      else if(p->skycoverage) fits_skycoverage(p);
+      else if(p->datasum)       fits_datasum(p);
+      else if(p->pixelscale)    fits_pixelscale(p);
+      else if(p->skycoverage)   fits_skycoverage(p);
+      else if(p->hasimagehdu)   fits_certain_hdu(p, 0, 0);
+      else if(p->hastablehdu)   fits_certain_hdu(p, 0, 1);
+      else if(p->listimagehdus) fits_certain_hdu(p, 1, 0);
+      else if(p->listtablehdus) fits_certain_hdu(p, 1, 1);
 
       /* Options that can be called together. */
       else
diff --git a/bin/fits/main.h b/bin/fits/main.h
index c0254c2..87c7ec6 100644
--- a/bin/fits/main.h
+++ b/bin/fits/main.h
@@ -64,6 +64,10 @@ struct fitsparams
   uint8_t           datasum;   /* Calculate and print HDU's datasum.    */
   uint8_t        pixelscale;   /* Calculate and print HDU's pixelscale. */
   uint8_t       skycoverage;   /* Calculate and image coverage in WCS.  */
+  uint8_t       hastablehdu;   /* File has atleast one table HDU.       */
+  uint8_t       hasimagehdu;   /* File has atleast one image HDU.       */
+  uint8_t     listtablehdus;   /* List all table HDUs within the file.  */
+  uint8_t     listimagehdus;   /* List all image HDUs within the file.  */
   uint8_t     primaryimghdu;   /* Copy/cut HDU into primary HDU.        */
   uint8_t      printallkeys;   /* Print all the header keywords.        */
   uint8_t              date;   /* Set DATE to current time.             */
diff --git a/bin/fits/ui.c b/bin/fits/ui.c
index 536ecd5..d63a0dd 100644
--- a/bin/fits/ui.c
+++ b/bin/fits/ui.c
@@ -367,7 +367,8 @@ ui_read_check_only_options(struct fitsparams *p)
 
   /* Same for the extension-related options */
   if( p->remove || p->copy || p->cut || p->numhdus || p->datasum
-      || p->pixelscale || p->skycoverage )
+      || p->pixelscale || p->skycoverage || p->hastablehdu
+      || p->hasimagehdu || p->listtablehdus || p->listimagehdus )
     {
       /* A small sanity check. */
       if(p->mode!=FITS_MODE_INVALID)
@@ -375,26 +376,32 @@ ui_read_check_only_options(struct fitsparams *p)
               "cannot be called together");
 
       /* Some HDU options cannot be called with other options. */
-      stdoutcheck = p->numhdus + p->datasum + p->pixelscale + p->skycoverage;
+      stdoutcheck = ( p->numhdus + p->datasum + p->pixelscale
+                      + p->skycoverage + p->hastablehdu + p->hasimagehdu
+                      + p->listtablehdus + p->listimagehdus );
 
       /* Make sure if an output file is needed. */
       if(stdoutcheck)
         {
-          /* Make sure the other HDU-related options aren't called. */
+          /* Make sure HDU reading and editing options aren't called
+             together. */
           if(p->remove || p->copy || p->cut)
-            error(EXIT_FAILURE, 0, "'--numhdus', '--datasum', '--pixelscale' "
-                  "or '--skycoverage' options cannot be called with any of "
-                  "the '--remove', '--copy' or '--cut' options");
+            error(EXIT_FAILURE, 0, "HDU reading options (like "
+                  "'--numhdus', '--datasum' and etc) cannot be called "
+                  "with any of the HDU modification options like "
+                  "'--remove', '--copy' or '--cut' options");
 
           /* Make sure these options are called alone. */
           if(stdoutcheck>1)
-            error(EXIT_FAILURE, 0, "'--numhdus', '--datasum', '--pixelscale' "
-                  "or '--skycoverage' options cannot be called together, "
-                  "only one at a time");
+            error(EXIT_FAILURE, 0, "HDU info options, like '--numhdus', "
+                  "'--datasum', '--pixelscale' or '--skycoverage', cannot "
+                  "be called together, only one at a time");
 
           /* Make sure the HDU is given if any of the options except
              '--numhdus' are called. */
-          if( stdoutcheck-p->numhdus && p->cp.hdu==NULL )
+          if( ( p->numhdus || p->hastablehdu || p->hasimagehdu
+                || p->listtablehdus || p->listimagehdus)
+              && p->cp.hdu==NULL )
             error(EXIT_FAILURE, 0, "a HDU (extension) is necessary for the "
                   "'--datasum', '--pixelscale' or '--skycoverage' options. "
                   "Please use the '--hdu' (or '-h') option to select one");
diff --git a/bin/fits/ui.h b/bin/fits/ui.h
index 61f70af..cb400c5 100644
--- a/bin/fits/ui.h
+++ b/bin/fits/ui.h
@@ -75,6 +75,10 @@ enum option_keys_enum
   UI_KEY_DATASUM,
   UI_KEY_PIXELSCALE,
   UI_KEY_SKYCOVERAGE,
+  UI_KEY_HASTABLEHDU,
+  UI_KEY_HASIMAGEHDU,
+  UI_KEY_LISTTABLEHDUS,
+  UI_KEY_LISTIMAGEHDUS,
   UI_KEY_OUTHDU,
   UI_KEY_COPYKEYS,
   UI_KEY_WCSCOORDSYS,
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index b23fd9a..c81e811 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -9052,6 +9052,28 @@ It is thus useful in scripts, for example when you need 
to do check the number o
 For a complete list of basic meta-data on the extensions in a FITS file, don't 
use any of the options in this section or in @ref{Keyword inspection and 
manipulation}.
 For more, see @ref{Invoking astfits}.
 
+@item --hastablehdu
+Print @code{1} (on standard output) if at least one table HDU (ASCII or 
binary) exists in the FITS file.
+Otherwise (when no table HDU exists in the file), print @code{0}.
+
+@item --listtablehdus
+Print the names or numbers (when a name doesn't exist, counting from zero) of 
HDUs that contain a table (ASCII or Binary) on standard output, one per line.
+Otherwise (when no table HDU exists in the file) nothing will be printed.
+
+@item --hasimagehdu
+Print @code{1} (on standard output) if at least one image HDU exists in the 
FITS file.
+Otherwise (when no image HDU exists in the file), print @code{0}.
+
+In the FITS standard, any array with any dimensions is called an ``image'', 
therefore this option includes 1, 3 and 4 dimensional arrays too.
+However, an image HDU with zero dimensions (which is usually the first 
extension and only contains metadata) is not counted here.
+
+@item --listimagehdus
+Print the names or numbers (when a name doesn't exist, counting from zero) of 
HDUs that contain an image on standard output, one per line.
+Otherwise (when no image HDU exists in the file) nothing will be printed.
+
+In the FITS standard, any array with any dimensions is called an ``image'', 
therefore this option includes 1, 3 and 4 dimensional arrays too.
+However, an image HDU with zero dimensions (which is usually the first 
extension and only contains metadata) is not counted here.
+
 @item --pixelscale
 Print the HDU's pixel-scale (change in world coordinate for one pixel along 
each dimension) and pixel area or voxel volume.
 Without the @option{--quiet} option, the output of @option{--pixelscale} has 
multiple lines and explanations, thus being more human-friendly.



reply via email to

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