Skip to content

Commit c7f202a

Browse files
authored
Merge pull request #69 from BastienTr/fix_61
Closed #61 - Refactor, docs & test for pnsequence
2 parents 1d26b07 + fab60ef commit c7f202a

File tree

2 files changed

+49
-13
lines changed

2 files changed

+49
-13
lines changed

commpy/sequences.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,25 @@
1515
"""
1616
__all__ = ['pnsequence', 'zcsequence']
1717

18-
from numpy import array, zeros, roll, exp, pi, arange
18+
from numpy import empty, exp, pi, arange, int8, fromiter, sum
1919

2020
def pnsequence(pn_order, pn_seed, pn_mask, seq_length):
2121
"""
2222
Generate a PN (Pseudo-Noise) sequence using a Linear Feedback Shift Register (LFSR).
23+
Seed and mask are ordered so that:
24+
- seed[-1] will be the first output
25+
- the new bit computed as :math:`sum(shift_register & mask) % 2` is inserted in shift[0]
2326
2427
Parameters
2528
----------
2629
pn_order : int
2730
Number of delay elements used in the LFSR.
2831
29-
pn_seed : string containing 0's and 1's
32+
pn_seed : iterable providing 0's and 1's
3033
Seed for the initialization of the LFSR delay elements.
3134
The length of this string must be equal to 'pn_order'.
3235
33-
pn_mask : string containing 0's and 1's
36+
pn_mask : iterable providing 0's and 1's
3437
Mask representing which delay elements contribute to the feedback
3538
in the LFSR. The length of this string must be equal to 'pn_order'.
3639
@@ -42,24 +45,32 @@ def pnsequence(pn_order, pn_seed, pn_mask, seq_length):
4245
pnseq : 1D ndarray of ints
4346
PN sequence generated.
4447
48+
Raises
49+
------
50+
ValueError
51+
If the pn_order is equal to the length of the strings pn_seed and pn_mask.
52+
4553
"""
4654
# Check if pn_order is equal to the length of the strings 'pn_seed' and 'pn_mask'
55+
if len(pn_seed) != pn_order:
56+
raise ValueError('pn_seed has not the same length as pn_order')
57+
if len(pn_mask) != pn_order:
58+
raise ValueError('pn_mask has not the same length as pn_order')
4759

48-
pnseq = zeros(seq_length)
60+
# Pre-allocate memory for output
61+
pnseq = empty(seq_length, int8)
4962

50-
# Initialize shift register with the pn_seed
51-
sr = array(map(lambda i: int(pn_seed[i]), range(0, len(pn_seed))))
63+
# Convert input as array
64+
sr = fromiter(pn_seed, int8, pn_order)
65+
mask = fromiter(pn_mask, int8, pn_order)
5266

5367
for i in range(seq_length):
54-
new_bit = 0
55-
for j in range(pn_order):
56-
if int(pn_mask[j]) == 1:
57-
new_bit = new_bit ^ sr[j]
58-
pnseq[i] = sr[pn_order-1]
59-
sr = roll(sr, 1)
68+
pnseq[i] = sr[-1]
69+
new_bit = sum(sr & mask) % 2
70+
sr[1:] = sr[:-1]
6071
sr[0] = new_bit
6172

62-
return pnseq.astype(int)
73+
return pnseq
6374

6475
def zcsequence(u, seq_length):
6576
"""

commpy/tests/test_sequences.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Authors: CommPy contributors
2+
# License: BSD 3-Clause
3+
4+
from numpy import array
5+
from numpy.random import seed
6+
from numpy.testing import run_module_suite, assert_raises, assert_equal
7+
8+
from commpy.sequences import pnsequence
9+
10+
11+
def test_pnsequence():
12+
# Test the raises of errors
13+
with assert_raises(ValueError):
14+
pnsequence(4, '001', '1101', 2**4 - 1)
15+
pnsequence(4, '0011', '110', 2 ** 4 - 1)
16+
17+
# Test output with
18+
assert_equal(pnsequence(4, '0011', [1, 1, 0, 1], 7), array((1, 1, 0, 0, 1, 0, 1), int),
19+
err_msg='Pseudo-noise sequence is not the one expected.')
20+
assert_equal(pnsequence(4, (0, 0, 1, 1), array((1, 1, 0, 1)), 7), array((1, 1, 0, 0, 1, 0, 1), int),
21+
err_msg='Pseudo-noise sequence is not the one expected.')
22+
23+
if __name__ == "__main__":
24+
seed(17121996)
25+
run_module_suite()

0 commit comments

Comments
 (0)