Data Formats

ADS Data Format


ADS Header Format

The first "record" of every ADS image (tape or disk) starts with the text string "ADS DATA TAPE" which is 20 bytes long (regardless of what you just counted). The second and third record are identical and contain the header, which describes what was recorded on this image. The header is a binary sequence of C structures. All C structures reside in a file called header.h. The first structure is always Fl:

struct Fl {
  str8 thdr;                            /* I.D. "THDR" */
  long item_len;                        /* Length of this struct in bytes */
  str8 version;                         /* header version number */
  str8 prnum;                           /* project number */
  str8 fltnum;                          /* flight number */
  str8 tpnum;                           /* tape number, obsolete */
  str12 date;                           /* "mm/dd/yyyy */
  str12 time;                           /* "hh:mm:ss" */
  str4 tzone;                           /* i.e. "MST" */
  str8 acraft;                          /* i.e. "N308D" */
  long n_items;                         /* # of items excluding this one */
  long lrlen;                           /* logical record length */
  long lrppr;                           /* logical records per physical rec */
  long thdrlen;                         /* length of this tape header */
  str8 ads_type;                        /* data system type */
};
typedef struct Fl Fl;

struct Fl is then followed by a number of struct Sh's, which describe each analog and digital channel to be sampled:

struct Sh {
  str8 item_type;                       /* desc type, 'SDI' 'HSKP' 'DIGOUT' */
  long item_len;                        /* Length of this struct in bytes */
  long start;                           /* byte address in the data record */
  long length;                          /* data item length in bytes */
  long rate;                            /* sample rate */
  long adsaddr;                         /* ADS channel address */
  str8 name;                            /* name of variable */
  str4 type;                            /* "A", "D", or "C" */
  long offset;                          /* offset between samples */
  float convert;                        /* conversion factor, bits to units */
  long order;                           /* number of cal coefficients */
  float cof[MX_COF];                    /* cal coefficients array */
  long ch_gain;                         /* channel gain setting, 1, 5, 10, 20 */
  long ch_offset;                       /* channel offset, 0 or 10 volts */
  str8 dsm_locn;                        /* sampling module location */
  long convert_offset;                  /* conversion offset counts at 0 volts*/};
typedef struct Sh Sh;

Notice that all structures start with the same two fields, item_type and item_len. And all structures except Fl also contain start and length, which give the position of the data in each record.

The Sh's are followed in some order by various other probe header structs (Blk, Pms1d, etc. See header.h for a full list):

struct Blk {
  str8 item_type;                       /* 'HDR','GPS','LRNC','JPLTDL','CLIMET' */
  long item_len;                        /* Length of this struct in bytes */
  long start;                           /* byte address in the data record */
  long length;                          /* block length in bytes */
  str8 locn;                            /* sensor location */
  str8 dsm_locn;                        /* sampling module location */
  long rate;                            /* sample rate                  */
};
typedef struct Blk Blk ;

A minumum header would consist of an Fl and a Blk for the HDR type. HDR contains the data and time stamp for each record.


An example header:

Structure type:
__________________________________________________________________________________
|  Fl   |  Sh   |  Sh   |  Sh   |  Sh   |  Sh   |  Blk  |  Blk  |  Irs  | Pms1v3 |
----------------------------------------------------------------------------------

Corresponding variable or block:
__________________________________________________________________________________
|       | ADIFR | BDFIR | OZONE | CNTS  | TTRL  |  HDR  |  GPS  |  INS  | FSSP-100|
----------------------------------------------------------------------------------

Some example code to print out all the names in the header:

  FILE *fp;
  char header[32000], *p;
  int  i;

  fp = fopen("ADS.image", "r");

  fread(&fl, sizeof(Fl), 1, fp);
  fread(header, fl.thdrlen - sizeof(Fl), 1, fp);

  p = header;

  for (i = 0; i < fl.n_items; ++i)
    {
    if (strncmp(p, "SDI", 3) == 0)
      printf("%s\n", ((Sh *)p)->name);
    else
    if (strncmp(p, "HDR", 3) == 0 ||
        strncmp(p, "GPS", 3) == 0 ||
        strncmp(p, "IRS", 3) == 0)
      printf("%s\n", ((Blk *)p)->item_type);
    else
    if (strncmp(p, "PMS1V3", 6) == 0)
      printf("%s\n", ((Pms1v3 *)p)->name);

    p += ((Blk *)p)->item_len;
    }

At RAF it is unnecessary to actually read the header like this as we have C (libhdr_api.a) and C++ (libraf++.a::hdrAPI) API's for reading the header.


ADS Record Format

Analog and digital are 16-bit values interleaved and grouped by data rate. Many instruments/interface cards/ISRs will produce a block of binary data, which follows the analog/digital section. A header reorded at the front of each file will tell exactly what is/was recorded in that file, and where in each record the data can be found. Header is produced by program xbuild.


ADS Processed Data Format

netCDF. Format supports multi-rate and vector data.