Binder Colab Deepnote Kaggle

Low-level API

The most common usage of the pyodc module will be for encoding and decoding ODB-2 data. However, the module also contains a number of classes that facilitate the exploration of the data. Together, they provide an API for exploring the structure and contents of ODB-2 data without actually decoding it.

The Reader Object

The Reader class provides an access point to further details.

For example, by creating a reader instance it’s possible to see how many frames are encoded in ODB-2 data:

[1]:
import sys
import os
sys.path.insert(0, os.path.abspath('../../..'))
[2]:
import pyodc as odc

r = odc.Reader('example-1.odb')

print('frame(s):', len(r.frames))
frame(s): 1

The Frame Object

The Frame class describes specific frames in the stream.

For example, to check how many rows and columns are present in particular frames, we can inspect their properties:

[3]:
print('row(s):   ', [f.nrows for f in r.frames])
print('column(s):', [f.ncolumns for f in r.frames])
row(s):    [10]
column(s): [7]

Next, we can inspect which columns are present in the frame and their types:

[4]:
print('column types:', *[f.columns for f in r.frames])
column types: [expver:integer, date@hdr:integer, statid@hdr:string, wigos@hdr:string, obsvalue@body:double, integer_missing:integer, double_missing:double]

Column Properties

The ColumnInfo class abstracts each column of a frame. To access its properties, simply refer to a particular column in a frame:

[5]:
obsvalue = r.frames[0].columns[4]
print('column name:     ', obsvalue.name)
print('column data type:', obsvalue.dtype)
print('column index:    ', obsvalue.index)
print('column data size:', obsvalue.datasize)
column name:      obsvalue@body
column data type: DataType.DOUBLE
column index:     4
column data size: 8

Bitfield Columns

Bitfield columns provide additional metadata, including flag names, their offsets and sizes.

[6]:
r_bf = odc.Reader('example-6.odb')

bitfield_column = r_bf.frames[0].columns[0]
print('flag names:   ', [flag.name for flag in bitfield_column.bitfields])
print('flag sizes:   ', [flag.size for flag in bitfield_column.bitfields])
print('flag offsets: ', [flag.offset for flag in bitfield_column.bitfields])
flag names:    ['flag_a', 'flag_b', 'flag_c']
flag sizes:    [1, 2, 5]
flag offsets:  [0, 1, 3]

Decoding Data

Data can also be decoded directly at the frame level, by calling member function dataframe on a specific frame object:

[7]:
df_decoded = r.frames[0].dataframe()
print(df_decoded)
   expver  date@hdr statid@hdr        wigos@hdr  obsvalue@body  \
0       1  20210420     stat00  0-12345-0-67890         0.0000
1       1  20210420     stat01  0-12345-0-67891        12.3456
2       1  20210420     stat02  0-12345-0-67892        24.6912
3       1  20210420     stat03  0-12345-0-67893        37.0368
4       1  20210420     stat04  0-12345-0-67894        49.3824
5       1  20210420     stat05  0-12345-0-67895        61.7280
6       1  20210420     stat06  0-12345-0-67896        74.0736
7       1  20210420     stat07  0-12345-0-67897        86.4192
8       1  20210420     stat08  0-12345-0-67898        98.7648
9       1  20210420     stat09  0-12345-0-67899       111.1104

   integer_missing  double_missing
0           1234.0           12.34
1           4321.0           43.21
2              NaN             NaN
3           1234.0           12.34
4           4321.0           43.21
5              NaN             NaN
6           1234.0           12.34
7           4321.0           43.21
8              NaN             NaN
9           1234.0           12.34