NASA Logo
Ocean Color Science Software

ocssw V2022
packet_fields.py
Go to the documentation of this file.
1 """High level object-oriented API for elements that can exist in a packet.
2 
3 See also:
4 - packet_types.FixedLength
5 - packet_types.VariableLength
6 """
7 
8 __author__ = "Daniel da Silva <mail@danieldasilva.org>"
9 
10 import numpy as np
11 
12 from .converters import Converter
13 
14 
16  """A field contained in a packet."""
17 
18  def __init__(self, name, data_type, bit_length, bit_offset=None, byte_order="big"):
19  """
20  Parameters
21  ----------
22  name : str
23  String identifier for the field. The name specified how you may
24  call upon this data later.
25  data_type : {'uint', 'int', 'float', 'str', 'fill'}
26  Data type of the field.
27  bit_length : int
28  Number of bits contained in the field.
29  bit_offset : int, optional
30  Bit offset into packet, including the primary header which is 48 bits long.
31  If this is not specified, than the bit offset will the be calculated automatically
32  from its position inside the packet definition.
33  byte_order : {'big', 'little'}, optional
34  Byte order of the field. Defaults to big endian.
35 
36  Raises
37  ------
38  TypeError
39  If one of the arguments is not of the correct type.
40  ValueError
41  data_type or byte_order is invalid
42  """
43  if not isinstance(name, str):
44  raise TypeError("name parameter must be a str")
45  if not isinstance(data_type, str):
46  raise TypeError("data_type parameter must be a str")
47  if not isinstance(bit_length, (int, np.integer)):
48  raise TypeError("bit_length parameter must be an int")
49  if not (bit_offset is None or isinstance(bit_offset, (int, np.integer))):
50  raise TypeError("bit_offset parameter must be an int")
51 
52  valid_data_types = ("uint", "int", "float", "str", "fill")
53  if data_type not in valid_data_types:
54  raise ValueError(f"data_type must be one of {valid_data_types}")
55 
56  valid_byte_orders = ("big", "little")
57  if byte_order not in valid_byte_orders:
58  raise ValueError(f"byte_order must be one of {valid_byte_orders}")
59 
60  self._name = name
61  self._data_type = data_type
62  self._bit_length = bit_length
63  self._bit_offset = bit_offset
64  self._byte_order = byte_order
65 
66  self._field_type = "element"
67  self._array_shape = None
68  self._array_order = None
69 
70  def __repr__(self):
71  values = {k: repr(v) for (k, v) in self.__dict__.items()}
72  values["cls_name"] = self.__class__.__name__
73 
74  if values["cls_name"] == "PacketArray":
75  return (
76  "{cls_name}(name={_name}, data_type={_data_type}, "
77  "bit_length={_bit_length}, bit_offset={_bit_offset}, "
78  "byte_order={_byte_order}, array_shape={_array_shape}, "
79  "array_order={_array_order})".format(**values)
80  )
81  else:
82  return (
83  "{cls_name}(name={_name}, data_type={_data_type}, "
84  "bit_length={_bit_length}, bit_offset={_bit_offset}, "
85  "byte_order={_byte_order})".format(**values)
86  )
87 
88  def __iter__(self):
89  return iter(
90  [
91  ("name", self._name),
92  ("dataType", self._data_type),
93  ("bitLength", self._bit_length),
94  ("bitOffset", self._bit_offset),
95  ("byteOrder", self._byte_order),
96  ]
97  )
98 
99 
101  """An array contained in a packet, similar to :py:class:`~ccsdspy.PacketField` but with multiple
102  elements of the same size (e.g. image).
103  """
104 
105  def __init__(self, *args, array_shape=None, array_order="C", **kwargs):
106  """
107  Parameters
108  ----------
109  name : str
110  String identifier for the field. The name specified how you may
111  call upon this data later.
112  data_type : {'uint', 'int', 'float', 'str', 'fill'}
113  Data type of the field.
114  bit_length : int
115  Number of bits contained in the field.
116  array_shape : int, tuple of ints, str, 'expand'
117  Shape of the array as a tuple. For a 1-dimensional array, a single integer
118  can be supplied. To use another field's value, pass the name of that field. To
119  grow to fill the packet, use "expand". For details on variable length fields, see
120  the :py:class:`~ccsdspy.VariableLength` class.
121  array_order {'C', 'F'}
122  Row-major (C-style) or column-major (Fortran-style) order.
123  bit_offset : int, optional
124  Bit offset into packet, including the primary header which is 48 bits long.
125  If this is not specified, than the bit offset will the be calculated automatically
126  from its position inside the packet definition.
127  byte_order : {'big', 'little'}, optional
128  Byte order of the field. Defaults to big endian.
129 
130  Raises
131  ------
132  TypeError
133  If one of the arguments is not of the correct type.
134  ValueError
135  array_shape, array_order, data_type, or byte_order is invalid
136  """
137  if isinstance(array_shape, str):
138  if "data_type" not in kwargs:
139  kwargs["data_type"] = "uint"
140  elif kwargs["data_type"] != "uint":
141  raise ValueError("Expanding arrays must be data_type='uint'")
142  else:
143  if isinstance(array_shape, int):
144  array_shape = (array_shape,)
145  if not isinstance(array_shape, tuple):
146  raise TypeError("array_shape parameter must be a tuple of ints")
147  if not all(isinstance(dim, int) for dim in array_shape):
148  raise TypeError("array_shape parameter must be a tuple of ints")
149 
150  if not all(dim >= 0 for dim in array_shape):
151  raise TypeError("array_shape parameter dimensions must be >= 0")
152  if sum(array_shape) == 0:
153  raise TypeError("array must have at least one element")
154 
155  if not isinstance(array_order, str):
156  raise TypeError("array_order parameter must be string")
157  if array_order not in {"C", "F"}:
158  raise TypeError("array_order parameter must be either 'C' or 'F'")
159 
160  super().__init__(*args, **kwargs)
161  self._field_type = "array"
162  self._array_shape = array_shape
163  self._array_order = array_order
def __init__(self, name, data_type, bit_length, bit_offset=None, byte_order="big")
def __init__(self, *args, array_shape=None, array_order="C", **kwargs)