-
- ARD — A Textual Language for Describing Regions within a Data Array
- Next→
- TOC ↑
1 Introduction
Astronomical applications often require the user to identify regions of interest within a data array. For
instance a statistics application may need to be told the region within the input image in which it is to
evaluate the pixel statistics. Another example is a data calibration application which needs to be told
the regions in which the detector was unreliable so that it can flag the corresponding output pixels as
bad.
One way of identifying such regions is through the use of a pixel mask. In a pixel mask, different pixel
values are used to differentiate between those pixels which are to be included by the application and
those which are to be excluded. Such pixel masks are usually the same size and shape as the data
array being processed by the application (so that a one-for-one correspondence exists between mask
pixels and data pixels). This results in such masks occupying large amounts of disk space. More
importantly, it means that different pixel masks are required for data arrays with different sizes or
shapes.
ARD circumvents these problems by using textual expressions (known as “ARD descriptions”) to
describe the pixels to be included by the application. Multi-dimensional data arrays can be handled. A
simple 2-dimensional ARD description such as:
CIRCLE( 20, 20, 5 ) .OR. RECT( 20, 20, 30, 30 )
tells the application to process all pixels which are either within a circle centred on pixel coordinates
(20,20) with a radius of 5 pixels, or are within the rectangle with opposite corners at pixels coordinates
(20,20) and (30,30). The ARD_WORK subroutine will convert an ARD description such as this into a
pixel mask, with a shape and size specified by the application. The application will usually know the
shape and size of the data array and so can ask ARD_WORK to create a pixel mask of the correct
shape and size. Once the pixel mask is no longer needed, the storage space used to hold
the mask can be released; there is no need to keep permanent copies of the pixel mask on
disk.
As well as creating pixel masks, the ARD library also provides facilities to plot an ARD
description on a graphics device. The ARD_PLOT routine draws the borders of the regions
described in the ARD description, using a supplied AST Plot (see SUN/210) to perform the
graphics.
In the above example, positions and distances in the ARD description were given in pixel coordinates.
The ARD language includes two systems which allow positions and distances to be given in other
coordinate systems:
-
(1)
- As of ARD version 2.0, the calling application can define an arbitrary collection of
coordinate systems (which need not be linearly related to pixel coordinates) by supplying
an AST FrameSet (see SUN/210). The FrameSet contains information which allows
positions to be mapped from any of these coordinate systems into pixel coordinates.
Positions within the ARD description can then be given in any of these coordinates
systems (a statement in the ARD description indicating which system is being used).
Thus, for instance, if the pixel array has an RA/DEC calibration, the application could
supply a FrameSet indicating how to convert from RA/DEC to pixel coordinates. This
would allow the ARD description to include positions in RA/DEC.
In addition, the ARD description itself can include a FrameSet defining a collection of
inter-related coordinate systems (positions in the ARD description should be given in the
"current" Frame of this FrameSet). In this case, an attempt is made to find a coordinate
system which is contained both within the FrameSet supplied by the calling application,
and within the FrameSet supplied in the ARD description. For instance, extending the
previous example, if an ARD description contains position given in pixel coordinates
in some other specific image and also contains a FrameSet which relates pixel positions
within that image to RA/DEC, then positions will be mapped from pixel coordinates
within the original image, into RA/DEC, and then into pixel coordinates within the
required mask image. This effectively allows pixel positions to be given within one image
and then transformed so that they can be used within another image.
-
(2)
- The calling application can also define an “application coordinate system” which is
linearly related to pixel coordinates. Positions within the ARD description can then either
be given directly in application coordinates, or in any coordinate system linearly related
to application coordinates (in which case the ARD description must include statements
describing the linear transformation). This system was present in version 1 of ARD and
is still present in the current version, but is now deprecated in favour of the above more
general system.
1.1 Some Example ARD Descriptions
ARD descriptions are made up by using logical operators (.AND., .OR., .NOT., etc.) to combine
together keywords which represent the basic shapes known to ARD. statements can also be included
which modify the way the ARD description is interpreted (for instance, by setting up an alternative
coordinate system).
The ARD library includes two subroutines (ARD_GROUP and ARD_GRPEX) which simplify the task
of obtaining ARD descriptions from the user or environment. Using these routines, an ARD
description can be supplied to an application either directly, or by storing it in a text file and supplying
the name of the text file to the application. The following examples represent lines stored in a text file.
Such lines are effectively concatenated together into a single string before being processed by
ARD:
ROTBOX( 0, 0, 20, 10, 30 )
This example is simply a single keyword representing one of the basic shapes known to ARD. It selects all
pixels which have centres on or within a 2-dimensional rotated box. The box is centred on coordinates
(0,0) and has sides of length 20 and 10. The first side of the box (i.e. the one with length 20) is at an angle of
to the
array X axis (measured anti-clockwise).
CIR( 0, 0, 10 ) .AND. .NOT. ( COLUMN( 10 ) .OR. ROW( 5 ) )
This example uses logical operators and parentheses to combine several basic shapes together into a
more complex shape. It also shows the use of abbreviated keywords. All pixels within the circle of
radius 10 centred on (0,0) are selected, except for those which are on column 10 or row
5.
COFRAME( SKY, System=FK5, Equinox=2003.5 )
BOX( 12:23:41, -89:14, 1h40m, 20m )
This example shows the use of statements to specify the coordinate system in which positions are
supplied. In this case, the COFRAME statement indicates that positions are supplied in FK5 equatorial
(RA/DEC) coordinates, referred to the equinox of 2003.5. The BOX keyword then selects a box centred at RA
and Dec.
. The box covers an
RA range of and
a Dec range of .
The edges of a BOX region are always lines of constant axis value. Since this region is very close to the
south equatorial pole, the pixel region containing this "box" will have quite strongly curved
sides.
PIXEL( 1, 1 )
PIXEL( 20, 13 )
PIXEL(-55,122 )
PIXEL(112, 87 )
PIXEL( 33, 12 )
This example demonstrates the ability of ARD to recognise implicit .OR. operators. The list of PIXEL
keywords specifies a set of individual pixels. Since these keywords have no intervening operators,
ARD assumes that a .OR. operator is to be inserted between each pair, i.e. the union of all the
individual pixels is assumed.
1.2 An Example ARD Application
This section presents Fortran code for an ADAM application which obtains a data array (in the form of
an NDF structure, see SUN/33) and an ARD description from the environment, converts the ARD
description into a pixel mask, and then finds and displays the data sum within the region specified by
the ARD description. The application will deal with NDFs of any dimensionality up to the limit
imposed by the NDF_ system.
SUBROUTINE ARD_TEST( STATUS ) [1]
IMPLICIT NONE
* Include definitions of global constants.
INCLUDE ’SAE_PAR’ [2]
INCLUDE ’NDF_PAR’
INCLUDE ’PRM_PAR’
INCLUDE ’GRP_PAR’
INCLUDE ’AST_PAR’
* Declare local variables.
INTEGER STATUS, IGRP, INDF, NDIM, IPDATA, IPMASK, EL,
: LBND( NDF__MXDIM ), UBND( NDF__MXDIM ), [3]
: LBNDI( NDF__MXDIM ), UBNDI( NDF__MXDIM ),
: LBNDE( NDF__MXDIM ), UBNDE( NDF__MXDIM ),
: REGVAL
REAL SUM, TRCOEF( 1 )
INTEGER IWCS
* Check inherited global status.
IF ( STATUS .NE. SAI__OK ) RETURN [4]
* Obtain an identifier for the input NDF.
CALL NDF_ASSOC( ’NDF’, ’READ’, INDF, STATUS ) [5]
* Obtain the bounds of the NDF.
CALL NDF_BOUND( INDF, NDF__MXDIM, LBND, UBND, NDIM, [6]
: STATUS )
* Map the DATA component of the NDF.
CALL NDF_MAP( INDF, ’DATA’, ’_REAL’, ’READ’, IPDATA, EL, [7]
: STATUS )
* Obtain an ARD description specifying the region in which
* the pixel values are to be summed.
CALL ARD_GROUP( ’REGION’, GRP__NOID, IGRP, STATUS ) [8]
* Obtain workspace to hold the pixel mask corresponding to
* the supplied ARD description.
CALL PSX_CALLOC( EL, ’_INTEGER’, IPMASK, STATUS ) [9]
* Get an AST FrameSet describing the WCS coordinate Frames stored
* in the NDF.
CALL NDF_GTWCS( INDF, IWCS, STATUS ) [10]
* Indicate that positions within the ARD description can be given in
* any coordinate Frame included in the above WCS FrameSet.
CALL ARD_WCS( IWCS, ’ ’, STATUS ) [11]
* Indicate that the value 2 should be used to represent
* pixels specified by the first keyword in the ARD
* description.
REGVAL = 2
* Call ARD_WORK to store positive values at all mask pixels
* specified by the ARD description, and zero at all other
* pixels.
CALL ARD_WORK( IGRP, NDIM, LBND, UBND, TRCOEF, .FALSE., [12]
: REGVAL, %VAL( IPMASK ), LBNDI, UBNDI,
: LBNDE, UBNDE, STATUS )
* Call a subroutine to sum the data in the specified regions.
CALL SUMIT( EL, %VAL( IPDATA ), %VAL( IPMASK ), SUM,
: STATUS ) [13]
* Display the data sum.
CALL MSG_SETR( ’SUM’, SUM )
CALL MSG_OUT( ’ARD_TEST_MSG1’, ’ Data sum: ^SUM’, [14]
: STATUS )
* Release the work space used to hold the pixel mask.
CALL PSX_FREE( IPMASK, STATUS ) [15]
* Delete the group used to hold the ARD description.
CALL GRP_DELET( IGRP, STATUS ) [16]
* Annul the AST FrameSet identifier.
CALL AST_ANNUL( IWCS, STATUS ) [17]
* Annul the NDF identifier.
CALL NDF_ANNUL( INDF, STATUS ) [18]
END
Programming notes:
-
(1)
- The example is actually an ADAM A-task, and so consists of a subroutine with a single
argument giving the inherited status value. See SUN/101 for further details about writing
ADAM A-tasks. A “stand-alone” equivalent to the ARD_GROUP routine is available
which can be used with non-ADAM applications.
-
(2)
- The INCLUDE statements are used to define the various “symbolic constants”, which
are used in this routine. Starlink software makes widespread use of such constants,
which should always be defined in this way rather than by using actual numerical
values. They are recognisable by the double underscore “__” (e.g. “SAI__OK”) which
distinguishes them from subroutine names. SAE_PAR defines constants starting with
“SAI__”, NDF_PAR defines constants starting with “NDF__” (see SUN/33), PRM_PAR
defines constants starting with “VAL__” (see SUN/39), GRP_PAR defines constants
starting with “GRP__” (see SUN/150), and AST_PAR defines constants starting with
“AST__” (see SUN/210).
-
(3)
- This application is designed to be able to handle data arrays of any dimensionality,
up to the limit set by the NDF library. This limit is given by the symbolic constant
NDF__MXDIM, which is used in the declaration of various arrays used to hold
information describing each axis.
-
(4)
- The value of the STATUS argument is checked. This is because the application uses the
Starlink error handling strategy (see SUN/104), which requires that a subroutine should
do nothing unless its STATUS argument is set to the value SAI__OK on entry. Here, we
simply return without action if STATUS has the wrong value.
-
(5)
- The input NDF is now obtained using the ADAM parameter ’NDF’. This may involve
prompting the user, or the NDF may be identified using some other means (for instance,
the NDF may have been specified on the command line which invoked the application).
An integer value is returned to the application in variable INDF. This is an NDF identifier
and is used to refer to the NDF throughout the rest of the application.
-
(6)
- The shape and size of the NDF is now obtained. This returns the number of dimensions,
and the upper and lower bounds on each axis. These bounds are needed to be able to
correctly locate positions supplied within the ARD description.
-
(7)
- The DATA array in the NDF is then accessed by calling NDF_MAP. Rather than returning
actual data values, this routine returns a pointer to the data values in IPDATA. The total
number of pixels in the array is returned in EL.
-
(8)
- Next, the ARD description is obtained using ADAM parameter ’REGION’. The returned
ARD description is stored in a “GRP group” (rather like a Fortran character array).
The GRP package is described in SUN/150 and programmers using ARD should be
aware of its contents. An integer value is returned in IGRP which is used to identify the
group containing the ARD description throughout the rest of the application. The second
argument is a “null group identifier” (a symbolic constant defined within the include file
GRP_PAR). It is used to indicate that there is no existing ARD description on which to
base the new ARD description; a completely new ARD description must be supplied.
-
(9)
- We now obtain a pointer to a temporary array in which we can store the pixel mask
corresponding to the ARD description. The mask has the same number of pixels as the
data array, and each pixel stores an integer value. The PSX library is a Fortran interface
to the POSIX library and is described in SUN/121.
-
(10)
- An NDF structure can have a range of “World Coordinate Systems” associated with
it. Information describing these coordinate systems, and how to transform positions
between them, is stored in the WCS component of the NDF. The NDF_GTWCS routine
returns an identifier for an AST FrameSet which is a representation of the WCS
component. The facilities of the AST library can then be used to manipulate the WCS
information in many different ways.
-
(11)
- ARD_WCS stores the supplied FrameSet pointer for later use by the ARD_WORK
routine. Making this call to ARD_WCS is optional. If it were not made, then positions
within the ARD description would have to be supplied in pixel coordinates. Since we are
in fact calling ARD_WCS, positions within the ARD description can be supplied in any
coordinate system which can be related to any of the coordinate systems in the NDF’s
WCS FrameSet.
-
(12)
- The subroutine ARD_WORK is now called to create the pixel mask identifying the pixels
specified by the ARD description. Positive values are stored in the mask for such pixels,
and zero is stored for all other pixels. Note, no value need be assigned to the TRCOEF
argument since it will be ignored anyway. This is because of the earlier call to ARD_WCS
which specifies the WCS information, and makes the TRCOEF argument redundant.
-
(13)
- A subroutine is now called to add up the pixel values in the regions specified by the ARD
description. The pointer values returned by NDF_MAP and PSX_CALLOC are turned
into actual Fortran arrays at this point, which SUMIT can access. This is done using the
%VAL function in the call to SUMIT. SUMIT is not part of the ARD package, but would
be written by the application programmer. It may look like this:
SUBROUTINE SUMIT( EL, DATA, MASK, SUM, STATUS )
IMPLICIT NONE
* Include definitions of global constants.
INCLUDE ’SAE_PAR’
INCLUDE ’PRM_PAR’
* Arguments Given.
INTEGER EL
REAL DATA( EL )
INTEGER MASK( EL )
* Arguments Returned.
REAL SUM
* Arguments Given and Returned.
INTEGER STATUS
* Declare local variables.
INTEGER I
* Check inherited global status.
IF ( STATUS .NE. SAI__OK ) RETURN
* Initialise the sum of the valid data values.
SUM = 0.0
* Loop round every element in the data array.
DO I = 1, EL
* Check to see if this pixel was included in the ARD
* description. It will have a positive mask value if it was.
* Skip over the pixel if it was not included.
IF( MASK( I ) .GT. 0 ) THEN
* The regions selected by the ARD description may contain
* pixels which are flagged as unusable in the input NDF.
* Such pixels have the value given by the symbolic constant
* VAL__BADR and should not be included in the returned data
* sum.
IF( DATA( I ) .NE. VAL__BADR ) THEN
SUM = SUM + DATA( I )
END IF
END IF
END DO
END
The two arrays can be treated as one dimensional vectors because they are the same size and
shape. This makes it easy to process arrays of any dimensionality.
-
(14)
- The data sum is displayed by assigning its value to an “MSG token” and then incorporating this
token into a message to be displayed on the standard output device. See SUN/104 for a
description of the MSG package.
-
(15)
- The storage space used to hold the pixel mask is released so that it can be re-used.
-
(16)
- The storage space used by the GRP group to hold the ARD description is released.
-
(17)
- We now tell the AST library to release the resources used to store the FrameSet read from the
NDF.
-
(18)
- Finally, the NDF is closed.
1.3 Supplying ARD Descriptions to an Application
This section outlines some of the ways in which a user could supply an ARD description in response
to a prompt for the ’REGION’ parameter in the example application described in the previous
section.
The first thing to be said is that the dimensionality of the ARD description (i.e. the number of values
used to represent a single position in the ARD description) need not match that of the supplied NDF.
The ARD description may refer to some subset of the axes in the NDF, in which case the mask will be
applied independently to every value on the unspecified axes. By default, ARD descriptions are
always assumed to be 2-dimensional, but this default can be over-ridden by including a
DIMENSION statement in the ARD description. Thus for instance, if the positions in the
ARD description are 3-dimensional, the user may want to give an ARD description such
as:
DIMENSION( 3 )
CIRCLE( 40, 50, 60, 10) .OR. CIRCLE( 45, 55, 65, 10 )
The DIMENSION statement tells ARD to expect three values per position. The rest of the ARD
description specifies the union of two spheres (i.e. “3-dimensional circles”), centred on (40,50,60) and
(45,55,65), each of radius 10. This ARD description uses the default coordinate system established by
the application’s call to ARD_WORK. In the case of the application above, this default coordinate
system is just the pixel coordinate system of the NDF.
ARD uses the versatile facilities of the GRP package to obtain the ARD description. The following
examples outline some of the ways in which the above ARD description could be specified in response to
a prompt for parameter ’REGION’. For more details on the facilities of GRP, see SUN/150. In each case
the “”
represents the final character of the prompt string issued by the ADAM parameter system and is not
actually typed in by the user:
-
(1)
- The entire ARD description could be given as a single literal string:
> DIMENSION(3) CIRCLE( 40, 50, 60, 10) .OR. CIRCLE( 45, 55, 65, 10 )
All blanks and tabs are ignored.
-
(2)
- The ARD description could be split up into several strings given in response to successive
prompts. This is particularly useful for long ARD descriptions:
> DIMENSION(3) -
> CIRCLE( 40, 50, 60, 10) .OR. -
> CIRCLE( 45, 55, 65, 10 )
If an ARD description ends with a minus sign
(“”),
the ARD_GROUP subroutine will issue another prompt and append any string supplied to the
end of the previously supplied string. This continues until an ARD description is supplied
which doesn’t end with a minus sign.
-
(3)
- ARD descriptions can be split anywhere except in the middle of a numerical value. So, for
instance, the following responses would be valid:
> DIMENSION(3) CIRCLE( 40, 50, -
> 60, 10) .OR. CIRCLE( 45, 55, -
> 65, 10 )
-
(4)
- If ARD finds adjacent keywords without any intervening operator, an implicit .OR. is inserted
between them. So the following, in which the .OR. operator is not explicitly included, would
give the same results as the previous examples:
> DIMENSION(3) -
> CIRCLE( 40, 50, 60, 10 ) -
> CIRCLE( 45, 55, 65, 10 )
-
(5)
- Instead of supplying the ARD description directly in response to the parameter prompt, it can be
stored in a text file and the name of the text file given in response to the prompt. To do this, the
file name must be preceded by an up-arrow symbol (“^”). If the file desc.ard contained the three
lines:
DIMENSION(3)
CIRCLE( 40, 50, 60, 10 )
CIRCLE( 45, 55, 65, 10 )
then the user could give the following response:
The ARD description can be split between the lines of the file in any way the user
chooses.
-
(6)
- If only part of the ARD description is stored in a text file, then the two methods can be
combined. For instance, if the DIMENSION statement is omitted from the file, so that desc.ard
contains:
CIRCLE( 40, 50, 60, 10 )
CIRCLE( 45, 55, 65, 10 )
then the user could give the complete ARD description by giving the following response:
This would cause the contents of the file desc.ard to be concatenated with the string preceding
the “;” character. Note, the semi-colon is not included in the ARD description returned by
ARD_GROUP.
-
(7)
- If the ARD description were to be split over several files, the contents of the files could be
concatenated together in a similar way:
> ^desc1.ard;^desc2.ard;^desc3.ard
This would cause the contents of files desc1.ard, desc2.ard and desc3.ard to be combined to
form the final ARD description.
-
(8)
- Indirection through text files can be nested. So if the string
^desc1.ard;^desc2.ard;^desc3.ard
were stored in a file total.ard, then the user could give the response:
-
- ARD — A Textual Language for Describing Regions within a Data Array
- Next→
- TOC ↑