8 Propagating NDFs

In the previous example the data array was modified in situ – no new NDF was created. However it is often preferable to create a new NDF rather than overwriting an input one. This can be done by propagating an existing NDF using NDF_PROP, which has the following calling sequence.

        CALL NDF_PROP (NDF1, CLIST, PARAM, NDF2, STATUS)

NDF1 is the identifier for an existing NDF which is used as the model (or template) for the new NDF. CLIST contains a list of data objects separated by commas as described below. PARAM is an ADAM parameter used to retrieve the name of the new NDF. NDF2 returns the identifier allocated to the new NDF, and STATUS is the global status.

The data objects which are to be copied from the model NDF to the new one are defined in the string CLIST. By default, the HISTORY, LABEL and TITLE data objects plus all extensions are propagated to the new NDF. Others are propagated by specifying them in CLIST. The propagation of default standard items can be suppressed by specifying ’NOHISTORY’ etc. The propagation of a particular extension is suppressed by specifying the extension name, for example, NOEXTENSION(FIGARO).

For example, the CLIST arguments below propagate the items which follow:

CLIST Items propagated
’ ’ title, label, history & extensions
’NOHISTORY’ title, label & extensions
’DATA,QUALITY,VARIANCE,AXIS’ title, label, history, extensions, data, quality, variance & axis
’NOEXTENSION(IRAS,FIGARO)’ title, label, history & extensions except IRAS & Figaro

ADAM_EXAMPLES:ADDNEW.FOR is a modified version of the program ADDCONST considered in the last section. It uses NDF_PROP to produce a new output NDF rather than updating the input file. The associated interface file, ADDNEW.IFL, includes the parameter ’OUTPUT’ to retrieve the name of the output NDF. The relevant portion of ADDNEW.FOR is reproduced below:

  *  Obtain an identifier for the input NDF.
        CALL NDF_ASSOC (’INPUT’, ’READ’, NDF1, STATUS)
  
  *  Propagate everything in the input NDF to the output.
        CALL NDF_PROP (NDF1, ’DATA,AXIS,QUALITY,VARIANCE,UNITS’,
       :               ’OUTPUT’, NDF2, STATUS)
  
  *  Map the output NDF data array for update.
        CALL NDF_MAP (NDF2, ’Data’, ’_REAL’, ’UPDATE’, PTR2, NELM, STATUS)
  
  *  Get the value of the constant to be added.
        CALL PAR_GET0R (’CONST’, VALUE, STATUS)
  
  *  Add the constant value to the data array.
        CALL ADDIT (NELM, %VAL (PTR2), VALUE, STATUS)

Note that the input NDF is opened with ’READ’ access rather than ’UPDATE’ as in ADDCONST.FOR.

In this example, everything including the main data array is propagated, and the copied data array in the output NDF is then mapped for update and modified in situ, thus avoiding the need to map the input data array. Of course this approach is not always suitable. Frequently the input data array is not propagated, but is mapped and used to generate the values which are written to the output data array. In such cases, the output data array is mapped for write access and is undefined until the program-generated data values are written to it.

What should be propagated?

A little consideration must be given to the choice of items to propagate. The basic rule is that an application program must not propagate items which may have become invalid.

For example, if the data processing is such that the original variance array is no longer valid then the output NDF must not contain this array. The program has the choice of producing an output with no variance array or creating a correctly evaluated variance array. (The subject of processing the variance array is considered in Section 13.) In the example program ADDNEW, all the data objects were propagated because adding a constant to the main data array does not invalidate the AXIS, VARIANCE, QUALITY etc.

For a given application, the standard objects in an NDF can be divided into three categories:

Those which remain valid – items in this first category are propagated unchanged. Title, history and label often fall into this category, hence their inclusion by default.
Those which are processed to retain their validity – these can be propagated and modified in situ or created afresh in the output NDF. The main data array often falls into this category as it is usually modified by an application. The choice of propagating the data array and modifying it in situ, or suppressing the propagation and creating a new array in the output NDF is application-dependent. Many applications require separate input and output arrays; for example a data array cannot be reversed in situ. In such cases the input data array should not be propagated as it is inefficient to copy large data arrays unnecessarily.
Those which have become invalid – these must not be propagated to the output NDF. Examples include variance arrays in cases where the program cannot or does not evaluate a new variance array.

As described in Section 16, an extension contains a set of related data objects which are not accommodated in the standard NDF. For example, the ‘IRAS’ extension might contain those data specific to the recording and processing of IRAS observations. The treatment of extensions obeys similar rules to that of standard NDF components and can be summarised as follows:

Extensions which the application doesn’t recognise – such extensions should be propagated unchanged. (It is clearly inappropriate that the information in extensions be deleted by a general application.)
Extensions which the application recognises and is equipped to process correctly – such extensions should be propagated and processed. The application should ensure that no items become invalid.
Extensions the application recognises but realises it is not equipped to process – these must not be propagated.

The propagated NDF has the same dimensionality and data type as the template NDF – irrespective of whether the data component has been propagated or not. In the example NDF below, the data component was not propagated, and before values were assigned to the new data array, the output NDF had the following form:

  IMAGE1  <NDF>
  
    DATA_ARRAY(256,256)  <_REAL>   {undefined}
  
  End of Trace.

If the data shape and type are appropriate for the output NDF, the array can be mapped for ’WRITE’ and appropriate values assigned. However, if the data shape or type are not as required in the output NDF, these can be modified using the NDF routines NDF_SBND and NDF_STYPE.