gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master e7f9a0e 2/2: Merged modular options commit


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master e7f9a0e 2/2: Merged modular options commit
Date: Fri, 21 Oct 2016 19:45:52 +0000 (UTC)

branch: master
commit e7f9a0e06691ff08add94a52d2c9aeb56fcc4c92
Merge: e97ff56 31bb42e
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Merged modular options commit
---
 bin/imgwarp/args.h          |  131 ++++++---
 bin/imgwarp/astimgwarp.conf |    2 +-
 bin/imgwarp/main.h          |   25 +-
 bin/imgwarp/ui.c            |  670 +++++++++++++++++++++++++++++++------------
 bin/imgwarp/ui.h            |   25 +-
 doc/gnuastro.texi           |  194 +++++++++----
 6 files changed, 748 insertions(+), 299 deletions(-)

diff --git a/bin/imgwarp/args.h b/bin/imgwarp/args.h
index dbaa94a..ec54363 100644
--- a/bin/imgwarp/args.h
+++ b/bin/imgwarp/args.h
@@ -71,10 +71,10 @@ const char doc[] =
 
 /* Available letters for short options:
 
-   c e f g i j k l p t u v w x y
+   c g i j k l u v w x y
    A B C E F G H I J L M O Q R T U W X Y Z
 
-   Number keys used: <=502
+   Number keys used: <=503
 
    Options with keys (second structure element) larger than 500 do not
    have a short version.
@@ -110,6 +110,15 @@ static struct argp_option options[] =
       "Header keyword number to stop reading WCS.",
       1
     },
+    {
+      "nofitscorrect",
+      503,
+      0,
+      0,
+      "Do not shift to correct for FITS positioning.",
+      1
+    },
+
 
 
 
@@ -121,30 +130,6 @@ static struct argp_option options[] =
       2
     },
     {
-      "align",
-      'a',
-      0,
-      0,
-      "Align the image and celestial axes.",
-      1
-    },
-    {
-      "rotate",
-      'r',
-      "FLT",
-      0,
-      "Rotate by the given angle in degrees.",
-      1
-    },
-    {
-      "scale",
-      's',
-      "FLT",
-      0,
-      "Scale the image by the given factor.",
-      1
-    },
-    {
       "nowcscorrection",
       'n',
       0,
@@ -179,6 +164,72 @@ static struct argp_option options[] =
 
 
 
+
+    {
+      0, 0, 0, 0,
+      "Modular warpings:",
+      3
+    },
+    {
+      "align",
+      'a',
+      0,
+      0,
+      "Align the image and celestial axes.",
+      3
+    },
+    {
+      "rotate",
+      'r',
+      "FLT",
+      0,
+      "Rotate by the given angle in degrees.",
+      3
+    },
+    {
+      "scale",
+      's',
+      "FLT[,FLT]",
+      0,
+      "Scale along the given axis(es).",
+      3
+    },
+    {
+      "flip",
+      'f',
+      "FLT[,FLT]",
+      0,
+      "Flip along the given axis(es).",
+      3
+    },
+    {
+      "sheer",
+      'e',
+      "FLT[,FLT]",
+      0,
+      "Sheer along the given axis(es).",
+      3
+    },
+    {
+      "translate",
+      't',
+      "FLT[,FLT]",
+      0,
+      "Translate along the given axis(es).",
+      3
+    },
+    {
+      "project",
+      'p',
+      "FLT[,FLT]",
+      0,
+      "Project along the given axis(es).",
+      3
+    },
+
+
+
+
     {
       0, 0, 0, 0,
       "Operating modes:",
@@ -252,17 +303,33 @@ parse_opt(int key, char *arg, struct argp_state *state)
                                  SPACK, NULL, 0);
       p->up.maxblankfracset=1;
       break;
+    case 503:
+      p->up.nofitscorrect=1;
+      p->up.nofitscorrectset=1;
+      break;
+
+
+    /* Modular warpings */
     case 'a':
-      p->up.align=1;
-      p->up.alignset=1;
+      add_to_optionwapsll(&p->up.owll, ALIGN_WARP, NULL);
       break;
     case 'r':
-      gal_checkset_any_float(arg, &p->up.rotate, "rotate", key, SPACK, NULL, 
0);
-      p->up.rotateset=1;
+      add_to_optionwapsll(&p->up.owll, ROTATE_WARP, arg);
       break;
     case 's':
-      gal_checkset_any_float(arg, &p->up.scale, "scale", key, SPACK, NULL, 0);
-      p->up.scaleset=1;
+      add_to_optionwapsll(&p->up.owll, SCALE_WARP, arg);
+      break;
+    case 'f':
+      add_to_optionwapsll(&p->up.owll, FLIP_WARP, arg);
+      break;
+    case 'e':
+      add_to_optionwapsll(&p->up.owll, SHEER_WARP, arg);
+      break;
+    case 't':
+      add_to_optionwapsll(&p->up.owll, TRANSLATE_WARP, arg);
+      break;
+    case 'p':
+      add_to_optionwapsll(&p->up.owll, PROJECT_WARP, arg);
       break;
 
 
diff --git a/bin/imgwarp/astimgwarp.conf b/bin/imgwarp/astimgwarp.conf
index e3047ee..1017118 100644
--- a/bin/imgwarp/astimgwarp.conf
+++ b/bin/imgwarp/astimgwarp.conf
@@ -21,5 +21,5 @@
  hdu           0
 
 # Output:
- matrix        "0.2, 0, 0, 0.2"
+ scale         1.0
  maxblankfrac  0.8
\ No newline at end of file
diff --git a/bin/imgwarp/main.h b/bin/imgwarp/main.h
index 3c850ed..79233d7 100644
--- a/bin/imgwarp/main.h
+++ b/bin/imgwarp/main.h
@@ -41,6 +41,16 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 
 
 
+struct optionwarpsll
+{
+  int                   type;
+  double                  v1;
+  double                  v2;
+  struct optionwarpsll *next;
+};
+
+
+
 
 
 struct uiparams
@@ -49,12 +59,9 @@ struct uiparams
   char       *matrixname;  /* Name of transform file.                  */
   char     *matrixstring;  /* String containing transform elements.    */
 
-  int              align;  /* ==1: Align the image.                    */
-  float           rotate;  /* Rotation degrees in degrees.             */
-  float            scale;  /* Scaling factor.                          */
-  int           alignset;
-  int          rotateset;
-  int           scaleset;
+  struct optionwarpsll *owll;    /* List of 2D rotations.              */
+  int      nofitscorrect;  /* No corr the 0.5 pixel necessary in FITS. */
+  int   nofitscorrectset;
 
   int    matrixstringset;
   int    maxblankfracset;
@@ -69,16 +76,14 @@ struct uiparams
 struct imgwarpparams
 {
   /* Other structures: */
-  struct uiparams      up;  /* User interface parameters.                 */
+  struct uiparams      up;  /* User interface parameters.                */
   struct gal_commonparams cp; /* Common parameters.                      */
 
   /* Input: */
   double           *input;  /* Name of input FITS file.                  */
-  double          *matrix;  /* Warp/Transformation matrix.               */
+  double        matrix[9];  /* Warp/Transformation matrix.               */
   size_t              is0;  /* Number of rows in input image.            */
   size_t              is1;  /* Number of columns in input image.         */
-  size_t              ms0;  /* Matrix number of rows.                    */
-  size_t              ms1;  /* Matrix number of columns.                 */
   int         inputbitpix;  /* The type of the input array.              */
   int                nwcs;  /* Number of WCS structures.                 */
   struct wcsprm      *wcs;  /* Pointer to WCS structures.                */
diff --git a/bin/imgwarp/ui.c b/bin/imgwarp/ui.c
index fa4bc25..1afe816 100644
--- a/bin/imgwarp/ui.c
+++ b/bin/imgwarp/ui.c
@@ -138,28 +138,39 @@ readconfig(char *filename, struct imgwarpparams *p)
                                      SPACK, filename, lineno);
           up->maxblankfracset=1;
         }
-      else if(strcmp(name, "align")==0)
+      else if(strcmp(name, "nofitscorrect")==0)
         {
-          if(up->alignset) continue;
-          gal_checkset_int_zero_or_one(value, &up->align, name, key,
-                                       SPACK, filename, lineno);
-          up->alignset=1;
+          if(up->nofitscorrectset) continue;
+          gal_checkset_int_zero_or_one(value, &up->nofitscorrect, name,
+                                       key, SPACK, filename, lineno);
+          up->nofitscorrectset=1;
         }
+
+
+
+
+
+      /* Modular warpings */
+      else if(strcmp(name, "align")==0)
+        add_to_optionwapsll(&p->up.owll, ALIGN_WARP, NULL);
+
       else if(strcmp(name, "rotate")==0)
-        {
-          if(up->rotateset) continue;
-          gal_checkset_any_float(value, &up->rotate, name, key, SPACK,
-                                 filename, lineno);
-          up->rotateset=1;
-        }
+        add_to_optionwapsll(&p->up.owll, ROTATE_WARP, value);
+
       else if(strcmp(name, "scale")==0)
-        {
-          if(up->scaleset) continue;
-          gal_checkset_any_float(value, &up->scale, name, key, SPACK,
-                                 filename, lineno);
-          up->scaleset=1;
-        }
+        add_to_optionwapsll(&p->up.owll, SCALE_WARP, value);
+
+      else if(strcmp(name, "flip")==0)
+        add_to_optionwapsll(&p->up.owll, FLIP_WARP, value);
+
+      else if(strcmp(name, "sheer")==0)
+        add_to_optionwapsll(&p->up.owll, SHEER_WARP, value);
 
+      else if(strcmp(name, "translate")==0)
+        add_to_optionwapsll(&p->up.owll, TRANSLATE_WARP, value);
+
+      else if(strcmp(name, "project")==0)
+        add_to_optionwapsll(&p->up.owll, PROJECT_WARP, value);
 
 
 
@@ -200,12 +211,6 @@ printvalues(FILE *fp, struct imgwarpparams *p)
   fprintf(fp, "\n# Output parameters:\n");
   if(up->matrixstringset)
     GAL_CHECKSET_PRINT_STRING_MAYBE_WITH_SPACE("matrix", up->matrixstring);
-  if(up->alignset)
-    fprintf(fp, CONF_SHOWFMT"%d\n", "align", up->align);
-  if(up->rotateset)
-    fprintf(fp, CONF_SHOWFMT"%.3f\n", "rotate", up->rotate);
-  if(up->scaleset)
-    fprintf(fp, CONF_SHOWFMT"%.3f\n", "scale", up->scale);
 
   if(cp->outputset)
     GAL_CHECKSET_PRINT_STRING_MAYBE_WITH_SPACE("output", cp->output);
@@ -214,6 +219,13 @@ printvalues(FILE *fp, struct imgwarpparams *p)
     fprintf(fp, CONF_SHOWFMT"%.3f\n", "maxblankfrac", p->maxblankfrac);
 
 
+
+  fprintf(fp, "\n# Modular transformations:\n");
+  if(up->nofitscorrectset)
+    fprintf(fp, CONF_SHOWFMT"%d\n", "nofitscorrect", up->nofitscorrect);
+
+
+
   /* For the operating mode, first put the macro to print the common
      options, then the (possible options particular to this
      program). */
@@ -261,52 +273,259 @@ checkifset(struct imgwarpparams *p)
 
 
 
-
 /**************************************************************/
-/***************       Prepare Matrix       *******************/
+/**********      Modular matrix linked list       *************/
 /**************************************************************/
 void
-readmatrixoption(struct imgwarpparams *p)
+add_to_optionwapsll(struct optionwarpsll **list, int type, char *value)
 {
-  size_t counter=0;
-  char *t, *tailptr;
+  double v1=NAN, v2=NAN;
+  char *tailptr, *secondstr;
+  struct optionwarpsll *newnode;
 
   /* Allocate the necessary space. */
   errno=0;
-  p->matrix=malloc(9*sizeof *p->matrix);
-  if(p->matrix==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for temporary array to keep "
-          "the matrix option", 9*sizeof *p->matrix);
-
-  /* Go over the string and set the values. */
-  t=p->up.matrixstring;
-  while(*t!='\0')
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno, "%zu bytes for newnode in "
+          "add_to_optionwarpsll", sizeof *newnode);
+
+  /* Read the numbers when necessary. */
+  if(value)
     {
-      switch(*t)
+      /* Parse the first number */
+      v1=strtod(value, &tailptr);
+      if(tailptr==value)
+        error(EXIT_FAILURE, 0, "The start of the string `%s' could not be "
+              "read as a number", value);
+
+      /* If there is any white space characters, ignore them and make sure
+         that the first character is a coma (`,'). */
+      secondstr=tailptr;
+      while(isspace(*secondstr)) ++secondstr;
+      if(*secondstr==',')
         {
-        case ' ': case '\t': case ',':
-          ++t;
-          break;
-        default:
-          errno=0;
-          p->matrix[counter++]=strtod(t, &tailptr);
-          if(errno) error(EXIT_FAILURE, errno, "In reading `%s`", t);
-          if(tailptr==t)
-            error(EXIT_FAILURE, 0, "the provided string `%s' for matrix "
-                  "could not be read as a number", t);
-          t=tailptr;
-          if(counter>9)       /* Note that it was ++'d! */
-            error(EXIT_FAILURE, 0, "there are %zu elements in `%s', there "
-                  "should be 4 or 9", counter, p->up.matrixstring);
-          /*printf("%f, %s\n", p->matrix[counter-1], t);*/
+          /* If the type is rotate, then print an error since rotate only
+             needs one input, not two. */
+          if(type==ROTATE_WARP)
+            error(EXIT_FAILURE, 0, "The `--rotate' (`-r') option only needs "
+                  "one input number, not more. It was given `%s'", value);
+
+          /* Ignore the coma. */
+          ++secondstr;
+
+          /* Read the second number: */
+          v2=strtod(secondstr, &tailptr);
+          if(tailptr==secondstr)
+            error(EXIT_FAILURE, 0, "The second part (after the coma) of "
+                  "`%s' (`%s') could not be read as a number", value,
+                  secondstr);
+        }
+
+      /* If there was only one number given, secondstr will be '\0' when
+         control reaches here. */
+      else if(*secondstr!='\0')
+        error(EXIT_FAILURE, 0, "the character between the two numbers (`%s') "
+              "must be a coma (`,')\n", value);
+    }
+
+  /* Put in the values. Note that both v1 and v2 were initialized to NaN,
+     so if v2 is not given, it will be NaN and the later function can
+     decide what it wants to replace it with.*/
+  newnode->v1=v1;
+  newnode->v2=v2;
+  newnode->type=type;
+  newnode->next=*list;
+
+  /* Set list to point to the new node. */
+  *list=newnode;
+}
+
+
+
+
+
+/* Allocate space for a new node: */
+struct optionwarpsll *
+alloc_owll_node(void)
+{
+  struct optionwarpsll *newnode;
+
+  errno=0;
+  newnode=malloc(sizeof *newnode);
+  if(newnode==NULL)
+    error(EXIT_FAILURE, errno, "%zu bytes for newnode in "
+          "add_to_optionwarpsll", sizeof *newnode);
+
+  return newnode;
+}
+
+
+
+
+
+/* The input list of warpings are recorded in a last-in-first-out order. So
+   we reverse the order and also add the transformations necessary for the
+   FITS definition (where the center of the pixel has a value of 1, not its
+   corner. */
+void
+prepare_optionwapsll(struct imgwarpparams *p)
+{
+  struct optionwarpsll *tmp, *next, *newnode, *prepared=NULL;
+
+  /* Add the FITS correction for the first warp (before everything else).
+
+     IMPORTANT: This is the last transform that will be done, so we have to
+     translate the image by -0.5.*/
+  if(!p->up.nofitscorrect)
+    {
+      newnode = alloc_owll_node();
+      newnode->v1 = newnode->v2 = -0.5f;
+      newnode->type = TRANSLATE_WARP;
+      newnode->next = prepared;
+      prepared = newnode;
+    }
+
+  /* Put in the rest of the warpings */
+  tmp=p->up.owll;
+  while(tmp!=NULL)
+    {
+      /* Allocate space for the new element, and put the values in. */
+      newnode = alloc_owll_node();
+      newnode->v1 = tmp->v1;
+      newnode->v2 = tmp->v2;
+      newnode->type = tmp->type;
+      newnode->next = prepared;
+
+      /* Now that previous nodes have been linked to next, set the
+         reversed to the new node. */
+      prepared = newnode;
+
+      /* Now keep the next element and free the old allocated space. */
+      next = tmp->next;
+      free(tmp);
+      tmp = next;
+    }
+
+  /* Add the FITS correction for the last warp (after everything else).
+
+     IMPORTANT: This is the first transform that will be done, so we have
+     to translate the image by +0.5.*/
+  if(!p->up.nofitscorrect)
+    {
+      newnode = alloc_owll_node();
+      newnode->v1 = newnode->v2 = 0.5f;
+      newnode->type = TRANSLATE_WARP;
+      newnode->next = prepared;
+      prepared = newnode;
+    }
+
+  /* Put the pointer in the output */
+  p->up.owll=prepared;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**************************************************************/
+/*************      Fill temporary matrix     *****************/
+/**************************************************************/
+void
+read_matrix(struct imgwarpparams *p)
+{
+  char *t, *tailptr;
+  size_t i, counter=0, m0, m1;
+  double *matrix=p->matrix, rmatrix[9], *fmatrix;
+
+  /* Read the matrix either as a file or from the command-line. */
+  if(p->up.matrixname)
+    {
+      gal_txtarray_txt_to_array(p->up.matrixname, &fmatrix, &m0, &m1);
+      counter=m0*m1;
+      for(i=0;i<(counter<9 ? counter : 9);++i)
+        rmatrix[i]=fmatrix[i];
+      free(fmatrix);
+    }
+  else
+    {
+      t=p->up.matrixstring;
+      while(*t!='\0')
+        {
+          switch(*t)
+            {
+            case ' ': case '\t': case ',':
+              ++t;
+              break;
+            default:
+              errno=0;
+              rmatrix[counter++]=strtod(t, &tailptr);
+              if(errno) error(EXIT_FAILURE, errno, "reading `%s`", t);
+              if(tailptr==t)
+                error(EXIT_FAILURE, 0, "the provided string `%s' for "
+                      "matrix could not be read as a number", t);
+              t=tailptr;
+              if(counter>9)       /* Note that it was incremented! */
+                error(EXIT_FAILURE, 0, "there are %zu elements in `%s', "
+                      "there should be 4 or 9", counter, p->up.matrixstring);
+              /*printf("%f, %s\n", p->matrix[counter-1], t);*/
+            }
         }
     }
 
-  /* Add the other necessary information: */
+  /* If there was 4 elements (a 2 by 2 matrix), put them into a 3 by 3
+     matrix. */
   if(counter==4)
-    p->ms1=p->ms0=2;
+    {
+      /* Fill in the easy 3 by 3 matrix: */
+      matrix[0]=rmatrix[0];   matrix[1]=rmatrix[1];
+      matrix[3]=rmatrix[2];   matrix[4]=rmatrix[3];
+      matrix[6]=0.0f;         matrix[7]=0.0f;         matrix[8]=1.0f;
+
+      /* If we need to correct for the FITS standard, then correc the last
+         two elements. Recall that the coordinates of the center of the
+         first pixel in the FITS standard are 1. We want 0 to be the
+         coordinates of the bottom corner of the image.
+
+         1  0  0.5      a  b  0      a  b  0.5
+         0  1  0.5   *  c  d  0   =  c  d  0.5
+         0  0   1       0  0  1      0  0   1
+
+         and
+
+         a  b  0.5     1  0  -0.5     a  b  (a*-0.5)+(b*-0.5)+0.5
+         c  d  0.5  *  0  1  -0.5  =  c  d  (c*-0.5)+(d*-0.5)+0.5
+         0  0   1      0  0   1       0  0           1
+      */
+      if(p->up.nofitscorrect)
+        matrix[2] = matrix[5] = 0.0f;
+      else
+        {
+          matrix[2] = ((rmatrix[0] + rmatrix[1]) * -0.5f) + 0.5f;
+          matrix[5] = ((rmatrix[2] + rmatrix[3]) * -0.5f) + 0.5f;
+        }
+    }
   else if (counter==9)
-    p->ms1=p->ms0=3;
+    {
+      matrix[0]=rmatrix[0];   matrix[1]=rmatrix[1];   matrix[2]=rmatrix[2];
+      matrix[3]=rmatrix[3];   matrix[4]=rmatrix[4];   matrix[5]=rmatrix[5];
+      matrix[6]=rmatrix[6];   matrix[7]=rmatrix[7];   matrix[8]=rmatrix[8];
+    }
   else
     error(EXIT_FAILURE, 0, "there are %zu numbers in the string `%s'! "
           "It should contain 4 or 9 numbers (for a 2 by 2 or 3 by 3 "
@@ -320,9 +539,10 @@ readmatrixoption(struct imgwarpparams *p)
 /* Set the matrix so the image is aligned with the axises. Note that
    WCSLIB automatically fills the CRPI */
 void
-makealignmatrix(struct imgwarpparams *p)
+makealignmatrix(struct imgwarpparams *p, double *tmatrix)
 {
   double A, dx, dy;
+  double amatrix[4];
   double w[4]={0,0,0,0};
 
   /* Check if there is only two WCS axises: */
@@ -356,14 +576,6 @@ makealignmatrix(struct imgwarpparams *p)
      using the scale along the image X axis for both values. */
   gal_wcs_pixel_scale_deg(p->wcs, &dx, &dy);
 
-  /* Allocate space for the matrix: */
-  errno=0;
-  p->matrix=malloc(4*sizeof *p->matrix);
-  if(p->matrix==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for p->matrix in makealignmatrix",
-          4*sizeof *p->matrix);
-  p->ms0=p->ms1=2;
-
   /* Lets call the given WCS orientation `W', the rotation matrix we want
      to find as `X' and the final (aligned matrix) to have just one useful
      value: `a' (which is the pixel scale):
@@ -403,12 +615,23 @@ makealignmatrix(struct imgwarpparams *p)
        --> x3 = a / w1 / A
        --> x2 = -1 * x3 * w2 / w0
 
+    Note that when the image is already aligned, a unity matrix should be
+    output.
    */
-  A = (w[3]/w[1]) - (w[2]/w[0]);
-  p->matrix[1] = dx / w[0] / A;
-  p->matrix[3] = dx / w[1] / A;
-  p->matrix[0] = -1 * p->matrix[1] * w[3] / w[1];
-  p->matrix[2] = -1 * p->matrix[3] * w[2] / w[0];
+  if( w[1]==0.0f && w[2]==0.0f )
+    {
+      amatrix[0]=1.0f;   amatrix[1]=0.0f;
+      amatrix[2]=0.0f;   amatrix[3]=1.0f;
+    }
+  else
+    {
+      A = (w[3]/w[1]) - (w[2]/w[0]);
+      amatrix[1] = dx / w[0] / A;
+      amatrix[3] = dx / w[1] / A;
+      amatrix[0] = -1 * amatrix[1] * w[3] / w[1];
+      amatrix[2] = -1 * amatrix[3] * w[2] / w[0];
+    }
+
 
   /* For a check:
   printf("dx: %e\n", dx);
@@ -416,41 +639,73 @@ makealignmatrix(struct imgwarpparams *p)
   printf("  %.8e    %.8e\n", w[0], w[1]);
   printf("  %.8e    %.8e\n", w[2], w[3]);
   printf("x:\n");
-  printf("  %.8e    %.8e\n", p->matrix[0], p->matrix[1]);
-  printf("  %.8e    %.8e\n", p->matrix[2], p->matrix[3]);
+  printf("  %.8e    %.8e\n", amatrix[0], amatrix[1]);
+  printf("  %.8e    %.8e\n", amatrix[2], amatrix[3]);
   */
+
+
+  /* Put the matrix elements into the ouput array: */
+  tmatrix[0]=amatrix[0];  tmatrix[1]=amatrix[1]; tmatrix[2]=0.0f;
+  tmatrix[3]=amatrix[2];  tmatrix[4]=amatrix[3]; tmatrix[5]=0.0f;
+  tmatrix[6]=0.0f;        tmatrix[7]=0.0f;       tmatrix[8]=1.0f;
 }
 
 
 
 
 
-/* Create rotation matrix */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**************************************************************/
+/***************       Prepare Matrix       *******************/
+/**************************************************************/
+/* This function is mainly for easy checking/debugging. */
 void
-makebasicmatrix(struct imgwarpparams *p)
+printmatrix(double *matrix)
 {
-  struct uiparams *up=&p->up;
+  printf("%-10.3f%-10.3f%-10.3f\n", matrix[0], matrix[1], matrix[2]);
+  printf("%-10.3f%-10.3f%-10.3f\n", matrix[3], matrix[4], matrix[5]);
+  printf("%-10.3f%-10.3f%-10.3f\n", matrix[6], matrix[7], matrix[8]);
+}
 
-  /* Allocate space for the matrix: */
-  errno=0;
-  p->matrix=malloc(4*sizeof *p->matrix);
-  if(p->matrix==NULL)
-    error(EXIT_FAILURE, errno, "%zu bytes for p->matrix in makerotationmatrix",
-          4*sizeof *p->matrix);
-  p->ms0=p->ms1=2;
-
-  /* Put in the elements */
-  if(up->rotateset)
-    {
-      p->matrix[1] = sin( up->rotate*M_PI/180 );
-      p->matrix[2] = p->matrix[1] * -1.0f;
-      p->matrix[3] = p->matrix[0] = cos( up->rotate*M_PI/180 );
-    }
-  else if (up->scaleset)
-    {
-      p->matrix[1] = p->matrix[2] = 0.0f;
-      p->matrix[0] = p->matrix[3] = up->scale;
-    }
+
+
+
+
+void
+inplace_matrix_multiply(double *in, double *with)
+{
+  /* `tin' will keep the values of the input array because we want to
+     write the multiplication result in the input array. */
+  double tin[9]={in[0],in[1],in[2],in[3],in[4],in[5],in[6],in[7],in[8]};
+
+  /* For easy checking, here are the matrix/memory layouts:
+          tin[0] tin[1] tin[2]     with[0] with[1] with[2]
+          tin[3] tin[4] tin[5]  *  with[3] with[4] with[5]
+          tin[6] tin[7] tin[8]     with[6] with[7] with[8]   */
+  in[0] = tin[0]*with[0] + tin[1]*with[3] + tin[2]*with[6];
+  in[1] = tin[0]*with[1] + tin[1]*with[4] + tin[2]*with[7];
+  in[2] = tin[0]*with[2] + tin[1]*with[5] + tin[2]*with[8];
+
+  in[3] = tin[3]*with[0] + tin[4]*with[3] + tin[5]*with[6];
+  in[4] = tin[3]*with[1] + tin[4]*with[4] + tin[5]*with[7];
+  in[5] = tin[3]*with[2] + tin[4]*with[5] + tin[5]*with[8];
+
+  in[6] = tin[6]*with[0] + tin[7]*with[3] + tin[8]*with[6];
+  in[7] = tin[6]*with[1] + tin[7]*with[4] + tin[8]*with[7];
+  in[8] = tin[6]*with[2] + tin[7]*with[5] + tin[8]*with[8];
 }
 
 
@@ -459,99 +714,122 @@ makebasicmatrix(struct imgwarpparams *p)
 
 /* Fill in the warping matrix elements based on the options/arguments */
 void
-preparematrix(struct imgwarpparams *p)
+prepare_modular_matrix(struct imgwarpparams *p)
 {
-  double *tmp;
-  int mcheck=0;
+  int f1, f2;                   /* For flipping. */
+  double s, c, tmatrix[9];
   struct uiparams *up=&p->up;
+  struct optionwarpsll *tmp, *next;
 
-  /* Make sure that none of the matrix creation options/arguments are given
-     together. Note that a matrix string is optional (will only be used if
-     there is no matrix file). */
-  mcheck = ( up->alignset + up->rotateset + up->scaleset +
-             (up->matrixname!=NULL) );
-  if( mcheck > 1 )
-    error(EXIT_FAILURE, 0, "More than one method to define the warping "
-          "matrix has been given. Please only specify one.");
 
+  /* Allocate space for the matrix, then initialize it. */
+  p->matrix[0]=1.0f;     p->matrix[1]=0.0f;     p->matrix[2]=0.0f;
+  p->matrix[3]=0.0f;     p->matrix[4]=1.0f;     p->matrix[5]=0.0f;
+  p->matrix[6]=0.0f;     p->matrix[7]=0.0f;     p->matrix[8]=1.0f;
 
-  /* Read the input image WCS structure. We are doing this here because
-     some of the matrix operations might need it. */
-  gal_fits_read_wcs(up->inputname, p->cp.hdu, p->hstartwcs,
-                    p->hendwcs, &p->nwcs, &p->wcs);
 
+  /* The linked list is last-in-first-out, so we need to reverse it to
+     easily apply the changes in the same order that was read in. */
+  prepare_optionwapsll(p);
 
-  /* Depending on the given situation make the matrix. */
-  if(up->alignset)
-    makealignmatrix(p);
-  else if( up->rotateset || up->scaleset)
-    makebasicmatrix(p);
-  else
+
+  /* Do all the operations */
+  tmp=up->owll;
+  while(tmp!=NULL)
     {
-      if(up->matrixname)
-        gal_txtarray_txt_to_array(up->matrixname, &p->matrix,
-                                  &p->ms0, &p->ms1);
-      else
+      /* Fill `tmatrix' depending on the type of the warp. */
+      switch(tmp->type)
         {
-          /* Check if a matrix string is actually present. */
-          if(up->matrixstringset==0)
-            error(EXIT_FAILURE, 0, "no warping matrix string has been and "
-                  "no other means of making the warping matrix (a file or "
-                  "other options have been specified");
-          readmatrixoption(p);
-        }
-  }
+        case ALIGN_WARP:
+          makealignmatrix(p, tmatrix);
+          break;
 
+        case ROTATE_WARP:
+          s = sin( tmp->v1*M_PI/180 );
+          c = cos( tmp->v1*M_PI/180 );
+          tmatrix[0]=c;        tmatrix[1]=s;     tmatrix[2]=0.0f;
+          tmatrix[3]=-1.0f*s;  tmatrix[4]=c;     tmatrix[5]=0.0f;
+          tmatrix[6]=0.0f;     tmatrix[7]=0.0f;  tmatrix[8]=1.0f;
+          break;
 
-  /* Convert a 2 by 2 matrix into a 3 by 3 matrix and also correct it for
-     the FITS definition. */
-  if(p->ms0==2 && p->ms1==2)
-    {
-      errno=0;
-      tmp=malloc(9*sizeof *tmp);
-      if(tmp==NULL)
-        error(EXIT_FAILURE, errno, "%zu bytes for 3 by 3 matrix",
-              9*sizeof *tmp);
-
-      /* Put the four identical elements in place. */
-      tmp[0]=p->matrix[0];
-      tmp[1]=p->matrix[1];
-      tmp[3]=p->matrix[2];
-      tmp[4]=p->matrix[3];
-
-      /* Add the other elements. Note that we need to correct for the FITS
-         standard that defines the coordinates of the center of the first
-         pixel in the image to be 1. We want 0 to be the coordinates of the
-         bottom corner of the image.
-
-         1  0  0.5     a  b  0     a  b  0.5
-         0  1  0.5  *  c  d  0  =  c  d  0.5
-         0  0   1      0  0  1     0  0   1
+        case SCALE_WARP:
+          if( isnan(tmp->v2) ) tmp->v2=tmp->v1;
+          tmatrix[0]=tmp->v1;  tmatrix[1]=0.0f;     tmatrix[2]=0.0f;
+          tmatrix[3]=0.0f;     tmatrix[4]=tmp->v2;  tmatrix[5]=0.0f;
+          tmatrix[6]=0.0f;     tmatrix[7]=0.0f;     tmatrix[8]=1.0f;
+          break;
 
-         and
+        case FLIP_WARP:
+          /* For the flip, the values dont really matter! As long as the
+             value is non-zero, the flip in the respective axis will be
+             made. Note that the second axis is optional (can be NaN), but
+             the first axis is required.*/
+          f1 = tmp->v1==0.0f ? 0 : 1;
+          f2 = isnan(tmp->v2) ? 0 : ( tmp->v2==0.0f ? 0 : 1);
+          if( f1 && !f2  )
+            {
+              tmatrix[0]=1.0f;   tmatrix[1]=0.0f;
+              tmatrix[3]=0.0f;   tmatrix[4]=-1.0f;
+            }
+          else if ( !f1 && f2 )
+            {
+              tmatrix[0]=-1.0f;  tmatrix[1]=0.0f;
+              tmatrix[3]=0.0f;   tmatrix[4]=1.0f;
+            }
+          else
+            {
+              tmatrix[0]=-1.0f;  tmatrix[1]=0.0f;
+              tmatrix[3]=0.0f;   tmatrix[4]=-1.0f;
+            }
+                                                      tmatrix[2]=0.0f;
+                                                      tmatrix[5]=0.0f;
+          tmatrix[6]=0.0f;       tmatrix[7]=0.0f;     tmatrix[8]=1.0f;
+          break;
 
-         a  b  0.5     1  0  -0.5     a  b  (a*-0.5)+(b*-0.5)+0.5
-         c  d  0.5  *  0  1  -0.5  =  c  d  (c*-0.5)+(d*-0.5)+0.5
-         0  0   1      0  0   1       0  0           1
+        case SHEER_WARP:
+          if( isnan(tmp->v2) ) tmp->v2=tmp->v1;
+          tmatrix[0]=1.0f;     tmatrix[1]=tmp->v1;    tmatrix[2]=0.0f;
+          tmatrix[3]=tmp->v2;  tmatrix[4]=1.0f;       tmatrix[5]=0.0f;
+          tmatrix[6]=0.0f;     tmatrix[7]=0.0f;       tmatrix[8]=1.0f;
+          break;
+
+        case TRANSLATE_WARP:
+          if( isnan(tmp->v2) ) tmp->v2=tmp->v1;
+          tmatrix[0]=1.0f;     tmatrix[1]=0.0f;       tmatrix[2]=tmp->v1;
+          tmatrix[3]=0.0f;     tmatrix[4]=1.0f;       tmatrix[5]=tmp->v2;
+          tmatrix[6]=0.0f;     tmatrix[7]=0.0f;       tmatrix[8]=1.0f;
+          break;
+
+        case PROJECT_WARP:
+          if( isnan(tmp->v2) ) tmp->v2=tmp->v1;
+          tmatrix[0]=1.0f;     tmatrix[1]=0.0f;       tmatrix[2]=0.0f;
+          tmatrix[3]=0.0f;     tmatrix[4]=1.0f;       tmatrix[5]=0.0f;
+          tmatrix[6]=tmp->v1;  tmatrix[7]=tmp->v2;    tmatrix[8]=1.0f;
+          break;
+
+        default:
+          error(EXIT_FAILURE, 0, "a bug! Please contact us at %s so we can "
+                "address the problem. For some reason the value of tmp->type "
+                "in `prepare_modular_matrix' of ui.c is not recognized. "
+                "This is an internal, not a user issue. So please let us "
+                "know.", PACKAGE_BUGREPORT);
+        }
+
+      /* Multiply this matrix with the main matrix in-place. */
+      inplace_matrix_multiply(p->matrix, tmatrix);
+
+      /* Keep the next element and free the node's allocated space. */
+      next = tmp->next;
+      free(tmp);
+      tmp = next;
+
+      /* For a check:
+      printf("tmatrix:\n");
+      printmatrix(tmatrix);
+      printf("out:\n");
+      printmatrix(p->matrix);
       */
-      tmp[8] = 1.0f;
-      tmp[6] = tmp[7] = 0.0f;
-      tmp[2] = ((p->matrix[0] + p->matrix[1]) * -0.5f) + 0.5f;
-      tmp[5] = ((p->matrix[2] + p->matrix[3]) * -0.5f) + 0.5f;
-
-      /* Free the previously allocated 2D matrix and put the put the newly
-         allocated array with correct values in it. */
-      free(p->matrix);
-      p->matrix=tmp;
-
-      /* Set the new sizes */
-      p->ms0=p->ms1==3;
     }
-  else if (p->ms0!=3 || p->ms1!=3)
-    error(EXIT_FAILURE, 0, "a bug! please contact us at %s so we can "
-          "address the problem. For some reason p->ms0=%zu and p->ms1=%zu! "
-          "They should both have a value of 3.", PACKAGE_BUGREPORT,
-          p->ms0, p->ms1);
 }
 
 
@@ -592,30 +870,37 @@ sanitycheck(struct imgwarpparams *p)
                                   p->cp.removedirinfo, p->cp.dontdelete,
                                   &p->cp.output);
 
+  /* If an actual matrix is given, then it will be used and all modular
+     warpings will be ignored. */
+  if(p->up.matrixstring || p->up.matrixname)
+    read_matrix(p);
+  else if (p->up.owll)
+    prepare_modular_matrix(p);
+  else
+    error(EXIT_FAILURE, 0, "No input matrix specified.\n\nPlease either "
+          "use the modular warp options like `--rotate' or `--scale', "
+          "or directly specify the matrix on the command-line, or in the "
+          "configuration files.\n\nRun with `--help' for the full list of "
+          "modular warpings (among other options), or see the manual's "
+          "`Warping basics' section for more on the matrix.");
 
-  /* Check the size of the input matrix, note that it might only have
-     the wrong numbers when it is read from a file. */
-  if(p->up.matrixname)
-     if( (p->ms0 != 2 && p->ms0 != 3) || p->ms0 != p->ms1 )
-       error(EXIT_FAILURE, 0, "the given matrix in %s has %zu rows and "
-             "%zu columns. Its size must be either 2x2 or 3x3",
-             p->up.matrixname, p->ms0, p->ms1);
 
   /* Check if there are any non-normal numbers in the matrix: */
-  df=(d=m)+p->ms0*p->ms1;
+  df=(d=p->matrix)+9;
   do
     if(!isfinite(*d++))
-      error(EXIT_FAILURE, 0, "%f is not a `normal' number", *(d-1));
+      {
+        printmatrix(p->matrix);
+        error(EXIT_FAILURE, 0, "%f is not a `normal' number in the "
+              "input matrix shown above", *(d-1));
+      }
   while(d<df);
 
   /* Check if the determinant is not zero: */
-  if( ( p->ms0==2 && (m[0]*m[3] - m[1]*m[2] == 0) )
-      ||
-      ( p->ms0==3 &&
-        (m[0]*m[4]*m[8] + m[1]*m[5]*m[6] + m[2]*m[3]*m[7]
-         - m[2]*m[4]*m[6] - m[1]*m[3]*m[8] - m[0]*m[5]*m[7] == 0) ) )
-      error(EXIT_FAILURE, 0, "the determinant of the given matrix "
-            "is zero");
+  if( m[0]*m[4]*m[8] + m[1]*m[5]*m[6] + m[2]*m[3]*m[7]
+      - m[2]*m[4]*m[6] - m[1]*m[3]*m[8] - m[0]*m[5]*m[7] == 0 )
+    error(EXIT_FAILURE, 0, "the determinant of the given matrix "
+          "is zero");
 
   /* Check if the transformation is spatially invariant */
 }
@@ -724,7 +1009,9 @@ setparams(int argc, char *argv[], struct imgwarpparams *p)
   cp->verb          = 1;
   cp->numthreads    = num_processors(NPROC_CURRENT);
   cp->removedirinfo = 1;
+
   p->correctwcs     = 1;
+  p->up.owll        = NULL;
 
   /* Read the arguments. */
   errno=0;
@@ -741,8 +1028,10 @@ setparams(int argc, char *argv[], struct imgwarpparams *p)
   if(cp->printparams)
     GAL_CONFIGFILES_REPORT_PARAMETERS_SET;
 
-  /* Read the input matrix */
-  preparematrix(p);
+  /* Read the input image WCS structure. We are doing this here because
+     some of the matrix operations might need it. */
+  gal_fits_read_wcs(p->up.inputname, p->cp.hdu, p->hstartwcs,
+                    p->hendwcs, &p->nwcs, &p->wcs);
 
   /* Do a sanity check. */
   sanitycheck(p);
@@ -795,7 +1084,6 @@ freeandreport(struct imgwarpparams *p, struct timeval *t1)
 {
   /* Free the allocated arrays: */
   free(p->input);
-  free(p->matrix);
   free(p->cp.hdu);
   free(p->inverse);
   free(p->cp.output);
diff --git a/bin/imgwarp/ui.h b/bin/imgwarp/ui.h
index f6b29e5..3307185 100644
--- a/bin/imgwarp/ui.h
+++ b/bin/imgwarp/ui.h
@@ -20,8 +20,29 @@ General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
 **********************************************************************/
-#ifndef IMCROPUI_H
-#define IMCROPUI_H
+#ifndef UI_H
+#define UI_H
+
+
+/* Macros for various types of standard transformation.*/
+enum standard_warps
+  {
+    ALIGN_WARP,
+    ROTATE_WARP,
+    SCALE_WARP,
+    FLIP_WARP,
+    SHEER_WARP,
+    TRANSLATE_WARP,
+    PROJECT_WARP,
+  };
+
+
+/* Functions */
+void
+add_to_optionwapsll(struct optionwarpsll **list, int type, char *value);
+
+void
+parse_two_values(char *str, double *v1, double *v2);
 
 void
 setparams(int argc, char *argv[], struct imgwarpparams *p);
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 18191d1..e09a8bc 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -9178,35 +9178,18 @@ One line examples:
 @example
 $ astimgwarp matrix.txt image.fits
 $ astimgwarp --align rawimage.fits
-$ astimgwarp --scale 1.82 image.fits
-$ astimgwarp --rotate=37.92 image.fits
+$ astimgwarp --scale 1.82 --translate 2.1 image.fits
+$ astimgwarp --rotate=37.92 --scale=0.8 image.fits
 $ astimgwarp --matrix=0.2,0,0.4,0,0.2,0.4,0,0,1 image.fits
 $ astimgwarp --matrix="0.7071,-0.7071  0.7071,0.7071" image.fits
 @end example
 
 ImageWarp can accept two arguments, one (an image) is mandatory if any
 processing is to be done. An optional argument is a plain text file, which
-must contain the warp/transform matrix, see @ref{Warping basics}. There is
-also the @option{--matrix} option from which the matrix can be literally
-specified on the command-line. If both are present when calling ImageWarp,
-the contents of the plain text file have higher precedence. You can also
-specify standard transformations without an explicit matrix as discussed
-below. If multiple transformations are specified, then ImageWarp will
-inform you and abort. The general options to all Gnuastro programs can be
-seen in @ref{Common options}.
-
address@hidden WCSLIB
address@hidden World Coordinate System
-By default the WCS (World Coordinate System) information of the input
-image is going to be corrected in the output image. WCSLIB will save
-the input WCS information in the @code{PC} address@hidden
-E.W., Calabretta M.R. (2002) Representation of world coordinates in
-FITS. Astronomy and Astrophysics, 395, 1061-1075.}. To correct the
-WCS, ImageWarp multiplies the @code{PC} matrix with the inverse of the
-specified transformation matrix. Also the @code{CRPIX} point is going
-to be changed to its correct place in the output image
-coordinates. This behavior can be disabled with the
address@hidden option.
+must contain the warp/transform matrix, see @ref{Warping basics}. When this
+text file is specified, then all options related to the matrix will be
+ignored (see below for the options). The general options to all Gnuastro
+programs (including ImageWarp) can be seen in @ref{Common options}.
 
 To be the most accurate the input image will be converted to double
 precision floating points and all the processing will be done in this
@@ -9219,25 +9202,118 @@ data. This behavior can be disabled with the 
@option{--doubletype}
 option. The input file and input warping matrix elements are stored in
 the output's header.
 
address@hidden
address@hidden
address@hidden of pixel center}: Based on the FITS standard,
-integer values are assigned to the center of a pixel and the
-coordinate [1.0, 1.0] is the center of the bottom left (first) image
-pixel. So the point [0.0, 0.0] is half a pixel away (in each axis)
-from the bottom left vertice of the first address@hidden if you
-want to warp the image relative to the bottom left vertice of the
-bottom left pixel, you have to shift the warping center by [0.5, 0.5],
-apply your transform then shift back by [-0.5, -0.5]. Similar to the
-example in see @ref{Merging multiple warpings}. For example see the
-one line example above which scales the image by one fifth
-(0.2). Without this correction (if it was
address@hidden,0,0,0,0.2,0,0,0,1}), the image would not be correctly
-scaled.}.
address@hidden cartouche
+When using options, warps can be specified in a modular form, with options
+to specify each transformation (for example @option{--rotate}, or
address@hidden), or directly as a matrix (with @option{--matrix}). If
+specified together, the latter (direct matrix) will take precedence and all
+the modular warpings will be ignored. Any number of modular warpings can be
+specified on the command-line and configuration files. If more than one
+modular warping is given, all will be merged to create one warping
+matrix. As described in @ref{Merging multiple warpings}, matrix
+multiplication is not commutative, so the order of specifing the modular
+warpings on the command-line, and/or configuration files makes a difference
+(see @ref{Configuration file precedence}). Below, the modular warpings are
+first listed (see @ref{Warping basics} for the definition of each type of
+warping), then the other ImageWarp options.
+
address@hidden FITS standard
+Based on the FITS standard, integer values are assigned to the center of a
+pixel and the coordinate [1.0, 1.0] is the center of the bottom left
+(first) image pixel. So the point [0.0, 0.0] is half a pixel away (in each
+axis) from the bottom left vertice of the first pixel. The resampling that
+is done in ImageWarp (see @ref{Resampling}) is dependent on this
+coordinate. So correction is done internally. With this resampling, the
+image must be warped relative to the bottom left vertice of the bottom left
+pixel and that point should lie at [0.0, 0.0]. So for a correct sampling,
+the warping center must first be translated by [0.5, 0.5], then the warp
+should be done and finally, a [-0.5, -0.5] translation should be
+specified. This correction is done internally in the following cases and
+can be disabled with the @option{--nofitscorrect} option.
+
address@hidden
address@hidden
+A 2D matrix is given in a file (as an argument).
address@hidden
+A 2D matrix is specified with the @option{--matrix} option.
address@hidden
+When modular warpings are used.
address@hidden itemize
+
 
 @table @option
 
address@hidden -a
address@hidden --align
+Align the image and celestial (WCS) axes, such that the vertical image
+direction (when viewed in SAO ds9) corresponds to the declination and the
+horizontal axis is the inverse of the Right Ascension (RA). The inverse of
+the RA is chosen so the image can correspond to what you would actually see
+on the sky and is common in most survey images. Align is internally treated
+just like a rotation (@option{--rotation}), but uses the input image's WCS
+to find the rotation angle.
+
address@hidden -r
address@hidden --rotate
+(@option{=FLT}) Rotate the input image by the given angle in degrees. Note
+that commonly, the WCS structure of the image is set such that the RA is
+the inverse of the image horizontal axis which increases towards the right
+in the FITS standard and as viewed by SAO ds9. So the default center for
+rotation is on the right of the image. If you want to rotate about other
+points, you have to translate the warping center first (with
address@hidden) then apply your rotation and then return the center
+back to the original position (with another call to @option{--translate},z
+see @ref{Merging multiple warpings}.
+
address@hidden -s
address@hidden --scale
+(@option{=FLT[,FLT]}) Scale the input image by the given factor. If only
+one value is given, then both image axises will be scaled with the given
+value. When two values are given, the first will be used to scale the first
+axis and the second will be used for the second axis. If you only need to
+scale one axis, use @option{1} for the axis you don't need to scale.
+
address@hidden -f
address@hidden --flip
+(@option{=FLT[,FLT]}) Flip the image around the first, second or both
+axises. The first value specifies a flip on the first axis and the second
+on the second axis. The values of the option only matter if they are
+non-zero. If any of the values are zero, that axis is not flipped. So if
+you want to flip by the second axis only, use @option{--flip=0,1} (which is
+equivalent to @option{--flip=0,20} since it only matters if it is
+non-zero).
+
address@hidden -e
address@hidden --sheer
+(@option{=FLT[,FLT]}) Apply a sheer to the image along the image axises. If
+only one value is given, then both image axises will be sheered with the
+given value. When two values are given, the first will be used to sheer the
+first axis and the second will be used for the second axis. If you only
+need to sheer one axis, use @option{0} for the axis you don't need.
+
address@hidden -t
address@hidden --translate
+(@option{=FLT[,FLT]}) Apply a translation to the image along the image
+axises. If only one value is given, then both image axises will be
+translated with the given value. When two values are given, the first will
+be used to translate along the first axis and the second will be used for
+the second axis. If you only need to translate one axis, use @option{0} for
+the axis you don't need.
+
address@hidden -p
address@hidden --project
+(@option{=FLT[,FLT]}) Apply a projection to the image along the image
+axises. If only one value is given, then the projection will be applied on
+both image axises with the given value. When two values are given, the
+first will be used for the first axis and the second will be used for the
+second axis. If you only need projection along one axis, use @option{0} for
+the axis you don't need.
+
address@hidden table
+
+
+ImageWarp also provides the following options:
address@hidden @option
+
 @item -m
 @itemx --matrix
 (@option{=STR}) The warp/transformation matrix. All the elements in this
@@ -9261,28 +9337,9 @@ elements of the matrix have to be written row by row. So 
for the
 general homography matrix of @ref{Warping basics}, it should be called
 with @command{--matrix=a,b,c,d,e,f,g,h,1}.
 
address@hidden -a
address@hidden --align
-Align the image and celestial (WCS) axes, such that the vertical image
-direction (when viewed in SAO ds9) corresponds to the declination and the
-horizontal axis is the inverse of the Right Ascension (RA). The inverse of
-the RA is chosen so the image can correspond to what you would actually see
-on the sky and is common in most survey images.
-
address@hidden -r
address@hidden --rotate
-(@option{=FLT}) Rotate the input image by the given angle in degrees. Note
-that commonly, the WCS structure of the image is set such that the RA is
-the inverse of the image horizontal axis which increases towards the right
-in the FITS standard and as viewed by SAO ds9. So the default center for
-rotation is on the right of the image. If you want to rotate about other
-points, you have to define your own transformation matrix by first shifting
-the central point, then applying your rotation and then returning the
-center back to the original position, see @ref{Merging multiple warpings}.
-
address@hidden -s
address@hidden --scale
-(@option{=FLT}) Scale the input image by the given factor.
address@hidden nofitscorrect
+Do not correct for the FITS definition of the pixel center as described in
+the @option{--matrix} option.
 
 @item --hstartwcs
 (@option{=INT}) Specify the first header keyword number (line) that
@@ -9296,8 +9353,19 @@ should be used to read the WCS information, see the full 
explanation in
 
 @item -n
 @itemx --nowcscorrection
-Do not correct the WCS information of the input image and save it
-untouched to the output image.
address@hidden WCSLIB
address@hidden World Coordinate System
+Do not correct the WCS information of the input image and save it untouched
+to the output image. By default the WCS (World Coordinate System)
+information of the input image is going to be corrected in the output
+image. WCSLIB will save the input WCS information in the @code{PC}
address@hidden E.W., Calabretta M.R. (2002) Representation of
+world coordinates in FITS. Astronomy and Astrophysics, 395, 1061-1075.}. To
+correct the WCS, ImageWarp multiplies the @code{PC} matrix with the inverse
+of the specified transformation matrix. Also the @code{CRPIX} point is
+going to be changed to its correct place in the output image
+coordinates. This behavior can be disabled with the
address@hidden option.
 
 @cindex Blank pixel
 @cindex Pixel, blank



reply via email to

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