### 5 Carrying on

5.3 Expressions
5.4 Selections
5.5 Indices

This section will briefly introduce some features of the CAT library which were not covered in the preceding example: celestial coordinates, vector columns, expressions, selections and indices. The description is introductory and informal; for a full description of these topics you should see the reference material in Part III.

#### 5.1 Celestial coordinates in catalogues

Most astronomical catalogues contain columns of celestial coordinates of some sort: usually Right Ascension and Declination for some equinox and epoch, or perhaps Galactic or ecliptic coordinates. The storage, manipulation and presentation for display of celestial coordinates in the computer-readable version of astronomical catalogues is something of a vexed topic which has caused a deal of confusion and difficulty, much of it, in principle, unnecessary. Celestial coordinates are angles. The basic conundrum in storing and processing them is as follows:

• for use in computations inside a program the only sensible way to represent coordinates is as DOUBLE PRECISION or REAL numbers expressed in radians,
• for display to a user the coordinates should almost invariably be expressed in units of hours or degrees and formatted as a sexagesimal value, with subdivisions into minutes and seconds.

For preexisting catalogues the format of the celestial coordinates will already be fixed and they must simply be used in whatever way is possible. For example, many catalogues contain the hours, or degrees, minutes and seconds which comprise a coordinate as separate columns; a form which is singularly inconvenient for further processing. However, CAT has some special facilities for processing and displaying angles which conveniently and automatically provide for:

• representation inside a program as a DOUBLE PRECISION or REAL number expressed in radians,
• representation for display to a user as a CHARACTER string expressed in hours or degrees and formatted as a sexagesimal value.

This facility works as follows:

• when the value for a field in a column containing angles is obtained using
CAT_EGT0D or CAT_EGT0R it is returned as a DOUBLE PRECISION or REAL value in radians,
• when the value for a field in a column containing angles is obtained formatted for display using CAT_EGT0F it is returned as a CHARACTER string containing the value expressed in hours or degrees and formatted as a sexagesimal value.

In order to use this facility CAT must know that the column contains an angle and the units (hours or degrees) and format to use when formatting the angle for display. The prescription for creating a column of angles in a CAT catalogue is as follows.

(1)
Create the column with data type DOUBLE PRECISION.
(2)
The UNITS attribute should start with the string RADIANS to indicate that the column contains an angle in radians and this should be followed by a specifier enclosed in curly brackets ‘{}’ indicating how it is to be formatted for display. For example:
RADIANS{HOURS}
if it is to be displayed in hours,
RADIANS{DEGREES}
if it is to be displayed in degrees.

Specifying ‘HOURS’ will cause the angle to be displayed in hours, minutes and seconds, with the seconds displayed to one place of decimals; ‘DEGREES’ will cause the angle to be displayed in degrees, minutes and seconds, with the seconds displayed as whole numbers6.

(3)
When writing the table of values for the catalogue, express the angles in radians as DOUBLE PRECISION variables and write them to the catalogue using CAT_PUT0D.

An example program is available which illustrates the creation of columns containing angular celestial coordinates. It creates a catalogue containing (fake) equatorial coordinates and B magnitudes for a set of stars. It is called EXAMPLE_ANGLES and the source code is available in file:

/star/share/cat/example_angles.f

The overall structure is very similar to the previous example of writing a catalogue,
EXAMPLE_WRITE, but note the way that the three points outlined above are followed in order to create the angular columns.

#### 5.2 Vector columns

CAT does not provide facilities to simultaneously GET or PUT all the values for a given field in a vector column; rather the individual elements of each field must be GOT or PUT separately. Individual vector elements have their own identifiers. To process a vector element you should first get an identifier for the element and then GET or PUT values using the identifier just as you would for a scalar column.

The name of a vector element is the name of the vector column followed by the number of the element7 enclosed in square brackets. Thus, FLUX[4] corresponds to the fourth element of vector FLUX. Identifiers for vector elements are obtained using CAT_TIDNT, just as for scalar columns.

The following example illustrates obtaining the values of the fourth element of vector FLUX for the first twenty-five rows of a catalogue. The value obtained for each row is read into REAL variable FLXVAL. In the example the value is overwritten by each successive row; in a real application it would be processed or stored in some way.

INTEGER
:  CI,      ! Catalogue identifier.
:  VEI,     ! Vector element identifier.
:  ROW      ! Current row.
REAL
:  FLXVAL   ! Value read for current row.
LOGICAL
:  NULFLG   ! Null value flag.
.
.
.

First get an identifier for the vector element.

CALL CAT_TIDNT (CI, ’FLUX[4]’, VEI, STATUS)

Then loop through the first twenty-five rows getting the value for the vector element.

DO ROW = 1, 25
CALL CAT_RGET (CI, ROW, STATUS)

CALL CAT_EGT0R (VEI, FLXVAL, NULFLG, STATUS)
.
.
.

END DO

#### 5.3 Expressions

In CAT an expression is an algebraic expression involving the names of columns and parameters and constants, linked by arithmetic operators and mathematical and astronomical functions. The syntax for expressions is described in Appendix B. The first step towards manipulating an expression is to obtain an identifier for it. Routine CAT_EIDNT is used for this purpose. If the expression is invalid (for example because it contains the name of a column which does not exist in the catalogue) this routine will return with an error status. Once you have an identifier for an expression the expression can be evaluated using the same routines that GET the values of a column (you are ‘getting the value of the expression’). Clearly, values cannot be written to expressions and there is no equivalent of PUTting a value to a column.

Suppose that a catalogue contained columns called x and y and parameter p. The following example illustrates evaluating the expression ‘x + y + p + 2.0’ (that is, getting its value) for the first twenty-five rows of the catalogue. The evaluated expression for each row is read into REAL variable8 EXPVAL. In the example the value is overwritten for each successive row; in a real application it would be processed or stored in some way.

INTEGER
:  CI,      ! Catalogue identifier.
:  EI,      ! Expression identifier.
:  ROW      ! Current row.
REAL
:  EXPVAL   ! Value read for current row.
LOGICAL
:  NULFLG   ! Null value flag.
.
.
.

First get an identifier for the expression.

CALL CAT_EIDNT (CI, ’x + y + p + 2.0’, EI, STATUS)

Then loop through the first twenty-five rows getting the value for the expression.

DO ROW = 1, 25
CALL CAT_RGET (CI, ROW, STATUS)

CALL CAT_EGT0R (EI, EXPVAL, NULFLG, STATUS)
.
.
.

END DO

Null values for expressions work just like null values for scalar columns. If a null value is generated CAT_EGT0$<$t$>$ returns the appropriate Starlink ‘bad’ value rather than a genuine datum, and the null value flag (argument NULFLG in the example) is set to .TRUE. Expressions can evaluate to null in a number of ways: perhaps individual fields in the expression are themselves null, or an arithmetic exception (such as $÷$ by zero) might occur in the expression.

#### 5.4 Selections

In CAT a selection is a set of rows in a catalogue which satisfy some criteria. Every selection that you create has a unique identifier. Once you have obtained a selection identifier it can be passed to CAT_RGET instead of a catalogue identifier, and CAT_RGET will operate on just the rows in the selection, rather than all the rows in the catalogue.

There are two routines for creating selections (that is, generating selection identifiers): CAT_SELCT and CAT_SFND$<$t$>$. CAT_SELCT allows selections to be made on complex criteria whereas CAT_SFND$<$t$>$ selects values in a simple range for a given sorted column. CAT_SFND$<$t$>$ will usually be faster than CAT_SELCT (a useful mnemonic is F for Fast and Find, S for Slow and Select), but is much less flexible. Both these routines optionally allow you to create a second selection comprising the rejected rows, as well as the primary selection of selected rows.

Suppose a catalogue was sorted on column DEC of data type REAL and you wished to find the rows for which DEC was in the range 10.0 to 20.0. Because this is a simple range selection on a sorted column routine CAT_SFND$<$t$>$ can be used.

INTEGER
:  CI,      ! Catalogue identifier.
:  FI,      ! Identifier for column DEC.
:  SI,      ! Selection identifier for selected rows.
:  NUMSEL,  ! Number of selected rows.
:  SIR,     ! Selection identifier for rejected rows.
:  NUMREJ,  ! Number of rejected rows.
:  ROW      ! Current row.
REAL
:  DECVAL   ! Value read for DEC from current row in selection.
LOGICAL
:  NULFLG   ! Null value flag.
.
.
.

First get an identifier for column DEC.

CALL CAT_TIDNT (CI, ’DEC’, FI, STATUS)

Next create the selection and get an identifier for it. Note that because column DEC is of type REAL, the REAL version of CAT_SFND$<$t$>$, CAT_SFNDR, is used, and in this example the optional second selection, comprising the rejected rows, is not generated.

CALL CAT_SFNDR (CI, FI, 10.0, 20.0, .FALSE., SI, NUMSEL,
:  SIR, NUMREJ, STATUS)

Loop through all the rows in the selection, getting values for column DEC. Note how the selection identifier, SI, rather than the catalogue identifier, is passed to routine CAT_RGET.

DO ROW = 1, NUMSEL
CALL CAT_RGET (SI, ROW, STATUS)

CALL CAT_EGT0R (FI, DECVAL, NULFLG, STATUS)
.
.
.

END DO

As a second example, suppose that the catalogue was not sorted on column DEC. CAT_SFND$<$t$>$ could not now be used to create the selection, and CAT_SELCT would have to be used instead. The procedure would then be as follows.

INTEGER
:  CI,      ! Catalogue identifier.
:  FI,      ! Identifier for column DEC.
:  EI,      ! Expression identifier.
:  SI,      ! Selection identifier for selected rows.
:  NUMSEL,  ! Number of selected rows.
:  SIR,     ! Selection identifier for rejected rows.
:  NUMREJ,  ! Number of rejected rows.
:  ROW      ! Current row.
REAL
:  DECVAL   ! Value read for DEC from current row in selection.
LOGICAL
:  NULFLG   ! Null value flag.
.
.
.

First CAT_EIDNT is used to get an expression identifier for the expression representing the criteria. This identifier is then passed to CAT_SELCT. Remember that the criterion is that DEC should be in the range 10.0 to 20.0.

CAT_EIDNT (CI, ’(DEC >= 10.0) & (DEC <= 20.0)’, EI, STATUS)

CAT_SELCT (CI, EI, .FALSE., SI, NUMSEL, SIR, NUMREJ, STATUS)

Next get an identifier for column DEC, then loop through all the rows in the selection, getting values for DEC. Again note how the selection identifier, SI, rather than the catalogue identifier, is passed to routine CAT_RGET.

CAT_TIDNT (CI, ’DEC’, FI, STATUS)

DO ROW = 1, NUMSEL
CALL CAT_RGET (SI, ROW, STATUS)

CALL CAT_EGT0R (FI, DECVAL, NULFLG, STATUS)
.
.
.

END DO

#### 5.5 Indices

In CAT an index is a mechanism for accessing the rows of a catalogue in the order that they would have were the catalogue sorted into ascending or descending order on some (numeric) column. That is, an index presents the application with a ‘virtual catalogue’ which appears to have been sorted on the specified column. Every index that you create has a unique identifier. Once you have obtained an index identifier it can be passed to CAT_RGET instead of a catalogue identifier, and CAT_RGET will return subsequent rows corresponding to ascending or descending order of the column used to generate the index.

Indices are created using routine CAT_INEW. Version 9.0 of CAT supports only temporary indices which persist only for the duration of the application which generated them and perish when it terminates. Future versions of CAT will support permanent indices which persist after the program which generated them terminates.

Suppose that you wished to generate an index on column DEC of data type REAL9 and then process the rows of the catalogue using this index.

INTEGER
:  CI,      ! Catalogue identifier.
:  FI,      ! Identifier for column DEC.
:  II,      ! Identifier for index generated from column DEC.
:  NUMROW,  ! Number of rows in the catalogue.
:  ROW      ! Current row.
REAL
:  DECVAL   ! Value read for DEC from current row in index.
LOGICAL
:  NULFLG   ! Null value flag.
.
.
.

First get an identifier for column DEC.

CALL CAT_TIDNT (CI, ’DEC’, FI, STATUS)

Next create an index and get an identifier for it.

CALL CAT_INEW (FI, ’TEMP’, CAT__ASCND, II, STATUS)

The second argument indicates that the index is temporary rather than permanent; ‘TEMP’ is the only permitted value here in version 9.0 of CAT. The third argument indicates whether the index is to correspond to ascending (‘CAT__ASCND’) or descending (‘CAT__DSCND’) order.

To access the rows via the index simply determine the number of rows in the catalogue and then loop through the rows, passing the index identifier, II, rather than then catalogue identifier, to routine CAT_RGET. The values obtained might be processed in some way, or written out to generate a sorted catalogue.

CALL CAT_TROWS (CI, NUMROW, STATUS)

DO ROW = 1, NUMROW
CALL CAT_RGET (II, ROW, STATUS)

CALL CAT_EGT0R (FI, DECVAL, NULFLG, STATUS)
.
.
.

END DO

# Part IIIReference

6This discussion covers only the simplest specifiers for formatting angles for display, though these are adequate for most cases and are the easiest to use. The full set of specifiers, which allow considerable flexibility in representing angles, are described in Section 8.3.

7The first element of a vector is numbered one.

8Internally, inside CAT, numeric expressions are always evaluated using data type DOUBLE PRECISION. If you are unsure about the data type to use for the evaluated result of an expression the safest choice is to use DOUBLE PRECISION in order to ensure that accuracy is not lost.

9Indices can be generated on columns of any of the numeric data types.