gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 9ad1dff7: Crop: new option to print single-pix


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 9ad1dff7: Crop: new option to print single-pixel's output to stdout
Date: Sat, 11 Jun 2022 20:04:35 -0400 (EDT)

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

    Crop: new option to print single-pixel's output to stdout
    
    Until now, Crop would always only create FITS images. However, when the
    output only has a single pixel, it is highly likely that the user just
    wanted to read that pixel's value. But doing this from a FITS file is
    annoying (requires creation of a file for every coordinate/pixel they
    want).
    
    With this commit, Crop now has a new option called '--oneelemstdout' (or in
    short '-t'). When the output has a single pixel and this option is called,
    then crop will print the value on the standard output instead of a FITS
    file.
    
    This feature was suggested by Raul Infante-Sainz.
---
 NEWS               |  8 ++++++
 bin/crop/args.h    | 13 +++++++++
 bin/crop/main.h    |  1 +
 bin/crop/onecrop.c | 84 +++++++++++++++++++++++++++++++++++-------------------
 bin/crop/ui.h      |  3 +-
 doc/gnuastro.texi  | 30 +++++++++++++++++--
 6 files changed, 107 insertions(+), 32 deletions(-)

diff --git a/NEWS b/NEWS
index 7ebbe815..5527148c 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,14 @@ See the end of the file for license conditions.
      written with the help of S. Zahra Hosseini Shahisavandi and Sepideh
      Eskandarlou.
 
+  Crop:
+   --oneelemstdout: when a crop has a single pixel and this option is
+     called, the single pixel's value will be printed on the standard
+     output instead of creating a FITS file. This option can be useful in
+     labeled images like detection maps (when you want to see what label a
+     certain coordiante/pixel corresponds to). This option was suggested by
+     Raul Infante-Sainz.
+
   Fits:
    --copykeys: can now take any number of keyword names also. For example
      '--copykeys=KEYNAME1,KEYNAME2,KEYNAME3'. Until now, it was only
diff --git a/bin/crop/args.h b/bin/crop/args.h
index 725b0f46..f8f04f5b 100644
--- a/bin/crop/args.h
+++ b/bin/crop/args.h
@@ -128,6 +128,19 @@ struct argp_option program_options[] =
       GAL_OPTIONS_MANDATORY,
       GAL_OPTIONS_NOT_SET
     },
+    {
+      "oneelemstdout",
+      UI_KEY_ONEELEMSTDOUT,
+      0,
+      0,
+      "Print one element's value on stdout.",
+      GAL_OPTIONS_GROUP_OUTPUT,
+      &p->oneelemstdout,
+      GAL_OPTIONS_NO_ARG_TYPE,
+      GAL_OPTIONS_RANGE_0_OR_1,
+      GAL_OPTIONS_NOT_MANDATORY,
+      GAL_OPTIONS_NOT_SET
+    },
 
 
 
diff --git a/bin/crop/main.h b/bin/crop/main.h
index bb6a0815..c1a2801d 100644
--- a/bin/crop/main.h
+++ b/bin/crop/main.h
@@ -119,6 +119,7 @@ struct cropparams
   void          *blankptrwrite;  /* Null value for writing of output type.*/
   struct inputimgs       *imgs;  /* WCS and size information for inputs.  */
   gal_data_t              *log;  /* Log file contents.                    */
+  int            oneelemstdout;  /* Print one element crops on stdout.    */
 };
 
 #endif
diff --git a/bin/crop/onecrop.c b/bin/crop/onecrop.c
index 4107a562..16c2ee35 100644
--- a/bin/crop/onecrop.c
+++ b/bin/crop/onecrop.c
@@ -646,8 +646,9 @@ onecrop(struct onecropparams *crp)
   struct inputimgs *img=&p->imgs[crp->in_ind];
 
   void *array;
-  int returnvalue=1;
+  char *stdoutstring;
   int status=0, anynul=0;
+  int returnvalue=1, hasoneelem=1;
   fitsfile *ifp=crp->infits, *ofp;
   char basekeyname[FLEN_KEYWORD-5];     /* '-5': avoid gcc 8.1+ warnings! */
   gal_fits_list_key_t *headers=NULL;    /* See above comment for more.    */
@@ -674,9 +675,15 @@ onecrop(struct onecropparams *crp)
   /* Find the overlap and apply it if there is any overlap. */
   if( gal_box_overlap(naxes, fpixel_i, lpixel_i, fpixel_o, lpixel_o, ndim) )
     {
-      /* Make the output FITS image and initialize it with an array of
-         NaN or BLANK values. */
-      if(crp->outfits==NULL)
+      /* See if the output only has a single element or not. */
+      for(i=0;i<ndim;++i)
+        if(fpixel_o[i]!=1 || lpixel_o[i]!=1)
+          {hasoneelem=0; break;}
+
+      /* Make the output FITS image and initialize it with an array of NaN
+         or BLANK values. But only when '--oneelemstdout' isn't called and
+         the output is single-element. */
+      if(crp->outfits==NULL && !( p->oneelemstdout && hasoneelem) )
         onecrop_make_array(crp, fpixel_i, lpixel_i, fpixel_o, lpixel_o);
       ofp=crp->outfits;
 
@@ -701,8 +708,8 @@ onecrop(struct onecropparams *crp)
         onecrop_zero_to_nan(array, cropsize, p->type);
 
 
-      /* If a polygon is given, remove all the pixels within or
-         outside of it.*/
+      /* If a polygon is given, remove all the pixels within or outside of
+         it.*/
       if(p->polygon)
         {
           /* A small sanity check until this part supports 3D. */
@@ -719,31 +726,50 @@ onecrop(struct onecropparams *crp)
         }
 
 
-      /* Write the array into the image. */
-      status=0;
-      if( fits_write_subset(ofp, gal_fits_type_to_datatype(p->type),
-                            fpixel_o, lpixel_o, array, &status) )
-        gal_fits_io_error(status, NULL);
+      /* Write the output (either to a file or standard output if its a
+         single element and the user asked for it). */
+      if(crp->outfits)
+        {
+          /* Write the array into the image. */
+          status=0;
+          if( fits_write_subset(ofp, gal_fits_type_to_datatype(p->type),
+                                fpixel_o, lpixel_o, array, &status) )
+            gal_fits_io_error(status, NULL);
+
+
+          /* Write the selected region of this image as a string to include as
+             a FITS keyword. Then we want to delete the last coma ','.*/
+          j=0;
+          for(i=0;i<ndim;++i)
+            j += sprintf(&region[j], "%ld:%ld,", fpixel_i[i], lpixel_i[i]);
+          region[j-1]='\0';
+
+
+          /* A section has been added to the cropped image from this input
+             image, so save the information of this image. */
+          sprintf(basekeyname, "ICF%zu", crp->numimg);
+          gal_fits_key_write_filename(basekeyname, img->name, &headers, 0,
+                                      p->cp.quiet);
+          sprintf(regionkey, "%sPIX", basekeyname);
+          gal_fits_key_list_add_end(&headers, GAL_TYPE_STRING, regionkey,
+                                    0, region, 0, "Range of pixels used for "
+                                    "this output.", 0, NULL, 0);
+          gal_fits_key_write_in_ptr(&headers, ofp);
+        }
 
 
-      /* Write the selected region of this image as a string to include as
-         a FITS keyword. Then we want to delete the last coma ','.*/
-      j=0;
-      for(i=0;i<ndim;++i)
-        j += sprintf(&region[j], "%ld:%ld,", fpixel_i[i], lpixel_i[i]);
-      region[j-1]='\0';
-
-
-      /* A section has been added to the cropped image from this input
-         image, so save the information of this image. */
-      sprintf(basekeyname, "ICF%zu", crp->numimg);
-      gal_fits_key_write_filename(basekeyname, img->name, &headers, 0,
-                                  p->cp.quiet);
-      sprintf(regionkey, "%sPIX", basekeyname);
-      gal_fits_key_list_add_end(&headers, GAL_TYPE_STRING, regionkey,
-                                0, region, 0, "Range of pixels used for "
-                                "this output.", 0, NULL, 0);
-      gal_fits_key_write_in_ptr(&headers, ofp);
+      /* The output should be printed in standard output. */
+      else
+        {
+          /* Convert the value into a string. If we only have a single
+             output, then print it without anything else (no identifier is
+             necessary!). Otherwise, use the desired output filename as the
+             identifier. */
+          stdoutstring=gal_type_to_string(array, p->type, 0);
+          if(p->numout==1) printf("%s\n", stdoutstring);
+          else             printf("%s %s\n", crp->name, stdoutstring);
+          free(stdoutstring);
+        }
 
 
       /* Free the allocated array. */
diff --git a/bin/crop/ui.h b/bin/crop/ui.h
index 8bba8b8d..c1bcee4a 100644
--- a/bin/crop/ui.h
+++ b/bin/crop/ui.h
@@ -45,7 +45,7 @@ enum program_args_groups
 
 /* Available letters for short options:
 
-   a d e f g i j k m r t u v y
+   a d e f g i j k m r u v y
    A B E G H J L Q R W Y
 */
 enum option_keys_enum
@@ -63,6 +63,7 @@ enum option_keys_enum
   UI_KEY_WIDTHINPIX     = 'X',
   UI_KEY_CENTER         = 'c',
   UI_KEY_COORDCOL       = 'x',
+  UI_KEY_ONEELEMSTDOUT  = 't',
 
   /* Only with long version (start with a value 1000, the rest will be set
      automatically). */
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index eb736c80..743a9496 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -14634,8 +14634,7 @@ The value must either be @option{img} or @option{wcs}, 
see @ref{Crop modes} for
 @node Crop output, Crop known issues, Crop options, Invoking astcrop
 @subsubsection Crop output
 
-The string given to @option{--output} option will be interpreted depending
-on how many crops were requested, see @ref{Crop modes}:
+The string given to @option{--output} option will be interpreted depending on 
how many crops were requested, see @ref{Crop modes}:
 
 @itemize
 @item
@@ -14676,6 +14675,33 @@ A @code{0} if the central few pixels (value to the 
@option{--checkcenter} option
 When the crop was not defined by its center (see @ref{Crop modes}), or 
@option{--checkcenter} was given a value of 0 (see @ref{Invoking astcrop}), the 
center will not be checked and this column will be given a value of @code{-1}.
 @end enumerate
 
+If the output crop(s) have a single element (pixel in an image) and 
@option{--oneelemstdout} has been called, no output file will be produced!
+Instead, the single element's value is printed on the standard output.
+See the description of @option{--oneelemstdout} below for more:
+
+@table @option
+@item -t
+@itemx --oneelemstdout
+When a crop only has a single element (a single pixel), print it to the 
standard output instead of making a file.
+By default (without this option), a single-pixel crop will be saved to a file, 
just like a crop of any other size.
+
+When a single crop is requested (either through @option{--center}, or a 
catalog of one row is given), the single value alone is printed with nothing 
else.
+This makes it easy to immediately write the value into a shell variable for 
example:
+
+@example
+value=$(astcrop img.fits --mode=wcs --center=1.234,5.678 \
+                --width=1 --widthinpix --oneelemstdout \
+                --quiet)
+@end example
+
+If a catalog of coordinates is given (that would produce multiple crops; or 
multiple values in this scenario), the solution for a single value won't work!
+Recall that Crop will do the crops in parallel, therefore each time you run 
it, the order of the rows will be different and not correspond to the order of 
the inputs.
+
+To allow identification of each value (which row of the input catalog it 
corresponds to), Crop will first print the name of the would-be created file 
name, and print the value after it (separated by an empty SPACE character).
+In other words, the file in the first column won't actually be created, but 
the value of the pixel it would have contained (if this option wasn't called) 
is printed after it.
+@end table
+
+
 @node Crop known issues,  , Crop output, Invoking astcrop
 @subsubsection Crop known issues
 



reply via email to

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