13 ACCESSING NDFS FOR OUTPUT

 13.1 Using Existing NDFs
 13.2 Creating New NDFs via Parameters
 13.3 Conditional NDF Creation
 13.4 Creating Primitive NDFs

13.1 Using Existing NDFs

An NDF data structure which is to be used for output from an application can be obtained in a number of ways. Most simply, an existing NDF may be acquired by using the NDF_ASSOC routine (§3.1) and specifying ‘UPDATE’ or ‘WRITE’ access (in both the call to the routine and the associated interface file if you are using ADAM). New values, or new components, may then be added to the NDF, as in the following simple example which obtains a new value for an NDF’s title component:

        SUBROUTINE TITLE( STATUS )
        INTEGER STATUS, INDF
  
        IF ( STATUS .NE. SAI__OK ) RETURN
        CALL NDF_ASSOC( ’OUT’, ’UPDATE’, INDF, STATUS )
        CALL NDF_CINP( ’TITLE’, INDF, ’Title’, STATUS )
        CALL NDF_ANNUL( INDF, STATUS )
        END

The same principle would also be used to write a new NDF data component by mapping it for ‘WRITE’ access and assigning new values to its pixels, as described in §8.4.

Note that ‘UPDATE’ access has been used here in the call to NDF_ASSOC because we want other NDF components to retain their previous values. If ‘WRITE’ access had been specified, then the NDF’s components would have been automatically reset to an undefined state, as the NDF_ system interprets this access mode as a request to re-write the data structure.

13.2 Creating New NDFs via Parameters

An alternative method of obtaining an NDF for output is to create an entirely new one. The NDF_CREAT routine will perform this task. For instance:

        INTEGER NDIM, LBND( NDIM ), UBND( NDIM )
  
        ...
  
        CALL NDF_CREAT( ’OUT’, ’_REAL’, NDIM, LBND, UBND, INDF, STATUS )

will create a new NDF and associate it with the parameter ‘OUT’. If you are using ADAM, a similar interface file entry to that in §3.1 would be required, except that ‘WRITE’ access would be specified in this case.

This example will create a simple, real NDF; i.e. one whose data and variance components will be stored as ‘_REAL’ arrays, and whose array components will have a storage form of ‘SIMPLE’ (see §12.3). Its dimensionality and pixel-index bounds are specified by the NDIM, LBND and UBND arguments. Initially, all its components will be in an undefined state.

13.3 Conditional NDF Creation

It is sometimes necessary to determine whether an NDF exists before deciding to create a new one. The routine NDF_EXIST is provided to allow this by associating an existing NDF with a parameter and returning an NDF identifier for it, if it exists. If the NDF does not exist, then no error results, but the routine returns with a “null” identifier value of NDF__NOID (defined in the include file NDF_PAR). In effect, this routine behaves identically to NDF_ASSOC, except that if the NDF does not exist, control is returned to the calling routine rather than re-prompting the user to supply a new name. The following illustrates how NDF_EXIST might be used:

        INCLUDE ’NDF_PAR’
  
        ...
  
        CALL NDF_EXIST( ’OUT’, ’UPDATE’, INDF, STATUS )
        IF ( INDF .EQ. NDF__NOID ) THEN
           CALL NDF_CREAT( ’OUT’, ’_INTEGER’, NDIM, LBND, UBND, INDF, STATUS )
        END IF

Here, an existing NDF is accessed if it exists, otherwise a new structure is created and used instead.

13.4 Creating Primitive NDFs

The routine NDF_CREP is provided for creating primitive NDFs; i.e. NDFs whose array components will have a storage form of ‘PRIMITIVE’. NDF_CREAT should normally be used to create a new NDF, but use of NDF_CREP may sometimes be necessary in order to maintain compatibility with existing software (see §12.6). Because of the restrictions inherent in the primitive form of array storage, the lower pixel-index bounds of primitive NDFs must be set to 1 in all dimensions, so NDF_CREP lacks the LBND argument of NDF_CREAT, the appropriate lower bounds being assumed:

        CALL NDF_CREP( ’OUT’, ’_REAL’, NDIM, UBND, INDF, STATUS )

Its use is otherwise identical to NDF_CREAT.