Add vectorized version of df and typecode functions.
This commit is contained in:
parent
47de4d1163
commit
e53b51faa5
@ -1,13 +1,7 @@
|
||||
import os
|
||||
import warnings
|
||||
|
||||
try:
|
||||
from . import c_common as common
|
||||
from .c_common import *
|
||||
except:
|
||||
from . import py_common as common
|
||||
from .py_common import *
|
||||
|
||||
from .common import *
|
||||
from .decoder import tell
|
||||
from .decoder import adsb
|
||||
from .decoder import commb
|
||||
|
48
pyModeS/common.py
Normal file
48
pyModeS/common.py
Normal file
@ -0,0 +1,48 @@
|
||||
import typing as tp
|
||||
from functools import singledispatch
|
||||
|
||||
from .vec import common as common_vec
|
||||
from .vec.types import InputData
|
||||
try:
|
||||
from . import c_common as common_str
|
||||
except:
|
||||
from . import py_common as common_str
|
||||
|
||||
@singledispatch
|
||||
def df(msg: tp.Any) -> int:
|
||||
raise NotImplementedError('Only string and NumPy arrays supported')
|
||||
|
||||
@df.register
|
||||
def _df_str(msg: str) -> int:
|
||||
return common_str.df(msg)
|
||||
|
||||
@df.register
|
||||
def _df_vec(msg: InputData) -> int:
|
||||
return common_vec.df(msg)
|
||||
|
||||
@singledispatch
|
||||
def typecode(msg: tp.Any) -> int:
|
||||
raise NotImplementedError('Only string and NumPy arrays supported')
|
||||
|
||||
@typecode.register
|
||||
def _tc_str(msg: str) -> int:
|
||||
return common_str.typecode(msg)
|
||||
|
||||
@typecode.register
|
||||
def _tc_vec(msg: InputData) -> int:
|
||||
return common_vec.typecode(msg)
|
||||
|
||||
icao = common_str.icao
|
||||
altitude = common_str.altitude
|
||||
altcode = common_str.altcode
|
||||
allzeros = common_str.allzeros
|
||||
data = common_str.data
|
||||
wrongstatus = common_str.wrongstatus
|
||||
idcode = common_str.idcode
|
||||
floor = common_str.floor
|
||||
cprNL = common_str.cprNL
|
||||
crc = common_str.crc
|
||||
squawk = common_str.squawk
|
||||
hex2bin = common_str.hex2bin
|
||||
hex2bin = common_str.hex2bin
|
||||
bin2int = common_str.bin2int
|
0
pyModeS/vec/__init__.py
Normal file
0
pyModeS/vec/__init__.py
Normal file
34
pyModeS/vec/common.py
Normal file
34
pyModeS/vec/common.py
Normal file
@ -0,0 +1,34 @@
|
||||
import numpy as np
|
||||
import typing as tp
|
||||
|
||||
from .util import create_array
|
||||
from .types import InputData, DownlinkFormat, TypeCode
|
||||
|
||||
|
||||
def df(data: InputData) -> DownlinkFormat:
|
||||
"""
|
||||
Parse downlink format address from ADS-B messages.
|
||||
|
||||
:param data: ADS-B messages.
|
||||
|
||||
..seealso:: `Message structure <https://mode-s.org/decode/content/ads-b/1-basics.html>`_
|
||||
"""
|
||||
result = (data[:, 0] & 0xf8) >> 3
|
||||
result[result > 24] = 24
|
||||
return result
|
||||
|
||||
def typecode(data: InputData, df_data: tp.Optional[DownlinkFormat]=None) -> TypeCode:
|
||||
"""
|
||||
Parse type code information from ADS-B messages.
|
||||
|
||||
:param data: ADS-B messages.
|
||||
:param df_data: Optional downlink format information for each ADS-B
|
||||
message.
|
||||
|
||||
..seealso:: `ADS-B message types <https://mode-s.org/decode/content/ads-b/1-basics.html>`_
|
||||
"""
|
||||
result = np.zeros(len(data), dtype=np.uint8)
|
||||
df_v = df(data) if df_data is None else df_data
|
||||
idx = (df_v == 17) | (df_v == 18)
|
||||
result[idx] = data[idx, 4] >> 3
|
||||
return create_array(result, idx)
|
15
pyModeS/vec/ctor.py
Normal file
15
pyModeS/vec/ctor.py
Normal file
@ -0,0 +1,15 @@
|
||||
import numpy as np
|
||||
import typing as tp
|
||||
|
||||
from .types import InputData
|
||||
|
||||
def array(data: tp.Sequence[bytes]) -> InputData:
|
||||
"""
|
||||
Create Numpy array, which is input for parsing functions.
|
||||
|
||||
:param data: Collection of ADS-B messages.
|
||||
"""
|
||||
vec = np.array(data)
|
||||
result = vec.view(dtype=np.uint8)
|
||||
return result.reshape(-1, 14)
|
||||
|
9
pyModeS/vec/types.py
Normal file
9
pyModeS/vec/types.py
Normal file
@ -0,0 +1,9 @@
|
||||
import numpy as np
|
||||
|
||||
# define aliases for basic types to support static type analysis; these for
|
||||
# convenience
|
||||
# NOTE: more specific types can be defined when numpy 1.20 is released,
|
||||
# i.e. use of np.ndarray[dtype, shape] shall be possible
|
||||
InputData = np.ndarray
|
||||
DownlinkFormat = np.ndarray
|
||||
TypeCode = np.ndarray
|
16
pyModeS/vec/util.py
Normal file
16
pyModeS/vec/util.py
Normal file
@ -0,0 +1,16 @@
|
||||
import numpy as np
|
||||
|
||||
def create_array(data, idx):
|
||||
"""
|
||||
Create NumPy masked array.
|
||||
|
||||
Note, that this function differes from NumPy constructor semantics. The
|
||||
index indicates the valid values (not the invalid as in the default
|
||||
masked array in NumPy).
|
||||
|
||||
:param data: Input data.
|
||||
:param idx: Index of valid values.
|
||||
"""
|
||||
return np.ma.array(data, mask=~idx)
|
||||
|
||||
# vim: sw=4:et:ai
|
0
tests/vec/__init__.py
Normal file
0
tests/vec/__init__.py
Normal file
26
tests/vec/data.py
Normal file
26
tests/vec/data.py
Normal file
@ -0,0 +1,26 @@
|
||||
import numpy as np
|
||||
from binascii import unhexlify
|
||||
|
||||
from pyModeS.vec.ctor import array
|
||||
from pyModeS.vec.common import df
|
||||
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def message():
|
||||
data = [
|
||||
'904ca3a33219741c85465ae1b4c3', # df = 18
|
||||
'a8281d3030000000000000850d4a', # df = 21
|
||||
'8d406b902015a678d4d220000000', # example from https://mode-s.org/decode/content/ads-b/8-error-control.html
|
||||
'904ca3da121010603d04f5df3ecf', # df = 18, tc = 2
|
||||
'977ba7ca0daa3e1915d83237c86e', # df = 18, tc = 1
|
||||
'8d4ca2d4234994b5452820e5b7ab', # df = 17, tc = 4
|
||||
]
|
||||
return array(np.array([unhexlify(v) for v in data]))
|
||||
|
||||
@pytest.fixture
|
||||
def df_message(message):
|
||||
return df(message)
|
||||
|
||||
# vim: sw=4:et:ai
|
||||
|
20
tests/vec/test_common.py
Normal file
20
tests/vec/test_common.py
Normal file
@ -0,0 +1,20 @@
|
||||
import numpy as np
|
||||
|
||||
from pyModeS.common import df, typecode
|
||||
|
||||
from .data import message
|
||||
|
||||
def test_df(message):
|
||||
"""
|
||||
Test parsing of ADS-B downlink format.
|
||||
"""
|
||||
result = df(message)
|
||||
assert np.array_equal([18, 21, 17, 18, 18, 17], result)
|
||||
|
||||
def test_typecode(message):
|
||||
"""
|
||||
Test ADS-B type code parsing.
|
||||
"""
|
||||
result = typecode(message)
|
||||
assert np.array_equal([6, 0, 4, 2, 1, 4], result)
|
||||
assert np.array_equal([6, 4, 2, 1, 4], result.compressed())
|
Loading…
Reference in New Issue
Block a user