gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 954409c9: dither-simulate: now accepts hooks f


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 954409c9: dither-simulate: now accepts hooks for customizations
Date: Sun, 30 Jul 2023 19:27:14 -0400 (EDT)

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

    dither-simulate: now accepts hooks for customizations
    
    Until now, the 'astscript-dither-simulate' script would only stack the
    1-valued individual exposures to produce an exposure map. But in a
    realistic dither simulation, many other customizations are usually
    necessary (including the vignetted areas, or seeing the actual noise
    pattern).
    
    With this commit, two hooks have been added to the script and Makefile to
    allow such customizations easily for the user without having to dig into
    the code. Their usage has also been added in the tutorials.
    
    The following changes have also been made:
    
     - I noticed that in all the installed scripts, the check for options like
       '--center' that take two values didn't account for cases like ',' (for
       example when two shell variables were used but there was a typo in their
       name). This has been fixed in all the scripts that have such options.
    
     - The Moire pattern tutorial wasn't yet brought into the Tutorials
       chapter.
---
 NEWS                           |   8 +-
 bin/script/dither-simulate.mk  |  58 ++-
 bin/script/dither-simulate.sh  |  94 +++--
 bin/script/ds9-region.sh       |   4 +-
 bin/script/psf-scale-factor.sh |   6 +-
 bin/script/psf-select-stars.sh |  15 +-
 bin/script/psf-stamp.sh        |   6 +-
 bin/script/psf-subtract.sh     |   4 +-
 bin/script/radial-profile.sh   |  12 +-
 bin/script/zeropoint.sh        |   8 +-
 doc/gnuastro.texi              | 860 +++++++++++++++++++++++++++--------------
 11 files changed, 719 insertions(+), 356 deletions(-)

diff --git a/NEWS b/NEWS
index 067467b5..6bf66096 100644
--- a/NEWS
+++ b/NEWS
@@ -11,9 +11,11 @@ See the end of the file for license conditions.
   New program:
   - 'astscript-dither-simulate': a new installed script that will simplify
     the process of designing the best dither pattern for your observing
-    strategy. It takes into account the distortion of the camera and runs
-    in parallel. A new tutorial has been added in the Tutorials chapter on
-    how to use it.
+    strategy. It takes into account the distortion of the camera, runs in
+    parallel and allows customizations (for example to account for
+    vignetting or large blobs of bad pixels) through hooks at relevant
+    steps. A new tutorial has been added in the Tutorials chapter of the
+    book on how to use this new script.
 
   Book:
   - New tutorial on a low surface brightness optimized design of a dither
diff --git a/bin/script/dither-simulate.mk b/bin/script/dither-simulate.mk
index 7654c6c5..778a1029 100644
--- a/bin/script/dither-simulate.mk
+++ b/bin/script/dither-simulate.mk
@@ -30,26 +30,62 @@ all: $(output)
 
 
 
+
+# Hooks preparation:
+#   - For the check in the shell (to see if the hook is activated or not),
+#     it is easier to work with a single word (hence why '$(word 1) is
+#     being used).
+#   - Shell scripts can have double-quotations, which can intefere with the
+#     double quotations within the recipe.
+hook-warp-after-check=$(subst \",,$(word 1,$(hook-warp-after)))
+hook-warp-before-check=$(subst \",,$(word 1,$(hook-warp-before)))
+
+
+
+
+
 # Build each separate exposure.
 exposures=$(foreach d,$(dithers),$(tmpdir)/exp-$(d).fits)
 $(exposures): $(tmpdir)/exp-%.fits: $(img) | $(tmpdir)
 
 #      Copy the input into a temporary one and edit its keywords to adjust
 #      to this pointings position.
-       @copy=$(subst .fits,-copy.fits,$@); \
-       warped=$(subst .fits,-warped.fits,$@); \
-       const=$(subst .fits,-constant.fits,$@); \
+#        - 'TARGET' is defined for hooks (who don't see Make's '$@').
+#        - After each hook, we need to make sure the necessary file for the
+#          next step has been created.
+       @TARGET=$@; \
+       copy=$(subst .fits,-copy.fits,$@); \
+       WARPED=$(subst .fits,-warped.fits,$@); \
+       TOWARP=$(subst .fits,-to-warp.fits,$@); \
+       EXPOSURE=$(subst .fits,-exposure.fits,$@); \
        astfits $(img) --copy=$(imghdu) --output=$$copy $(quiet); \
        astfits --update=CRVAL1,$($*-ra) $$copy \
                --update=CRVAL2,$($*-dec) $(quiet); \
-       astarithmetic $$copy 1 uint8 constant --output=$$const \
+       astarithmetic $$copy 1 uint8 constant --output=$$EXPOSURE \
                      $(quiet); \
        rm $$copy; \
-       astwarp $$const --center=$(center) --width=$(width) \
-               $(widthinpix) --output=$$warped $(quiet); \
-       rm $$const; \
-       astarithmetic $$warped isnotblank -o$@ $(quiet); \
-       rm $$warped
+       if [ x$(hook-warp-before-check) = x ]; then \
+         cp $$EXPOSURE $$TOWARP; \
+       else \
+         eval "$(hook-warp-before)"; \
+         if ! [ -f $$TOWARP ]; then \
+           echo "$(scriptname): command given to '--hook-warp-before' did not 
create the required input for the next step. Please make sure that the final 
output of the command given to this hoook is called as '\$$TOWARP' in your 
command. See the documentation and tutorials for more"; \
+           exit 1; \
+         fi; \
+       fi; \
+       astwarp $$TOWARP --ctype=$(ctype) --center=$(center) \
+               $(quiet) --width=$(width) --output=$$WARPED \
+               $(widthinpix); \
+       if [ x$(hook-warp-after-check) = x ]; then \
+         astarithmetic $$WARPED isnotblank -o$$TARGET $(quiet); \
+       else \
+         eval "$(hook-warp-after)"; \
+         if ! [ -f $$TARGET ]; then \
+           echo "$(scriptname): command given to '--hook-warp-after' did not 
create the required input for the next step. Please make sure that the final 
output of the command given to this hoook is called as \$$TARGET  in your 
command. See the documentation and tutorials for more"; \
+           exit 1; \
+         fi; \
+       fi; \
+       rm $$WARPED $$TOWARP $$EXPOSURE
 
 
 
@@ -57,5 +93,5 @@ $(exposures): $(tmpdir)/exp-%.fits: $(img) | $(tmpdir)
 
 # Build the stack
 $(output): $(exposures)
-       @astarithmetic $(exposures) $(words $(exposures)) \
-                     sum -g1 --output=$@ $(quiet)
+       astarithmetic $(exposures) $(words $(exposures)) \
+                      $(stack-operator) -g1 --output=$@ $(quiet)
diff --git a/bin/script/dither-simulate.sh b/bin/script/dither-simulate.sh
index 97f2082f..e6c2dc80 100644
--- a/bin/script/dither-simulate.sh
+++ b/bin/script/dither-simulate.sh
@@ -38,14 +38,17 @@ deccol="DEC"
 widthinpix=0
 numthreads=0
 version=@VERSION@
+hook_warp_after=""
+hook_warp_before=""
+stack_operator="sum"
 scriptname=@SCRIPT_NAME@
+ctype="RA---TAN,DEC--TAN"
 output=dither-simulate.fits
 installdir=@PREFIX@/share/gnuastro
 
 
 
 
-
 # Output of '--help'
 print_help() {
    cat <<EOF
@@ -66,13 +69,21 @@ $scriptname options:
   -H, --imghdu=STR/INT    HDU name or number of the input image.
   -r, --racol=STR/INT     Name/number of column containing RA.
   -d, --deccol=STR/INT    Name/number of column containing Declination.
-  -C, --center=FLT,FLT    Center of output stack (in RA,Dec).
-  -w, --width=FLT,FLT     Width of output stack (in WCS).
-      --widthinpix        Interpret '--width' values in pixels.
       --mksrc=STR         Makefile (for developers when debugging).
 
+ Hooks:
+      --hook-warp-before='COMMAND' Before warping each exposure;
+                          Input: '$EXPOSURE'. Output: '$TOWARP'.
+      --hook-warp-after='COMMAND' After warping each exposure;
+                          Input: '$WARPED'. Output: '$TARGET'.
+
  Output:
   -o, --output=STR        Name of finally stacked image.
+  -C, --center=FLT,FLT    Center of output stack (in RA,Dec).
+  -w, --width=FLT,FLT     Width of output stack (in WCS).
+      --ctype=STR,STR     Projection of output (CTYPEi in WCS).
+      --widthinpix        Interpret '--width' values in pixels.
+      --stack-operator="STR" Arithmetic operator to use for stacking.
   -t, --tmpdir=STR        Directory to keep temporary files.
   -k, --keeptmp           Keep temporal/auxiliar files.
 
@@ -219,27 +230,36 @@ do
     -d|--deccol)     deccol="$2";                                 check_v "$1" 
"$deccol"; shift;shift;;
     -d=*|--deccol=*) deccol="${1#*=}";                            check_v "$1" 
"$deccol"; shift;;
     -d*)             deccol=$(echo "$1" | sed -e's/-d//');        check_v "$1" 
"$deccol"; shift;;
+    --mksrc)         mksrc="$2";                                  check_v "$1" 
"$mksrc";  shift;shift;;
+    --mksrc=*)       mksrc="${1#*=}";                             check_v "$1" 
"$mksrc";  shift;;
+
+    # Hooks
+    --hook-warp-after) hook_warp_after=$(echo "$2" | sed -e's@\$@\$\$@g'); 
check_v "$1" "$hook_warp_after"; shift;;
+    --hook-warp-after=*) v="${1#*=}"; hook_warp_after=$(echo "$v" | sed 
-e's@\$@\$\$@g'); check_v "$1" "$hook_warp_after"; shift;;
+    --hook-warp-before) hook_warp_before=$(echo "$2" | sed -e's@\$@\$\$@g'); 
check_v "$1" "$hook_warp_before"; shift;;
+    --hook-warp-before=*) v="${1#*=}"; hook_warp_before=$(echo "$v" | sed 
-e's@\$@\$\$@g'); check_v "$1" "$hook_warp_before"; shift;;
+
+    # Output:
+    -o|--output)     output="$2";                                 check_v "$1" 
"$output"; shift;shift;;
+    -o=*|--output=*) output="${1#*=}";                            check_v "$1" 
"$output"; shift;;
+    -o*)             output=$(echo "$1" | sed -e's/-o//');        check_v "$1" 
"$output"; shift;;
     -C|--center)     center="$2";                                 check_v "$1" 
"$center"; shift;shift;;
     -C=*|--center=*) center="${1#*=}";                            check_v "$1" 
"$center"; shift;;
     -C*)             center=$(echo "$1" | sed -e's/-C//');        check_v "$1" 
"$center"; shift;;
     -w|--width)      width="$2";                                  check_v "$1" 
"$width";  shift;shift;;
     -w=*|--width=*)  width="${1#*=}";                             check_v "$1" 
"$width";  shift;;
     -w*)             width=$(echo "$1" | sed -e's/-w//');         check_v "$1" 
"$width";  shift;;
-    --mksrc)         mksrc="$2";                                  check_v "$1" 
"$mksrc";  shift;shift;;
-    --mksrc=*)       mksrc="${1#*=}";                             check_v "$1" 
"$mksrc";  shift;;
+    --ctype)         ctype="$2";                                  check_v "$1" 
"$ctype";  shift;shift;;
+    --ctype=*)       ctype="${1#*=}";                             check_v "$1" 
"$ctype";  shift;;
     --widthinpix)    widthinpix=1;                                             
           shift;;
     --widthinpix=*)  on_off_option_error --quiet -q;;
-
-
-   # Output parameters
-   -k|--keeptmp)           keeptmp=1; shift;;
-   -k*|--keeptmp=*)        on_off_option_error --keeptmp -k;;
-   -t|--tmpdir)            tmpdir="$2";                                  
check_v "$1" "$tmpdir";  shift;shift;;
-   -t=*|--tmpdir=*)        tmpdir="${1#*=}";                             
check_v "$1" "$tmpdir";  shift;;
-   -t*)                    tmpdir=$(echo "$1" | sed -e's/-t//');         
check_v "$1" "$tmpdir";  shift;;
-   -o|--output)            output="$2";                                  
check_v "$1" "$output"; shift;shift;;
-   -o=*|--output=*)        output="${1#*=}";                             
check_v "$1" "$output"; shift;;
-   -o*)                    output=$(echo "$1" | sed -e's/-o//');         
check_v "$1" "$output"; shift;;
+    --stack-operator) stack_operator="$2";                        check_v "$1" 
"$stack_operator";  shift;shift;;
+    --stack-operator=*) stack_operator="${1#*=}";                 check_v "$1" 
"$stack_operator";  shift;;
+    -k|--keeptmp)           keeptmp=1; shift;;
+    -k*|--keeptmp=*)        on_off_option_error --keeptmp -k;;
+    -t|--tmpdir)            tmpdir="$2";                                  
check_v "$1" "$tmpdir";  shift;shift;;
+    -t=*|--tmpdir=*)        tmpdir="${1#*=}";                             
check_v "$1" "$tmpdir";  shift;;
+    -t*)                    tmpdir=$(echo "$1" | sed -e's/-t//');         
check_v "$1" "$tmpdir";  shift;;
 
     # Non-operating options.
     -q|--quiet)             quiet="--quiet"; shift;;
@@ -286,8 +306,28 @@ fi
 if [ x"$width" = x ]; then
     echo "$scriptname: no stack width given to '--width'"; exit 1
 fi
+if [ x"$ctype" = x ]; then
+    echo "$scriptname: no projection given to '--ctype'"; exit 1
+fi
 if [ x"$center" = x ]; then
     echo "$scriptname: no stack center given to '--center'"; exit 1
+else
+    ncenter=$(echo $center | awk 'BEGIN{FS=","}\
+                                  {for(i=1;i<=NF;++i) c+=$i!=""}\
+                                  END{print c}')
+    if [ x$ncenter != x2 ]; then
+        cat <<EOF
+$scriptname: ERROR: '--center' (or '-c') only takes two values, but $ncenter 
value(s) ywere given in '$center'
+EOF
+        exit 1
+    fi
+fi
+ndither=$(asttable $cat --info-num-rows)
+if [ x$ndither = x0 ]; then
+        cat <<EOF
+$scriptname: ERROR: $cat: input dither pointing table is empty! It should 
contain at least one row, containing two columns for the RA and Dec of each 
pointing of the dither pattern. Please see the documentation with this command: 
'info astscript-dither-simulate'
+EOF
+        exit 1
 fi
 
 
@@ -327,18 +367,18 @@ fi
 # this configuration file (and the variables within it).
 counter=1;
 config=$tmpdir/dither-simulate.conf
-if astfits $cat &> /dev/null; then
-    ndither=$(astfits $cat --hdu=$hdu --keyvalue=NAXIS2 --quiet)
-else
-    ndither=$(awk '!/^#/ && NF>1' $cat | wc -l)
-fi
 echo "img = $img" > $config
+echo "ctype = $ctype" >> $config
 echo "width = $width" >> $config
 echo "quiet = $quiet" >> $config
 echo "center = $center" >> $config
 echo "output = $output" >> $config
 echo "imghdu = $imghdu" >> $config
+echo "scriptname = $scriptname" >> $config
+echo "stack-operator = $stack_operator" >> $config
 echo "dithers = $(seq $ndither | tr '\n' ' ')" >> $config
+echo "hook-warp-before=$hook_warp_before" >> $config
+echo "hook-warp-after=$hook_warp_after" >> $config
 if [ $widthinpix = 1 ]; then
     echo "widthinpix = --widthinpix" >> $config
 else
@@ -380,10 +420,12 @@ fi
 # Call the Makefile
 # -----------------
 #
-# Here, Makefile is invoked.
-if [ x$mksrc = x ]; then
-    mksrc=$installdir/dither-simulate.mk
-fi
+# Make is invoked with the requested Makefile. We cannot put 'tmpdir' into
+# the configuration file because the configuration file is within the
+# temporary directory. Also, the number of threads should be given when
+# calling Make. Otherwise, all other settings should be taken inside the
+# configuration file.
+if [ x"$mksrc" = x ]; then mksrc=$installdir/dither-simulate.mk; fi
 make -f $mksrc tmpdir=$tmpdir --jobs=$numthreads
 
 
diff --git a/bin/script/ds9-region.sh b/bin/script/ds9-region.sh
index 352fa13f..fee83504 100644
--- a/bin/script/ds9-region.sh
+++ b/bin/script/ds9-region.sh
@@ -254,7 +254,9 @@ if [ x"$col" = x ]; then
     echo "$scriptname: no columns specified, you can use '--column' (or '-c')"
     exit 1
 else
-    ncols=$(echo $col | awk 'BEGIN{FS=","}END{print NF}')
+    ncols=$(echo $col | awk 'BEGIN{FS=","} \
+                             {for(i=1;i<=NF;++i) c+=$i!=""} \
+                             END{print c}')
     if [ x$ncols != x2 ]; then
         echo "$scriptname: only two columns should be given with '--column' 
(or '-c'), but $ncols were given"
         exit 1
diff --git a/bin/script/psf-scale-factor.sh b/bin/script/psf-scale-factor.sh
index ccef6dce..b390b0e8 100644
--- a/bin/script/psf-scale-factor.sh
+++ b/bin/script/psf-scale-factor.sh
@@ -362,10 +362,12 @@ $scriptname: ERROR: no center coordinates provided. You 
can specify the object's
 EOF
     exit 1
 else
-    ncenter=$(echo $center | awk 'BEGIN{FS=","}END{print NF}')
+    ncenter=$(echo $center | awk 'BEGIN{FS=","} \
+                                  {for(i=1;i<=NF;++i) c+=$i!=""} \
+                                  END{print c}')
     if [ x$ncenter != x2 ]; then
         cat <<EOF
-$scriptname: ERROR: '--center' (or '-c') only take two values, but $ncenter 
were given in '$center'
+$scriptname: ERROR: '--center' (or '-c') only takes two values, but $ncenter 
were given in '$center'
 EOF
         exit 1
     fi
diff --git a/bin/script/psf-select-stars.sh b/bin/script/psf-select-stars.sh
index c0df1b1e..55c71b6c 100644
--- a/bin/script/psf-select-stars.sh
+++ b/bin/script/psf-select-stars.sh
@@ -398,10 +398,12 @@ $scriptname: ERROR:no magnitude range provided. Values to 
'--magnituderange' (or
 EOF
     exit 1
 else
-    nmagrange=$(echo $magnituderange | awk 'BEGIN{FS=","}END{print NF}')
-    if [ x$nmagrange != x2 ]; then
+    nmagrng=$(echo $magnituderange | awk 'BEGIN{FS=","} \
+                                          {for(i=1;i<=NF;++i) c+=$i!=""} \
+                                          END{print c}')
+    if [ x$nmagrng != x2 ]; then
         cat<<EOF
-$scriptname: ERROR: '--magnituderange' (or '-m') only take two values, but 
$nmagrange were given
+$scriptname: ERROR: '--magnituderange' (or '-m') only takes two values, but 
$nmagrng were given
 EOF
         exit 1
     fi
@@ -411,10 +413,13 @@ fi
 if [ x$parallaxanderrorcolumn = x ]; then
     columnquery=$racolumn,$deccolumn,$field
 else
-    nmparallax=$(echo $parallaxanderrorcolumn | awk 'BEGIN{FS=","}END{print 
NF}')
+    nmparallax=$(echo $parallaxanderrorcolumn \
+                      | awk 'BEGIN{FS=","} \
+                                  {for(i=1;i<=NF;++i) c+=$i!=""} \
+                                  END{print c}')
     if [ x$nmparallax != x2 ]; then
         cat<<EOF
-$scriptname: ERROR: '--parallaxanderrorcolumn' (or '-p') only take two values, 
but $nmparallax were given
+$scriptname: ERROR: '--parallaxanderrorcolumn' (or '-p') only takes two 
values, but $nmparallax were given
 EOF
         exit 1
     else
diff --git a/bin/script/psf-stamp.sh b/bin/script/psf-stamp.sh
index 65c041ff..5d7beec6 100644
--- a/bin/script/psf-stamp.sh
+++ b/bin/script/psf-stamp.sh
@@ -391,10 +391,12 @@ $scriptname: WARNING: no center provided ('--center' or 
'-c'). Considering that
 EOF
     fi
 else
-    ncenter=$(echo $center | awk 'BEGIN{FS=","}END{print NF}')
+    ncenter=$(echo $center | awk 'BEGIN{FS=","} \
+                                  {for(i=1;i<=NF;++i) c+=$i!=""} \
+                                  END{print c}')
     if [ x$ncenter != x2 ]; then
         cat <<EOF
-$scriptname: ERROR: '--center' (or '-c') only take two values, but $ncenter 
were given in '$center'
+$scriptname: ERROR: '--center' (or '-c') only takes two values, but $ncenter 
were given in '$center'
 EOF
         exit 1
     fi
diff --git a/bin/script/psf-subtract.sh b/bin/script/psf-subtract.sh
index 03f47dc9..3f5335b6 100644
--- a/bin/script/psf-subtract.sh
+++ b/bin/script/psf-subtract.sh
@@ -355,7 +355,9 @@ $scriptname: ERROR: no center coordinates provided (for the 
star that should be
 EOF
     exit 1
 else
-    ncenter=$(echo $center | awk 'BEGIN{FS=","}END{print NF}')
+    ncenter=$(echo $center | awk 'BEGIN{FS=","} \
+                                  {for(i=1;i<=NF;++i) c+=$i!=""} \
+                                  END{print c}')
     if [ x$ncenter != x2 ]; then
         cat <<EOF
 $scriptname: ERROR: $scriptname: '--center' (or '-c') only takes two values, 
but $ncenter were given
diff --git a/bin/script/radial-profile.sh b/bin/script/radial-profile.sh
index e3edfee0..84c2af80 100644
--- a/bin/script/radial-profile.sh
+++ b/bin/script/radial-profile.sh
@@ -322,9 +322,11 @@ fi
 
 # If a '--center' has been given, make sure it only has two numbers.
 if [ x"$center" != x ]; then
-    ncenter=$(echo $center | awk 'BEGIN{FS=","}END{print NF}')
+    ncenter=$(echo $center | awk 'BEGIN{FS=","} \
+                                  {for(i=1;i<=NF;++i) c+=$i!=""} \
+                                  END{print c}')
     if [ x$ncenter != x2 ]; then
-        echo "$scriptname: '--center' (or '-c') only take two values, but 
$ncenter were given"
+        echo "$scriptname: '--center' (or '-c') only takes two values, but 
$ncenter were given in '$center'"
         exit 1
     fi
 fi
@@ -341,9 +343,11 @@ fi
 
 # If a '--azimuth' has been given, make sure it only has two numbers.
 if [ x"$azimuth" != x ]; then
-    nazimuth=$(echo $azimuth | awk 'BEGIN{FS=","}END{print NF}')
+    nazimuth=$(echo $azimuth | awk 'BEGIN{FS=","} \
+                                    {for(i=1;i<=NF;++i) c+=$i!=""} \
+                                    END{print c}')
     if [ x$nazimuth != x2 ]; then
-        echo "$scriptname: '--azimuth' (or '-a') only take two values, but 
$nazimuth were given"
+        echo "$scriptname: '--azimuth' (or '-a') only takes two values, but 
$nazimuth were given"
         exit 1
     fi
 fi
diff --git a/bin/script/zeropoint.sh b/bin/script/zeropoint.sh
index 2a7f9ef5..3338539e 100644
--- a/bin/script/zeropoint.sh
+++ b/bin/script/zeropoint.sh
@@ -370,10 +370,12 @@ fi
 
 # If the brighter and fainter range of magnitude are not given at all.
 if [ x$magnituderange != x ]; then
-    nmagrange=$(echo $magnituderange | awk 'BEGIN{FS=","}END{print NF}')
-    if [ x$nmagrange != x2 ]; then
+    nmagrng=$(echo $magnituderange | awk 'BEGIN{FS=","} \
+                                          {for(i=1;i<=NF;++i) c+=$i!=""} \
+                                          END{print c}')
+    if [ x$nmagrng != x2 ]; then
         cat<<EOF
-$scriptname: ERROR: '--magnituderange' (or '-m') only take two values, but 
$nmagrange were given
+$scriptname: ERROR: '--magnituderange' (or '-m') only takes two values, but 
$nmagrng were given
 EOF
         exit 1
     fi
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 5150aa0d..e49b7199 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -108,15 +108,16 @@ A copy of the license is included in the section entitled 
``GNU Free Documentati
 * astwarp: (gnuastro)Invoking astwarp. Options to Warp.
 
 * astscript: (gnuastro)Installed scripts. Gnuastro's installed scripts.
-* astscript-sort-by-night: (gnuastro)Invoking astscript-sort-by-night. Options 
to this script
-* astscript-radial-profile: (gnuastro)Invoking astscript-radial-profile. 
Options to this script
+* astscript-dither-simulate: (gnuastro)Invoking astscript-dither-simulate. 
Options to this script
 * astscript-ds9-region: (gnuastro)Invoking astscript-ds9-region. Options to 
this script
 * astscript-fits-view: (gnuastro)Invoking astscript-fits-view. Options to this 
script
+* astscript-psf-scale-factor: (gnuastro)Invoking astscript-psf-scale-factor. 
Options to this script
 * astscript-psf-select-stars: (gnuastro)Invoking astscript-psf-select-stars. 
Options to this script
 * astscript-psf-stamp: (gnuastro)Invoking astscript-psf-stamp. Options to this 
script
-* astscript-psf-unite: (gnuastro)Invoking astscript-psf-unite. Options to this 
script
-* astscript-psf-scale-factor: (gnuastro)Invoking astscript-psf-scale-factor. 
Options to this script
 * astscript-psf-subtract: (gnuastro)Invoking astscript-psf-subtract. Options 
to this script
+* astscript-psf-unite: (gnuastro)Invoking astscript-psf-unite. Options to this 
script
+* astscript-radial-profile: (gnuastro)Invoking astscript-radial-profile. 
Options to this script
+* astscript-sort-by-night: (gnuastro)Invoking astscript-sort-by-night. Options 
to this script
 * astscript-zeropoint: (gnuastro)Invoking astscript-zeropoint. Options to this 
script
 @end direntry
 
@@ -274,6 +275,7 @@ Tutorials
 * Sufi simulates a detection::  Simulating a detection.
 * Detecting lines and extracting spectra in 3D data::  Extracting spectra and 
emission line properties.
 * Color channels in same pixel grid::  Aligning images to same grid to build 
color image.
+* Moire pattern in stacking and its correction::  How to avoid this grid-based 
artifact.
 * Zero point of an image::      Estimate the zero point of an image.
 * Dither pattern design::       Simulate the output image of a given dither 
pattern.
 
@@ -337,6 +339,10 @@ Zero point of an image
 * Zero point tutorial with reference image::  Using a reference image.
 * Zero point tutorial with reference catalog::  Using a reference catalog.
 
+Dither pattern design
+
+* Triming vignetted area::      Effect of triming the edges on your dither 
pattern.
+
 Installation
 
 * Dependencies::                Necessary packages for Gnuastro.
@@ -583,7 +589,6 @@ Warp
 * Linear warping basics::       Basics of coordinate transformation.
 * Merging multiple warpings::   How to merge multiple matrices.
 * Resampling::                  Warping an image is re-sampling it.
-* Moire pattern and its correction::  Spatial resonance of the grid pattern on 
output.
 * Invoking astwarp::            Arguments and options for Warp.
 
 Invoking Warp
@@ -2020,6 +2025,7 @@ But they need to be as realistic as possible, so this 
tutorial is dedicated to t
 There are other tutorials also, on things that are commonly necessary in 
astronomical research:
 In @ref{Detecting lines and extracting spectra in 3D data}, we use MUSE cubes 
(an IFU dataset) to show how you can subtract the continuum, detect 
emission-line features, extract spectra and build pseudo narrow-band images.
 In @ref{Color channels in same pixel grid} we demonstrate how you can warp 
multiple images into a single pixel grid (often necessary with mult-wavelength 
data), and build a single color image.
+In @ref{Moire pattern in stacking and its correction} we show how you can 
avoid the un-wanted Moir@'e pattern which happens when warping separate 
exposures to build a stacked/co-add deeper image.
 In @ref{Zero point of an image} we review the process of estimating the zero 
point of an image using a reference image or catalog.
 Finally, in @ref{Dither pattern design} we show the process by which you can 
simulate a dither pattern to find the best observing strategy for your next 
exciting scientific project.
 
@@ -2036,6 +2042,7 @@ For an explanation of the conventions we use in the 
example codes through the bo
 * Sufi simulates a detection::  Simulating a detection.
 * Detecting lines and extracting spectra in 3D data::  Extracting spectra and 
emission line properties.
 * Color channels in same pixel grid::  Aligning images to same grid to build 
color image.
+* Moire pattern in stacking and its correction::  How to avoid this grid-based 
artifact.
 * Zero point of an image::      Estimate the zero point of an image.
 * Dither pattern design::       Simulate the output image of a given dither 
pattern.
 @end menu
@@ -8691,7 +8698,7 @@ Click on the scroll-down menu in front of ``Table'' and 
select @file{2: collapse
 Afterwards, you will see the optimized pseudo-narrow-band image radial profile 
as blue points.
 @end enumerate
 
-@node Color channels in same pixel grid, Zero point of an image, Detecting 
lines and extracting spectra in 3D data, Tutorials
+@node Color channels in same pixel grid, Moire pattern in stacking and its 
correction, Detecting lines and extracting spectra in 3D data, Tutorials
 @section Color channels in same pixel grid
 
 In order to use different images as color channels, it is important that the 
images be properly aligned and on the same pixel grid.
@@ -8758,7 +8765,230 @@ This shows how green and red channels have been 
slightly shifted to put your ast
 If you don't want to have those, or if you want the outer parts of the final 
image (where there was no data) to be white, some more complex commands are 
necessary.
 We'll leave those as an exercise for you to try your self using @ref{Warp} 
and/or @ref{Crop} to pre-process the inputs before converting it to a color 
image.
 
-@node Zero point of an image, Dither pattern design, Color channels in same 
pixel grid, Tutorials
+@node Moire pattern in stacking and its correction, Zero point of an image, 
Color channels in same pixel grid, Tutorials
+@section Moir@'e pattern in stacking and its correction
+
+@cindex Moir@'e pattern or fringes
+After warping some images with the default mode of Warp (see @ref{Align pixels 
with WCS considering distortions}) you may notice that the background noise is 
no longer flat.
+Some regions will be smoother and some will be sharper; depending on the 
orientation and distortion of the input/output pixel grids.
+This is due to the @url{https://en.wikipedia.org/wiki/Moir%C3%A9_pattern, 
Moir@'e pattern}, which is especially noticeable/significant when two slightly 
different grids are super-imposed.
+
+With the commands below, we'll download a single exposure image from the 
@url{https://www.j-plus.es,J-PLUS survey} and run Warp (on a @mymath{8\times8} 
arcmin@mymath{^2} region to speed it up the demos here).
+Finally, we'll open the image to visually see the artificial Moir@'e pattern 
on the warped image.
+
+@example
+## Download the image (73.7 MB containing an 9216x9232 pixel image)
+$ jplusdr2=http://archive.cefca.es/catalogues/vo/siap/jplus-dr2/reduced
+$ wget $jplusdr2/get_fits?id=771463 -Ojplus-exp1.fits.fz
+
+## Align a small part of it with the sky coordinates.
+$ astwarp jplus-exp1.fits.fz --center=107.62920,39.72472 \
+          --width=8/60 -ojplus-e1.fits
+
+## Open the aligned region with DS9
+$ astscript-fits-view jplus-e1.fits
+@end example
+
+In the opened DS9 window, you can see the Moir@'e pattern as wave-like 
patterns in the noise: some parts of the noise are more smooth and some parts 
are more sharp.
+Right in the center of the image is a blob of sharp noise.
+Warp has the @option{--checkmaxfrac} option for direct inspection of the 
Moir@'e pattern (described with the other options in @ref{Align pixels with WCS 
considering distortions}).
+When run with this option, an extra HDU (called @code{MAX-FRAC}) will be added 
to the output.
+The image in this HDU has the same size as the output.
+However, each output pixel will contain the largest (maximum) fraction of area 
that it covered over the input pixel grid.
+So if an output pixel has a value of 0.9, this shows that it covered 
@mymath{90\%} of an input pixel.
+Let's run Warp with @option{--checkmaxfrac} and see the output (after DS9 
opens, in the ``Cube'' window, flip between the first and second HDUs):
+
+@example
+$ astwarp jplus-exp1.fits.fz --center=107.62920,39.72472 \
+          --width=8/60 -ojplus-e1.fits --checkmaxfrac
+
+$ astscript-fits-view jplus-e1.fits
+@end example
+
+By comparing the first and second HDUs/extensions, you will clearly see that 
the regions with a sharp noise pattern fall exactly on parts of the 
@code{MAX-FRAC} extension with values larger than 0.5.
+In other words, output pixels where one input pixel contributed more than half 
of the its value.
+As this fraction increases, the sharpness also increases because a single 
input pixel's value dominates the value of the output pixel.
+On the other hand, when this value is small, we see that many input pixels 
contribute to that output pixel.
+Since many input pixels contribute to an output pixel, it acts like a 
convolution, hence that output pixel becomes smoother (see @ref{Spatial domain 
convolution}).
+Let's have a look at the distribution of the @code{MAX-FRAC} pixel values:
+
+@example
+$ aststatistics jplus-e1.fits -hMAX-FRAC
+Statistics (GNU Astronomy Utilities) @value{VERSION}
+-------
+Input: jplus-e1.fits (hdu: MAX-FRAC)
+-------
+  Number of elements:                      744769
+  Minimum:                                 0.250213461
+  Maximum:                                 0.9987495374
+  Mode:                                    0.5034223567
+  Mode quantile:                           0.3773819498
+  Median:                                  0.5520805544
+  Mean:                                    0.5693956458
+  Standard deviation:                      0.1554693738
+-------
+Histogram:
+ |                      ***
+ |                   **********
+ |                 *****************
+ |              ************************
+ |           *******************************
+ |         **************************************
+ |       *********************************************
+ |     ****************************************************
+ |   ***********************************************************
+ | ******************************************************************
+ |**********************************************************************
+ |----------------------------------------------------------------------
+@end example
+
+The smallest value is 0.25 (=1/4), showing that 4 input pixels contributed to 
the output pixels value.
+While the maximum is almost 1.0, showing that a single input pixel defined the 
output pixel value.
+You can also see that the most probable value (the mode) is 0.5, and that the 
distribution is positively skewed.
+
+@cindex Pixel scale
+@cindex @code{CDELT}
+This is a well-known problem in astronomical imaging and professional 
photography.
+If you only have a single image (that is already taken!), you can undersample 
the input: set the angular size of the output pixels to be larger than the 
input.
+This will decrease the resolution of your image, but will ensure that 
pixel-mixing will always happen.
+In the example below we are setting the output pixel scale (which is known as 
@code{CDELT} in the FITS standard) to @mymath{1/0.5=2} of the input's.
+In other words each output pixel edge will cover double the input pixel's edge 
on the sky, and the output's number of pixels in each dimension will be half of 
the previous output.
+
+@example
+$ cdelt=$(astfits jplus-exp1.fits.fz --pixelscale -q \
+                  | awk '@{print $1@}')
+$ astwarp jplus-exp1.fits.fz --center=107.62920,39.72472 \
+          --width=8/60 -ojplus-e1.fits --cdelt=$cdelt/0.5 \
+          --checkmaxfrac
+@end example
+
+In the first extension, you can hardly see any Moir@'e pattern in the noise.
+When you go to the next (@code{MAX-FRAC}) extension, you will see that almost 
all the pixels have a value of 1.
+Of course, decreasing the resolution by half is a little too drastic.
+Depending on your image, you may be able to reach a sufficiently good result 
without such a drastic degrading of the input image.
+For example, if you want an output pixel scale that is just 1.5 times larger 
than the input, you can divide the original coordinate-delta (or ``cdelt'') by 
@mymath{1/1.5=0.6666} and try again.
+In the @code{MAX-FRAC} extension, you will see that the range of pixel values 
is now between 0.56 to 1.0 (recall that originally, this was between 0.25 and 
1.0).
+This shows that the pixels are more similarly mixed and in fact, when you look 
at the actual warped image, you can hardly distinguish any Moir@'e pattern in 
the noise.
+
+@cindex Stacking
+@cindex Dithering
+@cindex Coaddition
+However, deep astronomical data are usually built by several exposures 
(images), not a single one.
+Each image is also taken by (slightly) shifting the telescope compared to the 
previous exposure.
+This shift is known as ``dithering''.
+We do this for many reasons (for example tracking errors in the telescope, 
high background values, removing the effect of bad pixels or those affected by 
cosmic rays, robust flat pattern measurement, etc.@footnote{E.g., 
@url{https://www.stsci.edu/hst/instrumentation/wfc3/proposing/dithering-strategies}}).
+One of those ``etc.'' reasons is to correct the Moir@'e pattern in the final 
coadded deep image.
+
+The Moir@'e pattern is fixed to the grid of the image, slightly shifting the 
telescope will result in the pattern appearing in different parts of the sky.
+Therefore when we later stack, or coadd, the separate exposures into a deep 
image, the Moir@'e pattern will be decreased there.
+However, dithering has possible drawbacks based on the scientific goal.
+For example when observing time-variable phenomena where cutting the exposures 
to several shorter ones is not feasible.
+If this is not the case for you (for example in galaxy evolution), continue 
with the rest of this section.
+
+Because we have multiple exposures that are slightly (sub-pixel) shifted, we 
can also increase the spatial resolution of the output.
+For example, let's set the output coordinate-delta (or pixel scale) to be 1/2 
of the input.
+In other words, the number of pixels in each dimension of the output is double 
the first Warp command of this section:
+
+@example
+$ astwarp jplus-exp1.fits.fz --center=107.62920,39.72472 \
+          --width=8/60 -ojplus-e1.fits --cdelt=$cdelt/2 \
+          --checkmaxfrac
+
+$ aststatistics jplus-e1.fits -hMAX-FRAC --minimum --maximum
+0.06263604388 0.2506802701
+
+$ astscript-fits-view jplus-e1.fits
+@end example
+
+From the last command, you see that like the previous change in 
@option{--cdelt}, the range of @code{MAX-FRAC} has decreased.
+However, when you look at the warped image and the @code{MAX-FRAC} image with 
the last command, you still visually see the Moir@'e pattern in the noise 
(although it has significantly decreased compared to the original resolution).
+It is still present because 2 is an exact multiple of 1.
+Let's try increasing the resolution (oversampling) by a factor of 1.25 (which 
isn't an exact multiple of 1):
+
+@example
+$ astwarp jplus-exp1.fits.fz --center=107.62920,39.72472 \
+          --width=8/60 -ojplus-e1.fits --cdelt=$cdelt/1.25 \
+          --checkmaxfrac
+$ astscript-fits-view jplus-e1.fits
+@end example
+
+You don't see any Moir@'e pattern in the noise any more, but when you look at 
the @code{MAX-FRAC} extension, you see it is very different from the ones you 
had seen before.
+In the previous @code{MAX-FRAC} image, you could see large blobs of similar 
values.
+But here, you see that the variation is almost on a pixel scale, and the 
difference between one pixel to the next is not significant.
+This is why you don't see any Moir@'e pattern in the warped image.
+
+In J-PLUS, each part of the sky was observed with a three-point dithering 
pattern.
+Let's download the other two exposures and warp the same region of the sky to 
the same pixel grid (using the @option{--gridfile} feature).
+Then, let's open all three cropped images in one DS9 instance:
+
+@example
+$ wget $jplusdr2/get_fits?id=771465 -Ojplus-exp2.fits.fz
+$ wget $jplusdr2/get_fits?id=771467 -Ojplus-exp3.fits.fz
+
+$ astwarp jplus-exp2.fits.fz --gridfile jplus-e1.fits \
+          -o jplus-e2.fits --checkmaxfrac
+$ astwarp jplus-exp3.fits.fz --gridfile jplus-e1.fits \
+          -o jplus-e3.fits --checkmaxfrac
+
+$ astscript-fits-view jplus-e*.fits
+@end example
+
+@noindent
+In the three warped images, you don't see any Moir@'e pattern, so far so 
good...
+now, take the following steps:
+@enumerate
+@item
+Click on the ``Frame'' button (in the top row of buttons just on top of the 
image), and select the ``Single'' button in the bottom row.
+@item
+Open the ``Zoom'' menu, and select ``Zoom 16''.
+@item
+In the bottom row of buttons right on top of the image, press the ``next'' 
button to flip through each exposure's @code{MAX-FRAC} extension.
+@item
+Focus your eyes on the pixels with the largest value (white colored pixels), 
while pressing the ``next'' button to flip between the exposures.
+You will see that in each exposure they cover different pixels.
+@end enumerate
+
+The exercise above shows that the effect varying smoothing level (that had 
already shrank to a per-pixel level) will be further decreased after we stack 
the images.
+So let's stack these three images with the commands below.
+First, we need to remove the sky-level from each image using 
@ref{NoiseChisel}, then we'll stack the @code{INPUT-NO-SKY} extensions using 
sigma-clipping (to reject outliers by @ref{Sigma clipping}, using the 
@ref{Stacking operators}).
+
+@example
+$ astnoisechisel jplus-e1.fits -ojplus-nc1.fits
+$ astnoisechisel jplus-e2.fits -ojplus-nc2.fits
+$ astnoisechisel jplus-e3.fits -ojplus-nc3.fits
+
+$ astarithmetic jplus-nc*.fits 3 5 0.2 sigclip-mean \
+                -gINPUT-NO-SKY -ojplus-stack.fits
+
+$ astscript-fits-view jplus-nc*.fits jplus-stack.fits
+@end example
+
+@noindent
+After opening the individual exposures and the final stack with the last 
command, take the following steps to see the comparisons properly:
+@enumerate
+@item
+Click on the stack image so it is selected.
+@item
+Go to the ``Frame'' menu, then the ``Lock'' item, then activate ``Scale and 
Limits''.
+@item
+Scroll your mouse or touchpad to zoom into the image.
+@end enumerate
+
+@noindent
+You clearly see that the stacked image is deeper and that there is no Moir@'e 
pattern, while you have slightly @emph{improved} the spatial resolution of the 
output compared to the input.
+In case you want the stack to have the original pixel resolution, you just 
need one more warp:
+
+@example
+$ astwarp jplus-stack.fits --cdelt=$cdelt -ojplus-stack-origres.fits
+@end example
+
+For optimal results, the oversampling should be determined by the dithering 
pattern of the observation:
+For example if you only have two dither points, you want the pixels with 
maximum value in the @code{MAX-FRAC} image of one exposure to fall on those 
with a minimum value in the other exposure.
+Ideally, many more dither points should be chosen when you are planning your 
observation (not just for the Moir@'e pattern, but also for all the other 
reasons mentioned above).
+Based on the dithering pattern, you want to select the increased resolution 
such that the maximum @code{MAX-FRAC} values fall on every different pixel of 
the output grid for each exposure.
+
+
+@node Zero point of an image, Dither pattern design, Moire pattern in stacking 
and its correction, Tutorials
 @section Zero point of an image
 
 The ``zero point'' of an image is astronomical jargon for the calibration 
factor of its pixel values; allowing us to convert the raw pixel values to 
physical units.
@@ -9296,28 +9526,37 @@ $ astscript-fits-view jplus-zeropoint.fits 
jplus-zeropoint-cat.fits \
 Deciding a suitable dithering pattern is one of the most important steps when 
planning your observation strategy.
 Dithering is the process of moving each exposure compared to the previous one 
and is done for several reasons like increasing resolution, expending the area 
of the observation and etc.
 For a more complete introduction to dithering, see @ref{Dithering pattern 
simulation}.
-Gnuastro has a script (@command{astscript-dither-simulate}) for simplifying 
the process of choosing the best dither pattern to optimizing your observation 
strategy for your scientific goal.
 
-In this tutorial, let's assume you want to observe 
@url{https://en.wikipedia.org/wiki/Messier_94, M94} in the H-alpha and rSDSS 
filters@footnote{For the full list of available filters, see the 
@url{https://oaj.cefca.es/telescopes/t80cam, T80Cam description}.} (to study 
the extended star formation in the outer rings of this beautiful galaxy!).
+In this tutorial, we'll simulate a hypothetical dither pattern using 
Gnuastro's @command{astscript-dither-simulate} installed script.
+Let's assume you want to observe 
@url{https://en.wikipedia.org/wiki/Messier_94, M94} in the H-alpha and rSDSS 
filters (to study the extended star formation in the outer rings of this 
beautiful galaxy!).
 Including the outer parts of the rings, the galaxy is half a degree in 
diameter!
-This is very large, and you want to design a dither pattern that will cover 
this area with the maximum depth!
+This is very large, and you want to design a dither pattern that will cover 
this area efficiently!
 Therefore, you need an instrument with a large field of view.
+
+@cartouche
+@noindent
+@strong{Do Not start with this tutorial:} If you are new to Gnuastro and have 
not already completed @ref{General program usage tutorial}, we recommend going 
through that tutorial before starting this one.
+Basic features like access to this book on the command-line, the configuration 
files of Gnuastro's programs, benefiting from the modular nature of the 
programs, viewing multi-extension FITS files, and many others are discussed in 
more detail there.
+@end cartouche
+
 Let's assume that after some searching, you decide to write a proposal for the 
@url{https://oaj.cefca.es/telescopes/jast80, JAST80 telescope} at the 
@url{https://oaj.cefca.es, Observatorio Astrofísico de Javalambre}, 
OAJ@footnote{For full disclosure, Gnuastro is being developed at CEFCA (Centro 
de Estudios de F@'isica del Cosmos de Arag@'on); which also hosts OAJ.}, in 
Teruel (Spain).
-The field of view of this telescope's camera is almost 1.5 degrees wide, 
nicely fitting M94!
+The field of view of this telescope's camera is almost 1.4 degrees wide, 
nicely fitting M94!
+It also has these two filters that you need@footnote{For the full list of 
available filters, see the @url{https://oaj.cefca.es/telescopes/t80cam, T80Cam 
description}.}.
 
 Before we start, as described in @ref{Dithering pattern simulation}, it is 
just important to remember that the ideal dither pattern depends primarily on 
your scientific objective, as well as the limitations of the instrument you are 
observing with.
 Therefore, there is no single dither pattern for all purposes.
 However, the tools, methods, criteria or logic to check if your dither pattern 
satisfies your scientific requirement are similar.
 Therefore, you can use the same methods, tools or logic here to simulate or 
verify that your dither pattern will produce the products you expect after the 
observation.
 The hypothetical scenario above is just an example to show the usage.
-As with any tutorial, do not blindly follow the same final solution for any 
scenario; this is just an example to show you @emph{how to} find your own 
solution, not to give you the universal solution to any scenario!
+As with any tutorial, do not blindly follow the same final solution for any 
scenario; this is just an example to show you @emph{how to} find your own 
solution, not to give you the universal solution to any scenario.
 
 To start simulating a dither pattern for a certain telescope, you just need a 
single-exposure image of that telescope with WCS information.
 In other words, after astrometry, but before warping into any other pixel grid 
(to combine into a deeper stack).
 The image will give us the default number of the camera's pixels, its pixel 
scale (width of pixel in arcseconds) and the camera distortion.
 These are reference parameters that are independent of the position of the 
image on the sky.
 
-Because the actual position of the reference image is irrelevant, let's assume 
that in a previous project, persumably on 
@url{https://en.wikipedia.org/wiki/NGC_4395, NGC 4395}, you already had the 
download command of the following single exposure image:
+Because the actual position of the reference image is irrelevant, let's assume 
that in a previous project, persumably on 
@url{https://en.wikipedia.org/wiki/NGC_4395, NGC 4395}, you already had the 
download command of the following single exposure image.
+With the last command, please take a look at this image before continuing and 
explore it.
 
 @example
 $ mkdir dither-tutorial
@@ -9339,18 +9578,21 @@ Therefore, they become publicly available very soon 
after the observation date;
 
 As you see from the image above, the T80Cam images are large (9216 by 9232 
pixels).
 Therefore, to speed up the dither testing, let's down-sample the image above 
by a factor of 10.
-This step is optional and you can safely use the full resolution, which will 
give you a more precise stack, but which will be much slower (maybe good after 
you have an approximate solution on the down-sampled image).
+This step is optional and you can safely use the full resolution, which will 
give you a more precise stack.
+But it will be much slower (maybe good after you have an almost final solution 
on the down-sampled image).
 We will call the output @file{ref.fits} (since it is the ``reference'' for our 
test).
-We are putting these two ``input'' files (to the script) in a dedicated 
directory to keep the running directory clean (be able to easily delete 
temporary/test files for a fresh start with a `@command{rm *.fits}').
+We are putting these two ``input'' files (to the script) in a dedicated 
directory to keep the running directory clean (and be able to easily delete 
temporary/test files for a fresh start with a `@command{rm *.fits}').
 
 @example
 $ astwarp input/jplus-1050345.fits.fz --scale=1/10 -oinput/ref.fits
 @end example
 
-For a first trial, let's create a cross-shaped dither pattern around M94 
(which is centered at its center on the RA and Dec of 192.721250, 41.120556).
+For a first trial, let's create a cross-shaped dither pattern with 5 points 
around M94, which is centered at its center on the RA and Dec of 192.721250, 
41.120556.
 We'll center one exposure on the center of the galaxy, and include 4 more 
exposures that are each 1 arc-minute away along the RA and Dec axes.
 To simplify the actual command later@footnote{Instead of this, later, when you 
called @command{astscript-dither-simulate}, you could pass the 
@option{--racol=1} and @option{--deccol=2} options.
-But having metadata is always preferred (will avoid many bugs/frustrations in 
the long-run!).}, let's also include the column names through two lines of 
metadata.
+But having metadata is always preferred (will avoid many bugs/frustrations in 
the long-run!).}, let's also include the column names in @file{dither.text} 
through two lines of metadata.
+Also note that the @file{dither.txt} file can be made in any manner you like, 
for example, manually or through another programming language, or etc.
+We are using AWK here because it is sufficiently powerful for this job, is a 
very small program and is available on any Unix-based operating system 
(allowing you to easily run your programs on any computer).
 
 @example
 $ step_arcmin=1
@@ -9373,13 +9615,13 @@ $ cat dither.txt
 # Column 1: RA  [deg, f64] Right Ascension
 # Column 2: Dec [deg, f64] Declination
 192.721250 41.120556
-192.804583 41.120556
-192.721250 41.203889
-192.637917 41.120556
-192.721250 41.037223
+192.737917 41.120556
+192.721250 41.137223
+192.704583 41.120556
+192.721250 41.103889
 @end example
 
-We are now ready to generate the exposure map of the dither pattern above 
using the reference image that we made before it.
+We are now ready to generate the exposure map of the dither pattern above 
using the reference image that we downloaded before.
 Let's put the center of our final stack to be on the center of the galaxy, and 
we'll assume the stack has a size of 2 degrees.
 With the second command, you can see the exposure map of the final stack.
 Recall that in this image, each pixel shows the number of input images that 
went into it.
@@ -9392,11 +9634,11 @@ $ astscript-dither-simulate dither.txt 
--output=stack.fits \
 $ astscript-fits-view stack.fits
 @end example
 
-Because the step size is so small (compared to the field of view), we see that 
except for a thin boundary, we almost have 5 exposures over the full field of 
view.
+You will see that except for a thin boundary, we have a depth of 5 exposures 
over the area of the single exposure.
 Let's see what the width of the deepest part of the image is.
 First, we'll use Arithmetic to set all pixels that contain less than 5 
exposures to NaN (the outer pixels).
-In the same Arithmetic command, we'll trim all the blank rows and columns to 
only contain the non-blank region.
-Afterwards, we'll view the deep region with the second command.
+In the same Arithmetic command, we'll trim all the blank rows and columns, so 
the output only contains the pixels that are exposed 5 times.
+With the next command, let's view the deep region
 Finally, with the third command below, we'll use the @option{--skycoverage} 
option of the Fits program to see the coverage of deep part on the sky.
 
 @example
@@ -9407,35 +9649,46 @@ $ astarithmetic stack.fits set-s s s $deep_thresh lt 
nan where trim \
 $ astscript-fits-view deep.fits
 
 $ astfits deep.fits --skycoverage
-...
+Input file: deep.fits (hdu: 1)
+
 Sky coverage by center and (full) width:
   Center: 192.72125      41.120556
   Width:  1.880835157    1.392461166
-...
+
+Sky coverage by range along dimensions:
+  RA       191.7808324    193.6616676
+  DEC      40.42058203    41.81304319
 @end example
 
 @cindex Sky value
 @cindex Flat field
-As we see, the width of this deep field is about 1.4 degrees (in Dec; the 
coverage in RA depends on the Dec).
-This nicely covers the outers parts of M94.
-However, there is a problem: with a step size of 1 arc-minute, the brighter 
central parts of this large galaxy will always be on very similar pixels; 
making it hard to calibrate those pixels properly.
+As we see, the width of this deep field is about 1.4 degrees (in declination); 
the coverage in RA depends on the declination (recall that RA is only defined 
on the equator).
+This area therefore nicely covers the expected outer parts of M94.
+On first thought, it may seem that we are now finished, but that is not the 
case unfortunately!
+
+There is a problem: with a step size of 1 arc-minute, the brighter central 
parts of this large galaxy will always be on very similar pixels; making it 
hard to calibrate those pixels properly.
 If you are interested in the low surface brightness parts of this galaxy, it 
is even worse: the outer parts of the galaxy will always cover similar parts of 
the detector in all the exposures.
 To be able to accurately calibrate the image (in particular to estimate the 
flat field pattern and subtract the sky), you do not want this to happen!
-You want each exposure to cover very different sources of astrophysical 
signal, so you can accurately calibrate the instrument (for example flat field) 
and natural (for example the Sky) artifacts.
+You want each exposure to cover very different sources of astrophysical 
signal, so you can accurately calibrate the artifacts created by the instrument 
(for example flat field) or of natural causes (for example the Sky).
 
 Before we consider other alternatives, let's first get an accurate measure of 
the area that is covered by all 5 exposures.
 A first hint would be to simply multiply the widths along RA and Dec reported 
above: @mymath{1.8808\times1.3924=2.6189} degrees squared.
 
-However, the sky coverage reported above has two caveates:
-1) it doesn't take into account the blank pixels (NaN) that are on the four 
corners of the @file{deep.fits} image.
-2) the differing area of the pixels on the spherical sky in relation to those 
blank values can result in wrong estimations of the area.
+The simple sky coverage calculated by multiplication that reported above has 
two caveates:
+@itemize
+@item
+It doesn't take into account the thin rows/columns of blank pixels (NaN) that 
are on the four edges of the @file{deep.fits} image.
+@item
+The differing area of the pixels on the spherical sky in relation to those 
blank values can result in wrong estimations of the area.
+@end itemize
+
 So far, these blank areas are very small (and do not constitute a large 
portion of the image).
 As a result, these effects are negligible.
 However, as you get more creative with the dither pattern to optimize your 
scientific goal, such blank areas will cover a larger fraction of your final 
stack.
 
 So let's get a very accurate estimation of the area that will not be affected 
by the issues above.
 With the first command below, we'll use the @option{--pixelareaonwcs} option 
of the Fits program that will return the area of each pixel (in pixel units of 
degrees squared).
-After running the second command, please have a look at the output of the 
first:
+After running the second command, please have a look at the produced image:
 
 @example
 $ astfits deep.fits --pixelareaonwcs --output=deep-pix-area.fits
@@ -9444,9 +9697,11 @@ $ astscript-fits-view deep-pix-area.fits
 @end example
 
 @cindex Gnomonic projection
-The gradient you see in this image (that gets slightly curved towards the top 
of the image) is the effect of the default 
@url{https://en.wikipedia.org/wiki/Gnomonic_projection, Gnomonic projection} 
(summarized as @code{TAN} in the FITS WCS standard).
+You see a strong gradient in this image that gets slightly curved towards the 
top of the image.
+This is the effect of the 
@url{https://en.wikipedia.org/wiki/Gnomonic_projection, Gnomonic projection}; 
summarized as @code{TAN} (for ``tangential'') in the FITS WCS standard, the 
most commonly used in optical astronomical surveys and the default in this 
script.
 Since this image is aligned with the celestial coordinates, as we increase the 
declination, the pixel area also increases.
 For a comparison, please run the Fits program with the 
@option{--pixelareaonwcs} option on the originally downloaded 
@file{jplus-1050345.fits.fz} to see the distortion pattern of the camera's 
optics which domintes there.
+
 We can now use Arithmetic to set the areas of all the pixels that were NaN in 
@file{deep.fits} and sum all the values to get an accurate estimate of the area 
we get from this dither pattern:
 
 @example
@@ -9458,58 +9713,133 @@ $ astarithmetic deep-pix-area.fits deep.fits isblank 
nan where -g1 \
 As expected, this is very close to the simple multiplication that we did above.
 But it will allow us to accurately estimate the size of the deep field with 
any ditter pattern.
 
-As mentioned above, M94 is about half a degree in diameter; so let's set 
@code{step_arcmin=15}.
+As mentioned above, this small dither pattern is not good for the reduction of 
data from a large object like M94!
+M94 is about half a degree in diameter; so let's set @code{step_arcmin=15} and 
re-run the steps above.
 This is one quarter of a degree and will put the center of the four exposures 
on the four corners of the M94's main ring.
 You are now ready to repeat the commands above with this changed value.
 
 @cartouche
 @noindent
 @strong{Writing scripts:}
-It is better to write the steps above as a script so you can easily change the 
basic settings and see the output fast.
+From this point on, some of the variables set above will be changed, but the 
commands will not be repeated (unless a change is necessary).
+Therefore, it is better to write the steps above (after downloading the 
reference image) as a script.
+In this way, you can simply change those variables and see the final result 
fast.
 For more on writing scripts, see as described in @ref{Writing scripts to 
automate the steps}.
+Here are some tips:
+@itemize
+@item
+Where the commands are edited/changed, please also update them in your script.
+@item
+Keep all the variables at the top, even if they are used later.
+This allows to easily view or changed them without digging into the script.
+@end itemize
 @end cartouche
 
-After you run the commands above with this single change, you will get a total 
area of 2.1597 degrees squared.
-This is just roughly @mymath{15\%} smaller than the previous area; but it is 
much more easier to calibrate.
-However, since each pointing's center will fall on one edge of the galaxy, M94 
will be present in all the exposures while doing the calibrations.
-We already see a large ring around this galaxy, and when we do a low surface 
brightness optimized reduction, there is a chance that the size of the galaxy 
is much larger.
+After you run the commands above with the change of @code{step_arcmin} above, 
you will get a total area (from counting of per-pixel areas) of approximately 
1.28 degrees squared.
+This is just roughly half the previous area and will barely fit M94!
+To understand the cause, let's have a look at the full stack (not just the 
deepest area):
 
-Ideally, you want your target to be on the four edges/corners of each image.
-This will make sure that a large fraction of each exposure will not be covered 
by your final target, allowing you to clibrate much more accurately.
-Let's try setting @code{step_arcmin=40} (almost half the width of the 
detector).
-You will notice that the area is now 0.05013 degrees squared!
-This is 51 times smaller!
+@example
+$ astscript-fits-view stack.fits
+@end example
 
-Take a look at @file{deep.fits}, and you will see that it is a horizontally 
elongated rectangle!
-To see the cause, have a look at the @file{stack.fits}: the part with 5 
exposures is now very small; covered by a cross-like pattern (which is thicker 
along the horizontal) that is four exposures deep and even a larger square-like 
region which is three exposures deep.
+Compared to the first run (with @code{step_arcmin=1}), we clearly see how 
there are indeed fewer pixels that get photons in all 5 exposures.
+As the area of the deepest part has decreased, the areas with fewer exposures 
have grown.
+Based on the argument above, let's define our deep region to be the pixels 
with 3 or more exposures.
+Please set @code{deep_thresh=3} and re-run the script you have made from the 
commands above.
+You will see that the final (based on pixel-counting) area is now 2.68 degrees 
squared!
+This is (slightly) larger than the first run (with @code{step_arcmin=1})!
 
 The difference between 3 exposures and 5 exposures seems a lot at first.
-But let's calculate how much it actually affects the achieved signal-to-noise 
ratio and the surface brightness limit (for more, see @ref{Quantifying 
measurement limits}).
+But let's calculate how much it actually affects the achieved signal-to-noise 
ratio and the surface brightness limit.
 The surface brightness limit (or upper-limit surface brightness) are both 
calculated by applying the definition of magnitude to the standard deviation of 
the background.
-So let's calculate how much this difference in depth affects the sky standard 
deviation.
+So we should first calculate how much this difference in depth affects the sky 
standard deviation.
+For a complete discussion on the definition of the surface brightness limit, 
see @ref{Quantifying measurement limits}.
 
+@cindex Poisson noise
 Deep images will usually be dominated by @ref{Photon counting noise} (or 
Poisson noise).
-Therefore, if a single exposure image has a sky standard deviation of 
@mymath{\sigma_s}, and we combine @mymath{N} such exposures, the sky standard 
deviation on the stack will be @mymath{\sigma_s/\sqrt{N}}.
+Therefore, if a single exposure image has a sky standard deviation of 
@mymath{\sigma_s}, and we combine @mymath{N} such exposures by taking their 
mean, the final/stacked sky standard deviation (@mymath{\sigma}) will be 
@mymath{\sigma=\sigma_s/\sqrt{N}}.
 As a result, the surface brightness limit between the regions with @mymath{N} 
exposures and @mymath{M} exposures differs by @mymath{2.5\times 
log_{10}(\sqrt{N/M}) = 1.25\times log_{10}(N/M)} magnitudes.
-If we set @mymath{N=3} and @mymath{M=5}, we get a surface brightness magnitude 
difference of 0.27!
+If we set @mymath{N=3} and @mymath{M=5}, we get a surface brightness magnitude 
difference of 0.28!
+
+This is a very small difference; given all the other sources of error that 
will be present; and the improvement we gain by the calibrations of artifacts 
mentioned above.
+Therefore at the cost of decreasing our surface brightness limit by 0.28 
magnitudes, we are now able to calibrate the individual exposures much better, 
and even cover a larger area!
+
+The argument above didn't involve any image and was primarily theoretical.
+For the more visually-inclined readers, let's add raw Gaussian noise (with a 
@mymath{\sigma} of 100 counts) over each simulated exposure.
+We will then instruct the script to stack them as we would stack actual data 
(by taking the sigma-clipped mean).
+The command below is identical to the previous call to the dither simulation 
script with the following differences.
+Note that this is just for demonstration, so you do not need to include this 
in your script (unless you want to see the noisy stack every time).
 
-This is a very small difference (given all the other sources of error that 
will be present).
-Let's see how much we increase our stack area if we set @code{deep_thresh=3}.
-The newly calculated area is 2.6706 degrees squared!
-This is just slightly larger than the first trial (with @code{step_arcmin=1})!
-Therefore at the cost of decreasing our surface brightness limit by 0.27 
magnitudes, we are now able to perfectly calibrate the individual exposures, 
and even cover a larger area!
+@table @option
+@item --output
+We are using a different output name, so we can compare the output of the new 
command with the previous one.
+@item --stack-operator
+This should be one of the Arithmetic program's @ref{Stacking operators}.
+By default the value is @code{sum}; because by default, each pixel of each 
exposure is given a value of 1.
+When stacking is defined through the summation operator, we can obtain the 
exposure map that you have already seen above.
+
+But in this run, we are adding noise to each input exposure (through the hook 
that is described below) and stacking them (as we would stack actual science 
images).
+Since the purpose differs here, we are using this option to change the 
operator.
+
+@item --hook-warp-after
+@cindex Hook (programming)
+This is the most visible difference of this command the previous one.
+Through a ``hook'', you can give any arbitrarily long (series of) command(s) 
that will be added to the processing of this script at a certain location.
+This particular hook gets applied ``after'' the ``warp''ing phase of each 
exposure (when the pixels of each exposure are mapped to the final pixel grid; 
but not yet stacked).
+
+Since the script runs in parallel (the actual work-horse is a Makefile!), you 
can't assume any fixed file name for the input(s) and output.
+Therefore the inputs to, and output(s) of, hooks are some pre-defined shell 
variables; that are written in full-caps to be clear.
+In this case, they are the @code{$WARPED} (input) and @code{$TARGET} (output).
+As you see from the command below, through this hook we are calling the 
Arithmetic program to add noise to all non-zero pixels in the warped image.
+
+After all the images are placed in the same pixel grid, they are stacked in a 
separate step (described in the point above).
+@end table
+
+@example
+$ astscript-dither-simulate dither.txt --output=stack-noised.fits \
+           --img=input/ref.fits --center=$center_ra,$center_dec \
+           --width=2 --stack-operator="3 0.2 sigclip-mean" \
+           --hook-warp-after='astarithmetic $WARPED set-i \
+                                          i i 0 uint8 eq nan where \
+                                          100 mknoise-sigma \
+                                           --output=$TARGET'
+
+$ astscript-fits-view stack.fits stack-noised.fits
+@end example
+
+When you visually compare the two images of the last command above, you will 
see that (at least by eye) it is almost impossible to distinguish the differing 
noise pattern in the regions with 3 exposures from the regions with 5 exposures.
+But the regions with a single exposure are clearly visible!
+This is because the surface brightness limit in the single-exposure regions is 
@mymath{1.25\times\log_{10}(1/5)=-0.87} magnitudes brighter.
+This almost one magnitude difference in surface brightness is significant and 
clearly visible in the stacked image (recall that magnitudes are measured in a 
logarithmic scale).
+
+Thanks to the argument above, we can now have a sufficiently large area with a 
usable depth.
+However, each pointing's center will still contain the central part of the 
galaxy.
+In other words, M94 will be present in all the exposures while doing the 
calibrations.
+Even in not-too-deep observations, we already see a large ring around this 
galaxy.
+When we do a low surface brightness optimized reduction, there is a good 
chance that the size of the galaxy is much larger than that ring.
+This very extended structure will make it hard to do the calibrations on very 
accurate scales.
+Accurate calibration is necessary if you do not want to loose the faint 
photons that have been recorded in your exposures.
 
 @cartouche
 @noindent
-@strong{Calibration is very important:} Better calibration can result in a 
fainter surface brightness limit than more exposures with poor calibration; 
especially for very low surface brightness signal that covers a large area and 
is systematically affected by calibrationn issues.
+@strong{Calibration is very important:} Better calibration can result in a 
fainter surface brightness limit than more exposures with poor calibration; 
especially for very low surface brightness signal that covers a large area and 
is systematically affected by calibration issues.
 @end cartouche
 
-Based on the argument above, let's define our deep region to be the pixels 
with 3 or more exposures.
-Now, let's lave a look at the horizontally stretched cross that we see for the 
regions with 4 exposures.
-The reason that the vertical component is thicker is that the same change in 
RA and Dec (defined on a curved sphere) will result in different numbers of 
pixels on this flat image pixel grid.
+Ideally, you want your target to be on the four edges/corners of each image.
+This will make sure that a large fraction of each exposure will not be covered 
by your final target in each exposure, allowing you to calibrate much more 
accurately.
+Let's try setting @code{step_arcmin=40} (almost half the width of the 
detector) in your script@footnote{Assuming that the script is using the 
original @code{astscript-dither-simulate} command (that produced an exposure 
map output), not the one that produced a noisy image.}.
+After running the script, take a look at @file{deep.fits}:
+
+@example
+$ astscript-fits-view deep.fits --ds9scale=minmax
+@end example
 
+You will see that the region with 5 exposure depth is a horizontally elongated 
rectangle
+Let's focus at the horizontally stretched cross that we see for the regions 
with 4 exposures.
+The reason that the vertical component is thicker is that the same change in 
RA and Dec (defined on the curvature of a sphere) will result in different 
changes in each.
 To have the same size in both, we should divide the RA step by the cosine of 
the declination.
-In the command below, we have shown the relevant changes in the dither table 
construction above.
+In the command below, we have shown the relevant changes in the dither table 
construction above (this change should be taken into your script).
 
 @example
 $ echo $center_ra $center_dec \
@@ -9531,12 +9861,11 @@ The cosine function of AWK (@code{cos}) assumes that 
the input is in radians, no
 We therefore have to multiply each declination (in degrees) by a variable 
@code{r} that contains the conversion factor (@mymath{\pi/180}).
 @item
 AWK doesn't have the value of @mymath{\pi} in memory.
-We need to calculate it, and to do that, we use the @code{atan2} function (as 
recommended in the AWK manual, for its definition in Gnuastro, see 
@ref{Trigonometric and hyperbolic operators}).
+We need to calculate it, and to do that, we use the @code{atan2} function (as 
recommended in the AWK manual, for the definition of @code{atan2}, see 
@ref{Trigonometric and hyperbolic operators}).
 @end itemize
 
-Please use the new AWK command above in your script of the steps above, run it 
with everything else unchanged.
-Afterwards, open @file{deep.fits}.
-You will see that the widths of both the horizontal and vertical regions are 
the same.
+After updating the AWK command in your script to the one above run it with 
everything else unchanged.
+Afterwards, open @file{deep.fits} and you will see that the widths of both the 
horizontal and vertical regions are much more similar.
 
 @cartouche
 @noindent
@@ -9548,8 +9877,121 @@ You can try making the cross-like region as thin as 
possible by slightly increas
 For example, set it to @code{step_arcmin=42}.
 When you open @file{deep.fits}, you will see that the depth across this image 
is almost contiguous (which is another positive factor!).
 
-You can construct any complex dither pattern (with more than 5 points) based 
on the logic and reasoning above to help extract the most science from the 
valuable telescope time that you will be getting.
-Of course, factors like the optimal exposure time are also critical, but is 
was beyond the scope of this tutorial.
+You will notice that the vertical region of 4 exposure depth is thinner in the 
bottom than on the top.
+This is due to the RA/Dec change above, but across the width of the image.
+We can't therefore change this by just changing the position of the pointings, 
we need to rotate some of the exposures if we want it to be removed.
+But rotation is not yet implemented in this script.
+
+You can construct any complex dither pattern (with more than 5 points and in 
any shape) based on the logic and reasoning above to help extract the most 
science from the valuable telescope time that you will be getting.
+Since the output is a FITS file, you can easily download another FITS file of 
your target, open it with DS9 (and ``lock'' the ``WCS'') with the stack 
produced by this simulation to make sure that the deep parts correspond to the 
area of interest for your science case.
+
+Factors like the optimal exposure time are also critical for the final 
result@footnote{The exposure time will determine the Signal-to-noise ration on 
a single exposure level.}, but is was beyond the scope of this tutorial.
+One relevant factor however is the effect of vignetting: the pixels on the 
outer extremes of the field of view are usually exposed to much less flux than 
the central parts.
+In @ref{Triming vignetted area}, we will show how this can be done within the 
same test concept that we done here.
+
+
+@menu
+* Triming vignetted area::      Effect of triming the edges on your dither 
pattern.
+@end menu
+
+@node Triming vignetted area,  , Dither pattern design, Dither pattern design
+@subsection Triming vignetted area
+
+@cindex Baffle
+@cindex Vignetting
+@cindex Bad pixels
+The full area of a detector is not usually used in the final stack.
+This is mostly because of strong 
@url{https://en.wikipedia.org/wiki/Vignetting,vignetting}.
+But it can also have other causes: for example due to baffles in the optical 
path (to block stray light), or large regions of bad (unusable) pixels that may 
be in any place on the detector.
+
+Without accounting for these pixels that do not receive any light, the basic 
test that we did in @ref{Dither pattern design} will over-estimate the area of 
the deep region.
+In this sub-section, let's review the necessary modifications you need to do 
in that section by assuming that the image is affected by vignetting.
+Therefore, before continuing, please make sure that you have already read and 
done that section (this sub-section builds upon that section).
+
+@cindex Hook (programming)
+Vignetting strongly depends on the optical design of the instrument you are 
using.
+It can be a constant number of pixels on all the edges the detector, or it can 
have a more complex shape; for example on cameras that have multiple detectors 
on the field of view, in this case, the regions to exclude on each detector can 
be very different!
+Therefore, within Gnuastro's @command{astscript-dither-simulate} script there 
is no parameter for pre-defined vignetting shapes.
+Instead, you should define a mask that you can apply on each exposure through 
the provided before warping hook within this script 
(@option{--hook-warp-before}; recall that previously we used the hook that 
activated after warping).
+Through the mask, are free to set any un-wanted pixel to NaN (thus ignoring 
them in the stack) and applying it in any way that best suites your 
instrument+detector.
+
+The mask image should be same size as the reference image, but only containing 
two values: 0 or 1.
+Pixels in each exposure that have a value of 1 in the mask will be set to NaN 
before the stacking process and will not contribute to the final stack.
+Ideally, you can use the master flat field image of the previous reductions to 
create this mask: any pixel that has a low sensitivity in the master flat (for 
any reason) can be set to 1, and the rest of the pixels to 0.
+
+Let's build a simple mask by assuming that we only have strong vignetting that 
is affecting the outer 30 arc seconds of the individual exposures.
+To mask the outer edges of an image we can use Gnuastro's Arithmetic program; 
and in particular, the @code{indexonly} operator.
+To learn more about this operator, see @ref{Size and position operators}.
+
+But before doing that, we need convert this angular distance to pixels on the 
detector.
+In @ref{Dither pattern design}, we used an undersampled version of the input 
image, so we should do this conversion on that image:
+
+@example
+$ margin_arcsec=30
+$ margin_pix=$(astfits input/ref.fits --pixelscale --quiet \
+                     | awk '@{print int('$margin_arcsec'/($1*3600))@}')
+$ echo $margin_pix
+5
+@end example
+
+To build the mask, we can now follow the recipe under ``Image: masking 
margins'' of the @code{index} operator in Arithmetic (for a full description of 
what this command is doing@footnote{By learning how this command works, you can 
customize it.
+For example, to mask different widths along each separate edge: it often 
happens that the left/right or top/bottom edges are affected differently by 
vignetting.}, see @ref{Size and position operators}).
+Finally, in the last command, let's look at the mask image in the ``red'' 
color map of DS9 (which will shows the thin 1-valued pixels to mask on the 
border more clearly).
+
+@example
+$ width=$(astfits  input/ref.fits --keyvalue=NAXIS1 -q)
+$ height=$(astfits input/ref.fits --keyvalue=NAXIS2 -q)
+
+$ astarithmetic input/ref.fits indexonly     set-i \
+                $width         uint16        set-w \
+                $height        uint16        set-h \
+                $margin_pix    uint16        set-m \
+                i w %          uint16        set-X \
+                i w /          uint16        set-Y \
+                X m lt         X w m - gt       or \
+                Y m lt         Y h m - gt       or \
+                or --output=mask.fits
+
+$ astscript-fits-view mask.fits --ds9extra="-cmap red"
+@end example
+
+We are now ready to run the main dither simulate script.
+With the command below, we will use the @option{--hook-warp-before} to apply 
this mask on the image of each exposure just before warping.
+The concept of this hook is very similar to that of @option{--hook-warp-after} 
in @ref{Dither pattern design}.
+As the name suggests, this hook is applied ``before'' the warping.
+The input to the command given to this hook should be called with 
@code{$EXPOSURE} and the output should be called with @code{$TOWARP}.
+With the second command, let's compare the two outputs:
+
+@example
+$ astscript-dither-simulate dither.txt --output=stack-with-trim.fits \
+           --img=input/ref.fits --center=$center_ra,$center_dec \
+           --width=2 \
+           --hook-warp-before='astarithmetic $EXPOSURE mask.fits \
+                                             nan where -g1 -o$TOWARP'
+
+$ astscript-fits-view stack.fits stack-with-trim.fits
+@end example
+
+As expected, due to the smaller area of the detector that is exposed to 
photons, the regions with 4 exposures have become much thinner and on the 
bottom, it has been removed.
+To have contiguous depth in the deeper region, use this new call in your 
script and decrease the @code{step_arcmin=41}.
+
+You can use the same command on a mask that is created in any way and as 
realistic as possible.
+More generically, you can use the before and after hooks for any other 
operation; for example to insert objects from a catalog using 
@ref{MakeProfiles} as well as adding noise as we did in @ref{Dither pattern 
design}.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -22632,7 +23074,6 @@ It is therefore necessary to warp the image and correct 
for those distortions pr
 * Linear warping basics::       Basics of coordinate transformation.
 * Merging multiple warpings::   How to merge multiple matrices.
 * Resampling::                  Warping an image is re-sampling it.
-* Moire pattern and its correction::  Spatial resonance of the grid pattern on 
output.
 * Invoking astwarp::            Arguments and options for Warp.
 @end menu
 
@@ -22776,7 +23217,7 @@ These three operations can be merged in one operation 
by calculating the matrix
 
 
 
-@node Resampling, Moire pattern and its correction, Merging multiple warpings, 
Warp
+@node Resampling, Invoking astwarp, Merging multiple warpings, Warp
 @subsection Resampling
 
 @cindex Pixel
@@ -22841,7 +23282,7 @@ The output's pixel value is derived by summing all 
these multiplications for the
 Through this process, pixels are treated as an area not as a point (which is 
how detectors create the image), also the brightness (see @ref{Brightness flux 
magnitude}) of an object will be fully preserved.
 Since it involves the mixing of the input's pixel values, this pixel mixing 
method is a form of @ref{Spatial domain convolution}.
 Therefore, after comparing the input and output, you will notice that the 
output is slightly smoothed, thus boosting the more diffuse signal, but 
creating correlated noise.
-In astronomical imaging the correlated noise will be decreased later when you 
stack many exposures@footnote{If you are working on a single exposure image and 
see pronounced Moir@'e patterns after Warping, check @ref{Moire pattern and its 
correction} for a possible way to reduce them}.
+In astronomical imaging the correlated noise will be decreased later when you 
stack many exposures@footnote{If you are working on a single exposure image and 
see pronounced Moir@'e patterns after Warping, check @ref{Moire pattern in 
stacking and its correction} for a possible way to reduce them}.
 
 If there are very high spatial-frequency signals in the image (for example, 
fringes) which vary on a scale @emph{smaller than} your output image pixel size 
(this is rarely the case in astronomical imaging), pixel mixing can cause 
ailiasing@footnote{@url{http://en.wikipedia.org/wiki/Aliasing}}.
 Therefore, in case such fringes are present, they have to be calculated and 
removed separately (which would naturally be done in any astronomical reduction 
pipeline).
@@ -22854,229 +23295,10 @@ However, when a non-linear distortion (for example, 
@code{SIP} or @code{TPV}) is
 To account for such cases (which can only happen when correcting for 
non-linear distortions), Warp has the @option{--edgesampling} option to sample 
the output pixel over more vertices.
 For more, see the description of this option in @ref{Align pixels with WCS 
considering distortions}.
 
-@node Moire pattern and its correction, Invoking astwarp, Resampling, Warp
-@subsection Moir@'e pattern and its correction
-
-@cindex Moir@'e pattern or fringes
-After warping some images with the default mode of Warp (see @ref{Align pixels 
with WCS considering distortions}) you may notice that the background noise is 
no longer flat.
-Some regions will be smoother and some will be sharper; depending on the 
orientation and distortion of the input/output pixel grids.
-This is due to the @url{https://en.wikipedia.org/wiki/Moir%C3%A9_pattern, 
Moir@'e pattern}, which is especially noticeable/significant when two slightly 
different grids are super-imposed.
-
-With the commands below, we'll download a single exposure image from the 
@url{https://www.j-plus.es,J-PLUS survey} and run Warp (on a @mymath{8\times8} 
arcmin@mymath{^2} region to speed it up the demos here).
-Finally, we'll open the image to visually see the artificial Moir@'e pattern 
on the warped image.
-
-@example
-## Download the image (73.7 MB containing an 9216x9232 pixel image)
-$ jplusdr2=http://archive.cefca.es/catalogues/vo/siap/jplus-dr2/reduced
-$ wget $jplusdr2/get_fits?id=771463 -Ojplus-exp1.fits.fz
-
-## Align a small part of it with the sky coordinates.
-$ astwarp jplus-exp1.fits.fz --center=107.62920,39.72472 \
-          --width=8/60 -ojplus-e1.fits
 
-## Open the aligned region with DS9
-$ astscript-fits-view jplus-e1.fits
-@end example
 
-In the opened DS9 window, you can see the Moir@'e pattern as wave-like 
patterns in the noise: some parts of the noise are more smooth and some parts 
are more sharp.
-Right in the center of the image is a blob of sharp noise.
-Warp has the @option{--checkmaxfrac} option for direct inspection of the 
Moir@'e pattern (described with the other options in @ref{Align pixels with WCS 
considering distortions}).
-When run with this option, an extra HDU (called @code{MAX-FRAC}) will be added 
to the output.
-The image in this HDU has the same size as the output.
-However, each output pixel will contain the largest (maximum) fraction of area 
that it covered over the input pixel grid.
-So if an output pixel has a value of 0.9, this shows that it covered 
@mymath{90\%} of an input pixel.
-Let's run Warp with @option{--checkmaxfrac} and see the output (after DS9 
opens, in the ``Cube'' window, flip between the first and second HDUs):
 
-@example
-$ astwarp jplus-exp1.fits.fz --center=107.62920,39.72472 \
-          --width=8/60 -ojplus-e1.fits --checkmaxfrac
-
-$ astscript-fits-view jplus-e1.fits
-@end example
-
-By comparing the first and second HDUs/extensions, you will clearly see that 
the regions with a sharp noise pattern fall exactly on parts of the 
@code{MAX-FRAC} extension with values larger than 0.5.
-In other words, output pixels where one input pixel contributed more than half 
of the its value.
-As this fraction increases, the sharpness also increases because a single 
input pixel's value dominates the value of the output pixel.
-On the other hand, when this value is small, we see that many input pixels 
contribute to that output pixel.
-Since many input pixels contribute to an output pixel, it acts like a 
convolution, hence that output pixel becomes smoother (see @ref{Spatial domain 
convolution}).
-Let's have a look at the distribution of the @code{MAX-FRAC} pixel values:
-
-@example
-$ aststatistics jplus-e1.fits -hMAX-FRAC
-Statistics (GNU Astronomy Utilities) @value{VERSION}
--------
-Input: jplus-e1.fits (hdu: MAX-FRAC)
--------
-  Number of elements:                      744769
-  Minimum:                                 0.250213461
-  Maximum:                                 0.9987495374
-  Mode:                                    0.5034223567
-  Mode quantile:                           0.3773819498
-  Median:                                  0.5520805544
-  Mean:                                    0.5693956458
-  Standard deviation:                      0.1554693738
--------
-Histogram:
- |                      ***
- |                   **********
- |                 *****************
- |              ************************
- |           *******************************
- |         **************************************
- |       *********************************************
- |     ****************************************************
- |   ***********************************************************
- | ******************************************************************
- |**********************************************************************
- |----------------------------------------------------------------------
-@end example
-
-The smallest value is 0.25 (=1/4), showing that 4 input pixels contributed to 
the output pixels value.
-While the maximum is almost 1.0, showing that a single input pixel defined the 
output pixel value.
-You can also see that the most probable value (the mode) is 0.5, and that the 
distribution is positively skewed.
-
-@cindex Pixel scale
-@cindex @code{CDELT}
-This is a well-known problem in astronomical imaging and professional 
photography.
-If you only have a single image (that is already taken!), you can undersample 
the input: set the angular size of the output pixels to be larger than the 
input.
-This will decrease the resolution of your image, but will ensure that 
pixel-mixing will always happen.
-In the example below we are setting the output pixel scale (which is known as 
@code{CDELT} in the FITS standard) to @mymath{1/0.5=2} of the input's.
-In other words each output pixel edge will cover double the input pixel's edge 
on the sky, and the output's number of pixels in each dimension will be half of 
the previous output.
-
-@example
-$ cdelt=$(astfits jplus-exp1.fits.fz --pixelscale -q \
-                  | awk '@{print $1@}')
-$ astwarp jplus-exp1.fits.fz --center=107.62920,39.72472 \
-          --width=8/60 -ojplus-e1.fits --cdelt=$cdelt/0.5 \
-          --checkmaxfrac
-@end example
-
-In the first extension, you can hardly see any Moir@'e pattern in the noise.
-When you go to the next (@code{MAX-FRAC}) extension, you will see that almost 
all the pixels have a value of 1.
-Of course, decreasing the resolution by half is a little too drastic.
-Depending on your image, you may be able to reach a sufficiently good result 
without such a drastic degrading of the input image.
-For example, if you want an output pixel scale that is just 1.5 times larger 
than the input, you can divide the original coordinate-delta (or ``cdelt'') by 
@mymath{1/1.5=0.6666} and try again.
-In the @code{MAX-FRAC} extension, you will see that the range of pixel values 
is now between 0.56 to 1.0 (recall that originally, this was between 0.25 and 
1.0).
-This shows that the pixels are more similarly mixed and in fact, when you look 
at the actual warped image, you can hardly distinguish any Moir@'e pattern in 
the noise.
-
-@cindex Stacking
-@cindex Dithering
-@cindex Coaddition
-However, deep astronomical data are usually built by several exposures 
(images), not a single one.
-Each image is also taken by (slightly) shifting the telescope compared to the 
previous exposure.
-This shift is known as ``dithering''.
-We do this for many reasons (for example tracking errors in the telescope, 
high background values, removing the effect of bad pixels or those affected by 
cosmic rays, robust flat pattern measurement, etc.@footnote{E.g., 
@url{https://www.stsci.edu/hst/instrumentation/wfc3/proposing/dithering-strategies}}).
-One of those ``etc.'' reasons is to correct the Moir@'e pattern in the final 
coadded deep image.
-
-The Moir@'e pattern is fixed to the grid of the image, slightly shifting the 
telescope will result in the pattern appearing in different parts of the sky.
-Therefore when we later stack, or coadd, the separate exposures into a deep 
image, the Moir@'e pattern will be decreased there.
-However, dithering has possible drawbacks based on the scientific goal.
-For example when observing time-variable phenomena where cutting the exposures 
to several shorter ones is not feasible.
-If this is not the case for you (for example in galaxy evolution), continue 
with the rest of this section.
-
-Because we have multiple exposures that are slightly (sub-pixel) shifted, we 
can also increase the spatial resolution of the output.
-For example, let's set the output coordinate-delta (or pixel scale) to be 1/2 
of the input.
-In other words, the number of pixels in each dimension of the output is double 
the first Warp command of this section:
-
-@example
-$ astwarp jplus-exp1.fits.fz --center=107.62920,39.72472 \
-          --width=8/60 -ojplus-e1.fits --cdelt=$cdelt/2 \
-          --checkmaxfrac
-
-$ aststatistics jplus-e1.fits -hMAX-FRAC --minimum --maximum
-0.06263604388 0.2506802701
-
-$ astscript-fits-view jplus-e1.fits
-@end example
-
-From the last command, you see that like the previous change in 
@option{--cdelt}, the range of @code{MAX-FRAC} has decreased.
-However, when you look at the warped image and the @code{MAX-FRAC} image with 
the last command, you still visually see the Moir@'e pattern in the noise 
(although it has significantly decreased compared to the original resolution).
-It is still present because 2 is an exact multiple of 1.
-Let's try increasing the resolution (oversampling) by a factor of 1.25 (which 
isn't an exact multiple of 1):
-
-@example
-$ astwarp jplus-exp1.fits.fz --center=107.62920,39.72472 \
-          --width=8/60 -ojplus-e1.fits --cdelt=$cdelt/1.25 \
-          --checkmaxfrac
-$ astscript-fits-view jplus-e1.fits
-@end example
-
-You don't see any Moir@'e pattern in the noise any more, but when you look at 
the @code{MAX-FRAC} extension, you see it is very different from the ones you 
had seen before.
-In the previous @code{MAX-FRAC} image, you could see large blobs of similar 
values.
-But here, you see that the variation is almost on a pixel scale, and the 
difference between one pixel to the next is not significant.
-This is why you don't see any Moir@'e pattern in the warped image.
-
-In J-PLUS, each part of the sky was observed with a three-point dithering 
pattern.
-Let's download the other two exposures and warp the same region of the sky to 
the same pixel grid (using the @option{--gridfile} feature).
-Then, let's open all three cropped images in one DS9 instance:
-
-@example
-$ wget $jplusdr2/get_fits?id=771465 -Ojplus-exp2.fits.fz
-$ wget $jplusdr2/get_fits?id=771467 -Ojplus-exp3.fits.fz
-
-$ astwarp jplus-exp2.fits.fz --gridfile jplus-e1.fits \
-          -o jplus-e2.fits --checkmaxfrac
-$ astwarp jplus-exp3.fits.fz --gridfile jplus-e1.fits \
-          -o jplus-e3.fits --checkmaxfrac
-
-$ astscript-fits-view jplus-e*.fits
-@end example
-
-@noindent
-In the three warped images, you don't see any Moir@'e pattern, so far so 
good...
-now, take the following steps:
-@enumerate
-@item
-Click on the ``Frame'' button (in the top row of buttons just on top of the 
image), and select the ``Single'' button in the bottom row.
-@item
-Open the ``Zoom'' menu, and select ``Zoom 16''.
-@item
-In the bottom row of buttons right on top of the image, press the ``next'' 
button to flip through each exposure's @code{MAX-FRAC} extension.
-@item
-Focus your eyes on the pixels with the largest value (white colored pixels), 
while pressing the ``next'' button to flip between the exposures.
-You will see that in each exposure they cover different pixels.
-@end enumerate
-
-The exercise above shows that the effect varying smoothing level (that had 
already shrank to a per-pixel level) will be further decreased after we stack 
the images.
-So let's stack these three images with the commands below.
-First, we need to remove the sky-level from each image using 
@ref{NoiseChisel}, then we'll stack the @code{INPUT-NO-SKY} extensions using 
sigma-clipping (to reject outliers by @ref{Sigma clipping}, using the 
@ref{Stacking operators}).
-
-@example
-$ astnoisechisel jplus-e1.fits -ojplus-nc1.fits
-$ astnoisechisel jplus-e2.fits -ojplus-nc2.fits
-$ astnoisechisel jplus-e3.fits -ojplus-nc3.fits
-
-$ astarithmetic jplus-nc*.fits 3 5 0.2 sigclip-mean \
-                -gINPUT-NO-SKY -ojplus-stack.fits
-
-$ astscript-fits-view jplus-nc*.fits jplus-stack.fits
-@end example
-
-@noindent
-After opening the individual exposures and the final stack with the last 
command, take the following steps to see the comparisons properly:
-@enumerate
-@item
-Click on the stack image so it is selected.
-@item
-Go to the ``Frame'' menu, then the ``Lock'' item, then activate ``Scale and 
Limits''.
-@item
-Scroll your mouse or touchpad to zoom into the image.
-@end enumerate
-
-@noindent
-You clearly see that the stacked image is deeper and that there is no Moir@'e 
pattern, while you have slightly @emph{improved} the spatial resolution of the 
output compared to the input.
-In case you want the stack to have the original pixel resolution, you just 
need one more warp:
-
-@example
-$ astwarp jplus-stack.fits --cdelt=$cdelt -ojplus-stack-origres.fits
-@end example
-
-For optimal results, the oversampling should be determined by the dithering 
pattern of the observation:
-For example if you only have two dither points, you want the pixels with 
maximum value in the @code{MAX-FRAC} image of one exposure to fall on those 
with a minimum value in the other exposure.
-Ideally, many more dither points should be chosen when you are planning your 
observation (not just for the Moir@'e pattern, but also for all the other 
reasons mentioned above).
-Based on the dithering pattern, you want to select the increased resolution 
such that the maximum @code{MAX-FRAC} values fall on every different pixel of 
the output grid for each exposure.
-
-@node Invoking astwarp,  , Moire pattern and its correction, Warp
+@node Invoking astwarp,  , Resampling, Warp
 @subsection Invoking Warp
 
 Warp will warp an input image into a new pixel grid by pixel mixing (see 
@ref{Resampling}).
@@ -23202,12 +23424,12 @@ It is a normal/statistical error in measuring the 
astrometry.
 On a large image, these slight differences can cause different output sizes 
(of one or two pixels on a very large image).
 
 You can fix this by explicitly setting the pixel scale of each warped exposure 
with Warp's @option{--cdelt} option that is described below.
-For good strategies of setting the pixel scale, see @ref{Moire pattern and its 
correction}.
+For good strategies of setting the pixel scale, see @ref{Moire pattern in 
stacking and its correction}.
 @end cartouche
 
 Another problem that may arise when aligning images to new pixel grids is the 
aliasing or visible Moir@'e patterns on the output image.
 This artifact should be removed if you are stacking several exposures, 
especially with a dithering pattern.
-If not see @ref{Moire pattern and its correction} for ways to mitigate the 
visible patterns.
+If not see @ref{Moire pattern in stacking and its correction} for ways to 
mitigate the visible patterns.
 See the description of @option{--gridfile} below for more.
 
 @cartouche
@@ -23441,7 +23663,7 @@ To visually inspect the curvature effect on pixel area 
of the input image, see o
 @item --checkmaxfrac
 Check each output pixel's maximum coverage on the input data and append as the 
`@code{MAX-FRAC}' HDU/extension to the output aligned image.
 This option provides an easy visual inspection for possible recurring patterns 
or fringes caused by aligning to a new pixel grid.
-For more detail about the origin of these patterns and how to mitigate them 
see @ref{Moire pattern and its correction}.
+For more detail about the origin of these patterns and how to mitigate them 
see @ref{Moire pattern in stacking and its correction}.
 
 Note that the `@code{MAX-FRAC}' HDU/extension is not showing the patterns 
themselves;
 It represents the largest area coverage on the input data for that particular 
pixel.
@@ -32258,7 +32480,7 @@ In most cases this movement is small compared to the 
field of view, so most of t
 @cindex Exposure map
 For example see Figures 3 and 4 of @url{https://arxiv.org/pdf/1305.1931.pdf, 
Illingworth et al. 2013} which show the exposures that went into the XDF survey.
 The dither pattern can also be large compared to the field of view, for 
example see Figure 1 of @url{https://arxiv.org/pdf/2109.07478.pdf, Trujillo et 
al. 2021}, which show the dithering strategy for the LIGHTS survey.
-These types of images (where each pixel contains the number of exposures, or 
time, that were used in it)
+These types of images (where each pixel contains the number of exposures, or 
time, that were used in it) are known as exposure maps.
 
 The dithering pattern therefore is strongly defined by the science case 
(high-level purpose of the observation) and your telescope's field of view.
 For example in the XDF survey is focused on very high redshift (most distant!) 
galaxies.
@@ -32267,7 +32489,7 @@ However, the LIGHTS survey is focused on the halos of 
large nearby galaxies (tha
 
 In @ref{Invoking astscript-dither-simulate} of Gnuastro's @ref{Installed 
scripts} is described in detail.
 This script is designed to simplify the process of selecting the best 
dithering pattern for your observation strategy.
-For a more practical tutorial, see @ref{Dither pattern design}.
+For a practical tutorial on using this script, see @ref{Dither pattern design}.
 
 @menu
 * Invoking astscript-dither-simulate::  Options and running mode.
@@ -32362,6 +32584,48 @@ If @option{--widthinpix} is given, the two values 
given to this option will be i
 @item --widthinpix
 Interpret the values given to @option{--width} as number of pixels along each 
dimension), and not as degrees.
 
+@item --ctype=STR,STR
+The projection of the output stack (@code{CTYPEi} keyword in the FITS WCS 
standard).
+For more, see the description of the same option in @ref{Align pixels with WCS 
considering distortions}.
+
+@item --hook-warp-before='STR'
+Command to run before warping each exposure into the output pixel grid.
+By default, the exposure is immediately warped to the final pixel grid, but in 
some scenarios it is necessary to do some operations on the exposure before 
warping (for example account for vignetting; see @ref{Triming vignetted area}).
+The warping of each exposure is done in parallel by default; therefore there 
are pre-defined variables that you should use for the input and output file 
names of your command:
+@table @code
+@item $EXPOSURE
+Input: name of file with the same size as the reference image with all pixels 
having a fixed value of 1.
+The WCS has also been corrected based on the dither pattern.
+@item $TOWARP
+Output: name of the expected output of your hook.
+If it is not created by your script, the script will complain and abort.
+This file will be given to Warp to be warped into the output pixel grid.
+@end table
+
+For an example of using hooks with an exteded discussion, see @ref{Dither 
pattern design} and @ref{Triming vignetted area}.
+
+To develop your command, you can use @command{--hook-warp-before='...; echo 
GOOD; exit 1'} (where @code{...} can be replaced by any command) and run the 
script on a single thread (with @option{--numthreads=1}) to produce a single 
file and simplify the checking that your desired operation works as expected.
+All the files will be within the temporary directory (see @option{--tmpdir}).
+
+@item --hook-warp-after='STR'
+Command to run after the warp of each exposure into the output pixel grid, but 
before the stacking of all exposures.
+For more on hooks, see the description of @code{--hook-warp-before}, 
@ref{Dither pattern design} and @ref{Triming vignetted area}.
+
+@table @code
+@item $WARPED
+Input: name of file containing the warped exposure in the output pixel grid.
+@item $TOWARP
+Output: name of the expected output of your hook.
+If it is not created by your script, the script will complain and abort.
+This file will be stacked from the same file for all exposures into the final 
output.
+@end table
+
+@item --stack-operator="STR"
+The operator to use for stacking the warped individual exposures into the 
final output of this script.
+For the full list, see @ref{Stacking operators}.
+By default it is the @code{sum} operator (to produce an output exposure map).
+For an example usage, see the tutorial in @ref{Dither pattern design}.
+
 @item --mksrc=STR
 Use a non-standard Makefile for the Makefile to call.
 This option is primarily useful during the development of this script and its 
Makefile, not for normal/regular usage.
@@ -40982,7 +41246,7 @@ This dataset should have a type of 
@code{GAL_TYPE_FLOAT64} and contain exactly t
 @item uint8_t checkmaxfrac
 When this is non-zero, the output will be a two-element @ref{List of 
gal_data_t}.
 The second element shows the 
@url{https://en.wikipedia.org/wiki/Moir%C3%A9_pattern, Moir@'e pattern} of the 
warp.
-For more, see @ref{Moire pattern and its correction}.
+For more, see @ref{Moire pattern in stacking and its correction}.
 
 @end table
 @end deftp



reply via email to

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