World Data Centre
FORECAST SOL: Normal green MAG: Normal green ION: Normal green
HomeWorld Data CentreData CatalogueData FormatsIonogram Data Format Tuesday, Dec 12 2017 12:24 UT
Data Catalogue

Ionogram Data Format

Raw ionograms retain full, unprocessed information returned from the ionosonde. For example, an IPS 5A series raw ionogram consists of a standard header followed by channel information. Channels progress from lowest to highest frequency in 40 kHz steps. The 5A ionosonde samples each frequency at 512 virtual heights. The first height corresponds to 80 km and each height step is 1.2 km. Thus the sample height range is 80 to 693.2 km. Each frequency corresponds to a channel number, which varies from 0 to 511 (2 bytes). The channel number and frequency are related by the following expression.

Frequency = Channel number 0.04 + 1.0 MHz

Thus the corresponding frequency range comes out to be 1.0-21.44 MHz.

Raw and clean ionogram header

The header consists of a number of variables written in ASCII to the output file. The C-programming code for writing a header is similar to that used in the function readhdr() within the file readhdr.c. An example of an ASCII dump of a header follows.

0000000 A \n 5 1 2 \n 8 0 . 0 0 1 . 2 0000020 0 5 1 2 \n - 4 2 . 9 0 1 4 0000040 7 . 3 0 5 8 . 6 0 \n 1 9 9 4 0000060 0 4 0 1 0 0 0 0 \n h b t 5 0000010 a \n

The variables that comprise the header are described as follows.

  • Format - A single character to identify the ionosonde hardware. SWS internal use only (eg, A).
  • Nchans - An integer giving the number of channels sounded (eg, 512).
  • min_km - A double precision floating point number giving the minimum height of the sounding (start height) in km (eg, 80.00).
  • height_step - A double precision floating point number giving the height step for a channel in km (eg, 1.20).
  • nrows - An integer giving the number of height steps (eg, 512).
  • lat, lon, diplat - Three double precision floating point numbers giving geographic latitude and longitude and geomagnetic latitude in degrees (eg, -42.90 147.30 58.60).
  • year, month, day, hour, min - Five integers giving the time of the sounding (UT) (eg, 1994 04 01 00 00).
  • Location[80] - An ASCII description string used to describe the location of the ionosonde (eg, hbt5a for Hobart 5a ionosonde).

Raw ionogram data format

The data stored in the raw ionogram is in a pre-determined format. First the header information is stored as discussed above, followed by the channel information. Within each channel, first comes the two bytes for the frequency of the channel in kHz, and then a single byte for the number of repetitions for that channel. Of the two bytes for the frequency, the first byte gives the upper eight bits of the frequency and the second byte gives the lower eight bits. After the number of repetitions comes the amplitude list of nrows size. Each amplitude has a range of 0 to 255.

Channel field Size
Frequency2 bytes
Number of repetitions1 byte
Amplitude1 byte per amplitude

5D ionosonde raw data format

An ionogram header of 32 bytes, followed by channel data.

Each channel has a mini header of 8 bytes, 512 bytes of O trace, 4 bytes, and 512 bytes of X trace. The total bytes of a 5D raw ionogram data file is 32 + 500(8 + 512 + 4 + 512) = 518032 bytes.

Ionogram header in detail:

Field Size Example/Format
ID 1 byte
SITE 3 bytes
SONDE 4 bytes 5Df_
MODE 1 byte O, X, M, S
PROCESS 1 bytes f, 8, 1
NUM_CHANS 4 bytes
SPARE 4 bytes

The mini header which precedes each channel comprises 8 bytes, as follows.

Field Size
MAX 1b

Clean ionogram data format

The clean ionogram data format consists of three parts:

  • a standard header format describing the location, time and sounding parameters of the ionogram
  • a run-length encoded list of the frequencies sounded (frequency list)
  • a series of run-length encoded channel information

The clean ionogram data is saved in an encoded format to compress the data. Specific encoding and decoding functions have been developed for this purpose. Pseudo-code for the frequency list format and channel data format follows.

Frequency list

The frequency list consists of a start frequency, followed by a run-length encoded list of the steps between the sounded frequencies.

Pseudo-code for decoding frequencies:

// 2 bytes for the start frequency // left shift 8 bits of the first byte and do bitwise OR with the second byte, // this will put their bytes one after the other to find the start frequency, as below start_freq (kHz) = first byte << 8 | second byte while(loop counter < number of frequencies i.e. N_FREQS) { read the frequency step: 1 byte if < 255, else 3 bytes // i.e. read a byte if byte < 255 then it is the frequency step else the next 2 bytes are the frequency step read the runlength: 1 byte if < 255, else 3 bytes // i.e. read a byte if byte < 255 then it is runlength else the next 2 bytes are runlength loop counter = loop counter + runlength }

Channel data format

The channel data format is described below.

1 byte per channel: First 7 bits of which are for average amplitude and the high (8th) bit indicates whether there are any echoes.

1 byte per channel: Gives the offset of the start row from the last row (ninth bit of this is stored in high bit of first amplitude.

1 byte per amplitude: The high bit indicates end of run. If it is not the end of the run, the remaining 7 bits are the amplitude. If it is the end of the run, the 7th bit indicates end of channel and the remaining six bits are the amplitude truncated to be below 64. An amplitude of 0 is only possible as the second amplitude of a run and indicates the run was only length one (impossible with current method).

Pseudo-code for decoding the channel data:

Read 1 byte giving the average amplitude of the channel. // The 8th bit is used to indicate if there are echoes in this channel. lastrow = 0 // find average amplitude from the byte read above: average amplitude = (byte & 127) << 1 if (byte & 128) is true (eighth bit set) then continue decoding loop { read in one byte giving the row offset // if row offset > 255 the 8th bit of the amplitude is set read in 1 data byte // check if the eighth bit is set, i.e., if (data byte & 128) is non zero then row offset = row offset + 256 current row = last row + row offset amplitude = (data byte & 127) << 1 // get all the amplitude for this echo loop { current row = current row +1 read in data byte amplitude = (data byte & 127) << 1 } while (data byte & 128) equals 0 amplitude &= 127 if amplitude = 0 (runlength of 1) current row = current row -1 else current row = current row +1 } while (data byte & 64) = 0

go to top of page