From 5f63891c55c8ea6d1791c52a0281875716faa8b4 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Fri, 13 Oct 2023 15:41:40 +0100 Subject: [PATCH 1/2] Allowed for empty tables to be parsed in table_to_words --- pandablocks/utils.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pandablocks/utils.py b/pandablocks/utils.py index 7f9b46107..08012dd2d 100644 --- a/pandablocks/utils.py +++ b/pandablocks/utils.py @@ -60,11 +60,18 @@ def words_to_table( if field_info.subtype == "int": # First convert from 2's complement to offset, then add in offset. packing_value = (value ^ (1 << (bit_length - 1))) + (-1 << (bit_length - 1)) + packing_value = packing_value.astype(np.int32) elif field_info.subtype == "enum" and convert_enum_indices: assert field_info.labels, f"Enum field {field_name} has no labels" packing_value = [field_info.labels[x] for x in value] else: - packing_value = value + # Use shorter types, as these are used in waveform creation + if bit_length <= 8: + packing_value = value.astype(np.uint8) + elif bit_length <= 16: + packing_value = value.astype(np.uint16) + else: + packing_value = value.astype(np.uint32) # already uint32 unpacked.update({field_name: packing_value}) @@ -107,6 +114,8 @@ def table_to_words( # to prevent type error, this will still work if column is another iterable # e.g numpy array packed = np.zeros((len(column), row_words), dtype=np.uint32) + elif not len(column): + column_value = np.zeros(dtype=np.uint32, shape=packed.shape[0]) else: assert len(packed) == len(column), ( f"Table record {column_name} has mismatched length " From c4c787e256ee9a65187cee19bcf531b10f97c695 Mon Sep 17 00:00:00 2001 From: Eva Lott Date: Mon, 16 Oct 2023 15:10:23 +0100 Subject: [PATCH 2/2] Made corrections --- pandablocks/utils.py | 17 ++++++++++------- tests/test_utils.py | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/pandablocks/utils.py b/pandablocks/utils.py index 08012dd2d..233995065 100644 --- a/pandablocks/utils.py +++ b/pandablocks/utils.py @@ -6,6 +6,8 @@ from pandablocks.responses import TableFieldInfo UnpackedArray = Union[ + npt.NDArray[np.uint8], + npt.NDArray[np.uint16], npt.NDArray[np.int32], npt.NDArray[np.uint32], List[str], @@ -55,12 +57,13 @@ def words_to_table( # Mask to remove every bit that isn't in the range we want mask = (1 << bit_length) - 1 - value = (packed[word_offset] >> bit_offset) & mask + value: npt.NDArray[np.uint32] = (packed[word_offset] >> bit_offset) & mask + packing_value: UnpackedArray if field_info.subtype == "int": # First convert from 2's complement to offset, then add in offset. - packing_value = (value ^ (1 << (bit_length - 1))) + (-1 << (bit_length - 1)) - packing_value = packing_value.astype(np.int32) + temp = (value ^ (1 << (bit_length - 1))) + (-1 << (bit_length - 1)) + packing_value = temp.astype(np.int32) elif field_info.subtype == "enum" and convert_enum_indices: assert field_info.labels, f"Enum field {field_name} has no labels" packing_value = [field_info.labels[x] for x in value] @@ -114,12 +117,12 @@ def table_to_words( # to prevent type error, this will still work if column is another iterable # e.g numpy array packed = np.zeros((len(column), row_words), dtype=np.uint32) - elif not len(column): - column_value = np.zeros(dtype=np.uint32, shape=packed.shape[0]) else: assert len(packed) == len(column), ( - f"Table record {column_name} has mismatched length " - "compared to other records, cannot pack data" + f"Table record {column_name} has mismatched length {len(column)} " + f"compared to other records {len(packed)}, cannot pack data. " + "If setting values through the ioc, ensure all values are given " + "before submitting." ) offset = field_details.bit_low diff --git a/tests/test_utils.py b/tests/test_utils.py index c85fb567e..3940f1508 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -349,3 +349,19 @@ def test_table_packing_pack( for actual, expected in zip(unpacked, table_data_1): assert actual == expected + + +def test_table_packing_give_default_values( + table_1_np_arrays: Dict[str, UnpackedArray], + table_field_info: TableFieldInfo, +): + # We should have a complete table at the point of unpacking + table_1_np_arrays["TRIGGER"] = np.array([]) + + try: + table_to_words(table_1_np_arrays, table_field_info) + except AssertionError as e: + assert ( + "Table record TRIGGER has mismatched length 0 compared " + "to other records 3" in str(e) + )