IPS Raw and Clean Ionogram Format
The 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.
1. 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. IPS internal use only. e.g., A.
Nchans - An integer giving the number of channels sounded. e.g., 512.
min_km - A double precision floating point number giving the minimum height of the sounding
(start height) in km. e.g., 80.00.
height_step - A double precision floating point number giving the height step for a channel
in km. e.g., 1.20.
nrows - An integer giving the number of height steps. e.g., 512.
lat, lon, diplat - Three double precision floating point numbers giving geographic latitude and
longitude and geomagnetic latitude in degrees. e.g., - 4 2 . 9 0 1 4 7 . 3 0 5 8 . 6 0.
year, month, day, hour, min - Five integers giving the time of the sounding (UT). e.g., 1 9 9 4 0 4 0 1 0 0 0 0.
Location[80] - An ASCII description string used to describe the location of the ionosonde, e.g.,
hbt5a for Hobart 5a ionosonde.
2. 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 repetetions 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.
| Header |
Channels, each channel contains |
| bytes=(size of header) |
2 bytes for frequency |
1 byte for repetitions |
Amplitude: 1 byte per amplitude |
5D ionosonde raw data format
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.
In detail: IONO HEADER
| Field |
Size |
Example/Format |
| ID |
1b |
|
| SITE |
3b |
|
| DATE |
8b |
YYYYMMDD |
| TIME |
6b |
HHMMSS |
| SONDE |
4b |
5Df_ |
| MODE |
1b |
O, X, M, S |
| PROCESS |
1b |
f, 8, 1 |
| NUM_CHANS |
4b |
|
| SPARE |
4b |
|
CHANNEL DATA: MINI HEADER (precedes each channel, 8 bytes)
| Field |
Size |
Example/Format |
| FREQ |
2b |
|
| REG_NUM |
2b |
|
| MEDIAN |
1b |
|
| MAX |
1b |
|
| HT_MAX |
2b |
|
data: 512+4+512 bytes
FREQ(kHz) = first byte + second byte << 8
3. Clean ionogram data format
The IPS clean ionogram data format consists of three parts:
* a standard IPS 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 encoded format to compress the data. Specific encoding and
decoding functions have been developed for this purpose. A pseudo-code for the algorithm for (a)
frequency list format and (b) channel data format follows:
(a) 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
}
(b) Channel data format:
The channel data format is described as 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
THE END