18.1 Pixel Coordinates

18.2 Axis Coordinates

18.3 Axis Arrays

18.4 Pixel Positions and Dimensions

18.5 Default Axis Array Values

18.6 Contiguous and Non-Contiguous Pixels

18.7 Processing Axis Array Values

18.8 Axis Normalisation

18.2 Axis Coordinates

18.3 Axis Arrays

18.4 Pixel Positions and Dimensions

18.5 Default Axis Array Values

18.6 Contiguous and Non-Contiguous Pixels

18.7 Processing Axis Array Values

18.8 Axis Normalisation

This section describes the concepts which an NDF’s *axis* coordinate system represents. The following
section (§19) then goes on to consider how to access an NDF’s *axis* components, which hold
information about this coordinate system.

Hitherto, an NDF has been considered simply as an N-dimensional array of pixels, addressed by a set of pixel indices. Since they are integer quantities, these indices cannot represent a continuous coordinate system, although the information stored in an NDF will almost always require that positions within it be describable to sub-pixel accuracy. For example, a calculation to determine the centroid position of a star in a 2-dimensional image will inevitably give rise to a non-integer result, for which a continuous ($x,y$) coordinate system will be required.

There are a number of ways in which a continuous coordinate system can be defined for a regular array of pixels.
In the absence of other information, the NDF convention is to use a *pixel coordinate system* in which a pixel with
indices ($i,j$)
has its centre at the position:

($i-\frac{1}{2},j-\frac{1}{2}$)

and is taken to be one unit in extent in each dimension. Pixel (1,1) would therefore be centred at the position (0.5,0.5) and would have its “lower” and “upper” corners located at positions (0.0,0.0) and (1.0,1.0) respectively, as follows:

This makes it possible to refer to fractional pixel positions—in this case within a 2-dimensional array, although the principle can obviously be extended to other numbers of dimensions.

The pixel coordinate system described above defines how to convert pixel indices into a set of
continuous coordinates and therefore introduces a coordinate *axis* which runs along each dimension of
the NDF, as follows:

The use of the pixel size to determine the units of these axes is rather restrictive, however, and in practice we may want to use more realistic physical units. This would allow a spectrum to be calibrated in wavelength, for instance, or the output from a plate-measuring machine to be related to axes calibrated in microns.

Of course, the pixel coordinate system is only the default choice, and is intended to be used only in the
absence of other information. The NDF’s *axis* components are designed to hold the extra information
needed to define more useful coordinate systems, so that realistic axes can be associated with
a NDF, along with *labels* and *units* for these axes. The method used also allows for the
possibility that an NDF’s pixels may not be square and that they may not be contiguous
(*i.e.* that they may have gaps between them, or may overlap) when their positions are
expressed in *axis* units. Statistical uncertainty in the pixel positions may also be represented, if
present.

To define the pixel coordinate system in §18.1, we specified the location of each pixel
by giving its *centre* position and *width* on each *axis*. Thus, for a given dimension,
the pixel *centre* position C was derived from the corresponding pixel index
$i$
according to the formula:

$C\left(i\right)=i-\frac{1}{2}$

and its *width* W was given by:

$W\left(i\right)=1$

An NDF’s *axis* coordinate system extends this idea by allowing each of these *centre* and *width*
functions to be determined by values stored in a 1-dimensional array. These *axis arrays* then act as
“look-up tables” which convert pixel indices into pixel *centre* coordinates and *width* values on each
*axis:*

This allows a wide range of possible coordinate systems to be accommodated. A third
*axis variance* array is also provided as a look-up table to convert pixel indices into *variance*
estimates, which can be used to represent any possible statistical uncertainty in a pixel’s *centre*
position.

If C${}_{n}$ and
W${}_{n}$
represent the *axis centre* and *width* arrays for the n’th dimension of an NDF,
then a pixel with index i in this dimension has its *centre* at coordinate
C${}_{n}$(i) and has a
*width* of W${}_{n}$(i)
on the corresponding *axis*. It therefore extends along the *axis* from the point:

${C}_{n}\left(i\right)-\frac{1}{2}{W}_{n}\left(i\right)$

to the point:

${C}_{n}\left(i\right)+\frac{1}{2}{W}_{n}\left(i\right)$

In two dimensions the central ($x,y$) coordinate of a pixel with indices ($i,j$) would therefore be given by:

$\left(x,\phantom{\rule{2.43306pt}{0ex}}y\right)=\left(\phantom{\rule{2.43306pt}{0ex}}{C}_{1}\left(i\right),\phantom{\rule{2.43306pt}{0ex}}{C}_{2}\left(j\right)\phantom{\rule{2.43306pt}{0ex}}\right)$

and its size would be:

$\Delta x\phantom{\rule{2.43306pt}{0ex}}\times \phantom{\rule{2.43306pt}{0ex}}\Delta y={W}_{1}\left(i\right)\phantom{\rule{2.43306pt}{0ex}}\times \phantom{\rule{2.43306pt}{0ex}}{W}_{2}\left(j\right)$

The *axis variance* array is used to represent any statistical uncertainty
in a pixel’s *centre* position and hence in the position of the pixel as a
whole.^{16}
Like the NDF’s main *variance* component (§8.9), its values are estimates of the mean squared error in
the pixel’s position, so the value which would normally be quoted as the positional uncertainly (or
used to plot error bars) is the square root of this value. *Axis variance* arrays may also be accessed
directly as standard deviation values if required (see §19.10).

An important feature of each *axis* array is a set of default values which serve to define the *axis*
coordinate system in the absence of complete information. In the simplest case (*i.e.* no information),
this reduces to the pixel coordinate system discussed in §18.1. The following describes how default
values are obtained for each *axis* array:

- Centre:
- If values are required for an
*axis centre*array and none have been provided, then its values are set equal to $i-\frac{1}{2}$, where $i$ is the pixel’s index in the relevant dimension. Thus, if an NDF had pixel-index bounds (3:10) in a particular dimension, the default*axis centre*array values for this dimension would be:2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5 - Width:
- If values are required for an
*axis width*array and none have been defined, then its values are derived from the corresponding*axis centre*array by forming differences between the*centre*coordinates of the neighbouring pixels,*i.e.*the default*width*values are obtained as follows:^{17}${W}_{n}\left(i\right)=\frac{1}{2}|{C}_{n}\left(i+1\right)-{C}_{n}\left(i-1\right)|$This means that the default pixel

*widths*match the local average spacing between pixel*centres*, which is usually appropriate. Note, however, that this does not guarantee that the pixels will be contiguous (*i.e.*that their edges will meet exactly) except in cases where the pixel*centres*are uniformly spaced (see §18.6). - Variance:
- If no
*axis variance*array values have been defined, then they default to zero, implying no uncertainty in the pixel*centre*positions.

It is important to note that the meanings attached to an NDF’s *axis* arrays are defined rather precisely.
In particular, note that the *axis centre* array specifies the position of the geometrical *centre* of a pixel,
*i.e.* the mid-point between its edges, so that a pixel will always extend by an equal amount on either
side of this position.

The edges of adjacent pixels will therefore only meet exactly (*i.e.* there will be no overlap or gap) if
their *centre* and *width* values are related in the correct way. To be precise, adjacent pixels with indices
$i$ and
$i+1$ must
have *centre* positions separated by half the sum of their *widths* if they are to be contiguous along a
particular *axis*, so that:

$|{C}_{n}\left(i+1\right)-{C}_{n}\left(i\right)|=\frac{1}{2}\left[{W}_{n}\left(i+1\right)+{W}_{n}\left(i\right)\right]$

With contiguous pixels (the normal case), this means that the *axis centre* and *width* arrays are not
independent. In fact, either could be derived from the other to within a constant, but since this
constant cannot be found without additional information, it is often necessary to store both arrays.
However, an important exception occurs if the pixel *centres* are evenly spaced, because a convenient
method then exists of deriving the *width* array from the *centre* array so that contiguous pixels
always result. This is the method used to generate default *axis width* values when necessary
(§18.5).

To avoid any potential ambiguity about the interpretation of *axis* array values and whether an NDF’s
pixels should be considered contiguous or not, the following recommendations are given about the
information which should be stored in *axis* arrays:

- If the default NDF pixel coordinate system is satisfactory, then it should be used and
no
*axis*coordinate information should be defined. In this case the pixels will always be contiguous. - Otherwise, if the pixel
*centres*are evenly spaced, then...- If the pixels are contiguous, the
*axis centre*array should be assigned values but the associated*width*array may be left undefined. - If the pixels are not contiguous, both the
*axis centre*and*width*arrays should be assigned values.

- If the pixels are contiguous, the
- Otherwise, if the pixel
*centres*are un-evenly spaced, then both the*axis centre*and*width*arrays should always be assigned values.

The method by which NDF *axis* arrays are processed should also reflect their meanings, as defined
above. By way of illustration, suppose that a transformation of *axis* values is to be performed, so that
each *axis* coordinate is converted to a new value by means of some non-linear function. Rather than
simply applying this function to calculate new pixel *centre* locations from the old ones, the correct
procedure is to transform the pixel edge locations and to derive new *centre* positions from these, as
follows:

- (1)
- Obtain the relevant pixel
*centre*and*width*arrays, accepting their default values if necessary. - (2)
- From these, calculate the positions of the edges of each pixel.
- (3)
- Transform the edge positions using the non-linear transformation function.
- (4)
- Calculate new pixel
*centre*positions (mid-way between the new edge positions) and store them in the NDF’s*axis centre*array. - (5)
- Calculate associated pixel
*width*values (from the difference in the pixel edge positions). Since the pixel*centres*will now be non-uniformly separated, these new*width*values should also be stored in the NDF’s*axis width*array. - (6)
- If
*axis variance*array values are available, then these should be propagated through the transformation function using the usual error-propagation formulae.

This procedure is necessary to ensure that the pixels remain contiguous (or non-contiguous, if
appropriate) and that the new *centre* positions lie mid-way between the new pixel edge locations.
Furthermore, the operations above can all be reversed if necessary to recover the original *axis* array
values.

One aspect of the *axis* coordinate system which has not yet been discussed is the property of *axis
normalisation*, which is indicated by a logical *normalisation flag* associated with each *axis*. This flag
does not affect the interpretation of the *axis* information itself, but instead determines how
the NDF’s *data* and *variance* arrays should behave when the associated *axis* information is
modified.

If the normalisation flag for an NDF *axis* is set to .TRUE., then it indicates that the NDF’s *data* values
(and by implication its *variance* values) are *normalised* to the pixel *width* values for that *axis*. To give an
example, suppose that a spectrum contains *data* values representing energy accumulated per unit of
wavelength, with each pixel having a known spread in wavelength. In this case, the sum of
each pixel’s *data* value multiplied by its *width* will give the total energy in any part of the
spectrum. This is an important property which may need to be retained if the *axis width*
values are altered for any reason (*e.g.* to apply an instrumental correction, or to allow for
red-shift).

The *axis* normalisation flag indicates whether this type of normalisation should be
preserved. If it is set to .TRUE., and the associated *axis width* values are modified, then
each NDF *data* value should be multiplied by an appropriate factor so that its *data*
$\times $ *width*
product remains unchanged. If present, the *variance* values should also be corrected by multiplying by
the square of this factor. In cases where more than one *axis* normalisation flag is set to .TRUE., the
correction factors for each *axis* must be applied in turn.

If all the *axis* normalisation flags are set to .FALSE. (the default situation), then no changes to the *data*
or *variance* components will be necessary if the *axis width* values are modified.

^{16}There is no corresponding provision for recording any uncertainty in a pixel’s *width*.

^{17}If either of the neighbouring *centre* values does not exist (because the pixel is at the end of the array) then it is replaced
by C${}_{n}\left(i\right)$ and
the $\frac{1}{2}$ in
the formula is dropped. If neither neighbour exists (because the NDF’s dimension size is 1) then the *width* value is set to
unity. Note that the default *centre* array values will be used if none have been defined, and this will also result in *width*
values of unity.