legend-pydataobj 1.2.1__py3-none-any.whl → 1.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import logging
3
4
  from dataclasses import dataclass
4
5
 
5
6
  import numba
@@ -8,7 +9,9 @@ from numpy import int16, int32, ubyte, uint16, uint32
8
9
  from numpy.typing import NDArray
9
10
 
10
11
  from .. import types as lgdo
11
- from .base import WaveformCodec
12
+ from .base import WaveformCodec, numba_defaults
13
+
14
+ log = logging.getLogger(__name__)
12
15
 
13
16
  # fmt: off
14
17
  _radware_sigcompress_mask = uint16([0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023,
@@ -38,16 +41,27 @@ class RadwareSigcompress(WaveformCodec):
38
41
 
39
42
  def encode(
40
43
  sig_in: NDArray | lgdo.VectorOfVectors | lgdo.ArrayOfEqualSizedArrays,
41
- sig_out: NDArray[ubyte]
42
- | lgdo.VectorOfEncodedVectors
43
- | lgdo.ArrayOfEncodedEqualSizedArrays = None,
44
+ sig_out: NDArray[ubyte] = None,
44
45
  shift: int32 = 0,
45
- ) -> NDArray[ubyte] | lgdo.VectorOfEncodedVectors:
46
+ ) -> (
47
+ (NDArray[ubyte], NDArray[uint32])
48
+ | lgdo.VectorOfEncodedVectors
49
+ | lgdo.ArrayOfEncodedEqualSizedArrays
50
+ ):
46
51
  """Compress digital signal(s) with `radware-sigcompress`.
47
52
 
48
53
  Wraps :func:`._radware_sigcompress_encode` and adds support for encoding
49
54
  LGDO arrays. Resizes the encoded array to its actual length.
50
55
 
56
+ Note
57
+ ----
58
+ If `sig_in` is a NumPy array, no resizing of `sig_out` is performed. Not
59
+ even of the internally allocated one.
60
+
61
+ Because of the current (hardware vectorized) implementation, providing a
62
+ pre-allocated :class:`.VectorOfEncodedVectors` or
63
+ :class:`.ArrayOfEncodedEqualSizedArrays` as `sig_out` is not possible.
64
+
51
65
  Note
52
66
  ----
53
67
  The compression algorithm internally interprets the input waveform values as
@@ -66,99 +80,128 @@ def encode(
66
80
 
67
81
  Returns
68
82
  -------
69
- sig_out
83
+ sig_out, nbytes | LGDO
70
84
  given pre-allocated `sig_out` structure or new structure of unsigned
71
- 8-bit integers.
85
+ 8-bit integers, plus the number of bytes (length) of the encoded
86
+ signal. If `sig_in` is an :class:`.LGDO`, only a newly allocated
87
+ :class:`.VectorOfEncodedVectors` or
88
+ :class:`.ArrayOfEncodedEqualSizedArrays` is returned.
72
89
 
73
90
  See Also
74
91
  --------
75
92
  ._radware_sigcompress_encode
76
93
  """
77
- # the encoded signal is an array of bytes -> twice as long as a uint16
78
- # array
79
- max_out_len = 2 * len(sig_in)
80
- if isinstance(sig_in, np.ndarray) and sig_in.ndim == 1:
94
+ if isinstance(sig_in, np.ndarray):
95
+ s = sig_in.shape
81
96
  if len(sig_in) == 0:
82
- return sig_in
97
+ return np.empty(s[:-1] + (0,), dtype=ubyte), np.empty(0, dtype=uint32)
83
98
 
84
- if not sig_out:
85
- # pre-allocate ubyte (uint8) array
86
- sig_out = np.empty(max_out_len, dtype=ubyte)
99
+ if sig_out is None:
100
+ # the encoded signal is an array of bytes
101
+ # -> twice as long as a uint16
102
+ # pre-allocate ubyte (uint8) array, expand last dimension
103
+ sig_out = np.empty(s[:-1] + (s[-1] * 2,), dtype=ubyte)
87
104
 
88
105
  if sig_out.dtype != ubyte:
89
106
  raise ValueError("sig_out must be of type ubyte")
90
107
 
91
- outlen = _radware_sigcompress_encode(sig_in, sig_out, shift=shift)
108
+ # nbytes has one dimension less (the last one)
109
+ nbytes = np.empty(s[:-1], dtype=uint32)
110
+ # shift too, but let the user specify one value for all waveforms
111
+ # and give it the right shape
112
+ if not hasattr(shift, "__len__"):
113
+ shift = np.full(s[:-1], shift, dtype=int32)
92
114
 
93
- # resize (down) the encoded signal to its actual length
94
- # TODO: really even if user supplied? Maybe not
95
- if outlen < max_out_len:
96
- sig_out.resize(outlen, refcheck=True)
115
+ _radware_sigcompress_encode(
116
+ sig_in, sig_out, shift, nbytes, _radware_sigcompress_mask
117
+ )
97
118
 
98
- elif isinstance(sig_in, lgdo.ArrayOfEqualSizedArrays):
99
- if not sig_out:
100
- # pre-allocate output structure
101
- # use maximum length possible
102
- sig_out = lgdo.ArrayOfEncodedEqualSizedArrays(
103
- encoded_data=lgdo.VectorOfVectors(
104
- shape_guess=(len(sig_in), 2 * sig_in.nda.shape[1]), dtype=ubyte
105
- ),
106
- decoded_size=sig_in.nda.shape[1],
119
+ # return without resizing
120
+ return sig_out, nbytes
121
+
122
+ elif isinstance(sig_in, lgdo.VectorOfVectors):
123
+ if sig_out is not None:
124
+ log.warning(
125
+ "a pre-allocated VectorOfEncodedVectors was given "
126
+ "to hold an encoded ArrayOfEqualSizedArrays. "
127
+ "This is not supported at the moment, so a new one "
128
+ "will be allocated to replace it"
107
129
  )
108
- elif not isinstance(sig_out, lgdo.ArrayOfEncodedEqualSizedArrays):
109
- raise ValueError("sig_out must be an ArrayOfEncodedEqualSizedArrays")
130
+ # convert VectorOfVectors to ArrayOfEqualSizedArrays so it can be
131
+ # directly passed to the low-level encoding routine
132
+ sig_out_nda, nbytes = encode(sig_in.to_aoesa(), shift=shift)
110
133
 
111
- # use unsafe set_vector to fill pre-allocated memory
112
- for i, wf in enumerate(sig_in):
113
- sig_out.encoded_data._set_vector_unsafe(i, encode(wf, shift=shift))
134
+ # build the encoded LGDO
135
+ encoded_data = lgdo.ArrayOfEqualSizedArrays(nda=sig_out_nda).to_vov(
136
+ cumulative_length=np.cumsum(nbytes, dtype=uint32)
137
+ )
138
+ # decoded_size is an array, compute it by diff'ing the original VOV
139
+ decoded_size = np.diff(sig_in.cumulative_length, prepend=uint32(0))
114
140
 
115
- # resize down flattened data array
116
- # TODO: really even if user supplied? Maybe not
117
- sig_out.resize(len(sig_in))
141
+ sig_out = lgdo.VectorOfEncodedVectors(encoded_data, decoded_size)
118
142
 
119
- elif isinstance(sig_in, lgdo.VectorOfVectors):
120
- if not sig_out:
121
- max_out_len = 2 * len(sig_in.flattened_data) / len(sig_in.cumulative_length)
122
- sig_out = lgdo.VectorOfEncodedVectors(
123
- encoded_data=lgdo.VectorOfVectors(
124
- shape_guess=(len(sig_in), max_out_len), dtype=ubyte
125
- ),
143
+ return sig_out
144
+
145
+ elif isinstance(sig_in, lgdo.ArrayOfEqualSizedArrays):
146
+ if sig_out is not None:
147
+ log.warning(
148
+ "a pre-allocated ArrayOfEncodedEqualSizedArrays was given "
149
+ "to hold an encoded ArrayOfEqualSizedArrays. "
150
+ "This is not supported at the moment, so a new one "
151
+ "will be allocated to replace it"
126
152
  )
127
- elif not isinstance(sig_out, lgdo.VectorOfEncodedVectors):
128
- raise ValueError("sig_out must be a VectorOfEncodedVectors")
129
153
 
130
- # use unsafe set_vector to fill pre-allocated memory
131
- # should be fast enough
132
- for i, wf in enumerate(sig_in):
133
- sig_out.encoded_data._set_vector_unsafe(i, encode(wf, shift=shift))
134
- sig_out.decoded_size[i] = len(wf)
154
+ # encode the internal numpy array
155
+ sig_out_nda, nbytes = encode(sig_in.nda, shift=shift)
135
156
 
136
- else:
137
- raise ValueError(f"unsupported input signal type ({type(sig_in)})")
157
+ # build the encoded LGDO
158
+ encoded_data = lgdo.ArrayOfEqualSizedArrays(nda=sig_out_nda).to_vov(
159
+ cumulative_length=np.cumsum(nbytes, dtype=uint32)
160
+ )
161
+ sig_out = lgdo.ArrayOfEncodedEqualSizedArrays(
162
+ encoded_data, decoded_size=sig_in.nda.shape[1]
163
+ )
138
164
 
139
- # resize down flattened data array
140
- # TODO: really even if user supplied? Maybe not
141
- sig_out.resize(len(sig_in))
165
+ return sig_out
142
166
 
143
- return sig_out
167
+ elif isinstance(sig_in, lgdo.Array):
168
+ # encode the internal numpy array
169
+ sig_out_nda, nbytes = encode(sig_in.nda, sig_out, shift=shift)
170
+ return lgdo.Array(sig_out_nda), nbytes
171
+
172
+ else:
173
+ raise ValueError(f"unsupported input signal type ({type(sig_in)})")
144
174
 
145
175
 
146
176
  def decode(
147
177
  sig_in: NDArray[ubyte]
148
178
  | lgdo.VectorOfEncodedVectors
149
179
  | lgdo.ArrayOfEncodedEqualSizedArrays,
150
- sig_out: NDArray | lgdo.VectorOfVectors | lgdo.ArrayOfEqualSizedArrays = None,
180
+ sig_out: NDArray | lgdo.ArrayOfEqualSizedArrays = None,
151
181
  shift: int32 = 0,
152
- ) -> NDArray | lgdo.VectorOfVectors | lgdo.ArrayOfEqualSizedArrays:
182
+ ) -> (NDArray, NDArray[uint32]) | lgdo.VectorOfVectors | lgdo.ArrayOfEqualSizedArrays:
153
183
  """Decompress digital signal(s) with `radware-sigcompress`.
154
184
 
155
185
  Wraps :func:`._radware_sigcompress_decode` and adds support for decoding
156
186
  LGDOs. Resizes the decoded signals to their actual length.
157
187
 
188
+ Note
189
+ ----
190
+ If `sig_in` is a NumPy array, no resizing (along the last dimension) of
191
+ `sig_out` to its actual length is performed. Not even of the internally
192
+ allocated one. If a pre-allocated :class:`.ArrayOfEqualSizedArrays` is
193
+ provided, it won't be resized too. The internally allocated
194
+ :class:`.ArrayOfEqualSizedArrays` `sig_out` has instead always the correct
195
+ size.
196
+
197
+ Because of the current (hardware vectorized) implementation, providing a
198
+ pre-allocated :class:`.VectorOfVectors` as `sig_out` is not possible.
199
+
158
200
  Parameters
159
201
  ----------
160
202
  sig_in
161
- array(s) holding the input, compressed signal(s).
203
+ array(s) holding the input, compressed signal(s). Output of
204
+ :func:`.encode`.
162
205
  sig_out
163
206
  pre-allocated array(s) for the decompressed signal(s). If not
164
207
  provided, will allocate a 32-bit integer array(s) structure.
@@ -168,62 +211,97 @@ def decode(
168
211
 
169
212
  Returns
170
213
  -------
171
- sig_out
172
- given pre-allocated structure or new structure of 32-bit integers.
214
+ sig_out, nbytes | LGDO
215
+ given pre-allocated structure or new structure of 32-bit integers, plus
216
+ the number of bytes (length) of the decoded signal.
173
217
 
174
218
  See Also
175
219
  --------
176
220
  ._radware_sigcompress_decode
177
221
  """
178
- if isinstance(sig_in, np.ndarray) and sig_in.ndim == 1 and sig_in.dtype == ubyte:
179
- if len(sig_in) == 0:
180
- return sig_in
222
+ # expect the output of encode()
223
+ if isinstance(sig_in, tuple):
224
+ s = sig_in[0].shape
225
+ if sig_out is None:
226
+ # allocate output array with lasd dim as large as the longest
227
+ # uncompressed wf
228
+ maxs = np.max(_get_hton_u16(sig_in[0], 0))
229
+ sig_out = np.empty(s[:-1] + (maxs,), dtype=int32)
181
230
 
182
- siglen = _get_hton_u16(sig_in, 0)
183
- if not sig_out:
184
- # pre-allocate memory, use safe int32
185
- sig_out = np.empty(siglen, dtype="int32")
186
- elif len(sig_out) < siglen:
187
- # TODO: really even if user supplied? Maybe not
188
- sig_out.resize(siglen, refcheck=False)
231
+ # siglen has one dimension less (the last)
232
+ siglen = np.empty(s[:-1], dtype=uint32)
189
233
 
190
- _radware_sigcompress_decode(sig_in, sig_out, shift=shift)
234
+ if len(sig_in[0]) == 0:
235
+ return sig_out, siglen
236
+
237
+ # call low-level routine
238
+ # does not need to know sig_in[1]
239
+ _radware_sigcompress_decode(
240
+ sig_in[0], sig_out, shift, siglen, _radware_sigcompress_mask
241
+ )
242
+
243
+ return sig_out, siglen
191
244
 
192
245
  elif isinstance(sig_in, lgdo.ArrayOfEncodedEqualSizedArrays):
193
- if not sig_out:
194
- # pre-allocate output structure
246
+ if sig_out is None:
247
+ # initialize output structure with decoded_size
195
248
  sig_out = lgdo.ArrayOfEqualSizedArrays(
196
249
  dims=(1, 1),
197
250
  shape=(len(sig_in), sig_in.decoded_size.value),
198
- dtype="int32",
251
+ dtype=int32,
252
+ attrs=sig_in.getattrs(),
199
253
  )
200
254
 
201
- elif not isinstance(sig_out, lgdo.ArrayOfEqualSizedArrays):
202
- raise ValueError("sig_out must be an ArrayOfEqualSizedArrays")
255
+ siglen = np.empty(len(sig_in), dtype=uint32)
256
+ # save original encoded vector lengths
257
+ nbytes = np.diff(sig_in.encoded_data.cumulative_length.nda, prepend=uint32(0))
203
258
 
204
- for i, wf in enumerate(sig_in):
205
- sig_out[i] = decode(wf, shift=shift)
259
+ if len(sig_in) == 0:
260
+ return sig_out
261
+
262
+ # convert vector of vectors to array of equal sized arrays
263
+ # can now decode on the 2D matrix together with number of bytes to read per row
264
+ _, siglen = decode(
265
+ (sig_in.encoded_data.to_aoesa(preserve_dtype=True).nda, nbytes),
266
+ sig_out if isinstance(sig_out, np.ndarray) else sig_out.nda,
267
+ shift=shift,
268
+ )
269
+
270
+ # sanity check
271
+ assert np.all(sig_in.decoded_size.value == siglen)
272
+
273
+ return sig_out
206
274
 
207
275
  elif isinstance(sig_in, lgdo.VectorOfEncodedVectors):
208
- if not sig_out:
209
- # pre-allocate output structure
210
- sig_out = lgdo.VectorOfVectors(
211
- cumulative_length=np.cumsum(sig_in.decoded_size), dtype="int32"
276
+ if sig_out:
277
+ log.warning(
278
+ "a pre-allocated VectorOfVectors was given "
279
+ "to hold an encoded VectorOfVectors. "
280
+ "This is not supported at the moment, so a new one "
281
+ "will be allocated to replace it"
212
282
  )
213
283
 
214
- elif not isinstance(sig_out, lgdo.VectorOfVectors):
215
- raise ValueError("sig_out must be a VectorOfVectors")
284
+ siglen = np.empty(len(sig_in), dtype=uint32)
285
+ # save original encoded vector lengths
286
+ nbytes = np.diff(sig_in.encoded_data.cumulative_length.nda, prepend=uint32(0))
216
287
 
217
- for i, wf in enumerate(sig_in):
218
- sig_out[i] = decode(wf[0], shift=shift)
288
+ # convert vector of vectors to array of equal sized arrays
289
+ # can now decode on the 2D matrix together with number of bytes to read per row
290
+ sig_out, siglen = decode(
291
+ (sig_in.encoded_data.to_aoesa(preserve_dtype=True).nda, nbytes), shift=shift
292
+ )
219
293
 
220
- else:
221
- raise ValueError(f"unsupported input signal type ({type(sig_in)})")
294
+ # sanity check
295
+ assert np.array_equal(sig_in.decoded_size, siglen)
222
296
 
223
- return sig_out
297
+ # converto to VOV before returning
298
+ return sig_out.to_vov(np.cumsum(siglen, dtype=uint32))
299
+
300
+ else:
301
+ raise ValueError("unsupported input signal type")
224
302
 
225
303
 
226
- @numba.jit(nopython=True)
304
+ @numba.jit(**numba_defaults)
227
305
  def _set_hton_u16(a: NDArray[ubyte], i: int, x: int) -> int:
228
306
  """Store an unsigned 16-bit integer value in an array of unsigned 8-bit integers.
229
307
 
@@ -238,7 +316,7 @@ def _set_hton_u16(a: NDArray[ubyte], i: int, x: int) -> int:
238
316
  return x
239
317
 
240
318
 
241
- @numba.jit(nopython=True)
319
+ @numba.jit(**numba_defaults)
242
320
  def _get_hton_u16(a: NDArray[ubyte], i: int) -> uint16:
243
321
  """Read unsigned 16-bit integer values from an array of unsigned 8-bit integers.
244
322
 
@@ -247,36 +325,51 @@ def _get_hton_u16(a: NDArray[ubyte], i: int) -> uint16:
247
325
  """
248
326
  i_1 = i * 2
249
327
  i_2 = i_1 + 1
250
- return uint16(a[i_1] << 8 | a[i_2])
328
+ if a.ndim == 1:
329
+ return uint16(a[i_1] << 8 | a[i_2])
330
+ else:
331
+ return a[..., i_1].astype("uint16") << 8 | a[..., i_2]
251
332
 
252
333
 
253
- @numba.jit("uint16(uint32)", nopython=True)
334
+ @numba.jit("uint16(uint32)", **numba_defaults)
254
335
  def _get_high_u16(x: uint32) -> uint16:
255
336
  return uint16(x >> 16)
256
337
 
257
338
 
258
- @numba.jit("uint32(uint32, uint16)", nopython=True)
339
+ @numba.jit("uint32(uint32, uint16)", **numba_defaults)
259
340
  def _set_high_u16(x: uint32, y: uint16) -> uint32:
260
341
  return uint32(x & 0x0000FFFF | (y << 16))
261
342
 
262
343
 
263
- @numba.jit("uint16(uint32)", nopython=True)
344
+ @numba.jit("uint16(uint32)", **numba_defaults)
264
345
  def _get_low_u16(x: uint32) -> uint16:
265
346
  return uint16(x >> 0)
266
347
 
267
348
 
268
- @numba.jit("uint32(uint32, uint16)", nopython=True)
349
+ @numba.jit("uint32(uint32, uint16)", **numba_defaults)
269
350
  def _set_low_u16(x: uint32, y: uint16) -> uint32:
270
351
  return uint32(x & 0xFFFF0000 | (y << 0))
271
352
 
272
353
 
273
- @numba.jit(nopython=True)
354
+ @numba.guvectorize(
355
+ [
356
+ "void(uint16[:], byte[:], int32[:], uint32[:], uint16[:])",
357
+ "void(uint32[:], byte[:], int32[:], uint32[:], uint16[:])",
358
+ "void(uint64[:], byte[:], int32[:], uint32[:], uint16[:])",
359
+ "void( int16[:], byte[:], int32[:], uint32[:], uint16[:])",
360
+ "void( int32[:], byte[:], int32[:], uint32[:], uint16[:])",
361
+ "void( int64[:], byte[:], int32[:], uint32[:], uint16[:])",
362
+ ],
363
+ "(n),(m),(),(),(o)",
364
+ **numba_defaults,
365
+ )
274
366
  def _radware_sigcompress_encode(
275
367
  sig_in: NDArray,
276
368
  sig_out: NDArray[ubyte],
277
369
  shift: int32,
370
+ siglen: uint32,
278
371
  _mask: NDArray[uint16] = _radware_sigcompress_mask,
279
- ) -> int32:
372
+ ) -> None:
280
373
  """Compress a digital signal.
281
374
 
282
375
  Shifts the signal values by ``+shift`` and internally interprets the result
@@ -297,7 +390,7 @@ def _radware_sigcompress_encode(
297
390
  - Store encoded, :class:`numpy.uint16` signal as an array of bytes
298
391
  (:class:`numpy.ubyte`), in big-endian ordering.
299
392
  - Declare mask globally to avoid extra memory allocation.
300
- - Apply just-in-time compilation with Numba.
393
+ - Enable hardware-vectorization with Numba (:func:`numba.guvectorize`).
301
394
  - Add a couple of missing array boundary checks.
302
395
 
303
396
  .. [1] `radware-sigcompress source code
@@ -313,6 +406,10 @@ def _radware_sigcompress_encode(
313
406
  sig_out
314
407
  pre-allocated array for the unsigned 8-bit encoded signal. In the
315
408
  original C code, an array of unsigned 16-bit integers was expected.
409
+ shift
410
+ value to be added to `sig_in` before compression.
411
+ siglen
412
+ array that will hold the lengths of the compressed signals.
316
413
 
317
414
  Returns
318
415
  -------
@@ -320,6 +417,7 @@ def _radware_sigcompress_encode(
320
417
  number of bytes in the encoded signal
321
418
  """
322
419
  mask = _mask
420
+ shift = shift[0]
323
421
 
324
422
  i = j = max1 = max2 = min1 = min2 = ds = int16(0)
325
423
  nb1 = nb2 = iso = nw = bp = dd1 = dd2 = int16(0)
@@ -463,16 +561,28 @@ def _radware_sigcompress_encode(
463
561
  if iso % 2 > 0:
464
562
  iso += 1
465
563
 
466
- return 2 * iso # number of bytes in compressed signal data
467
-
468
-
469
- @numba.jit(nopython=True)
564
+ siglen[0] = 2 * iso # number of bytes in compressed signal data
565
+
566
+
567
+ @numba.guvectorize(
568
+ [
569
+ "void(byte[:], uint16[:], int32[:], uint32[:], uint16[:])",
570
+ "void(byte[:], uint32[:], int32[:], uint32[:], uint16[:])",
571
+ "void(byte[:], uint64[:], int32[:], uint32[:], uint16[:])",
572
+ "void(byte[:], int16[:], int32[:], uint32[:], uint16[:])",
573
+ "void(byte[:], int32[:], int32[:], uint32[:], uint16[:])",
574
+ "void(byte[:], int64[:], int32[:], uint32[:], uint16[:])",
575
+ ],
576
+ "(n),(m),(),(),(o)",
577
+ **numba_defaults,
578
+ )
470
579
  def _radware_sigcompress_decode(
471
580
  sig_in: NDArray[ubyte],
472
581
  sig_out: NDArray,
473
582
  shift: int32,
583
+ siglen: uint32,
474
584
  _mask: NDArray[uint16] = _radware_sigcompress_mask,
475
- ) -> int32:
585
+ ) -> None:
476
586
  """Deompress a digital signal.
477
587
 
478
588
  After decoding, the signal values are shifted by ``-shift`` to restore the
@@ -491,6 +601,9 @@ def _radware_sigcompress_decode(
491
601
  sig_out
492
602
  pre-allocated array for the decompressed signal. In the original code,
493
603
  an array of 16-bit integers was expected.
604
+ shift
605
+ the value the original signal(s) was shifted before compression. The
606
+ value is *subtracted* from samples in `sig_out` right after decoding.
494
607
 
495
608
  Returns
496
609
  -------
@@ -498,15 +611,16 @@ def _radware_sigcompress_decode(
498
611
  length of output, decompressed signal.
499
612
  """
500
613
  mask = _mask
614
+ shift = shift[0]
501
615
 
502
616
  i = j = min_val = nb = isi = iso = nw = bp = int16(0)
503
617
  dd = uint32(0)
504
618
 
505
619
  sig_len_in = int(sig_in.size / 2)
506
- siglen = int16(_get_hton_u16(sig_in, isi)) # signal length
620
+ _siglen = int16(_get_hton_u16(sig_in, isi)) # signal length
507
621
  isi += 1
508
622
 
509
- while (isi < sig_len_in) and (iso < siglen):
623
+ while (isi < sig_len_in) and (iso < _siglen):
510
624
  if bp > 0:
511
625
  isi += 1
512
626
  bp = 0 # bit pointer
@@ -521,7 +635,7 @@ def _radware_sigcompress_decode(
521
635
  isi += 1
522
636
  dd = _set_low_u16(dd, _get_hton_u16(sig_in, isi))
523
637
  i = 0
524
- while (i < nw) and (iso < siglen):
638
+ while (i < nw) and (iso < _siglen):
525
639
  if (bp + nb) > 15:
526
640
  bp -= 16
527
641
  dd = _set_high_u16(dd, _get_hton_u16(sig_in, isi))
@@ -549,7 +663,7 @@ def _radware_sigcompress_decode(
549
663
  dd = _set_low_u16(dd, _get_hton_u16(sig_in, isi))
550
664
 
551
665
  i = 1
552
- while (i < nw) and (iso < siglen):
666
+ while (i < nw) and (iso < _siglen):
553
667
  if (bp + nb) > 15:
554
668
  bp -= 16
555
669
  dd = _set_high_u16(dd, _get_hton_u16(sig_in, isi))
@@ -573,7 +687,7 @@ def _radware_sigcompress_decode(
573
687
  i += 1
574
688
  j += nw
575
689
 
576
- if siglen != iso:
690
+ if _siglen != iso:
577
691
  raise RuntimeError("failure: unexpected signal length after decompression")
578
692
 
579
- return siglen # number of shorts in decompressed signal data
693
+ siglen[0] = _siglen # number of shorts in decompressed signal data