From 170b2c2b0105390e7c94ffcf30a6b8d48f38a23f Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Sat, 19 Feb 2022 12:59:37 -0300 Subject: [PATCH 01/13] Create test_dsp.py --- tests/test_dsp.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/test_dsp.py diff --git a/tests/test_dsp.py b/tests/test_dsp.py new file mode 100644 index 00000000..482239c2 --- /dev/null +++ b/tests/test_dsp.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +""" +Created on Sat Feb 19 12:58:47 2022 + +@author: edson +""" + From 7c1f6cd5954319b4aa72006ce986e46e6ef9cbed Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Sat, 19 Feb 2022 13:15:21 -0300 Subject: [PATCH 02/13] Update test_dsp.py --- tests/test_dsp.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/test_dsp.py b/tests/test_dsp.py index 482239c2..b2c4a2ae 100644 --- a/tests/test_dsp.py +++ b/tests/test_dsp.py @@ -5,3 +5,23 @@ @author: edson """ +from optic.dsp import finddelay +import numpy as np + + +def test_finddelay_for_arrays_of_real_values(): + delay = 35 + + a = np.arange(0, 100) + b = np.roll(a, -delay) + + assert delay == finddelay(a, b) + + +def test_finddelay_for_arrays_of_complex_values(): + delay = 57 + + a = np.arange(0, 100) + 1j * np.arange(0, 100) + b = np.roll(a, -delay) + + assert delay == finddelay(a, b) From 546d1cbc409ca8ad318d293f4853211310d08ddc Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Sun, 20 Feb 2022 10:31:39 -0300 Subject: [PATCH 03/13] Update test_dsp.py --- tests/test_dsp.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_dsp.py b/tests/test_dsp.py index b2c4a2ae..928320f2 100644 --- a/tests/test_dsp.py +++ b/tests/test_dsp.py @@ -16,6 +16,7 @@ def test_finddelay_for_arrays_of_real_values(): b = np.roll(a, -delay) assert delay == finddelay(a, b) + assert delay == -finddelay(b, a) def test_finddelay_for_arrays_of_complex_values(): @@ -25,3 +26,4 @@ def test_finddelay_for_arrays_of_complex_values(): b = np.roll(a, -delay) assert delay == finddelay(a, b) + assert delay == -finddelay(b, a) From f63ada439fb8d8cd86ebbd2fad5e35530fca0f63 Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Sun, 20 Feb 2022 10:37:11 -0300 Subject: [PATCH 04/13] Update test_dsp.py --- tests/test_dsp.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_dsp.py b/tests/test_dsp.py index 928320f2..f2f3fe32 100644 --- a/tests/test_dsp.py +++ b/tests/test_dsp.py @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- """ -Created on Sat Feb 19 12:58:47 2022 +Test functions in dsp.py -@author: edson """ from optic.dsp import finddelay From f563fd5fbbb5cef1490c73e82c2d97fc733a0b59 Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Sun, 26 Nov 2023 11:05:18 -0300 Subject: [PATCH 05/13] Update test_dsp.py --- tests/test_dsp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_dsp.py b/tests/test_dsp.py index f2f3fe32..a1eed577 100644 --- a/tests/test_dsp.py +++ b/tests/test_dsp.py @@ -4,7 +4,7 @@ """ -from optic.dsp import finddelay +from optic.dsp.core import finddelay import numpy as np From 4c933794fa65e8d88376c2e4c0cb6ecaf512f7b3 Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Sun, 26 Nov 2023 11:05:29 -0300 Subject: [PATCH 06/13] Create test_modulation.py --- tests/test_modulation.py | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 tests/test_modulation.py diff --git a/tests/test_modulation.py b/tests/test_modulation.py new file mode 100644 index 00000000..28911841 --- /dev/null +++ b/tests/test_modulation.py @@ -0,0 +1,56 @@ +import unittest +import numpy as np +from optic.utils import bitarray2dec, dec2bitarray +from optic.comm.modulation import GrayCode, GrayMapping, minEuclid, demap, modulateGray, demodulateGray + +class TestModulationFunctions(unittest.TestCase): + def test_GrayCode(self): + # Test GrayCode function for different values of n + for n in range(1, 6): + with self.subTest(n=n): + result = GrayCode(n) + self.assertEqual(len(result), 2**n) + self.assertEqual(len(result[0]), n) + + def test_GrayMapping(self): + # Test GrayMapping function for different values of M and constType + M_values = [4, 16, 64] + constTypes = ['qam', 'psk', 'pam'] + for M in M_values: + for constType in constTypes: + with self.subTest(M=M, constType=constType): + result = GrayMapping(M, constType) + self.assertEqual(len(result), M) + + def test_minEuclid(self): + # Test minEuclid function with some example inputs + symb = np.array([1+1j, 2+2j, 3+3j]) + const = np.array([1+1j, 3+3j, 2+2j]) + result = minEuclid(symb, const) + np.testing.assert_array_equal(result, np.array([0, 2, 1])) + + def test_demap(self): + # Test demap function with some example inputs + indSymb = np.array([0, 2, 1]) + bitMap = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) + result = demap(indSymb, bitMap) + np.testing.assert_array_equal(result, np.array([0, 0, 1, 0, 0, 1])) + + def test_modulateGray(self): + # Test modulateGray function with some example inputs + bits = np.array([0, 1, 0, 0, 1, 0]) + M = 4 + constType = 'qam' + result = modulateGray(bits, M, constType) + self.assertEqual(len(result), len(bits) // int(np.log2(M))) + + def test_demodulateGray(self): + # Test demodulateGray function with some example inputs + symb = np.array([1+1j, 3+3j, 2+2j]) + M = 4 + constType = 'qam' + result = demodulateGray(symb, M, constType) + self.assertEqual(len(result), len(symb) * int(np.log2(M))) + +if __name__ == '__main__': + unittest.main() From f508a493ee253a05ca88d0f418c3ae73ea0524dc Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Sun, 26 Nov 2023 11:47:04 -0300 Subject: [PATCH 07/13] Create test_metrics.py --- tests/test_metrics.py | 108 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 tests/test_metrics.py diff --git a/tests/test_metrics.py b/tests/test_metrics.py new file mode 100644 index 00000000..f502aaa6 --- /dev/null +++ b/tests/test_metrics.py @@ -0,0 +1,108 @@ +import unittest +import numpy as np +from optic.dsp.core import pnorm +from optic.models.channels import awgn +from optic.comm.modulation import modulateGray +from optic.comm.metrics import ( + fastBERcalc, + calcLLR, + monteCarloGMI, + monteCarloMI, + Qfunc, + calcEVM, + theoryBER, + calcLinOSNR, + GN_Model_NyquistWDM, + ASE_NyquistWDM, + GNmodel_OSNR, +) + +class TestCommunicationMetrics(unittest.TestCase): + + def setUp(self): + # Set up common parameters or fixtures if needed + pass + + def test_fastBERcalc(self): + # Add test cases for fastBERcalc + + # Run BER vs Ebn0 Monte Carlo simulation in the AWGN channel + + qamOrder = [4, 16, 64, 256] # Modulation order + + EbN0dB_ = np.arange(10, 25.5, 0.5) + BER = np.zeros((len(EbN0dB_),len(qamOrder))) + BER_theory = np.zeros((len(EbN0dB_),len(qamOrder))) + + for ii, M in enumerate(qamOrder): + + for indSNR in range(EbN0dB_.size): + + EbN0dB = EbN0dB_[indSNR] + + # generate random bits + bitsTx = np.random.randint(2, size=int(np.log2(M)*1e5)) + + # Map bits to constellation symbols + symbTx = modulateGray(bitsTx, M, 'qam') + + # Normalize symbols energy to 1 + symbTx = pnorm(symbTx) + + # AWGN channel + snrdB = EbN0dB + 10*np.log10(np.log2(M)) + symbRx = awgn(symbTx, snrdB) + + # BER calculation + BER[indSNR, ii], _, _ = fastBERcalc(symbRx, symbTx, M, 'qam') + BER_theory[indSNR, ii] = theoryBER(M, EbN0dB, 'qam') + + if BER[indSNR, ii] == 0: + break + + np.testing.assert_array_almost_equal(BER, BER_theory, decimal=3) + + + + def test_calcLLR(self): + # Add test cases for calcLLR + pass + + def test_monteCarloGMI(self): + # Add test cases for monteCarloGMI + pass + + def test_monteCarloMI(self): + # Add test cases for monteCarloMI + pass + + def test_Qfunc(self): + # Add test cases for Qfunc + pass + + def test_calcEVM(self): + # Add test cases for calcEVM + pass + + def test_theoryBER(self): + # Add test cases for theoryBER + pass + + def test_calcLinOSNR(self): + # Add test cases for calcLinOSNR + pass + + def test_GN_Model_NyquistWDM(self): + # Add test cases for GN_Model_NyquistWDM + pass + + def test_ASE_NyquistWDM(self): + # Add test cases for ASE_NyquistWDM + pass + + def test_GNmodel_OSNR(self): + # Add test cases for GNmodel_OSNR + pass + +if __name__ == '__main__': + unittest.main() From 90bce7bd94ef4ea190eedea867999565f15399c0 Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Sun, 26 Nov 2023 23:35:23 -0300 Subject: [PATCH 08/13] Update test_metrics.py --- tests/test_metrics.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/tests/test_metrics.py b/tests/test_metrics.py index f502aaa6..6df464e6 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -68,14 +68,37 @@ def test_calcLLR(self): # Add test cases for calcLLR pass - def test_monteCarloGMI(self): - # Add test cases for monteCarloGMI - pass + def test_monteCarlo_MI_and_GMI(self): + # Run GMI vs SNR Monte Carlo simulation + qamOrder = [4, 16, 64] # Modulation order - def test_monteCarloMI(self): - # Add test cases for monteCarloMI - pass + SNR = np.arange(15, 26, 1) + MI = np.zeros((len(SNR),len(qamOrder))) + GMI = np.zeros((len(SNR),len(qamOrder))) + + for ii, M in enumerate(qamOrder): + for indSNR in range(SNR.size): + + snrdB = SNR[indSNR] + + # generate random bits + bitsTx = np.random.randint(2, size=int(np.log2(M)*1e5)) + + # Map bits to constellation symbols + symbTx = modulateGray(bitsTx, M, 'qam') + + # Normalize symbols energy to 1 + symbTx = pnorm(symbTx) + + # AWGN channel + symbRx = awgn(symbTx, snrdB) + + # GMI estimation + MI[indSNR, ii] = monteCarloMI(symbRx, symbTx, M, 'qam') + GMI[indSNR, ii], _ = monteCarloGMI(symbRx, symbTx, M, 'qam') + np.testing.assert_array_almost_equal(MI, GMI, decimal=1) + def test_Qfunc(self): # Add test cases for Qfunc pass From 8a374355f03d63df52c795cf6586ca5cda39b1ae Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Mon, 22 Apr 2024 17:56:47 -0300 Subject: [PATCH 09/13] Update metrics.py --- optic/comm/metrics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optic/comm/metrics.py b/optic/comm/metrics.py index 17634c79..a858b78b 100644 --- a/optic/comm/metrics.py +++ b/optic/comm/metrics.py @@ -381,7 +381,7 @@ def monteCarloMI(rx, tx, M, constType, px=None): for k in range(nModes): σ2 = noiseVar[k] - MI[k] = calcMI(rx[:, k], tx[:, k], σ2, constSymb, px) + MI[k] = calcMI(rx[:, k], tx[:, k], σ2, constSymb, px)[0] return MI From 9424787efd331ceaeb44a4696c6a8eb95ce24aac Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Mon, 22 Apr 2024 17:56:54 -0300 Subject: [PATCH 10/13] Update test_metrics.py --- tests/test_metrics.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_metrics.py b/tests/test_metrics.py index 6df464e6..a2908f7c 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -54,7 +54,7 @@ def test_fastBERcalc(self): symbRx = awgn(symbTx, snrdB) # BER calculation - BER[indSNR, ii], _, _ = fastBERcalc(symbRx, symbTx, M, 'qam') + BER[indSNR, ii] = fastBERcalc(symbRx, symbTx, M, 'qam')[0][0] BER_theory[indSNR, ii] = theoryBER(M, EbN0dB, 'qam') if BER[indSNR, ii] == 0: @@ -94,8 +94,8 @@ def test_monteCarlo_MI_and_GMI(self): symbRx = awgn(symbTx, snrdB) # GMI estimation - MI[indSNR, ii] = monteCarloMI(symbRx, symbTx, M, 'qam') - GMI[indSNR, ii], _ = monteCarloGMI(symbRx, symbTx, M, 'qam') + MI[indSNR, ii] = monteCarloMI(symbRx, symbTx, M, 'qam')[0] + GMI[indSNR, ii] = monteCarloGMI(symbRx, symbTx, M, 'qam')[0][0] np.testing.assert_array_almost_equal(MI, GMI, decimal=1) From 1883ef6de1826a0f2fde2af4a528284245e19f85 Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Mon, 22 Apr 2024 17:56:59 -0300 Subject: [PATCH 11/13] Update test_modulation.py --- tests/test_modulation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_modulation.py b/tests/test_modulation.py index 28911841..8456ffe4 100644 --- a/tests/test_modulation.py +++ b/tests/test_modulation.py @@ -1,14 +1,14 @@ import unittest import numpy as np from optic.utils import bitarray2dec, dec2bitarray -from optic.comm.modulation import GrayCode, GrayMapping, minEuclid, demap, modulateGray, demodulateGray +from optic.comm.modulation import grayCode, grayMapping, minEuclid, demap, modulateGray, demodulateGray class TestModulationFunctions(unittest.TestCase): def test_GrayCode(self): # Test GrayCode function for different values of n for n in range(1, 6): with self.subTest(n=n): - result = GrayCode(n) + result = grayCode(n) self.assertEqual(len(result), 2**n) self.assertEqual(len(result[0]), n) @@ -19,7 +19,7 @@ def test_GrayMapping(self): for M in M_values: for constType in constTypes: with self.subTest(M=M, constType=constType): - result = GrayMapping(M, constType) + result = grayMapping(M, constType) self.assertEqual(len(result), M) def test_minEuclid(self): From b47e87665eb44ea2119562f1f46e94875227d6c5 Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Mon, 22 Apr 2024 17:58:08 -0300 Subject: [PATCH 12/13] Update test_metrics.py --- tests/test_metrics.py | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/tests/test_metrics.py b/tests/test_metrics.py index a2908f7c..b4304a7d 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -60,9 +60,7 @@ def test_fastBERcalc(self): if BER[indSNR, ii] == 0: break - np.testing.assert_array_almost_equal(BER, BER_theory, decimal=3) - - + np.testing.assert_array_almost_equal(BER, BER_theory, decimal=3) def test_calcLLR(self): # Add test cases for calcLLR @@ -97,35 +95,7 @@ def test_monteCarlo_MI_and_GMI(self): MI[indSNR, ii] = monteCarloMI(symbRx, symbTx, M, 'qam')[0] GMI[indSNR, ii] = monteCarloGMI(symbRx, symbTx, M, 'qam')[0][0] - np.testing.assert_array_almost_equal(MI, GMI, decimal=1) + np.testing.assert_array_almost_equal(MI, GMI, decimal=1) - def test_Qfunc(self): - # Add test cases for Qfunc - pass - - def test_calcEVM(self): - # Add test cases for calcEVM - pass - - def test_theoryBER(self): - # Add test cases for theoryBER - pass - - def test_calcLinOSNR(self): - # Add test cases for calcLinOSNR - pass - - def test_GN_Model_NyquistWDM(self): - # Add test cases for GN_Model_NyquistWDM - pass - - def test_ASE_NyquistWDM(self): - # Add test cases for ASE_NyquistWDM - pass - - def test_GNmodel_OSNR(self): - # Add test cases for GNmodel_OSNR - pass - if __name__ == '__main__': unittest.main() From 4f983ae86306810e01bc3182279c384768eb41eb Mon Sep 17 00:00:00 2001 From: Edson Porto da Silva Date: Mon, 22 Apr 2024 17:58:36 -0300 Subject: [PATCH 13/13] Update test_metrics.py --- tests/test_metrics.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/test_metrics.py b/tests/test_metrics.py index b4304a7d..a6f17c1e 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -60,12 +60,8 @@ def test_fastBERcalc(self): if BER[indSNR, ii] == 0: break - np.testing.assert_array_almost_equal(BER, BER_theory, decimal=3) - - def test_calcLLR(self): - # Add test cases for calcLLR - pass - + np.testing.assert_array_almost_equal(BER, BER_theory, decimal=3) + def test_monteCarlo_MI_and_GMI(self): # Run GMI vs SNR Monte Carlo simulation qamOrder = [4, 16, 64] # Modulation order