1+ """Aztec Code code-word reader with Reed-Solomon error correction and high-level decoding."""
2+
13from __future__ import annotations
24
35from functools import cached_property
2325class CodewordReader :
2426 """Read the data spiral, apply Reed-Solomon correction and decode code-words.
2527
26- Parameters
27- ----------
28- matrix : numpy.ndarray
29- Square binary matrix (0/1) representing the Aztec symbol.
30- layers : int
31- Number of data layers (excluding the bull's-eye).
32- data_words : int
33- Expected count of data code-words (script does *not* include ECC words).
34- aztec_type : AztecType
35- ``AztecType.COMPACT`` or ``AztecType.FULL`` according to the spec.
36- auto_correct : Optional[bool], default ``True``
37- If *True*, a Reed-Solomon pass is executed before high-level decoding.
38-
39- Attributes
40- ----------
41- bitmap : numpy.ndarray
42- Raw bit-stream extracted from the symbol (before ECC correction).
43- corrected_bits : List[int]
44- Bit-stream after Reed-Solomon decoding and bit-stuff removal.
45- decoded_string : str
46- Final user message built with the Aztec shift/latch tables.
47-
48- Raises
49- ------
50- InvalidParameterError
51- One of the constructor arguments is incoherent (e.g. *layers* < 1).
52- BitReadError
53- Data spiral extraction failed (index out of matrix or empty result).
54- ReedSolomonError
55- The Reed-Solomon decoder could not correct the symbol.
56- BitStuffingError
57- Stuffed/padding bits do not follow the spec rules.
58- SymbolDecodeError
59- An index maps to no entry in the current character table.
60- StreamTerminationError
61- Premature end of bit-stream (e.g. incomplete Byte-shift segment).
28+ :param matrix: Square binary matrix (0/1) representing the Aztec symbol.
29+ :type matrix: numpy.ndarray
30+ :param layers: Number of data layers (excluding the bull's-eye).
31+ :type layers: int
32+ :param data_words: Expected count of data code-words (script does *not* include ECC words).
33+ :type data_words: int
34+ :param aztec_type: ``AztecType.COMPACT`` or ``AztecType.FULL`` according to the spec.
35+ :type aztec_type: AztecType
36+ :param auto_correct: If *True*, a Reed-Solomon pass is executed before high-level decoding, defaults to ``True``
37+ :type auto_correct: Optional[bool]
38+
39+ :raises InvalidParameterError: One of the constructor arguments is incoherent (e.g. *layers* < 1).
40+ :raises BitReadError: Data spiral extraction failed (index out of matrix or empty result).
41+ :raises ReedSolomonError: The Reed-Solomon decoder could not correct the symbol.
42+ :raises BitStuffingError: Stuffed/padding bits do not follow the spec rules.
43+ :raises SymbolDecodeError: An index maps to no entry in the current character table.
44+ :raises StreamTerminationError: Premature end of bit-stream (e.g. incomplete Byte-shift segment).
6245 """
6346
6447 PRIM_POLY = {
@@ -67,6 +50,7 @@ class CodewordReader:
6750 10 : 0x409 , # x^10 + x^3 + 1
6851 12 : 0x1069 , # x^12 + x^6 + x^5 + x^3 + 1
6952 }
53+ """Primitive polynomials for Galois Field generation, keyed by code-word size."""
7054
7155 def __init__ (
7256 self ,
@@ -93,21 +77,18 @@ def __init__(
9377
9478 def _is_reference (self , r : int , c : int ) -> bool :
9579 """Check if the given coordinates are part of the reference grid.
80+
9681 A coordinate is part of the reference grid if it is a multiple of 16
9782 from the center of the matrix. The center is defined as the middle of the
9883 matrix (i.e. the middle row and column).
9984
100- Parameters
101- ----------
102- r : int
103- Row index of the coordinate.
104- c : int
105- Column index of the coordinate.
106-
107- Returns
108- -------
109- bool
110- True if the coordinate is part of the reference grid, False otherwise.
85+ :param r: Row index of the coordinate.
86+ :type r: int
87+ :param c: Column index of the coordinate.
88+ :type c: int
89+
90+ :return: True if the coordinate is part of the reference grid, False otherwise.
91+ :rtype: bool
11192 """
11293 centre = self .matrix .shape [0 ] // 2
11394 return bool ((r - centre ) % 16 == 0 or (c - centre ) % 16 == 0 )
@@ -221,6 +202,7 @@ def _read_bits(self) -> np.ndarray:
221202
222203 @cached_property
223204 def bitmap (self ) -> np .ndarray :
205+ """Raw bit-stream extracted from the symbol (before ECC correction)."""
224206 return self ._read_bits ()
225207
226208 def _correct (self ) -> List [int ]:
@@ -275,6 +257,7 @@ def _correct(self) -> List[int]:
275257
276258 @cached_property
277259 def corrected_bits (self ) -> List [int ]:
260+ """Bit-stream after Reed-Solomon decoding and bit-stuff removal."""
278261 return self ._correct ()
279262
280263 @classmethod
@@ -289,24 +272,21 @@ def _remove_stuff_bits(
289272 self , bits : List [int ], cw_size : int , data_words : int
290273 ) -> List [int ]:
291274 """Remove the stuffing bits from the bit-stream.
275+
292276 A stuffed bit is a bit that is added to the bit-stream when there are cw_size-1
293277 consecutive bits of the same value. The stuffed bit is the opposite of the last bit.
294278 We need to remove the stuffed bits from the bit-stream before decoding it.
295279 Remove also the padding bits at the beginning of the stream.
296280
297- Parameters
298- ----------
299- bits : List[int]
300- The bit-stream to clean.
301- cw_size : int
302- The size of the code-words (6, 8, 10 or 12).
303- data_words : int
304- The number of data code-words in the symbol.
305-
306- Returns
307- -------
308- List[int]
309- The cleaned bit-stream without the stuffed bits and the padding bits.
281+ :param bits: The bit-stream to clean.
282+ :type bits: List[int]
283+ :param cw_size: The size of the code-words (6, 8, 10 or 12).
284+ :type cw_size: int
285+ :param data_words: The number of data code-words in the symbol.
286+ :type data_words: int
287+
288+ :return: The cleaned bit-stream without the stuffed bits and the padding bits.
289+ :rtype: List[int]
310290 """
311291 cleaned = []
312292 i = 0
@@ -443,4 +423,5 @@ def _decode(self) -> str:
443423
444424 @cached_property
445425 def decoded_string (self ) -> str :
426+ """Final user message built with the Aztec shift/latch tables."""
446427 return self ._decode ()
0 commit comments