gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 0dd7c438: Make (ast-text-contains): new func.


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 0dd7c438: Make (ast-text-contains): new func. to find words containing substring
Date: Thu, 1 Sep 2022 19:22:29 -0400 (EDT)

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

    Make (ast-text-contains): new func. to find words containing substring
    
    Until now, it was very hard in Make to select all the words in a list that
    contain a certain string! The '$(filter ...)' function is only good if your
    desired string is at the start or end of the string, it can't be anywhere!
    In other words, Make's '$(filter ...)' function only takes one '%'! So it
    was hard to find words that may contain a certain string at any place
    within the word.
    
    With this commit, a Gnuastro Make extension function called
    '$(ast-text-contains ...)' function has been added for this purpose and
    simplify scenarios like above.
    
    In the process, I also noticed that the two currently existing functions
    weren't following the Make function convention of putting the list at the
    end! In the two FITS-related functions, the list of files was placed at the
    start, making the main parameter (the keyword/value) go to the end and
    harder to see when reading the code. So with this commit, this problem has
    also been fixed and they now take the keyword/value as the first
    argument(s), the HDU as the second-last argument and the list of FITS files
    as the last argument.
---
 NEWS               |  16 ++++++--
 doc/gnuastro.texi  |  30 ++++++++++++---
 lib/gnuastro/txt.h |   3 ++
 lib/makeplugin.c   | 111 +++++++++++++++++++++++++++++++++++++++++++----------
 lib/txt.c          |  24 ++++++++++++
 5 files changed, 155 insertions(+), 29 deletions(-)

diff --git a/NEWS b/NEWS
index ef81f548..9729d36b 100644
--- a/NEWS
+++ b/NEWS
@@ -99,12 +99,19 @@ See the end of the file for license conditions.
     analysis becomes even more easier and faster. In the following, you can
     see the first set of such functions (they all begin with 'astgmk' for
     "Astronomical GNU Make"):
-    - astgmk-fits-with-keyvalue: Takes a list of files, a HDU, a keyword
-      name and a list of keyword values. It will return only those FITS
-      files that have the requested value(s) in the requested keyword of
-      the requested HDU.
+    - ast-text-contains: Will only return those space-separated words
+      within a larger list that contain a certain string. The to-contain
+      string can be placed anywhere within the words of the larger list.
+    - ast-fits-with-keyvalue: Takes a keyword name, a list of keyword
+      values, a HDU and a list of FITS files. It will return only those
+      FITS files that have the requested value(s) in the requested keyword
+      of the requested HDU.
+    - ast-fits-unique-keyvalues: Takes a keyword name, a HDU and a list of
+      FITS files. It will return all the unique values given to that
+      keyword within the FITS files.
 
   Library functions:
+
   - gal_box_border_rotate_around_center: width of box after rotation.
   - gal_color_id_to_name: return the name of a color from its ID.
   - gal_color_in_rgb: return the fraction of red-green-blue in a color.
@@ -119,6 +126,7 @@ See the end of the file for license conditions.
   - gal_list_str_extract: Extract space-separated tokens to a list.
   - gal_python_type_from_numpy: Convert Numpy's type id. to Gnuastro's.
   - gal_python_type_to_numpy: Convert Gnuastro's type id. to Numpy's.
+  - gal_txt_contains_string: Check a certain string within in a larger one.
   - gal_units_counts_to_sb: SB from counts, zeropoint and area.
   - gal_units_mag_to_sb: surface brightness (SB) from magnitude and area.
   - gal_units_sb_to_counts: counts from SB, zeropoint and area.
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index e37b5d63..25e5ede1 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -27974,7 +27974,21 @@ For more, see the 
@url{https://www.gnu.org/software/make/manual/html_node/Flavor
 @end cartouche
 
 @table @code
-@item $(ast-fits-with-keyvalue FITS_FILES, HDU, KEYNAME, KEYVALUES)
+@item $(ast-text-contains PATTERN, TEXT)
+Returns all whitespace-separated words in @code{TEXT} that contain of the 
@code{PATTERN}, removing any words that @emph{do not} match.
+For example, the following minimal Makefile will only print the @code{bAaz} 
word of the list.
+
+@example
+list = fooo baar bAaz uggh
+all:
+     echo $(ast-text-contains Aa, $(list))
+@end example
+
+This can be thought of as Make's own @code{filter} function, but if it would 
accept two patterns in a format like this @code{$(filter %Aa%,$(list))} (for 
the example above).
+In fact, the first sentence describing this function is taken from the Make 
manual's first sentence that describes the @code{filter} function!
+However, unfortuantely Make's @code{filter} function only accepts a single 
@code{%}, not two!
+
+@item $(ast-fits-with-keyvalue KEYNAME, KEYVALUES, HDU, FITS_FILES)
 Will select only the FITS files (from a list of many in @code{FITS_FILES}, 
non-FITS files are ignored), where the @code{KEYNAME} keyword has the value(s) 
given in @code{KEYVALUES}.
 Only the HDU given in the @code{HDU} argument will be checked.
 According to the FITS standard, the keyword name is not case sensitive, but 
the keyword value is.
@@ -27986,20 +28000,20 @@ Notice how there is no comma between @code{BAR} and 
@code{BAZ}: you can specify
 load /usr/local/lib/libgnuastro_make.so
 
 files := $(wildcard /datasets/images/*.fits)
-selected := $(ast-fits-with-keyvalue $(files), 1, FOO, BAR BAZ)
+selected := $(ast-fits-with-keyvalue FOO, BAR BAZ, 1, $(files))
 
 all:
        echo "Full:     $(words $(files)) files";
        echo "Selected: $(words $(selected)) files"
 @end verbatim
 
-@item $(ast-fits-unique-keyvalues FITS_FILES, HDU, KEYNAME)
+@item $(ast-fits-unique-keyvalues KEYNAME, HDU, FITS_FILES)
 Will return the unique values given to the given FITS keyword (@code{KEYNAME}) 
in the given HDU of all the input FITS files (non-FITS files are ignored).
 For example, after the commands below, the @code{keyvalues} variable will 
contain the unique values given to the @code{FOO} keyword in HDU number 1 of 
all the FITS files in @file{/datasets/images/*.fits}.
 
 @example
 files := $(wildcard /datasets/images/*.fits)
-keyvalues := $(ast-fits-unique-keyvalues $(files), 1, FOO)
+keyvalues := $(ast-fits-unique-keyvalues FOO, 1, $(files))
 @end example
 
 This is useful when you do not know the full range of values a-priori.
@@ -28013,7 +28027,7 @@ Knowing the calibration keyword values, you can extract 
the science keyword valu
 calib = BIAS FLAT
 files := $(wildcard /datasets/images/*.fits)
 science := $(filter-out $(calib), \
-             $(ast-fits-unique-keyvalues $(files), 1, OBJECT))
+             $(ast-fits-unique-keyvalues OBJECT, 1, $(files)))
 @end example
 
 The @code{science} variable will now contain the unique science targets that 
were observed in your selected FITS images.
@@ -32271,6 +32285,12 @@ The returned pointer is within the input string.
 If the input pointer is @code{NULL}, or the string only has white-space 
characters, the returned pointer will be @code{NULL}.
 @end deftypefun
 
+@deftypefun int gal_txt_contains_string (char @code{*full}, char @code{*match})
+Return 1 if the string that @code{match} points to, can be exactly found 
within the string that @code{full} points to (character by character).
+The to-match string can be in any part of the full string.
+If any of the two strings have zero length or are a @code{NULL} pointer, this 
function will return 0.
+@end deftypefun
+
 @deftypefun {gal_data_t *} gal_txt_table_info (char @code{*filename}, 
gal_list_str_t @code{*lines}, size_t @code{*numcols}, size_t @code{*numrows})
 Store the information of each column in a text file @code{filename}, or list 
of strings (@code{lines}) into an array of data structures with @code{numcols} 
elements (one data structure for each column) see @ref{Arrays of datasets}.
 The total number of rows in the table is also put into the memory that 
@code{numrows} points to.
diff --git a/lib/gnuastro/txt.h b/lib/gnuastro/txt.h
index 6405b75d..91551966 100644
--- a/lib/gnuastro/txt.h
+++ b/lib/gnuastro/txt.h
@@ -82,6 +82,9 @@ gal_txt_line_stat(char *line);
 char *
 gal_txt_trim_space(char *str);
 
+int
+gal_txt_contains_string(char *full, char *match);
+
 gal_data_t *
 gal_txt_table_info(char *filename, gal_list_str_t *lines, size_t *numcols,
                    size_t *numrows);
diff --git a/lib/makeplugin.c b/lib/makeplugin.c
index 217a6d1d..354530af 100644
--- a/lib/makeplugin.c
+++ b/lib/makeplugin.c
@@ -48,6 +48,7 @@ int plugin_is_GPL_compatible=1;
 
 /* Names of the separate functions */
 #define MAKEPLUGIN_FUNC_PREFIX "ast"
+static char *text_contains_name=MAKEPLUGIN_FUNC_PREFIX"-text-contains";
 static char 
*fits_with_keyvalue_name=MAKEPLUGIN_FUNC_PREFIX"-fits-with-keyvalue";
 static char 
*fits_unique_keyvalues_name=MAKEPLUGIN_FUNC_PREFIX"-fits-unique-keyvalues";
 
@@ -55,10 +56,72 @@ static char 
*fits_unique_keyvalues_name=MAKEPLUGIN_FUNC_PREFIX"-fits-unique-keyv
 
 
 
+
+
+
+
+
+/**********************************************************************/
+/***************             Text utilities             ***************/
+/**********************************************************************/
+
+/* Return any of the input strings that contain the given string. It takes
+   two arguments:
+      0. String to check.
+      1. List of text.*/
+static char *
+makeplugin_text_contains(const char *caller, unsigned int argc,
+                         char **argv)
+{
+  char *out=NULL;
+  gal_list_str_t *tmp, *outlist=NULL;
+  char *match=argv[0]; /* No trimming the white space before/after, as in */
+  gal_list_str_t *strings=gal_list_str_extract(argv[1]); /* Make itself.  */
+
+  printf("%s: HERE\n", __func__);
+  gal_list_str_print(strings);
+
+  /* Parse the input strings and find the ones that match. */
+  for(tmp=strings; tmp!=NULL; tmp=tmp->next)
+    if( gal_txt_contains_string(tmp->v, match) )
+      gal_list_str_add(&outlist, tmp->v, 0);
+
+  /* Write the list into one string. */
+  out=gal_list_str_cat(outlist);
+
+  /* Clean up and return. */
+  gal_list_str_free(strings, 1);
+  gal_list_str_free(outlist, 0); /* We didn't allocate these. */
+  return out;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**********************************************************************/
+/***************             FITS utilities             ***************/
+/**********************************************************************/
+
 /* Select the input files that have the requested value(s) in the requested
    keywords. */
 static int
-makeplugin_goodinput(char **argv, size_t numargs, char *name)
+makeplugin_fits_check_input(char **argv, size_t numargs, char *name)
 {
   char *c;
   size_t i;
@@ -85,26 +148,32 @@ makeplugin_goodinput(char **argv, size_t numargs, char 
*name)
 
 
 
+/* Select files, were a certain keyword has a certain value. It takes four
+   arguments:
+       0. Keyword name.
+       1. Keyword value(s).
+       2. HDU (fixed in all files).
+       3. List of files. */
 static char *
 makeplugin_fits_with_keyvalue(const char *caller, unsigned int argc,
                               char **argv)
 {
   gal_list_str_t *outlist=NULL;
-  char *name=gal_txt_trim_space(argv[2]);
+  char *name=gal_txt_trim_space(argv[0]);
   gal_list_str_t *files=NULL, *values=NULL;
-  char *out, *hdu=gal_txt_trim_space(argv[1]);
+  char *out, *hdu=gal_txt_trim_space(argv[2]);
 
   /* If any of the inputs are empty, then don't bother continuing. */
-  if( makeplugin_goodinput(argv, 4, fits_with_keyvalue_name)==0 )
+  if( makeplugin_fits_check_input(argv, 4, fits_with_keyvalue_name)==0 )
     return NULL;
 
   /* Extract the components in the arguments with possibly multiple
      values and find the output files.*/
-  files=gal_list_str_extract(argv[0]);
-  values=gal_list_str_extract(argv[3]);
+  files=gal_list_str_extract(argv[3]);
+  values=gal_list_str_extract(argv[1]);
   outlist=gal_fits_with_keyvalue(files, hdu, name, values);
 
-  /* Write the output value. */
+  /* Write the output string */
   out=gal_list_str_cat(outlist);
 
   /* Clean up and return. */
@@ -117,23 +186,27 @@ makeplugin_fits_with_keyvalue(const char *caller, 
unsigned int argc,
 
 
 
-
+/* Return the unique values given to a certain keyword in many FITS
+   files. It takes three arguments.
+       0. Keyword name.
+       1. HDU (fixed in all files).
+       2. List of files. */
 static char *
 makeplugin_fits_unique_keyvalues(const char *caller, unsigned int argc,
                                  char **argv)
 {
   gal_list_str_t *files=NULL;
   gal_list_str_t *outlist=NULL;
-  char *name=gal_txt_trim_space(argv[2]);
+  char *name=gal_txt_trim_space(argv[0]);
   char *out, *hdu=gal_txt_trim_space(argv[1]);
 
   /* If any of the inputs are empty, then don't bother continuing. */
-  if( makeplugin_goodinput(argv, 3, fits_unique_keyvalues_name)==0 )
+  if( makeplugin_fits_check_input(argv, 3, fits_unique_keyvalues_name)==0 )
     return NULL;
 
   /* Extract the components in the arguments with possibly multiple
      values and find the output files.*/
-  files=gal_list_str_extract(argv[0]);
+  files=gal_list_str_extract(argv[2]);
   outlist=gal_fits_unique_keyvalues(files, hdu, name);
 
   /* Write the output value. */
@@ -153,20 +226,18 @@ makeplugin_fits_unique_keyvalues(const char *caller, 
unsigned int argc,
 int
 libgnuastro_make_gmk_setup()
 {
+  /* Return any of the input strings that contain the given string. */
+  gmk_add_function(text_contains_name,
+                   makeplugin_text_contains,
+                   2, 2, GMK_FUNC_DEFAULT);
+
   /* Select files, were a certain keyword has a certain value. It takes
-     four arguments:
-       0. List of files.
-       1. HDU (fixed in all files).
-       2. Keyword name.
-       3. Keyword value(s). */
+     four arguments. */
   gmk_add_function(fits_with_keyvalue_name, makeplugin_fits_with_keyvalue,
                    4, 4, GMK_FUNC_DEFAULT);
 
   /* Return the unique values given to a certain keyword in many FITS
-     files. It takes three arguments.
-       0. List of files.
-       1. HDU (fixed in all files).
-       2. Keyword name. */
+     files.*/
   gmk_add_function(fits_unique_keyvalues_name,
                    makeplugin_fits_unique_keyvalues,
                    3, 3, GMK_FUNC_DEFAULT);
diff --git a/lib/txt.c b/lib/txt.c
index 7628efab..4922d56d 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -122,6 +122,30 @@ gal_txt_trim_space(char *str)
 
 
 
+/* Return 1 if the input string contains the 'match' substring. */
+int
+gal_txt_contains_string(char *full, char *match)
+{
+  char *c=full;
+  size_t ml = match ? strlen(match) : 0;
+
+  /* If the input or output strings are empty, a match can't be defined
+     (strncmp will always succeed to find a match). */
+  if(ml==0 || full==NULL || *full=='\0') return 0;
+
+  /* Parse the string (character by character) to see if there is a
+     match. */
+  do if( strncmp(c, match, ml)==0 ) return 1;
+  while( *(++c)!='\0' );
+
+  /* If control reaches here, there was no match. */
+  return 0;
+}
+
+
+
+
+
 /* Each information comment should have a format like this (replace
    'Column' with 'Image' for 2D arrays):
 



reply via email to

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