\documentclass[11pt]{article}

\usepackage{amsmath}

% GILDAS specific definitions
\include{gildas-def}

\newcommand{\CD}{{\tt CD}}
\newcommand{\PC}{{\tt PC}}

\title{Support of FITS coordinates \\
       rotation and reflection in \gildas}%
\author{S. Bardeau$^{1}$\\[0.5cm]
  1. IRAM (Grenoble)}%
\date{29-nov-2024 \\
  version 1.0} \makeindex{}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}

\maketitle

\begin{rawhtml}
  Note: this is the on-line version of the Support of FITS rotation
  and reflection in \gildas. A <A HREF="../../pdf/fits-rotation.pdf"> PDF
  version</A> is also available.
\end{rawhtml}

\begin{abstract}
  This document summarizes the FITS \CD\ and \PC\ matrices in FITS,
  which are used to describe the projection plane rotations (among
  other possible transformations). It also documents the conversion
  to \gildas\ Data Format and the related limitations.\\

  Keywords: FITS data format, \gildas\ data format, rotation, reflection\\

  Related documents: \emph{GreG documentation}, \emph{Review of the spatial
                     projections support in GILDAS}
\end{abstract}

\newpage
\tableofcontents

\newpage

\section{Mathematical formalism}

A $\theta$ rotation of a 2D plane can be represented as a matrix of the
following form:
\begin{equation}
\label{eqn:rot}
\mathrm{Rot(\theta)} =
\begin{pmatrix}
\cos \theta & -\sin \theta \\
\sin \theta &  \cos \theta
\end{pmatrix}
\end{equation}
while a reflection along the line at angle $\theta$ is written:
\begin{equation}
\mathrm{Ref(\theta)} =
\begin{pmatrix}
\cos 2\theta &  \sin 2\theta \\
\sin 2\theta & -\cos 2\theta
\end{pmatrix}
\end{equation}
Note that rotation matrices have a determinant of $+1$, while reflection
matrices have a determinant of $-1$.\\

As a result, $(p_1,p_2)$ rotated coordinates transform to $(x_1,x_2)$:
\begin{equation}
\begin{pmatrix}
x_1 \\
x_2
\end{pmatrix}
=
\begin{pmatrix}
\cos \theta & -\sin \theta \\
\sin \theta &  \cos \theta
\end{pmatrix}
\begin{pmatrix}
p_1 \\
p_2
\end{pmatrix}
=
\begin{pmatrix}
p_1 \cos \theta - p_2 \sin \theta \\
p_1 \sin \theta + p_2 \cos \theta
\end{pmatrix}
\end{equation}
and reflected coordinates transform to:
\begin{equation}
\begin{pmatrix}
x_1 \\
x_2
\end{pmatrix}
=
\begin{pmatrix}
p_1 \cos 2\theta + p_2 \sin 2\theta \\
p_1 \sin 2\theta - p_2 \cos 2\theta
\end{pmatrix}
\end{equation}

\section{FITS formalism}

The Calabretta \& Greisen 2002 paper\footnote{\emph{Representations of
celestial coordinates in FITS}, M. R. Calabretta and E. W. Greisen,
A\&A 395, 1077-1122 (2002)} introduces two transformations matrices when
converting from pixel coordinates to \emph{intermediate world coordinates}
(their formula 1):
\begin{eqnarray}
x_i & = & s_i \sum_{j=1}^{N} m_{ij}(p_j-r_j) \\
    & = & \sum_{j=1}^{N} (s_i m_{ij}) (p_j-r_j)
\end{eqnarray}
where $x_i$ is the intermediate world coordinate on axis $i$ (\ie\ the
coordinate before deprojection to absolute coordinate, see related
\gildas\ memo), $p_j$ is the pixel number on axis $j$, and $r_j$ is the
reference pixel ({\tt CRPIX}$j$) on the same axis.
Quoting Calabretta \& Greisen: \emph{As suggested by the two forms of the
equation, the scales $s_i$, and matrix elements $m_{ij}$ may be
represented either separately or in combination. In the first form $s_i$
is given by {\tt CDELT}$ia$ and $m_{ij}$ by \PC$i\_ja$; in the
second, the product $s_i m_{ij}$ is given by \CD$i\_ja$.} If the matrices
are to be applied on the 2 first dimensions of a FITS file, the \CD\ and
\PC\ matrices are related with:
\begin{equation}
  \label{eqn:CD2PC}
  \begin{pmatrix}
    \CD_{11} & \CD_{12} \\
    \CD_{21} & \CD_{22}
  \end{pmatrix}
  =
  \begin{pmatrix}
    {\tt CDELT1} \; \PC_{11} & {\tt CDELT1} \; \PC_{12} \\
    {\tt CDELT2} \; \PC_{21} & {\tt CDELT2} \; \PC_{22}
  \end{pmatrix}
  =
  \begin{pmatrix}
    {\tt CDELT1} & 0 \\
    0            & {\tt CDELT2}
  \end{pmatrix}
  \begin{pmatrix}
    \PC_{11} & \PC_{12} \\
    \PC_{21} & \PC_{22}
  \end{pmatrix}
\end{equation}
In practice this means a transformation (like a rotation) from the
pixel coordinates followed by a rescaling of the axes.

\subsection{From {\tt CROTAi} to the \PC\ and \CD\ matrices}

W. Pence\footnote{\emph{A User's Guide for the Flexible Image
Transport System (FITS)}, April 14, 1997, section: \emph{Transforming
to Projected Sky Coordinate}: {\tt https://fits.gsfc.nasa.gov/users\_guide/users\_guide/node57.html})}
explains how the {\tt CROTAi} values were used and interpreted in AIPS.
In particular, the {\tt CROTA2} value is meant to rotate the physical
coordinates, \ie\ \emph{after} the transformation from pixel to physical.
If $\delta_i$ is the value of {\tt CDELTi} and $\theta$ the latitude
angle represented by {\tt CROTA2}, this translates as a rescaling followed
by a rotation:
\begin{eqnarray}
\begin{pmatrix}
x_1 \\
x_2
\end{pmatrix}
& = &
\begin{pmatrix}
\cos \theta & -\sin \theta \\
\sin \theta &  \cos \theta
\end{pmatrix}
\begin{pmatrix}
\delta_1 & 0 \\
0        & \delta_2
\end{pmatrix}
\begin{pmatrix}
p_1 \\
p_2
\end{pmatrix}\\
& = &
\begin{pmatrix}
\delta_1 \cos \theta & - \delta_2 \sin \theta \\
\delta_1 \sin \theta &   \delta_2 \cos \theta
\end{pmatrix}
\begin{pmatrix}
p_1 \\
p_2
\end{pmatrix}\\
& = &
\begin{pmatrix}
\delta_1 & 0 \\
0        & \delta_2
\end{pmatrix}
\begin{pmatrix}
\cos \theta                    & -(\delta_2/\delta_1) \sin \theta \\
(\delta_1/\delta_2)\sin \theta &  \cos \theta
\end{pmatrix}
\begin{pmatrix}
p_1 \\
p_2
\end{pmatrix}
\end{eqnarray}
This means that the case of the {\tt CROTA2} rotation can be expressed
as a \PC\ matrix according to Eq.~\ref{eqn:CD2PC} with the values:
\begin{equation}
\label{eqn:PCfromROTA}
 \PC\ =
\begin{pmatrix}
\cos \theta                    & -(\delta_2/\delta_1) \sin \theta \\
(\delta_1/\delta_2)\sin \theta &  \cos \theta
\end{pmatrix}
\end{equation}
Its determinant is +1 in all cases. Or it can be expressed as a \CD\
matrix:
\begin{equation}
\label{eqn:CDfromROTA}
 \CD\ =
\begin{pmatrix}
\delta_1 \cos \theta & -\delta_2 \sin \theta \\
\delta_1 \sin \theta &  \delta_2 \cos \theta
\end{pmatrix}
\end{equation}
having in mind that the $\delta_i$, $\cos()$, and $\sin()$ signs are
now mixed in the matrix coefficients (loss of information), which will
bring ambiguities later on (section~\ref{txt:CDtoROTA}).\\

As stressed by W.Pence, the opposite transformation is not always
possible, \ie\ {\bf not all \PC\ (or \CD) matrices are equivalent to a
{\tt CROTA2} rotation} of the physical plane. For example, physical
axes may not be orthogonal with a random \PC\ matrix.

\subsection{From \PC\ matrix to {\tt CROTA2}}
\label{txt:PCtoROTA}

In the context of an equivalent {\tt CROTA2} rotation, the associated
rotation angle can be computed with the one of the two expressions
derived from Eq.~\ref{eqn:PCfromROTA}:
\begin{eqnarray}
\theta & =      & \mathrm{atan2} (-(\delta_1/\delta_2) \PC_{12},\PC_{22})\\
       & \equiv & \mathrm{atan2} (+(\delta_2/\delta_1) \PC_{21},\PC_{11})
\end{eqnarray}
Note they are strictly equivalent, whatever the $\delta_1$ or $\delta_2$
signs.

\subsection{From \CD\ matrix to {\tt CDELTi} and {\tt CROTA2}}
\label{txt:CDtoROTA}

Still in the context of an equivalent {\tt CROTA2} rotation, the
{\tt CDELTi} modulus can easily be computed from
Eq.~\ref{eqn:CDfromROTA}:
\begin{eqnarray}
 |\delta_1| & = & \sqrt{\CD_{11}^2+\CD_{21}^2} \label{eqn:mod1} \\
 |\delta_2| & = & \sqrt{\CD_{12}^2+\CD_{22}^2} \label{eqn:mod2}
\end{eqnarray}

The rotation angle can be computed from Eq.~\ref{eqn:CDfromROTA} {\bf if
$\delta_1$ and $\delta_2$ have the same sign}:
\begin{eqnarray}
\theta & =      & \mathrm{atan2} (-\CD_{12},\CD_{22}) \label{eqn:theta1} \\
       & \equiv & \mathrm{atan2} (+\CD_{21},\CD_{11}) \label{eqn:theta2}
\end{eqnarray}

If $\delta_1$ and $\delta_2$ have opposite signs, the above formulae
give values different by $\pm \pi$ (because
$\cos (\theta \pm \pi) = - \cos \theta$ and
$\sin (\theta \pm \pi) = - \sin \theta$). This can be anticipated by
checking if the $\CD_{11}/\CD_{22}$ ratio is negative. However, the
{\tt CROTA2} context enforces the $\theta$ unicity. The ambiguity we
are facing can only happen if one of the two axes was reversed (negative
increment). Considering that
\begin{equation}
 \CD
\equiv \CD' =
\begin{pmatrix}
|\delta_1| \cos \theta & -|\delta_2| \sin \theta \\
|\delta_1| \sin \theta &  |\delta_2| \cos \theta
\end{pmatrix}
\end{equation}
$\CD'$ is equivalent to \CD\ as it gives the same $|\delta_i|$ modulus and
this time consistent angles in Eqs.~\ref{eqn:theta1} and \ref{eqn:theta2}
(diagonal coefficients have same sign). Then one has to choose how to go
to $\CD'$:
\begin{enumerate}
\item assume $\delta_1<0$ and $\delta_2>0$: use $-|\delta_1|$ for {\tt CDELT1}
      value and thus swap $\CD_{11}$ and $\CD_{21}$ signs, or
\item assume $\delta_1>0$ and $\delta_2<0$: use $-|\delta_2|$ for {\tt CDELT2}
      value and thus swap $\CD_{12}$ and $\CD_{22}$ signs.
\end{enumerate}
These two options are valid but do not give the same $\theta$ angle
(again, different by $\pm \pi$)\footnote{These solutions are close to ones
exposed at appendix~\ref{app:reftorot}, except that additional scaling
factors are involved.}. The best choice might depend on the context,
otherwise it has to be arbitrary due to the lack of information.

\section{Conversion from FITS to GILDAS}

\subsection{\gildas\ support for coordinates}

\gildas\ (in particular the \gildas\ Data Format) does not support
fully generic transformations of the pixel coordinates to sky coordinates
as the FITS formalism does. It is basically able to describe a rescaling
(through the {\tt convert(:,3)} array) then optionally followed by a
rotation through the projection angle. This closely conforms to the
{\tt CROTA2} formalism. In other words, \gildas\ does not support
\PC\ or \CD\ matrices which can not be expressed as in
Eqs.~\ref{eqn:PCfromROTA} or \ref{eqn:CDfromROTA}.

\subsection{In practice}

In the simplest case, no \PC\ nor \CD\ matrix is defined. In this case, no
modification of the axis increments are applied and the rotation angle
is null.\\

If a \PC\ matrix is defined, it is checked if its determinant is +1.
If not, it can not be converted to the \gildas\ Data Format. If yes,
the equivalent {\tt CROTA2} rotation angle is computed as explained
in section~\ref{txt:PCtoROTA}. The {\tt CDELTi} values are left
unmodified.\\

Finally, if a \CD\ matrix is available, it is analyzed to be converted
to the GILDAS data format:
\begin{enumerate}
\item the moduli for {\tt CDELTi} are computed according to
      Eqs.~\ref{eqn:mod1} and \ref{eqn:mod2}.
\item if the matrix describes a {\tt CROTA2} rotation, it should satisfy
      $|\delta_1|/|\delta_2| = |\CD_{11}/\CD_{22}|$. If not, the
      matrix is \emph{skewed} and can not be converted to \gildas\ Data
      Format.
\item if the ratio $\CD_{11}/\CD_{22}$ is positive, both $\delta_i$ are
      assumed positive.
\item if the ratio $\CD_{11}/\CD_{22}$ is negative, one of the
      solutions proposed at section~\ref{txt:CDtoROTA} has to
      be applied. Swapping the first axis is prefered, assuming we face
      an astronomical image where X coordinate increase to left (\ie\
      towards to East).
\item the rotation angle $\theta$ is finally computed from
      Eqs~\ref{eqn:theta1} or \ref{eqn:theta2}, using the \CD\
      coefficients (swapped if relevant).
\end{enumerate}

\newpage
\appendix

\section{Reflection as a rotation}
\label{app:reftorot}

% It is noted that the combination of a rotation and a reflection can always
% be expressed under a single reflection:
% \begin{equation}
% \mathrm{Rot(\theta)} \, \mathrm{Ref(\phi)} = \mathrm{Ref(\phi+\frac{1}{2}\theta)}
% \end{equation}
% \begin{equation}
% \mathrm{Ref(\phi)} \, \mathrm{Rot(\theta)} = \mathrm{Ref(\phi-\frac{1}{2}\theta)}
% \end{equation}

A reflection matrix can be expressed as a rotation matrix by swapping the
sign of one of the 2 axes:
\begin{eqnarray}
\mathrm{Ref \left(\frac{\theta}{2}\right)}
\begin{pmatrix}
p_1 \\
p_2
\end{pmatrix}
      & = &
\begin{pmatrix}
\cos \theta &  \sin \theta \\
\sin \theta & -\cos \theta
\end{pmatrix}
\begin{pmatrix}
p_1 \\
p_2
\end{pmatrix} \label{eqn:conv1}\\
      & = &
\begin{pmatrix}
p_1 \cos \theta + p_2 \sin \theta \\
p_1 \sin \theta - p_2 \cos \theta
\end{pmatrix} \label{eqn:conv2} \\
      & = &
\begin{pmatrix}
-p_1 (- \cos \theta) + p_2 \sin \theta \\
-p_1 (- \sin \theta) - p_2 \cos \theta
\end{pmatrix} \label{eqn:conv3} \\
      & = &
\begin{pmatrix}
- \cos \theta &  \sin \theta \\
- \sin \theta & -\cos \theta
\end{pmatrix}\begin{pmatrix}
-p_1 \\
p_2
\end{pmatrix} \label{eqn:conv4}\\
      & = &
-\mathrm{Rot (\theta)}
\begin{pmatrix}
-p_1 \\
p_2
\end{pmatrix} \label{eqn:conv5}\\
      & = &
\mathrm{Rot (\theta+\pi)}
\begin{pmatrix}
-p_1 \\
p_2
\end{pmatrix} \label{eqn:conv6}
\end{eqnarray}
but it can also be written as (swapping signs of the two operands
from Eq.~\ref{eqn:conv4}):
\begin{eqnarray}
      & = &
\begin{pmatrix}
\cos \theta & -\sin \theta \\
\sin \theta &  \cos \theta
\end{pmatrix}\begin{pmatrix}
p_1 \\
-p_2
\end{pmatrix} \label{eqn:conv7}\\
      & = &
\mathrm{Rot (\theta)}
\begin{pmatrix}
p_1 \\
-p_2
\end{pmatrix} \label{eqn:conv8}
\end{eqnarray}
The two conversions are strictly equivalent. In practice, one just needs
to:
\begin{itemize}
\item swap the signs of $p_1$ and the coefficients of the first column
      (Eq.~\ref{eqn:conv1} vs \ref{eqn:conv4}), or
\item swap the signs of $p_2$ and the coefficients of the second column
      (Eq.~\ref{eqn:conv1} vs \ref{eqn:conv7}).
\end{itemize}


\end{document}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
