gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master d5ca7d3: Logical operators in Arithmetic


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master d5ca7d3: Logical operators in Arithmetic
Date: Sat, 10 Sep 2016 16:49:41 +0000 (UTC)

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

    Logical operators in Arithmetic
    
    The three logical operators `and', `or' and `not' where added to
    Arithmetic, the book was also updated and a test was written for the `or'
    operator which is now checked with `make check'.
    
    The explanation for the `where' operator was also made more clear.
    
    The other operator lines in the `reversepolish' function were just adjusted
    so all their function names are on the same column to help in reading.
    
    This finishes task #14153.
---
 doc/gnuastro.texi           |   53 ++++++++++++++-------
 src/arithmetic/args.h       |    6 +--
 src/arithmetic/arithmetic.c |  107 +++++++++++++++++++++++++++++++++++++------
 tests/Makefile.am           |   31 +++++++------
 tests/arithmetic/or.sh      |   51 +++++++++++++++++++++
 5 files changed, 199 insertions(+), 49 deletions(-)

diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 975bb5a..f0a61c2 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -6998,22 +6998,41 @@ even equal to itself, so you cannot use the equal 
operator above to select
 blank pixels. See the ``Blank pixels'' box below for more on Blank pixels
 in Arithmetic.
 
address@hidden and
+Logical AND: returns 1 if both operands have a non-zero value and 0 if both
+are zero. Both operands have to be the same kind: either both images or
+both numbers.
+
address@hidden or
+Logical OR: returns 1 if either one of the operands is non-zero and 0 only
+when both operators are zero. Both operands have to be the same kind:
+either both images or both numbers.
+
address@hidden not
+Logical NOT: returns 1 when the operand is zero and 0 when the operand is
+non-zero. The operand can be an image or number, for an image, it is
+applied to each pixel separately.
+
 @item where
 Change the input (pixel) value `where' a certain condition holds. The
 conditional operators above can be used to define the condition. Three
-operands are required for @command{where}, with the format of:
+operands are required for @command{where}. The input format is demonstrated
+in this simplified example:
 @example
 astarithmetic in.fits condition.fits new.fits where
 @end example
-The first two operands above have to be images or all three operands have
-to be numbers. In the former case (when the first two are images), the
-third operand can be an image or a number. The value of any pixel in
address@hidden that corresponds to a non-zero pixel of
address@hidden will be changed to the value of the same pixel in
address@hidden Commonly you won't be dealing with an actual FITS file of
-a conditional image. You will probably actually define the condition in the
-same run or Arithmetic based on some other reference. For example the case
-below:
+The third and second popped operands (@file{in.fits} and
address@hidden above, see @ref{Reverse polish notation}) have to be
+images or all three operands have to be numbers. In the former case (when
+the first two are images), the third operand can be an image or a
+number. The value of any pixel in @file{in.fits} that corresponds to a
+non-zero pixel of @file{condition.fits} will be changed to the value of the
+same pixel in @file{new.fits} (or a fixed number if the first popped
+operand is a number). Commonly you won't be dealing with an actual FITS
+file of a conditional image. You will probably define the condition in the
+same run based on some other reference image and use the conditional and
+logical operators above to make a true/false (or one/zero) image for you
+internally. For example the case below:
 
 @example
 $ astarithmetic in.fits reference.fits 100 gt new.fits where
@@ -7034,13 +7053,13 @@ affected, they are only read.
 
 @cartouche
 @noindent
address@hidden pixels:} Currently all Arithmetic operations are internally
-done in double precision floating points. So all blank pixels in the image
-(see @ref{Blank pixels}) will be stored as IEEE NaN values. One particular
-aspect of NaN values is that by definition they will fail on @emph{any}
-comparison. Hence both equal and not-equal operators will fail when both
-their operands are NaN! The only way to select blank pixels is through the
address@hidden operator explained above.
address@hidden pixels in Arithmetic:} Currently all Arithmetic operations
+are internally done in double precision floating points. So all blank
+pixels in the image (see @ref{Blank pixels}) will be stored as IEEE NaN
+values. One particular aspect of NaN values is that by definition they will
+fail on @emph{any} comparison. Hence both equal and not-equal operators
+will fail when both their operands are NaN! The only way to select blank
+pixels is through the @command{isblank} operator explained above.
 
 One way you can exploit this property of the NaN value to your advantage is
 when you want a fully zero-valued image (even over the blank pixels) based
diff --git a/src/arithmetic/args.h b/src/arithmetic/args.h
index f46ce23..64df67b 100644
--- a/src/arithmetic/args.h
+++ b/src/arithmetic/args.h
@@ -68,9 +68,9 @@ const char doc[] =
   "Please see the manual for more information. "
   "\n\nThe operators/functions recognized by "SPACK_NAME" are: +, -, *, /, "
   "abs, pow, sqrt, log, log10, minvalue, maxvalue, min, max, average, median, "
-  "lt, le, gt, ge, eq, neq, isblank. Please run `info gnuastro \"Arithmetic "
-  "operators\"' for detailed information on each operator. Note that "
-  "multiplication should be quoted (like \"*\", or '*') to avoid shell "
+  "lt, le, gt, ge, eq, neq, and, or, not, isblank. Please run `info gnuastro "
+  "\"Arithmetic operators\"' for detailed information on each operator. Note "
+  "that multiplication should be quoted (like \"*\", or '*') to avoid shell "
   "expansion.\n"
   GAL_STRINGS_MORE_HELP_INFO
   /* After the list of options: */
diff --git a/src/arithmetic/arithmetic.c b/src/arithmetic/arithmetic.c
index dc7a3eb..6aa0283 100644
--- a/src/arithmetic/arithmetic.c
+++ b/src/arithmetic/arithmetic.c
@@ -838,6 +838,82 @@ conditionals(struct imgarithparams *p, char *operator)
 
 
 
+void
+andor(struct imgarithparams *p, char *operator)
+{
+  double *f, *s, *ff;
+  double fnum, snum, *farr, *sarr;
+
+  /* Pop out the number of operands needed. */
+  pop_operand(p, &fnum, &farr, operator);
+  pop_operand(p, &snum, &sarr, operator);
+
+  /* Do a small sanity check: */
+  if(strcmp(operator, "and") && strcmp(operator, "or") )
+    error(EXIT_FAILURE, 0, "a bug! Please contact us at %s so we "
+          "can address the problem. The value of `operator' in "
+          "`andor' (%s) is not recognized", PACKAGE_BUGREPORT, operator);
+
+  /* Do the operation: */
+  if(farr && sarr)
+    {
+      /* Fill the first array with the result. IMPORTANT: It is important
+         that the second array pointer is the first checked array, since it
+         is also incremented. In the `or' operation, if `*f' is successful,
+         `*s++' is never called and so not incremented. */
+      s = sarr;
+      ff = (f=farr) + p->s0*p->s1;
+      if(!strcmp(operator, "and"))
+        do *f = *s++ && *f; while(++f<ff);
+      else
+        do *f = *s++ || *f; while(++f<ff);
+
+      /* Push the output onto the stack. */
+      add_operand(p, NOOPTFILENAME, NOOPTNUMBER, farr);
+
+      /* Clean up */
+      free(sarr);
+    }
+  else if(farr==NULL || sarr==NULL)
+    error(EXIT_FAILURE, 0, "The `and' and `or' operators need two operators "
+          "of the same type: either both images or both numbers.");
+  else
+    add_operand(p, NOOPTFILENAME,
+                !strcmp(operator, "and") ? fnum && snum : fnum || snum,
+                NOOPTARRAY);
+}
+
+
+
+
+void
+notfunc(struct imgarithparams *p)
+{
+  double *f, *ff;
+  double fnum, *farr;
+  char *operator="not";
+
+  /* Pop out the number of operands needed. */
+  pop_operand(p, &fnum, &farr, operator);
+
+  /* Do the operation: */
+  if(farr)
+    {
+      /* Fill the array with the output values. */
+      ff = (f=farr) + p->s0*p->s1;
+      do *f = !(*f); while(++f<ff);
+
+      /* Push the output onto the stack. */
+      add_operand(p, NOOPTFILENAME, NOOPTNUMBER, farr);
+    }
+  else
+    add_operand(p, NOOPTFILENAME, !fnum, NOOPTARRAY);
+}
+
+
+
+
+
 /* In order to not conflict with the internal C `is...' functions, and in
    particular the `isblank' function, we are calling this function
    opisblank for operator-isblank. */
@@ -980,17 +1056,17 @@ reversepolish(struct imgarithparams *p)
         add_operand(p, NOOPTFILENAME, number, NOOPTARRAY);
       else
         {
-          if     (!strcmp(token->v, "+"))       sum(p);
-          else if(!strcmp(token->v, "-"))       subtract(p);
-          else if(!strcmp(token->v, "*"))       multiply(p);
-          else if(!strcmp(token->v, "/"))       divide(p);
-          else if(!strcmp(token->v, "abs"))     takeabs(p);
-          else if(!strcmp(token->v, "pow"))     topower(p, NULL);
-          else if(!strcmp(token->v, "sqrt"))    takesqrt(p);
-          else if(!strcmp(token->v, "log"))     takelog(p);
-          else if(!strcmp(token->v, "log10"))   takelog10(p);
-          else if(!strcmp(token->v, "minvalue"))findmin(p);
-          else if(!strcmp(token->v, "maxvalue"))findmax(p);
+          if     (!strcmp(token->v, "+"))         sum(p);
+          else if(!strcmp(token->v, "-"))         subtract(p);
+          else if(!strcmp(token->v, "*"))         multiply(p);
+          else if(!strcmp(token->v, "/"))         divide(p);
+          else if(!strcmp(token->v, "abs"))       takeabs(p);
+          else if(!strcmp(token->v, "pow"))       topower(p, NULL);
+          else if(!strcmp(token->v, "sqrt"))      takesqrt(p);
+          else if(!strcmp(token->v, "log"))       takelog(p);
+          else if(!strcmp(token->v, "log10"))     takelog10(p);
+          else if(!strcmp(token->v, "minvalue"))  findmin(p);
+          else if(!strcmp(token->v, "maxvalue"))  findmax(p);
           else if(!strcmp(token->v, "min")
                   || !strcmp(token->v, "max")
                   || !strcmp(token->v, "average")
@@ -1000,9 +1076,12 @@ reversepolish(struct imgarithparams *p)
                   || !strcmp(token->v, "gt")
                   || !strcmp(token->v, "ge")
                   || !strcmp(token->v, "eq")
-                  || !strcmp(token->v, "neq")) conditionals(p, token->v);
-          else if(!strcmp(token->v, "isblank")) opisblank(p);
-          else if(!strcmp(token->v, "where")) where(p);
+                  || !strcmp(token->v, "neq"))    conditionals(p, token->v);
+          else if(!strcmp(token->v, "and")
+                  || !strcmp(token->v, "or"))     andor(p, token->v);
+          else if(!strcmp(token->v, "not"))       notfunc(p);
+          else if(!strcmp(token->v, "isblank"))   opisblank(p);
+          else if(!strcmp(token->v, "where"))     where(p);
           else
             error(EXIT_FAILURE, 0, "the argument \"%s\" could not be "
                   "interpretted as an operator", token->v);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index fb5943d..82e317c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -54,21 +54,21 @@ version_SOURCES = lib/version.c
 
 
 # The actual test scripts that are run:
-TESTS = prepconf.sh mkprof/mosaic1.sh mkprof/mosaic2.sh mkprof/mosaic3.sh   \
-  mkprof/mosaic4.sh mkprof/radeccat.sh imgcrop/imgcat.sh imgcrop/wcscat.sh  \
-  imgcrop/xcyc.sh imgcrop/xcycnoblank.sh imgcrop/section.sh                 \
-  imgcrop/radec.sh imgcrop/imgpolygon.sh imgcrop/imgoutpolygon.sh           \
-  imgcrop/wcspolygon.sh convertt/fitstotxt.sh convertt/fitstojpeg.sh        \
-  convertt/blankch.sh convertt/jpegtotxt.sh convertt/fitstojpegcmyk.sh      \
-  convertt/jpegtofits.sh convertt/fitstopdf.sh convolve/spatial.sh          \
-  convolve/frequency.sh imgwarp/imgwarp_scale.sh imgwarp/homographic.sh     \
-  mknoise/addnoise.sh mkprof/ellipticalmasks.sh mkprof/inputascanvas.sh     \
-  header/write.sh header/print.sh header/update.sh header/delete.sh         \
-  imgstat/basicstats.sh subtractsky/subtractsky.sh                          \
-  noisechisel/noisechisel.sh mkcatalog/simple.sh mkcatalog/aperturephot.sh  \
-  arithmetic/snimage.sh arithmetic/onlynumbers.sh arithmetic/where.sh       \
-  cosmiccal/simpletest.sh table/asciitobinary.sh table/binarytoascii.sh     \
-  $(check_PROGRAMS)
+TESTS = $(check_PROGRAMS) prepconf.sh mkprof/mosaic1.sh mkprof/mosaic2.sh    \
+  mkprof/mosaic3.sh mkprof/mosaic4.sh mkprof/radeccat.sh imgcrop/imgcat.sh   \
+  imgcrop/wcscat.sh imgcrop/xcyc.sh imgcrop/xcycnoblank.sh                   \
+  imgcrop/section.sh imgcrop/radec.sh imgcrop/imgpolygon.sh                  \
+  imgcrop/imgoutpolygon.sh imgcrop/wcspolygon.sh convertt/fitstotxt.sh       \
+  convertt/fitstojpeg.sh convertt/blankch.sh convertt/jpegtotxt.sh           \
+  convertt/fitstojpegcmyk.sh convertt/jpegtofits.sh convertt/fitstopdf.sh    \
+  convolve/spatial.sh convolve/frequency.sh imgwarp/imgwarp_scale.sh         \
+  imgwarp/homographic.sh mknoise/addnoise.sh mkprof/ellipticalmasks.sh       \
+  mkprof/inputascanvas.sh header/write.sh header/print.sh header/update.sh   \
+  header/delete.sh imgstat/basicstats.sh subtractsky/subtractsky.sh          \
+  noisechisel/noisechisel.sh mkcatalog/simple.sh mkcatalog/aperturephot.sh   \
+  arithmetic/snimage.sh arithmetic/onlynumbers.sh arithmetic/where.sh        \
+  arithmetic/or.sh cosmiccal/simpletest.sh table/asciitobinary.sh            \
+  table/binarytoascii.sh
 
 
 
@@ -157,5 +157,6 @@ mkcatalog/aperturephot.sh: noisechisel/noisechisel.sh.log   
       \
                            mkprof/inputascanvas.sh
 arithmetic/snimage.sh: noisechisel/noisechisel.sh.log
 arithmetic/where.sh: noisechisel/noisechisel.sh.log
+arithmetic/or.sh: noisechisel/noisechisel.sh.log
 arithmetic/onlynumbers.sh: prepconf.sh.log
 cosmiccal/simpletest.sh: prepconf.sh.log
diff --git a/tests/arithmetic/or.sh b/tests/arithmetic/or.sh
new file mode 100755
index 0000000..12e8da7
--- /dev/null
+++ b/tests/arithmetic/or.sh
@@ -0,0 +1,51 @@
+# Choose two detected regions with the `or' operator
+#
+# See the Tests subsection of the manual for a complete explanation
+# (in the Installing gnuastro section).
+#
+# Original author:
+#     Mohammad Akhlaghi <address@hidden>
+# Contributing author(s):
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.  This file is offered as-is,
+# without any warranty.
+
+
+
+
+
+# Preliminaries
+# =============
+#
+# Set the variabels (The executable is in the build tree). Do the
+# basic checks to see if the executable is made or if the defaults
+# file exists (basicchecks.sh is in the source tree).
+prog=arithmetic
+execname=../src/$prog/ast$prog
+img=convolve_spatial_noised_labeled.fits
+
+
+
+
+
+# Skip?
+# =====
+#
+# If the dependencies of the test don't exist, then skip it. There are two
+# types of dependencies:
+#
+#   - The executable was not made (for example due to a configure option),
+#
+#   - The input data was not made (for example the test that created the
+#     data file failed).
+if [ ! -f $execname ] || [ ! -f $img ]; then exit 77; fi
+
+
+
+
+
+# Actual test script
+# ==================
+$execname $img 6 eq $img 3 eq or -h1 -h1 --output=or.fits



reply via email to

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