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