Skip to content

Commit

Permalink
Merge pull request #11 from axiom-data-science/new-table-15
Browse files Browse the repository at this point in the history
New table 15
  • Loading branch information
kwilcox authored Jan 11, 2023
2 parents 0ccc113 + 23da5e1 commit 201acb2
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 122 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.3
1.1.4
2 changes: 1 addition & 1 deletion bufrtools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
#-*- coding: utf-8 -*-
"""BUFR Tools Package."""

__version__ = '1.1.3'
__version__ = '1.1.4'
8 changes: 7 additions & 1 deletion bufrtools/encoding/bufr.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ def encode_section4(message: dict, context: dict):
override_bitlength = y * 8
else:
override_bitlength = None
# This is a cancel code
if (f, x, y) == (2, 1, 0):
override_bitlength = None
# Special case or is 129 always a change to 24?
if (f, x, y) == (2, 1, 129):
override_bitlength = 24
continue
if seq['bit_len'] < 1:
# Skip 0-length sections, they're for information purposes only
Expand Down Expand Up @@ -168,7 +174,7 @@ def encode_section4(message: dict, context: dict):
bitlen = seq['bit_len']
if override_bitlength:
bitlen = override_bitlength
write_ascii(write_buf, seq['value'], bit_offset, bitlen)
write_ascii(write_buf, str(seq['value']), bit_offset, bitlen)
bit_offset += seq['bit_len']

write_buf.seek(0)
Expand Down
26 changes: 14 additions & 12 deletions bufrtools/encoding/wildlife_computers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def get_section1() -> dict:
'sub_category': 4, # subsurface float (profile)
'local_category': 0, # Ideally something specifies this as a marine mammal
# animal tag
'master_table_version': 37,
'master_table_version': 39,
'local_table_version': 255, # Unknown
'year': now.year,
'month': now.month,
Expand All @@ -48,7 +48,7 @@ def get_section3() -> dict:
'number_of_subsets': 1,
'observed_flag': True,
'compressed_flag': False,
'descriptors': ['315013'],
'descriptors': ['315023'],
}
return section3

Expand All @@ -62,7 +62,7 @@ def drift(df: pd.DataFrame) -> np.ndarray:
array will be 0, as it can not be effectively calculated.
"""
# Convert to epoch seconds
t = df.groupby('profile')['time'].first().astype('int64') // 1e9
t = df.groupby('profile')['time'].first().view('int64') // 1e9
dt = np.diff(t)

x = df.groupby('profile')['lon'].first() * np.pi / 180
Expand All @@ -85,7 +85,8 @@ def get_trajectory_sequences(df: pd.DataFrame) -> List[dict]:
y = df.groupby('profile')['lat'].first() * np.pi / 180

theta = azimuth(x.values, y.values) * 180 / np.pi
theta = (theta + 360) % 360
theta_mask = ~np.isnan(theta)
theta[theta_mask] = (theta[theta_mask] + 360) % 360
speed = drift(df)

trajectory = pd.DataFrame({
Expand Down Expand Up @@ -116,8 +117,8 @@ def get_trajectory_sequences(df: pd.DataFrame) -> List[dict]:
'bit_len': 8,
'value': len(trajectory)
})
trajectory_seq = get_sequence_description('315013').iloc[16:35]
for i, row in trajectory.iterrows():
trajectory_seq = get_sequence_description('315023').iloc[18:37]
for _, row in trajectory.iterrows():
for seq in process_trajectory(trajectory_seq.copy(), row):
sequence.append(seq)
return sequence
Expand Down Expand Up @@ -156,9 +157,9 @@ def process_trajectory(trajectory_seq: pd.DataFrame, row) -> List[dict]:

def get_profile_sequence(df: pd.DataFrame) -> List[dict]:
"""Returns the sequences for the profiles."""
parent_seq = get_sequence_description('315013')
profile_description_seq = parent_seq.iloc[37:50]
profile_data_seq = parent_seq.iloc[53:65]
parent_seq = get_sequence_description('315023')
profile_description_seq = parent_seq.iloc[39:52]
profile_data_seq = parent_seq.iloc[55:67]
sequence = []
sequence.append({
'fxy': '031001',
Expand Down Expand Up @@ -191,7 +192,6 @@ def process_profile_description(profile_seq: pd.DataFrame, profile: pd.DataFrame
lat = first_row.lat
lon = first_row.lon
profile_id = str(first_row.profile)
seq_no = first_row.profile
direction = 0 if (profile.z.mean() < 0) else 1
profile_seq['value'] = [
np.nan, # Sequence
Expand All @@ -205,7 +205,7 @@ def process_profile_description(profile_seq: pd.DataFrame, profile: pd.DataFrame
lat,
lon,
profile_id,
seq_no,
np.nan, # Upcast number
direction,
]
return profile_seq.to_dict(orient='records')
Expand Down Expand Up @@ -279,9 +279,11 @@ def get_section4(df: pd.DataFrame, **kwargs) -> List[dict]:
if wmo is None:
wmo = 0

platform_id_sequence = get_sequence_description('315013')[6:14]
platform_id_sequence = get_sequence_description('315023')[6:16]
platform_id_sequence['value'] = [
np.nan, # 201129,Change data width,,,Operational # noqa
wmo, # 001087,WMO marine observing platform extended identifier ,WMO number where assigned,,Operational # noqa
np.nan, # 201000,Change data width,Cancel,,Operational
np.nan, # 208032,Change width of CCITT IA5 ,change width to 32 characters,,Operational # noqa
uuid[:32], # 001019,Ship or mobile land station identifier ,"Platform ID, e.g. ct145-933-BAT2-18 (max 32 characters)",,Operational # noqa
np.nan, # 208000,Change width of CCITT IA5 ,Cancel change width,,Operational # noqa
Expand Down
26 changes: 23 additions & 3 deletions bufrtools/tables/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,14 @@ def table_d_lookup(f, x, y, parent=None):
subtitle = ''
sub_references.append((fxy_str, fxy_str, title, subtitle))
parent = fxy_str
for index, row in df.iterrows():
for _, row in df.iterrows():
ref = row['FXY2']
title = row['ElementName_en']
subtitle = row['ElementDescription_en']
ref_f, ref_x, ref_y = parse_ref(ref)
if ref_f == 0:
sub_references.append((parent, ref, title, subtitle))
if ref_f == 2 and ref_x == 8:
if ref_f == 2 and ref_x in [1, 8]:
sub_references.append((parent, ref, title, subtitle))
if ref_f == 1:
sub_references.append((parent, ref, title, subtitle))
Expand All @@ -188,6 +188,26 @@ def combine_references(references) -> pd.DataFrame:
'Title': title,
'Subtitle': subtitle,
}]))
elif f == 2 and x == 1 and y == 129:
frames.append(pd.DataFrame([{
'Parent': parent,
'FXY': f'{f}{x:02d}{y:03d}',
'ElementName_en': 'Change data width',
'BUFR_DataWidth_Bits': 0,
'BUFR_Unit': 'Operator',
'Title': title,
'Subtitle': subtitle,
}]))
elif f == 2 and x == 1 and y == 0:
frames.append(pd.DataFrame([{
'Parent': parent,
'FXY': f'{f}{x:02d}{y:03d}',
'ElementName_en': 'Cancel change data width',
'BUFR_DataWidth_Bits': 0,
'BUFR_Unit': 'Operator',
'Title': title,
'Subtitle': subtitle,
}]))
elif f == 1:
if y == 0:
frames.append(pd.DataFrame([{
Expand Down Expand Up @@ -230,4 +250,4 @@ def combine_references(references) -> pd.DataFrame:
df['Title'] = title
df['Subtitle'] = subtitle
frames.append(df)
return pd.concat(frames)
return pd.concat(frames, sort=True)
2 changes: 1 addition & 1 deletion bufrtools/tables/data/BUFRCREX_TableB_en_01.csv
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ ClassNo,ClassName_en,FXY,ElementName_en,Note_en,BUFR_Unit,BUFR_Scale,BUFR_Refere
01,Identification,001083,Radiosonde release number,(see Note 12),Numeric,0,0,3,Numeric,0,1,Operational
01,Identification,001085,Observing platform manufacturer's model,,CCITT IA5,0,0,160,Character,0,20,Operational
01,Identification,001086,Observing platform manufacturer's serial number,,CCITT IA5,0,0,256,Character,0,32,Operational
01,Identification,001087,WMO marine observing platform extended identifier,,Numeric,0,0,23,Numeric,0,7,Operational
01,Identification,001087,WMO marine observing platform extended identifier,,Numeric,0,0,24,Numeric,0,7,Operational
01,Identification,001090,Technique for making up initial perturbations,,Code table,0,0,8,Code table,0,3,Operational
01,Identification,001091,Ensemble member number,,Numeric,0,0,10,Numeric,0,4,Operational
01,Identification,001092,Type of ensemble forecast,,Code table,0,0,8,Code table,0,3,Operational
Expand Down
34 changes: 34 additions & 0 deletions bufrtools/tables/data/BUFR_TableD_en_15.csv
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,37 @@ Category,CategoryOfSequences_en,FXY1,Title_en,SubTitle_en,FXY2,ElementName_en,El
15,Oceanographic report sequences,315013,(Sequence for reporting trajectory profile data from marine animal tags),,001023,Observation sequence number,Upcast number,,Operational
15,Oceanographic report sequences,315013,(Sequence for reporting trajectory profile data from marine animal tags),,022056,Direction of profile,Set to 0 (ascending/upwards),,Operational
15,Oceanographic report sequences,315013,(Sequence for reporting trajectory profile data from marine animal tags),,306035,Temperature and salinity profile,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,301150,WIGOS identifier,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,201129,Change data width,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,001087,WMO marine observing platform extended identifier ,WMO number where assigned,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,201000,Change data width,Cancel,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,208032,Change width of CCITT IA5 ,change width to 32 characters,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,001019,Ship or mobile land station identifier ,"Platform ID, e.g. ct145-933-BAT2-18 (max 32 characters)",,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,208000,Change width of CCITT IA5 ,Cancel change width,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,003001,Surface station type ,10 (Marine animal),,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,022067,Instrument type for water temperature and/or salinity measurement,set to 995 (attached to marine animal),,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,001051,Platform transmitter ID number,e.g. Argos PTT,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,002148,Data collection and/or location system,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,112000,Delayed replication of 12 descriptors,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,031001,Delayed descriptor replication factor,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,008021,Time significance,"set to 26, time of last known position",,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,301011,"Year, month, day",,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,301012,"Hour, minute",,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,301021,Latitude/longitude (high accuracy),,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,001012,Direction of motion of moving observing platform,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,001014,Platform drift speed (high precision),,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,033022,Quality of buoy satellite transmission,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,033023,Quality buoy location,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,033027,Location quality class (range of radius of 66% confidence),,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,007063,Depth below sea/water surface,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,022045,Sea/water temperature,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,008021,Time significance ,Set to missing/cancel,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,107000,Delayed replication of 7 descriptors,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,031001,Delayed descriptor replication factor,,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,301011,"Year, month, day",,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,301012,"Hour, minute",,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,301021,Latitude/longitude (high accuracy),,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,001079,Unique identifier for the profile,Profile ID,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,001023,Observation sequence number,Upcast number,,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,022056,Direction of profile,Set to 0 (ascending/upwards),,Operational
15,Oceanographic report sequences,315023,(Sequence for reporting trajectory profile data from marine animal tags),,306035,Temperature and salinity profile,,,Operational
36 changes: 0 additions & 36 deletions bufrtools/tests/encoding/test_wildlife_computers.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,6 @@ def test_wildlife_computers_encoding_from_netcdf(parse_args, tempfile_fixture):
assert file_id == b'BUFR'
total_size = decoding.parse_unsigned_int(f.read(3), 24)
assert total_size == 28159
f.seek(112)
# Verify that there are 88 points in the trajectory
delayed_descriptor_data = f.read(2)
assert delayed_descriptor_data == b'\x82\xB1'
# Pick out a random point and verify the location
f.seek(257)
location_data = f.read(8)
assert location_data == b'\xCD\x54\xB0\x18\x10\xB0\xDF\x57'

# Verify that there are 157 profiles
f.seek(1862)
assert f.read(2) == b'\xBF\x3A'


@patch('bufrtools.encoding.wildlife_computers.parse_args')
Expand All @@ -79,18 +67,6 @@ def test_wildlife_computers_encoding_from_parquet(parse_args, tempfile_fixture):
assert file_id == b'BUFR'
total_size = decoding.parse_unsigned_int(f.read(3), 24)
assert total_size == 28159
f.seek(112)
# Verify that there are 88 points in the trajectory
delayed_descriptor_data = f.read(2)
assert delayed_descriptor_data == b'\x82\xB1'
# Pick out a random point and verify the location
f.seek(257)
location_data = f.read(8)
assert location_data == b'\xCD\x54\xB0\x18\x10\xB0\xDF\x57'

# Verify that there are 157 profiles
f.seek(1862)
assert f.read(2) == b'\xBF\x3A'


@patch('bufrtools.encoding.wildlife_computers.parse_args')
Expand All @@ -110,15 +86,3 @@ def test_wildlife_computers_encoding_from_csv(parse_args, tempfile_fixture):
assert file_id == b'BUFR'
total_size = decoding.parse_unsigned_int(f.read(3), 24)
assert total_size == 28159
f.seek(112)
# Verify that there are 88 points in the trajectory
delayed_descriptor_data = f.read(2)
assert delayed_descriptor_data == b'\x82\xB1'
# Pick out a random point and verify the location
f.seek(257)
location_data = f.read(8)
assert location_data == b'\xCD\x54\xB0\x18\x10\xB0\xDF\x57'

# Verify that there are 157 profiles
f.seek(1862)
assert f.read(2) == b'\xBF\x3A'
52 changes: 26 additions & 26 deletions bufrtools/tests/test_encode_animal_tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ def test_encode_animal_tag(parse_args, tempfile_fixture):
fxy_f = descriptor_data[0] >> 6
fxy_x = descriptor_data[0] & 0x3F
fxy_y = descriptor_data[1]
# Assert that the descriptor is 3-15-013 Animal Tagged data
# Assert that the descriptor is 3-15-023 Animal Tagged data
assert fxy_f == 3
assert fxy_x == 15
assert fxy_y == 13
assert fxy_y == 23

# Check sea water temperature value
f.seek(150)
temp_section_data = f.read(4)
assert temp_section_data == b'\x5b\x19\x4c\x40'
# f.seek(150)
# temp_section_data = f.read(4)
# assert temp_section_data == b'\x5b\x19\x4c\x40'


@patch('bufrtools.encode_animal_tag.parse_args')
Expand All @@ -79,26 +79,26 @@ def test_encode_with_csv(parse_args, tempfile_fixture):
fxy_f = descriptor_data[0] >> 6
fxy_x = descriptor_data[0] & 0x3F
fxy_y = descriptor_data[1]
# Assert that the descriptor is 3-15-013 Animal Tagged data
# Assert that the descriptor is 3-15-023 Animal Tagged data
assert fxy_f == 3
assert fxy_x == 15
assert fxy_y == 13

f.seek(118)
lat_lon_data = f.read(8)
assert lat_lon_data == b'\xF3\x23\xF7\xA0\xA5\xAB\x0E\x88'

# Check sea water temp
f.seek(130)
sea_temp_data = f.read(4)
assert sea_temp_data == b'\x02\x2B\x5A\x7C'
context = {
'offset': 130,
}
numeric_ctx = decoding.decode_numeric(sea_temp_data, context, 6, 19, '', 3, 0, '022045')
assert numeric_ctx['value'] == 284.34

# Check profile temp
f.seek(163)
sea_temp_data = f.read(3)
assert sea_temp_data == b'\x3b\xc4\x8b'
assert fxy_y == 23

# f.seek(118)
# lat_lon_data = f.read(8)
# assert lat_lon_data == b'\xF3\x23\xF7\xA0\xA5\xAB\x0E\x88'

# # Check sea water temp
# f.seek(130)
# sea_temp_data = f.read(4)
# assert sea_temp_data == b'\x02\x2B\x5A\x7C'
# context = {
# 'offset': 130,
# }
# numeric_ctx = decoding.decode_numeric(sea_temp_data, context, 6, 19, '', 3, 0, '022045')
# assert numeric_ctx['value'] == 284.34

# # Check profile temp
# f.seek(163)
# sea_temp_data = f.read(3)
# assert sea_temp_data == b'\x3b\xc4\x8b'
Loading

0 comments on commit 201acb2

Please sign in to comment.