From d470838b491a40b4de250e914cecde281279c796 Mon Sep 17 00:00:00 2001 From: Andrew Rowley Date: Fri, 1 May 2020 08:28:20 +0100 Subject: [PATCH 1/5] Add functions to get closest value and convert a single value --- data_specification/enums/data_type.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/data_specification/enums/data_type.py b/data_specification/enums/data_type.py index c0e1be9..02a91af 100644 --- a/data_specification/enums/data_type.py +++ b/data_specification/enums/data_type.py @@ -380,6 +380,16 @@ def numpy_typename(self): """ return self._numpy_typename + def closest_representable_value(self, value): + """ Returns the closest value to the given value that can be + represented by this type + + :param value: + :type value: float or in + :rtype: float + """ + return self.decode_from_int(self.encode_as_int(value)) + def encode_as_int(self, value): """ Returns the value as an integer, according to this type. @@ -450,6 +460,14 @@ def decode_numpy_array(self, array): """ return array / float(self._scale) + def decode_from_int(self, value): + """ Decode a single value represented as an int according to this type. + + :param int array: + :rtype: float or int + """ + return value / float(self._scale) + def decode_array(self, values): """ Decodes a byte array into iterable of this type. From 2af9ec910be4328a140f5873dbaea478bf7c81af Mon Sep 17 00:00:00 2001 From: Andrew Rowley Date: Wed, 20 May 2020 07:57:18 +0100 Subject: [PATCH 2/5] Round to nearest when using integer types --- data_specification/enums/data_type.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/data_specification/enums/data_type.py b/data_specification/enums/data_type.py index 02a91af..47f7717 100644 --- a/data_specification/enums/data_type.py +++ b/data_specification/enums/data_type.py @@ -19,6 +19,15 @@ import numpy as np +def _round_to_int(value): + """ Rounds a number to the closest integer + + :param float value: The value to round + :rtype: int + """ + return int(round(value)) + + class DataType(Enum): """ Supported data types. Internally, these are actually tuples. @@ -49,7 +58,7 @@ class DataType(Enum): decimal.Decimal("1"), "B", False, - int, + _round_to_int, np.uint8, "8-bit unsigned integer") #: 16-bit unsigned integer @@ -60,7 +69,7 @@ class DataType(Enum): decimal.Decimal("1"), "H", False, - int, + _round_to_int, np.uint16, "16-bit unsigned integer") #: 32-bit unsigned integer @@ -71,7 +80,7 @@ class DataType(Enum): decimal.Decimal("1"), "I", False, - int, + _round_to_int, np.uint32, "32-bit unsigned integer") #: 64-bit unsigned integer @@ -82,7 +91,7 @@ class DataType(Enum): decimal.Decimal("1"), "Q", False, - int, + _round_to_int, np.uint64, "64-bit unsigned integer") #: 8-bit signed integer @@ -93,7 +102,7 @@ class DataType(Enum): decimal.Decimal("1"), "b", False, - int, + _round_to_int, np.int8, "8-bit signed integer") #: 16-bit signed integer @@ -104,7 +113,7 @@ class DataType(Enum): decimal.Decimal("1"), "h", False, - int, + _round_to_int, np.int16, "16-bit signed integer") #: 32-bit signed integer @@ -115,7 +124,7 @@ class DataType(Enum): decimal.Decimal("1"), "i", False, - int, + _round_to_int, np.int32, "32-bit signed integer") #: 64-bit signed integer @@ -126,7 +135,7 @@ class DataType(Enum): decimal.Decimal("1"), "q", False, - int, + _round_to_int, np.int64, "64-bit signed integer") #: 8.8 unsigned fixed point number From f225c0862f3399d2d4476ed0977e302607318e4a Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 30 Jul 2020 15:56:01 +0100 Subject: [PATCH 3/5] Add function to calculate closest value above --- data_specification/enums/data_type.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/data_specification/enums/data_type.py b/data_specification/enums/data_type.py index 47f7717..7c1b093 100644 --- a/data_specification/enums/data_type.py +++ b/data_specification/enums/data_type.py @@ -399,6 +399,19 @@ def closest_representable_value(self, value): """ return self.decode_from_int(self.encode_as_int(value)) + def closest_representable_value_above(self, value): + """ Returns the closest value above the given value that can be + represented by this type + + :param value: + :type value: float or in + :rtype: float + """ + closest_value = self.decode_from_int(self.encode_as_int(value)) + if closest_value >= value: + return closest_value + return self.decode_from_int(self.encode_as_int(value)+1) + def encode_as_int(self, value): """ Returns the value as an integer, according to this type. From 64dc6859c60ed12cfefcdcf8f77e0a3728d617d2 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 30 Jul 2020 17:23:29 +0100 Subject: [PATCH 4/5] Python 2 is silly --- data_specification/enums/data_type.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_specification/enums/data_type.py b/data_specification/enums/data_type.py index 7c1b093..948928b 100644 --- a/data_specification/enums/data_type.py +++ b/data_specification/enums/data_type.py @@ -25,6 +25,8 @@ def _round_to_int(value): :param float value: The value to round :rtype: int """ + if isinstance(value, int): + return value return int(round(value)) From 6c2dc3d9ffaa17a05cbc0c03baa8222147d2aa73 Mon Sep 17 00:00:00 2001 From: Andrew Gait Date: Thu, 26 May 2022 13:46:29 +0100 Subject: [PATCH 5/5] Unittest new functions for closest representable values --- unittests/test_enums.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/unittests/test_enums.py b/unittests/test_enums.py index 3180cdb..cb5aca7 100644 --- a/unittests/test_enums.py +++ b/unittests/test_enums.py @@ -170,6 +170,11 @@ def test_data_type_enum(self): self.assertEqual( DataType.S1615.max, decimal.Decimal("65535.999969482421875")) + self.assertEqual( + DataType.S1615.closest_representable_value(1.00001), 1.0) + self.assertEqual( + DataType.S1615.closest_representable_value_above(0.99997), 1.0) + self.assertEqual(DataType.S3231.value, 13) self.assertEqual(DataType.S3231.size, 8) self.assertEqual(DataType.S3231.min, decimal.Decimal("-4294967296"))