[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnuastro-commits] master d5ca7d3: Logical operators in Arithmetic,
Mohammad Akhlaghi <=