Los Alamos National Laboratory Go to the Lab's home page Search for people in the Lab's phone book Search the Laboratory's Web site
  MENA  >  UDF  >  UDF DLM Package for IDL

UDF DLM Package for IDL

UDF is a powerful, flexible data storage format. As always, though, with flexibility comes complexity. The UDF-DLM package is intended to provide a simple interface to UDF for IDL programmers.

This document provides a brief introduction to UDF-DLM. Please keep in mind that UDF-DLM is a work in progress, and this page may be out of date by the time you read it.


If you're anxious to get your hands on the goods, go to the download page.

Installation is beyond the scope of this document; please read the INSTALL file provided with the snapshot.


Most programmers are accustomed to the OPEN, READ, CLOSE model of file I/O. The UDF-DLM package provides an abstraction layer on top of the UDF libraries, so IDL programmers can access UDF data with a few seconds' work, instead of a few hours.


UDF-DLM can be used interactively, or in IDL programs. Although your eventual goal is doubtless to access UDF data from within your programs, this example introduces steps in interactive mode. It is assumed that you can take it from there.

  1. You need to start by obtaining a key. UDF data files are accessed hierarchically via project, mission, experiment, instrument, and virtual instrument. These correspond to the data file layout described elsewhere. The UDF_KEY function is used for this:

     IDL> key = udf_key( vinst_to_full_path('ImMStats') )
     % Loaded DLM: UDF.
     IDL> help, key
     KEY             ULONG     =    101204098

    UDF_KEY takes five strings as input: either as five positional parameters, or as one 5-element IDL array (as returned by vinst_to_full_path() above). The returned key can be used by UDF_OPEN, UDF_TIMES, or UDF_PIDF. It is an opaque value, and you really don't need to know anything more about it.

    The message "% Loaded DLM: UDF" appears only the first time you access one of the UDF-DLM functions.

    NOTE: Try getting a key for your own instrument, not MENA. Even if you get a valid key, UDF_OPEN will fail if you have not installed any UDF data files for that instrument.

  2. With key in hand, you can now use UDF_OPEN to find data for your instrument:

     IDL> fh = udf_open(key, [2000, 130])

    This initiates UDF access to the data set referenced by key, for day 130, 2000, 00:00 through 23:59:59.999. If it is successful, UDF_OPEN silently returns a "filehandle", which can then be passed on to UDF_READ or UDF_EOF.

    If there are no data records for the given time period, you might see:

    % UDF_OPEN: (file_open): UDF error [NO_DATA]

    The probable cause for this is that there are no data files installed for this particular instrument (did you remember to get a key for your own data set, above?), or the data files are for a different time range.

    UDF_OPEN can accept two optional keyword parameters: /GROUP and /COLLAPSE. These are described in the following section.

  3. Read in a data record:

     IDL> d = udf_read(fh)
     IDL> help, d, /struct
    ** Structure IMMSTATS, 29 tags, length=13360:
       BTIME           STRUCT    -> UDF_TIME Array[1]
       ETIME           STRUCT    -> UDF_TIME Array[1]
       D_QUAL          DOUBLE           2.0000000
       START_AZ        FLOAT     Array[128]
       STOP_AZ         FLOAT     Array[128]
       SCAN_INDEX      FLOAT     Array[128]
       START_HEIGHT    FLOAT     Array[128]
       STOP_HEIGHT     FLOAT     Array[128]
       START_POSITION  FLOAT     Array[128]
       STOP_POSITION   FLOAT     Array[128]
       COARSE_AZIMUTH  FLOAT     Array[128]
       FINE_AZIMUTH    FLOAT     Array[128]
       TOTAL_AZIMUTH   FLOAT     Array[128]
       TIME_OF_FLIGHT  FLOAT     Array[128]
       HEAD_ID         FLOAT     Array[128]
       PACKET_COUNTER  FLOAT     Array[128]
                       FLOAT     = Array[128]
                       FLOAT     = Array[128]
                       FLOAT     = Array[128]
                       FLOAT     = Array[128]
                       FLOAT     = Array[128]
                       FLOAT     = Array[128]
       SPIN_COUNTER    FLOAT     Array[128]
       GCI_SATELLITE_X FLOAT     Array[128]
       GCI_SATELLITE_Y FLOAT     Array[128]
       GCI_SATELLITE_Z FLOAT     Array[128]
                       FLOAT     = Array[128]
                       FLOAT     = Array[128]
                       FLOAT     = Array[128]
     IDL> help, d.btime, /st
     ** Structure UDF_TIME, 7 tags, length=20:
       YEAR            INT           2000
       DOY             UINT           130
       HOUR            BYTE        14
       MIN             BYTE        16
       SEC             BYTE        12
       MSEC            UINT           851
       DP              DOUBLE           0.0000000
        [user input]
        [tags common to all returned STRUCTs]

    It doesn't get much simpler than that, does it?

    The data structure contains one tag each for beginning and ending time, plus one tag for each sensor defined in the PIDF file. It is generated on-the-fly at run time.

    As with any IDL data, you are now free to plot, analyze, bend, fold, spindle or mutilate it. You can even lump structs together... since it's a named structure, you can loop over UDF_READ (calling UDF_EOF to test for end-of-file) and append the structs together into an array of structs:

     IDL> while not udf_eof(fh) do d = [d, udf_read(fh)]
     IDL> help,d
     D               STRUCT    = -> IMMSTATS Array[100]

    If you had called UDF_OPEN with /GROUP, this is what your data structure would look like (highlights indicate changes from above):

    ** Structure IMMSTATS_G, 14 tags, length=13360:
       BTIME           STRUCT    -> UDF_TIME Array[1]
       ETIME           STRUCT    -> UDF_TIME Array[1]
       D_QUAL          DOUBLE           2.0000000
       START_AZ        FLOAT     Array[128]
       STOP_AZ         FLOAT     Array[128]
       SCAN_INDEX      FLOAT     Array[128]
       START_STOP_DATA FLOAT     Array[128, 4]
       ANGLE_DATA      FLOAT     Array[128, 3]
                       FLOAT     = Array[128, 2]
       PACKET_COUNTER  FLOAT     Array[128, 1]
                       FLOAT     = Array[128, 6]
       SPIN_COUNTER    FLOAT     Array[128, 1]
                       FLOAT     = Array[128, 3]
                       FLOAT     = Array[128, 3]
        [tags common to all returned STRUCTs]
        [what has changed since the last one]

    Groups are logical groupings of sensors, defined manually in the PIDF.

    If you had called UDF_OPEN with /COLLAPSE, your data records would be fully collapsed into one tag, called DATA:

    ** Structure IMMSTATS_C, 7 tags, length=13360:
       BTIME           STRUCT    -> UDF_TIME Array[1]
       ETIME           STRUCT    -> UDF_TIME Array[1]
       D_QUAL          DOUBLE           2.0000000
       START_AZ        FLOAT     Array[128]
       STOP_AZ         FLOAT     Array[128]
       SCAN_INDEX      FLOAT     Array[128]
       DATA            FLOAT     Array[128, 23]

    Note that the structure length never varies. This is as expected; the bits are the same, only their names have changed.

  4. Finally, please be polite; clean up after yourself:

     IDL> UDF_Close, fh

Tables, etc

UDF defines ways to extract useful fields from the raw data, via its convert_to_units function. For instance, raw telemetry can be converted to counts, degrees, and so on.

UDF-DLM does this automatically... if there's a sensor defined in the PIDF file. Thus it is in your best interest to make sure that the PIDF is well written!

If you don't want this conversion, use the /RAW flag to UDF_OPEN.


"Sensors" can access multiple units. For instance, ImHimcpl (HENA) has a group of "sensors" that can use any of units 0,4,7,8 (raw, counts/acc, count rate, or Number Flux).

By default, UDF-DLM chooses the "most advanced" unit, that is, the last one defined for each sensor. In the example above, that would be unit 8 for each. If UDF_OPEN is invoked with the /RAW flag, though, the lowest-numbered unit is used, and (more importantly) convert_to_units() is not invoked -- you get the bits exactly as they are in the UDF file.

These two extremes don't always suffice. What if you want to see unit 7 (count rate) in ImHimcpl ?

UDF_OPEN provides a UNITS keyword for this. Its usage is a little complex, though:

ISR-1 Software Team
 Los Alamos National Laboratory  Operated by the University of California for the National Nuclear Security Administration,
of the US Department of Energy.     Copyright © 2002 UC | Disclaimer/Privacy

Last Modified $Date: 2004-08-06 18:17:42-06 $