B Handling NDFs in IDL

 B.1 The Easy Way
 B.2 Other Methods

B.1 The Easy Way

Note that this method cannot be used with the 64-bit Solaris version of IDL (use % idl -32).

IDL function READ_NDF is available to convert a component of an NDF to an IDL array, and IDL procedure WRITE_NDF will create an NDF component from an IDL array. So, for example:

  IDL> tv,read_ndf(’comwest’)

will display the data array of the NDF, comwest.sdf, using the IDL command, TV, and:

  IDL> write_ndf,field,’stars’

will create an NDF, stars.sdf, of a suitable type and size, and write the IDL array, field, to its DATA_ARRAY component.

  IDL> write_ndf,q,’stars’,’QUALITY’

will write the IDL array, q, to the QUALITY component of an existing NDF, stars.sdf.

Both READ_NDF and WRITE_NDF can take special action on bad values. For a full description of their arguments see

Appendix C.

Complete structures can be handled by function HDS2IDL and procedure IDL2HDS. So, for example:

  IDL> comwest=hds2idl(’comwest’)
  % Loaded DLM: HDS2IDL.
  IDL> help,comwest,/str
  ** Structure <40071208>, 5 tags, length=262184, refs=1:
     HDSSTRUCTYPE    STRING    ’IMAGE’
     TITLE           STRING    ’Comet West, low resolution’
     DATA_ARRAY      FLOAT     Array[256, 256]
     DATA_MIN        FLOAT           3.89062
     DATA_MAX        FLOAT           245.937
  IDL>tv,comwest.data_array

will display the same image as the READ_NDF example above, but the other components of the NDF are also available in the IDL structure, comwest, so that:

  IDL> idl2hds,comwest,’newcomwest’

will create a duplicate of comwest.sdf in newcomwest.sdf. Exact duplication of the type and structure is not always possible – see the routine descriptions for details.

When CONVERT is installed, the converter procedures and routines are placed in $CONVERT_DIR so, to make them available to IDL, that directory must be added to the IDL search paths, IDL_PATH and IDL_DLM_PATH. This will be done if the environment variable IDL_PATH has been set (usually by ‘sourcing’ the idl_setup script) when you start the CONVERT package by typing:

  % convert

Note that convert must be run after sourcing the idl_setup script.

Note also that having started CONVERT the NDF library (see SUN/33), which is ultimately used by READ_NDF and WRITE_NDF, will allow them (but not HDS2IDL and IDL2HDS) to do on-the-fly conversion (see Section 3) of any files given as parameters. This opens up the possibility of using almost any data format with IDL.

As an example:

  IDL> tv,read_ndf(’moon.imh’)

will display the IRAF file, moon.imh.

B.2 Other Methods

B.2.1 A simple route (but rather slow)

The simplest route to use when generating data for IDL from NDFs is to create an ASCII copy of the NDF you are interested in using the CONVERT package application NDF2ASCII and then read the resulting file with IDL. The steps taken might be something like:

  % ndf2ascii in=imagein out=fileout

This will create a file, fileout, containing the DATA component of the NDF called imagein. If you want to store the VARIANCE or QUALITY components you would use comp=v or comp=q respectively as additional parameters.

You can then employ a simple IDL batch file such as:

  ; Create IMAGE an 339x244 single precision floating point array.
  IMAGE=FLTARR(339,244)
  
  ; Open the existing NDF2ASCII file "fileout" for read only access.
  OPENR, UNIT, ’fileout’, /GET_LUN
  
  ; Read formatted input from the specified file unit and
  ; place in the variable "IMAGE".
  READF, UNIT, IMAGE
  
  ; Closes the file unit used.
  CLOSE, UNIT
  
  ; Display the image after suitable scaling.
  TVSCL, IMAGE

The above example assumes image dimensions of 339×244 pixels. If you are in any doubt as to the dimensions of your image you can determine them using the Kappa application NDFTRACE.

One advantage of this route is that the ASCII data can instead be read directly into byte, integer or double-precision arrays/structures by simply substituting INTARR, DBLARR or BYTARR for FLTARR. Clearly, it should be remembered that attempting to represent floating-point values within a byte array will not work properly, whereas a double-precision array will accommodate double-precision, floating-point, integer or byte values (though somewhat inefficiently in terms of memory consumption).

B.2.2 A faster route (but a little more complicated)

However, the NDF2ASCII routine is not fast and makes this route awkward if time is important. Consequently, you may want to use NDF2UNF to create an F77 unformatted sequential file thus:

  % ndf2unf in=imagein out=fileout noperec=339

Where the noperec number should be the size of the first axis of the image.

You can then read the created file using an IDL batch file similar to:

  ; Supply the name of the image and its dimensions.
  FNAME=’fileout’
  SD1=339
  SD2=244
  
  ; Set up the main array and temporary array
  ; use NOZERO option to avoid initialisation
  IMAGE=INTARR(SD1,SD2,/NOZERO)
  TEMP= INTARR(SD1,    /NOZERO)
  
  ; Display what is going on.
  PRINT, "Converting file: ", FNAME
  
  ; Open the file generated by NDF2UNF for read access only.
  OPENR, UNIT, fname, /GET_LUN, /F77_UNFORMATTED
  
  ; Read the image one record at a time.
  FOR I=0,SD2-1  DO BEGIN  READU, UNIT, TEMP & $
    ; Transfer each line into the main image array.
    FOR J=0,SD1-1 DO BEGIN IMAGE(J,I)=TEMP(J) & $
  ENDFOR & ENDFOR
  
  ; Close the opened file unit.
  CLOSE, 1
  
  ; Scale the image for display.
  IMAGE=CONGRID(IMAGE,SD1,SD2,/INTERP)
  WINDOW, 0,XSIZE=SD1,YSIZE=SD2
  
  ; Display the image.
  TVSCL, IMAGE

The image is then contained in the integer array IMAGE and may be manipulated by IDL. This would allow such operations as storing it as a UNIX unformatted file where the image might subsequently be read in from disc in one go.

It should be remembered that the data type of the F77 unformatted file created by NDF2UNF may differ depending on the type of data stored in the original NDF. If this is the case you might need to change the type definition of the arrays image and temp to reflect this. The data type used within each component of an NDF may be determined using NDFTRACE.

B.2.3 Using the IDL Astronomy Users’ Library

If this all seems a bit tedious, then those of you with with the IDL Astronomy Users’ Library installed on your machines might choose to take advantage of its FITS conversion procedures to make life easier still. Users wishing to obtain a copy of the library can find it at http://idlastro.gsfc.nasa.gov/homepage.html.

The library contains IDL procedures from a number of sources that allow FITS format files to be read into IDL data structures. The routine chosen for the example below was FXREAD which may be found in the /pro/bintable sub-directory. It is part of a comprehensive suite of FITS conversion programs that seems particularly easy to use.

So if you first convert your NDF into a FITS file using NDF2FITS like this:

  % ndf2fits in=m42 out=m42.fit comp=d

you can then use the following code from within IDL to place the image into an IDL structure and display it.

  ; Read the FITS file
  fxread, ’m42.fit’, DATA, HEADER
  
  ; Determine the size of the image
  SIZEX=fxpar(header, ’NAXIS1’)
  SIZEY=fxpar(header, ’NAXIS2’)
  
  ; Find the data type being read
  DTYPE=fxpar(header, ’BITPIX’)
  
  ; Scale the image for display
  IMAGE=congrid(DATA,SIZEX,SIZEY,/INTERP)
  window, 0,xsize=SIZEX,ysize=SIZEY
  
  ; Display the image
  TVSCL, IMAGE

As can be seen above, various values contained within the FITS header of the original can be obtained using the FXPAR procedure.

You should bear in mind that a number of other procedures (such as IEEE_TO_HOST and GET_DATE) from the Astronomy Users’ Library are also needed by IDL when compiling this code. Consequently it is essential that the whole library should be obtained from the archive.