From 61b55531e80609c29835ca1d24277117c8d516d7 Mon Sep 17 00:00:00 2001 From: Junzi Sun Date: Tue, 16 Apr 2019 11:57:57 +0200 Subject: [PATCH] update BDS 44 and 45, and MRAR switch in infer(). --- pyModeS/decoder/bds/__init__.py | 29 +++++--- pyModeS/decoder/bds/bds44.py | 32 ++++----- pyModeS/decoder/bds/bds45.py | 120 ++++++++++++++++++++++++++++++-- 3 files changed, 144 insertions(+), 37 deletions(-) diff --git a/pyModeS/decoder/bds/__init__.py b/pyModeS/decoder/bds/__init__.py index d08ddd3..548cf2e 100644 --- a/pyModeS/decoder/bds/__init__.py +++ b/pyModeS/decoder/bds/__init__.py @@ -24,11 +24,11 @@ import numpy as np from pyModeS.extra import aero from pyModeS.decoder import common from pyModeS.decoder.bds import bds05, bds06, bds08, bds09, \ - bds10, bds17, bds20, bds30, bds40, bds44, bds50, bds53, bds60 + bds10, bds17, bds20, bds30, bds40, bds44, bds45, bds50, bds53, bds60 def is50or60(msg, spd_ref, trk_ref, alt_ref): - """Use reference ground speed and trk to determine BDS50 and DBS60 + """Use reference ground speed and trk to determine BDS50 and DBS60. Args: msg (String): 28 bytes hexadecimal message string @@ -38,6 +38,7 @@ def is50or60(msg, spd_ref, trk_ref, alt_ref): Returns: String or None: BDS version, or possible versions, or None if nothing matches. + """ def vxy(v, angle): vx = v * np.sin(np.radians(angle)) @@ -88,16 +89,17 @@ def is50or60(msg, spd_ref, trk_ref, alt_ref): return BDS -def infer(msg): - """Estimate the most likely BDS code of an message +def infer(msg, mrar=False): + """Estimate the most likely BDS code of an message. Args: msg (String): 28 bytes hexadecimal message string + mrar (bool): Also infer MRAR (BDS 44) and MHR (BDS 45). Defaults to False. Returns: String or None: BDS version, or possible versions, or None if nothing matches. - """ + """ df = common.df(msg) if common.allzeros(msg): @@ -124,7 +126,7 @@ def infer(msg): if tc == 31: return 'BDS65' # operational status - # For Comm-B replies, ELS + EHS only + # For Comm-B replies IS10 = bds10.is10(msg) IS17 = bds17.is17(msg) IS20 = bds20.is20(msg) @@ -132,12 +134,17 @@ def infer(msg): IS40 = bds40.is40(msg) IS50 = bds50.is50(msg) IS60 = bds60.is60(msg) + IS44 = bds44.is44(msg) + IS45 = bds45.is45(msg) - allbds = np.array([ - "BDS10", "BDS17", "BDS20", "BDS30", "BDS40", "BDS50", "BDS60" - ]) - - mask = [IS10, IS17, IS20, IS30, IS40, IS50, IS60] + if mrar: + allbds = np.array(["BDS10", "BDS17", "BDS20", "BDS30", "BDS40", + "BDS44", "BDS45", "BDS50", "BDS60"]) + mask = [IS10, IS17, IS20, IS30, IS40, IS44, IS45, IS50, IS60] + else: + allbds = np.array(["BDS10", "BDS17", "BDS20", "BDS30", "BDS40", + "BDS50", "BDS60"]) + mask = [IS10, IS17, IS20, IS30, IS40, IS50, IS60] bds = ','.join(sorted(allbds[mask])) diff --git a/pyModeS/decoder/bds/bds44.py b/pyModeS/decoder/bds/bds44.py index f20d67c..9db8ec8 100644 --- a/pyModeS/decoder/bds/bds44.py +++ b/pyModeS/decoder/bds/bds44.py @@ -29,7 +29,6 @@ def is44(msg): Args: msg (String): 28 bytes hexadecimal message string - rev (bool): using revised version Returns: bool: True or False @@ -61,13 +60,13 @@ def is44(msg): if vw is not None and vw[0] > 250: return False - temp = temp44(msg) - if temp: - if temp > 60 or temp < -80: - return False - - elif temp == 0: - return False + # CAN NOT USE TEMP HERE. THERE IS AN ERROR IN ICAO 9871 (2008) + # temp = temp44(msg) + # if temp: + # if temp > 60 or temp < -80: + # return False + # elif temp == 0: + # return False return True @@ -76,8 +75,7 @@ def wind44(msg): """Wind speed and direction. Args: - msg (String): 28 bytes hexadecimal message (BDS44) string - rev (bool): using revised version + msg (String): 28 bytes hexadecimal message string Returns: (int, float): speed (kt), direction (degree) @@ -99,8 +97,7 @@ def temp44(msg): """Static air temperature. Args: - msg (String): 28 bytes hexadecimal message (BDS44) string - rev (bool): using revised version + msg (String): 28 bytes hexadecimal message string Returns: float: tmeperature in Celsius degree @@ -127,8 +124,7 @@ def p44(msg): """Static pressure. Args: - msg (String): 28 bytes hexadecimal message (BDS44) string - rev (bool): using revised version + msg (String): 28 bytes hexadecimal message string Returns: int: static pressure in hPa @@ -148,8 +144,7 @@ def hum44(msg): """humidity Args: - msg (String): 28 bytes hexadecimal message (BDS44) string - rev (bool): using revised version + msg (String): 28 bytes hexadecimal message string Returns: float: percentage of humidity, [0 - 100] % @@ -168,11 +163,10 @@ def turb44(msg): """Turblence. Args: - msg (String): 28 bytes hexadecimal message (BDS44) string - rev (bool): using revised version + msg (String): 28 bytes hexadecimal message string Returns: - int: turbulence level. 0: NIL, 1: Light, 2: Moderate, 3: Severe + int: turbulence level. 0=NIL, 1=Light, 2=Moderate, 3=Severe """ d = hex2bin(data(msg)) diff --git a/pyModeS/decoder/bds/bds45.py b/pyModeS/decoder/bds/bds45.py index 6c8587f..5a4daf4 100644 --- a/pyModeS/decoder/bds/bds45.py +++ b/pyModeS/decoder/bds/bds45.py @@ -29,7 +29,6 @@ def is45(msg): Args: msg (String): 28 bytes hexadecimal message string - rev (bool): using revised version Returns: bool: True or False @@ -59,7 +58,7 @@ def is45(msg): if wrongstatus(d, 16, 17, 26): return False - if wrongstatus(d, 17, 28, 38): + if wrongstatus(d, 27, 28, 38): return False if wrongstatus(d, 39, 40, 51): @@ -77,12 +76,101 @@ def is45(msg): return True +def turb45(msg): + """Turbulence. + + Args: + msg (String): 28 bytes hexadecimal message string + + Returns: + int: Turbulence level. 0=NIL, 1=Light, 2=Moderate, 3=Severe + + """ + d = hex2bin(data(msg)) + if d[0] == '0': + return None + + turb = bin2int(d[1:3]) + return turb + + +def ws45(msg): + """Wind shear. + + Args: + msg (String): 28 bytes hexadecimal message string + + Returns: + int: Wind shear level. 0=NIL, 1=Light, 2=Moderate, 3=Severe + + """ + d = hex2bin(data(msg)) + if d[3] == '0': + return None + + ws = bin2int(d[4:6]) + return ws + + +def mb45(msg): + """Microburst. + + Args: + msg (String): 28 bytes hexadecimal message string + + Returns: + int: Microburst level. 0=NIL, 1=Light, 2=Moderate, 3=Severe + + """ + d = hex2bin(data(msg)) + if d[6] == '0': + return None + + mb = bin2int(d[7:9]) + return mb + + +def ic45(msg): + """Icing. + + Args: + msg (String): 28 bytes hexadecimal message string + + Returns: + int: Icing level. 0=NIL, 1=Light, 2=Moderate, 3=Severe + + """ + d = hex2bin(data(msg)) + if d[9] == '0': + return None + + ic = bin2int(d[10:12]) + return ic + + +def wv45(msg): + """Wake vortex. + + Args: + msg (String): 28 bytes hexadecimal message string + + Returns: + int: Wake vortex level. 0=NIL, 1=Light, 2=Moderate, 3=Severe + + """ + d = hex2bin(data(msg)) + if d[12] == '0': + return None + + ws = bin2int(d[13:15]) + return ws + + def temp45(msg): """Static air temperature. Args: - msg (String): 28 bytes hexadecimal message (BDS44) string - rev (bool): using revised version + msg (String): 28 bytes hexadecimal message string Returns: float: tmeperature in Celsius degree @@ -102,17 +190,35 @@ def temp45(msg): return temp -def p44(msg, rev=False): +def p45(msg): """Average static pressure. Args: - msg (String): 28 bytes hexadecimal message (BDS44) string - rev (bool): using revised version + msg (String): 28 bytes hexadecimal message string Returns: int: static pressure in hPa """ d = hex2bin(data(msg)) + if d[26] == '0': + return None p = bin2int(d[27:38]) # hPa return p + + +def rh45(msg): + """Radio height. + + Args: + msg (String): 28 bytes hexadecimal message string + + Returns: + int: radio height in ft + + """ + d = hex2bin(data(msg)) + if d[38] == '0': + return None + rh = bin2int(d[39:51]) + return rh